diff --git a/docs/llm.md b/docs/llm.md index 156200c..3d88d45 100644 --- a/docs/llm.md +++ b/docs/llm.md @@ -6,7 +6,7 @@ VibePod can connect agents to external LLM servers that expose OpenAI- or Anthro | Agent | Env vars injected | CLI flags appended | |-------|------------------|--------------------| -| claude | `ANTHROPIC_BASE_URL`, `ANTHROPIC_API_KEY` | `--model ` | +| claude | `ANTHROPIC_BASE_URL`, `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_MODEL`, `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL` | `--model ` | | codex | `CODEX_OSS_BASE_URL` | `--oss -m ` | Other agents do not yet have LLM mapping and will not receive any LLM configuration. @@ -42,6 +42,11 @@ vp run claude # Starts Claude Code with: # ANTHROPIC_BASE_URL=http://host.docker.internal:11434 # ANTHROPIC_API_KEY=ollama +# ANTHROPIC_AUTH_TOKEN=ollama +# ANTHROPIC_MODEL=qwen3:14b +# ANTHROPIC_DEFAULT_OPUS_MODEL=qwen3:14b +# ANTHROPIC_DEFAULT_SONNET_MODEL=qwen3:14b +# ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen3:14b # claude --model qwen3:14b vp run codex diff --git a/src/vibepod/commands/run.py b/src/vibepod/commands/run.py index 7038bd9..aeea279 100644 --- a/src/vibepod/commands/run.py +++ b/src/vibepod/commands/run.py @@ -276,7 +276,9 @@ def run( for key, env_var in spec.llm_env_map.items(): value = llm_values.get(key, "") if value: - merged_env.setdefault(env_var, value) + targets = [env_var] if isinstance(env_var, str) else env_var + for target in targets: + merged_env.setdefault(target, value) llm_model = llm_values["model"] if llm_model and spec.llm_model_args: llm_command_extra = [*spec.llm_model_args, llm_model] diff --git a/src/vibepod/core/agents.py b/src/vibepod/core/agents.py index 801feb2..659e246 100644 --- a/src/vibepod/core/agents.py +++ b/src/vibepod/core/agents.py @@ -22,7 +22,7 @@ class AgentSpec: platform: str | None = None run_as_host_user: bool = False ikwid_args: list[str] | None = None - llm_env_map: dict[str, str] | None = None + llm_env_map: dict[str, str | list[str]] | None = None llm_model_args: list[str] | None = None @@ -36,7 +36,16 @@ class AgentSpec: "/claude", {"CLAUDE_CONFIG_DIR": "/claude"}, ikwid_args=["--dangerously-skip-permissions"], - llm_env_map={"base_url": "ANTHROPIC_BASE_URL", "api_key": "ANTHROPIC_API_KEY"}, + llm_env_map={ + "base_url": "ANTHROPIC_BASE_URL", + "api_key": ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"], + "model": [ + "ANTHROPIC_MODEL", + "ANTHROPIC_DEFAULT_OPUS_MODEL", + "ANTHROPIC_DEFAULT_SONNET_MODEL", + "ANTHROPIC_DEFAULT_HAIKU_MODEL", + ], + }, llm_model_args=["--model"], ), "gemini": AgentSpec( diff --git a/tests/test_agents.py b/tests/test_agents.py index cd25f66..8b98cc5 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -83,7 +83,13 @@ def test_claude_spec_has_llm_env_map() -> None: spec = get_agent_spec("claude") assert spec.llm_env_map == { "base_url": "ANTHROPIC_BASE_URL", - "api_key": "ANTHROPIC_API_KEY", + "api_key": ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"], + "model": [ + "ANTHROPIC_MODEL", + "ANTHROPIC_DEFAULT_OPUS_MODEL", + "ANTHROPIC_DEFAULT_SONNET_MODEL", + "ANTHROPIC_DEFAULT_HAIKU_MODEL", + ], } assert spec.llm_model_args == ["--model"] diff --git a/tests/test_run.py b/tests/test_run.py index 62b9942..58d5d8f 100644 --- a/tests/test_run.py +++ b/tests/test_run.py @@ -757,7 +757,11 @@ def run_agent(self, **kwargs) -> object: # type: ignore[no-untyped-def] env = captured["env"] assert env["ANTHROPIC_BASE_URL"] == "http://localhost:11434/v1" assert env["ANTHROPIC_API_KEY"] == "sk-test-key" - assert "ANTHROPIC_MODEL" not in env + assert env["ANTHROPIC_AUTH_TOKEN"] == "sk-test-key" + assert env["ANTHROPIC_MODEL"] == "llama3" + assert env["ANTHROPIC_DEFAULT_OPUS_MODEL"] == "llama3" + assert env["ANTHROPIC_DEFAULT_SONNET_MODEL"] == "llama3" + assert env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] == "llama3" assert captured["command"] == ["claude", "--model", "llama3"] @@ -863,6 +867,10 @@ def run_agent(self, **kwargs) -> object: # type: ignore[no-untyped-def] env = captured["env"] assert "ANTHROPIC_BASE_URL" not in env assert "ANTHROPIC_API_KEY" not in env + assert "ANTHROPIC_AUTH_TOKEN" not in env + assert "ANTHROPIC_DEFAULT_OPUS_MODEL" not in env + assert "ANTHROPIC_DEFAULT_SONNET_MODEL" not in env + assert "ANTHROPIC_DEFAULT_HAIKU_MODEL" not in env assert "ANTHROPIC_MODEL" not in env @@ -966,6 +974,9 @@ def run_agent(self, **kwargs) -> object: # type: ignore[no-untyped-def] env = captured["env"] assert env["ANTHROPIC_BASE_URL"] == "http://localhost:11434/v1" + assert "ANTHROPIC_DEFAULT_OPUS_MODEL" not in env + assert "ANTHROPIC_DEFAULT_SONNET_MODEL" not in env + assert "ANTHROPIC_DEFAULT_HAIKU_MODEL" not in env assert captured["command"] == ["claude"]