agentbridge-cli 0.1.11__py3-none-any.whl

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.
@@ -0,0 +1,9 @@
1
+ {% set capacity_available = size - in_use %}
2
+ {% set at_capacity = size > 0 and capacity_available <= 0 %}
3
+ <div class="pool-status">
4
+ <span class="pool-health{% if at_capacity %} error{% endif %}">
5
+ <span class="pool-dot {% if at_capacity %}empty{% else %}available{% endif %}"></span>
6
+ {% if at_capacity %}Busy{% else %}Healthy{% endif %}
7
+ </span>
8
+ <span class="pool-count">{{ [capacity_available, 0]|max }}/{{ size }} capacity</span>
9
+ </div>
@@ -0,0 +1,67 @@
1
+ <h3 class="request-list-title">Requests</h3>
2
+ {% if requests %}
3
+ {% set active_requests = requests|selectattr("is_active")|list %}
4
+ {% set failed_requests = requests|rejectattr("is_active")|selectattr("error")|list %}
5
+ {% set completed_requests = requests|rejectattr("is_active")|rejectattr("error")|list %}
6
+
7
+ {% macro request_row(req) -%}
8
+ <div class="request-row{% if req.is_active %} request-row-active{% endif %}" data-request-id="{{ req.request_id }}" hx-get="/dashboard/request/{{ req.request_id }}" hx-target="#detail" hx-swap="innerHTML">
9
+ <div class="request-main">
10
+ <div class="request-title">
11
+ <span class="status-dot {% if req.is_active %}streaming{% elif req.error %}error{% else %}idle{% endif %}"></span>
12
+ <span class="request-id">{{ req.request_id }}</span>
13
+ {% if req.is_active %}
14
+ <span class="badge badge-active">streaming</span>
15
+ {% elif req.error %}
16
+ <span class="badge badge-err">error</span>
17
+ {% else %}
18
+ <span class="badge badge-ok">ok</span>
19
+ {% endif %}
20
+ </div>
21
+ <div class="request-model">{{ req.model }}</div>
22
+ </div>
23
+ <div class="request-metrics">
24
+ <div>{% if req.is_active %}{{ req.elapsed_s }}s{% else %}{{ req.duration_ms }}ms{% endif %}</div>
25
+ <div>{% if not req.is_active and (req.input_tokens is not none or req.output_tokens is not none) %}{{ (req.input_tokens or 0) + (req.output_tokens or 0) }}t{% else %}-{% endif %}</div>
26
+ </div>
27
+ </div>
28
+ {%- endmacro %}
29
+
30
+ {% if active_requests %}
31
+ <section class="request-group">
32
+ <h4 class="request-group-title">
33
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg>
34
+ Active ({{ active_requests|length }})
35
+ </h4>
36
+ {% for req in active_requests %}
37
+ {{ request_row(req) }}
38
+ {% endfor %}
39
+ </section>
40
+ {% endif %}
41
+
42
+ {% if completed_requests %}
43
+ <section class="request-group">
44
+ <h4 class="request-group-title">
45
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg>
46
+ Completed ({{ completed_requests|length }})
47
+ </h4>
48
+ {% for req in completed_requests %}
49
+ {{ request_row(req) }}
50
+ {% endfor %}
51
+ </section>
52
+ {% endif %}
53
+
54
+ {% if failed_requests %}
55
+ <section class="request-group">
56
+ <h4 class="request-group-title">
57
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg>
58
+ Failed ({{ failed_requests|length }})
59
+ </h4>
60
+ {% for req in failed_requests %}
61
+ {{ request_row(req) }}
62
+ {% endfor %}
63
+ </section>
64
+ {% endif %}
65
+ {% else %}
66
+ <p class="empty-state">No requests</p>
67
+ {% endif %}
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentbridge-cli
3
+ Version: 0.1.11
4
+ Summary: Bridge OpenAI tools to Claude Code SDK, Codex CLI, and OpenRouter
5
+ Project-URL: Homepage, https://github.com/tsilva/agentbridge
6
+ Project-URL: Repository, https://github.com/tsilva/agentbridge
7
+ Project-URL: Issues, https://github.com/tsilva/agentbridge/issues
8
+ Author: tsilva
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: anthropic,api,bridge,claude,claude-code,codex,fastapi,llm,openai,streaming
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Framework :: FastAPI
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: claude-agent-sdk>=0.1.0
21
+ Requires-Dist: fastapi>=0.115.0
22
+ Requires-Dist: jinja2>=3.1.0
23
+ Requires-Dist: openrouter==0.9.1
24
+ Requires-Dist: pillow>=11.2
25
+ Requires-Dist: uvicorn[standard]>=0.32.0
26
+ Provides-Extra: test
27
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
28
+ Requires-Dist: pytest>=8.0.0; extra == 'test'
29
+ Description-Content-Type: text/markdown
30
+
31
+ <div align="center">
32
+ <img src="./logo.png" alt="agentbridge" width="512" />
33
+
34
+ **🌉 Bridge OpenAI tools to Claude Code SDK, Codex CLI, or OpenRouter — use your subscriptions anywhere 🔌**
35
+ </div>
36
+
37
+ agentbridge is a local API bridge for developers who want to connect OpenAI-compatible apps to Claude Code, Codex, or OpenRouter. Run one server, choose a backend with a namespaced model ID, and point existing Chat Completions clients at `http://localhost:8082/api/v1`.
38
+
39
+ It supports streaming and non-streaming responses, image and PDF inputs where the backend accepts them, native Codex image editing, strict JSON Schema output, OpenAI-style tool calls, a live dashboard, and local JSON session logs.
40
+
41
+ > **Legal notice:** agentbridge can use Claude Code SDK and Codex CLI access through your local subscriptions, and can forward requests to OpenRouter when configured. You are responsible for determining whether your use complies with each service's terms. Use it conservatively and at your own risk.
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ uv tool install agentbridge-cli
47
+ agentbridge
48
+ ```
49
+
50
+ If you installed an earlier release under the previous PyPI distribution name,
51
+ migrate once with:
52
+
53
+ ```bash
54
+ uv tool uninstall agentbridge-py
55
+ uv tool install agentbridge-cli
56
+ ```
57
+
58
+ The Python import and executable remain `agentbridge`.
59
+
60
+ Open the [dashboard](http://localhost:8082/dashboard), try the built-in [chat](http://localhost:8082/dashboard/chat), or use `http://localhost:8082/api/v1` as an OpenAI-compatible base URL.
61
+
62
+ Authenticate at least one backend before sending requests:
63
+
64
+ ```bash
65
+ claude login # for claudecode/* models
66
+ codex login # for codex/* models
67
+ ```
68
+
69
+ For OpenRouter, start agentbridge once and add `OPENROUTER_API_KEY` to `~/.config/agentbridge/.env`.
70
+
71
+ To work on the repository itself:
72
+
73
+ ```bash
74
+ git clone https://github.com/tsilva/agentbridge.git
75
+ cd agentbridge
76
+ uv sync --extra test
77
+ uv run agentbridge
78
+ ```
79
+
80
+ ## Usage
81
+
82
+ ```bash
83
+ curl http://localhost:8082/api/v1/chat/completions \
84
+ -H "Content-Type: application/json" \
85
+ -d '{"model":"claudecode/sonnet","messages":[{"role":"user","content":"Hello!"}]}'
86
+ ```
87
+
88
+ Every request requires one of these model namespaces:
89
+
90
+ - `claudecode/<model>` — `opus`, `sonnet`, `haiku`, or a namespaced Claude slug containing one of those names.
91
+ - `codex/<model>` — passed directly to Codex CLI. `gpt-5.6-sol` and `gpt-5.5` default to high reasoning effort unless the request overrides it.
92
+ - `openrouter/<provider>/<model>` — passed to the official OpenRouter Python SDK.
93
+
94
+ OpenAI SDKs may use any placeholder API key:
95
+
96
+ ```python
97
+ from openai import OpenAI
98
+
99
+ client = OpenAI(base_url="http://localhost:8082/api/v1", api_key="not-needed")
100
+ response = client.chat.completions.create(
101
+ model="codex/gpt-5.6-sol",
102
+ reasoning_effort="high",
103
+ messages=[{"role": "user", "content": "Hello from Codex!"}],
104
+ )
105
+ print(response.choices[0].message.content)
106
+ ```
107
+
108
+ Codex can also edit one bounded PNG, JPEG, or WebP reference through the
109
+ purpose-built image route. The request is non-persistent and returns one base64
110
+ raster:
111
+
112
+ ```bash
113
+ curl http://localhost:8082/api/v1/images \
114
+ -H "Content-Type: application/json" \
115
+ -d "{\"model\":\"codex/gpt-5.6-sol\",\"prompt\":\"Make this look like a scanner capture without changing any content.\",\"input_references\":[{\"type\":\"image_url\",\"image_url\":{\"url\":\"data:image/png;base64,$PAGE_DATA\"}}],\"n\":1,\"store\":false}"
116
+ ```
117
+
118
+ `GET /api/v1/capabilities` reports whether the local Codex CLI is available,
119
+ authenticated, and supports the strict image and JSON-schema profiles.
120
+
121
+ ## Commands
122
+
123
+ ```bash
124
+ agentbridge # start on 127.0.0.1:8082
125
+ agentbridge --port 8083 # choose another port
126
+ agentbridge --workers 3 # set Claude pool and Codex concurrency to 3
127
+ agentbridge --version # print package and git version
128
+ uv run --frozen --extra test pytest -q # run tests
129
+ uv run --frozen --extra test ruff check agentbridge tests # lint Python
130
+ uv lock --check # verify the lockfile
131
+ uv build # build wheel and source distribution
132
+ ```
133
+
134
+ ## Notes
135
+
136
+ - Python 3.12+ and at least one authenticated backend are required.
137
+ - Public routes include `POST /api/v1/chat/completions`, `POST /api/v1/images`, `GET /api/v1/models`, `GET /api/v1/capabilities`, `GET /health`, `/dashboard`, and `/dashboard/chat`.
138
+ - `PORT`, `POOL_SIZE`, `CLAUDE_TIMEOUT`, `CODEX_TIMEOUT`, `CODEX_IMAGE_TIMEOUT`, and `OPENROUTER_TIMEOUT` control the server port, pool size, and provider timeouts. `--workers` overrides `POOL_SIZE`; Codex chat and native image generation default to 600-second timeouts, while Claude and OpenRouter default to 120 seconds.
139
+ - `MAX_IMAGE_INPUT_BYTES`, `MAX_IMAGE_OUTPUT_BYTES`, and `MAX_IMAGE_PIXELS` bound native image requests. Defaults are 64 MiB input, 32 MiB output, and 40 million pixels.
140
+ - `AGENTBRIDGE_CONFIG_DIR` moves the user configuration directory. `LOG_DIR` moves session logs, and `MAX_LOG_FILES` limits retained JSON logs.
141
+ - `OPENROUTER_API_KEY`, `OPENROUTER_SITE_URL`, and `OPENROUTER_APP_NAME` configure OpenRouter requests. Process environment variables take precedence over the user `.env` file.
142
+ - Claude clients are created lazily, reused by model, and capped by the worker count. Claude sessions do not load filesystem settings and run with built-in tools disabled.
143
+ - Codex runs one ephemeral `codex exec` process per request in a temporary directory with read-only sandboxing, no approvals, and project rules ignored. Multimodal structured-output calls also ignore user config and disable execution and image-generation tools. Native image calls use the same strict profile, keep execution disabled, and enable the image-generation capability needed for the edit.
144
+ - Claude and Codex function calls are represented through prompted JSON; OpenRouter tool calls pass through its SDK. Session logs and extracted image or PDF attachments are saved under `~/.config/agentbridge/logs/sessions` by default.
145
+ - Set `store: false` on chat requests to suppress session-log artifacts. The native image route requires `store: false`, accepts data URLs only, validates both rasters, locates the result from the structured Codex thread ID, and removes that thread's generated-image directory after the request.
146
+
147
+ ## Publishing
148
+
149
+ Releases use the `Release` GitHub Actions workflow and PyPI Trusted Publishing for the `agentbridge-cli` project. The publisher is scoped to owner `tsilva`, repository `agentbridge`, workflow `release.yml`, and environment `pypi`; no PyPI API token is required. Releases through `0.1.10` remain available under the previous `agentbridge-py` distribution name.
150
+
151
+ ## Architecture
152
+
153
+ ![agentbridge architecture diagram](./architecture.png)
154
+
155
+ ## License
156
+
157
+ [MIT](LICENSE)
@@ -0,0 +1,18 @@
1
+ agentbridge/__init__.py,sha256=n9GlIClgTwfovU-dZJTI7wHhPT7VrYHgBnnoM42grg8,253
2
+ agentbridge/config.py,sha256=9hwXPbXb34Gf4ESyY__VzbfmXlIgC3N2bzpCLQYFULA,2711
3
+ agentbridge/dashboard.py,sha256=lNqRydgiX8nnOrslBX48-JAvg4QioKtOlFGTLjpHD8Y,17483
4
+ agentbridge/models.py,sha256=17_hohGps1uYoIwfeeSHC5bvwSxuYrTi3hgJ_ZvghNE,9215
5
+ agentbridge/pool.py,sha256=KtZ--b1RlT5zm1brP1kgFjpSV3d-Ay85CV38m1vJXHo,12602
6
+ agentbridge/server.py,sha256=6p-t1nVbm3CNVdS5w-JEGCWHPOpUgnMH5lmIB6iqUCw,106493
7
+ agentbridge/templates/dashboard/base.html,sha256=mDmBa7XsYRFRv6otvoethxitTe89qdNYF-k2EbIb2aw,5005
8
+ agentbridge/templates/dashboard/chat.html,sha256=xmgK3y2FD6c3WCWbDLYP6uTdO6G7ZvypHoe4C5JisX0,48224
9
+ agentbridge/templates/dashboard/detail.html,sha256=n2c86asWtuluP9ecncDLbZbDgRr_G35sGJwV10VZE-s,7310
10
+ agentbridge/templates/dashboard/page.html,sha256=KMQtjycFki_6C4g-2s_5FhNDIBX3418tJvw8SrtKBkA,27426
11
+ agentbridge/templates/dashboard/pool.html,sha256=Cj82bQvM-sllWPE8LfzCtUwT8m3De08in9MqcPlTLz4,465
12
+ agentbridge/templates/dashboard/requests.html,sha256=VYNPSb_Vdqkn_7l1zjg_mWAyxhI_W63OK1GQEWeDNII,3038
13
+ agentbridge/_build_info.py,sha256=u78KhLyvgyWjUoCs30k7OxpPsuL-xdvmXoUoRn3hk4Q,21
14
+ agentbridge_cli-0.1.11.dist-info/METADATA,sha256=RSnmYPclW1cUjDTzobWXaz4Om1ULu9j5ooR7YfDfWIA,8076
15
+ agentbridge_cli-0.1.11.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
16
+ agentbridge_cli-0.1.11.dist-info/entry_points.txt,sha256=S1bW9OBjg8rfmiOw6i45uGs_dZnHoKxG4YkB5wb106c,56
17
+ agentbridge_cli-0.1.11.dist-info/licenses/LICENSE,sha256=bep-KRGnKqbtPrVpJlAfWnx2eMzwCcTHxNcT8f2QYGo,1063
18
+ agentbridge_cli-0.1.11.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ agentbridge = agentbridge.server:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tsilva
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.