opencode-runtime 0.4.0__py3-none-any.whl → 0.4.1__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.
- opencode_runtime/__init__.py +1 -1
- opencode_runtime/client.py +1 -5
- opencode_runtime/event.py +3 -2
- opencode_runtime/response.py +1 -1
- opencode_runtime/server.py +1 -1
- opencode_runtime/session.py +4 -1
- opencode_runtime-0.4.1.dist-info/METADATA +125 -0
- opencode_runtime-0.4.1.dist-info/RECORD +16 -0
- {opencode_runtime-0.4.0.dist-info → opencode_runtime-0.4.1.dist-info}/WHEEL +1 -1
- opencode_runtime-0.4.0.dist-info/METADATA +0 -299
- opencode_runtime-0.4.0.dist-info/RECORD +0 -16
- {opencode_runtime-0.4.0.dist-info → opencode_runtime-0.4.1.dist-info}/entry_points.txt +0 -0
- {opencode_runtime-0.4.0.dist-info → opencode_runtime-0.4.1.dist-info}/licenses/LICENSE +0 -0
opencode_runtime/__init__.py
CHANGED
opencode_runtime/client.py
CHANGED
|
@@ -154,7 +154,7 @@ class OpenCodeClient:
|
|
|
154
154
|
delta string when ``properties.field == "text"``.
|
|
155
155
|
* ``message.part.updated`` — full part snapshot (text, tool, thinking,
|
|
156
156
|
…); ``event.text`` is the text content when ``part.type == "text"``.
|
|
157
|
-
* ``session.status`` — status change (e.g. ``{type: "
|
|
157
|
+
* ``session.status`` — status change (e.g. ``{type: "busy"}``).
|
|
158
158
|
* ``session.idle`` — terminal; model finished.
|
|
159
159
|
* ``session.error`` — terminal; something went wrong.
|
|
160
160
|
* ``permission.asked`` — tool permission request; caller must handle.
|
|
@@ -222,7 +222,3 @@ class OpenCodeClient:
|
|
|
222
222
|
return
|
|
223
223
|
if event_type == "session.error":
|
|
224
224
|
return
|
|
225
|
-
if event_type == "session.status":
|
|
226
|
-
status = props.get("status", {})
|
|
227
|
-
if isinstance(status, dict) and status.get("type") == "idle":
|
|
228
|
-
return
|
opencode_runtime/event.py
CHANGED
|
@@ -9,9 +9,10 @@ class OpenCodeEvent:
|
|
|
9
9
|
"""A normalized event from the OpenCode server SSE stream.
|
|
10
10
|
|
|
11
11
|
Attributes:
|
|
12
|
-
type: Event type string, e.g. "message.delta", "message.
|
|
12
|
+
type: Event type string, e.g. "message.part.delta", "message.part.updated",
|
|
13
13
|
"session.error". Mirrors the OpenCode bus event types.
|
|
14
|
-
text: Text content for message.delta events
|
|
14
|
+
text: Text content for message.part.delta events (when properties.field == "text")
|
|
15
|
+
and message.part.updated events (when part.type == "text"); None otherwise.
|
|
15
16
|
raw: The raw event payload from the server. Use this escape hatch
|
|
16
17
|
when you need fields beyond type and text.
|
|
17
18
|
"""
|
opencode_runtime/response.py
CHANGED
|
@@ -9,7 +9,7 @@ class OpenCodeResponse:
|
|
|
9
9
|
"""Collected response from a completed ask() call.
|
|
10
10
|
|
|
11
11
|
Attributes:
|
|
12
|
-
text: Full assistant text, concatenated from all message.delta events.
|
|
12
|
+
text: Full assistant text, concatenated from all message.part.delta events.
|
|
13
13
|
raw: List of raw event objects received during the session, in order.
|
|
14
14
|
Use this as an escape hatch when you need parts beyond plain text.
|
|
15
15
|
"""
|
opencode_runtime/server.py
CHANGED
|
@@ -327,7 +327,7 @@ class ServerManager:
|
|
|
327
327
|
if server_dir is not None:
|
|
328
328
|
process_env["HOME"] = str(server_dir)
|
|
329
329
|
process_env["TMPDIR"] = str(server_dir / "tmp")
|
|
330
|
-
process_env["
|
|
330
|
+
process_env["OPENCODE_CONFIG"] = str(server_dir / "opencode.json")
|
|
331
331
|
|
|
332
332
|
if server_dir is not None:
|
|
333
333
|
log_file = open(server_dir / "opencode.log", "ab")
|
opencode_runtime/session.py
CHANGED
|
@@ -77,7 +77,10 @@ class OpenCodeSession:
|
|
|
77
77
|
async for event in self.stream(message, **kwargs):
|
|
78
78
|
raw_events.append(event.raw)
|
|
79
79
|
if event.type == "session.error":
|
|
80
|
-
|
|
80
|
+
props = (event.raw or {}).get("properties") or {}
|
|
81
|
+
err = props.get("error") or {}
|
|
82
|
+
msg = (err.get("data") or {}).get("message") or err.get("name") or "unknown error"
|
|
83
|
+
raise OpenCodeServerError(msg)
|
|
81
84
|
if event.type == "message.part.delta" and event.text:
|
|
82
85
|
text += event.text
|
|
83
86
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opencode-runtime
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: Embed OpenCode in your Python application.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ashish16052/opencode-runtime
|
|
6
|
+
Project-URL: Repository, https://github.com/ashish16052/opencode-runtime
|
|
7
|
+
Project-URL: Issues, https://github.com/ashish16052/opencode-runtime/issues
|
|
8
|
+
Author: Ashish Mohite
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: AI coding agent,agent runtime,lifecycle management,multi-user,opencode,workspace isolation
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: httpx
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build; extra == 'dev'
|
|
25
|
+
Requires-Dist: hatchling; extra == 'dev'
|
|
26
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-timeout; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
31
|
+
Requires-Dist: twine; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# opencode-runtime
|
|
35
|
+
|
|
36
|
+
**Embed OpenCode in your Python application.**
|
|
37
|
+
|
|
38
|
+
OpenCode is a great CLI coding agent. But to embed it in a product, SaaS
|
|
39
|
+
backend, or multi-user automation system, you need more than a CLI process.
|
|
40
|
+
|
|
41
|
+
opencode-runtime turns OpenCode into a managed application runtime for
|
|
42
|
+
Python. It uses OpenCode as the agent harness and adds what you need to
|
|
43
|
+
run it as part of an application: lifecycle management, per-user
|
|
44
|
+
workspaces, reusable sessions, health checks, streaming output, and
|
|
45
|
+
multi-server orchestration.
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pip install opencode-runtime
|
|
51
|
+
npm install -g opencode-ai # opencode must be on PATH
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Use
|
|
55
|
+
|
|
56
|
+
### Your first session
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from opencode_runtime import OpenCodeRuntime
|
|
60
|
+
|
|
61
|
+
async with OpenCodeRuntime() as r:
|
|
62
|
+
session = await r.session()
|
|
63
|
+
response = await session.ask("Explain this repo")
|
|
64
|
+
print(response.text)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### One server per user, automatically
|
|
68
|
+
|
|
69
|
+
Every `(workspace, user_id)` pair gets its own isolated server, workspace, and conversation history — started on first use, reused after:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
async with OpenCodeRuntime(runtime_dir=".opencode-runtime") as r:
|
|
73
|
+
s1 = await r.session(workspace="org_a", user_id="u_1")
|
|
74
|
+
s2 = await r.session(workspace="org_b", user_id="u_2")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Stream every token as it arrives
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
async for event in session.stream("Review this PR"):
|
|
81
|
+
if event.type == "message.part.delta" and event.text:
|
|
82
|
+
print(event.text, end="", flush=True)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Inspect
|
|
86
|
+
|
|
87
|
+
Servers started from Python are visible and manageable from the terminal:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
opencode-runtime ps
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
ID PID PORT STATUS UPTIME WORKSPACE USER PROJECT
|
|
95
|
+
──────────────────────────────────────────────────────────────────────────────────
|
|
96
|
+
39dce5beb4debfaa 12051 58409 ● alive Up 5m org_a u_1 ~/Developer/myproject
|
|
97
|
+
81fa29acb3e9210f 12088 58411 ● alive Up 3m org_b u_2 ~/Developer/myproject
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
opencode-runtime health 39dce5beb4debfaa
|
|
102
|
+
opencode-runtime stop-all
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Guides
|
|
106
|
+
|
|
107
|
+
- [OpenCode config](docs/opencode-config.md) — models, permissions, agents, skills
|
|
108
|
+
- [Sessions](docs/sessions.md) — continuation, resume across restarts
|
|
109
|
+
- [Users & workspaces](docs/users-and-workspaces.md) — multi-tenant isolation
|
|
110
|
+
- [Streaming](docs/streaming.md) — event types, tool calls, permissions, cost
|
|
111
|
+
- [CLI](docs/cli.md) — manage your fleet from the terminal
|
|
112
|
+
- [HTTP client](docs/http-client.md) — direct server access
|
|
113
|
+
|
|
114
|
+
## Requirements
|
|
115
|
+
|
|
116
|
+
- Python 3.10+
|
|
117
|
+
- `opencode` 1.0+ on PATH
|
|
118
|
+
|
|
119
|
+
## Contributing
|
|
120
|
+
|
|
121
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
Apache 2.0
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
opencode_runtime/__init__.py,sha256=RNZO_09NXusYD_xhbeJLb2HCp_0JeogNEi6247mPcL4,362
|
|
2
|
+
opencode_runtime/cli.py,sha256=byy2ezufQvk5f_e1nwDN8ZIFflIwgvuC9SX7HQGYTkU,8938
|
|
3
|
+
opencode_runtime/client.py,sha256=XZw413XiTOaAeKY5WufmMFsDAlullel50i_N5A0wYyM,9069
|
|
4
|
+
opencode_runtime/event.py,sha256=7tWTLXTVUB6g3Ni7jiG2VYdHhjU9rpiwrY0MT1RnEMQ,960
|
|
5
|
+
opencode_runtime/exceptions.py,sha256=uarBFCh8ovI3w4ZB4oQuffv97-5nwTdkZQrkBcOWtWs,471
|
|
6
|
+
opencode_runtime/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
opencode_runtime/registry.py,sha256=rxr3D4iqceskmPBYvRC_lbtME8hoMR4I6rsdYCqllLA,2309
|
|
8
|
+
opencode_runtime/response.py,sha256=MmT4qiakWD55J8cFg64VOztusfWkynrucdjbm0srNks,541
|
|
9
|
+
opencode_runtime/runtime.py,sha256=magKzC-kN7g9bsttNhSLEif9hD92_qrHgJgvXDOauYU,5255
|
|
10
|
+
opencode_runtime/server.py,sha256=eu2JwLwkpICRviZx4OmN2z2_gVWCkfnm4qhcQRW3bSw,12595
|
|
11
|
+
opencode_runtime/session.py,sha256=9ES_mVvXWFhLPNnFFY9KwvRi_4zoVNTe8EToU8oe3ng,5777
|
|
12
|
+
opencode_runtime-0.4.1.dist-info/METADATA,sha256=IkOu8zi4YGNidowr_OUYpypcvCYsq4R1-z8ul8-ocZc,4179
|
|
13
|
+
opencode_runtime-0.4.1.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
14
|
+
opencode_runtime-0.4.1.dist-info/entry_points.txt,sha256=4lbdu1KELOg8TD6F7gC-Xrt3VJXdk3RTaH8cQHVy-Tc,63
|
|
15
|
+
opencode_runtime-0.4.1.dist-info/licenses/LICENSE,sha256=EVYfwpsynn_pB9fQ0OhMX-ghTZM10CrFAPv1JbLODi4,11343
|
|
16
|
+
opencode_runtime-0.4.1.dist-info/RECORD,,
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: opencode-runtime
|
|
3
|
-
Version: 0.4.0
|
|
4
|
-
Summary: Python runtime for deploying and managing OpenCode instances at scale.
|
|
5
|
-
Project-URL: Homepage, https://github.com/ashish16052/opencode-runtime
|
|
6
|
-
Project-URL: Repository, https://github.com/ashish16052/opencode-runtime
|
|
7
|
-
Project-URL: Issues, https://github.com/ashish16052/opencode-runtime/issues
|
|
8
|
-
Author: Ashish Mohite
|
|
9
|
-
License-Expression: Apache-2.0
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
Keywords: AI coding agent,agent runtime,lifecycle management,multi-user,opencode,workspace isolation
|
|
12
|
-
Classifier: Development Status :: 3 - Alpha
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
-
Requires-Python: >=3.10
|
|
22
|
-
Requires-Dist: httpx
|
|
23
|
-
Provides-Extra: dev
|
|
24
|
-
Requires-Dist: build; extra == 'dev'
|
|
25
|
-
Requires-Dist: hatchling; extra == 'dev'
|
|
26
|
-
Requires-Dist: mypy; extra == 'dev'
|
|
27
|
-
Requires-Dist: pytest; extra == 'dev'
|
|
28
|
-
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
29
|
-
Requires-Dist: pytest-timeout; extra == 'dev'
|
|
30
|
-
Requires-Dist: ruff; extra == 'dev'
|
|
31
|
-
Requires-Dist: twine; extra == 'dev'
|
|
32
|
-
Description-Content-Type: text/markdown
|
|
33
|
-
|
|
34
|
-
# opencode-runtime
|
|
35
|
-
|
|
36
|
-
Python runtime for deploying and managing OpenCode instances at scale.
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
Running OpenCode for a single developer is simple.
|
|
41
|
-
|
|
42
|
-
Running OpenCode for many users, isolated repositories, persistent workspaces,
|
|
43
|
-
multiple OpenCode instances, and production workloads requires infrastructure.
|
|
44
|
-
|
|
45
|
-
OpenCode Runtime provides that infrastructure.
|
|
46
|
-
|
|
47
|
-
**Use this when you need to:**
|
|
48
|
-
- Run OpenCode for multiple users or teams from a Python backend
|
|
49
|
-
- Give each user an isolated workspace with no shared state
|
|
50
|
-
- Embed OpenCode in a SaaS product or internal platform
|
|
51
|
-
- Manage OpenCode instance lifecycles (start, health-check, reuse, stop)
|
|
52
|
-
- Stream OpenCode responses to your application in real time
|
|
53
|
-
|
|
54
|
-
**What it provides:**
|
|
55
|
-
- **One instance per user** — automatically started, isolated, and reused
|
|
56
|
-
- **Filesystem isolation** — each user gets a private workspace; no shared state
|
|
57
|
-
- **Lifecycle management** — health-checked startup, graceful shutdown, stale process recovery
|
|
58
|
-
- **Streaming** — consume every OpenCode event as it arrives
|
|
59
|
-
- **Native OpenCode config** — your existing `opencode.json`, agents, and skills drop in unchanged
|
|
60
|
-
|
|
61
|
-
## Install
|
|
62
|
-
|
|
63
|
-
```sh
|
|
64
|
-
pip install opencode-runtime
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Requires `opencode` on PATH:
|
|
68
|
-
|
|
69
|
-
```sh
|
|
70
|
-
npm install -g opencode-ai
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Usage
|
|
74
|
-
|
|
75
|
-
### Ask
|
|
76
|
-
|
|
77
|
-
```python
|
|
78
|
-
from opencode_runtime import OpenCodeRuntime
|
|
79
|
-
|
|
80
|
-
async with OpenCodeRuntime() as r:
|
|
81
|
-
session = await r.session()
|
|
82
|
-
response = await session.ask("Explain this repo")
|
|
83
|
-
print(response.text)
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Config
|
|
87
|
-
|
|
88
|
-
Pass a raw `opencode.json` dict to control model, permissions, and any other OpenCode-native setting:
|
|
89
|
-
|
|
90
|
-
```python
|
|
91
|
-
from opencode_runtime import OpenCodeRuntime
|
|
92
|
-
|
|
93
|
-
async with OpenCodeRuntime(
|
|
94
|
-
config={"model": "anthropic/claude-sonnet-4-5", "permission": {"bash": "deny"}},
|
|
95
|
-
) as r:
|
|
96
|
-
session = await r.session()
|
|
97
|
-
response = await session.ask("Analyse the architecture")
|
|
98
|
-
print(response.text)
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Materials
|
|
102
|
-
|
|
103
|
-
Pass a directory of OpenCode-native files — `AGENTS.md`, `opencode.json`, `.opencode/skills/`, etc. — and they are copied into the server before it starts:
|
|
104
|
-
|
|
105
|
-
```python
|
|
106
|
-
from opencode_runtime import OpenCodeRuntime
|
|
107
|
-
|
|
108
|
-
async with OpenCodeRuntime(materials="./opencode-materials") as r:
|
|
109
|
-
session = await r.session()
|
|
110
|
-
response = await session.ask("Follow the instructions in AGENTS.md")
|
|
111
|
-
print(response.text)
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Isolation
|
|
115
|
-
|
|
116
|
-
Set `project_dir` and `runtime_dir` to give the server its own `HOME`, config, and conversation history — separate from your real environment:
|
|
117
|
-
|
|
118
|
-
```python
|
|
119
|
-
from opencode_runtime import OpenCodeRuntime
|
|
120
|
-
|
|
121
|
-
async with OpenCodeRuntime(
|
|
122
|
-
project_dir="/path/to/project",
|
|
123
|
-
runtime_dir=".opencode-runtime",
|
|
124
|
-
materials="./opencode-materials",
|
|
125
|
-
) as r:
|
|
126
|
-
session = await r.session()
|
|
127
|
-
response = await session.ask("What does this project do?")
|
|
128
|
-
print(response.text)
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Per-user sessions
|
|
132
|
-
|
|
133
|
-
Each unique `user_id` gets its own isolated server and conversation history:
|
|
134
|
-
|
|
135
|
-
```python
|
|
136
|
-
from opencode_runtime import OpenCodeRuntime
|
|
137
|
-
|
|
138
|
-
async with OpenCodeRuntime(runtime_dir=".opencode-runtime") as r:
|
|
139
|
-
session = await r.session(user_id="u_1")
|
|
140
|
-
response = await session.ask("What does this project do?")
|
|
141
|
-
print(response.text)
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Multi-tenant
|
|
145
|
-
|
|
146
|
-
Add `workspace` to isolate by tenant. Different `(workspace, user_id)` → different server. Same combination → server reused:
|
|
147
|
-
|
|
148
|
-
```python
|
|
149
|
-
from opencode_runtime import OpenCodeRuntime
|
|
150
|
-
|
|
151
|
-
async with OpenCodeRuntime(runtime_dir=".opencode-runtime") as r:
|
|
152
|
-
s1 = await r.session(workspace="org_a", user_id="u_1")
|
|
153
|
-
s2 = await r.session(workspace="org_b", user_id="u_2")
|
|
154
|
-
r1 = await s1.ask("What does this project do?")
|
|
155
|
-
r2 = await s2.ask("List the main dependencies")
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Session continuation
|
|
159
|
-
|
|
160
|
-
Multiple `ask()` calls on the same session continue the same conversation — OpenCode keeps the full history server-side:
|
|
161
|
-
|
|
162
|
-
```python
|
|
163
|
-
from opencode_runtime import OpenCodeRuntime
|
|
164
|
-
|
|
165
|
-
async with OpenCodeRuntime() as r:
|
|
166
|
-
session = await r.session()
|
|
167
|
-
await session.ask("Explain this repo")
|
|
168
|
-
await session.ask("Which file should I start with?") # has full context
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
To resume a conversation in a future session, store `session.session_id` and pass it back:
|
|
172
|
-
|
|
173
|
-
```python
|
|
174
|
-
# First session
|
|
175
|
-
async with OpenCodeRuntime() as r:
|
|
176
|
-
session = await r.session()
|
|
177
|
-
await session.ask("Explain this repo")
|
|
178
|
-
saved_id = session.session_id # persist this
|
|
179
|
-
|
|
180
|
-
# Later — resumes the same conversation
|
|
181
|
-
async with OpenCodeRuntime() as r:
|
|
182
|
-
session = await r.session(session_id=saved_id)
|
|
183
|
-
await session.ask("What were we discussing?")
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Raw client
|
|
187
|
-
|
|
188
|
-
Access any OpenCode server endpoint directly:
|
|
189
|
-
|
|
190
|
-
```python
|
|
191
|
-
from opencode_runtime import OpenCodeRuntime
|
|
192
|
-
|
|
193
|
-
async with OpenCodeRuntime() as r:
|
|
194
|
-
session = await r.session()
|
|
195
|
-
agents = await session.raw_client.get("/agent")
|
|
196
|
-
mcp = await session.raw_client.get("/mcp")
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### Streaming
|
|
200
|
-
|
|
201
|
-
For live output, use `stream()`. It yields every event OpenCode emits as an
|
|
202
|
-
`OpenCodeEvent` with three fields: `type` (event kind), `text` (populated for
|
|
203
|
-
text-bearing events, `None` otherwise), and `raw` (full server payload). See
|
|
204
|
-
the [OpenCode server docs](https://opencode.ai/docs/server#events) for all event types.
|
|
205
|
-
|
|
206
|
-
```python
|
|
207
|
-
from opencode_runtime import OpenCodeRuntime
|
|
208
|
-
|
|
209
|
-
async with OpenCodeRuntime() as r:
|
|
210
|
-
session = await r.session()
|
|
211
|
-
async for event in session.stream("Review this PR"):
|
|
212
|
-
if event.type == "message.part.delta" and event.text:
|
|
213
|
-
print(event.text, end="", flush=True)
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## CLI
|
|
217
|
-
|
|
218
|
-
`opencode-runtime` ships with a CLI for managing opencode servers from the terminal. Useful for inspecting what your application is running, debugging sessions, or managing servers independently.
|
|
219
|
-
|
|
220
|
-
### Start a server
|
|
221
|
-
|
|
222
|
-
```sh
|
|
223
|
-
opencode-runtime serve
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
The server runs in the background. Use `ps`, `stop`, and `health` to manage it.
|
|
227
|
-
|
|
228
|
-
### Multi-tenant
|
|
229
|
-
|
|
230
|
-
Each unique `(workspace, user-id)` combination gets its own isolated server:
|
|
231
|
-
|
|
232
|
-
```sh
|
|
233
|
-
opencode-runtime serve --workspace org_a --user-id u_1
|
|
234
|
-
opencode-runtime serve --workspace org_b --user-id u_2
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
### List servers
|
|
238
|
-
|
|
239
|
-
```sh
|
|
240
|
-
opencode-runtime ps
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
```
|
|
244
|
-
ID PID PORT STATUS UPTIME WORKSPACE USER PROJECT
|
|
245
|
-
──────────────────────────────────────────────────────────────────────────────────
|
|
246
|
-
39dce5beb4debfaa 12051 58409 ● alive Up 5m org_a u_1 ~/Developer/myproject
|
|
247
|
-
81fa29acb3e9210f 12088 58411 ● alive Up 3m org_b u_2 ~/Developer/myproject
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### Check health
|
|
251
|
-
|
|
252
|
-
```sh
|
|
253
|
-
opencode-runtime health 39dce5beb4debfaa
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### Stop a server
|
|
257
|
-
|
|
258
|
-
```sh
|
|
259
|
-
opencode-runtime stop 39dce5beb4debfaa
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### Stop all servers
|
|
263
|
-
|
|
264
|
-
```sh
|
|
265
|
-
opencode-runtime stop-all
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
### Library + CLI
|
|
269
|
-
|
|
270
|
-
Start a server from Python, then inspect and manage it from the terminal:
|
|
271
|
-
|
|
272
|
-
```python
|
|
273
|
-
from opencode_runtime import OpenCodeRuntime
|
|
274
|
-
|
|
275
|
-
async with OpenCodeRuntime() as r:
|
|
276
|
-
session = await r.session()
|
|
277
|
-
response = await session.ask("Review this PR")
|
|
278
|
-
print(response.text)
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
```sh
|
|
282
|
-
# while app.py is running
|
|
283
|
-
opencode-runtime ps
|
|
284
|
-
opencode-runtime health 39dce5beb4debfaa
|
|
285
|
-
opencode-runtime stop 39dce5beb4debfaa
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
## Requirements
|
|
289
|
-
|
|
290
|
-
- Python 3.10+
|
|
291
|
-
- `opencode` 1.0+ on PATH
|
|
292
|
-
|
|
293
|
-
## Contributing
|
|
294
|
-
|
|
295
|
-
See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
296
|
-
|
|
297
|
-
## License
|
|
298
|
-
|
|
299
|
-
Apache 2.0
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
opencode_runtime/__init__.py,sha256=j6GRSnhDThfOBeAxqJw3oZ2_QwB3IbSK312J37e0ajw,362
|
|
2
|
-
opencode_runtime/cli.py,sha256=byy2ezufQvk5f_e1nwDN8ZIFflIwgvuC9SX7HQGYTkU,8938
|
|
3
|
-
opencode_runtime/client.py,sha256=OtPELbo48XC-r3atNcOpuS54tMNVJq3xKc2DhHZTOwQ,9305
|
|
4
|
-
opencode_runtime/event.py,sha256=Y3QoElyk_tgTNqpSsG2MPo4-rjorTAPBEkoAPyzr8CQ,845
|
|
5
|
-
opencode_runtime/exceptions.py,sha256=uarBFCh8ovI3w4ZB4oQuffv97-5nwTdkZQrkBcOWtWs,471
|
|
6
|
-
opencode_runtime/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
opencode_runtime/registry.py,sha256=rxr3D4iqceskmPBYvRC_lbtME8hoMR4I6rsdYCqllLA,2309
|
|
8
|
-
opencode_runtime/response.py,sha256=p-xTPmPXs1icHk_dgztTMNh7Il1DwBbN775CuOyKfDI,536
|
|
9
|
-
opencode_runtime/runtime.py,sha256=magKzC-kN7g9bsttNhSLEif9hD92_qrHgJgvXDOauYU,5255
|
|
10
|
-
opencode_runtime/server.py,sha256=giYJ2ebCmB5ialgOjsJefpooipCLjSSglkhcZN6z0Yo,12582
|
|
11
|
-
opencode_runtime/session.py,sha256=1CT8phyzpj_jxaLXrp1vC6gKUnebUEwberPwdpIQ9j8,5612
|
|
12
|
-
opencode_runtime-0.4.0.dist-info/METADATA,sha256=69B_qmK1TOGsCC-syndWfcfCjz7AWua0hHdbuMAL1yw,8814
|
|
13
|
-
opencode_runtime-0.4.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
14
|
-
opencode_runtime-0.4.0.dist-info/entry_points.txt,sha256=4lbdu1KELOg8TD6F7gC-Xrt3VJXdk3RTaH8cQHVy-Tc,63
|
|
15
|
-
opencode_runtime-0.4.0.dist-info/licenses/LICENSE,sha256=EVYfwpsynn_pB9fQ0OhMX-ghTZM10CrFAPv1JbLODi4,11343
|
|
16
|
-
opencode_runtime-0.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|