Fix false "ok, subscription" claim for CLI backends that were never logged in
codex_health()/gemini_health()/claude_health()/grok_health()/muse_health() ran only `<cli> --version` and printed "ok, subscription" on any zero exit -- which proves the binary runs, nothing about whether it's authenticated. Confirmed as a real false claim: `codex login status` reported "Not logged in" (exit 1) on a machine whose banner nonetheless said "codex: ok, subscription". codex and claude each expose a real, cheap, read-only status check (`codex login status`, `claude auth status` -- the latter returns JSON with a loggedIn field) and now use it. grok, muse, and gemini have no such command (confirmed against gemini --help and muse --help), so they now honestly report "login unverified" instead of asserting a subscription this check never measured. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3474,30 +3474,40 @@ def muse_run(argv, cwd, stream_sink, timeout, on_reap=None):
|
||||
raise BackendError("muse exit %s: %s" % (code, "".join(stderr_parts).strip()[-300:] or "no terminal event"))
|
||||
|
||||
|
||||
def muse_health():
|
||||
binary = muse_binary()
|
||||
if not binary:
|
||||
return "missing: muse CLI not found"
|
||||
def _cli_version_detail(done, fallback):
|
||||
return (done.stdout.strip() or done.stderr.strip()).splitlines()[0][:60] if (done.stdout.strip() or done.stderr.strip()) else fallback
|
||||
|
||||
|
||||
def _cli_version_only_health(binary, fallback_name):
|
||||
"""Shared by the CLIs with no cheap, read-only way to check real login
|
||||
state (muse, grok): `--version` only proves the binary runs, never that
|
||||
it's actually authenticated, so this deliberately never claims "ok" or
|
||||
"subscription" -- a claim this check cannot back up (see codex_health/
|
||||
claude_health for the two CLIs that DO expose a real status command,
|
||||
used instead of this). Caught a real bug: this used to print "ok,
|
||||
subscription" unconditionally on a successful --version, which is false
|
||||
whenever the CLI is installed but never logged in."""
|
||||
try:
|
||||
done = subprocess.run([binary, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
|
||||
except (OSError, subprocess.SubprocessError) as exc:
|
||||
return "fail: %s" % short_error(exc)[:60]
|
||||
if done.returncode != 0:
|
||||
return "fail: exit %d" % done.returncode
|
||||
return "ok, subscription (%s)" % (done.stdout.strip().splitlines()[0][:60] if done.stdout.strip() else "muse")
|
||||
return "cli found (%s), login unverified: no status command" % _cli_version_detail(done, fallback_name)
|
||||
|
||||
|
||||
def muse_health():
|
||||
binary = muse_binary()
|
||||
if not binary:
|
||||
return "missing: muse CLI not found"
|
||||
return _cli_version_only_health(binary, "muse")
|
||||
|
||||
|
||||
def grok_health():
|
||||
binary = grok_binary()
|
||||
if not binary:
|
||||
return "missing: grok CLI not found"
|
||||
try:
|
||||
done = subprocess.run([binary, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
|
||||
except (OSError, subprocess.SubprocessError) as exc:
|
||||
return "fail: %s" % short_error(exc)[:60]
|
||||
if done.returncode != 0:
|
||||
return "fail: exit %d" % done.returncode
|
||||
return "ok, subscription (%s)" % ((done.stdout.strip() or done.stderr.strip()).splitlines()[0][:60] if (done.stdout.strip() or done.stderr.strip()) else "grok")
|
||||
return _cli_version_only_health(binary, "grok")
|
||||
|
||||
|
||||
def claude_health():
|
||||
@@ -3505,12 +3515,21 @@ def claude_health():
|
||||
if not binary:
|
||||
return "missing: claude CLI not found"
|
||||
try:
|
||||
done = subprocess.run([binary, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
|
||||
done = subprocess.run([binary, "auth", "status"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
|
||||
except (OSError, subprocess.SubprocessError) as exc:
|
||||
return "fail: %s" % short_error(exc)[:60]
|
||||
if done.returncode != 0:
|
||||
return "fail: exit %d" % done.returncode
|
||||
return "ok, subscription (%s)" % ((done.stdout.strip() or done.stderr.strip()).splitlines()[0][:60] if (done.stdout.strip() or done.stderr.strip()) else "claude")
|
||||
try:
|
||||
info = json.loads(done.stdout)
|
||||
except ValueError:
|
||||
info = None
|
||||
if isinstance(info, dict) and "loggedIn" in info:
|
||||
if info["loggedIn"]:
|
||||
return "ok, subscription (%s)" % (info.get("authMethod") or "logged in")
|
||||
return "not logged in"
|
||||
# `claude auth status` didn't return the expected shape (older/newer
|
||||
# CLI) -- fall back to the honest version-only signal instead of
|
||||
# claiming a subscription this check couldn't actually verify.
|
||||
return _cli_version_only_health(binary, "claude")
|
||||
|
||||
|
||||
def codex_health():
|
||||
@@ -3518,25 +3537,20 @@ def codex_health():
|
||||
if not binary:
|
||||
return "missing: codex CLI not found"
|
||||
try:
|
||||
done = subprocess.run([binary, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
|
||||
done = subprocess.run([binary, "login", "status"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
|
||||
except (OSError, subprocess.SubprocessError) as exc:
|
||||
return "fail: %s" % short_error(exc)[:60]
|
||||
detail = _cli_version_detail(done, "codex")
|
||||
if done.returncode != 0:
|
||||
return "fail: exit %d" % done.returncode
|
||||
return "ok, subscription (%s)" % ((done.stdout.strip() or done.stderr.strip()).splitlines()[0][:60] if (done.stdout.strip() or done.stderr.strip()) else "codex")
|
||||
return "not logged in: %s" % detail
|
||||
return "ok, subscription (%s)" % detail
|
||||
|
||||
|
||||
def gemini_health():
|
||||
binary = gemini_binary()
|
||||
if not binary:
|
||||
return "missing: gemini CLI not found"
|
||||
try:
|
||||
done = subprocess.run([binary, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
|
||||
except (OSError, subprocess.SubprocessError) as exc:
|
||||
return "fail: %s" % short_error(exc)[:60]
|
||||
if done.returncode != 0:
|
||||
return "fail: exit %d" % done.returncode
|
||||
return "ok, subscription (%s)" % ((done.stdout.strip() or done.stderr.strip()).splitlines()[0][:60] if (done.stdout.strip() or done.stderr.strip()) else "gemini")
|
||||
return _cli_version_only_health(binary, "gemini")
|
||||
|
||||
|
||||
_OPENCODE_ID_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
Reference in New Issue
Block a user