mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
feat(providers): add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) (#7647)
Validated in local merge-train @ 8f27177d1 (full parity suite green: typecheck+file-size+complexity+cognitive+changelog+unit shards 1&2+vitest)
This commit is contained in:
committed by
GitHub
parent
9a71113583
commit
8bf2e6929f
@@ -3,12 +3,12 @@
|
||||
## Project
|
||||
|
||||
Unified AI proxy/router — route any LLM through one endpoint. Multi-provider support
|
||||
with **259 provider entries** (OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Fireworks,
|
||||
with **264 provider entries** (OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Fireworks,
|
||||
Cohere, NVIDIA, Cerebras, Pollinations, Puter, Cloudflare AI, HuggingFace, DeepInfra,
|
||||
SambaNova, Meta Llama API, Moonshot AI, AI21 Labs, Databricks, Snowflake, and many more)
|
||||
with **MCP Server** (94 tools), **A2A v0.3 Protocol**, and **Electron desktop app**.
|
||||
|
||||
> **Live counts (v3.8.49)**: providers 259 · MCP tools 94 · MCP scopes 30 · A2A skills 6 ·
|
||||
> **Live counts (v3.8.49)**: providers 264 · MCP tools 94 · MCP scopes 30 · A2A skills 6 ·
|
||||
> open-sse services 134 · routing strategies 17 · auto-combo scoring factors 12 ·
|
||||
> DB modules 95 · DB migrations 110 · base tables 17 · search providers 11 ·
|
||||
> i18n locales 42. **Refresh with `npm run check:docs-all`.**
|
||||
|
||||
@@ -35,7 +35,7 @@ For full test matrix, see `CONTRIBUTING.md` → "Running Tests". For deep archit
|
||||
|
||||
## Project at a Glance
|
||||
|
||||
**OmniRoute** — unified AI proxy/router. One endpoint, 259 LLM providers, auto-fallback.
|
||||
**OmniRoute** — unified AI proxy/router. One endpoint, 264 LLM providers, auto-fallback.
|
||||
|
||||
| Layer | Location | Purpose |
|
||||
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
|
||||
10
README.md
10
README.md
@@ -6,7 +6,7 @@
|
||||
|
||||
# 🚀 OmniRoute — The Free AI Gateway
|
||||
|
||||
### Never stop coding. Connect every AI tool to **259 providers** — **90+ free** — through one endpoint.
|
||||
### Never stop coding. Connect every AI tool to **264 providers** — **90+ free** — through one endpoint.
|
||||
|
||||
**Plug Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini. Auto-fallback.**
|
||||
<br/>
|
||||
@@ -149,11 +149,11 @@
|
||||
|
||||
</div>
|
||||
|
||||
> One endpoint. **259 providers.** Never stop building — and let OmniRoute pick the cheapest one that works.
|
||||
> One endpoint. **264 providers.** Never stop building — and let OmniRoute pick the cheapest one that works.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width="33%" valign="top"><b>🚫 Never hit limits</b><br/><sub>Auto-fallback across 259 providers in milliseconds. Quota out? Next provider takes over — zero downtime.</sub></td>
|
||||
<td width="33%" valign="top"><b>🚫 Never hit limits</b><br/><sub>Auto-fallback across 264 providers in milliseconds. Quota out? Next provider takes over — zero downtime.</sub></td>
|
||||
<td width="33%" valign="top"><b>💸 Save up to 95% tokens</b><br/><sub>RTK + Caveman stacked compression cuts 15–95% of eligible tokens (~89% avg on tool-heavy sessions).</sub></td>
|
||||
<td width="33%" valign="top"><b>🆓 $0 to start</b><br/><sub>90+ providers with a free tier, 11 free <i>forever</i> (Kiro, Qoder, Pollinations, LongCat…). No card needed.</sub></td>
|
||||
</tr>
|
||||
@@ -368,7 +368,7 @@ All **18** strategies — mix & match per combo step:
|
||||
|
||||
</div>
|
||||
|
||||
> The most complete catalog of any open-source router: **259 providers**, **90+ with a free tier**, **11 free forever**.
|
||||
> The most complete catalog of any open-source router: **264 providers**, **90+ with a free tier**, **11 free forever**.
|
||||
|
||||
<div align="center">
|
||||
|
||||
@@ -874,7 +874,7 @@ Compression: aggressive (~50%) → double your free quota · Cost: $0/mo
|
||||
**Will I be charged by OmniRoute?** No — it's free, open-source software on your machine. You only pay paid providers directly. OmniRoute has no billing system.
|
||||
**Are FREE providers really unlimited?** Mostly — Qoder, Pollinations, LongCat, and Cloudflare are free with no per-account credit cap. Kiro is free too but capped at ~50 credits/month per account. Stack multiple free providers in a combo and auto-fallback keeps you serving for $0.
|
||||
**Will compression hurt quality?** No — it only compresses the **input**; code, URLs, JSON are always protected.
|
||||
**Does it work where AI is blocked?** Yes — 3-level proxy + 1proxy marketplace reach all 259 providers.
|
||||
**Does it work where AI is blocked?** Yes — 3-level proxy + 1proxy marketplace reach all 264 providers.
|
||||
|
||||
📖 [User Guide](docs/guides/USER_GUIDE.md) · [API Reference](docs/reference/API_REFERENCE.md) · [Environment Config](docs/reference/ENVIRONMENT.md)
|
||||
|
||||
|
||||
1
changelog.d/features/6650-g4f-space-gateway.md
Normal file
1
changelog.d/features/6650-g4f-space-gateway.md
Normal file
@@ -0,0 +1 @@
|
||||
- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127).
|
||||
@@ -10,7 +10,7 @@ lastUpdated: 2026-07-17
|
||||
> Regenerate with: `npm run gen:provider-reference`
|
||||
> **Last generated:** 2026-07-17
|
||||
|
||||
Total providers: **259**. See category breakdown below.
|
||||
Total providers: **264**. See category breakdown below.
|
||||
|
||||
## Categories
|
||||
|
||||
@@ -90,7 +90,7 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
|
||||
| `zai-web` | `zw` | Z.ai Web (Free) | Web cookie | [link](https://chat.z.ai) | Paste the full Cookie header from chat.z.ai (must include the token=<JWT> cookie) |
|
||||
| `zenmux-free` | `zmf` | ZenMux Free (Web) | Web cookie | [link](https://zenmux.ai) | Login at zenmux.ai, then export all cookies using EditThisCookie or Cookie-Editor and paste the full Cookie header string here. Refresh every ~30 days. |
|
||||
|
||||
## API Key Providers (paid / paid-with-free-credits) (172)
|
||||
## API Key Providers (paid / paid-with-free-credits) (177)
|
||||
|
||||
| ID | Alias | Name | Tags | Website | Notes |
|
||||
|----|-------|------|------|---------|-------|
|
||||
@@ -149,6 +149,11 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
|
||||
| `freepik` | `fpk` | Freepik (Mystic) | API key, image | [link](https://freepik.com) | Get API key at freepik.com/developers (Mystic image endpoint) |
|
||||
| `freetheai` | `fta` | FreeTheAi | API key, aggregator | [link](https://freetheai.xyz) | Join the FreeTheAi Discord to get your free API key. |
|
||||
| `friendliai` | `friendli` | FriendliAI | API key | [link](https://friendli.ai) | Free tier for serverless inference — no credit card required |
|
||||
| `g4f-gemini` | `g4fgem` | g4f.space — Gemini | API key, aggregator | [link](https://g4f.space) | No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits. |
|
||||
| `g4f-groq` | `g4fgroq` | g4f.space — Groq | API key, aggregator | [link](https://g4f.space) | No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits. |
|
||||
| `g4f-nvidia` | `g4fnv` | g4f.space — NVIDIA | API key, aggregator | [link](https://g4f.space) | No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits. |
|
||||
| `g4f-ollama` | `g4foll` | g4f.space — Ollama | API key, aggregator | [link](https://g4f.space) | No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits. |
|
||||
| `g4f-pollinations` | `g4fpol` | g4f.space — Pollinations | API key, aggregator | [link](https://g4f.space) | No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits. |
|
||||
| `galadriel` | `galadriel` | Galadriel | API key | [link](https://galadriel.com) | ⚠️ **DEPRECATED.** api.galadriel.ai no longer resolves (sweep 2026-06-19); the inference API appears discontinued. |
|
||||
| `gemini` | `gemini` | Gemini (Google AI Studio) | API key | [link](https://aistudio.google.com) | Free forever: 1,500 req/day for Gemini 2.5 Flash — no credit card, get key at aistudio.google.com |
|
||||
| `getgoapi` | `ggo` | GoAPI | API key, aggregator | [link](https://api.getgoapi.com) | — |
|
||||
|
||||
@@ -66,6 +66,11 @@ import { cursorProvider } from "./registry/cursor/index.ts";
|
||||
import { volcengineProvider } from "./registry/volcengine/index.ts";
|
||||
import { hackclubProvider } from "./registry/hackclub/index.ts";
|
||||
import { freetheaiProvider } from "./registry/freetheai/index.ts";
|
||||
import { g4f_groqProvider } from "./registry/g4f-groq/index.ts";
|
||||
import { g4f_geminiProvider } from "./registry/g4f-gemini/index.ts";
|
||||
import { g4f_pollinationsProvider } from "./registry/g4f-pollinations/index.ts";
|
||||
import { g4f_ollamaProvider } from "./registry/g4f-ollama/index.ts";
|
||||
import { g4f_nvidiaProvider } from "./registry/g4f-nvidia/index.ts";
|
||||
import { tencentProvider } from "./registry/tencent/index.ts";
|
||||
import { cozeProvider } from "./registry/coze/index.ts";
|
||||
import { ai21Provider } from "./registry/ai21/index.ts";
|
||||
@@ -256,6 +261,11 @@ export const REGISTRY: Record<string, RegistryEntry> = {
|
||||
volcengine: volcengineProvider,
|
||||
hackclub: hackclubProvider,
|
||||
freetheai: freetheaiProvider,
|
||||
"g4f-groq": g4f_groqProvider,
|
||||
"g4f-gemini": g4f_geminiProvider,
|
||||
"g4f-pollinations": g4f_pollinationsProvider,
|
||||
"g4f-ollama": g4f_ollamaProvider,
|
||||
"g4f-nvidia": g4f_nvidiaProvider,
|
||||
tencent: tencentProvider,
|
||||
coze: cozeProvider,
|
||||
ai21: ai21Provider,
|
||||
|
||||
20
open-sse/config/providers/registry/g4f-gemini/index.ts
Normal file
20
open-sse/config/providers/registry/g4f-gemini/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { RegistryEntry } from "../../shared.ts";
|
||||
|
||||
// g4f.space/api/gemini — no-key reverse proxy to Gemini (gpt4free project, issue #6650).
|
||||
// Distinct auth mechanism from the existing gemini-web (browser cookie): this is a
|
||||
// plain no-key HTTP proxy. Same OpenAI-compatible shape as the other no-key gateways.
|
||||
export const g4f_geminiProvider: RegistryEntry = {
|
||||
id: "g4f-gemini",
|
||||
alias: "g4fgem",
|
||||
format: "openai",
|
||||
executor: "default",
|
||||
baseUrl: "https://g4f.space/api/gemini/v1/chat/completions",
|
||||
modelsUrl: "https://g4f.space/api/gemini/v1/models",
|
||||
authType: "optional",
|
||||
authHeader: "bearer",
|
||||
passthroughModels: true,
|
||||
models: [
|
||||
{ id: "models/gemini-2.5-flash", name: "Gemini 2.5 Flash (g4f)" },
|
||||
{ id: "models/gemini-2.5-pro", name: "Gemini 2.5 Pro (g4f)" },
|
||||
],
|
||||
};
|
||||
20
open-sse/config/providers/registry/g4f-groq/index.ts
Normal file
20
open-sse/config/providers/registry/g4f-groq/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { RegistryEntry } from "../../shared.ts";
|
||||
|
||||
// g4f.space/api/groq — no-key reverse proxy to Groq (gpt4free project, issue #6650).
|
||||
// Same OpenAI-compatible shape as the other no-key gateways (hackclub, uncloseai):
|
||||
// standard chat/completions + /v1/models discovery, no custom executor/translator.
|
||||
export const g4f_groqProvider: RegistryEntry = {
|
||||
id: "g4f-groq",
|
||||
alias: "g4fgroq",
|
||||
format: "openai",
|
||||
executor: "default",
|
||||
baseUrl: "https://g4f.space/api/groq/v1/chat/completions",
|
||||
modelsUrl: "https://g4f.space/api/groq/v1/models",
|
||||
authType: "optional",
|
||||
authHeader: "bearer",
|
||||
passthroughModels: true,
|
||||
models: [
|
||||
{ id: "llama-3.3-70b-versatile", name: "Llama 3.3 70B (g4f/Groq)" },
|
||||
{ id: "llama-3.1-8b-instant", name: "Llama 3.1 8B Instant (g4f/Groq)" },
|
||||
],
|
||||
};
|
||||
22
open-sse/config/providers/registry/g4f-nvidia/index.ts
Normal file
22
open-sse/config/providers/registry/g4f-nvidia/index.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { RegistryEntry } from "../../shared.ts";
|
||||
|
||||
// g4f.space/api/nvidia — no-key reverse proxy to NVIDIA NIM (gpt4free project,
|
||||
// issue #6650). The existing `nvidia` entry requires signup; this is the genuine
|
||||
// no-key gap the reporter flagged. Free tier is rate-limited to 5 req/min
|
||||
// (confirmed live via 429 upsell to g4f.dev/members.html).
|
||||
export const g4f_nvidiaProvider: RegistryEntry = {
|
||||
id: "g4f-nvidia",
|
||||
alias: "g4fnv",
|
||||
format: "openai",
|
||||
executor: "default",
|
||||
baseUrl: "https://g4f.space/api/nvidia/v1/chat/completions",
|
||||
modelsUrl: "https://g4f.space/api/nvidia/v1/models",
|
||||
authType: "optional",
|
||||
authHeader: "bearer",
|
||||
passthroughModels: true,
|
||||
models: [
|
||||
{ id: "nvidia/nemotron-3-nano-30b-a3b", name: "Nemotron 3 Nano 30B (g4f/NVIDIA)" },
|
||||
{ id: "z-ai/glm-5.2", name: "GLM 5.2 (g4f/NVIDIA)" },
|
||||
{ id: "minimaxai/minimax-m2.7", name: "MiniMax M2.7 (g4f/NVIDIA)" },
|
||||
],
|
||||
};
|
||||
18
open-sse/config/providers/registry/g4f-ollama/index.ts
Normal file
18
open-sse/config/providers/registry/g4f-ollama/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { RegistryEntry } from "../../shared.ts";
|
||||
|
||||
// g4f.space/api/ollama — no-key hosted Ollama gateway (gpt4free project, issue #6650).
|
||||
// Fills a niche none of the existing ollama-* entries cover (local/cloud/search) —
|
||||
// this is a no-key *hosted* Ollama proxy. Same OpenAI-compatible shape as the other
|
||||
// no-key gateways.
|
||||
export const g4f_ollamaProvider: RegistryEntry = {
|
||||
id: "g4f-ollama",
|
||||
alias: "g4foll",
|
||||
format: "openai",
|
||||
executor: "default",
|
||||
baseUrl: "https://g4f.space/api/ollama/v1/chat/completions",
|
||||
modelsUrl: "https://g4f.space/api/ollama/v1/models",
|
||||
authType: "optional",
|
||||
authHeader: "bearer",
|
||||
passthroughModels: true,
|
||||
models: [{ id: "gemma3:4b", name: "Gemma 3 4B (g4f/Ollama)" }],
|
||||
};
|
||||
20
open-sse/config/providers/registry/g4f-pollinations/index.ts
Normal file
20
open-sse/config/providers/registry/g4f-pollinations/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { RegistryEntry } from "../../shared.ts";
|
||||
|
||||
// g4f.space/api/pollinations — no-key reverse proxy to Pollinations (gpt4free project,
|
||||
// issue #6650). Separate route from the existing direct pollinations.ai entry; same
|
||||
// OpenAI-compatible shape as the other no-key gateways.
|
||||
export const g4f_pollinationsProvider: RegistryEntry = {
|
||||
id: "g4f-pollinations",
|
||||
alias: "g4fpol",
|
||||
format: "openai",
|
||||
executor: "default",
|
||||
baseUrl: "https://g4f.space/api/pollinations/v1/chat/completions",
|
||||
modelsUrl: "https://g4f.space/api/pollinations/v1/models",
|
||||
authType: "optional",
|
||||
authHeader: "bearer",
|
||||
passthroughModels: true,
|
||||
models: [
|
||||
{ id: "openai", name: "OpenAI (g4f/Pollinations)" },
|
||||
{ id: "openai-fast", name: "OpenAI Fast (g4f/Pollinations)" },
|
||||
],
|
||||
};
|
||||
@@ -80,6 +80,11 @@ export const AGGREGATOR_PROVIDER_IDS = new Set([
|
||||
"chutes",
|
||||
"hackclub",
|
||||
"freetheai",
|
||||
"g4f-groq",
|
||||
"g4f-gemini",
|
||||
"g4f-pollinations",
|
||||
"g4f-ollama",
|
||||
"g4f-nvidia",
|
||||
]);
|
||||
|
||||
export const ENTERPRISE_CLOUD_PROVIDER_IDS = new Set([
|
||||
@@ -165,17 +170,30 @@ export function isSelfHostedChatProvider(providerId: unknown): boolean {
|
||||
return typeof providerId === "string" && SELF_HOSTED_CHAT_PROVIDER_IDS.has(providerId);
|
||||
}
|
||||
|
||||
// Providers with heterogeneous/no-key auth that don't fit the NOAUTH_PROVIDERS
|
||||
// registry (e.g. free-tier gateways where a key is accepted but not required).
|
||||
// Kept as a Set (not an || chain) to keep providerAllowsOptionalApiKey's
|
||||
// cyclomatic complexity flat as this list grows — see g4f.space (#6650).
|
||||
const EXPLICIT_OPTIONAL_APIKEY_PROVIDER_IDS = new Set([
|
||||
"searxng-search",
|
||||
"pollinations",
|
||||
"copilot-web",
|
||||
"hackclub",
|
||||
"g4f-groq",
|
||||
"g4f-gemini",
|
||||
"g4f-pollinations",
|
||||
"g4f-ollama",
|
||||
"g4f-nvidia",
|
||||
"huggingchat",
|
||||
"gitlawb",
|
||||
"gitlawb-gmi",
|
||||
]);
|
||||
|
||||
export function providerAllowsOptionalApiKey(providerId: unknown): boolean {
|
||||
return (
|
||||
// ponytail: any noAuth provider auto-qualifies — no per-provider maintenance
|
||||
(typeof providerId === "string" && providerId in NOAUTH_PROVIDERS) ||
|
||||
providerId === "searxng-search" ||
|
||||
providerId === "pollinations" ||
|
||||
providerId === "copilot-web" ||
|
||||
providerId === "hackclub" ||
|
||||
providerId === "huggingchat" ||
|
||||
providerId === "gitlawb" ||
|
||||
providerId === "gitlawb-gmi" ||
|
||||
(typeof providerId === "string" && EXPLICIT_OPTIONAL_APIKEY_PROVIDER_IDS.has(providerId)) ||
|
||||
isLocalProvider(providerId) ||
|
||||
isSelfHostedChatProvider(providerId) ||
|
||||
isOpenAICompatibleProvider(providerId) ||
|
||||
|
||||
@@ -251,6 +251,81 @@ export const APIKEY_PROVIDERS_GATEWAYS = {
|
||||
passthroughModels: true,
|
||||
authHint: "Join the FreeTheAi Discord to get your free API key.",
|
||||
},
|
||||
"g4f-groq": {
|
||||
id: "g4f-groq",
|
||||
alias: "g4fgroq",
|
||||
name: "g4f.space — Groq",
|
||||
icon: "bolt",
|
||||
color: "#F97316",
|
||||
textIcon: "G4F",
|
||||
website: "https://g4f.space",
|
||||
hasFree: true,
|
||||
freeNote:
|
||||
"Free no-key reverse proxy to Groq (gpt4free project) — rate-limited to 5 req/min.",
|
||||
passthroughModels: true,
|
||||
authHint:
|
||||
"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.",
|
||||
},
|
||||
"g4f-gemini": {
|
||||
id: "g4f-gemini",
|
||||
alias: "g4fgem",
|
||||
name: "g4f.space — Gemini",
|
||||
icon: "bolt",
|
||||
color: "#F97316",
|
||||
textIcon: "G4F",
|
||||
website: "https://g4f.space",
|
||||
hasFree: true,
|
||||
freeNote:
|
||||
"Free no-key reverse proxy to Gemini (gpt4free project) — rate-limited to 5 req/min.",
|
||||
passthroughModels: true,
|
||||
authHint:
|
||||
"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.",
|
||||
},
|
||||
"g4f-pollinations": {
|
||||
id: "g4f-pollinations",
|
||||
alias: "g4fpol",
|
||||
name: "g4f.space — Pollinations",
|
||||
icon: "bolt",
|
||||
color: "#F97316",
|
||||
textIcon: "G4F",
|
||||
website: "https://g4f.space",
|
||||
hasFree: true,
|
||||
freeNote:
|
||||
"Free no-key reverse proxy to Pollinations (gpt4free project) — rate-limited to 5 req/min.",
|
||||
passthroughModels: true,
|
||||
authHint:
|
||||
"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.",
|
||||
},
|
||||
"g4f-ollama": {
|
||||
id: "g4f-ollama",
|
||||
alias: "g4foll",
|
||||
name: "g4f.space — Ollama",
|
||||
icon: "bolt",
|
||||
color: "#F97316",
|
||||
textIcon: "G4F",
|
||||
website: "https://g4f.space",
|
||||
hasFree: true,
|
||||
freeNote:
|
||||
"Free no-key hosted Ollama gateway (gpt4free project) — rate-limited to 5 req/min.",
|
||||
passthroughModels: true,
|
||||
authHint:
|
||||
"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.",
|
||||
},
|
||||
"g4f-nvidia": {
|
||||
id: "g4f-nvidia",
|
||||
alias: "g4fnv",
|
||||
name: "g4f.space — NVIDIA",
|
||||
icon: "bolt",
|
||||
color: "#F97316",
|
||||
textIcon: "G4F",
|
||||
website: "https://g4f.space",
|
||||
hasFree: true,
|
||||
freeNote:
|
||||
"Free no-key reverse proxy to NVIDIA NIM (gpt4free project) — rate-limited to 5 req/min.",
|
||||
passthroughModels: true,
|
||||
authHint:
|
||||
"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.",
|
||||
},
|
||||
"vercel-ai-gateway": {
|
||||
id: "vercel-ai-gateway",
|
||||
alias: "vag",
|
||||
|
||||
@@ -1646,6 +1646,121 @@
|
||||
"stream": "https://api.friendli.ai/serverless/v1/chat/completions"
|
||||
}
|
||||
},
|
||||
"g4f-gemini": {
|
||||
"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://g4f.space/api/gemini/v1/chat/completions",
|
||||
"stream": "https://g4f.space/api/gemini/v1/chat/completions"
|
||||
}
|
||||
},
|
||||
"g4f-groq": {
|
||||
"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://g4f.space/api/groq/v1/chat/completions",
|
||||
"stream": "https://g4f.space/api/groq/v1/chat/completions"
|
||||
}
|
||||
},
|
||||
"g4f-nvidia": {
|
||||
"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://g4f.space/api/nvidia/v1/chat/completions",
|
||||
"stream": "https://g4f.space/api/nvidia/v1/chat/completions"
|
||||
}
|
||||
},
|
||||
"g4f-ollama": {
|
||||
"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://g4f.space/api/ollama/v1/chat/completions",
|
||||
"stream": "https://g4f.space/api/ollama/v1/chat/completions"
|
||||
}
|
||||
},
|
||||
"g4f-pollinations": {
|
||||
"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://g4f.space/api/pollinations/v1/chat/completions",
|
||||
"stream": "https://g4f.space/api/pollinations/v1/chat/completions"
|
||||
}
|
||||
},
|
||||
"galadriel": {
|
||||
"format": "openai",
|
||||
"headers": {
|
||||
|
||||
103
tests/unit/g4f-space-gateway-6650.test.ts
Normal file
103
tests/unit/g4f-space-gateway-6650.test.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Issue #6650 — Add g4f.space no-key gateway (Groq/Ollama/Pollinations/NVIDIA/Gemini
|
||||
* via gpt4free).
|
||||
*
|
||||
* Live-verified reachability (triage, not re-verified in CI — see plan-file):
|
||||
* GET https://g4f.space/api/nvidia/models → 200, real model list
|
||||
* GET https://g4f.space/api/ollama/v1/models → 200, real model list
|
||||
* GET https://g4f.space/api/pollinations/v1/models → 200, real model list
|
||||
* GET https://g4f.space/api/gemini/v1/models → 200, real model list
|
||||
* GET https://g4f.space/api/groq/... → live Groq backend
|
||||
*
|
||||
* Verifies each of the 5 sub-path providers is wired end-to-end the same way as
|
||||
* the other no-key gateway providers (hackclub, uncloseai):
|
||||
* - present in the executor REGISTRY with a no-key OpenAI-compatible shape
|
||||
* - resolvable through getExecutor() (falls through to DefaultExecutor)
|
||||
* - listed in AGGREGATOR_PROVIDER_IDS so it shows up in the aggregator
|
||||
* category on the dashboard
|
||||
* - allowed to skip API key validation (providerAllowsOptionalApiKey)
|
||||
* - has provider metadata (name/website/free-tier note) in the apikey
|
||||
* gateway catalog
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
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 SUB_PATHS: Record<string, string> = {
|
||||
"g4f-groq": "groq",
|
||||
"g4f-gemini": "gemini",
|
||||
"g4f-pollinations": "pollinations",
|
||||
"g4f-ollama": "ollama",
|
||||
"g4f-nvidia": "nvidia",
|
||||
};
|
||||
|
||||
for (const [id, subPath] of Object.entries(SUB_PATHS)) {
|
||||
test(`#6650 ${id} is registered in the executor registry with a no-key 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, `https://g4f.space/api/${subPath}/v1/chat/completions`);
|
||||
assert.equal(entry.modelsUrl, `https://g4f.space/api/${subPath}/v1/models`);
|
||||
assert.equal(entry.authType, "optional");
|
||||
assert.equal(entry.passthroughModels, true);
|
||||
assert.ok(
|
||||
Array.isArray(entry.models) && entry.models.length > 0,
|
||||
`${id} must seed a fallback model list`
|
||||
);
|
||||
});
|
||||
|
||||
test(`#6650 ${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(`#6650 ${id} is classified as an aggregator/gateway provider`, () => {
|
||||
assert.ok(
|
||||
AGGREGATOR_PROVIDER_IDS.has(id),
|
||||
`${id} must be listed in AGGREGATOR_PROVIDER_IDS alongside hackclub/uncloseai`
|
||||
);
|
||||
});
|
||||
|
||||
test(`#6650 ${id} allows optional (no-key) API key validation`, () => {
|
||||
assert.equal(providerAllowsOptionalApiKey(id), true);
|
||||
});
|
||||
|
||||
test(`#6650 ${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, "https://g4f.space");
|
||||
assert.equal(meta.hasFree, true);
|
||||
assert.equal(typeof meta.freeNote, "string");
|
||||
assert.ok((meta.freeNote as string).length > 0);
|
||||
});
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
// Characterization of the providers.ts catalog split (god-file decomposition): the host became a
|
||||
// barrel that re-exports 10 data catalogs now living under constants/providers/*, and APIKEY is
|
||||
// merged from 6 semantic family files (apikey/<family>.ts). Locks: the public surface (every catalog
|
||||
// + helpers still exported), the spread-merge integrity (168 APIKEY entries, no loss/dup), and that
|
||||
// + helpers still exported), the spread-merge integrity (177 APIKEY entries, no loss/dup), and that
|
||||
// load-time Zod validation still runs. Pure-data move → behavior must be identical.
|
||||
// Count was 171 before obsolete provider removals (PR #6675: glhf/kluster/cablyai/inclusionai etc.,
|
||||
// 171->167) plus #6126 (ClinePass dual-auth): the API-key-only APIKEY_PROVIDERS_GATEWAYS entry was
|
||||
// removed as a duplicate now that clinepass is OAuth-primary (OAUTH_PROVIDERS.clinepass) with its
|
||||
// BYOK path admitted through the DUAL_AUTH_APIKEY_PROVIDER_IDS gate instead (167->166), then the
|
||||
// OpenVecta inference-gateway addition brought it back to 167, then #7246 (Chenzk API gateway)
|
||||
// brought it to 168.
|
||||
// brought it to 168, then more additions brought it to 172, then #6650 (g4f.space no-key gateway:
|
||||
// 5 new sub-path entries — g4f-groq/g4f-gemini/g4f-pollinations/g4f-ollama/g4f-nvidia) brought it
|
||||
// to 177.
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
@@ -37,12 +39,12 @@ test("barrel still exports every catalog + key helpers", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("APIKEY_PROVIDERS merges the 6 family files into 172 entries (no loss / no dup)", async () => {
|
||||
test("APIKEY_PROVIDERS merges the 6 family files into 177 entries (no loss / no dup)", async () => {
|
||||
const keys = Object.keys((P as Record<string, object>).APIKEY_PROVIDERS);
|
||||
assert.equal(keys.length, 172);
|
||||
assert.equal(new Set(keys).size, 172, "duplicate keys after spread-merge");
|
||||
assert.equal(keys.length, 177);
|
||||
assert.equal(new Set(keys).size, 177, "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 172.
|
||||
// strict partition (every provider in exactly one), so the sum must be exactly 177.
|
||||
const families: [string, string][] = [
|
||||
["gateways", "APIKEY_PROVIDERS_GATEWAYS"],
|
||||
["frontier-labs", "APIKEY_PROVIDERS_FRONTIER"],
|
||||
@@ -62,7 +64,7 @@ test("APIKEY_PROVIDERS merges the 6 family files into 172 entries (no loss / no
|
||||
seen.add(k);
|
||||
}
|
||||
}
|
||||
assert.equal(famTotal, 172, "families must partition all 172 providers");
|
||||
assert.equal(famTotal, 177, "families must partition all 177 providers");
|
||||
});
|
||||
|
||||
test("AI_PROVIDERS Proxy aggregates all sections; lookups resolve", () => {
|
||||
|
||||
Reference in New Issue
Block a user