fix(litellm): gate OAuth routes on real credentials

This commit is contained in:
Codex
2026-10-08 21:43:18 -07:00
parent 9a4020b7ec
commit 6473297555
4 changed files with 33 additions and 5 deletions
+4
View File
@@ -29,6 +29,8 @@ Google AI Studio key 尚未取得;latest 自动维护尚未实现。
只使用单个代理 worker,降低 OAuth refresh token 竞争的风险。
所有配置从 Git 生成,不允许 UI 中的模型配置成为另一份权威。
未提供 key 或未完成 OAuth 登录的路线不会进入运行配置。
OAuth 判定检查 auth.json 中 access_token,不仅检查文件存在性:
Codex 设备授权期间会先写入冷却占位文件,这不代表已经授权。
## Provider 与缓存
@@ -100,6 +102,8 @@ bash oauth-login.sh xai
登录 helper 使用 host network 仅供本地 OAuth 回调,生产代理仍使用独立 bridge。
确认账号实际支持的模型 ID 后,在 `models.yaml` 的 `chatgpt`/`xai` 表添加别名。
已预置的 OAuth 候选为 gpt-luna-latest/gpt-sol-latest/grok-latest,
只是先前 Hindsight 使用过的模型,不代表本代理独立账号已授权。
Codex 路线由 `chatgpt/` 访问,优先 `/v1/responses`;
xAI 路线使用 `xai/` 与 `use_xai_oauth: true`,不能设置 XAI API key 覆盖它。
新增 token 后需重启代理,运行时 refresh 会写回同一个持久卷。
+7 -3
View File
@@ -10,6 +10,10 @@ openrouter:
kimi-latest: moonshotai/kimi-k3
mimo-flash-latest: xiaomi/mimo-v2.6-flash
google_ai_studio: {}
# OAuth 模型需完成独立登录,并根据账号实际模型目录确认后启用。
chatgpt: {}
xai: {}
# 已有 Hindsight 部署用过的候选模型;本代理仍需独立授权与请求验收。
# renderer 在实际 token 出现前排除这些路线。
chatgpt:
gpt-luna-latest: gpt-6-luna
gpt-sol-latest: gpt-6-sol
xai:
grok-latest: grok-4.7
+10 -1
View File
@@ -1,10 +1,19 @@
"""Render only credential-ready routes; credentials remain environment references."""
import os
import json
from pathlib import Path
import yaml
def oauth_ready(path):
try:
record = json.loads(path.read_text())
return isinstance(record, dict) and bool(record.get('access_token'))
except (OSError, ValueError):
return False
def build_config(catalog, env, exists):
routes = []
@@ -49,7 +58,7 @@ def build_config(catalog, env, exists):
if __name__ == '__main__':
catalog = yaml.safe_load(Path('/etc/litellm/models.yaml').read_text())
config = build_config(catalog, os.environ, Path.is_file)
config = build_config(catalog, os.environ, oauth_ready)
output = Path('/tmp/litellm.yaml')
output.write_text(yaml.safe_dump(config, allow_unicode=True, sort_keys=False))
output.chmod(0o600)
+12 -1
View File
@@ -1,5 +1,7 @@
import unittest
from render_config import build_config
from pathlib import Path
from tempfile import TemporaryDirectory
from render_config import build_config, oauth_ready
class ConfigTests(unittest.TestCase):
@@ -33,6 +35,15 @@ class ConfigTests(unittest.TestCase):
self.assertTrue(routes[0]['litellm_params']['use_xai_oauth'])
self.assertNotIn('api_key', routes[0]['litellm_params'])
def test_pending_oauth_is_not_ready(self):
with TemporaryDirectory() as folder:
path = Path(folder) / 'auth.json'
self.assertFalse(oauth_ready(path))
path.write_text('{"device_code_requested_at": 1}')
self.assertFalse(oauth_ready(path))
path.write_text('{"access_token": "fixture-only"}')
self.assertTrue(oauth_ready(path))
if __name__ == '__main__':
unittest.main()