codai-sdk 0.2.1__tar.gz → 0.4.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.2.1 → codai_sdk-0.4.0}/CHANGELOG.md +33 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/PKG-INFO +28 -1
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/README.md +27 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/pyproject.toml +1 -1
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/scripts/gen-types.py +39 -16
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/__init__.py +31 -2
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/_operations.py +56 -0
- codai_sdk-0.4.0/src/codai/_resolve_types.py +174 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/_types.py +1053 -3
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/__init__.py +24 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/core.py +13 -0
- codai_sdk-0.4.0/src/codai/resources/environments.py +183 -0
- codai_sdk-0.4.0/src/codai/resources/resolve.py +148 -0
- codai_sdk-0.4.0/src/codai/resources/triggers.py +115 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/tests/test_parity.py +4 -3
- codai_sdk-0.4.0/tests/test_resolve.py +95 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/tests/test_resources.py +173 -2
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/.github/dependabot.yml +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/.github/pull_request_template.md +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/.github/workflows/publish.yml +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/.gitignore +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/CONTRIBUTING.md +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/LICENSE +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/SECURITY.md +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/examples/agent.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/examples/chat.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/examples/feedback.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/examples/streaming.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/scripts/smoke_local.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/_http.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/_base.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/agents.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/chat.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/messages.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/platform.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/responses.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/src/codai/resources/sessions.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/tests/conftest.py +0 -0
- {codai_sdk-0.2.1 → codai_sdk-0.4.0}/tests/test_http.py +0 -0
|
@@ -6,6 +6,39 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.4.0] - 2026-09-27
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `client.resolve` — codai Resolve (pay per verified fix, `https://resolve.codai.ro`,
|
|
14
|
+
override with `resolve_base_url=`): `submit`, `get`, `accept`, `attestation`,
|
|
15
|
+
`health`, `wait_for`. `ResolveError` / `ResolveInsufficientFundsError` (402 carries
|
|
16
|
+
`topup_url`, `balance`, `required`). `RESOLVE_OPERATION_METHODS` maps every
|
|
17
|
+
`resolve.yaml` operationId; `_resolve_types.py` is generated from it.
|
|
18
|
+
|
|
19
|
+
## [0.3.1] - 2026-09-26
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Regenerated `_types.py`: project prebuild pool fields, environment `prebuild`
|
|
24
|
+
and `prebuild_claimed` on create (CE-0072).
|
|
25
|
+
|
|
26
|
+
## [0.3.0] - 2026-09-25
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Projects + environments resources (26 operations), restoring full parity with the gateway
|
|
31
|
+
OpenAPI (88 operations): `projects.{list,create,get,update,delete}`,
|
|
32
|
+
`environments.{list,create,enroll,get,update,start,stop,archive,destroy,enroll_token}`,
|
|
33
|
+
`environments.members.{list,add,set_ssh_key,set_role,remove}`,
|
|
34
|
+
`environments.ports.{list,set,remove}` and `environments.secrets.{list,set,remove}`.
|
|
35
|
+
`enroll`, `create` and `enroll_token` are never retried (the enrolment token is single-use).
|
|
36
|
+
- `_types.py` regenerated: `Project*` and `Environment*` TypedDicts.
|
|
37
|
+
- `system_one.create({"state", "questions"})` — typed decisions from codai-s1 (`POST /v1/systemone`,
|
|
38
|
+
Choice / Score / Noul with calibrated probabilities). Raises on 503 `s1_unavailable`; keep a fallback.
|
|
39
|
+
- `triggers.*`, `notifications.*`, `environments.members.ssh_cert`, `environments.ssh_ca`,
|
|
40
|
+
`environments.tasks.{list,create,get}` — parity with the TypeScript SDK.
|
|
41
|
+
|
|
9
42
|
## [0.2.1] - 2026-09-24
|
|
10
43
|
|
|
11
44
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: codai-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Official Python SDK for the codai AI gateway — chat, messages, responses, streaming, agents, sessions, hosts, tasks, account.
|
|
5
5
|
Project-URL: Homepage, https://codai.ro
|
|
6
6
|
Project-URL: Repository, https://github.com/codai-ro/codai-sdk-python
|
|
@@ -147,6 +147,33 @@ Typed request/response shapes live in `codai._types` (generated from the
|
|
|
147
147
|
OpenAPI spec — `TypedDict`s such as `ChatCompletionRequest`, `Task`,
|
|
148
148
|
`SessionEvent`, `CreateSessionShareResponse`).
|
|
149
149
|
|
|
150
|
+
## codai Resolve (0.4.0)
|
|
151
|
+
|
|
152
|
+
Pay per verified fix: submit a public GitHub issue, get a flat quote, accept it
|
|
153
|
+
(held on your wallet), and pay only when the fix passes your tests. First 3 fixes
|
|
154
|
+
are free. Lives on `https://resolve.codai.ro` (same key; `resolve_base_url=` to override).
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from codai import Codai, ResolveInsufficientFundsError
|
|
158
|
+
|
|
159
|
+
client = Codai(api_key="codai_...")
|
|
160
|
+
job = client.resolve.submit({
|
|
161
|
+
"repo_url": "https://github.com/owner/repo",
|
|
162
|
+
"issue_url": "https://github.com/owner/repo/issues/42",
|
|
163
|
+
})
|
|
164
|
+
if job["status"] == "quoted":
|
|
165
|
+
try:
|
|
166
|
+
client.resolve.accept(job["id"])
|
|
167
|
+
except ResolveInsufficientFundsError as e:
|
|
168
|
+
print("top up first:", e.topup_url)
|
|
169
|
+
raise
|
|
170
|
+
done = client.resolve.wait_for(job["id"])
|
|
171
|
+
print(done["status"], done.get("attestation_url"))
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Failed attempts and infrastructure errors refund the hold in full. Types:
|
|
175
|
+
`codai._resolve_types` (generated from `resolve.yaml`).
|
|
176
|
+
|
|
150
177
|
## Development
|
|
151
178
|
|
|
152
179
|
```bash
|
|
@@ -123,6 +123,33 @@ Typed request/response shapes live in `codai._types` (generated from the
|
|
|
123
123
|
OpenAPI spec — `TypedDict`s such as `ChatCompletionRequest`, `Task`,
|
|
124
124
|
`SessionEvent`, `CreateSessionShareResponse`).
|
|
125
125
|
|
|
126
|
+
## codai Resolve (0.4.0)
|
|
127
|
+
|
|
128
|
+
Pay per verified fix: submit a public GitHub issue, get a flat quote, accept it
|
|
129
|
+
(held on your wallet), and pay only when the fix passes your tests. First 3 fixes
|
|
130
|
+
are free. Lives on `https://resolve.codai.ro` (same key; `resolve_base_url=` to override).
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from codai import Codai, ResolveInsufficientFundsError
|
|
134
|
+
|
|
135
|
+
client = Codai(api_key="codai_...")
|
|
136
|
+
job = client.resolve.submit({
|
|
137
|
+
"repo_url": "https://github.com/owner/repo",
|
|
138
|
+
"issue_url": "https://github.com/owner/repo/issues/42",
|
|
139
|
+
})
|
|
140
|
+
if job["status"] == "quoted":
|
|
141
|
+
try:
|
|
142
|
+
client.resolve.accept(job["id"])
|
|
143
|
+
except ResolveInsufficientFundsError as e:
|
|
144
|
+
print("top up first:", e.topup_url)
|
|
145
|
+
raise
|
|
146
|
+
done = client.resolve.wait_for(job["id"])
|
|
147
|
+
print(done["status"], done.get("attestation_url"))
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Failed attempts and infrastructure errors refund the hold in full. Types:
|
|
151
|
+
`codai._resolve_types` (generated from `resolve.yaml`).
|
|
152
|
+
|
|
126
153
|
## Development
|
|
127
154
|
|
|
128
155
|
```bash
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codai-sdk"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
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"
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Generate ``src/codai/_types.py`` from ``apps/docs/openapi/en/gateway.yaml
|
|
2
|
+
"""Generate ``src/codai/_types.py`` from ``apps/docs/openapi/en/gateway.yaml``
|
|
3
|
+
(and ``src/codai/_resolve_types.py`` from ``resolve.yaml`` with ``--spec resolve``).
|
|
3
4
|
|
|
4
5
|
TypedDicts for every ``components.schemas`` entry plus a ``<operationId>Body`` /
|
|
5
6
|
``<operationId>Response`` alias for each operation's JSON request / 2xx body.
|
|
6
7
|
Deterministic: the same spec always produces byte-identical output, so a second
|
|
7
8
|
run is a no-op (the parity CI step diffs the committed file against a fresh run).
|
|
8
9
|
|
|
9
|
-
.\\.venv\\Scripts\\python scripts/gen-types.py
|
|
10
|
-
.\\.venv\\Scripts\\python scripts/gen-types.py --check
|
|
10
|
+
.\\.venv\\Scripts\\python scripts/gen-types.py # write
|
|
11
|
+
.\\.venv\\Scripts\\python scripts/gen-types.py --check # exit 1 when stale
|
|
12
|
+
.\\.venv\\Scripts\\python scripts/gen-types.py --spec resolve # Resolve API types
|
|
11
13
|
|
|
12
14
|
Dev-only dependency: pyyaml (``pip install -e ".[dev]"``). The runtime SDK stays
|
|
13
15
|
zero-dependency — this script is never imported by the package.
|
|
@@ -25,15 +27,24 @@ import yaml
|
|
|
25
27
|
|
|
26
28
|
HERE = Path(__file__).resolve().parent
|
|
27
29
|
PKG = HERE.parent
|
|
28
|
-
|
|
30
|
+
OPENAPI = PKG.parents[1] / "apps" / "docs" / "openapi" / "en"
|
|
31
|
+
SPEC = OPENAPI / "gateway.yaml"
|
|
29
32
|
OUT = PKG / "src" / "codai" / "_types.py"
|
|
33
|
+
RESOLVE_SPEC = OPENAPI / "resolve.yaml"
|
|
34
|
+
RESOLVE_OUT = PKG / "src" / "codai" / "_resolve_types.py"
|
|
35
|
+
|
|
36
|
+
# --spec name → (spec file, output file, API label, regenerate command)
|
|
37
|
+
TARGETS: Dict[str, Tuple[Path, Path, str, str]] = {
|
|
38
|
+
"gateway": (SPEC, OUT, "gateway", "python scripts/gen-types.py"),
|
|
39
|
+
"resolve": (RESOLVE_SPEC, RESOLVE_OUT, "Resolve", "python scripts/gen-types.py --spec resolve"),
|
|
40
|
+
}
|
|
30
41
|
|
|
31
42
|
HTTP_METHODS = ("get", "post", "put", "patch", "delete")
|
|
32
43
|
|
|
33
|
-
HEADER = '''"""Typed dictionaries for the codai
|
|
44
|
+
HEADER = '''"""Typed dictionaries for the codai {api} API.
|
|
34
45
|
|
|
35
|
-
generated — do not edit. Source: apps/docs/openapi/en/
|
|
36
|
-
Regenerate with ``
|
|
46
|
+
generated — do not edit. Source: apps/docs/openapi/en/{source}.
|
|
47
|
+
Regenerate with ``{regen}`` (see that script's docstring).
|
|
37
48
|
|
|
38
49
|
Every ``components.schemas`` entry is a ``TypedDict`` (``total=False`` when the
|
|
39
50
|
schema has optional fields; a ``_<Name>Required`` base carries the required
|
|
@@ -76,8 +87,15 @@ def union(parts: List[str]) -> str:
|
|
|
76
87
|
|
|
77
88
|
|
|
78
89
|
class Generator:
|
|
79
|
-
def __init__(
|
|
90
|
+
def __init__(
|
|
91
|
+
self,
|
|
92
|
+
spec: Dict[str, Any],
|
|
93
|
+
api: str = "gateway",
|
|
94
|
+
source: str = "gateway.yaml",
|
|
95
|
+
regen: str = "python scripts/gen-types.py",
|
|
96
|
+
) -> None:
|
|
80
97
|
self.spec = spec
|
|
98
|
+
self.header = HEADER.format(api=api, source=source, regen=regen)
|
|
81
99
|
self.schemas: Dict[str, Any] = spec["components"]["schemas"]
|
|
82
100
|
self.blocks: List[Tuple[str, str]] = []
|
|
83
101
|
self.emitted: Dict[str, str] = {}
|
|
@@ -295,7 +313,7 @@ class Generator:
|
|
|
295
313
|
for name in self.schemas: # YAML order
|
|
296
314
|
self.ensure_schema(name)
|
|
297
315
|
self.emit_operations()
|
|
298
|
-
out = [
|
|
316
|
+
out = [self.header]
|
|
299
317
|
for _, code in self.blocks:
|
|
300
318
|
out.append(code)
|
|
301
319
|
out.append("\n\n")
|
|
@@ -307,18 +325,23 @@ class Generator:
|
|
|
307
325
|
|
|
308
326
|
|
|
309
327
|
def main(argv: List[str]) -> int:
|
|
310
|
-
|
|
328
|
+
name = argv[argv.index("--spec") + 1] if "--spec" in argv else "gateway"
|
|
329
|
+
if name not in TARGETS:
|
|
330
|
+
print(f"unknown --spec {name!r}; one of {', '.join(TARGETS)}", file=sys.stderr)
|
|
331
|
+
return 2
|
|
332
|
+
spec_path, out, api, regen = TARGETS[name]
|
|
333
|
+
with spec_path.open("r", encoding="utf-8") as fh:
|
|
311
334
|
spec = yaml.safe_load(fh)
|
|
312
|
-
text = Generator(spec).render()
|
|
335
|
+
text = Generator(spec, api=api, source=spec_path.name, regen=regen).render()
|
|
313
336
|
if "--check" in argv:
|
|
314
|
-
current =
|
|
337
|
+
current = out.read_text(encoding="utf-8") if out.exists() else ""
|
|
315
338
|
if current != text:
|
|
316
|
-
print(f"STALE: {
|
|
339
|
+
print(f"STALE: {out} differs from a fresh generation", file=sys.stderr)
|
|
317
340
|
return 1
|
|
318
|
-
print(f"OK: {
|
|
341
|
+
print(f"OK: {out} is up to date")
|
|
319
342
|
return 0
|
|
320
|
-
|
|
321
|
-
print(f"wrote {
|
|
343
|
+
out.write_text(text, encoding="utf-8", newline="\n")
|
|
344
|
+
print(f"wrote {out} ({text.count(chr(10))} lines, {len(spec['components']['schemas'])} schemas)")
|
|
322
345
|
return 0
|
|
323
346
|
|
|
324
347
|
|
|
@@ -32,8 +32,9 @@ from __future__ import annotations
|
|
|
32
32
|
from typing import Any, Dict, Generator, List, Optional
|
|
33
33
|
|
|
34
34
|
from ._http import CodaiError, HttpClient, RequestExtensions, SseFrame, extension_headers, frame_json, read_sse
|
|
35
|
-
from ._operations import OPERATION_METHODS, STREAMING_OPERATIONS
|
|
35
|
+
from ._operations import OPERATION_METHODS, RESOLVE_OPERATION_METHODS, STREAMING_OPERATIONS
|
|
36
36
|
from .resources import (
|
|
37
|
+
RESOLVE_TERMINAL_STATUSES,
|
|
37
38
|
Account,
|
|
38
39
|
AgentRunResult,
|
|
39
40
|
Agents,
|
|
@@ -43,20 +44,28 @@ from .resources import (
|
|
|
43
44
|
ChatStream,
|
|
44
45
|
Devices,
|
|
45
46
|
Embeddings,
|
|
47
|
+
Environments,
|
|
46
48
|
EphemeralToken,
|
|
47
49
|
Feedback,
|
|
48
50
|
Health,
|
|
49
51
|
Hosts,
|
|
50
52
|
Messages,
|
|
51
53
|
Models,
|
|
54
|
+
Notifications,
|
|
52
55
|
Orgs,
|
|
53
56
|
PhoneModels,
|
|
57
|
+
Projects,
|
|
54
58
|
Receipts,
|
|
59
|
+
Resolve,
|
|
60
|
+
ResolveError,
|
|
61
|
+
ResolveInsufficientFundsError,
|
|
55
62
|
Responses,
|
|
56
63
|
Sessions,
|
|
64
|
+
SystemOne,
|
|
57
65
|
Tasks,
|
|
58
66
|
Tokens,
|
|
59
67
|
Tools,
|
|
68
|
+
Triggers,
|
|
60
69
|
)
|
|
61
70
|
|
|
62
71
|
__all__ = [
|
|
@@ -70,12 +79,16 @@ __all__ = [
|
|
|
70
79
|
"RequestExtensions",
|
|
71
80
|
"SseFrame",
|
|
72
81
|
"OPERATION_METHODS",
|
|
82
|
+
"RESOLVE_OPERATION_METHODS",
|
|
83
|
+
"RESOLVE_TERMINAL_STATUSES",
|
|
84
|
+
"ResolveError",
|
|
85
|
+
"ResolveInsufficientFundsError",
|
|
73
86
|
"STREAMING_OPERATIONS",
|
|
74
87
|
"extension_headers",
|
|
75
88
|
"frame_json",
|
|
76
89
|
"read_sse",
|
|
77
90
|
]
|
|
78
|
-
__version__ = "0.
|
|
91
|
+
__version__ = "0.4.0"
|
|
79
92
|
|
|
80
93
|
|
|
81
94
|
class _CallableGroup:
|
|
@@ -108,6 +121,7 @@ class Codai:
|
|
|
108
121
|
client: Optional[str] = None,
|
|
109
122
|
defaults: Optional[RequestExtensions] = None,
|
|
110
123
|
opener: Any = None,
|
|
124
|
+
resolve_base_url: str = "https://resolve.codai.ro",
|
|
111
125
|
) -> None:
|
|
112
126
|
if not api_key:
|
|
113
127
|
raise ValueError("Codai: api_key is required")
|
|
@@ -134,6 +148,7 @@ class Codai:
|
|
|
134
148
|
self.messages = Messages(http)
|
|
135
149
|
self.responses = Responses(http)
|
|
136
150
|
self.audio = Audio(http)
|
|
151
|
+
self.system_one = SystemOne(http)
|
|
137
152
|
self.tokens = Tokens(http)
|
|
138
153
|
self.health = Health(http)
|
|
139
154
|
self.agents = Agents(http)
|
|
@@ -143,9 +158,23 @@ class Codai:
|
|
|
143
158
|
self.devices = Devices(http)
|
|
144
159
|
self.hosts = Hosts(http)
|
|
145
160
|
self.orgs = Orgs(http)
|
|
161
|
+
self.projects = Projects(http)
|
|
162
|
+
self.environments = Environments(http)
|
|
146
163
|
self.account = Account(http)
|
|
147
164
|
self.receipt = Receipts(http)
|
|
148
165
|
self.phone_models = PhoneModels(http)
|
|
166
|
+
self.triggers = Triggers(http)
|
|
167
|
+
self.notifications = Notifications(http)
|
|
168
|
+
# codai Resolve lives on its own host; same key, no X-Codai-* defaults.
|
|
169
|
+
self.resolve = Resolve(
|
|
170
|
+
HttpClient(
|
|
171
|
+
api_key=api_key,
|
|
172
|
+
base_url=resolve_base_url,
|
|
173
|
+
timeout=timeout,
|
|
174
|
+
max_retries=max_retries,
|
|
175
|
+
opener=opener,
|
|
176
|
+
)
|
|
177
|
+
)
|
|
149
178
|
|
|
150
179
|
self.chat: Any = _CallableGroup(Chat(http), self._legacy_chat)
|
|
151
180
|
self.embeddings: Any = _CallableGroup(Embeddings(http), self._legacy_embeddings)
|
|
@@ -16,6 +16,7 @@ OPERATION_METHODS: Dict[str, str] = {
|
|
|
16
16
|
"createMessage": "messages.create",
|
|
17
17
|
# Embeddings & Audio
|
|
18
18
|
"createEmbeddings": "embeddings.create",
|
|
19
|
+
"createSystemOne": "system_one.create",
|
|
19
20
|
"createTranscription": "audio.transcribe",
|
|
20
21
|
"createSpeech": "audio.speech",
|
|
21
22
|
"createEphemeralToken": "tokens.create",
|
|
@@ -78,6 +79,52 @@ OPERATION_METHODS: Dict[str, str] = {
|
|
|
78
79
|
"listOrgMembers": "orgs.members.list",
|
|
79
80
|
"addOrgMember": "orgs.members.add",
|
|
80
81
|
"removeOrgMember": "orgs.members.remove",
|
|
82
|
+
# Projects
|
|
83
|
+
"listProjects": "projects.list",
|
|
84
|
+
"createProject": "projects.create",
|
|
85
|
+
"getProject": "projects.get",
|
|
86
|
+
"updateProject": "projects.update",
|
|
87
|
+
"deleteProject": "projects.delete",
|
|
88
|
+
# Environments
|
|
89
|
+
"listEnvironments": "environments.list",
|
|
90
|
+
"createEnvironment": "environments.create",
|
|
91
|
+
"enrollEnvironment": "environments.enroll",
|
|
92
|
+
"getEnvironment": "environments.get",
|
|
93
|
+
"updateEnvironment": "environments.update",
|
|
94
|
+
"startEnvironment": "environments.start",
|
|
95
|
+
"stopEnvironment": "environments.stop",
|
|
96
|
+
"archiveEnvironment": "environments.archive",
|
|
97
|
+
"destroyEnvironment": "environments.destroy",
|
|
98
|
+
"createEnvironmentEnrollToken": "environments.enroll_token",
|
|
99
|
+
"listEnvironmentMembers": "environments.members.list",
|
|
100
|
+
"addEnvironmentMember": "environments.members.add",
|
|
101
|
+
"setMyEnvironmentSshKey": "environments.members.set_ssh_key",
|
|
102
|
+
"setEnvironmentMemberRole": "environments.members.set_role",
|
|
103
|
+
"removeEnvironmentMember": "environments.members.remove",
|
|
104
|
+
"listEnvironmentPorts": "environments.ports.list",
|
|
105
|
+
"setEnvironmentPort": "environments.ports.set",
|
|
106
|
+
"removeEnvironmentPort": "environments.ports.remove",
|
|
107
|
+
"listEnvironmentSecrets": "environments.secrets.list",
|
|
108
|
+
"setEnvironmentSecret": "environments.secrets.set",
|
|
109
|
+
"removeEnvironmentSecret": "environments.secrets.remove",
|
|
110
|
+
"issueMyEnvironmentSshCert": "environments.members.ssh_cert",
|
|
111
|
+
"getEnvironmentSshCa": "environments.ssh_ca",
|
|
112
|
+
"listEnvironmentTasks": "environments.tasks.list",
|
|
113
|
+
"createEnvironmentTask": "environments.tasks.create",
|
|
114
|
+
"getEnvironmentTask": "environments.tasks.get",
|
|
115
|
+
"listTriggers": "triggers.list",
|
|
116
|
+
"createTrigger": "triggers.create",
|
|
117
|
+
"updateTrigger": "triggers.update",
|
|
118
|
+
"deleteTrigger": "triggers.delete",
|
|
119
|
+
"rotateTriggerSecret": "triggers.rotate_secret",
|
|
120
|
+
"setTriggerSecret": "triggers.set_secret",
|
|
121
|
+
"testTrigger": "triggers.test",
|
|
122
|
+
"listTriggerEvents": "triggers.events",
|
|
123
|
+
"receiveTriggerHook": "triggers.fire_hook",
|
|
124
|
+
"listNotifications": "notifications.list",
|
|
125
|
+
"markNotificationsRead": "notifications.mark_read",
|
|
126
|
+
"deleteNotification": "notifications.delete",
|
|
127
|
+
"deleteNotifications": "notifications.delete_many",
|
|
81
128
|
# Account
|
|
82
129
|
"getAccount": "account.get",
|
|
83
130
|
"patchAccount": "account.update",
|
|
@@ -88,3 +135,12 @@ OPERATION_METHODS: Dict[str, str] = {
|
|
|
88
135
|
|
|
89
136
|
# Operations whose SDK method is a generator (SSE-only endpoints).
|
|
90
137
|
STREAMING_OPERATIONS: FrozenSet[str] = frozenset({"streamAgentRun", "streamSession", "streamHost"})
|
|
138
|
+
|
|
139
|
+
# codai Resolve (``apps/docs/openapi/en/resolve.yaml``) → ``client.resolve.*``.
|
|
140
|
+
RESOLVE_OPERATION_METHODS: Dict[str, str] = {
|
|
141
|
+
"resolveHealth": "resolve.health",
|
|
142
|
+
"createResolveJob": "resolve.submit",
|
|
143
|
+
"getResolveJob": "resolve.get",
|
|
144
|
+
"acceptResolveJob": "resolve.accept",
|
|
145
|
+
"getResolveAttestation": "resolve.attestation",
|
|
146
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""Typed dictionaries for the codai Resolve API.
|
|
2
|
+
|
|
3
|
+
generated — do not edit. Source: apps/docs/openapi/en/resolve.yaml.
|
|
4
|
+
Regenerate with ``python scripts/gen-types.py --spec resolve`` (see that script's docstring).
|
|
5
|
+
|
|
6
|
+
Every ``components.schemas`` entry is a ``TypedDict`` (``total=False`` when the
|
|
7
|
+
schema has optional fields; a ``_<Name>Required`` base carries the required
|
|
8
|
+
keys of mixed schemas). Non-object schemas (enums, unions, arrays) are type
|
|
9
|
+
aliases. ``<operationId>Body`` / ``<operationId>Response`` name each
|
|
10
|
+
operation's JSON request body and first 2xx JSON response.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Any, Dict, List, Literal, Optional, TypedDict, Union
|
|
16
|
+
|
|
17
|
+
class ResolveHealth(TypedDict):
|
|
18
|
+
ok: bool
|
|
19
|
+
service: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ResolveValidationDetails(TypedDict):
|
|
23
|
+
"""Zod `flatten()` output returned when the intake body fails schema validation."""
|
|
24
|
+
formErrors: List[str]
|
|
25
|
+
fieldErrors: Dict[str, List[str]]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ResolveError(TypedDict):
|
|
29
|
+
"""Flat error envelope used by every Resolve endpoint. Not the gateway `{ error: { code, message } }` shape."""
|
|
30
|
+
error: Union[str, ResolveValidationDetails]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class _ResolveIntakeRequired(TypedDict):
|
|
34
|
+
repo_url: str
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ResolveIntake(_ResolveIntakeRequired, total=False):
|
|
38
|
+
"""Body of `POST /v1/resolve/jobs`. Provide `issue_url` or `issue_text` (at least one)."""
|
|
39
|
+
issue_url: str
|
|
40
|
+
issue_text: str
|
|
41
|
+
test_command: str
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# `free` (first 3 resolves per user), `t7` ($7), `t19` ($19), `t49` ($49). Prices are in USD micros on the wire.
|
|
45
|
+
ResolveTier = Literal['free', 't7', 't19', 't49']
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# Lifecycle: `triage → quoted → accepted → running → resolved | failed`, plus `declined`
|
|
49
|
+
ResolveJobStatus = Literal['triage', 'quoted', 'declined', 'accepted', 'running', 'resolved', 'failed', 'error']
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ResolveQuote(TypedDict):
|
|
53
|
+
"""`201` body — the job was quoted (`quoted`) or auto-accepted on the free tier (`accepted`)."""
|
|
54
|
+
id: str
|
|
55
|
+
status: Literal['quoted', 'accepted']
|
|
56
|
+
tier: ResolveTier
|
|
57
|
+
quote_micro_usd: int
|
|
58
|
+
triage_reason: str
|
|
59
|
+
free_tier_remaining: int
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class ResolveDeclined(TypedDict):
|
|
63
|
+
"""`200` body — triage declined the issue. The job is persisted with `status: declined` and is never billed."""
|
|
64
|
+
id: str
|
|
65
|
+
status: str
|
|
66
|
+
decline_reason: str
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ResolveAccepted(TypedDict):
|
|
70
|
+
"""Accepted"""
|
|
71
|
+
id: str
|
|
72
|
+
status: str
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ResolveInsufficientFunds(TypedDict):
|
|
76
|
+
"""`402` body of `POST /v1/resolve/jobs/{id}/accept` when the wallet cannot hold the quote."""
|
|
77
|
+
error: str
|
|
78
|
+
balance: int
|
|
79
|
+
required: int
|
|
80
|
+
currency: str
|
|
81
|
+
topup_url: str
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class ResolveJob(TypedDict):
|
|
85
|
+
"""Full job view returned by `GET /v1/resolve/jobs/{id}`. Nullable fields are `null` until the corresponding stag…"""
|
|
86
|
+
id: str
|
|
87
|
+
status: ResolveJobStatus
|
|
88
|
+
repo_url: str
|
|
89
|
+
tier: Optional[ResolveTier]
|
|
90
|
+
quote_micro_usd: Optional[int]
|
|
91
|
+
triage_reason: Optional[str]
|
|
92
|
+
decline_reason: Optional[str]
|
|
93
|
+
fail_reason: Optional[str]
|
|
94
|
+
cost_micro_usd: int
|
|
95
|
+
attestation_id: Optional[str]
|
|
96
|
+
attestation_url: Optional[str]
|
|
97
|
+
created_at: str
|
|
98
|
+
completed_at: Optional[str]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class ResolveReproTest(TypedDict):
|
|
102
|
+
"""Repro test written by the agent when you did not supply `test_command`."""
|
|
103
|
+
path: str
|
|
104
|
+
content: Optional[str]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ResolveAttestation(TypedDict):
|
|
108
|
+
"""Public execution proof. Everything needed to reproduce the verification locally."""
|
|
109
|
+
id: str
|
|
110
|
+
kind: str
|
|
111
|
+
repo_url: str
|
|
112
|
+
base_commit: str
|
|
113
|
+
patch: str
|
|
114
|
+
repro_test: Optional[ResolveReproTest]
|
|
115
|
+
test_command: str
|
|
116
|
+
regression_command: Optional[str]
|
|
117
|
+
test_output_before: str
|
|
118
|
+
test_output_after: str
|
|
119
|
+
regression_output: Optional[str]
|
|
120
|
+
runner_image_digest: str
|
|
121
|
+
started_at: str
|
|
122
|
+
verified_at: str
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# GET /health — 200 response
|
|
126
|
+
ResolveHealthResponse = ResolveHealth
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# POST /v1/resolve/jobs — request body
|
|
130
|
+
CreateResolveJobBody = ResolveIntake
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# POST /v1/resolve/jobs — 200 response
|
|
134
|
+
CreateResolveJobResponse = ResolveDeclined
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# POST /v1/resolve/jobs — 201 response
|
|
138
|
+
CreateResolveJobResponse201 = ResolveQuote
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# GET /v1/resolve/jobs/{id} — 200 response
|
|
142
|
+
GetResolveJobResponse = ResolveJob
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# POST /v1/resolve/jobs/{id}/accept — 200 response
|
|
146
|
+
AcceptResolveJobResponse = ResolveAccepted
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# GET /v1/resolve/attestations/{id} — 200 response
|
|
150
|
+
GetResolveAttestationResponse = ResolveAttestation
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
__all__ = [
|
|
154
|
+
'AcceptResolveJobResponse',
|
|
155
|
+
'CreateResolveJobBody',
|
|
156
|
+
'CreateResolveJobResponse',
|
|
157
|
+
'CreateResolveJobResponse201',
|
|
158
|
+
'GetResolveAttestationResponse',
|
|
159
|
+
'GetResolveJobResponse',
|
|
160
|
+
'ResolveAccepted',
|
|
161
|
+
'ResolveAttestation',
|
|
162
|
+
'ResolveDeclined',
|
|
163
|
+
'ResolveError',
|
|
164
|
+
'ResolveHealth',
|
|
165
|
+
'ResolveHealthResponse',
|
|
166
|
+
'ResolveInsufficientFunds',
|
|
167
|
+
'ResolveIntake',
|
|
168
|
+
'ResolveJob',
|
|
169
|
+
'ResolveJobStatus',
|
|
170
|
+
'ResolveQuote',
|
|
171
|
+
'ResolveReproTest',
|
|
172
|
+
'ResolveTier',
|
|
173
|
+
'ResolveValidationDetails',
|
|
174
|
+
]
|