Skip to content

Commit f3dbe5c

Browse files
author
Mateusz
committed
feat: Add OpenCode Zen backend and migrate to Kiro spec system
Major changes: - Migrate from OpenSpec to Kiro spec-driven development system in AGENTS.md - Add OpenCode Zen backend connector with full integration and unit tests - Enhance OpenAI Codex connector with improved Droid compatibility - Add models controller endpoints for backend model listing - Improve translation service and streaming contracts - Update test suite with better documentation coverage - Add demo script for Droid codex translation - Add utility script for checking redirects Files changed: 22 modified, 7 new (1095 insertions, 513 deletions)
1 parent dccb7f7 commit f3dbe5c

29 files changed

+3036
-513
lines changed

AGENTS-OpenSpec.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<!-- OPENSPEC:START -->
2+
# OpenSpec Instructions
3+
4+
These instructions are for AI assistants working in this project.
5+
6+
Always open `@/openspec/AGENTS.md` when the request:
7+
8+
- Mentions planning or proposals (words like proposal, spec, change, plan)
9+
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
10+
- Sounds ambiguous and you need the authoritative spec before coding
11+
12+
Use `@/openspec/AGENTS.md` to learn:
13+
- How to create and apply change proposals
14+
- Spec format and conventions
15+
- Project structure and guidelines
16+
17+
Keep this managed block so 'openspec update' can refresh the instructions.
18+
19+
<!-- OPENSPEC:END -->
20+
21+
## Agent Onboarding & Development Guidelines
22+
23+
## Project Identity
24+
25+
**Universal LLM Proxy** built with **FastAPI (Async)** using **Staged Initialization**.
26+
27+
- **Core Features**: Traffic routing, failover, accounting, and byte-precise **CBOR wire captures**.
28+
- **Architecture**: Service-based (DI), Staged startup (`src/core/app/stages`), Adapter pattern for LLM backends.
29+
30+
## Quick Start
31+
32+
1. **Environment**: Windows-based. ALWAYS use `./.venv/Scripts/python.exe`.
33+
2. **Config**: `cp config/config.example.yaml config/config.yaml` (if missing).
34+
3. **Start**: `./.venv/Scripts/python.exe -m src.core.cli`
35+
4. **Onboarding**: Open `@README.md` for fundamenal project description.
36+
5. **Docs**: Check `docs/` for architecture deep-dives.
37+
38+
## Key Architecture Paths
39+
40+
| Path | Purpose |
41+
|------|---------|
42+
| `src/core/cli.py` | **Entry Point**. CLI args -> Config -> App Builder. |
43+
| `src/core/app/stages/` | **Startup Logic**. Infrastructure -> Services -> Backends -> Controllers. |
44+
| `src/connectors/` | **Backends**. Implementations for OpenAI, Gemini, Anthropic, etc. |
45+
| `src/core/simulation/` | **Debugging**. Traffic replay & inspection tools (`capture_reader.py`). |
46+
| `var/wire_captures_cbor/` | **Data**. Binary captures of all traffic (pair with `var/logs/`). |
47+
48+
## Commands & Workflow
49+
50+
**Rule**: Edit `pyproject.toml` for deps. **NO** manual `pip install`. **NO** emojis.
51+
52+
| Action | Command |
53+
|--------|---------|
54+
| **Test (Fast)** | `./.venv/Scripts/python.exe -m pytest` (skips slow/integration) |
55+
| **Test (Full)** | `./.venv/Scripts/python.exe -m pytest -m "integration or unit"` |
56+
| **Lint/Fix** | `./.venv/Scripts/python.exe -m ruff --fix check .` |
57+
| **Format** | `./.venv/Scripts/python.exe -m black .` |
58+
| **Inspect** | `./.venv/Scripts/python.exe scripts/inspect_cbor_capture.py <file> --detect-issues` |
59+
60+
## Quality & Testing Standards
61+
62+
1. **TDD**: Write test -> Fail -> Code -> Pass.
63+
2. **Verify**: Run **directly related tests** first. Fix until green.
64+
3. **Regression**: Run full suite after multi-file changes.
65+
4. **Style**: PEP 8, Async/Await correctness, Exception Hierarchy (`LLMProxyError`).
66+
5. **Safety**: Never remove features without explicit request.
67+
68+
## Common Pitfalls
69+
70+
- **Async**: Use `await` for all I/O. Don't block the event loop.
71+
- **Paths**: Use `pathlib` or `/` forward slashes (Windows accepts them).
72+
- **Errors**: Don't use bare `except Exception`. Log with `exc_info=True`.

