Skip to content
Merged
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Set up Python ${{ matrix.python-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build_sphinx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Set up Python 3.11
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Set up Python ${{ matrix.python-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Set up Python ${{ matrix.python-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sphinx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Set up Python 3.11
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Set up Python ${{ matrix.python-version }}
Expand Down
45 changes: 45 additions & 0 deletions .github/workflows/zai-code-bot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Z.ai Code Bot

on:
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review
branches:
- main
- prod
issue_comment:
types:
- created
pull_request_review_comment:
types:
- created

permissions:
contents: read
pull-requests: write
issues: write

concurrency:
group: zai-bot-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
zai-bot:
if: |
(github.event_name == 'pull_request' && github.event.pull_request.draft == false) ||
(github.event_name == 'issue_comment' && github.event.issue.pull_request) ||
(github.event_name == 'pull_request_review_comment' && github.event.pull_request.draft == false)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Run Z.ai Bot
uses: AndreiDrang/zai-code-bot@main
with:
ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}
ZAI_MODEL: ${{ vars.ZAI_MODEL || 'glm-5' }}
GITHUB_TOKEN: ${{ github.token }}
71 changes: 51 additions & 20 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,72 @@
# PROJECT KNOWLEDGE BASE

**Generated:** 2026-01-13
**Generated:** 2026-03-15
**Commit:** b797332
**Branch:** main

## OVERVIEW
Python 3.8+ library for Capsolver service API. Supports both synchronous (`requests`) and asynchronous (`aiohttp`) operations. Uses `msgspec` for high-performance JSON serialization.
Python 3.8+ library for Capsolver service API. Dual sync (`requests`) / async (`aiohttp`) support. `msgspec` for serialization, `tenacity` for retries.

## STRUCTURE
```
./
├── src/python3_capsolver/ # Main library package
│ ├── core/ # Base classes, serializers, instruments
│ └── *.py # Service-specific implementations (ReCaptcha, Cloudflare, etc.)
├── tests/ # Pytest suite
└── docs/ # Sphinx documentation
├── src/python3_capsolver/ # Main library (service implementations)
│ ├── core/ # Base classes, instruments, serializers
│ └── *.py # Service-specific (ReCaptcha, Cloudflare, etc.)
├── tests/ # Pytest suite (matches source structure)
├── docs/ # Sphinx documentation
├── ARCHITECTURE.md # System architecture (matklad-style)
└── pyproject.toml # Build, uv, pytest, black/isort config
```

## WHERE TO LOOK
| Task | Location | Notes |
|------|----------|-------|
| **Base Logic** | `src/python3_capsolver/core/` | `base.py`, `serializer.py`, `enum.py` |
| **Service Implementations** | `src/python3_capsolver/*.py` | `recaptcha.py`, `cloudflare.py`, etc. |
| **Tests** | `tests/` | Matches source structure |
| **Configuration** | `pyproject.toml` | Build, dependency, tool config |
| **Architecture** | `ARCHITECTURE.md` | Layered design, invariants, life of a request |
| **Base Logic** | `src/python3_capsolver/core/` | `base.py`, `serializer.py`, `enum.py`, instruments |
| **Service Implementations** | `src/python3_capsolver/*.py` | `recaptcha.py`, `cloudflare.py`, `control.py` |
| **Tests** | `tests/` | `conftest.py` (BaseTest, fixtures), per-service tests |
| **Configuration** | `pyproject.toml` | uv, black (120), isort, pytest (asyncio auto) |
| **Commands** | `Makefile` | `make tests`, `make build`, `make upload` |

## CONVENTIONS
- **Formatter**: `black` (line-length 120), `isort` (profile "black").
- **Serialization**: `msgspec` preferred over `json` for performance.
- **Concurrency**: Dual support (Sync/Async) required for all instruments.
- **Retries**: `tenacity` library used for resilience.
- **Toolchain**: `uv` for package management (`uv sync`, `uv run`, `uv build`, `uv publish`)
- **Formatter**: `black` (line-length 120), `isort` (profile "black")
- **Cleanup**: `autoflake` (remove unused imports/variables)
- **Serialization**: `msgspec` (not `json`) for performance
- **Concurrency**: Dual sync/async required for all instruments
- **Retries**: `tenacity` (async), `requests.Retry` (sync) — 5 attempts, exponential backoff
- **Testing**: pytest 7.0+, `pytest-asyncio` (auto mode), rate-limiting fixtures (1s func, 2s class)

## ANTI-PATTERNS (THIS PROJECT)
- **Empty `__init__.py` files**: `src/python3_capsolver/__init__.py` only exports `__version__`; `core/__init__.py` is completely empty. Users must import via full paths (`from python3_capsolver.recaptcha import ReCaptcha`)
- **AGENTS.md in package dirs**: Will ship with distribution unless excluded in `pyproject.toml`
- **No CLI entry points**: Library-only, no console_scripts defined

## UNIQUE STYLES
- **Service Pattern**: Each captcha service inherits from `CaptchaParams` with `captcha_handler()` (sync) + `aio_captcha_handler()` (async)
- **Task Payload**: Dict merged with internal params, passed to `create_task()` API
- **Context Managers**: All services support `with` / `async with` for session cleanup
- **Test Duplication**: Every sync test (`def test_*`) has async counterpart (`async def test_aio_*`)

## COMMANDS
```bash
make tests # Run test suite
pip install . # Install package locally
# Development
uv sync --all-groups # Install all dependencies
uv run pytest tests/ # Run tests
uv run black src/ tests/ # Format
uv run isort src/ tests/ # Sort imports

# Build & Publish
uv build # Build wheel/sdist
uv publish # Upload to PyPI

# Documentation
cd docs/ && uv run --group docs make html -e
```

## NOTES
- Dependencies: `requests`, `aiohttp`, `msgspec`, `tenacity`.
- Requires `API_KEY` in environment for tests.

- **API Key**: Tests require `API_KEY` environment variable
- **Coverage**: HTML reports in `coverage/html/`, XML in `coverage/coverage.xml`
- **Python Support**: 3.8–3.12 (tested via `target-version = ['py310']`)
- **Dependencies**: `requests>=2.21.0`, `aiohttp>=3.9.2`, `msgspec>=0.18,<=0.21`, `tenacity>=8,<10`
Loading
Loading