Add LLM server integration for connecting agents (claude, codex) to Ollama, vLLM, and other providers#48
Conversation
…llama, vLLM, and other providers
📝 WalkthroughWalkthroughThis PR introduces LLM integration for VibePod, enabling agents to connect to local or remote LLM servers. It adds a new configuration schema (llm section with enabled, base_url, api_key, model), defines per-agent LLM metadata (environment variable mappings and model arguments for claude and codex), implements runtime injection of LLM environment variables and command arguments in the run command, and provides comprehensive documentation and test coverage. Changes
Sequence DiagramsequenceDiagram
participant User
participant Config as Configuration
participant Run as Run Command
participant AgentSpec as Agent Metadata
participant Container as Container
User->>Config: Load config.yaml with llm settings
Config->>Run: Pass llm config (enabled, base_url, api_key, model)
Run->>AgentSpec: Query agent for llm_env_map and llm_model_args
AgentSpec-->>Run: Return env mappings and model args
alt LLM enabled and agent has mappings
Run->>Run: Prepare environment variables<br/>(map config values to agent-specific vars)
Run->>Run: Build command with model args<br/>(append --model, --oss, etc.)
end
Run->>Container: Launch container with<br/>injected env vars and command args
Container-->>User: Agent runs with LLM integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip CodeRabbit can use OpenGrep to find security vulnerabilities and bugs across 17+ programming languages.OpenGrep is compatible with Semgrep configurations. Add an |
Greptile SummaryThis PR introduces a unified Key changes:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant run.py
participant config.py
participant agents.py
participant DockerManager
participant LLM Server
User->>run.py: vp run claude (or codex)
run.py->>config.py: get_config()
config.py-->>run.py: merged config (default + global YAML + project YAML + VP_LLM_* env)
run.py->>agents.py: get_agent_spec(agent)
agents.py-->>run.py: AgentSpec (llm_env_map, llm_model_args)
Note over run.py: Build merged_env from spec.extra_env,<br/>per-agent config env, CLI --env flags
alt llm.enabled AND spec.llm_env_map present
run.py->>run.py: setdefault(ANTHROPIC_BASE_URL, base_url)<br/>setdefault(ANTHROPIC_API_KEY, api_key)
run.py->>run.py: llm_command_extra = [--model, model]
end
run.py->>DockerManager: run_agent(env=merged_env, command=[claude, --model, qwen3:14b])
DockerManager->>LLM Server: HTTP requests via ANTHROPIC_BASE_URL
LLM Server-->>DockerManager: model responses
Last reviewed commit: d36daa2 |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
tests/test_run.py (2)
711-766: Rename tests/docstrings to match asserted env namespace.At Line 711 and Line 764, the names/docstrings say “OPENAI env vars”, but Claude assertions check
ANTHROPIC_*and Codex checksCODEX_OSS_*. This is a small clarity mismatch that can confuse future debugging.✏️ Suggested rename
-def test_llm_enabled_injects_openai_env_vars(monkeypatch, tmp_path: Path) -> None: - """When llm.enabled=true, OPENAI_BASE_URL/API_KEY/MODEL are injected.""" +def test_llm_enabled_injects_claude_llm_env_vars(monkeypatch, tmp_path: Path) -> None: + """When llm.enabled=true, Claude receives ANTHROPIC_* env vars and --model args.""" -def test_llm_enabled_injects_openai_env_vars_for_codex(monkeypatch, tmp_path: Path) -> None: - """When llm.enabled=true, codex gets OPENAI_* env vars.""" +def test_llm_enabled_injects_codex_llm_env_vars(monkeypatch, tmp_path: Path) -> None: + """When llm.enabled=true, Codex receives CODEX_OSS_* env vars and --oss model args."""🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_run.py` around lines 711 - 766, Rename the misleading test names/docstrings so they match the environment variables actually asserted: update test_llm_enabled_injects_openai_env_vars (and its docstring) to reference "ANTHROPIC env vars" (or "Anthropic env vars") since the assertions check ANTHROPIC_* and update test_llm_enabled_injects_openai_env_vars_for_codex (and its docstring) to reference "CODEX_OSS env vars" (or "Codex OSS env vars") to match the CODEX_OSS_* assertions; change only the function names and docstring strings (keep behavior and assertions in run_cmd.run, _CapturingDockerManager, captured, and env checks unchanged).
715-1005: Extract duplicated_CapturingDockerManagertest stub into a helper.The same stub class is repeated many times in this changed section. A shared helper will reduce noise and drift risk.
♻️ Suggested consolidation
+def _make_capturing_manager(captured: dict, container_name: str): + class _CapturingDockerManager: + def ensure_network(self, name: str) -> None: + pass + def networks_with_running_containers(self) -> list[str]: + return [] + def pull_image(self, image: str) -> None: + pass + def ensure_proxy(self, **kwargs) -> None: # type: ignore[no-untyped-def] + pass + def run_agent(self, **kwargs) -> object: # type: ignore[no-untyped-def] + captured.update(kwargs) + return type( + "_Container", + (), + { + "name": container_name, + "id": "abc123", + "status": "running", + "attrs": {"NetworkSettings": {"Networks": {}}}, + "reload": lambda self: None, + "labels": {}, + "logs": lambda self, **kw: b"", + }, + )() + return _CapturingDockerManager- class _CapturingDockerManager: - ... - monkeypatch.setattr(run_cmd, "DockerManager", _CapturingDockerManager) + monkeypatch.setattr( + run_cmd, + "DockerManager", + _make_capturing_manager(captured, "vibepod-claude-test"), + )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_run.py` around lines 715 - 1005, Multiple tests duplicate the _CapturingDockerManager stub; extract it into a single helper (or pytest fixture) to reduce repetition. Create a helper function or class (e.g., _make_capturing_docker_manager or a pytest fixture named capturing_docker_manager) that accepts the shared captured dict and returns a DockerManager-like object implementing ensure_network, networks_with_running_containers, pull_image, ensure_proxy, and run_agent (which updates the provided captured dict and returns the container object used in tests). Replace each inline _CapturingDockerManager in the tests with calls to this helper or the fixture and wire monkeypatch.setattr(run_cmd, "DockerManager", ...) to use the helper to keep existing test behavior (preserve container attrs, name/id/status, and logs/reload lambdas). Ensure tests that need per-agent differences still pass a modified container name or env via parameters to the helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@tests/test_run.py`:
- Around line 711-766: Rename the misleading test names/docstrings so they match
the environment variables actually asserted: update
test_llm_enabled_injects_openai_env_vars (and its docstring) to reference
"ANTHROPIC env vars" (or "Anthropic env vars") since the assertions check
ANTHROPIC_* and update test_llm_enabled_injects_openai_env_vars_for_codex (and
its docstring) to reference "CODEX_OSS env vars" (or "Codex OSS env vars") to
match the CODEX_OSS_* assertions; change only the function names and docstring
strings (keep behavior and assertions in run_cmd.run, _CapturingDockerManager,
captured, and env checks unchanged).
- Around line 715-1005: Multiple tests duplicate the _CapturingDockerManager
stub; extract it into a single helper (or pytest fixture) to reduce repetition.
Create a helper function or class (e.g., _make_capturing_docker_manager or a
pytest fixture named capturing_docker_manager) that accepts the shared captured
dict and returns a DockerManager-like object implementing ensure_network,
networks_with_running_containers, pull_image, ensure_proxy, and run_agent (which
updates the provided captured dict and returns the container object used in
tests). Replace each inline _CapturingDockerManager in the tests with calls to
this helper or the fixture and wire monkeypatch.setattr(run_cmd,
"DockerManager", ...) to use the helper to keep existing test behavior (preserve
container attrs, name/id/status, and logs/reload lambdas). Ensure tests that
need per-agent differences still pass a modified container name or env via
parameters to the helper.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0ae59b23-3e7c-4d29-82a6-5f7490526acd
📒 Files selected for processing (9)
docs/configuration.mddocs/llm.mdmkdocs.ymlsrc/vibepod/commands/run.pysrc/vibepod/core/agents.pysrc/vibepod/core/config.pytests/test_agents.pytests/test_config.pytests/test_run.py
Introduces first-class support for connecting VibePod agents to external LLM servers (such as Ollama and vLLM) via a new unified
llmconfiguration section. It enables automatic injection of environment variables and CLI flags for supported agents (Claude Code and Codex), allowing users to run these agents against open-source models or compatible endpoints.Summary by CodeRabbit
Release Notes
New Features
Documentation