130 lines
3.6 KiB
Python
130 lines
3.6 KiB
Python
|
|
"""
|
|||
|
|
Provider / CLI 检测与配置 API
|
|||
|
|
|
|||
|
|
提供系统可用的 AI CLI 工具检测和 LLM Provider 状态查询
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import os
|
|||
|
|
from fastapi import APIRouter
|
|||
|
|
from ..services.cli_invoker import detect_available_clis, CLI_REGISTRY
|
|||
|
|
|
|||
|
|
router = APIRouter(prefix="/providers", tags=["providers"])
|
|||
|
|
|
|||
|
|
|
|||
|
|
# 支持的 CLI 工具元信息
|
|||
|
|
CLI_META = {
|
|||
|
|
"claude": {
|
|||
|
|
"display_name": "Claude Code",
|
|||
|
|
"description": "Anthropic Claude CLI",
|
|||
|
|
"models": ["claude", "claude-sonnet", "claude-opus"],
|
|||
|
|
},
|
|||
|
|
"kimi": {
|
|||
|
|
"display_name": "Kimi CLI",
|
|||
|
|
"description": "Moonshot Kimi CLI",
|
|||
|
|
"models": ["kimi", "kimi-k2", "moonshot"],
|
|||
|
|
},
|
|||
|
|
"opencode": {
|
|||
|
|
"display_name": "OpenCode",
|
|||
|
|
"description": "OpenCode CLI (支持多种模型)",
|
|||
|
|
"models": ["opencode"],
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 支持的 LLM API Provider
|
|||
|
|
API_PROVIDERS = {
|
|||
|
|
"anthropic": {
|
|||
|
|
"display_name": "Anthropic",
|
|||
|
|
"env_key": "ANTHROPIC_API_KEY",
|
|||
|
|
"models": ["claude-opus-4.6", "claude-sonnet-4.6", "claude-haiku-4.6"],
|
|||
|
|
},
|
|||
|
|
"openai": {
|
|||
|
|
"display_name": "OpenAI",
|
|||
|
|
"env_key": "OPENAI_API_KEY",
|
|||
|
|
"models": ["gpt-4o", "gpt-4-turbo", "gpt-3.5-turbo"],
|
|||
|
|
},
|
|||
|
|
"deepseek": {
|
|||
|
|
"display_name": "DeepSeek",
|
|||
|
|
"env_key": "DEEPSEEK_API_KEY",
|
|||
|
|
"models": ["deepseek-chat", "deepseek-coder"],
|
|||
|
|
},
|
|||
|
|
"google": {
|
|||
|
|
"display_name": "Google Gemini",
|
|||
|
|
"env_key": "GOOGLE_API_KEY",
|
|||
|
|
"models": ["gemini-2.5-pro", "gemini-2.5-flash"],
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
@router.get("/")
|
|||
|
|
async def list_providers():
|
|||
|
|
"""
|
|||
|
|
列出所有可用的 AI Provider(CLI + API)
|
|||
|
|
|
|||
|
|
前端用于填充 Agent 注册的模型下拉框和 Settings 的 Provider 配置区
|
|||
|
|
"""
|
|||
|
|
available_clis = detect_available_clis()
|
|||
|
|
|
|||
|
|
cli_list = []
|
|||
|
|
for name, meta in CLI_META.items():
|
|||
|
|
installed = name in available_clis
|
|||
|
|
cli_list.append({
|
|||
|
|
"id": name,
|
|||
|
|
"type": "cli",
|
|||
|
|
"display_name": meta["display_name"],
|
|||
|
|
"description": meta["description"],
|
|||
|
|
"installed": installed,
|
|||
|
|
"path": available_clis.get(name, ""),
|
|||
|
|
"models": meta["models"],
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
api_list = []
|
|||
|
|
for name, meta in API_PROVIDERS.items():
|
|||
|
|
has_key = bool(os.environ.get(meta["env_key"]))
|
|||
|
|
api_list.append({
|
|||
|
|
"id": name,
|
|||
|
|
"type": "api",
|
|||
|
|
"display_name": meta["display_name"],
|
|||
|
|
"env_key": meta["env_key"],
|
|||
|
|
"configured": has_key,
|
|||
|
|
"models": meta["models"],
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"cli": cli_list,
|
|||
|
|
"api": api_list,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
@router.get("/models")
|
|||
|
|
async def list_available_models():
|
|||
|
|
"""
|
|||
|
|
列出当前可用的所有模型(已安装 CLI + 已配置 API Key 的模型)
|
|||
|
|
|
|||
|
|
前端 Agent 注册弹窗的模型下拉框直接使用此接口
|
|||
|
|
"""
|
|||
|
|
available_clis = detect_available_clis()
|
|||
|
|
models = []
|
|||
|
|
|
|||
|
|
for name in available_clis:
|
|||
|
|
meta = CLI_META.get(name, {})
|
|||
|
|
display = meta.get("display_name", name)
|
|||
|
|
for model in meta.get("models", [name]):
|
|||
|
|
models.append({
|
|||
|
|
"value": model,
|
|||
|
|
"label": f"{model} ({display})",
|
|||
|
|
"provider": name,
|
|||
|
|
"type": "cli",
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
for name, meta in API_PROVIDERS.items():
|
|||
|
|
if os.environ.get(meta["env_key"]):
|
|||
|
|
for model in meta["models"]:
|
|||
|
|
models.append({
|
|||
|
|
"value": model,
|
|||
|
|
"label": f"{model} ({meta['display_name']} API)",
|
|||
|
|
"provider": name,
|
|||
|
|
"type": "api",
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return {"models": models}
|