fix: improve ccproxy OAuth install hint (#55)

Co-authored-by: Dinos Papakostas <dinospk1999@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
akou
2026-03-18 16:57:06 +08:00
committed by GitHub
parent 16dc1121e4
commit 2f1622579f
2 changed files with 54 additions and 3 deletions
+35 -1
View File
@@ -49,6 +49,40 @@ def is_ccproxy_available() -> bool:
return _ccproxy_exe() is not None
def _is_editable_install() -> bool:
"""Return True if EvoScientist was installed in editable/development mode.
Checks all matching distributions because a stale ``.egg-info`` in the
project root can shadow the real ``dist-info`` in site-packages.
"""
try:
import json
import importlib.metadata as _meta
for dist in _meta.distributions():
name = dist.metadata.get("Name", "")
if name.lower() != "evoscientist":
continue
direct_url = dist.read_text("direct_url.json")
if direct_url is not None:
data = json.loads(direct_url)
if data.get("dir_info", {}).get("editable", False) is True:
return True
except Exception:
pass
return False
def _oauth_install_hint() -> str:
"""Return the appropriate install command depending on install method."""
if _is_editable_install():
return (
"uv sync --extra oauth "
"or pip install -e '.[oauth]'"
)
return "pip install 'evoscientist[oauth]'"
def _summarize_auth_output(raw: str) -> str:
"""Extract key fields from ccproxy auth status output into a one-line summary.
@@ -356,7 +390,7 @@ def maybe_start_ccproxy(config: EvoScientistConfig) -> subprocess.Popen | None:
if not is_ccproxy_available():
raise RuntimeError(
"ccproxy is required for OAuth mode but not found. "
"Install it with: pip install 'evoscientist[oauth]'"
f"Install it with: {_oauth_install_hint()}"
)
# Check auth for each provider that uses OAuth
+19 -2
View File
@@ -334,13 +334,30 @@ class TestMaybeStartCcproxy:
mock_anthropic_env.assert_called_once()
mock_codex_env.assert_called_once()
@patch("EvoScientist.ccproxy_manager._is_editable_install", return_value=True)
@patch("EvoScientist.ccproxy_manager.is_ccproxy_available", return_value=False)
def test_openai_oauth_raises_no_binary(self, mock_avail):
def test_openai_oauth_raises_no_binary_editable(self, mock_avail, mock_edit):
config = MagicMock()
config.anthropic_auth_mode = "api_key"
config.openai_auth_mode = "oauth"
with pytest.raises(RuntimeError, match="not found"):
with pytest.raises(RuntimeError) as exc_info:
maybe_start_ccproxy(config)
msg = str(exc_info.value)
assert "ccproxy is required for OAuth mode but not found" in msg
assert "uv sync --extra oauth" in msg
assert "pip install -e '.[oauth]'" in msg
@patch("EvoScientist.ccproxy_manager._is_editable_install", return_value=False)
@patch("EvoScientist.ccproxy_manager.is_ccproxy_available", return_value=False)
def test_openai_oauth_raises_no_binary_pip(self, mock_avail, mock_edit):
config = MagicMock()
config.anthropic_auth_mode = "api_key"
config.openai_auth_mode = "oauth"
with pytest.raises(RuntimeError) as exc_info:
maybe_start_ccproxy(config)
msg = str(exc_info.value)
assert "ccproxy is required for OAuth mode but not found" in msg
assert "pip install 'evoscientist[oauth]'" in msg
@patch(
"EvoScientist.ccproxy_manager.check_ccproxy_auth",