opencode-python-sdk 0.1.0__tar.gz → 0.1.2__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.
Files changed (70) hide show
  1. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/.gitignore +4 -0
  2. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/PKG-INFO +28 -2
  3. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/README.md +24 -0
  4. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/pyproject.toml +20 -5
  5. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/__init__.py +4 -0
  6. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_exceptions.py +22 -0
  7. opencode_python_sdk-0.1.2/src/opencode/_pty.py +586 -0
  8. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_server.py +8 -0
  9. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/agent.py +14 -14
  10. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/command.py +6 -6
  11. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/config.py +18 -18
  12. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/credential.py +22 -22
  13. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/debug.py +10 -8
  14. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/event.py +4 -4
  15. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/experimental.py +77 -74
  16. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/file.py +28 -28
  17. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/form.py +6 -6
  18. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/generate.py +8 -8
  19. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/integration.py +102 -94
  20. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/location.py +12 -12
  21. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/mcp.py +44 -42
  22. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/message.py +10 -10
  23. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/migration.py +6 -4
  24. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/model.py +16 -16
  25. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/permission.py +68 -64
  26. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/plugin.py +20 -20
  27. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/project.py +14 -14
  28. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/provider.py +18 -18
  29. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/pty.py +51 -48
  30. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/reference.py +6 -6
  31. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/rpc.py +10 -10
  32. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/server.py +12 -12
  33. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/session.py +378 -366
  34. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/shell.py +34 -34
  35. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/skill.py +6 -6
  36. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/vcs.py +48 -46
  37. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/voice.py +8 -8
  38. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/websearch.py +16 -16
  39. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/worktree.py +30 -30
  40. opencode_python_sdk-0.1.2/tests/test_docs_coverage.py +256 -0
  41. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/test_live.py +16 -0
  42. opencode_python_sdk-0.1.2/tests/test_pty.py +236 -0
  43. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/CHANGELOG.md +0 -0
  44. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/LICENSE +0 -0
  45. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/api.md +0 -0
  46. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/.generated.json +0 -0
  47. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_base_client.py +0 -0
  48. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_client.py +0 -0
  49. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_constants.py +0 -0
  50. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_errors.py +0 -0
  51. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_models.py +0 -0
  52. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_pagination.py +0 -0
  53. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_qs.py +0 -0
  54. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_resource.py +0 -0
  55. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_streaming.py +0 -0
  56. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_types.py +0 -0
  57. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_unions.py +0 -0
  58. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/_version.py +0 -0
  59. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/py.typed +0 -0
  60. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/resources/__init__.py +0 -0
  61. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/types/__init__.py +0 -0
  62. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/src/opencode/types/_generated.py +0 -0
  63. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/__init__.py +0 -0
  64. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/conftest.py +0 -0
  65. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/test_async_client.py +0 -0
  66. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/test_client.py +0 -0
  67. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/test_encoding.py +0 -0
  68. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/test_models.py +0 -0
  69. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/test_pagination.py +0 -0
  70. {opencode_python_sdk-0.1.0 → opencode_python_sdk-0.1.2}/tests/test_streaming.py +0 -0
@@ -14,3 +14,7 @@ htmlcov/
14
14
  codegen/extract/node_modules/
15
15
  codegen/extract/.cache/
16
16
  .DS_Store
17
+
18
+ # MkDocs output
19
+ site/
20
+ .cache/
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: opencode-python-sdk
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Typed Python client for the OpenCode 2.x server API
5
5
  Project-URL: Homepage, https://github.com/shrijayan/opencode-python-sdk
6
- Project-URL: Documentation, https://github.com/shrijayan/opencode-python-sdk#readme
6
+ Project-URL: Documentation, https://shrijayan.github.io/opencode-python-sdk/
7
7
  Project-URL: Repository, https://github.com/shrijayan/opencode-python-sdk
8
8
  Project-URL: Issues, https://github.com/shrijayan/opencode-python-sdk/issues
9
9
  Project-URL: Changelog, https://github.com/shrijayan/opencode-python-sdk/blob/main/CHANGELOG.md
@@ -31,16 +31,21 @@ Requires-Dist: anyio<5,>=4.4
31
31
  Requires-Dist: httpx<1,>=0.27
