Fix/onboard oauth ux (#38)

* "fix(onboard): guide ccproxy install and auth in OAuth flow

  - Always show API Key / OAuth choice; prompt to install evoscientist[oauth]
    when ccproxy missing (mirrors iMessage imsg install UX)
  - Add _ccproxy_exe() helper: checks PATH then env bin dir (fixes conda envs
    where shutil.which may not find newly installed binaries)
  - Fix check_ccproxy_auth() false positive: ccproxy auth status exits 0 even
    when not authenticated; detect via output content + filter structlog noise
  - Silent install/login subprocesses; show browser URL as fallback
  - Reset anthropic/openai auth_mode to api_key when switching to non-Anthropic/
    OpenAI provider, preventing stale oauth config from triggering ccproxy error

  Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>"

* fix(onboard): update OAuth support details in README and zh-CN translation
This commit is contained in:
Xi Zhang
2026-03-16 21:22:20 +01:00
committed by GitHub
parent 4b648b3413
commit e515f69bdc
6 changed files with 165 additions and 43 deletions
+7 -3
View File
@@ -29,8 +29,10 @@ class TestIsCcproxyAvailable:
assert is_ccproxy_available() is True
mock_which.assert_called_once_with("ccproxy")
@patch("os.access", return_value=False)
@patch("os.path.isfile", return_value=False)
@patch("shutil.which", return_value=None)
def test_not_found(self, mock_which):
def test_not_found(self, mock_which, mock_isfile, mock_access):
assert is_ccproxy_available() is False
@@ -49,7 +51,8 @@ class TestCheckCcproxyAuth:
assert valid is True
assert "Authenticated" in msg
mock_run.assert_called_once()
assert mock_run.call_args[0][0] == ["ccproxy", "auth", "status", "claude_api"]
cmd = mock_run.call_args[0][0]
assert cmd[1:] == ["auth", "status", "claude_api"]
@patch("subprocess.run")
def test_valid_auth_codex(self, mock_run):
@@ -58,7 +61,8 @@ class TestCheckCcproxyAuth:
)
valid, msg = check_ccproxy_auth("codex")
assert valid is True
assert mock_run.call_args[0][0] == ["ccproxy", "auth", "status", "codex"]
cmd = mock_run.call_args[0][0]
assert cmd[1:] == ["auth", "status", "codex"]
@patch("subprocess.run")
def test_invalid_auth(self, mock_run):