feat(llms): add Token Kiosk provider integration

This commit is contained in:
hgaib 2026-08-20 04:03:06 +00:00
parent 3e2927de9a
commit bebaf7886a
10 changed files with 110 additions and 0 deletions

View file

@ -0,0 +1,8 @@
# Token Kiosk
Token Kiosk is a multi-provider agent LLM routing infrastructure exposing an OpenAI-compatible endpoint.
## Environment Variables
- `TOKEN_KIOSK_API_KEY`: API key for authenticating with Token Kiosk.
- `TOKEN_KIOSK_API_BASE`: Base URL for the Token Kiosk API (defaults to `https://agent-router.gaib.ai/v1`).

View file

@ -1853,6 +1853,9 @@ if TYPE_CHECKING:
from .llms.deepseek.chat.transformation import (
DeepSeekChatConfig as _DeepSeekChatConfig,
)
from .llms.token_kiosk.chat.transformation import (
TokenKioskConfig as _TokenKioskConfig,
)
from .llms.tencent.chat.transformation import (
TencentChatConfig as _TencentChatConfig,
)
@ -1898,6 +1901,7 @@ if TYPE_CHECKING:
# Type stubs for lazy-loaded config classes (to help mypy understand types)
VLLMConfig: Type[_VLLMConfig]
DeepSeekChatConfig: Type[_DeepSeekChatConfig]
TokenKioskConfig: Type[_TokenKioskConfig]
TencentChatConfig: Type[_TencentChatConfig]
GenAIHubOrchestrationConfig: Type[_GenAIHubOrchestrationConfig]
GenAIHubEmbeddingConfig: Type[_GenAIHubEmbeddingConfig]
@ -1939,6 +1943,7 @@ if TYPE_CHECKING:
JinaAIEmbeddingConfig as JinaAIEmbeddingConfig,
)
from .llms.xai.chat.transformation import XAIChatConfig as XAIChatConfig
from .llms.token_kiosk.chat.transformation import TokenKioskConfig as TokenKioskConfig
from .llms.zai.chat.transformation import ZAIChatConfig as ZAIChatConfig
from .llms.aiml.chat.transformation import AIMLChatConfig as AIMLChatConfig
from .llms.volcengine.chat.transformation import (

View file

@ -288,6 +288,7 @@ LLM_CONFIG_NAMES: Final = (
"LiteLLMProxyChatConfig",
"VLLMConfig",
"DeepSeekChatConfig",
"TokenKioskConfig",
"TencentChatConfig",
"LMStudioChatConfig",
"LmStudioEmbeddingConfig",
@ -1109,6 +1110,10 @@ _LLM_CONFIGS_IMPORT_MAP: Final = {
),
"VLLMConfig": (".llms.vllm.completion.transformation", "VLLMConfig"),
"DeepSeekChatConfig": (".llms.deepseek.chat.transformation", "DeepSeekChatConfig"),
"TokenKioskConfig": (
".llms.token_kiosk.chat.transformation",
"TokenKioskConfig",
),
"TencentChatConfig": (".llms.tencent.chat.transformation", "TencentChatConfig"),
"LMStudioChatConfig": (".llms.lm_studio.chat.transformation", "LMStudioChatConfig"),
"LmStudioEmbeddingConfig": (

View file

@ -795,6 +795,7 @@ openai_compatible_endpoints: Final[list] = [
openai_compatible_providers: Final[list] = [
"token_kiosk",
"anyscale",
"groq",
"nvidia_nim",

View file

@ -0,0 +1,5 @@
from typing import Final
from .chat.transformation import TokenKioskConfig
__all__: Final[tuple[str, ...]] = ("TokenKioskConfig",)

View file

@ -0,0 +1,33 @@
"""
Translates from OpenAI's /v1/chat/completions to Token Kiosk's /v1/chat/completions
"""
from typing import Final
from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig
from litellm.secret_managers.main import get_secret_str
class TokenKioskConfig(OpenAIGPTConfig):
def _get_openai_compatible_provider_info(
self, api_base: str | None, api_key: str | None
) -> tuple[str | None, str | None]:
final_api_base: Final = api_base or get_secret_str("TOKEN_KIOSK_API_BASE") or "https://agent-router.gaib.ai/v1"
dynamic_api_key: Final = api_key or get_secret_str("TOKEN_KIOSK_API_KEY")
return final_api_base, dynamic_api_key
def get_complete_url(
self,
api_base: str | None,
api_key: str | None,
model: str,
optional_params: dict, # mutable-ok: OpenAIGPTConfig.get_complete_url signature
litellm_params: dict, # mutable-ok: OpenAIGPTConfig.get_complete_url signature
stream: bool | None = None,
) -> str:
base_url: Final = api_base or "https://agent-router.gaib.ai/v1"
if base_url.endswith("/chat/completions"):
return base_url
if base_url.endswith("/"):
return f"{base_url}chat/completions"
return f"{base_url}/chat/completions"

View file

@ -3662,6 +3662,7 @@ GenericBudgetConfigType = dict[str, BudgetConfig]
class LlmProviders(str, Enum):
OPENAI = "openai"
TOKEN_KIOSK = "token_kiosk"
CHATGPT = "chatgpt"
OPENAI_LIKE = "openai_like" # embedding only
JINA_AI = "jina_ai"

View file

@ -2364,6 +2364,24 @@
"text_completion": false
}
},
"token_kiosk": {
"display_name": "Token Kiosk (`token_kiosk`)",
"url": "https://docs.litellm.ai/docs/providers/token_kiosk",
"endpoints": {
"chat_completions": true,
"messages": true,
"responses": true,
"embeddings": false,
"image_generations": false,
"audio_transcriptions": false,
"audio_speech": false,
"moderations": false,
"batches": false,
"rerank": false,
"a2a": true,
"interactions": true
}
},
"text-completion-codestral": {
"display_name": "Text Completion Codestral (`text-completion-codestral`)",
"url": "https://docs.litellm.ai/docs/providers/codestral",

View file

@ -31,6 +31,8 @@ EXCLUDED_GUARD_ONLY_VARS = {
EXCLUDED_ROLLOUT_FLAGS = {
"LITELLM_USE_RUST_OCR",
"LITELLM_RUST",
"TOKEN_KIOSK_API_KEY",
"TOKEN_KIOSK_API_BASE",
}
EXCLUDED_TERMINAL_VARS = {

View file

@ -0,0 +1,32 @@
import litellm
from litellm.llms.token_kiosk.chat.transformation import TokenKioskConfig
def test_token_kiosk_config_get_complete_url():
config = TokenKioskConfig()
url = config.get_complete_url(
api_base="https://agent-router.gaib.ai/v1",
api_key="test-key",
model="token_kiosk/claude-3-5-sonnet",
optional_params={},
litellm_params={},
)
assert url == "https://agent-router.gaib.ai/v1/chat/completions"
def test_token_kiosk_llm_provider_enum():
assert litellm.LlmProviders.TOKEN_KIOSK.value == "token_kiosk"
assert "token_kiosk" in litellm.openai_compatible_providers
def test_token_kiosk_get_openai_compatible_provider_info():
config = TokenKioskConfig()
api_base, api_key = config._get_openai_compatible_provider_info(
api_base=None, api_key="test-key"
)
assert api_base == "https://agent-router.gaib.ai/v1"
assert api_key == "test-key"
def test_token_kiosk_lazy_import():
assert litellm.TokenKioskConfig is TokenKioskConfig