88 lines
3.1 KiB
Python
88 lines
3.1 KiB
Python
"""End-to-end test for ``examples/claude_code_agent.yaml``.
|
|
|
|
The example pins ``executor.type: claude_sdk`` and exposes
|
|
Claude Code's built-in tools (Bash, Read, Edit, etc.) plus any
|
|
Omnigent tools declared in YAML (passed through as MCP tools).
|
|
|
|
**What breaks if this fails:**
|
|
- ``executor.type: claude_sdk`` spec translation regresses.
|
|
- The ``claude_sdk`` harness wiring loses its MCP-tool bridging
|
|
(Omnigent tools declared in YAML stop reaching Claude).
|
|
- Harness-specific ``--model`` resolution changes.
|
|
|
|
Dependency: requires the ``claude-agent-sdk`` Python package. We
|
|
fail loud upfront via :func:`require_claude_sdk` rather than
|
|
letting the subprocess die with a mid-run ImportError.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from tests.e2e.conftest import configure_mock_llm, reset_mock_llm
|
|
from tests.e2e.omnigent._example_helpers import (
|
|
assert_completed_one_shot,
|
|
require_claude_sdk,
|
|
run_one_shot,
|
|
)
|
|
|
|
|
|
def test_claude_code_agent_one_shot(
|
|
omnigent_python: Path,
|
|
omnigent_repo_root: Path,
|
|
mock_credentials_env: dict[str, str],
|
|
mock_llm_server_url: str,
|
|
) -> None:
|
|
"""
|
|
Run the claude_code_agent YAML one-shot through the claude_sdk
|
|
harness (pinned in the YAML — we pass ``harness=None`` so the
|
|
spec wins).
|
|
|
|
Uses the mock LLM server so no real Anthropic credentials are
|
|
needed. ``ANTHROPIC_BASE_URL`` is injected into the env dict so
|
|
the Claude SDK harness routes its ``POST /v1/messages`` calls to
|
|
the mock server instead of api.anthropic.com.
|
|
|
|
:param omnigent_python: Interpreter with omnigent +
|
|
claude-agent-sdk installed.
|
|
:param omnigent_repo_root: Repo root for subprocess cwd.
|
|
:param mock_credentials_env: Env dict pointing at the mock LLM
|
|
server (``OPENAI_BASE_URL`` + ``OPENAI_API_KEY``).
|
|
:param mock_llm_server_url: Base URL of the mock LLM server
|
|
(no ``/v1`` suffix — the Anthropic SDK appends
|
|
``/v1/messages`` automatically).
|
|
"""
|
|
if shutil.which("claude") is None:
|
|
pytest.skip("'claude' CLI is not on PATH. Install Claude Code to run this test.")
|
|
|
|
require_claude_sdk()
|
|
|
|
mock_model = "mock-claude-code-agent"
|
|
reset_mock_llm(mock_llm_server_url)
|
|
configure_mock_llm(
|
|
mock_llm_server_url,
|
|
[{"text": "OK"}],
|
|
key=mock_model,
|
|
)
|
|
|
|
# Inject the Anthropic mock base URL so the Claude SDK harness routes
|
|
# LLM calls to the mock server. The SDK appends /v1/messages itself,
|
|
# so we pass the raw server root without a /v1 suffix.
|
|
env = dict(mock_credentials_env)
|
|
env["ANTHROPIC_BASE_URL"] = mock_llm_server_url
|
|
env["ANTHROPIC_API_KEY"] = "mock-key"
|
|
env["HARNESS_CLAUDE_SDK_API_KEY_HELPER"] = "printf %s mock-key"
|
|
|
|
result = run_one_shot(
|
|
omnigent_python=omnigent_python,
|
|
omnigent_repo_root=omnigent_repo_root,
|
|
omnigent_credentials_env=env,
|
|
example_name="claude_code_agent",
|
|
harness=None, # Let the YAML's executor.type pin win.
|
|
model=mock_model,
|
|
)
|
|
assert_completed_one_shot(result, "claude_code_agent")
|