AGENTS.md

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
1-
<!-- OPENSPEC:START -->
2-
# OpenSpec Instructions
1+
<!-- KIRO-SPEC:START -->
2+
# Kiro Spec-Driven Development
33

4-
These instructions are for AI assistants working in this project.
4+
## When to Use Kiro Specs
55

6-
Always open `@/openspec/AGENTS.md` when the request:
6+
**Suggest spec workflow** when request involves: new features, breaking changes, architecture shifts, complex integrations, or unclear requirements needing structured analysis.
77

8-
- Mentions planning or proposals (words like proposal, spec, change, plan)
9-
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
10-
- Sounds ambiguous and you need the authoritative spec before coding
8+
**Code directly** for: quick fixes, simple bugs, trivial changes, or when user explicitly says "just code this".
119

12-
Use `@/openspec/AGENTS.md` to learn:
13-
- How to create and apply change proposals
14-
- Spec format and conventions
15-
- Project structure and guidelines
10+
## Kiro Commands (User-Triggered)
1611

17-
Keep this managed block so 'openspec update' can refresh the instructions.
12+
When working on specs, the user will invoke `/kiro:*` commands. Follow the instructions provided in each command's context.
1813

19-
<!-- OPENSPEC:END -->
14+
**Workflow order**: `spec-init``spec-requirements``spec-design``spec-tasks``spec-impl`
2015

21-
## Agent Onboarding & Development Guidelines
16+
**Spec-driven rule**: When a spec exists at `.kiro/specs/{feature}/`, no code edits until `requirements.md` and `design.md` are approved (check `spec.json` for approval status). Every task in `tasks.md` must reference at least one acceptance criterion from requirements.
17+
18+
**Key locations**:
19+
20+
- Specs: `.kiro/specs/{feature-name}/` (requirements.md, design.md, tasks.md, research.md)
21+
- Steering (project memory): `.kiro/steering/` - load when generating specs
22+
- Templates: `.kiro/settings/templates/`
23+
- Rules: `.kiro/settings/rules/`
24+
<!-- KIRO-SPEC:END -->
2225

2326
## Project Identity
2427

@@ -64,6 +67,11 @@ Keep this managed block so 'openspec update' can refresh the instructions.
6467
3. **Regression**: Run full suite after multi-file changes.
6568
4. **Style**: PEP 8, Async/Await correctness, Exception Hierarchy (`LLMProxyError`).
6669
5. **Safety**: Never remove features without explicit request.
70+
6. **Post-edit QA**: After each Python file edit, run:
71+
72+
```powershell
73+
./.venv/Scripts/python.exe -m ruff check --fix <file> && ./.venv/Scripts/python.exe -m black <file> && ./.venv/Scripts/python.exe -m mypy <file>
74+
```
6775

6876
## Common Pitfalls
6977

check_redirects.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
import httpx
3+
import asyncio
4+
5+
async def check_redirects():
6+
url = "https://opencode.ai/zen/v1/models"
7+
print(f"Checking URL: {url}")
8+
async with httpx.AsyncClient() as client:
9+
resp = await client.get(url, follow_redirects=False)
10+
print(f"Status: {resp.status_code}")
11+
if resp.is_redirect:
12+
print(f"Redirect location: {resp.headers.get('location')}")
13+
14+
# Also check POST endpoint
15+
url_post = "https://opencode.ai/zen/v1/chat/completions"
16+
print(f"Checking POST URL: {url_post}")
17+
resp_post = await client.post(url_post, follow_redirects=False)
18+
print(f"Status: {resp_post.status_code}")
19+
if resp_post.is_redirect:
20+
print(f"Redirect location: {resp_post.headers.get('location')}")
21+
22+
if __name__ == "__main__":
23+
asyncio.run(check_redirects())

