codai-sdk 0.1.0__tar.gz → 0.3.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.
- codai_sdk-0.3.0/CHANGELOG.md +92 -0
- codai_sdk-0.3.0/PKG-INFO +158 -0
- codai_sdk-0.3.0/README.md +134 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/pyproject.toml +11 -4
- codai_sdk-0.3.0/scripts/gen-types.py +326 -0
- codai_sdk-0.3.0/scripts/smoke_local.py +141 -0
- codai_sdk-0.3.0/src/codai/__init__.py +315 -0
- codai_sdk-0.3.0/src/codai/_http.py +393 -0
- codai_sdk-0.3.0/src/codai/_operations.py +135 -0
- codai_sdk-0.3.0/src/codai/_types.py +3116 -0
- codai_sdk-0.3.0/src/codai/resources/__init__.py +92 -0
- codai_sdk-0.3.0/src/codai/resources/_base.py +32 -0
- codai_sdk-0.3.0/src/codai/resources/agents.py +73 -0
- codai_sdk-0.3.0/src/codai/resources/chat.py +165 -0
- codai_sdk-0.3.0/src/codai/resources/core.py +209 -0
- codai_sdk-0.3.0/src/codai/resources/environments.py +183 -0
- codai_sdk-0.3.0/src/codai/resources/messages.py +126 -0
- codai_sdk-0.3.0/src/codai/resources/platform.py +199 -0
- codai_sdk-0.3.0/src/codai/resources/responses.py +100 -0
- codai_sdk-0.3.0/src/codai/resources/sessions.py +151 -0
- codai_sdk-0.3.0/src/codai/resources/triggers.py +107 -0
- codai_sdk-0.3.0/tests/conftest.py +148 -0
- codai_sdk-0.3.0/tests/test_http.py +163 -0
- codai_sdk-0.3.0/tests/test_parity.py +121 -0
- codai_sdk-0.3.0/tests/test_resources.py +331 -0
- codai_sdk-0.1.0/CHANGELOG.md +0 -23
- codai_sdk-0.1.0/PKG-INFO +0 -69
- codai_sdk-0.1.0/README.md +0 -48
- codai_sdk-0.1.0/src/codai/__init__.py +0 -338
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/.github/dependabot.yml +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/.github/pull_request_template.md +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/.github/workflows/publish.yml +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/.gitignore +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/CODE_OF_CONDUCT.md +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/CONTRIBUTING.md +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/LICENSE +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/SECURITY.md +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/examples/agent.py +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/examples/chat.py +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/examples/feedback.py +0 -0
- {codai_sdk-0.1.0 → codai_sdk-0.3.0}/examples/streaming.py +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `codai-sdk` are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.3.0] - 2026-09-25
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Projects + environments resources (26 operations), restoring full parity with the gateway
|
|
14
|
+
OpenAPI (88 operations): `projects.{list,create,get,update,delete}`,
|
|
15
|
+
`environments.{list,create,enroll,get,update,start,stop,archive,destroy,enroll_token}`,
|
|
16
|
+
`environments.members.{list,add,set_ssh_key,set_role,remove}`,
|
|
17
|
+
`environments.ports.{list,set,remove}` and `environments.secrets.{list,set,remove}`.
|
|
18
|
+
`enroll`, `create` and `enroll_token` are never retried (the enrolment token is single-use).
|
|
19
|
+
- `_types.py` regenerated: `Project*` and `Environment*` TypedDicts.
|
|
20
|
+
- `system_one.create({"state", "questions"})` — typed decisions from codai-s1 (`POST /v1/systemone`,
|
|
21
|
+
Choice / Score / Noul with calibrated probabilities). Raises on 503 `s1_unavailable`; keep a fallback.
|
|
22
|
+
- `triggers.*`, `notifications.*`, `environments.members.ssh_cert`, `environments.ssh_ca`,
|
|
23
|
+
`environments.tasks.{list,create,get}` — parity with the TypeScript SDK.
|
|
24
|
+
|
|
25
|
+
## [0.2.1] - 2026-09-24
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- `WalletLedgerEntry.source` literal gains `compute_charge` — the debit written every 10 minutes
|
|
30
|
+
for a running managed cloud environment (F2). Additive; regenerated from the gateway OpenAPI.
|
|
31
|
+
|
|
32
|
+
## [0.2.0] - 2026-09-23
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- Full gateway coverage: one method per `operationId` in `apps/docs/openapi/en/gateway.yaml`
|
|
37
|
+
(62 operations), grouped like the TypeScript SDK — `client.chat.completions`, `messages`,
|
|
38
|
+
`responses`, `embeddings`, `audio`, `tokens`, `models`, `health`, `agents` (+ `agents.runs`),
|
|
39
|
+
`tools`, `tasks`, `sessions` (+ `events`, `controls`, `lease`, `shares`), `devices`, `hosts`,
|
|
40
|
+
`orgs` (+ `members`), `account`, `receipt`, `feedback`, `phone_models`.
|
|
41
|
+
- `OPERATION_METHODS` (operationId → dotted method path) and `tests/test_parity.py`, which
|
|
42
|
+
parses the OpenAPI spec and fails on a missing, stale or non-callable mapping and when the
|
|
43
|
+
Python table diverges from the TypeScript one.
|
|
44
|
+
- Generated `codai._types` (`TypedDict`s for every schema plus `<operationId>Body` /
|
|
45
|
+
`<operationId>Response`) from `scripts/gen-types.py`; the parity test fails when it is stale.
|
|
46
|
+
- SSE streams: `chat.completions.stream()` / `messages.stream()` / `responses.stream()` return
|
|
47
|
+
iterables with `.text()`, raw chunks/events and a `.final` aggregate (content, tool calls,
|
|
48
|
+
usage, finish reason, routing headers); `agents.runs.stream()`, `sessions.stream()` and
|
|
49
|
+
`hosts.stream()` are generators of `{"event", "data"}` frames.
|
|
50
|
+
- `ext={...}` extension bag on every method covering all documented `X-Codai-*` request
|
|
51
|
+
headers (`effort`, `thinking`, `thinking_budget`, `cache`, `no_task`, `task_id`, `device`,
|
|
52
|
+
`compact`, `best_of`, `share_token`, …) plus raw `headers`; client-wide `defaults`, `device`,
|
|
53
|
+
`device_name`, `device_platform`, `client` constructor options.
|
|
54
|
+
- `CodaiError.code`, `.request_id`, `.retry_after` parsed from the gateway error envelope.
|
|
55
|
+
- Dev extras `pip install -e ".[dev]"` (pyyaml + pytest); an `http.server` stub test suite.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- `__version__` now reports the real version (`0.2.0`; it said `0.1.0` in 0.1.1).
|
|
60
|
+
- `chat_stream()` is built on `chat.completions.stream()`; 429/5xx retries add jitter.
|
|
61
|
+
- Runtime stays zero-dependency (stdlib `urllib`), Python 3.9+.
|
|
62
|
+
|
|
63
|
+
### Backward compatibility
|
|
64
|
+
|
|
65
|
+
- Every 0.1.x method keeps its name, signature and return shape: `chat()`, `chat_stream()`,
|
|
66
|
+
`agents_run()`, `feedback()`, `models()`, `mint_token()`, `embeddings()`, `transcribe()`,
|
|
67
|
+
`speech()`. `chat`, `embeddings`, `models` and `feedback` are callable resource groups, so
|
|
68
|
+
`client.chat([...])` and `client.chat.completions.create({...})` are the same call.
|
|
69
|
+
|
|
70
|
+
## [0.1.1] - 2026-09-13
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
|
|
74
|
+
- Repository moved to https://github.com/codai-ro/codai-sdk-python (project URLs updated). No code changes.
|
|
75
|
+
|
|
76
|
+
## [0.1.0] - 2026-06-23
|
|
77
|
+
|
|
78
|
+
### Added
|
|
79
|
+
|
|
80
|
+
- Initial public release.
|
|
81
|
+
- `Codai.chat()` — OpenAI-compatible completions with codai extensions
|
|
82
|
+
(`session_id`, `agent_mode`, `compact`, `best_of`).
|
|
83
|
+
- `Codai.chat_stream()` — streaming via generator.
|
|
84
|
+
- `Codai.agents_run()` — server-side agent loop.
|
|
85
|
+
- `Codai.feedback()` — thumbs rating on a completed request.
|
|
86
|
+
- `Codai.models()` — list models available to the key.
|
|
87
|
+
- Zero dependencies (stdlib only), Python 3.9+.
|
|
88
|
+
|
|
89
|
+
[Unreleased]: https://github.com/codai-ro/codai-sdk-python/compare/v0.2.0...HEAD
|
|
90
|
+
[0.2.0]: https://github.com/codai-ro/codai-sdk-python/compare/v0.1.1...v0.2.0
|
|
91
|
+
[0.1.1]: https://github.com/codai-ro/codai-sdk-python/compare/v0.1.0...v0.1.1
|
|
92
|
+
[0.1.0]: https://github.com/codai-ro/codai-sdk-python/releases/tag/v0.1.0
|
codai_sdk-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: codai-sdk
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Official Python SDK for the codai AI gateway — chat, messages, responses, streaming, agents, sessions, hosts, tasks, account.
|
|
5
|
+
Project-URL: Homepage, https://codai.ro
|
|
6
|
+
Project-URL: Repository, https://github.com/codai-ro/codai-sdk-python
|
|
7
|
+
Project-URL: Issues, https://github.com/codai-ro/codai-sdk-python/issues
|
|
8
|
+
Author-email: codai <support@codai.ro>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,ai,codai,gateway,llm,openai-compatible
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: pyyaml>=6.0; extra == 'dev'
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# codai-sdk — Python SDK
|
|
26
|
+
|
|
27
|
+
[](https://pypi.org/project/codai-sdk/)
|
|
28
|
+
[](https://pypi.org/project/codai-sdk/)
|
|
29
|
+
[](./LICENSE)
|
|
30
|
+
|
|
31
|
+
Official Python client for the [codai](https://codai.ro) AI gateway.
|
|
32
|
+
Zero dependencies (stdlib only), Python 3.9+.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install codai-sdk
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
> You need a codai API key. Get one at **[codai.ro](https://codai.ro)**.
|
|
39
|
+
> The import name stays `codai`:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from codai import Codai
|
|
43
|
+
|
|
44
|
+
client = Codai(api_key="ck-...", session_id="my-project")
|
|
45
|
+
|
|
46
|
+
# Chat (OpenAI-compatible, smart-routed)
|
|
47
|
+
result = client.chat([{"role": "user", "content": "Explain asyncio.gather"}])
|
|
48
|
+
print(result.content)
|
|
49
|
+
print(result.routed_to) # which model actually served
|
|
50
|
+
|
|
51
|
+
# Streaming
|
|
52
|
+
for delta in client.chat_stream([{"role": "user", "content": "hi"}]):
|
|
53
|
+
print(delta, end="", flush=True)
|
|
54
|
+
|
|
55
|
+
# Server-side agent loop
|
|
56
|
+
run = client.agents_run("Find and summarize the TODOs in this codebase")
|
|
57
|
+
print(run.result)
|
|
58
|
+
|
|
59
|
+
# Feedback (improves routing for everyone)
|
|
60
|
+
client.feedback(result.request_id, 1)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## codai extensions
|
|
64
|
+
|
|
65
|
+
| Option | Effect |
|
|
66
|
+
| ----------------- | ------------------------------------ |
|
|
67
|
+
| `session_id` | Session memory + routing stickiness |
|
|
68
|
+
| `agent_mode=True` | Plan-and-execute loop (Pro+) |
|
|
69
|
+
| `compact="auto"` | Server-side context compaction |
|
|
70
|
+
| `best_of=0/3` | Disable / force best-of-N ensembling |
|
|
71
|
+
|
|
72
|
+
## Resource groups (0.2.0)
|
|
73
|
+
|
|
74
|
+
Every gateway operation is a method on the client, grouped exactly like the
|
|
75
|
+
TypeScript SDK (`camelCase` → `snake_case`). The 0.1.x helpers above still
|
|
76
|
+
work — `client.chat([...])` and `client.chat.completions.create({...})` are
|
|
77
|
+
the same call. Every method takes an optional `ext={...}` bag of `X-Codai-*`
|
|
78
|
+
headers (`effort`, `thinking`, `thinking_budget`, `cache`, `no_task`,
|
|
79
|
+
`task_id`, `device`, `compact`, `best_of`, `share_token`, … plus raw `headers`).
|
|
80
|
+
|
|
81
|
+
| Attribute | Methods | Gateway |
|
|
82
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
|
|
83
|
+
| `chat.completions` | `create`, `stream` | `POST /v1/chat/completions` |
|
|
84
|
+
| `messages` | `create`, `stream` | `POST /v1/messages` (Anthropic wire) |
|
|
85
|
+
| `responses` | `create`, `stream` | `POST /v1/responses` (OpenAI Responses wire) |
|
|
86
|
+
| `embeddings` | `create` | `POST /v1/embeddings` |
|
|
87
|
+
| `audio` | `transcribe`, `transcribe_detailed`, `speech`, `speech_detailed` | `/v1/audio/*` |
|
|
88
|
+
| `tokens` | `create` | `POST /v1/tokens` |
|
|
89
|
+
| `models` | `list` | `GET /v1/models` |
|
|
90
|
+
| `health` | `get`, `ready`, `status` | `/health`, `/health/ready`, `/status` |
|
|
91
|
+
| `agents` | `run`; `runs.create/get/steps/stats/cancel/stream` | `/v1/agents/*` |
|
|
92
|
+
| `tools` | `search`, `fetch` | `/v1/tools/*` |
|
|
93
|
+
| `tasks` | `list`, `pending`, `stats`, `get`, `confirm` | `/v1/tasks/*` |
|
|
94
|
+
| `sessions` | `create`, `list`, `get`, `update`, `delete`, `dispatch`, `stream`; `events.*`, `controls.*`, `lease.*`, `shares.*` | `/v1/sessions/*` |
|
|
95
|
+
| `devices` | `list`, `update`, `delete`, `dispatch_inbox` | `/v1/devices/*` |
|
|
96
|
+
| `hosts` | `list`, `exec`, `post_result`, `stream` | `/v1/hosts/*` |
|
|
97
|
+
| `orgs` | `create`, `list`; `members.list/add/remove` | `/v1/orgs/*` |
|
|
98
|
+
| `account` | `get`, `update` | `/v1/account` |
|
|
99
|
+
| `receipt` | `get` | `GET /v1/receipt` |
|
|
100
|
+
| `feedback` | `submit` | `POST /v1/feedback` |
|
|
101
|
+
| `phone_models` | `list` | `GET /v1/phone/models` |
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from codai import Codai, CodaiError
|
|
105
|
+
|
|
106
|
+
client = Codai(api_key="codai_...", device="5dc0de00-0000-4000-8000-00000000c0da")
|
|
107
|
+
|
|
108
|
+
# Chat with extension headers; raw chunks + aggregate on streams
|
|
109
|
+
r = client.chat.completions.create(
|
|
110
|
+
{"model": "codai", "messages": [{"role": "user", "content": "hi"}]},
|
|
111
|
+
ext={"effort": "high", "thinking": True, "thinking_budget": 8192},
|
|
112
|
+
)
|
|
113
|
+
print(r.content, r.routed_to, r.usage)
|
|
114
|
+
|
|
115
|
+
stream = client.chat.completions.stream({"messages": [{"role": "user", "content": "hi"}]})
|
|
116
|
+
for delta in stream: # text deltas; stream.chunks() for raw chunk dicts
|
|
117
|
+
print(delta, end="")
|
|
118
|
+
print(stream.final.usage, stream.final.tool_calls)
|
|
119
|
+
|
|
120
|
+
# Anthropic / OpenAI Responses wires
|
|
121
|
+
client.messages.create({"messages": [{"role": "user", "content": "hi"}], "max_tokens": 200}).text
|
|
122
|
+
client.responses.create({"input": "hi"}).output_text
|
|
123
|
+
|
|
124
|
+
# Async agent run + SSE progress
|
|
125
|
+
run = client.agents.runs.create({"task": "Summarise the repo README."})
|
|
126
|
+
for ev in client.agents.runs.stream(run["id"]):
|
|
127
|
+
if ev["event"] == "done":
|
|
128
|
+
print(ev["data"]["status"], ev["data"]["result"])
|
|
129
|
+
|
|
130
|
+
# Tasks, account, receipt
|
|
131
|
+
page = client.tasks.list(limit=20)
|
|
132
|
+
print(client.account.get()["plan"], client.receipt.get(since="2026-09-01T00:00:00Z"))
|
|
133
|
+
|
|
134
|
+
# Shared sessions (needs a device id on the client) and hosts
|
|
135
|
+
s = client.sessions.create({"title": "pairing"})
|
|
136
|
+
for ev in client.sessions.stream(s["id"], after=0):
|
|
137
|
+
print(ev["event"], ev["data"].get("seq"))
|
|
138
|
+
print(client.hosts.list())
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
client.orgs.members.add("org-1", {"user_id": "u", "role": "member"})
|
|
142
|
+
except CodaiError as e:
|
|
143
|
+
print(e.status, e.code, e.request_id, e.retry_after)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Typed request/response shapes live in `codai._types` (generated from the
|
|
147
|
+
OpenAPI spec — `TypedDict`s such as `ChatCompletionRequest`, `Task`,
|
|
148
|
+
`SessionEvent`, `CreateSessionShareResponse`).
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
python -m venv .venv && .venv/Scripts/python -m pip install -e ".[dev]"
|
|
154
|
+
.venv/Scripts/python -m pytest -q # unit + OpenAPI parity tests, no network
|
|
155
|
+
.venv/Scripts/python scripts/gen-types.py # regenerate src/codai/_types.py
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
MIT © codai
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# codai-sdk — Python SDK
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/codai-sdk/)
|
|
4
|
+
[](https://pypi.org/project/codai-sdk/)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
Official Python client for the [codai](https://codai.ro) AI gateway.
|
|
8
|
+
Zero dependencies (stdlib only), Python 3.9+.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install codai-sdk
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
> You need a codai API key. Get one at **[codai.ro](https://codai.ro)**.
|
|
15
|
+
> The import name stays `codai`:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from codai import Codai
|
|
19
|
+
|
|
20
|
+
client = Codai(api_key="ck-...", session_id="my-project")
|
|
21
|
+
|
|
22
|
+
# Chat (OpenAI-compatible, smart-routed)
|
|
23
|
+
result = client.chat([{"role": "user", "content": "Explain asyncio.gather"}])
|
|
24
|
+
print(result.content)
|
|
25
|
+
print(result.routed_to) # which model actually served
|
|
26
|
+
|
|
27
|
+
# Streaming
|
|
28
|
+
for delta in client.chat_stream([{"role": "user", "content": "hi"}]):
|
|
29
|
+
print(delta, end="", flush=True)
|
|
30
|
+
|
|
31
|
+
# Server-side agent loop
|
|
32
|
+
run = client.agents_run("Find and summarize the TODOs in this codebase")
|
|
33
|
+
print(run.result)
|
|
34
|
+
|
|
35
|
+
# Feedback (improves routing for everyone)
|
|
36
|
+
client.feedback(result.request_id, 1)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## codai extensions
|
|
40
|
+
|
|
41
|
+
| Option | Effect |
|
|
42
|
+
| ----------------- | ------------------------------------ |
|
|
43
|
+
| `session_id` | Session memory + routing stickiness |
|
|
44
|
+
| `agent_mode=True` | Plan-and-execute loop (Pro+) |
|
|
45
|
+
| `compact="auto"` | Server-side context compaction |
|
|
46
|
+
| `best_of=0/3` | Disable / force best-of-N ensembling |
|
|
47
|
+
|
|
48
|
+
## Resource groups (0.2.0)
|
|
49
|
+
|
|
50
|
+
Every gateway operation is a method on the client, grouped exactly like the
|
|
51
|
+
TypeScript SDK (`camelCase` → `snake_case`). The 0.1.x helpers above still
|
|
52
|
+
work — `client.chat([...])` and `client.chat.completions.create({...})` are
|
|
53
|
+
the same call. Every method takes an optional `ext={...}` bag of `X-Codai-*`
|
|
54
|
+
headers (`effort`, `thinking`, `thinking_budget`, `cache`, `no_task`,
|
|
55
|
+
`task_id`, `device`, `compact`, `best_of`, `share_token`, … plus raw `headers`).
|
|
56
|
+
|
|
57
|
+
| Attribute | Methods | Gateway |
|
|
58
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
|
|
59
|
+
| `chat.completions` | `create`, `stream` | `POST /v1/chat/completions` |
|
|
60
|
+
| `messages` | `create`, `stream` | `POST /v1/messages` (Anthropic wire) |
|
|
61
|
+
| `responses` | `create`, `stream` | `POST /v1/responses` (OpenAI Responses wire) |
|
|
62
|
+
| `embeddings` | `create` | `POST /v1/embeddings` |
|
|
63
|
+
| `audio` | `transcribe`, `transcribe_detailed`, `speech`, `speech_detailed` | `/v1/audio/*` |
|
|
64
|
+
| `tokens` | `create` | `POST /v1/tokens` |
|
|
65
|
+
| `models` | `list` | `GET /v1/models` |
|
|
66
|
+
| `health` | `get`, `ready`, `status` | `/health`, `/health/ready`, `/status` |
|
|
67
|
+
| `agents` | `run`; `runs.create/get/steps/stats/cancel/stream` | `/v1/agents/*` |
|
|
68
|
+
| `tools` | `search`, `fetch` | `/v1/tools/*` |
|
|
69
|
+
| `tasks` | `list`, `pending`, `stats`, `get`, `confirm` | `/v1/tasks/*` |
|
|
70
|
+
| `sessions` | `create`, `list`, `get`, `update`, `delete`, `dispatch`, `stream`; `events.*`, `controls.*`, `lease.*`, `shares.*` | `/v1/sessions/*` |
|
|
71
|
+
| `devices` | `list`, `update`, `delete`, `dispatch_inbox` | `/v1/devices/*` |
|
|
72
|
+
| `hosts` | `list`, `exec`, `post_result`, `stream` | `/v1/hosts/*` |
|
|
73
|
+
| `orgs` | `create`, `list`; `members.list/add/remove` | `/v1/orgs/*` |
|
|
74
|
+
| `account` | `get`, `update` | `/v1/account` |
|
|
75
|
+
| `receipt` | `get` | `GET /v1/receipt` |
|
|
76
|
+
| `feedback` | `submit` | `POST /v1/feedback` |
|
|
77
|
+
| `phone_models` | `list` | `GET /v1/phone/models` |
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from codai import Codai, CodaiError
|
|
81
|
+
|
|
82
|
+
client = Codai(api_key="codai_...", device="5dc0de00-0000-4000-8000-00000000c0da")
|
|
83
|
+
|
|
84
|
+
# Chat with extension headers; raw chunks + aggregate on streams
|
|
85
|
+
r = client.chat.completions.create(
|
|
86
|
+
{"model": "codai", "messages": [{"role": "user", "content": "hi"}]},
|
|
87
|
+
ext={"effort": "high", "thinking": True, "thinking_budget": 8192},
|
|
88
|
+
)
|
|
89
|
+
print(r.content, r.routed_to, r.usage)
|
|
90
|
+
|
|
91
|
+
stream = client.chat.completions.stream({"messages": [{"role": "user", "content": "hi"}]})
|
|
92
|
+
for delta in stream: # text deltas; stream.chunks() for raw chunk dicts
|
|
93
|
+
print(delta, end="")
|
|
94
|
+
print(stream.final.usage, stream.final.tool_calls)
|
|
95
|
+
|
|
96
|
+
# Anthropic / OpenAI Responses wires
|
|
97
|
+
client.messages.create({"messages": [{"role": "user", "content": "hi"}], "max_tokens": 200}).text
|
|
98
|
+
client.responses.create({"input": "hi"}).output_text
|
|
99
|
+
|
|
100
|
+
# Async agent run + SSE progress
|
|
101
|
+
run = client.agents.runs.create({"task": "Summarise the repo README."})
|
|
102
|
+
for ev in client.agents.runs.stream(run["id"]):
|
|
103
|
+
if ev["event"] == "done":
|
|
104
|
+
print(ev["data"]["status"], ev["data"]["result"])
|
|
105
|
+
|
|
106
|
+
# Tasks, account, receipt
|
|
107
|
+
page = client.tasks.list(limit=20)
|
|
108
|
+
print(client.account.get()["plan"], client.receipt.get(since="2026-09-01T00:00:00Z"))
|
|
109
|
+
|
|
110
|
+
# Shared sessions (needs a device id on the client) and hosts
|
|
111
|
+
s = client.sessions.create({"title": "pairing"})
|
|
112
|
+
for ev in client.sessions.stream(s["id"], after=0):
|
|
113
|
+
print(ev["event"], ev["data"].get("seq"))
|
|
114
|
+
print(client.hosts.list())
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
client.orgs.members.add("org-1", {"user_id": "u", "role": "member"})
|
|
118
|
+
except CodaiError as e:
|
|
119
|
+
print(e.status, e.code, e.request_id, e.retry_after)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Typed request/response shapes live in `codai._types` (generated from the
|
|
123
|
+
OpenAPI spec — `TypedDict`s such as `ChatCompletionRequest`, `Task`,
|
|
124
|
+
`SessionEvent`, `CreateSessionShareResponse`).
|
|
125
|
+
|
|
126
|
+
## Development
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
python -m venv .venv && .venv/Scripts/python -m pip install -e ".[dev]"
|
|
130
|
+
.venv/Scripts/python -m pytest -q # unit + OpenAPI parity tests, no network
|
|
131
|
+
.venv/Scripts/python scripts/gen-types.py # regenerate src/codai/_types.py
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
MIT © codai
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codai-sdk"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "Official Python SDK for the codai AI gateway — chat, streaming, agents,
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Official Python SDK for the codai AI gateway — chat, messages, responses, streaming, agents, sessions, hosts, tasks, account."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
requires-python = ">=3.9"
|
|
@@ -22,10 +22,17 @@ classifiers = [
|
|
|
22
22
|
]
|
|
23
23
|
dependencies = []
|
|
24
24
|
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
dev = ["pyyaml>=6.0", "pytest>=8.0"]
|
|
27
|
+
|
|
25
28
|
[project.urls]
|
|
26
29
|
Homepage = "https://codai.ro"
|
|
27
|
-
Repository = "https://github.com/
|
|
28
|
-
Issues = "https://github.com/
|
|
30
|
+
Repository = "https://github.com/codai-ro/codai-sdk-python"
|
|
31
|
+
Issues = "https://github.com/codai-ro/codai-sdk-python/issues"
|
|
29
32
|
|
|
30
33
|
[tool.hatch.build.targets.wheel]
|
|
31
34
|
packages = ["src/codai"]
|
|
35
|
+
|
|
36
|
+
[tool.pytest.ini_options]
|
|
37
|
+
testpaths = ["tests"]
|
|
38
|
+
pythonpath = ["src"]
|