From 6473297555893dfa9356317a6040f551fdc86f33 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 8 Oct 2026 21:43:18 -0700 Subject: [PATCH] fix(litellm): gate OAuth routes on real credentials --- servers/tools-pve/litellm/README.md | 4 ++++ servers/tools-pve/litellm/models.yaml | 10 +++++++--- servers/tools-pve/litellm/render_config.py | 11 ++++++++++- servers/tools-pve/litellm/test_config.py | 13 ++++++++++++- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/servers/tools-pve/litellm/README.md b/servers/tools-pve/litellm/README.md index f56233a..28bf99f 100644 --- a/servers/tools-pve/litellm/README.md +++ b/servers/tools-pve/litellm/README.md @@ -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 会写回同一个持久卷。 diff --git a/servers/tools-pve/litellm/models.yaml b/servers/tools-pve/litellm/models.yaml index d50dc19..a82adcc 100644 --- a/servers/tools-pve/litellm/models.yaml +++ b/servers/tools-pve/litellm/models.yaml @@ -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 diff --git a/servers/tools-pve/litellm/render_config.py b/servers/tools-pve/litellm/render_config.py index 91d6f6d..091d7f1 100644 --- a/servers/tools-pve/litellm/render_config.py +++ b/servers/tools-pve/litellm/render_config.py @@ -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) diff --git a/servers/tools-pve/litellm/test_config.py b/servers/tools-pve/litellm/test_config.py index f3ad550..b62fc01 100644 --- a/servers/tools-pve/litellm/test_config.py +++ b/servers/tools-pve/litellm/test_config.py @@ -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()