airelays 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airelays-0.2.0/.github/workflows/ci.yml +37 -0
- airelays-0.2.0/.github/workflows/publish-pypi.yml +58 -0
- airelays-0.2.0/.gitignore +20 -0
- airelays-0.2.0/ACKNOWLEDGEMENTS.md +5 -0
- airelays-0.2.0/CHANGELOG.md +19 -0
- airelays-0.2.0/CODE_OF_CONDUCT.md +12 -0
- airelays-0.2.0/CONTRIBUTING.md +25 -0
- airelays-0.2.0/DISCLAIMER.md +9 -0
- airelays-0.2.0/LICENSE +21 -0
- airelays-0.2.0/PKG-INFO +258 -0
- airelays-0.2.0/README.md +229 -0
- airelays-0.2.0/SECURITY.md +20 -0
- airelays-0.2.0/airelay.example.env +11 -0
- airelays-0.2.0/docs/README.md +24 -0
- airelays-0.2.0/docs/adr/0001-no-silent-degradation-truncation-or-budget-invention.md +36 -0
- airelays-0.2.0/docs/adr/0002-chatgpt-subscription-backend-compatibility-boundary.md +30 -0
- airelays-0.2.0/docs/adr/0003-local-config-and-default-deny-relay-security.md +49 -0
- airelays-0.2.0/docs/adr/README.md +5 -0
- airelays-0.2.0/docs/api.md +185 -0
- airelays-0.2.0/docs/architecture.md +86 -0
- airelays-0.2.0/docs/configuration.md +129 -0
- airelays-0.2.0/docs/faq.md +54 -0
- airelays-0.2.0/docs/getting-started.md +204 -0
- airelays-0.2.0/docs/security.md +97 -0
- airelays-0.2.0/docs/subscription-status.md +43 -0
- airelays-0.2.0/docs/troubleshooting.md +86 -0
- airelays-0.2.0/llms-full.txt +152 -0
- airelays-0.2.0/llms.txt +49 -0
- airelays-0.2.0/pyproject.toml +47 -0
- airelays-0.2.0/src/airelay/__init__.py +3 -0
- airelays-0.2.0/src/airelay/__main__.py +5 -0
- airelays-0.2.0/src/airelay/app.py +765 -0
- airelays-0.2.0/src/airelay/auth.py +737 -0
- airelays-0.2.0/src/airelay/backend.py +243 -0
- airelays-0.2.0/src/airelay/cli.py +574 -0
- airelays-0.2.0/src/airelay/config.py +396 -0
- airelays-0.2.0/src/airelay/html.py +252 -0
- airelays-0.2.0/src/airelay/security.py +314 -0
- airelays-0.2.0/src/airelay/store.py +243 -0
- airelays-0.2.0/src/airelay/terminal.py +47 -0
- airelays-0.2.0/src/airelay/traffic.py +108 -0
- airelays-0.2.0/src/airelay/transforms.py +981 -0
- airelays-0.2.0/tests/conftest.py +10 -0
- airelays-0.2.0/tests/test_auth_and_cli.py +305 -0
- airelays-0.2.0/tests/test_auth_login.py +134 -0
- airelays-0.2.0/tests/test_backend_and_app.py +594 -0
- airelays-0.2.0/tests/test_config.py +80 -0
- airelays-0.2.0/tests/test_transforms.py +556 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main", "master"]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12"]
|
|
15
|
+
steps:
|
|
16
|
+
- name: Check out repository
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install package and test dependencies
|
|
25
|
+
run: python -m pip install --upgrade pip && python -m pip install -e .[dev]
|
|
26
|
+
|
|
27
|
+
- name: Run tests
|
|
28
|
+
run: pytest -q
|
|
29
|
+
|
|
30
|
+
- name: Byte-compile source and tests
|
|
31
|
+
run: python -m compileall src tests
|
|
32
|
+
|
|
33
|
+
- name: Build distribution artifacts
|
|
34
|
+
run: python -m build
|
|
35
|
+
|
|
36
|
+
- name: Check distribution metadata
|
|
37
|
+
run: python -m twine check dist/*
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Publish PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- "v*"
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
publish:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
contents: read
|
|
15
|
+
environment:
|
|
16
|
+
name: pypi
|
|
17
|
+
steps:
|
|
18
|
+
- name: Check out repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
|
|
26
|
+
- name: Verify tag matches project version
|
|
27
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
28
|
+
run: |
|
|
29
|
+
python - <<'PY'
|
|
30
|
+
import os
|
|
31
|
+
import pathlib
|
|
32
|
+
import tomllib
|
|
33
|
+
|
|
34
|
+
payload = tomllib.loads(pathlib.Path("pyproject.toml").read_text(encoding="utf-8"))
|
|
35
|
+
version = payload["project"]["version"]
|
|
36
|
+
tag = os.environ["GITHUB_REF_NAME"]
|
|
37
|
+
expected = f"v{version}"
|
|
38
|
+
if tag != expected:
|
|
39
|
+
raise SystemExit(f"Tag {tag!r} does not match project version {expected!r}.")
|
|
40
|
+
PY
|
|
41
|
+
|
|
42
|
+
- name: Install project and build tooling
|
|
43
|
+
run: python -m pip install --upgrade pip build twine -e .[dev]
|
|
44
|
+
|
|
45
|
+
- name: Run test suite
|
|
46
|
+
run: pytest -q
|
|
47
|
+
|
|
48
|
+
- name: Compile sources
|
|
49
|
+
run: python -m compileall src tests
|
|
50
|
+
|
|
51
|
+
- name: Build distribution artifacts
|
|
52
|
+
run: python -m build
|
|
53
|
+
|
|
54
|
+
- name: Verify distribution metadata
|
|
55
|
+
run: python -m twine check dist/*
|
|
56
|
+
|
|
57
|
+
- name: Publish to PyPI
|
|
58
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Acknowledgements
|
|
2
|
+
|
|
3
|
+
- The public Codex CLI repository informed the compatible login and auth-storage model reused here.
|
|
4
|
+
- The observed subscription-backend behavior defined the current compatibility boundary.
|
|
5
|
+
- AIRelay is an independent third-party project. Provider and product names are used only to describe compatibility and upstream behavior.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
- Renamed the project surface to `AIRelay`, with package name `airelay` and CLI command `airelay`.
|
|
6
|
+
- Added `airelay init`, `airelay status`, and `airelay token rotate` to make first-run setup and local token management explicit.
|
|
7
|
+
- Added a local config file at `~/.config/airelay/config.toml` with `AIRELAY_*` overrides and legacy `OPENAI_ENDPOINT_*` fallback support.
|
|
8
|
+
- Added default bearer-token protection for `/v1/*` and `/no-tools/v1/*`.
|
|
9
|
+
- Added in-memory per-IP request rate limits, concurrent-request caps, and temporary blocks after repeated invalid tokens.
|
|
10
|
+
- Added protected `GET /v1/relay/status` diagnostics and reduced public `GET /healthz` to a minimal liveness payload.
|
|
11
|
+
- Added bounded local upload limits with explicit `413` failures instead of unbounded buffering.
|
|
12
|
+
- Made bearer-token bootstrap explicit by default: `airelay init` creates the token, while `airelay serve` fails fast if bearer auth is enabled and no token is configured.
|
|
13
|
+
- Clarified relay-token setup and client usage in the CLI output, startup banner, and user documentation.
|
|
14
|
+
- Corrected auth readiness so API-key-only state is not reported as request-ready.
|
|
15
|
+
- Moved upstream auth storage to AIRelay-owned state instead of reusing Codex-owned auth storage.
|
|
16
|
+
- Removed `codex_home` from the public AIRelay configuration surface.
|
|
17
|
+
- Added structured security events to the JSONL traffic log.
|
|
18
|
+
- Updated the landing page, docs, and API guidance to use the AIRelay token as the client API key.
|
|
19
|
+
- Added GitHub Actions workflows for CI and PyPI publishing preparation.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Code Of Conduct
|
|
2
|
+
|
|
3
|
+
This project expects direct, respectful, and technically grounded collaboration.
|
|
4
|
+
|
|
5
|
+
Participants should:
|
|
6
|
+
|
|
7
|
+
- focus on evidence and reproducible behavior
|
|
8
|
+
- avoid harassment, intimidation, and personal attacks
|
|
9
|
+
- assume good faith while still challenging weak technical claims directly
|
|
10
|
+
- keep security-sensitive details out of public discussion when responsible disclosure is warranted
|
|
11
|
+
|
|
12
|
+
Maintainers may remove content or participation that undermines a safe and productive collaboration environment.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Development Setup
|
|
4
|
+
|
|
5
|
+
Contributor setup from a local checkout:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
python -m pip install -e .[dev]
|
|
9
|
+
pytest -q
|
|
10
|
+
python -m compileall src tests
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Project Rules
|
|
14
|
+
|
|
15
|
+
- preserve the explicit compatibility boundary
|
|
16
|
+
- do not silently widen support claims
|
|
17
|
+
- do not add truncation or hidden coercion for files, modalities, or token accounting
|
|
18
|
+
- prefer explicit errors over compatibility theater
|
|
19
|
+
- keep AIRelay auth storage independent from Codex or any other external tool state
|
|
20
|
+
|
|
21
|
+
## Pull Request Expectations
|
|
22
|
+
|
|
23
|
+
- include tests for behavioral changes
|
|
24
|
+
- update docs when API behavior changes
|
|
25
|
+
- update ADRs when a durable engineering rule changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Disclaimer
|
|
2
|
+
|
|
3
|
+
AIRelay is an independent third-party project. It is not affiliated with, endorsed by, or sponsored by OpenAI or any other model provider.
|
|
4
|
+
|
|
5
|
+
Provider and product names are used only to describe compatibility targets, client shapes, and upstream protocol behavior.
|
|
6
|
+
|
|
7
|
+
AIRelay is designed for a single user operating a local relay for personal convenience. It is not presented as a shared, pooled, multi-user, or resale service.
|
|
8
|
+
|
|
9
|
+
You are responsible for reviewing and complying with the terms, policies, and usage limits that apply to any upstream account or subscription you use with AIRelay.
|
airelays-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Laurent-Philippe Albou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
airelays-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: airelays
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: AIRelay: an independent OpenAI-compatible local relay for single-user subscription-backed access.
|
|
5
|
+
Author: Laurent-Philippe Albou
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: ai,gateway,openai-compatible,relay,subscription
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Framework :: FastAPI
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Requires-Dist: fastapi>=0.115.0
|
|
19
|
+
Requires-Dist: httpx>=0.28.0
|
|
20
|
+
Requires-Dist: keyring>=25.5.0
|
|
21
|
+
Requires-Dist: python-multipart>=0.0.20
|
|
22
|
+
Requires-Dist: uvicorn>=0.35.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build>=1.2.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: twine>=6.1.0; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# AIRelay
|
|
31
|
+
|
|
32
|
+
`AIRelay` is an independent local OpenAI-compatible HTTP server backed by a ChatGPT subscription login that AIRelay stores independently. It exposes the verified OpenAI-shaped routes this upstream can support, protects the local relay with its own bearer token, and logs every transit to hourly JSONL files.
|
|
33
|
+
|
|
34
|
+
`AIRelay` does not require a user-supplied OpenAI platform API key for upstream inference. Instead, it uses the same upstream ChatGPT login protocol that Codex uses while keeping AIRelay auth storage separate from Codex storage. Clients that call `AIRelay` should use the relay bearer token as the local client credential they present to AIRelay.
|
|
35
|
+
|
|
36
|
+
## Independence And Intended Use
|
|
37
|
+
|
|
38
|
+
- AIRelay is an independent third-party project. It is not affiliated with, endorsed by, or sponsored by OpenAI.
|
|
39
|
+
- Provider and product names are used only to describe compatibility targets and upstream behavior.
|
|
40
|
+
- AIRelay is designed for a single user running a local relay for personal convenience.
|
|
41
|
+
- AIRelay is not presented as a shared, pooled, multi-user, or resale service.
|
|
42
|
+
- You are responsible for complying with the terms and usage policies that apply to any upstream account or subscription you use with AIRelay.
|
|
43
|
+
|
|
44
|
+
See [DISCLAIMER.md](DISCLAIMER.md) for the short project notice.
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python -m pip install .
|
|
50
|
+
airelay init
|
|
51
|
+
airelay login
|
|
52
|
+
airelay serve --port 8080
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If you are installing from a published package instead of a source checkout, use `python -m pip install airelay`.
|
|
56
|
+
|
|
57
|
+
Smoke test the public and protected surfaces:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
curl http://127.0.0.1:8080/healthz
|
|
61
|
+
curl http://127.0.0.1:8080/v1/relay/status \
|
|
62
|
+
-H 'authorization: Bearer YOUR_AIRELAY_TOKEN'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Inspect the resolved relay and upstream-auth state at any point:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
airelay status
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
CLI status and setup commands default to readable terminal output. Use `--json` on `airelay init`, `airelay status`, `airelay logout`, `airelay token show`, or `airelay token rotate` when you need machine-readable output for automation.
|
|
72
|
+
|
|
73
|
+
Point your client at:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
http://127.0.0.1:8080/v1
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use the token generated by `airelay init` as the client credential when you point an OpenAI-compatible SDK at AIRelay. Standard OpenAI SDKs will then send `Authorization: Bearer <relay-token>` automatically.
|
|
80
|
+
|
|
81
|
+
If you want to provide the relay token yourself instead of using the default token file, launch the server with:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
AIRELAY_BEARER_TOKEN='YOUR_AIRELAY_TOKEN' airelay serve --port 8080
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
or point AIRelay at a specific token file:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
airelay serve --bearer-token-file /path/to/relay-token --port 8080
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## What AIRelay Does
|
|
94
|
+
|
|
95
|
+
- Uses the same upstream login protocol as Codex browser login and device-code login.
|
|
96
|
+
- Stores upstream auth under AIRelay-owned state instead of reusing `~/.codex`.
|
|
97
|
+
- Generates and persists a separate relay bearer token for client-to-relay access.
|
|
98
|
+
- Protects `/v1/*` and `/no-tools/v1/*` with bearer auth, per-IP rate limits, concurrent-request caps, and temporary blocks after repeated bad tokens.
|
|
99
|
+
- Exposes OpenAI-compatible routes for:
|
|
100
|
+
- `GET /v1/models`
|
|
101
|
+
- `GET /v1/subscription/status`
|
|
102
|
+
- `GET /v1/account/rate_limits`
|
|
103
|
+
- `POST /v1/completions`
|
|
104
|
+
- `POST /v1/responses`
|
|
105
|
+
- `POST /v1/chat/completions`
|
|
106
|
+
- `POST /v1/files`
|
|
107
|
+
- `GET /v1/files`
|
|
108
|
+
- `GET /v1/files/{file_id}`
|
|
109
|
+
- `GET /v1/files/{file_id}/content`
|
|
110
|
+
- `DELETE /v1/files/{file_id}`
|
|
111
|
+
- `POST /v1/conversations`
|
|
112
|
+
- `GET /v1/conversations/{conversation_id}`
|
|
113
|
+
- `POST /v1/conversations/{conversation_id}`
|
|
114
|
+
- `DELETE /v1/conversations/{conversation_id}`
|
|
115
|
+
- `/no-tools/v1/models`
|
|
116
|
+
- `/no-tools/v1/completions`
|
|
117
|
+
- `/no-tools/v1/responses`
|
|
118
|
+
- `/no-tools/v1/chat/completions`
|
|
119
|
+
- Logs inbound requests, endpoint rejects, outbound responses, upstream requests, upstream responses, stream lines, and usage summaries to `logs/YYYY/MM/DD-HH.log`.
|
|
120
|
+
|
|
121
|
+
## First-Run Flow
|
|
122
|
+
|
|
123
|
+
1. `airelay init`
|
|
124
|
+
- writes `~/.config/airelay/config.toml` if it does not already exist
|
|
125
|
+
- creates `~/.airelay/relay-token` with `0600` permissions if a relay token is missing
|
|
126
|
+
- prints a formatted setup summary and reveals the token only when it was newly created
|
|
127
|
+
2. `airelay login`
|
|
128
|
+
- creates an AIRelay-owned ChatGPT subscription session
|
|
129
|
+
3. `airelay serve --port 8080`
|
|
130
|
+
- starts the protected local endpoint
|
|
131
|
+
- fails fast if bearer auth is enabled but no relay token is configured
|
|
132
|
+
- prints the client base URL, token file path, and the required `Authorization` header shape
|
|
133
|
+
|
|
134
|
+
You can show the current relay token at any time:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
airelay token show
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
You can also rotate the relay token later:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
airelay token rotate
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Example Client Usage
|
|
147
|
+
|
|
148
|
+
Python with the OpenAI SDK:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from openai import OpenAI
|
|
152
|
+
|
|
153
|
+
client = OpenAI(
|
|
154
|
+
base_url="http://127.0.0.1:8080/v1",
|
|
155
|
+
api_key="YOUR_AIRELAY_TOKEN",
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
response = client.responses.create(
|
|
159
|
+
model="gpt-5.4-mini",
|
|
160
|
+
input="Summarize the purpose of AIRelay.",
|
|
161
|
+
)
|
|
162
|
+
print(response.output_text)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Raw `curl`:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
curl http://127.0.0.1:8080/v1/responses \
|
|
169
|
+
-H 'authorization: Bearer YOUR_AIRELAY_TOKEN' \
|
|
170
|
+
-H 'content-type: application/json' \
|
|
171
|
+
-d '{
|
|
172
|
+
"model": "gpt-5.4-mini",
|
|
173
|
+
"input": "Summarize the purpose of AIRelay.",
|
|
174
|
+
"stream": false
|
|
175
|
+
}'
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Shell example with the OpenAI Python SDK environment variables:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
export OPENAI_BASE_URL='http://127.0.0.1:8080/v1'
|
|
182
|
+
export OPENAI_API_KEY="$(tr -d '\n' < ~/.airelay/relay-token)"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Verified Compatibility Boundary
|
|
186
|
+
|
|
187
|
+
This server is intentionally explicit about what is and is not verified.
|
|
188
|
+
|
|
189
|
+
- Inference uses `https://chatgpt.com/backend-api/codex`.
|
|
190
|
+
- Subscription status uses `https://chatgpt.com/backend-api/wham/usage`.
|
|
191
|
+
- The upstream requires `stream=true`, so non-stream OpenAI responses are reconstructed locally from streamed event sequences.
|
|
192
|
+
- The upstream requires `store=false`, so requests that try to enable upstream storage are rejected with `422`.
|
|
193
|
+
- The upstream requires non-empty `instructions`, so the compatibility layer injects the minimal verified placeholder `"."` only when the caller omitted instructions entirely.
|
|
194
|
+
- Image input is supported.
|
|
195
|
+
- Text and JSON-like document input is supported by local inlining up to 1 MB.
|
|
196
|
+
- Local file uploads are capped at 32 MiB each and 256 MiB total by default.
|
|
197
|
+
- Audio input, embeddings, image generation, realtime sessions, and other unverified routes return explicit `501 unsupported_error`.
|
|
198
|
+
|
|
199
|
+
## Security Defaults
|
|
200
|
+
|
|
201
|
+
- Listener default: `127.0.0.1:8080`
|
|
202
|
+
- Protected routes: `/v1/*` and `/no-tools/v1/*`
|
|
203
|
+
- Public routes: `/` and a minimal `GET /healthz`
|
|
204
|
+
- Protected diagnostics: `GET /v1/relay/status`
|
|
205
|
+
- Relay auth: bearer token required by default
|
|
206
|
+
- Token storage: `~/.airelay/relay-token`
|
|
207
|
+
- Default rate limit: `120` requests/minute with burst `40`
|
|
208
|
+
- Default concurrent request cap: `8` per IP
|
|
209
|
+
- Default repeated-auth-failure block: `8` bad attempts in `300` seconds -> `900` second block
|
|
210
|
+
|
|
211
|
+
See [Security](docs/security.md) for the full behavior.
|
|
212
|
+
|
|
213
|
+
## Configuration
|
|
214
|
+
|
|
215
|
+
AIRelay reads configuration in this order:
|
|
216
|
+
|
|
217
|
+
1. explicit CLI flags such as `--config`, `--port`, or `--auth-storage`
|
|
218
|
+
2. `AIRELAY_*` environment variables
|
|
219
|
+
3. legacy `OPENAI_ENDPOINT_*` environment variables where supported as a migration fallback
|
|
220
|
+
4. `~/.config/airelay/config.toml`
|
|
221
|
+
5. built-in defaults
|
|
222
|
+
|
|
223
|
+
`auth.storage = "auto"` prefers the AIRelay keyring namespace and falls back to `~/.airelay/auth.json` when keyring access is unavailable.
|
|
224
|
+
|
|
225
|
+
Important paths:
|
|
226
|
+
|
|
227
|
+
- config: `~/.config/airelay/config.toml`
|
|
228
|
+
- data dir: `~/.airelay`
|
|
229
|
+
- upstream auth fallback file: `~/.airelay/auth.json`
|
|
230
|
+
- logs: `~/.airelay/logs`
|
|
231
|
+
- relay token: `~/.airelay/relay-token`
|
|
232
|
+
|
|
233
|
+
To override the default token source at launch time:
|
|
234
|
+
|
|
235
|
+
- `AIRELAY_BEARER_TOKEN`
|
|
236
|
+
- `airelay serve --bearer-token-file /path/to/relay-token`
|
|
237
|
+
|
|
238
|
+
See [Configuration](docs/configuration.md) for field details and a sample config.
|
|
239
|
+
|
|
240
|
+
## Publication Surface
|
|
241
|
+
|
|
242
|
+
- package name: `airelay`
|
|
243
|
+
- CLI command: `airelay`
|
|
244
|
+
- legacy CLI alias kept for migration: `openai-endpoint`
|
|
245
|
+
- Python package: `airelay`
|
|
246
|
+
|
|
247
|
+
## Documentation
|
|
248
|
+
|
|
249
|
+
- [Getting Started](docs/getting-started.md)
|
|
250
|
+
- [Configuration](docs/configuration.md)
|
|
251
|
+
- [Security](docs/security.md)
|
|
252
|
+
- [Disclaimer](DISCLAIMER.md)
|
|
253
|
+
- [API Notes](docs/api.md)
|
|
254
|
+
- [Architecture](docs/architecture.md)
|
|
255
|
+
- [Subscription Status](docs/subscription-status.md)
|
|
256
|
+
- [FAQ](docs/faq.md)
|
|
257
|
+
- [Troubleshooting](docs/troubleshooting.md)
|
|
258
|
+
- [ADR Index](docs/adr/README.md)
|