Merge pull request #3 from amoussa1229/chore/ci-workflow-sonnet-bump
Add CI workflow and bump Sonnet to 4.6
This commit is contained in:
commit
db34d7e0ba
4 changed files with 67 additions and 15 deletions
50
.github/workflows/ci.yaml
vendored
Normal file
50
.github/workflows/ci.yaml
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install ruff
|
||||
run: pip install ruff
|
||||
|
||||
- name: Ruff check
|
||||
run: ruff check .
|
||||
|
||||
- name: Ruff format check
|
||||
run: ruff format --check .
|
||||
|
||||
test-collect:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: pip
|
||||
cache-dependency-path: requirements.txt
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -r requirements.txt
|
||||
pip install pytest python-dotenv
|
||||
|
||||
- name: Pytest collect-only
|
||||
# Verifies all test modules + their imports resolve cleanly.
|
||||
# Live test execution requires ANTHROPIC_API_KEY + COMPOSIO_API_KEY
|
||||
# and runs locally before push, not in CI.
|
||||
run: pytest --collect-only -q
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -6,3 +6,4 @@ __pycache__/
|
|||
.cache/
|
||||
.pytest_cache/
|
||||
.ruff_cache/
|
||||
.DS_Store
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from langchain_google_genai import ChatGoogleGenerativeAI
|
|||
from langchain_openai import ChatOpenAI
|
||||
|
||||
# Model IDs — single source of truth. Bump here when families ship new revs.
|
||||
CLAUDE_SONNET = "claude-sonnet-4-20250514"
|
||||
CLAUDE_SONNET = "claude-sonnet-4-6"
|
||||
CLAUDE_HAIKU = "claude-haiku-4-5-20251001"
|
||||
OPENAI_CROSS_REVIEWER = "gpt-4.1"
|
||||
GEMINI_SCANNER = "gemini-2.5-pro"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
"""Golden-set routing test for the structured router.
|
||||
|
||||
20 labelled tasks → expected agent. Skipped if provider keys are missing
|
||||
(ANTHROPIC for the router LLM, COMPOSIO because importing the graph eagerly
|
||||
loads tools). Run with:
|
||||
20 labelled tasks → expected agent. Live tests require ANTHROPIC_API_KEY +
|
||||
COMPOSIO_API_KEY; without them the parametrized cases skip at runtime but
|
||||
the module still collects (so `pytest --collect-only` in CI works without
|
||||
secrets). Run with:
|
||||
|
||||
pytest tests/test_routing_golden.py -v
|
||||
"""
|
||||
|
|
@ -14,17 +15,12 @@ from dotenv import load_dotenv
|
|||
|
||||
load_dotenv(os.path.join(os.path.dirname(__file__), "..", ".env"))
|
||||
|
||||
if not os.getenv("ANTHROPIC_API_KEY"):
|
||||
pytest.skip(
|
||||
"ANTHROPIC_API_KEY not set; skipping live router tests.",
|
||||
allow_module_level=True,
|
||||
)
|
||||
if not os.getenv("COMPOSIO_API_KEY"):
|
||||
pytest.skip(
|
||||
"COMPOSIO_API_KEY not set; skipping live router tests.", allow_module_level=True
|
||||
)
|
||||
|
||||
from graph import router_node # noqa: E402
|
||||
_REQUIRED_KEYS = ("ANTHROPIC_API_KEY", "COMPOSIO_API_KEY")
|
||||
_missing = [k for k in _REQUIRED_KEYS if not os.getenv(k)]
|
||||
requires_keys = pytest.mark.skipif(
|
||||
bool(_missing),
|
||||
reason=f"Requires {', '.join(_REQUIRED_KEYS)}; missing: {', '.join(_missing)}",
|
||||
)
|
||||
|
||||
|
||||
GOLDEN_SET: list[tuple[str, str]] = [
|
||||
|
|
@ -107,8 +103,13 @@ def test_golden_set_size():
|
|||
assert len(GOLDEN_SET) == 20
|
||||
|
||||
|
||||
@requires_keys
|
||||
@pytest.mark.parametrize("task,expected", GOLDEN_SET)
|
||||
def test_router_picks_expected_agent(task: str, expected: str):
|
||||
# Lazy import — graph.py loads composio_tools at module import and needs
|
||||
# COMPOSIO_API_KEY. Keep the import inside the skipif-guarded test body.
|
||||
from graph import router_node
|
||||
|
||||
out = router_node({"task": task, "messages": []})
|
||||
assert out["route"] == expected, (
|
||||
f"task={task!r} got={out['route']} expected={expected}"
|
||||
|
|
|
|||
Reference in a new issue