feat(providers): add Token Kiosk as an OpenAI-compatible provider (#10722)

Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution!
This commit is contained in:
hgaib
2026-08-20 17:29:03 +08:00
committed by GitHub
parent 5185571f18
commit 08f23d0d0d
7 changed files with 76 additions and 1 deletions

View File

@@ -323,7 +323,8 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
| `tinyfish` | `tf` | TinyFish Fetch | API key | [link](https://docs.tinyfish.ai/fetch-api) | X-API-Key from agent.tinyfish.ai/api-keys |
| `together` | `together` | Together AI | API key, video | [link](https://www.together.ai) | — |
| `tokenreply` | `tokenreply` | TokenReply | API key, aggregator | [link](https://www.tokenreply.com) | Free-tagged models have model- and campaign-specific daily limits; no fixed global free quota is published. |
| `tokenrouter` | `trk` | TokenRouter | API key | [link](https://tokenrouter.com) | Use your TokenRouter API key in Authorization: Bearer <key>. Fully OpenAI-compatible. API base URL: https://api.tokenrouter.com/v1. |
| `tokenrouter` | `trk` | TokenRouter | API key | [link](https://tokenrouter.com) | Use your TokenRouter API key in Authorization: Bearer *** Fully OpenAI-compatible. API base URL: https://api.tokenrouter.com/v1. |
| `token-kiosk` | `tk` | Token Kiosk | API key | [link](https://agent-router.gaib.ai) | Use your Token Kiosk API key in Authorization: Bearer *** Fully OpenAI-compatible. API base URL: https://agent-router.gaib.ai/v1. |
| `topaz` | `topaz` | Topaz | API key, image | [link](https://topazlabs.com) | — |
| `typhoon` | `typhoon` | Typhoon | API key | [link](https://docs.opentyphoon.ai) | Free API key with a 5 req/s and 200 req/m rate limit. |
| `udio` | `udio` | Udio | API key | [link](https://udio.com) | Paste session cookie from udio.com (Supabase auth) |

View File

@@ -213,6 +213,7 @@ import { kiroProvider } from "./registry/kiro/index.ts";
import { openadapterProvider } from "./registry/openadapter/index.ts";
import { ditProvider } from "./registry/dit/index.ts";
import { tokenrouterProvider } from "./registry/tokenrouter/index.ts";
import { token_kioskProvider } from "./registry/token-kiosk/index.ts";
import { grok_cliProvider } from "./registry/grok-cli/index.ts";
import { codebuddy_cnProvider } from "./registry/codebuddy-cn/index.ts";
import { pioneerProvider } from "./registry/pioneer/index.ts";
@@ -475,6 +476,7 @@ export const REGISTRY: Record<string, RegistryEntry> = {
openadapter: openadapterProvider,
dit: ditProvider,
tokenrouter: tokenrouterProvider,
"token-kiosk": token_kioskProvider,
"grok-cli": grok_cliProvider,
"codebuddy-cn": codebuddy_cnProvider,
pioneer: pioneerProvider,

View File

@@ -0,0 +1,20 @@
import type { RegistryEntry } from "../../shared.ts";
export const token_kioskProvider: RegistryEntry = {
id: "token-kiosk",
alias: "tk",
format: "openai",
executor: "default",
baseUrl: "https://agent-router.gaib.ai/v1/chat/completions",
modelsUrl: "https://agent-router.gaib.ai/v1/models",
authType: "apikey",
authHeader: "bearer",
defaultContextLength: 128000,
models: [
{ id: "claude-3-5-sonnet", name: "Claude 3.5 Sonnet (Token Kiosk)", contextLength: 200000, toolCalling: true, supportsVision: true },
{ id: "deepseek-v3", name: "DeepSeek V3 (Token Kiosk)", contextLength: 64000, toolCalling: true },
{ id: "deepseek-r1", name: "DeepSeek R1 (Token Kiosk)", contextLength: 64000, toolCalling: true, supportsReasoning: true },
{ id: "kimi-k1.5", name: "Kimi K1.5 (Token Kiosk)", contextLength: 128000, toolCalling: true },
{ id: "minimax-m6", name: "MiniMax M6 (Token Kiosk)", contextLength: 128000, toolCalling: true },
],
};

View File

@@ -23,6 +23,7 @@ export const NAMED_OPENAI_STYLE_PROVIDERS = new Set([
"openadapter",
"dit",
"tokenrouter",
"token-kiosk",
// provider-model-sweep (2026-06-19): same class as #3976/#4202/#4249 — keyed
// openai-style providers with a real live `<baseUrl>/models` catalog, served
// their small hardcoded seed because unclassified. Seed stays as offline fallback.

View File

@@ -53,6 +53,7 @@ export const PROVIDER_ENDPOINTS = {
openadapter: "https://api.openadapter.in/v1/chat/completions",
dit: "https://api.dit.ai/v1/chat/completions",
tokenrouter: "https://api.tokenrouter.com/v1/chat/completions",
"token-kiosk": "https://agent-router.gaib.ai/v1/chat/completions",
sumopod: "https://ai.sumopod.com/v1/chat/completions",
x5lab: "https://api.x5lab.dev/v1/chat/completions",
kenari: "https://kenari.id/v1/chat/completions",

View File

@@ -1055,6 +1055,19 @@ export const APIKEY_PROVIDERS_GATEWAYS = {
apiHint:
"TokenRouter exposes an OpenAI-compatible chat completions endpoint at https://api.tokenrouter.com/v1/chat/completions, plus a working /v1/models catalog. OmniRoute uses the OpenAI protocol.",
},
"token-kiosk": {
id: "token-kiosk",
alias: "tk",
name: "Token Kiosk",
icon: "hub",
color: "#6366F1",
textIcon: "TKI",
website: "https://agent-router.gaib.ai",
authHint:
"Use your Token Kiosk API key in Authorization: Bearer <key>. Fully OpenAI-compatible gateway. API base URL: https://agent-router.gaib.ai/v1.",
apiHint:
"Token Kiosk is a multi-provider agent LLM routing infrastructure exposing an OpenAI-compatible endpoint at https://agent-router.gaib.ai/v1/chat/completions with auto-fallback and latency routing.",
},
sumopod: {
id: "sumopod",
alias: "sumopod",

View File

@@ -0,0 +1,37 @@
import test from "node:test";
import assert from "node:assert/strict";
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers.ts");
const { PROVIDER_ENDPOINTS } = await import("../../src/shared/constants/config.ts");
const { REGISTRY: providerRegistry } = await import("../../open-sse/config/providerRegistry.ts");
const { isNamedOpenAIStyleProvider } = await import("../../src/app/api/providers/[id]/models/discovery/providerSets.ts");
test("Token Kiosk is registered as an API-key gateway provider", () => {
const entry = APIKEY_PROVIDERS["token-kiosk"];
assert.ok(entry, "APIKEY_PROVIDERS['token-kiosk'] must be defined");
assert.equal(entry.id, "token-kiosk");
assert.equal(entry.alias, "tk");
assert.equal(entry.name, "Token Kiosk");
assert.equal(entry.website, "https://agent-router.gaib.ai");
});
test("Token Kiosk exposes the OpenAI-compatible chat completions URL", () => {
assert.equal(PROVIDER_ENDPOINTS["token-kiosk"], "https://agent-router.gaib.ai/v1/chat/completions");
});
test("Token Kiosk registry entry uses OpenAI format with bearer apikey auth", () => {
const entry = providerRegistry["token-kiosk"];
assert.ok(entry, "providerRegistry['token-kiosk'] must be defined");
assert.equal(entry.id, "token-kiosk");
assert.equal(entry.alias, "tk");
assert.equal(entry.format, "openai");
assert.equal(entry.executor, "default");
assert.equal(entry.authType, "apikey");
assert.equal(entry.authHeader, "bearer");
assert.equal(entry.baseUrl, "https://agent-router.gaib.ai/v1/chat/completions");
assert.equal(entry.modelsUrl, "https://agent-router.gaib.ai/v1/models");
});
test("Token Kiosk is registered as a named OpenAI-style provider for live model discovery", () => {
assert.ok(isNamedOpenAIStyleProvider("token-kiosk"));
});