fix(cli): put --base-url before the subcommand in lite up's apiKeyHelper

Claude Code runs the apiKeyHelper string verbatim, and --base-url is an option on the lite group, so the generated command failed with 'No such option: --base-url' and every request through lite up was unauthenticated.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
mateo 2026-08-11 01:35:43 +00:00
parent f1ed4690bb
commit d6def0c2d6
2 changed files with 27 additions and 4 deletions

View file

@ -145,7 +145,8 @@ def resolve_api_key_helper(base_url: str) -> str:
Code would otherwise use) makes `print-token` enforce that the cached
token was actually issued for this proxy -- without it, a token minted
for a different, previously-logged-into proxy would be handed to
whichever server `up` currently points at.
whichever server `up` currently points at. `--base-url` is an option on
the `lite` group itself, so it has to precede the subcommand.
"""
lite_path: Final = shutil.which("lite")
if lite_path is None:
@ -153,7 +154,7 @@ def resolve_api_key_helper(base_url: str) -> str:
"Could not find `lite` on your PATH. Claude Code's apiKeyHelper needs "
"an absolute path to it, so `lite up` cannot continue."
)
return f"{shlex.quote(lite_path)} auth print-token --base-url {shlex.quote(base_url)}"
return f"{shlex.quote(lite_path)} --base-url {shlex.quote(base_url)} auth print-token"
def _ensure_fresh_login(ctx: click.Context) -> None:

View file

@ -1,7 +1,9 @@
import json
import shlex
import shutil
import stat
import sys
import time
from unittest.mock import patch
import click
@ -201,18 +203,38 @@ class TestResolveApiKeyHelper:
def test_returns_helper_command_bound_to_the_selected_proxy(self, monkeypatch):
monkeypatch.setattr(shutil, "which", lambda name: "/usr/local/bin/lite")
helper = resolve_api_key_helper("http://localhost:4000")
assert helper == "/usr/local/bin/lite auth print-token --base-url http://localhost:4000"
assert helper == "/usr/local/bin/lite --base-url http://localhost:4000 auth print-token"
def test_quotes_a_base_url_containing_shell_metacharacters(self, monkeypatch):
monkeypatch.setattr(shutil, "which", lambda name: "/usr/local/bin/lite")
helper = resolve_api_key_helper("http://example.com/path; rm -rf /")
assert helper == "/usr/local/bin/lite auth print-token --base-url 'http://example.com/path; rm -rf /'"
assert helper == "/usr/local/bin/lite --base-url 'http://example.com/path; rm -rf /' auth print-token"
def test_raises_when_lite_not_on_path(self, monkeypatch):
monkeypatch.setattr(shutil, "which", lambda name: None)
with pytest.raises(UpError, match="Could not find `lite`"):
resolve_api_key_helper("http://localhost:4000")
def test_generated_helper_command_is_runnable_and_prints_the_token(self, monkeypatch):
"""Claude Code runs this command verbatim, so the argv `up` writes has to parse: `--base-url`
belongs to the `lite` group, and putting it after `auth print-token` made every request fail
with `No such option: --base-url`."""
from litellm.proxy.client.cli import cli
monkeypatch.setattr(shutil, "which", lambda name: "/usr/local/bin/lite")
helper = resolve_api_key_helper("http://localhost:4000")
token_data = {
"key": "sk-issued-for-this-proxy",
"base_url": "http://localhost:4000",
"timestamp": time.time(),
}
with patch("litellm.proxy.client.cli.commands.auth.load_token", return_value=token_data):
result = CliRunner().invoke(cli, shlex.split(helper)[1:])
assert result.exit_code == 0, result.output
assert result.output.strip() == "sk-issued-for-this-proxy"
def _make_ctx(base_url):
return click.Context(click.Command("test"), obj={"base_url": base_url})