Skip to content

Commit 2b27615

Browse files
committed
Release v0.2.1
1 parent 5110115 commit 2b27615

79 files changed

Lines changed: 2158 additions & 485 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/RELEASE_NOTES.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
🎉 **New @tenro decorator and LLM tool call API**
2+
3+
**Added**
4+
5+
- **`@tenro` decorator**: Simplified test setup - no explicit fixture parameter needed:
6+
```python
7+
from tenro.testing import tenro
8+
from tenro.simulate import llm
9+
10+
@tenro
11+
def test_my_agent():
12+
llm.simulate(response="Hello!")
13+
result = my_agent.run("prompt")
14+
```
15+
16+
- **`LLMResponse`**: Ordered sequence of text and tool calls with full interleaving support:
17+
```python
18+
from tenro import LLMResponse, ToolCall
19+
20+
llm.simulate(Provider.ANTHROPIC, responses=[
21+
LLMResponse(blocks=["Let me search", ToolCall(search, query="AI")])
22+
])
23+
```
24+
25+
- **`RawLLMResponse`**: Raw provider JSON passthrough for edge cases:
26+
```python
27+
from tenro import RawLLMResponse
28+
29+
llm.simulate(Provider.OPENAI, responses=[
30+
RawLLMResponse(payload={"choices": [{"message": {"content": "Hi"}}]})
31+
])
32+
```
33+
34+
- **`ToolCall` smart constructor**: Direct tool call simulation without dict wrappers:
35+
```python
36+
# Before: {"tool_calls": [ToolCall(search, query="AI")]}
37+
# After:
38+
llm.simulate(Provider.OPENAI, responses=[
39+
ToolCall(search, query="AI")
40+
])
41+
```
42+
43+
---
44+
45+
**Installation**
46+
47+
```bash
48+
pip install tenro==0.2.1
49+
```

.github/workflows/ci.yml

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
lint:
14+
name: Lint
15+
runs-on: ubuntu-latest
16+
timeout-minutes: 5
17+
steps:
18+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
19+
20+
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
21+
with:
22+
enable-cache: true
23+
24+
- name: Set up Python
25+
run: |
26+
uv python install 3.12
27+
uv venv --python 3.12
28+
29+
- name: Install dependencies
30+
run: uv sync --dev
31+
32+
- name: Check formatting
33+
run: uv run ruff format --check .
34+
35+
- name: Check linting
36+
run: uv run ruff check . --output-format=github
37+
38+
- name: Type check
39+
run: uv run mypy src/
40+
41+
test:
42+
name: Test (Python ${{ matrix.python-version }})
43+
runs-on: ubuntu-latest
44+
timeout-minutes: 10
45+
strategy:
46+
fail-fast: false
47+
matrix:
48+
python-version: ["3.11", "3.12", "3.13"]
49+
steps:
50+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
51+
52+
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
53+
with:
54+
enable-cache: true
55+
56+
- name: Set up Python ${{ matrix.python-version }}
57+
run: |
58+
uv python install ${{ matrix.python-version }}
59+
uv venv --python ${{ matrix.python-version }}
60+
61+
- name: Install dependencies
62+
run: uv sync --group dev --group examples
63+
64+
- name: Run tests
65+
env:
66+
OPENAI_API_KEY: sk-fake-key-for-testing
67+
ANTHROPIC_API_KEY: sk-ant-fake-key-for-testing
68+
GOOGLE_API_KEY: fake-gemini-key-for-testing
69+
run: uv run pytest tests/ -v
70+
71+
clean-room:
72+
name: Clean Room Test
73+
runs-on: ubuntu-latest
74+
timeout-minutes: 10
75+
steps:
76+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
77+
78+
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
79+
with:
80+
enable-cache: true
81+
82+
- name: Set up Python
83+
run: |
84+
uv python install 3.12
85+
uv venv --python 3.12
86+
87+
- name: Build wheel
88+
run: uv build
89+
90+
- name: Clean-room install and test
91+
run: |
92+
set -euo pipefail
93+
94+
CLEAN_ROOM=$(mktemp -d)
95+
trap 'rm -rf "$CLEAN_ROOM"' EXIT
96+
echo "Clean room: $CLEAN_ROOM"
97+
98+
cp -R tests "$CLEAN_ROOM/tests"
99+
WHEEL="$(ls -1 dist/*.whl | sort | tail -1)"
100+
echo "Installing wheel: $WHEEL"
101+
102+
uv venv --python 3.12 "$CLEAN_ROOM/.venv"
103+
VIRTUAL_ENV="$CLEAN_ROOM/.venv" uv pip install "$WHEEL"
104+
VIRTUAL_ENV="$CLEAN_ROOM/.venv" uv pip install pytest pytest-asyncio respx
105+
106+
"$CLEAN_ROOM/.venv/bin/python" -c "import tenro; print(f'tenro {tenro.__version__}')"
107+
108+
cd "$CLEAN_ROOM"
109+
# Run core tests only (not examples, not openai_integration marked tests)
110+
PYTHONPATH=tests "$CLEAN_ROOM/.venv/bin/pytest" \
111+
tests/test_tool_simulation.py \
112+
tests/test_agent_simulation.py \
113+
tests/test_pytest_plugin.py \
114+
tests/test_llm_simulation.py \
115+
-v -m "not openai_integration"

0 commit comments

Comments
 (0)