Files
AirToSocks/AGENTS.md

272 lines
7.7 KiB
Markdown

# AGENTS.md
## Purpose
This repo is a small Python Flask service that converts subscription links (`vmess`, `vless`, `trojan`, `ss`) into local SOCKS5 proxies via `xray-core`.
Almost all backend logic, API routes, and the inline web UI live in `main.py`.
Agents should prefer minimal, in-place changes over architectural rewrites.
## Repository Layout
- `main.py`: app entrypoint, dataclasses, parsers, proxy manager, schedulers, Flask routes, and embedded HTML/CSS/JS.
- `requirements.txt`: runtime dependencies.
- `start.sh`: local bootstrap script.
- `Dockerfile`: image build.
- `docker-compose.yml`: recommended container run path.
- `config.yaml.example`: optional config sample.
- `config/`: persisted JSON state.
- `data/`: runtime files such as generated xray configs.
- `bin/`: xray binary/assets.
## Extra Agent Rules
I checked for repo-specific agent instruction files:
- `.cursor/rules/`: not present.
- `.cursorrules`: not present.
- `.github/copilot-instructions.md`: not present.
There are no Cursor or Copilot rules to merge into this file right now.
## Environment
- Python: README says `3.10+`.
- Docker image: `python:3.13-slim`.
- Default web port: `8080`.
- App downloads `xray-core` on startup if `bin/xray` is missing.
- Runtime state is persisted under `config/` and `data/`.
## Setup Commands
### Local environment
```bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
### Run locally
```bash
python3 main.py
```
### Run via helper script
```bash
chmod +x start.sh
./start.sh
```
### Build Docker image
```bash
docker build -t airtosocks .
```
### Run with Docker Compose
```bash
docker-compose up -d
docker-compose logs -f
docker-compose down
```
## Build, Lint, And Test Reality
This repository currently has no formal lint or test setup.
- No `tests/` directory was found.
- No `pytest` or `unittest` test files were found.
- No `ruff`, `black`, `isort`, `flake8`, `pylint`, `mypy`, `tox`, or `nox` config was found.
Agents should say this explicitly instead of pretending a missing command exists.
## Verification Commands That Work Today
### Syntax check
```bash
python3 -m py_compile main.py
```
### Compile Python files
```bash
python3 -m compileall .
```
### Manual app run
```bash
python3 main.py
```
### HTTP smoke checks
```bash
curl http://127.0.0.1:8080/api/links
curl http://127.0.0.1:8080/api/subscriptions
curl http://127.0.0.1:8080/api/random
```
### Container smoke checks
```bash
docker-compose up -d
curl http://127.0.0.1:8080/api/links
docker-compose logs --tail=200
docker-compose down
```
## Single-Test Guidance
There is no real single-test command yet because there is no test suite.
If tests are added later, prefer `pytest` and document commands like:
```bash
pytest
pytest tests/test_parser.py
pytest tests/test_parser.py::test_parse_vmess
```
Until then, a “single test” means a targeted manual verification of the exact parser, route, or runtime behavior touched by the change.
## Config Notes
Optional runtime config lives in `config.yaml` and currently supports:
```yaml
port: 8080
check_interval: 600
```
When changing config behavior:
- Preserve compatibility for missing keys.
- Keep defaults aligned across code, `README.md`, and `config.yaml.example`.
- Do not silently rename config fields.
## Code Style
The repo does not use an autoformatter today. Match the existing style unless the user asks for cleanup.
### Imports
- Keep standard library imports before third-party imports.
- Do not reorder the whole import block for cosmetic reasons.
- Add new imports near related imports.
- Prefer explicit imports over wildcard imports.
### Formatting
- Follow normal Python/PEP 8 conventions without broad reformatting.
- Use 4-space indentation.
- Preserve surrounding quote style; Python code here mostly uses single quotes.
- Avoid reflowing large inline HTML, CSS, or JS unless required.
- Keep diffs small and local.
### Types
- Continue the existing `typing` style: `Optional`, `List`, `Dict`, `Tuple`, `Any`.
- Add type hints for new helpers when practical.
- Use `@dataclass` for record-like state models.
- Do not introduce a new validation or typing framework without a concrete need.
### Naming
- `snake_case` for variables, functions, and methods.
- `PascalCase` for classes.
- `UPPER_SNAKE_CASE` for module constants.
- Use descriptive domain names like `subscription_id`, `socks_port`, `last_check`, `available_count`.
### Data Modeling And Persistence
- Persist structured state through dataclasses and `asdict(...)`.
- New persisted fields need safe defaults so old JSON continues to load.
- Consider compatibility with existing files in `config/`.
- Do not casually rename persisted fields.
### Error Handling
- Follow the existing pattern: catch failures near parsing, file I/O, network calls, and subprocess operations.
- Use `logger.error(...)` or `logger.warning(...)`, then return a safe fallback or JSON error.
- Avoid crashing daemon threads for recoverable problems.
- Prefer specific exceptions when obvious, but broad `except Exception as e` is already common here.
- API handlers should return meaningful JSON error payloads with sensible HTTP status codes.
### Logging
- Use the module-level `logger`, not `print`.
- Keep log messages short and operational.
- Include useful identifiers such as node name, subscription name, or port.
- Do not log secrets or full credentials from proxy links unless absolutely necessary.
### Concurrency And Shared State
- `ProxyManager` protects mutable state with `threading.RLock`; preserve that discipline.
- Be careful when changing `nodes`, `subscriptions`, `pools`, `used_ports`, or `xray_processes`.
- Keep background threads daemonized when matching the current pattern.
- Do not introduce async or heavier concurrency models for small tasks.
### Files, Processes, And Runtime Data
- Runtime files belong under `config/` or `data/`.
- Keep xray config generation deterministic and JSON-serializable.
- Follow the existing `subprocess.Popen(...)` pattern for xray processes.
- Release ports and clean up subprocess state on failure paths.
### Flask And API Conventions
- Keep Flask route handlers thin.
- Put behavior in `ProxyManager` or small helpers rather than in the route body.
- Return `jsonify(...)` for API responses.
- Validate request JSON defensively.
- Keep API response shapes stable unless a breaking change is explicitly requested.
### Frontend Conventions
- The frontend is intentionally inline inside the `/` route.
- For small UI changes, edit the embedded HTML/JS directly instead of adding a frontend build system.
- Preserve the current fetch-based interaction pattern.
- Keep the existing visual language unless the task asks for redesign work.
### Comments And Docs
- Existing comments/docstrings are short and often Chinese; match the surrounding language in touched code.
- Add comments only when behavior is not obvious from the code.
- Update `README.md`, `config.yaml.example`, and this file when commands or behavior change.
## Change Strategy For Agents
- Prefer surgical edits.
- Avoid splitting `main.py` into modules unless explicitly requested.
- Respect persisted data compatibility.
- Ignore unrelated runtime files unless the task specifically involves them.
- If you add tests or lint tooling, immediately document the new commands here.
## Recommended Post-Change Checks
For most Python-only changes:
```bash
python3 -m py_compile main.py
```
For API behavior changes:
1. Start the app with `python3 main.py`.
2. Hit the affected endpoint with `curl`.
3. Confirm there is no traceback and the response shape is correct.
For Docker-related changes:
```bash
docker build -t airtosocks .
docker-compose up -d
curl http://127.0.0.1:8080/api/links
docker-compose down
```