data/test_suite_state.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"test_count": 7613,
2+
"test_count": 7717,
33
"last_updated": "1764197177.513252"
44
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# OpenCode Zen Backend
2+
3+
The `opencode-zen` backend allows the LLM Interactive Proxy to route requests through OpenCode's Zen gateway using the credentials managed by the OpenCode CLI. This integration provides seamless access to premium models like `anthropic/claude-sonnet-4` and `openai/gpt-4.1` for users who are already authenticated with the OpenCode CLI.
4+
5+
## Prerequisites
6+
7+
1. **OpenCode CLI Installed**: You must have the `opencode` CLI tool installed on your system.
8+
2. **Authenticated**: You must be logged in via the CLI.
9+
```bash
10+
opencode auth login
11+
```
12+
This command generates the `auth.json` file that this backend reads.
13+
14+
## Configuration
15+
16+
To use this backend, add it to your configuration (e.g., `config/config.yaml`) or rely on the default auto-discovery if enabled.
17+
18+
### Basic Configuration
19+
20+
```yaml
21+
backends:
22+
opencode-zen:
23+
enabled: true
24+
# Optional: Custom API URL
25+
# api_base_url: "https://opencode.ai/zen/v1"
26+
```
27+
28+
### Environment Variables
29+
30+
| Variable | Description | Default |
31+
|----------|-------------|---------|
32+
| `OPENCODE_AUTH_PATH` | Custom path to the `auth.json` file. | OS-specific default (see below) |
33+
| `OPENCODE_ZEN_API_URL` | Override the gateway API endpoint. | `https://opencode.ai/zen/v1` |
34+
35+
## Credential Locations
36+
37+
The backend automatically detects the `auth.json` file created by the OpenCode CLI in standard locations:
38+
39+
| Platform | Default Path |
40+
|----------|--------------|
41+
| **Windows** | `%LOCALAPPDATA%\opencode\auth.json` |
42+
| **Linux** | `$XDG_DATA_HOME/opencode/auth.json` or `~/.local/share/opencode/auth.json` |
43+
| **macOS** | `$XDG_DATA_HOME/opencode/auth.json` or `~/.local/share/opencode/auth.json` |
44+
45+
If your credentials are stored elsewhere, use the `OPENCODE_AUTH_PATH` environment variable or `credentials_path` in config.
46+
47+
## Supported Models
48+
49+
The backend dynamically fetches the list of available models from the OpenCode Zen gateway. As of the latest check, the following models are supported:
50+
51+
### Anthropic
52+
- `anthropic/claude-opus-4-5`
53+
- `anthropic/claude-opus-4-1`
54+
- `anthropic/claude-sonnet-4-5`
55+
- `anthropic/claude-sonnet-4`
56+
- `anthropic/claude-3-5-haiku`
57+
- `anthropic/claude-haiku-4-5`
58+
59+
### OpenAI
60+
- `openai/gpt-5.1`
61+
- `openai/gpt-5`
62+
- `openai/gpt-5.1-codex-max`
63+
- `openai/gpt-5.1-codex`
64+
- `openai/gpt-5-codex`
65+
- `openai/gpt-5-nano`
66+
67+
### Google
68+
- `google/gemini-3-pro`
69+
70+
### Other Vendors
71+
- `qwen/qwen3-coder`
72+
- `zhipuai/glm-4.6`
73+
- `moonshot/kimi-k2`
74+
- `moonshot/kimi-k2-thinking`
75+
- `xai/grok-code`
76+
- `deepmind/alpha-gd4`
77+
- `misc/big-pickle`
78+
79+
When sending requests, you can use either the plain model name (e.g., `claude-sonnet-4`) or prefix it with the vendor (e.g., `opencode-zen:claude-sonnet-4`) to ensure routing to this specific backend. Note that the backend normalized the model names, so `anthropic/claude-sonnet-4` is accessed via `opencode-zen:claude-sonnet-4`.
80+
81+
## Usage Example
82+
83+
Once configured, you can send requests using the proxy:
84+
85+
```bash
86+
curl http://localhost:8080/v1/chat/completions \
87+
-H "Content-Type: application/json" \
88+
-d '{
89+
"model": "opencode-zen:anthropic/claude-sonnet-4",
90+
"messages": [{"role": "user", "content": "Hello!"}]
91+
}'
92+
```
93+
94+
## Troubleshooting
95+
96+
### "OpenCode credentials not found"
97+
- Ensure you have run `opencode auth login`.
98+
- Verify the file exists at the expected path for your OS.
99+
- If using a custom path, check `OPENCODE_AUTH_PATH`.
100+
101+
### "OpenCode OAuth token is expired"
102+
- The backend automatically reloads the credentials file if the token is expired.
103+
- If the error persists, the refresh token might also be invalid. Run `opencode auth login` again to refresh your session.
104+
105+
### "Backend is not functional"
106+
- Check the application logs for specific initialization errors.
107+
- Ensure the `auth.json` file is valid JSON and contains the `opencode` provider key with OAuth credentials.

0 commit comments

Comments
 (0)