32
32
  Requires-Dist: pydantic<3,>=2.12
33
33
  Requires-Dist: typing-extensions>=4.12
34
+ Provides-Extra: pty
35
+ Requires-Dist: websockets<17,>=14; extra == 'pty'
34
36
  Description-Content-Type: text/markdown
35
37
 
36
38
  # opencode-python-sdk
37
39
 
38
40
  [![CI](https://github.com/shrijayan/opencode-python-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/shrijayan/opencode-python-sdk/actions/workflows/ci.yml)
39
41
  [![PyPI](https://img.shields.io/pypi/v/opencode-python-sdk.svg)](https://pypi.org/project/opencode-python-sdk/)
42
+ [![Docs](https://img.shields.io/badge/docs-shrijayan.github.io-d9730d)](https://shrijayan.github.io/opencode-python-sdk/)
40
43
  [![Python](https://img.shields.io/pypi/pyversions/opencode-python-sdk.svg)](https://pypi.org/project/opencode-python-sdk/)
41
44
 
42
45
  Typed Python client for the [OpenCode](https://github.com/anomalyco/opencode) 2.x server API.
43
46
 
47
+ **Documentation: <https://shrijayan.github.io/opencode-python-sdk/>**
48
+
44
49
  > **Unofficial, community-maintained.** This package is not affiliated with or endorsed by the OpenCode team.
45
50
  > If the OpenCode maintainers want to take it over, we are happy to transfer this repository and the `opencode-python-sdk`
46
51
  > name on PyPI. Open an issue and we will hand it over.
@@ -201,6 +206,27 @@ Events are typed (`SessionCreatedEvent`, `SessionTextDeltaEvent`, and so on). Ev
201
206
  not know arrive as `UnknownEvent` with all their fields kept. Streams apply only the connect timeout by default, since
202
207
  they stay open between events.
203
208
 
209
+ ## Terminals
210
+
211
+ `client.pty.attach()` opens an interactive connection to a PTY over a WebSocket. It needs the `pty` extra:
212
+ `pip install "opencode-python-sdk[pty]"`.
213
+
214
+ ```python
215
+ pty = client.pty.create(command="/bin/sh").data
216
+ with client.pty.attach(pty.id) as term:
217
+ term.resize(120, 40)
218
+ term.send("echo hi\n")
219
+ for chunk in term: # output bytes, until the shell exits
220
+ print(chunk.decode(errors="replace"), end="")
221
+ ```
222
+
223
+ `recv(timeout=...)` reads one chunk and returns `None` once the terminal has ended. `term.cursor` holds the output
224
+ position to pass as `cursor=` when reattaching; `cursor=-1` skips the replay of earlier output. Persistent terminals
225
+ work the same way through `client.experimental.persistent_pty.attach(pty_id, role=..., takeover=...)`. The async
226
+ client returns `AsyncPtyConnection` (asyncio only): `async with await client.pty.attach(...) as term`. A connection
227
+ the server refuses or closes abnormally raises `PtyConnectionError`. See
228
+ [`examples/terminal.py`](examples/terminal.py) for a full TTY bridge.
229
+
204
230
  ## Errors
205
231
 
206
232
  Every error derives from `opencode.OpencodeError`. Errors the server declares are raised as their own class, with a
@@ -2,10 +2,13 @@
2
2
 
3
3
  [![CI](https://github.com/shrijayan/opencode-python-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/shrijayan/opencode-python-sdk/actions/workflows/ci.yml)
4
4
  [![PyPI](https://img.shields.io/pypi/v/opencode-python-sdk.svg)](https://pypi.org/project/opencode-python-sdk/)
5
+ [![Docs](https://img.shields.io/badge/docs-shrijayan.github.io-d9730d)](https://shrijayan.github.io/opencode-python-sdk/)
5
6
  [![Python](https://img.shields.io/pypi/pyversions/opencode-python-sdk.svg)](https://pypi.org/project/opencode-python-sdk/)
6
7
 
7
8
  Typed Python client for the [OpenCode](https://github.com/anomalyco/opencode) 2.x server API.
8
9
 
10
+ **Documentation: <https://shrijayan.github.io/opencode-python-sdk/>**
11
+
9
12
  > **Unofficial, community-maintained.** This package is not affiliated with or endorsed by the OpenCode team.
10
13
  > If the OpenCode maintainers want to take it over, we are happy to transfer this repository and the `opencode-python-sdk`
11
14
  > name on PyPI. Open an issue and we will hand it over.
@@ -166,6 +169,27 @@ Events are typed (`SessionCreatedEvent`, `SessionTextDeltaEvent`, and so on). Ev
166
169
  not know arrive as `UnknownEvent` with all their fields kept. Streams apply only the connect timeout by default, since
167
170
  they stay open between events.
168
171
 
172
+ ## Terminals
173
+
174
+ `client.pty.attach()` opens an interactive connection to a PTY over a WebSocket. It needs the `pty` extra:
175
+ `pip install "opencode-python-sdk[pty]"`.
176
+
177
+ ```python
178
+ pty = client.pty.create(command="/bin/sh").data
179
+ with client.pty.attach(pty.id) as term:
180
+ term.resize(120, 40)
181
+ term.send("echo hi\n")
182
+ for chunk in term: # output bytes, until the shell exits
183
+ print(chunk.decode(errors="replace"), end="")
184
+ ```
185
+
186
+ `recv(timeout=...)` reads one chunk and returns `None` once the terminal has ended. `term.cursor` holds the output
187
+ position to pass as `cursor=` when reattaching; `cursor=-1` skips the replay of earlier output. Persistent terminals
188
+ work the same way through `client.experimental.persistent_pty.attach(pty_id, role=..., takeover=...)`. The async
189
+ client returns `AsyncPtyConnection` (asyncio only): `async with await client.pty.attach(...) as term`. A connection
190
+ the server refuses or closes abnormally raises `PtyConnectionError`. See
191
+ [`examples/terminal.py`](examples/terminal.py) for a full TTY bridge.
192
+
169
193
  ## Errors
170
194
 
171
195
  Every error derives from `opencode.OpencodeError`. Errors the server declares are raised as their own class, with a
@@ -34,11 +34,16 @@ dependencies = [
34
34
 
35
35
  [project.urls]
36
36
  Homepage = "https://github.com/shrijayan/opencode-python-sdk"
37
- Documentation = "https://github.com/shrijayan/opencode-python-sdk#readme"
37
+ Documentation = "https://shrijayan.github.io/opencode-python-sdk/"
38
38
  Repository = "https://github.com/shrijayan/opencode-python-sdk"
39
39
  Issues = "https://github.com/shrijayan/opencode-python-sdk/issues"
40
40
  Changelog = "https://github.com/shrijayan/opencode-python-sdk/blob/main/CHANGELOG.md"
41
41
 
42
+ [project.optional-dependencies]
43
+ pty = [
44
+ "websockets>=14,<17",
45
+ ]
46
+
42
47
  [dependency-groups]
43
48
  dev = [
44
49
  "mypy>=1.18",
@@ -48,6 +53,11 @@ dev = [
48
53
  "respx>=0.22",
49
54
  "ruff>=0.14",
50
55
  "trio>=0.31",
56
+ "websockets>=14",
57
+ ]
58
+ docs = [
59
+ "mkdocs-material[imaging]>=9.6",
60
+ "mkdocstrings[python]>=0.30",
51
61
  ]
52
62
 
53
63
  [build-system]
@@ -93,6 +103,7 @@ src = ["src", "tests", "codegen"]
93
103
  select = [
94
104
  "B", # bugbear
95
105
  "C4", # comprehensions
106
+ "D1", # missing docstrings (public modules only; tests/test_docs_coverage.py covers the private runtime modules)
96
107
  "E", # pycodestyle errors
97
108
  "F", # pyflakes
98
109
  "FA", # future annotations
@@ -107,6 +118,8 @@ select = [
107
118
  "W", # pycodestyle warnings
108
119
  ]
109
120
  ignore = [
121
+ "D105", # magic methods
122
+ "D107", # __init__: arguments are documented on the class
110
123
  "E501", # line length is handled by the formatter
111
124
  "RUF022", # __all__ keeps a readable, grouped order
112
125
  ]
@@ -116,10 +129,12 @@ ignore = [
116
129
  "src/opencode/types/**" = ["E741", "TC"]
117
130
  "src/opencode/resources/**" = ["TC"]
118
131
  "src/opencode/_errors.py" = ["TC"]
119
- "codegen/**" = ["T20"]
120
- "scripts/**" = ["T20"]
121
- "examples/**" = ["T20"]
122
- "tests/**" = ["E501", "TC"]
132
+ # D1 applies to the published package only.
133
+ "codegen/**" = ["T20", "D1"]
134
+ "scripts/**" = ["T20", "D1"]
135
+ "examples/**" = ["T20", "D1"]
136
+ "tests/**" = ["E501", "TC", "D1"]
137
+ "docs/**" = ["D1"]
123
138
 
124
139
  [tool.ruff.lint.isort]
125
140
  known-first-party = ["opencode", "codegen"]
@@ -75,6 +75,7 @@ from ._exceptions import (
75
75
  )
76
76
  from ._models import BaseModel
77
77
  from ._pagination import AsyncCursorPage, AsyncPaginator, SyncCursorPage
78
+ from ._pty import AsyncPtyConnection, PtyConnection, PtyConnectionError
78
79
  from ._server import AsyncOpencodeServer, OpencodeServer, ServerStartError
79
80
  from ._streaming import AsyncStream, Stream
80
81
  from ._types import NOT_GIVEN, NotGiven
@@ -97,6 +98,7 @@ __all__ = [
97
98
  "AsyncOpencode",
98
99
  "AsyncOpencodeServer",
99
100
  "AsyncPaginator",
101
+ "AsyncPtyConnection",
100
102
  "AsyncStream",
101
103
  "AuthenticationError",
102
104
  "BadRequestError",
@@ -111,6 +113,8 @@ __all__ = [
111
113
  "OpencodeError",
112
114
  "OpencodeServer",
113
115
  "PermissionDeniedError",
116
+ "PtyConnection",
117
+ "PtyConnectionError",
114
118
  "RateLimitError",
115
119
  "ServerStartError",
116
120
  "ServiceUnavailableError",
@@ -147,47 +147,69 @@ class APIStatusError(APIError):
147
147
 
148
148
 
149
149
  class BadRequestError(APIStatusError):
150
+ """The server rejected the request as malformed (400)."""
151
+
150
152
  status = 400
151
153
 
152
154
 
153
155
  class AuthenticationError(APIStatusError):
156
+ """The password was missing or wrong (401)."""
157
+
154
158
  status = 401
155
159
 
156
160
 
157
161
  class PermissionDeniedError(APIStatusError):
162
+ """The request is not allowed (403)."""
163
+
158
164
  status = 403
159
165
 
160
166
 
161
167
  class NotFoundError(APIStatusError):
168
+ """The requested resource does not exist (404)."""
169
+
162
170
  status = 404
163
171
 
164
172
 
165
173
  class ConflictError(APIStatusError):
174
+ """The request conflicts with the current state, for example a busy session (409)."""
175
+
166
176
  status = 409
167
177
  tag = "ConflictError"
168
178
 
169
179
 
170
180
  class ContentTooLargeError(APIStatusError):
181
+ """The request body is too large (413)."""
182
+
171
183
  status = 413
172
184
 
173
185
 
174
186
  class UnprocessableEntityError(APIStatusError):
187
+ """The request was well formed but could not be processed (422)."""
188
+
175
189
  status = 422
176
190
 
177
191
 
178
192
  class RateLimitError(APIStatusError):
193
+ """Too many requests (429). Retried automatically, honoring ``Retry-After``."""
194
+
179
195
  status = 429
180
196
 
181
197
 
182
198
  class InternalServerError(APIStatusError):
199
+ """The server failed (500, and the base class for every 5xx)."""
200
+
183
201
  status = 500
184
202
 
185
203
 
186
204
  class NotImplementedServerError(InternalServerError):
205
+ """The server does not implement this endpoint (501)."""
206
+
187
207
  status = 501
188
208
 
189
209
 
190
210
  class ServiceUnavailableError(InternalServerError):
211
+ """The server is temporarily unavailable (503). Retried automatically."""
212
+
191
213
  status = 503
192
214
  tag = "ServiceUnavailableError"
193
215