From e9bdc09f7350b7cc766a4f50456a8d4ac64a5323 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 17 Jul 2025 19:21:52 +0000
Subject: [PATCH 01/50] feat(api): api update
---
.stats.yml | 4 +-
src/opencode_ai/resources/session.py | 20 +--
src/opencode_ai/types/__init__.py | 2 -
src/opencode_ai/types/config.py | 6 +-
src/opencode_ai/types/file_part_param.py | 25 ----
src/opencode_ai/types/keybinds_config.py | 5 +-
src/opencode_ai/types/mcp_remote_config.py | 5 +-
src/opencode_ai/types/session_chat_params.py | 48 +++++--
src/opencode_ai/types/text_part_param.py | 31 -----
tests/api_resources/test_session.py | 138 ++++++++++---------
10 files changed, 138 insertions(+), 146 deletions(-)
delete mode 100644 src/opencode_ai/types/file_part_param.py
delete mode 100644 src/opencode_ai/types/text_part_param.py
diff --git a/.stats.yml b/.stats.yml
index 22b27ac..bab7aeb 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-8792f91dd070f7b4ee671fc86e8a03976dc7fb6ee49f8c99ad989e1597003774.yml
-openapi_spec_hash: fe9dc3a074be560de0b97df9b5af2c1b
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-f9a2ce0fd0addc365614ef8c4bb1746f5ba14bc92f3d01f4cd85fb3b33a8d975.yml
+openapi_spec_hash: c58dec8e5250d41f216cded6afb763af
config_hash: b7f3d9742335715c458494988498b183
diff --git a/src/opencode_ai/resources/session.py b/src/opencode_ai/resources/session.py
index 087f3b4..8a3cb46 100644
--- a/src/opencode_ai/resources/session.py
+++ b/src/opencode_ai/resources/session.py
@@ -158,11 +158,12 @@ class SessionResource(SyncAPIResource):
self,
id: str,
*,
- message_id: str,
- mode: str,
model_id: str,
parts: Iterable[session_chat_params.Part],
provider_id: str,
+ session_id: str,
+ message_id: str | NotGiven = NOT_GIVEN,
+ mode: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -190,11 +191,12 @@ class SessionResource(SyncAPIResource):
f"/session/{id}/message",
body=maybe_transform(
{
- "message_id": message_id,
- "mode": mode,
"model_id": model_id,
"parts": parts,
"provider_id": provider_id,
+ "session_id": session_id,
+ "message_id": message_id,
+ "mode": mode,
},
session_chat_params.SessionChatParams,
),
@@ -524,11 +526,12 @@ class AsyncSessionResource(AsyncAPIResource):
self,
id: str,
*,
- message_id: str,
- mode: str,
model_id: str,
parts: Iterable[session_chat_params.Part],
provider_id: str,
+ session_id: str,
+ message_id: str | NotGiven = NOT_GIVEN,
+ mode: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -556,11 +559,12 @@ class AsyncSessionResource(AsyncAPIResource):
f"/session/{id}/message",
body=await async_maybe_transform(
{
- "message_id": message_id,
- "mode": mode,
"model_id": model_id,
"parts": parts,
"provider_id": provider_id,
+ "session_id": session_id,
+ "message_id": message_id,
+ "mode": mode,
},
session_chat_params.SessionChatParams,
),
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index f07c40b..801de7d 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -27,10 +27,8 @@ from .user_message import UserMessage as UserMessage
from .layout_config import LayoutConfig as LayoutConfig
from .snapshot_part import SnapshotPart as SnapshotPart
from .app_log_params import AppLogParams as AppLogParams
-from .file_part_param import FilePartParam as FilePartParam
from .keybinds_config import KeybindsConfig as KeybindsConfig
from .step_start_part import StepStartPart as StepStartPart
-from .text_part_param import TextPartParam as TextPartParam
from .app_log_response import AppLogResponse as AppLogResponse
from .file_read_params import FileReadParams as FileReadParams
from .find_text_params import FindTextParams as FindTextParams
diff --git a/src/opencode_ai/types/config.py b/src/opencode_ai/types/config.py
index 9f1490d..51a4792 100644
--- a/src/opencode_ai/types/config.py
+++ b/src/opencode_ai/types/config.py
@@ -162,10 +162,10 @@ class Config(BaseModel):
provider: Optional[Dict[str, Provider]] = None
"""Custom provider configurations and model overrides"""
- share: Optional[Literal["auto", "disabled"]] = None
+ share: Optional[Literal["manual", "auto", "disabled"]] = None
"""
- Control sharing behavior: 'auto' enables automatic sharing, 'disabled' disables
- all sharing
+ Control sharing behavior:'manual' allows manual sharing via commands, 'auto'
+ enables automatic sharing, 'disabled' disables all sharing
"""
theme: Optional[str] = None
diff --git a/src/opencode_ai/types/file_part_param.py b/src/opencode_ai/types/file_part_param.py
deleted file mode 100644
index bd219ec..0000000
--- a/src/opencode_ai/types/file_part_param.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["FilePartParam"]
-
-
-class FilePartParam(TypedDict, total=False):
- id: Required[str]
-
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- mime: Required[str]
-
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
- type: Required[Literal["file"]]
-
- url: Required[str]
-
- filename: str
diff --git a/src/opencode_ai/types/keybinds_config.py b/src/opencode_ai/types/keybinds_config.py
index 0513d8f..ca53231 100644
--- a/src/opencode_ai/types/keybinds_config.py
+++ b/src/opencode_ai/types/keybinds_config.py
@@ -105,7 +105,10 @@ class KeybindsConfig(BaseModel):
"""Unshare current session"""
switch_mode: str
- """Switch mode"""
+ """Next mode"""
+
+ switch_mode_reverse: str
+ """Previous Mode"""
theme_list: str
"""List available themes"""
diff --git a/src/opencode_ai/types/mcp_remote_config.py b/src/opencode_ai/types/mcp_remote_config.py
index ddbb7d4..6863ec7 100644
--- a/src/opencode_ai/types/mcp_remote_config.py
+++ b/src/opencode_ai/types/mcp_remote_config.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import Dict, Optional
from typing_extensions import Literal
from .._models import BaseModel
@@ -17,3 +17,6 @@ class McpRemoteConfig(BaseModel):
enabled: Optional[bool] = None
"""Enable or disable the MCP server on startup"""
+
+ headers: Optional[Dict[str, str]] = None
+ """Headers to send with the request"""
diff --git a/src/opencode_ai/types/session_chat_params.py b/src/opencode_ai/types/session_chat_params.py
index 51d2e2e..7475317 100644
--- a/src/opencode_ai/types/session_chat_params.py
+++ b/src/opencode_ai/types/session_chat_params.py
@@ -3,25 +3,55 @@
from __future__ import annotations
from typing import Union, Iterable
-from typing_extensions import Required, Annotated, TypeAlias, TypedDict
+from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
from .._utils import PropertyInfo
-from .file_part_param import FilePartParam
-from .text_part_param import TextPartParam
-__all__ = ["SessionChatParams", "Part"]
+__all__ = ["SessionChatParams", "Part", "PartUnionMember0", "PartUnionMember0Time", "PartUnionMember1"]
class SessionChatParams(TypedDict, total=False):
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- mode: Required[str]
-
model_id: Required[Annotated[str, PropertyInfo(alias="modelID")]]
parts: Required[Iterable[Part]]
provider_id: Required[Annotated[str, PropertyInfo(alias="providerID")]]
+ session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-Part: TypeAlias = Union[FilePartParam, TextPartParam]
+ message_id: Annotated[str, PropertyInfo(alias="messageID")]
+
+ mode: str
+
+
+class PartUnionMember0Time(TypedDict, total=False):
+ start: Required[float]
+
+ end: float
+
+
+class PartUnionMember0(TypedDict, total=False):
+ text: Required[str]
+
+ type: Required[Literal["text"]]
+
+ id: str
+
+ synthetic: bool
+
+ time: PartUnionMember0Time
+
+
+class PartUnionMember1(TypedDict, total=False):
+ mime: Required[str]
+
+ type: Required[Literal["file"]]
+
+ url: Required[str]
+
+ id: str
+
+ filename: str
+
+
+Part: TypeAlias = Union[PartUnionMember0, PartUnionMember1]
diff --git a/src/opencode_ai/types/text_part_param.py b/src/opencode_ai/types/text_part_param.py
deleted file mode 100644
index 3129256..0000000
--- a/src/opencode_ai/types/text_part_param.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["TextPartParam", "Time"]
-
-
-class Time(TypedDict, total=False):
- start: Required[float]
-
- end: float
-
-
-class TextPartParam(TypedDict, total=False):
- id: Required[str]
-
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
- text: Required[str]
-
- type: Required[Literal["text"]]
-
- synthetic: bool
-
- time: Time
diff --git a/tests/api_resources/test_session.py b/tests/api_resources/test_session.py
index 379cde4..670c501 100644
--- a/tests/api_resources/test_session.py
+++ b/tests/api_resources/test_session.py
@@ -171,20 +171,40 @@ class TestSession:
def test_method_chat(self, client: Opencode) -> None:
session = client.session.chat(
id="id",
- message_id="messageID",
- mode="mode",
model_id="modelID",
parts=[
{
- "id": "id",
- "message_id": "messageID",
- "mime": "mime",
- "session_id": "sessionID",
- "type": "file",
- "url": "url",
+ "text": "text",
+ "type": "text",
}
],
provider_id="providerID",
+ session_id="ses",
+ )
+ assert_matches_type(AssistantMessage, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_chat_with_all_params(self, client: Opencode) -> None:
+ session = client.session.chat(
+ id="id",
+ model_id="modelID",
+ parts=[
+ {
+ "text": "text",
+ "type": "text",
+ "id": "id",
+ "synthetic": True,
+ "time": {
+ "start": 0,
+ "end": 0,
+ },
+ }
+ ],
+ provider_id="providerID",
+ session_id="ses",
+ message_id="msg",
+ mode="mode",
)
assert_matches_type(AssistantMessage, session, path=["response"])
@@ -193,20 +213,15 @@ class TestSession:
def test_raw_response_chat(self, client: Opencode) -> None:
response = client.session.with_raw_response.chat(
id="id",
- message_id="messageID",
- mode="mode",
model_id="modelID",
parts=[
{
- "id": "id",
- "message_id": "messageID",
- "mime": "mime",
- "session_id": "sessionID",
- "type": "file",
- "url": "url",
+ "text": "text",
+ "type": "text",
}
],
provider_id="providerID",
+ session_id="ses",
)
assert response.is_closed is True
@@ -219,20 +234,15 @@ class TestSession:
def test_streaming_response_chat(self, client: Opencode) -> None:
with client.session.with_streaming_response.chat(
id="id",
- message_id="messageID",
- mode="mode",
model_id="modelID",
parts=[
{
- "id": "id",
- "message_id": "messageID",
- "mime": "mime",
- "session_id": "sessionID",
- "type": "file",
- "url": "url",
+ "text": "text",
+ "type": "text",
}
],
provider_id="providerID",
+ session_id="ses",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -248,20 +258,15 @@ class TestSession:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
client.session.with_raw_response.chat(
id="",
- message_id="messageID",
- mode="mode",
model_id="modelID",
parts=[
{
- "id": "id",
- "message_id": "messageID",
- "mime": "mime",
- "session_id": "sessionID",
- "type": "file",
- "url": "url",
+ "text": "text",
+ "type": "text",
}
],
provider_id="providerID",
+ session_id="ses",
)
@pytest.mark.skip()
@@ -645,20 +650,40 @@ class TestAsyncSession:
async def test_method_chat(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.chat(
id="id",
- message_id="messageID",
- mode="mode",
model_id="modelID",
parts=[
{
- "id": "id",
- "message_id": "messageID",
- "mime": "mime",
- "session_id": "sessionID",
- "type": "file",
- "url": "url",
+ "text": "text",
+ "type": "text",
}
],
provider_id="providerID",
+ session_id="ses",
+ )
+ assert_matches_type(AssistantMessage, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_chat_with_all_params(self, async_client: AsyncOpencode) -> None:
+ session = await async_client.session.chat(
+ id="id",
+ model_id="modelID",
+ parts=[
+ {
+ "text": "text",
+ "type": "text",
+ "id": "id",
+ "synthetic": True,
+ "time": {
+ "start": 0,
+ "end": 0,
+ },
+ }
+ ],
+ provider_id="providerID",
+ session_id="ses",
+ message_id="msg",
+ mode="mode",
)
assert_matches_type(AssistantMessage, session, path=["response"])
@@ -667,20 +692,15 @@ class TestAsyncSession:
async def test_raw_response_chat(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.chat(
id="id",
- message_id="messageID",
- mode="mode",
model_id="modelID",
parts=[
{
- "id": "id",
- "message_id": "messageID",
- "mime": "mime",
- "session_id": "sessionID",
- "type": "file",
- "url": "url",
+ "text": "text",
+ "type": "text",
}
],
provider_id="providerID",
+ session_id="ses",
)
assert response.is_closed is True
@@ -693,20 +713,15 @@ class TestAsyncSession:
async def test_streaming_response_chat(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.chat(
id="id",
- message_id="messageID",
- mode="mode",
model_id="modelID",
parts=[
{
- "id": "id",
- "message_id": "messageID",
- "mime": "mime",
- "session_id": "sessionID",
- "type": "file",
- "url": "url",
+ "text": "text",
+ "type": "text",
}
],
provider_id="providerID",
+ session_id="ses",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -722,20 +737,15 @@ class TestAsyncSession:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
await async_client.session.with_raw_response.chat(
id="",
- message_id="messageID",
- mode="mode",
model_id="modelID",
parts=[
{
- "id": "id",
- "message_id": "messageID",
- "mime": "mime",
- "session_id": "sessionID",
- "type": "file",
- "url": "url",
+ "text": "text",
+ "type": "text",
}
],
provider_id="providerID",
+ session_id="ses",
)
@pytest.mark.skip()
From 23ee4bb2799c12a8496f94a7a64ed5895f7348e8 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 17 Jul 2025 19:22:09 +0000
Subject: [PATCH 02/50] release: 0.1.0-alpha.20
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index b386bef..fac1407 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.19"
+ ".": "0.1.0-alpha.20"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 36c737a..9420e1a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.20 (2025-07-17)
+
+Full Changelog: [v0.1.0-alpha.19...v0.1.0-alpha.20](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.19...v0.1.0-alpha.20)
+
+### Features
+
+* **api:** api update ([f48c0d6](https://github.com/sst/opencode-sdk-python/commit/f48c0d6bb1943df3e3758d19b83c70fd1c15e2c2))
+
## 0.1.0-alpha.19 (2025-07-16)
Full Changelog: [v0.1.0-alpha.18...v0.1.0-alpha.19](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.18...v0.1.0-alpha.19)
diff --git a/pyproject.toml b/pyproject.toml
index a0d2553..420f74f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.19"
+version = "0.1.0-alpha.20"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 0e1e5de..ac3c99b 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.19" # x-release-please-version
+__version__ = "0.1.0-alpha.20" # x-release-please-version
From a617d3359fd8e9f4bb0dd0af6637baee4b183811 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 17 Jul 2025 19:25:06 +0000
Subject: [PATCH 03/50] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index bab7aeb..d1665dd 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-f9a2ce0fd0addc365614ef8c4bb1746f5ba14bc92f3d01f4cd85fb3b33a8d975.yml
-openapi_spec_hash: c58dec8e5250d41f216cded6afb763af
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-68cbf6e18d22079b425afcaed2bd8f3e6d728aeded96ea31261e81acf2664895.yml
+openapi_spec_hash: 1e2f53491687817ec77f4929b469ce29
config_hash: b7f3d9742335715c458494988498b183
From 5e3dae765d648cd83d5bb13ab317b03f553b8558 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 17 Jul 2025 19:29:37 +0000
Subject: [PATCH 04/50] feat(api): api update
---
.stats.yml | 6 +--
api.md | 2 +
src/opencode_ai/types/__init__.py | 2 +
.../types/file_part_input_param.py | 19 ++++++++++
src/opencode_ai/types/session_chat_params.py | 38 +++----------------
.../types/text_part_input_param.py | 25 ++++++++++++
6 files changed, 56 insertions(+), 36 deletions(-)
create mode 100644 src/opencode_ai/types/file_part_input_param.py
create mode 100644 src/opencode_ai/types/text_part_input_param.py
diff --git a/.stats.yml b/.stats.yml
index d1665dd..5ccf547 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-68cbf6e18d22079b425afcaed2bd8f3e6d728aeded96ea31261e81acf2664895.yml
-openapi_spec_hash: 1e2f53491687817ec77f4929b469ce29
-config_hash: b7f3d9742335715c458494988498b183
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-186e713234760e9f755b35c78809f89378e4f778a451cd5e30649f41489e0bfd.yml
+openapi_spec_hash: 5fb2ce9d8055253d597567a8a3293e73
+config_hash: a8441af7cb2db855d79fd372ee3b9fb1
diff --git a/api.md b/api.md
index 8ba2145..917b959 100644
--- a/api.md
+++ b/api.md
@@ -102,6 +102,7 @@ Types:
from opencode_ai.types import (
AssistantMessage,
FilePart,
+ FilePartInput,
Message,
Part,
Session,
@@ -109,6 +110,7 @@ from opencode_ai.types import (
StepFinishPart,
StepStartPart,
TextPart,
+ TextPartInput,
ToolPart,
ToolStateCompleted,
ToolStateError,
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index 801de7d..58c00ae 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -51,9 +51,11 @@ from .session_chat_params import SessionChatParams as SessionChatParams
from .session_init_params import SessionInitParams as SessionInitParams
from .file_status_response import FileStatusResponse as FileStatusResponse
from .tool_state_completed import ToolStateCompleted as ToolStateCompleted
+from .file_part_input_param import FilePartInputParam as FilePartInputParam
from .find_symbols_response import FindSymbolsResponse as FindSymbolsResponse
from .session_init_response import SessionInitResponse as SessionInitResponse
from .session_list_response import SessionListResponse as SessionListResponse
+from .text_part_input_param import TextPartInputParam as TextPartInputParam
from .app_providers_response import AppProvidersResponse as AppProvidersResponse
from .session_abort_response import SessionAbortResponse as SessionAbortResponse
from .session_delete_response import SessionDeleteResponse as SessionDeleteResponse
diff --git a/src/opencode_ai/types/file_part_input_param.py b/src/opencode_ai/types/file_part_input_param.py
new file mode 100644
index 0000000..53002cc
--- /dev/null
+++ b/src/opencode_ai/types/file_part_input_param.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["FilePartInputParam"]
+
+
+class FilePartInputParam(TypedDict, total=False):
+ mime: Required[str]
+
+ type: Required[Literal["file"]]
+
+ url: Required[str]
+
+ id: str
+
+ filename: str
diff --git a/src/opencode_ai/types/session_chat_params.py b/src/opencode_ai/types/session_chat_params.py
index 7475317..1d2bc4b 100644
--- a/src/opencode_ai/types/session_chat_params.py
+++ b/src/opencode_ai/types/session_chat_params.py
@@ -3,11 +3,13 @@
from __future__ import annotations
from typing import Union, Iterable
-from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
+from typing_extensions import Required, Annotated, TypeAlias, TypedDict
from .._utils import PropertyInfo
+from .file_part_input_param import FilePartInputParam
+from .text_part_input_param import TextPartInputParam
-__all__ = ["SessionChatParams", "Part", "PartUnionMember0", "PartUnionMember0Time", "PartUnionMember1"]
+__all__ = ["SessionChatParams", "Part"]
class SessionChatParams(TypedDict, total=False):
@@ -24,34 +26,4 @@ class SessionChatParams(TypedDict, total=False):
mode: str
-class PartUnionMember0Time(TypedDict, total=False):
- start: Required[float]
-
- end: float
-
-
-class PartUnionMember0(TypedDict, total=False):
- text: Required[str]
-
- type: Required[Literal["text"]]
-
- id: str
-
- synthetic: bool
-
- time: PartUnionMember0Time
-
-
-class PartUnionMember1(TypedDict, total=False):
- mime: Required[str]
-
- type: Required[Literal["file"]]
-
- url: Required[str]
-
- id: str
-
- filename: str
-
-
-Part: TypeAlias = Union[PartUnionMember0, PartUnionMember1]
+Part: TypeAlias = Union[TextPartInputParam, FilePartInputParam]
diff --git a/src/opencode_ai/types/text_part_input_param.py b/src/opencode_ai/types/text_part_input_param.py
new file mode 100644
index 0000000..2850484
--- /dev/null
+++ b/src/opencode_ai/types/text_part_input_param.py
@@ -0,0 +1,25 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["TextPartInputParam", "Time"]
+
+
+class Time(TypedDict, total=False):
+ start: Required[float]
+
+ end: float
+
+
+class TextPartInputParam(TypedDict, total=False):
+ text: Required[str]
+
+ type: Required[Literal["text"]]
+
+ id: str
+
+ synthetic: bool
+
+ time: Time
From 5ae45651bd4168f398650123f2e48c89017533f3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 17 Jul 2025 19:29:52 +0000
Subject: [PATCH 05/50] release: 0.1.0-alpha.21
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index fac1407..7c31fce 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.20"
+ ".": "0.1.0-alpha.21"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9420e1a..2281cd3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.21 (2025-07-17)
+
+Full Changelog: [v0.1.0-alpha.20...v0.1.0-alpha.21](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.20...v0.1.0-alpha.21)
+
+### Features
+
+* **api:** api update ([71211e8](https://github.com/sst/opencode-sdk-python/commit/71211e888ecd5e848ac4de5ed058e4756025f694))
+
## 0.1.0-alpha.20 (2025-07-17)
Full Changelog: [v0.1.0-alpha.19...v0.1.0-alpha.20](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.19...v0.1.0-alpha.20)
diff --git a/pyproject.toml b/pyproject.toml
index 420f74f..06248ca 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.20"
+version = "0.1.0-alpha.21"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index ac3c99b..2d60c92 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.20" # x-release-please-version
+__version__ = "0.1.0-alpha.21" # x-release-please-version
From d19014d3917eaa7d09cd5183092fd8cc49bef34d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 17 Jul 2025 19:40:10 +0000
Subject: [PATCH 06/50] feat(api): api update
---
.stats.yml | 4 ++--
src/opencode_ai/resources/session.py | 4 ----
src/opencode_ai/types/session_chat_params.py | 2 --
tests/api_resources/test_session.py | 10 ----------
4 files changed, 2 insertions(+), 18 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 5ccf547..0f1eb3f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-186e713234760e9f755b35c78809f89378e4f778a451cd5e30649f41489e0bfd.yml
-openapi_spec_hash: 5fb2ce9d8055253d597567a8a3293e73
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-d34620b462127c45497743c97fd3569f9e629d9fbd97c0707087eeddbd4b3de1.yml
+openapi_spec_hash: 23864c98d555350fe56f1d0e56f205c5
config_hash: a8441af7cb2db855d79fd372ee3b9fb1
diff --git a/src/opencode_ai/resources/session.py b/src/opencode_ai/resources/session.py
index 8a3cb46..472dfe0 100644
--- a/src/opencode_ai/resources/session.py
+++ b/src/opencode_ai/resources/session.py
@@ -161,7 +161,6 @@ class SessionResource(SyncAPIResource):
model_id: str,
parts: Iterable[session_chat_params.Part],
provider_id: str,
- session_id: str,
message_id: str | NotGiven = NOT_GIVEN,
mode: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -194,7 +193,6 @@ class SessionResource(SyncAPIResource):
"model_id": model_id,
"parts": parts,
"provider_id": provider_id,
- "session_id": session_id,
"message_id": message_id,
"mode": mode,
},
@@ -529,7 +527,6 @@ class AsyncSessionResource(AsyncAPIResource):
model_id: str,
parts: Iterable[session_chat_params.Part],
provider_id: str,
- session_id: str,
message_id: str | NotGiven = NOT_GIVEN,
mode: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -562,7 +559,6 @@ class AsyncSessionResource(AsyncAPIResource):
"model_id": model_id,
"parts": parts,
"provider_id": provider_id,
- "session_id": session_id,
"message_id": message_id,
"mode": mode,
},
diff --git a/src/opencode_ai/types/session_chat_params.py b/src/opencode_ai/types/session_chat_params.py
index 1d2bc4b..f9dfee5 100644
--- a/src/opencode_ai/types/session_chat_params.py
+++ b/src/opencode_ai/types/session_chat_params.py
@@ -19,8 +19,6 @@ class SessionChatParams(TypedDict, total=False):
provider_id: Required[Annotated[str, PropertyInfo(alias="providerID")]]
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
message_id: Annotated[str, PropertyInfo(alias="messageID")]
mode: str
diff --git a/tests/api_resources/test_session.py b/tests/api_resources/test_session.py
index 670c501..644f9a7 100644
--- a/tests/api_resources/test_session.py
+++ b/tests/api_resources/test_session.py
@@ -179,7 +179,6 @@ class TestSession:
}
],
provider_id="providerID",
- session_id="ses",
)
assert_matches_type(AssistantMessage, session, path=["response"])
@@ -202,7 +201,6 @@ class TestSession:
}
],
provider_id="providerID",
- session_id="ses",
message_id="msg",
mode="mode",
)
@@ -221,7 +219,6 @@ class TestSession:
}
],
provider_id="providerID",
- session_id="ses",
)
assert response.is_closed is True
@@ -242,7 +239,6 @@ class TestSession:
}
],
provider_id="providerID",
- session_id="ses",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -266,7 +262,6 @@ class TestSession:
}
],
provider_id="providerID",
- session_id="ses",
)
@pytest.mark.skip()
@@ -658,7 +653,6 @@ class TestAsyncSession:
}
],
provider_id="providerID",
- session_id="ses",
)
assert_matches_type(AssistantMessage, session, path=["response"])
@@ -681,7 +675,6 @@ class TestAsyncSession:
}
],
provider_id="providerID",
- session_id="ses",
message_id="msg",
mode="mode",
)
@@ -700,7 +693,6 @@ class TestAsyncSession:
}
],
provider_id="providerID",
- session_id="ses",
)
assert response.is_closed is True
@@ -721,7 +713,6 @@ class TestAsyncSession:
}
],
provider_id="providerID",
- session_id="ses",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -745,7 +736,6 @@ class TestAsyncSession:
}
],
provider_id="providerID",
- session_id="ses",
)
@pytest.mark.skip()
From 002bf2d57f89429cfab3c92a8d95745041f0c7d5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 17 Jul 2025 19:40:26 +0000
Subject: [PATCH 07/50] release: 0.1.0-alpha.22
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 7c31fce..aa84875 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.21"
+ ".": "0.1.0-alpha.22"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2281cd3..91054ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.22 (2025-07-17)
+
+Full Changelog: [v0.1.0-alpha.21...v0.1.0-alpha.22](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.21...v0.1.0-alpha.22)
+
+### Features
+
+* **api:** api update ([582070a](https://github.com/sst/opencode-sdk-python/commit/582070ae69b0ae1088271038b0fcb818c30c74cf))
+
## 0.1.0-alpha.21 (2025-07-17)
Full Changelog: [v0.1.0-alpha.20...v0.1.0-alpha.21](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.20...v0.1.0-alpha.21)
diff --git a/pyproject.toml b/pyproject.toml
index 06248ca..9d81585 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.21"
+version = "0.1.0-alpha.22"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 2d60c92..e09499b 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.21" # x-release-please-version
+__version__ = "0.1.0-alpha.22" # x-release-please-version
From 5f542aa68e3daf759ca50697671ce20339b1169b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 18 Jul 2025 17:46:15 +0000
Subject: [PATCH 08/50] feat(api): api update
---
.stats.yml | 6 +++---
api.md | 9 +--------
src/opencode_ai/types/__init__.py | 1 -
src/opencode_ai/types/config.py | 5 ++---
src/opencode_ai/types/layout_config.py | 7 -------
5 files changed, 6 insertions(+), 22 deletions(-)
delete mode 100644 src/opencode_ai/types/layout_config.py
diff --git a/.stats.yml b/.stats.yml
index 0f1eb3f..02591cb 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-d34620b462127c45497743c97fd3569f9e629d9fbd97c0707087eeddbd4b3de1.yml
-openapi_spec_hash: 23864c98d555350fe56f1d0e56f205c5
-config_hash: a8441af7cb2db855d79fd372ee3b9fb1
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-a1da357fcefd3105736841fbf44018022fade78e67ffc81e178cf9196da723ee.yml
+openapi_spec_hash: 9bd27afcc5b8f43d8e4223f7c984035f
+config_hash: 62b73a3397120578a992bffd1e69386a
diff --git a/api.md b/api.md
index 917b959..dddb269 100644
--- a/api.md
+++ b/api.md
@@ -80,14 +80,7 @@ Methods:
Types:
```python
-from opencode_ai.types import (
- Config,
- KeybindsConfig,
- LayoutConfig,
- McpLocalConfig,
- McpRemoteConfig,
- ModeConfig,
-)
+from opencode_ai.types import Config, KeybindsConfig, McpLocalConfig, McpRemoteConfig, ModeConfig
```
Methods:
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index 58c00ae..f5d4e4a 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -24,7 +24,6 @@ from .text_part import TextPart as TextPart
from .tool_part import ToolPart as ToolPart
from .mode_config import ModeConfig as ModeConfig
from .user_message import UserMessage as UserMessage
-from .layout_config import LayoutConfig as LayoutConfig
from .snapshot_part import SnapshotPart as SnapshotPart
from .app_log_params import AppLogParams as AppLogParams
from .keybinds_config import KeybindsConfig as KeybindsConfig
diff --git a/src/opencode_ai/types/config.py b/src/opencode_ai/types/config.py
index 51a4792..19963ad 100644
--- a/src/opencode_ai/types/config.py
+++ b/src/opencode_ai/types/config.py
@@ -9,7 +9,6 @@ from .._utils import PropertyInfo
from .._models import BaseModel
from .log_level import LogLevel
from .mode_config import ModeConfig
-from .layout_config import LayoutConfig
from .keybinds_config import KeybindsConfig
from .mcp_local_config import McpLocalConfig
from .mcp_remote_config import McpRemoteConfig
@@ -144,8 +143,8 @@ class Config(BaseModel):
keybinds: Optional[KeybindsConfig] = None
"""Custom keybind configurations"""
- layout: Optional[LayoutConfig] = None
- """Layout to use for the TUI"""
+ layout: Optional[Literal["auto", "stretch"]] = None
+ """@deprecated Always uses stretch layout."""
log_level: Optional[LogLevel] = None
"""Minimum log level to write to log files"""
diff --git a/src/opencode_ai/types/layout_config.py b/src/opencode_ai/types/layout_config.py
deleted file mode 100644
index 99b69ee..0000000
--- a/src/opencode_ai/types/layout_config.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import Literal, TypeAlias
-
-__all__ = ["LayoutConfig"]
-
-LayoutConfig: TypeAlias = Literal["auto", "stretch"]
From 06577e968562005fafdd9f48e0a48baedc6ca99a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 18 Jul 2025 17:46:31 +0000
Subject: [PATCH 09/50] release: 0.1.0-alpha.23
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index aa84875..1c0bb88 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.22"
+ ".": "0.1.0-alpha.23"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 91054ee..e892995 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.23 (2025-07-18)
+
+Full Changelog: [v0.1.0-alpha.22...v0.1.0-alpha.23](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.22...v0.1.0-alpha.23)
+
+### Features
+
+* **api:** api update ([d8c9fc9](https://github.com/sst/opencode-sdk-python/commit/d8c9fc984c48b7dadce8840c5c1e010a508d58b4))
+
## 0.1.0-alpha.22 (2025-07-17)
Full Changelog: [v0.1.0-alpha.21...v0.1.0-alpha.22](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.21...v0.1.0-alpha.22)
diff --git a/pyproject.toml b/pyproject.toml
index 9d81585..55a9f68 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.22"
+version = "0.1.0-alpha.23"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index e09499b..3ac2a7b 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.22" # x-release-please-version
+__version__ = "0.1.0-alpha.23" # x-release-please-version
From e2e1f1d3844dc6152d52b52c342627de77a68f0b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 22:39:56 +0000
Subject: [PATCH 10/50] feat(api): api update
---
.stats.yml | 6 +--
api.md | 5 ++-
src/opencode_ai/resources/session.py | 6 ++-
src/opencode_ai/types/__init__.py | 9 +++-
src/opencode_ai/types/config.py | 10 +++--
src/opencode_ai/types/file_part.py | 3 ++
.../types/file_part_input_param.py | 4 ++
src/opencode_ai/types/file_part_source.py | 12 ++++++
.../types/file_part_source_param.py | 13 ++++++
.../types/file_part_source_text.py | 13 ++++++
.../types/file_part_source_text_param.py | 15 +++++++
src/opencode_ai/types/file_source.py | 16 ++++++++
src/opencode_ai/types/file_source_param.py | 17 ++++++++
src/opencode_ai/types/log_level.py | 7 ----
src/opencode_ai/types/session_chat_params.py | 4 +-
src/opencode_ai/types/symbol_source.py | 40 ++++++++++++++++++
src/opencode_ai/types/symbol_source_param.py | 41 +++++++++++++++++++
tests/api_resources/test_session.py | 2 +
18 files changed, 205 insertions(+), 18 deletions(-)
create mode 100644 src/opencode_ai/types/file_part_source.py
create mode 100644 src/opencode_ai/types/file_part_source_param.py
create mode 100644 src/opencode_ai/types/file_part_source_text.py
create mode 100644 src/opencode_ai/types/file_part_source_text_param.py
create mode 100644 src/opencode_ai/types/file_source.py
create mode 100644 src/opencode_ai/types/file_source_param.py
delete mode 100644 src/opencode_ai/types/log_level.py
create mode 100644 src/opencode_ai/types/symbol_source.py
create mode 100644 src/opencode_ai/types/symbol_source_param.py
diff --git a/.stats.yml b/.stats.yml
index 02591cb..32b1351 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-a1da357fcefd3105736841fbf44018022fade78e67ffc81e178cf9196da723ee.yml
-openapi_spec_hash: 9bd27afcc5b8f43d8e4223f7c984035f
-config_hash: 62b73a3397120578a992bffd1e69386a
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-5e3b108daef12bb43f728ee42261cd1322e8909e6225db58d6fe0617f3b5904c.yml
+openapi_spec_hash: 1f9d2853ba0c1179e45426560e082ef4
+config_hash: 6d56a7ca0d6ed899ecdb5c053a8278ae
diff --git a/api.md b/api.md
index dddb269..e8f80d9 100644
--- a/api.md
+++ b/api.md
@@ -23,7 +23,6 @@ Types:
```python
from opencode_ai.types import (
App,
- LogLevel,
Mode,
Model,
Provider,
@@ -96,12 +95,16 @@ from opencode_ai.types import (
AssistantMessage,
FilePart,
FilePartInput,
+ FilePartSource,
+ FilePartSourceText,
+ FileSource,
Message,
Part,
Session,
SnapshotPart,
StepFinishPart,
StepStartPart,
+ SymbolSource,
TextPart,
TextPartInput,
ToolPart,
diff --git a/src/opencode_ai/resources/session.py b/src/opencode_ai/resources/session.py
index 472dfe0..baf2060 100644
--- a/src/opencode_ai/resources/session.py
+++ b/src/opencode_ai/resources/session.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Iterable
+from typing import Dict, Iterable
import httpx
@@ -163,6 +163,7 @@ class SessionResource(SyncAPIResource):
provider_id: str,
message_id: str | NotGiven = NOT_GIVEN,
mode: str | NotGiven = NOT_GIVEN,
+ tools: Dict[str, bool] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -195,6 +196,7 @@ class SessionResource(SyncAPIResource):
"provider_id": provider_id,
"message_id": message_id,
"mode": mode,
+ "tools": tools,
},
session_chat_params.SessionChatParams,
),
@@ -529,6 +531,7 @@ class AsyncSessionResource(AsyncAPIResource):
provider_id: str,
message_id: str | NotGiven = NOT_GIVEN,
mode: str | NotGiven = NOT_GIVEN,
+ tools: Dict[str, bool] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -561,6 +564,7 @@ class AsyncSessionResource(AsyncAPIResource):
"provider_id": provider_id,
"message_id": message_id,
"mode": mode,
+ "tools": tools,
},
session_chat_params.SessionChatParams,
),
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index f5d4e4a..5151b92 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -19,16 +19,18 @@ from .message import Message as Message
from .session import Session as Session
from .provider import Provider as Provider
from .file_part import FilePart as FilePart
-from .log_level import LogLevel as LogLevel
from .text_part import TextPart as TextPart
from .tool_part import ToolPart as ToolPart
+from .file_source import FileSource as FileSource
from .mode_config import ModeConfig as ModeConfig
from .user_message import UserMessage as UserMessage
from .snapshot_part import SnapshotPart as SnapshotPart
+from .symbol_source import SymbolSource as SymbolSource
from .app_log_params import AppLogParams as AppLogParams
from .keybinds_config import KeybindsConfig as KeybindsConfig
from .step_start_part import StepStartPart as StepStartPart
from .app_log_response import AppLogResponse as AppLogResponse
+from .file_part_source import FilePartSource as FilePartSource
from .file_read_params import FileReadParams as FileReadParams
from .find_text_params import FindTextParams as FindTextParams
from .mcp_local_config import McpLocalConfig as McpLocalConfig
@@ -36,6 +38,7 @@ from .step_finish_part import StepFinishPart as StepFinishPart
from .tool_state_error import ToolStateError as ToolStateError
from .app_init_response import AppInitResponse as AppInitResponse
from .assistant_message import AssistantMessage as AssistantMessage
+from .file_source_param import FileSourceParam as FileSourceParam
from .find_files_params import FindFilesParams as FindFilesParams
from .mcp_remote_config import McpRemoteConfig as McpRemoteConfig
from .app_modes_response import AppModesResponse as AppModesResponse
@@ -48,16 +51,20 @@ from .find_files_response import FindFilesResponse as FindFilesResponse
from .find_symbols_params import FindSymbolsParams as FindSymbolsParams
from .session_chat_params import SessionChatParams as SessionChatParams
from .session_init_params import SessionInitParams as SessionInitParams
+from .symbol_source_param import SymbolSourceParam as SymbolSourceParam
from .file_status_response import FileStatusResponse as FileStatusResponse
from .tool_state_completed import ToolStateCompleted as ToolStateCompleted
from .file_part_input_param import FilePartInputParam as FilePartInputParam
+from .file_part_source_text import FilePartSourceText as FilePartSourceText
from .find_symbols_response import FindSymbolsResponse as FindSymbolsResponse
from .session_init_response import SessionInitResponse as SessionInitResponse
from .session_list_response import SessionListResponse as SessionListResponse
from .text_part_input_param import TextPartInputParam as TextPartInputParam
from .app_providers_response import AppProvidersResponse as AppProvidersResponse
+from .file_part_source_param import FilePartSourceParam as FilePartSourceParam
from .session_abort_response import SessionAbortResponse as SessionAbortResponse
from .session_delete_response import SessionDeleteResponse as SessionDeleteResponse
from .session_summarize_params import SessionSummarizeParams as SessionSummarizeParams
from .session_messages_response import SessionMessagesResponse as SessionMessagesResponse
from .session_summarize_response import SessionSummarizeResponse as SessionSummarizeResponse
+from .file_part_source_text_param import FilePartSourceTextParam as FilePartSourceTextParam
diff --git a/src/opencode_ai/types/config.py b/src/opencode_ai/types/config.py
index 19963ad..927bfc5 100644
--- a/src/opencode_ai/types/config.py
+++ b/src/opencode_ai/types/config.py
@@ -7,7 +7,6 @@ from pydantic import Field as FieldInfo
from .._utils import PropertyInfo
from .._models import BaseModel
-from .log_level import LogLevel
from .mode_config import ModeConfig
from .keybinds_config import KeybindsConfig
from .mcp_local_config import McpLocalConfig
@@ -146,9 +145,6 @@ class Config(BaseModel):
layout: Optional[Literal["auto", "stretch"]] = None
"""@deprecated Always uses stretch layout."""
- log_level: Optional[LogLevel] = None
- """Minimum log level to write to log files"""
-
mcp: Optional[Dict[str, Mcp]] = None
"""MCP (Model Context Protocol) server configurations"""
@@ -167,6 +163,12 @@ class Config(BaseModel):
enables automatic sharing, 'disabled' disables all sharing
"""
+ small_model: Optional[str] = None
+ """
+ Small model to use for tasks like summarization and title generation in the
+ format of provider/model
+ """
+
theme: Optional[str] = None
"""Theme name to use for the interface"""
diff --git a/src/opencode_ai/types/file_part.py b/src/opencode_ai/types/file_part.py
index a4b9934..42851c9 100644
--- a/src/opencode_ai/types/file_part.py
+++ b/src/opencode_ai/types/file_part.py
@@ -6,6 +6,7 @@ from typing_extensions import Literal
from pydantic import Field as FieldInfo
from .._models import BaseModel
+from .file_part_source import FilePartSource
__all__ = ["FilePart"]
@@ -24,3 +25,5 @@ class FilePart(BaseModel):
url: str
filename: Optional[str] = None
+
+ source: Optional[FilePartSource] = None
diff --git a/src/opencode_ai/types/file_part_input_param.py b/src/opencode_ai/types/file_part_input_param.py
index 53002cc..96325e0 100644
--- a/src/opencode_ai/types/file_part_input_param.py
+++ b/src/opencode_ai/types/file_part_input_param.py
@@ -4,6 +4,8 @@ from __future__ import annotations
from typing_extensions import Literal, Required, TypedDict
+from .file_part_source_param import FilePartSourceParam
+
__all__ = ["FilePartInputParam"]
@@ -17,3 +19,5 @@ class FilePartInputParam(TypedDict, total=False):
id: str
filename: str
+
+ source: FilePartSourceParam
diff --git a/src/opencode_ai/types/file_part_source.py b/src/opencode_ai/types/file_part_source.py
new file mode 100644
index 0000000..25cb97d
--- /dev/null
+++ b/src/opencode_ai/types/file_part_source.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union
+from typing_extensions import Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .file_source import FileSource
+from .symbol_source import SymbolSource
+
+__all__ = ["FilePartSource"]
+
+FilePartSource: TypeAlias = Annotated[Union[FileSource, SymbolSource], PropertyInfo(discriminator="type")]
diff --git a/src/opencode_ai/types/file_part_source_param.py b/src/opencode_ai/types/file_part_source_param.py
new file mode 100644
index 0000000..7b5bcbb
--- /dev/null
+++ b/src/opencode_ai/types/file_part_source_param.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from typing_extensions import TypeAlias
+
+from .file_source_param import FileSourceParam
+from .symbol_source_param import SymbolSourceParam
+
+__all__ = ["FilePartSourceParam"]
+
+FilePartSourceParam: TypeAlias = Union[FileSourceParam, SymbolSourceParam]
diff --git a/src/opencode_ai/types/file_part_source_text.py b/src/opencode_ai/types/file_part_source_text.py
new file mode 100644
index 0000000..95af821
--- /dev/null
+++ b/src/opencode_ai/types/file_part_source_text.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["FilePartSourceText"]
+
+
+class FilePartSourceText(BaseModel):
+ end: int
+
+ start: int
+
+ value: str
diff --git a/src/opencode_ai/types/file_part_source_text_param.py b/src/opencode_ai/types/file_part_source_text_param.py
new file mode 100644
index 0000000..40d94bc
--- /dev/null
+++ b/src/opencode_ai/types/file_part_source_text_param.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["FilePartSourceTextParam"]
+
+
+class FilePartSourceTextParam(TypedDict, total=False):
+ end: Required[int]
+
+ start: Required[int]
+
+ value: Required[str]
diff --git a/src/opencode_ai/types/file_source.py b/src/opencode_ai/types/file_source.py
new file mode 100644
index 0000000..fd5f328
--- /dev/null
+++ b/src/opencode_ai/types/file_source.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .file_part_source_text import FilePartSourceText
+
+__all__ = ["FileSource"]
+
+
+class FileSource(BaseModel):
+ path: str
+
+ text: FilePartSourceText
+
+ type: Literal["file"]
diff --git a/src/opencode_ai/types/file_source_param.py b/src/opencode_ai/types/file_source_param.py
new file mode 100644
index 0000000..caf14a5
--- /dev/null
+++ b/src/opencode_ai/types/file_source_param.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .file_part_source_text_param import FilePartSourceTextParam
+
+__all__ = ["FileSourceParam"]
+
+
+class FileSourceParam(TypedDict, total=False):
+ path: Required[str]
+
+ text: Required[FilePartSourceTextParam]
+
+ type: Required[Literal["file"]]
diff --git a/src/opencode_ai/types/log_level.py b/src/opencode_ai/types/log_level.py
deleted file mode 100644
index 7d35a2e..0000000
--- a/src/opencode_ai/types/log_level.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import Literal, TypeAlias
-
-__all__ = ["LogLevel"]
-
-LogLevel: TypeAlias = Literal["DEBUG", "INFO", "WARN", "ERROR"]
diff --git a/src/opencode_ai/types/session_chat_params.py b/src/opencode_ai/types/session_chat_params.py
index f9dfee5..b1f197a 100644
--- a/src/opencode_ai/types/session_chat_params.py
+++ b/src/opencode_ai/types/session_chat_params.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Union, Iterable
+from typing import Dict, Union, Iterable
from typing_extensions import Required, Annotated, TypeAlias, TypedDict
from .._utils import PropertyInfo
@@ -23,5 +23,7 @@ class SessionChatParams(TypedDict, total=False):
mode: str
+ tools: Dict[str, bool]
+
Part: TypeAlias = Union[TextPartInputParam, FilePartInputParam]
diff --git a/src/opencode_ai/types/symbol_source.py b/src/opencode_ai/types/symbol_source.py
new file mode 100644
index 0000000..f8982d8
--- /dev/null
+++ b/src/opencode_ai/types/symbol_source.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .file_part_source_text import FilePartSourceText
+
+__all__ = ["SymbolSource", "Range", "RangeEnd", "RangeStart"]
+
+
+class RangeEnd(BaseModel):
+ character: float
+
+ line: float
+
+
+class RangeStart(BaseModel):
+ character: float
+
+ line: float
+
+
+class Range(BaseModel):
+ end: RangeEnd
+
+ start: RangeStart
+
+
+class SymbolSource(BaseModel):
+ kind: int
+
+ name: str
+
+ path: str
+
+ range: Range
+
+ text: FilePartSourceText
+
+ type: Literal["symbol"]
diff --git a/src/opencode_ai/types/symbol_source_param.py b/src/opencode_ai/types/symbol_source_param.py
new file mode 100644
index 0000000..b1ec7a0
--- /dev/null
+++ b/src/opencode_ai/types/symbol_source_param.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .file_part_source_text_param import FilePartSourceTextParam
+
+__all__ = ["SymbolSourceParam", "Range", "RangeEnd", "RangeStart"]
+
+
+class RangeEnd(TypedDict, total=False):
+ character: Required[float]
+
+ line: Required[float]
+
+
+class RangeStart(TypedDict, total=False):
+ character: Required[float]
+
+ line: Required[float]
+
+
+class Range(TypedDict, total=False):
+ end: Required[RangeEnd]
+
+ start: Required[RangeStart]
+
+
+class SymbolSourceParam(TypedDict, total=False):
+ kind: Required[int]
+
+ name: Required[str]
+
+ path: Required[str]
+
+ range: Required[Range]
+
+ text: Required[FilePartSourceTextParam]
+
+ type: Required[Literal["symbol"]]
diff --git a/tests/api_resources/test_session.py b/tests/api_resources/test_session.py
index 644f9a7..08ecc09 100644
--- a/tests/api_resources/test_session.py
+++ b/tests/api_resources/test_session.py
@@ -203,6 +203,7 @@ class TestSession:
provider_id="providerID",
message_id="msg",
mode="mode",
+ tools={"foo": True},
)
assert_matches_type(AssistantMessage, session, path=["response"])
@@ -677,6 +678,7 @@ class TestAsyncSession:
provider_id="providerID",
message_id="msg",
mode="mode",
+ tools={"foo": True},
)
assert_matches_type(AssistantMessage, session, path=["response"])
From 05859cbd0196da7b20e180615e8327ad4ba14eaa Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 22:40:11 +0000
Subject: [PATCH 11/50] release: 0.1.0-alpha.24
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 1c0bb88..380b6f9 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.23"
+ ".": "0.1.0-alpha.24"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e892995..42c2638 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.24 (2025-07-21)
+
+Full Changelog: [v0.1.0-alpha.23...v0.1.0-alpha.24](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.23...v0.1.0-alpha.24)
+
+### Features
+
+* **api:** api update ([bd6dd48](https://github.com/sst/opencode-sdk-python/commit/bd6dd48f11b23c77802e0a36af94c1a92c0326c7))
+
## 0.1.0-alpha.23 (2025-07-18)
Full Changelog: [v0.1.0-alpha.22...v0.1.0-alpha.23](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.22...v0.1.0-alpha.23)
diff --git a/pyproject.toml b/pyproject.toml
index 55a9f68..cc7a6a2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.23"
+version = "0.1.0-alpha.24"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 3ac2a7b..87c4570 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.23" # x-release-please-version
+__version__ = "0.1.0-alpha.24" # x-release-please-version
From 4c406aa02713a83a78a9e1f35a885ef70968b0bd Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 22:58:00 +0000
Subject: [PATCH 12/50] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 32b1351..9eaab8a 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-5e3b108daef12bb43f728ee42261cd1322e8909e6225db58d6fe0617f3b5904c.yml
-openapi_spec_hash: 1f9d2853ba0c1179e45426560e082ef4
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-69b99aaffe10dd5247638b6a34d6c0b3c1cf5300853d12c947151fd946e7fcdb.yml
+openapi_spec_hash: e2c746cf689d71f04c6e9b1bd92e6356
config_hash: 6d56a7ca0d6ed899ecdb5c053a8278ae
From c9d0f6daa1d473a2c94668d8dc86bab83458bf7d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 22:58:46 +0000
Subject: [PATCH 13/50] codegen metadata
---
.stats.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.stats.yml b/.stats.yml
index 9eaab8a..bf53dd4 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-69b99aaffe10dd5247638b6a34d6c0b3c1cf5300853d12c947151fd946e7fcdb.yml
openapi_spec_hash: e2c746cf689d71f04c6e9b1bd92e6356
-config_hash: 6d56a7ca0d6ed899ecdb5c053a8278ae
+config_hash: e64b350ea4abbb4d56d49b0adebacb02
From 98315648f765314b5a7964bd4b2c5d4344a7a201 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 22:59:44 +0000
Subject: [PATCH 14/50] feat(api): api update
---
.stats.yml | 4 +-
api.md | 12 ++
src/opencode_ai/_client.py | 10 +-
src/opencode_ai/resources/__init__.py | 14 ++
src/opencode_ai/resources/tui.py | 135 +++++++++++++++++++
src/opencode_ai/types/__init__.py | 1 +
src/opencode_ai/types/tui_prompt_response.py | 7 +
tests/api_resources/test_tui.py | 80 +++++++++++
8 files changed, 260 insertions(+), 3 deletions(-)
create mode 100644 src/opencode_ai/resources/tui.py
create mode 100644 src/opencode_ai/types/tui_prompt_response.py
create mode 100644 tests/api_resources/test_tui.py
diff --git a/.stats.yml b/.stats.yml
index bf53dd4..9110eeb 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 22
+configured_endpoints: 23
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-69b99aaffe10dd5247638b6a34d6c0b3c1cf5300853d12c947151fd946e7fcdb.yml
openapi_spec_hash: e2c746cf689d71f04c6e9b1bd92e6356
-config_hash: e64b350ea4abbb4d56d49b0adebacb02
+config_hash: d779331eb3dabf2d99f2a20be154d1c9
diff --git a/api.md b/api.md
index e8f80d9..aa2f3b1 100644
--- a/api.md
+++ b/api.md
@@ -134,3 +134,15 @@ Methods:
- client.session.share(id) -> Session
- client.session.summarize(id, \*\*params) -> SessionSummarizeResponse
- client.session.unshare(id) -> Session
+
+# Tui
+
+Types:
+
+```python
+from opencode_ai.types import TuiPromptResponse
+```
+
+Methods:
+
+- client.tui.prompt() -> TuiPromptResponse
diff --git a/src/opencode_ai/_client.py b/src/opencode_ai/_client.py
index b162cc3..cabe5b7 100644
--- a/src/opencode_ai/_client.py
+++ b/src/opencode_ai/_client.py
@@ -21,7 +21,7 @@ from ._types import (
)
from ._utils import is_given, get_async_library
from ._version import __version__
-from .resources import app, file, find, event, config, session
+from .resources import app, tui, file, find, event, config, session
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import APIStatusError
from ._base_client import (
@@ -49,6 +49,7 @@ class Opencode(SyncAPIClient):
file: file.FileResource
config: config.ConfigResource
session: session.SessionResource
+ tui: tui.TuiResource
with_raw_response: OpencodeWithRawResponse
with_streaming_response: OpencodeWithStreamedResponse
@@ -101,6 +102,7 @@ class Opencode(SyncAPIClient):
self.file = file.FileResource(self)
self.config = config.ConfigResource(self)
self.session = session.SessionResource(self)
+ self.tui = tui.TuiResource(self)
self.with_raw_response = OpencodeWithRawResponse(self)
self.with_streaming_response = OpencodeWithStreamedResponse(self)
@@ -208,6 +210,7 @@ class AsyncOpencode(AsyncAPIClient):
file: file.AsyncFileResource
config: config.AsyncConfigResource
session: session.AsyncSessionResource
+ tui: tui.AsyncTuiResource
with_raw_response: AsyncOpencodeWithRawResponse
with_streaming_response: AsyncOpencodeWithStreamedResponse
@@ -260,6 +263,7 @@ class AsyncOpencode(AsyncAPIClient):
self.file = file.AsyncFileResource(self)
self.config = config.AsyncConfigResource(self)
self.session = session.AsyncSessionResource(self)
+ self.tui = tui.AsyncTuiResource(self)
self.with_raw_response = AsyncOpencodeWithRawResponse(self)
self.with_streaming_response = AsyncOpencodeWithStreamedResponse(self)
@@ -368,6 +372,7 @@ class OpencodeWithRawResponse:
self.file = file.FileResourceWithRawResponse(client.file)
self.config = config.ConfigResourceWithRawResponse(client.config)
self.session = session.SessionResourceWithRawResponse(client.session)
+ self.tui = tui.TuiResourceWithRawResponse(client.tui)
class AsyncOpencodeWithRawResponse:
@@ -378,6 +383,7 @@ class AsyncOpencodeWithRawResponse:
self.file = file.AsyncFileResourceWithRawResponse(client.file)
self.config = config.AsyncConfigResourceWithRawResponse(client.config)
self.session = session.AsyncSessionResourceWithRawResponse(client.session)
+ self.tui = tui.AsyncTuiResourceWithRawResponse(client.tui)
class OpencodeWithStreamedResponse:
@@ -388,6 +394,7 @@ class OpencodeWithStreamedResponse:
self.file = file.FileResourceWithStreamingResponse(client.file)
self.config = config.ConfigResourceWithStreamingResponse(client.config)
self.session = session.SessionResourceWithStreamingResponse(client.session)
+ self.tui = tui.TuiResourceWithStreamingResponse(client.tui)
class AsyncOpencodeWithStreamedResponse:
@@ -398,6 +405,7 @@ class AsyncOpencodeWithStreamedResponse:
self.file = file.AsyncFileResourceWithStreamingResponse(client.file)
self.config = config.AsyncConfigResourceWithStreamingResponse(client.config)
self.session = session.AsyncSessionResourceWithStreamingResponse(client.session)
+ self.tui = tui.AsyncTuiResourceWithStreamingResponse(client.tui)
Client = Opencode
diff --git a/src/opencode_ai/resources/__init__.py b/src/opencode_ai/resources/__init__.py
index 7b0815f..ee6a647 100644
--- a/src/opencode_ai/resources/__init__.py
+++ b/src/opencode_ai/resources/__init__.py
@@ -8,6 +8,14 @@ from .app import (
AppResourceWithStreamingResponse,
AsyncAppResourceWithStreamingResponse,
)
+from .tui import (
+ TuiResource,
+ AsyncTuiResource,
+ TuiResourceWithRawResponse,
+ AsyncTuiResourceWithRawResponse,
+ TuiResourceWithStreamingResponse,
+ AsyncTuiResourceWithStreamingResponse,
+)
from .file import (
FileResource,
AsyncFileResource,
@@ -86,4 +94,10 @@ __all__ = [
"AsyncSessionResourceWithRawResponse",
"SessionResourceWithStreamingResponse",
"AsyncSessionResourceWithStreamingResponse",
+ "TuiResource",
+ "AsyncTuiResource",
+ "TuiResourceWithRawResponse",
+ "AsyncTuiResourceWithRawResponse",
+ "TuiResourceWithStreamingResponse",
+ "AsyncTuiResourceWithStreamingResponse",
]
diff --git a/src/opencode_ai/resources/tui.py b/src/opencode_ai/resources/tui.py
new file mode 100644
index 0000000..5a8e2e9
--- /dev/null
+++ b/src/opencode_ai/resources/tui.py
@@ -0,0 +1,135 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+from ..types.tui_prompt_response import TuiPromptResponse
+
+__all__ = ["TuiResource", "AsyncTuiResource"]
+
+
+class TuiResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> TuiResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/sst/opencode-sdk-python#accessing-raw-response-data-eg-headers
+ """
+ return TuiResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> TuiResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/sst/opencode-sdk-python#with_streaming_response
+ """
+ return TuiResourceWithStreamingResponse(self)
+
+ def prompt(
+ self,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TuiPromptResponse:
+ """Send a prompt to the TUI"""
+ return self._post(
+ "/tui/prompt",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TuiPromptResponse,
+ )
+
+
+class AsyncTuiResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncTuiResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/sst/opencode-sdk-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncTuiResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncTuiResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/sst/opencode-sdk-python#with_streaming_response
+ """
+ return AsyncTuiResourceWithStreamingResponse(self)
+
+ async def prompt(
+ self,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TuiPromptResponse:
+ """Send a prompt to the TUI"""
+ return await self._post(
+ "/tui/prompt",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TuiPromptResponse,
+ )
+
+
+class TuiResourceWithRawResponse:
+ def __init__(self, tui: TuiResource) -> None:
+ self._tui = tui
+
+ self.prompt = to_raw_response_wrapper(
+ tui.prompt,
+ )
+
+
+class AsyncTuiResourceWithRawResponse:
+ def __init__(self, tui: AsyncTuiResource) -> None:
+ self._tui = tui
+
+ self.prompt = async_to_raw_response_wrapper(
+ tui.prompt,
+ )
+
+
+class TuiResourceWithStreamingResponse:
+ def __init__(self, tui: TuiResource) -> None:
+ self._tui = tui
+
+ self.prompt = to_streamed_response_wrapper(
+ tui.prompt,
+ )
+
+
+class AsyncTuiResourceWithStreamingResponse:
+ def __init__(self, tui: AsyncTuiResource) -> None:
+ self._tui = tui
+
+ self.prompt = async_to_streamed_response_wrapper(
+ tui.prompt,
+ )
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index 5151b92..db18d1b 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -52,6 +52,7 @@ from .find_symbols_params import FindSymbolsParams as FindSymbolsParams
from .session_chat_params import SessionChatParams as SessionChatParams
from .session_init_params import SessionInitParams as SessionInitParams
from .symbol_source_param import SymbolSourceParam as SymbolSourceParam
+from .tui_prompt_response import TuiPromptResponse as TuiPromptResponse
from .file_status_response import FileStatusResponse as FileStatusResponse
from .tool_state_completed import ToolStateCompleted as ToolStateCompleted
from .file_part_input_param import FilePartInputParam as FilePartInputParam
diff --git a/src/opencode_ai/types/tui_prompt_response.py b/src/opencode_ai/types/tui_prompt_response.py
new file mode 100644
index 0000000..95dde9e
--- /dev/null
+++ b/src/opencode_ai/types/tui_prompt_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["TuiPromptResponse"]
+
+TuiPromptResponse: TypeAlias = bool
diff --git a/tests/api_resources/test_tui.py b/tests/api_resources/test_tui.py
new file mode 100644
index 0000000..92fde65
--- /dev/null
+++ b/tests/api_resources/test_tui.py
@@ -0,0 +1,80 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from opencode_ai import Opencode, AsyncOpencode
+from tests.utils import assert_matches_type
+from opencode_ai.types import TuiPromptResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestTui:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_prompt(self, client: Opencode) -> None:
+ tui = client.tui.prompt()
+ assert_matches_type(TuiPromptResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_raw_response_prompt(self, client: Opencode) -> None:
+ response = client.tui.with_raw_response.prompt()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ tui = response.parse()
+ assert_matches_type(TuiPromptResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_streaming_response_prompt(self, client: Opencode) -> None:
+ with client.tui.with_streaming_response.prompt() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ tui = response.parse()
+ assert_matches_type(TuiPromptResponse, tui, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncTui:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_prompt(self, async_client: AsyncOpencode) -> None:
+ tui = await async_client.tui.prompt()
+ assert_matches_type(TuiPromptResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_raw_response_prompt(self, async_client: AsyncOpencode) -> None:
+ response = await async_client.tui.with_raw_response.prompt()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ tui = await response.parse()
+ assert_matches_type(TuiPromptResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_streaming_response_prompt(self, async_client: AsyncOpencode) -> None:
+ async with async_client.tui.with_streaming_response.prompt() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ tui = await response.parse()
+ assert_matches_type(TuiPromptResponse, tui, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
From 8ea99fb27b499634bac3457c8e1e111766ba6682 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 22:59:59 +0000
Subject: [PATCH 15/50] release: 0.1.0-alpha.25
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 380b6f9..3188ced 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.24"
+ ".": "0.1.0-alpha.25"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42c2638..84ac353 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.25 (2025-07-21)
+
+Full Changelog: [v0.1.0-alpha.24...v0.1.0-alpha.25](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.24...v0.1.0-alpha.25)
+
+### Features
+
+* **api:** api update ([a85f832](https://github.com/sst/opencode-sdk-python/commit/a85f832a942075091b9ca3f7e6399ba00239f354))
+
## 0.1.0-alpha.24 (2025-07-21)
Full Changelog: [v0.1.0-alpha.23...v0.1.0-alpha.24](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.23...v0.1.0-alpha.24)
diff --git a/pyproject.toml b/pyproject.toml
index cc7a6a2..74c0396 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.24"
+version = "0.1.0-alpha.25"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 87c4570..20e5605 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.24" # x-release-please-version
+__version__ = "0.1.0-alpha.25" # x-release-please-version
From e27c59a26c8caf4e470013cdb6210206e58c2704 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 23:15:33 +0000
Subject: [PATCH 16/50] codegen metadata
---
.stats.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 9110eeb..38d680f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 23
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-69b99aaffe10dd5247638b6a34d6c0b3c1cf5300853d12c947151fd946e7fcdb.yml
-openapi_spec_hash: e2c746cf689d71f04c6e9b1bd92e6356
-config_hash: d779331eb3dabf2d99f2a20be154d1c9
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-36685e6c811d5fcefdf3a2850a6c198417f6ae822ceddc77cac73625d2cc93ce.yml
+openapi_spec_hash: fb6cbcb766a009845ff5c10fbdea8e38
+config_hash: 0032a76356d31c6b4c218b39fff635bb
From be1f9d88f0e0f65c888ccfb427c0e29c61d7e2ff Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 23:24:37 +0000
Subject: [PATCH 17/50] feat(api): api update
---
.stats.yml | 4 +-
api.md | 2 +-
src/opencode_ai/resources/tui.py | 49 +++++++++++-
src/opencode_ai/types/__init__.py | 12 +++
src/opencode_ai/types/file_part_param.py | 28 +++++++
src/opencode_ai/types/part_param.py | 19 +++++
src/opencode_ai/types/snapshot_part_param.py | 21 +++++
.../types/step_finish_part_param.py | 39 ++++++++++
.../types/step_start_part_param.py | 19 +++++
src/opencode_ai/types/text_part_param.py | 31 ++++++++
src/opencode_ai/types/tool_part_param.py | 32 ++++++++
.../types/tool_state_completed_param.py | 28 +++++++
.../types/tool_state_error_param.py | 24 ++++++
.../types/tool_state_pending_param.py | 11 +++
.../types/tool_state_running_param.py | 24 ++++++
src/opencode_ai/types/tui_prompt_params.py | 16 ++++
tests/api_resources/test_tui.py | 78 +++++++++++++++++--
17 files changed, 426 insertions(+), 11 deletions(-)
create mode 100644 src/opencode_ai/types/file_part_param.py
create mode 100644 src/opencode_ai/types/part_param.py
create mode 100644 src/opencode_ai/types/snapshot_part_param.py
create mode 100644 src/opencode_ai/types/step_finish_part_param.py
create mode 100644 src/opencode_ai/types/step_start_part_param.py
create mode 100644 src/opencode_ai/types/text_part_param.py
create mode 100644 src/opencode_ai/types/tool_part_param.py
create mode 100644 src/opencode_ai/types/tool_state_completed_param.py
create mode 100644 src/opencode_ai/types/tool_state_error_param.py
create mode 100644 src/opencode_ai/types/tool_state_pending_param.py
create mode 100644 src/opencode_ai/types/tool_state_running_param.py
create mode 100644 src/opencode_ai/types/tui_prompt_params.py
diff --git a/.stats.yml b/.stats.yml
index 38d680f..2ff039c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 23
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-36685e6c811d5fcefdf3a2850a6c198417f6ae822ceddc77cac73625d2cc93ce.yml
-openapi_spec_hash: fb6cbcb766a009845ff5c10fbdea8e38
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-04eaffcca7fcec3eba3c34ba4e91ba830867173c552015a0abfd65e25084d9b5.yml
+openapi_spec_hash: 4dfbcc2ce25451592f610e372ecad0cb
config_hash: 0032a76356d31c6b4c218b39fff635bb
diff --git a/api.md b/api.md
index aa2f3b1..e4866ed 100644
--- a/api.md
+++ b/api.md
@@ -145,4 +145,4 @@ from opencode_ai.types import TuiPromptResponse
Methods:
-- client.tui.prompt() -> TuiPromptResponse
+- client.tui.prompt(\*\*params) -> TuiPromptResponse
diff --git a/src/opencode_ai/resources/tui.py b/src/opencode_ai/resources/tui.py
index 5a8e2e9..fd3cb73 100644
--- a/src/opencode_ai/resources/tui.py
+++ b/src/opencode_ai/resources/tui.py
@@ -2,9 +2,13 @@
from __future__ import annotations
+from typing import Iterable
+
import httpx
+from ..types import tui_prompt_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -14,6 +18,7 @@ from .._response import (
async_to_streamed_response_wrapper,
)
from .._base_client import make_request_options
+from ..types.part_param import PartParam
from ..types.tui_prompt_response import TuiPromptResponse
__all__ = ["TuiResource", "AsyncTuiResource"]
@@ -42,6 +47,8 @@ class TuiResource(SyncAPIResource):
def prompt(
self,
*,
+ parts: Iterable[PartParam],
+ text: str,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -49,9 +56,27 @@ class TuiResource(SyncAPIResource):
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> TuiPromptResponse:
- """Send a prompt to the TUI"""
+ """
+ Send a prompt to the TUI
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
return self._post(
"/tui/prompt",
+ body=maybe_transform(
+ {
+ "parts": parts,
+ "text": text,
+ },
+ tui_prompt_params.TuiPromptParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -82,6 +107,8 @@ class AsyncTuiResource(AsyncAPIResource):
async def prompt(
self,
*,
+ parts: Iterable[PartParam],
+ text: str,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -89,9 +116,27 @@ class AsyncTuiResource(AsyncAPIResource):
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> TuiPromptResponse:
- """Send a prompt to the TUI"""
+ """
+ Send a prompt to the TUI
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
return await self._post(
"/tui/prompt",
+ body=await async_maybe_transform(
+ {
+ "parts": parts,
+ "text": text,
+ },
+ tui_prompt_params.TuiPromptParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index db18d1b..6621bb7 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -21,14 +21,18 @@ from .provider import Provider as Provider
from .file_part import FilePart as FilePart
from .text_part import TextPart as TextPart
from .tool_part import ToolPart as ToolPart
+from .part_param import PartParam as PartParam
from .file_source import FileSource as FileSource
from .mode_config import ModeConfig as ModeConfig
from .user_message import UserMessage as UserMessage
from .snapshot_part import SnapshotPart as SnapshotPart
from .symbol_source import SymbolSource as SymbolSource
from .app_log_params import AppLogParams as AppLogParams
+from .file_part_param import FilePartParam as FilePartParam
from .keybinds_config import KeybindsConfig as KeybindsConfig
from .step_start_part import StepStartPart as StepStartPart
+from .text_part_param import TextPartParam as TextPartParam
+from .tool_part_param import ToolPartParam as ToolPartParam
from .app_log_response import AppLogResponse as AppLogResponse
from .file_part_source import FilePartSource as FilePartSource
from .file_read_params import FileReadParams as FileReadParams
@@ -41,6 +45,7 @@ from .assistant_message import AssistantMessage as AssistantMessage
from .file_source_param import FileSourceParam as FileSourceParam
from .find_files_params import FindFilesParams as FindFilesParams
from .mcp_remote_config import McpRemoteConfig as McpRemoteConfig
+from .tui_prompt_params import TuiPromptParams as TuiPromptParams
from .app_modes_response import AppModesResponse as AppModesResponse
from .file_read_response import FileReadResponse as FileReadResponse
from .find_text_response import FindTextResponse as FindTextResponse
@@ -51,6 +56,7 @@ from .find_files_response import FindFilesResponse as FindFilesResponse
from .find_symbols_params import FindSymbolsParams as FindSymbolsParams
from .session_chat_params import SessionChatParams as SessionChatParams
from .session_init_params import SessionInitParams as SessionInitParams
+from .snapshot_part_param import SnapshotPartParam as SnapshotPartParam
from .symbol_source_param import SymbolSourceParam as SymbolSourceParam
from .tui_prompt_response import TuiPromptResponse as TuiPromptResponse
from .file_status_response import FileStatusResponse as FileStatusResponse
@@ -60,12 +66,18 @@ from .file_part_source_text import FilePartSourceText as FilePartSourceText
from .find_symbols_response import FindSymbolsResponse as FindSymbolsResponse
from .session_init_response import SessionInitResponse as SessionInitResponse
from .session_list_response import SessionListResponse as SessionListResponse
+from .step_start_part_param import StepStartPartParam as StepStartPartParam
from .text_part_input_param import TextPartInputParam as TextPartInputParam
from .app_providers_response import AppProvidersResponse as AppProvidersResponse
from .file_part_source_param import FilePartSourceParam as FilePartSourceParam
from .session_abort_response import SessionAbortResponse as SessionAbortResponse
+from .step_finish_part_param import StepFinishPartParam as StepFinishPartParam
+from .tool_state_error_param import ToolStateErrorParam as ToolStateErrorParam
from .session_delete_response import SessionDeleteResponse as SessionDeleteResponse
from .session_summarize_params import SessionSummarizeParams as SessionSummarizeParams
+from .tool_state_pending_param import ToolStatePendingParam as ToolStatePendingParam
+from .tool_state_running_param import ToolStateRunningParam as ToolStateRunningParam
from .session_messages_response import SessionMessagesResponse as SessionMessagesResponse
from .session_summarize_response import SessionSummarizeResponse as SessionSummarizeResponse
+from .tool_state_completed_param import ToolStateCompletedParam as ToolStateCompletedParam
from .file_part_source_text_param import FilePartSourceTextParam as FilePartSourceTextParam
diff --git a/src/opencode_ai/types/file_part_param.py b/src/opencode_ai/types/file_part_param.py
new file mode 100644
index 0000000..9de2723
--- /dev/null
+++ b/src/opencode_ai/types/file_part_param.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+from .file_part_source_param import FilePartSourceParam
+
+__all__ = ["FilePartParam"]
+
+
+class FilePartParam(TypedDict, total=False):
+ id: Required[str]
+
+ message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
+
+ mime: Required[str]
+
+ session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
+
+ type: Required[Literal["file"]]
+
+ url: Required[str]
+
+ filename: str
+
+ source: FilePartSourceParam
diff --git a/src/opencode_ai/types/part_param.py b/src/opencode_ai/types/part_param.py
new file mode 100644
index 0000000..8160b98
--- /dev/null
+++ b/src/opencode_ai/types/part_param.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from typing_extensions import TypeAlias
+
+from .file_part_param import FilePartParam
+from .text_part_param import TextPartParam
+from .tool_part_param import ToolPartParam
+from .snapshot_part_param import SnapshotPartParam
+from .step_start_part_param import StepStartPartParam
+from .step_finish_part_param import StepFinishPartParam
+
+__all__ = ["PartParam"]
+
+PartParam: TypeAlias = Union[
+ TextPartParam, FilePartParam, ToolPartParam, StepStartPartParam, StepFinishPartParam, SnapshotPartParam
+]
diff --git a/src/opencode_ai/types/snapshot_part_param.py b/src/opencode_ai/types/snapshot_part_param.py
new file mode 100644
index 0000000..847ba82
--- /dev/null
+++ b/src/opencode_ai/types/snapshot_part_param.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["SnapshotPartParam"]
+
+
+class SnapshotPartParam(TypedDict, total=False):
+ id: Required[str]
+
+ message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
+
+ session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
+
+ snapshot: Required[str]
+
+ type: Required[Literal["snapshot"]]
diff --git a/src/opencode_ai/types/step_finish_part_param.py b/src/opencode_ai/types/step_finish_part_param.py
new file mode 100644
index 0000000..4dabb28
--- /dev/null
+++ b/src/opencode_ai/types/step_finish_part_param.py
@@ -0,0 +1,39 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["StepFinishPartParam", "Tokens", "TokensCache"]
+
+
+class TokensCache(TypedDict, total=False):
+ read: Required[float]
+
+ write: Required[float]
+
+
+class Tokens(TypedDict, total=False):
+ cache: Required[TokensCache]
+
+ input: Required[float]
+
+ output: Required[float]
+
+ reasoning: Required[float]
+
+
+class StepFinishPartParam(TypedDict, total=False):
+ id: Required[str]
+
+ cost: Required[float]
+
+ message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
+
+ session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
+
+ tokens: Required[Tokens]
+
+ type: Required[Literal["step-finish"]]
diff --git a/src/opencode_ai/types/step_start_part_param.py b/src/opencode_ai/types/step_start_part_param.py
new file mode 100644
index 0000000..a7d5655
--- /dev/null
+++ b/src/opencode_ai/types/step_start_part_param.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["StepStartPartParam"]
+
+
+class StepStartPartParam(TypedDict, total=False):
+ id: Required[str]
+
+ message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
+
+ session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
+
+ type: Required[Literal["step-start"]]
diff --git a/src/opencode_ai/types/text_part_param.py b/src/opencode_ai/types/text_part_param.py
new file mode 100644
index 0000000..3129256
--- /dev/null
+++ b/src/opencode_ai/types/text_part_param.py
@@ -0,0 +1,31 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["TextPartParam", "Time"]
+
+
+class Time(TypedDict, total=False):
+ start: Required[float]
+
+ end: float
+
+
+class TextPartParam(TypedDict, total=False):
+ id: Required[str]
+
+ message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
+
+ session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
+
+ text: Required[str]
+
+ type: Required[Literal["text"]]
+
+ synthetic: bool
+
+ time: Time
diff --git a/src/opencode_ai/types/tool_part_param.py b/src/opencode_ai/types/tool_part_param.py
new file mode 100644
index 0000000..559c770
--- /dev/null
+++ b/src/opencode_ai/types/tool_part_param.py
@@ -0,0 +1,32 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
+
+from .._utils import PropertyInfo
+from .tool_state_error_param import ToolStateErrorParam
+from .tool_state_pending_param import ToolStatePendingParam
+from .tool_state_running_param import ToolStateRunningParam
+from .tool_state_completed_param import ToolStateCompletedParam
+
+__all__ = ["ToolPartParam", "State"]
+
+State: TypeAlias = Union[ToolStatePendingParam, ToolStateRunningParam, ToolStateCompletedParam, ToolStateErrorParam]
+
+
+class ToolPartParam(TypedDict, total=False):
+ id: Required[str]
+
+ call_id: Required[Annotated[str, PropertyInfo(alias="callID")]]
+
+ message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
+
+ session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
+
+ state: Required[State]
+
+ tool: Required[str]
+
+ type: Required[Literal["tool"]]
diff --git a/src/opencode_ai/types/tool_state_completed_param.py b/src/opencode_ai/types/tool_state_completed_param.py
new file mode 100644
index 0000000..cea3758
--- /dev/null
+++ b/src/opencode_ai/types/tool_state_completed_param.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ToolStateCompletedParam", "Time"]
+
+
+class Time(TypedDict, total=False):
+ end: Required[float]
+
+ start: Required[float]
+
+
+class ToolStateCompletedParam(TypedDict, total=False):
+ input: Required[Dict[str, object]]
+
+ metadata: Required[Dict[str, object]]
+
+ output: Required[str]
+
+ status: Required[Literal["completed"]]
+
+ time: Required[Time]
+
+ title: Required[str]
diff --git a/src/opencode_ai/types/tool_state_error_param.py b/src/opencode_ai/types/tool_state_error_param.py
new file mode 100644
index 0000000..7622868
--- /dev/null
+++ b/src/opencode_ai/types/tool_state_error_param.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ToolStateErrorParam", "Time"]
+
+
+class Time(TypedDict, total=False):
+ end: Required[float]
+
+ start: Required[float]
+
+
+class ToolStateErrorParam(TypedDict, total=False):
+ error: Required[str]
+
+ input: Required[Dict[str, object]]
+
+ status: Required[Literal["error"]]
+
+ time: Required[Time]
diff --git a/src/opencode_ai/types/tool_state_pending_param.py b/src/opencode_ai/types/tool_state_pending_param.py
new file mode 100644
index 0000000..d375cd5
--- /dev/null
+++ b/src/opencode_ai/types/tool_state_pending_param.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ToolStatePendingParam"]
+
+
+class ToolStatePendingParam(TypedDict, total=False):
+ status: Required[Literal["pending"]]
diff --git a/src/opencode_ai/types/tool_state_running_param.py b/src/opencode_ai/types/tool_state_running_param.py
new file mode 100644
index 0000000..1814d43
--- /dev/null
+++ b/src/opencode_ai/types/tool_state_running_param.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ToolStateRunningParam", "Time"]
+
+
+class Time(TypedDict, total=False):
+ start: Required[float]
+
+
+class ToolStateRunningParam(TypedDict, total=False):
+ status: Required[Literal["running"]]
+
+ time: Required[Time]
+
+ input: object
+
+ metadata: Dict[str, object]
+
+ title: str
diff --git a/src/opencode_ai/types/tui_prompt_params.py b/src/opencode_ai/types/tui_prompt_params.py
new file mode 100644
index 0000000..be85887
--- /dev/null
+++ b/src/opencode_ai/types/tui_prompt_params.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+from .part_param import PartParam
+
+__all__ = ["TuiPromptParams"]
+
+
+class TuiPromptParams(TypedDict, total=False):
+ parts: Required[Iterable[PartParam]]
+
+ text: Required[str]
diff --git a/tests/api_resources/test_tui.py b/tests/api_resources/test_tui.py
index 92fde65..dbcfd75 100644
--- a/tests/api_resources/test_tui.py
+++ b/tests/api_resources/test_tui.py
@@ -20,13 +20,35 @@ class TestTui:
@pytest.mark.skip()
@parametrize
def test_method_prompt(self, client: Opencode) -> None:
- tui = client.tui.prompt()
+ tui = client.tui.prompt(
+ parts=[
+ {
+ "id": "id",
+ "message_id": "messageID",
+ "session_id": "sessionID",
+ "text": "text",
+ "type": "text",
+ }
+ ],
+ text="text",
+ )
assert_matches_type(TuiPromptResponse, tui, path=["response"])
@pytest.mark.skip()
@parametrize
def test_raw_response_prompt(self, client: Opencode) -> None:
- response = client.tui.with_raw_response.prompt()
+ response = client.tui.with_raw_response.prompt(
+ parts=[
+ {
+ "id": "id",
+ "message_id": "messageID",
+ "session_id": "sessionID",
+ "text": "text",
+ "type": "text",
+ }
+ ],
+ text="text",
+ )
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -36,7 +58,18 @@ class TestTui:
@pytest.mark.skip()
@parametrize
def test_streaming_response_prompt(self, client: Opencode) -> None:
- with client.tui.with_streaming_response.prompt() as response:
+ with client.tui.with_streaming_response.prompt(
+ parts=[
+ {
+ "id": "id",
+ "message_id": "messageID",
+ "session_id": "sessionID",
+ "text": "text",
+ "type": "text",
+ }
+ ],
+ text="text",
+ ) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -54,13 +87,35 @@ class TestAsyncTui:
@pytest.mark.skip()
@parametrize
async def test_method_prompt(self, async_client: AsyncOpencode) -> None:
- tui = await async_client.tui.prompt()
+ tui = await async_client.tui.prompt(
+ parts=[
+ {
+ "id": "id",
+ "message_id": "messageID",
+ "session_id": "sessionID",
+ "text": "text",
+ "type": "text",
+ }
+ ],
+ text="text",
+ )
assert_matches_type(TuiPromptResponse, tui, path=["response"])
@pytest.mark.skip()
@parametrize
async def test_raw_response_prompt(self, async_client: AsyncOpencode) -> None:
- response = await async_client.tui.with_raw_response.prompt()
+ response = await async_client.tui.with_raw_response.prompt(
+ parts=[
+ {
+ "id": "id",
+ "message_id": "messageID",
+ "session_id": "sessionID",
+ "text": "text",
+ "type": "text",
+ }
+ ],
+ text="text",
+ )
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -70,7 +125,18 @@ class TestAsyncTui:
@pytest.mark.skip()
@parametrize
async def test_streaming_response_prompt(self, async_client: AsyncOpencode) -> None:
- async with async_client.tui.with_streaming_response.prompt() as response:
+ async with async_client.tui.with_streaming_response.prompt(
+ parts=[
+ {
+ "id": "id",
+ "message_id": "messageID",
+ "session_id": "sessionID",
+ "text": "text",
+ "type": "text",
+ }
+ ],
+ text="text",
+ ) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
From c75c9633c96437ef532c720c75c9b6bdb90f2527 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 23:24:51 +0000
Subject: [PATCH 18/50] release: 0.1.0-alpha.26
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 3188ced..315f7d3 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.25"
+ ".": "0.1.0-alpha.26"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 84ac353..4d97d3d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.26 (2025-07-21)
+
+Full Changelog: [v0.1.0-alpha.25...v0.1.0-alpha.26](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.25...v0.1.0-alpha.26)
+
+### Features
+
+* **api:** api update ([827dc0c](https://github.com/sst/opencode-sdk-python/commit/827dc0c780afd217f981cdd31d371fe96327aeec))
+
## 0.1.0-alpha.25 (2025-07-21)
Full Changelog: [v0.1.0-alpha.24...v0.1.0-alpha.25](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.24...v0.1.0-alpha.25)
diff --git a/pyproject.toml b/pyproject.toml
index 74c0396..349aa84 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.25"
+version = "0.1.0-alpha.26"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 20e5605..6d9c11d 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.25" # x-release-please-version
+__version__ = "0.1.0-alpha.26" # x-release-please-version
From ff6b72a6da5a0a13281e8bd572004deae2a26c8c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 23:53:21 +0000
Subject: [PATCH 19/50] feat(api): api update
---
.stats.yml | 6 +-
api.md | 3 +-
src/opencode_ai/resources/tui.py | 51 ++++++++++++++++
src/opencode_ai/types/__init__.py | 1 +
.../types/tui_open_help_response.py | 7 +++
tests/api_resources/test_tui.py | 58 ++++++++++++++++++-
6 files changed, 121 insertions(+), 5 deletions(-)
create mode 100644 src/opencode_ai/types/tui_open_help_response.py
diff --git a/.stats.yml b/.stats.yml
index 2ff039c..56337c0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 23
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-04eaffcca7fcec3eba3c34ba4e91ba830867173c552015a0abfd65e25084d9b5.yml
-openapi_spec_hash: 4dfbcc2ce25451592f610e372ecad0cb
+configured_endpoints: 24
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-d10809ab68e48a338167e5504d69db2a0a80739adf6ecd3f065644a4139bc374.yml
+openapi_spec_hash: 4875565ef8df3446dbab11f450e04c51
config_hash: 0032a76356d31c6b4c218b39fff635bb
diff --git a/api.md b/api.md
index e4866ed..efcd86b 100644
--- a/api.md
+++ b/api.md
@@ -140,9 +140,10 @@ Methods:
Types:
```python
-from opencode_ai.types import TuiPromptResponse
+from opencode_ai.types import TuiOpenHelpResponse, TuiPromptResponse
```
Methods:
+- client.tui.open_help() -> TuiOpenHelpResponse
- client.tui.prompt(\*\*params) -> TuiPromptResponse
diff --git a/src/opencode_ai/resources/tui.py b/src/opencode_ai/resources/tui.py
index fd3cb73..9a37ba8 100644
--- a/src/opencode_ai/resources/tui.py
+++ b/src/opencode_ai/resources/tui.py
@@ -20,6 +20,7 @@ from .._response import (
from .._base_client import make_request_options
from ..types.part_param import PartParam
from ..types.tui_prompt_response import TuiPromptResponse
+from ..types.tui_open_help_response import TuiOpenHelpResponse
__all__ = ["TuiResource", "AsyncTuiResource"]
@@ -44,6 +45,25 @@ class TuiResource(SyncAPIResource):
"""
return TuiResourceWithStreamingResponse(self)
+ def open_help(
+ self,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TuiOpenHelpResponse:
+ """Open the help dialog"""
+ return self._post(
+ "/tui/open-help",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TuiOpenHelpResponse,
+ )
+
def prompt(
self,
*,
@@ -104,6 +124,25 @@ class AsyncTuiResource(AsyncAPIResource):
"""
return AsyncTuiResourceWithStreamingResponse(self)
+ async def open_help(
+ self,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TuiOpenHelpResponse:
+ """Open the help dialog"""
+ return await self._post(
+ "/tui/open-help",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TuiOpenHelpResponse,
+ )
+
async def prompt(
self,
*,
@@ -148,6 +187,9 @@ class TuiResourceWithRawResponse:
def __init__(self, tui: TuiResource) -> None:
self._tui = tui
+ self.open_help = to_raw_response_wrapper(
+ tui.open_help,
+ )
self.prompt = to_raw_response_wrapper(
tui.prompt,
)
@@ -157,6 +199,9 @@ class AsyncTuiResourceWithRawResponse:
def __init__(self, tui: AsyncTuiResource) -> None:
self._tui = tui
+ self.open_help = async_to_raw_response_wrapper(
+ tui.open_help,
+ )
self.prompt = async_to_raw_response_wrapper(
tui.prompt,
)
@@ -166,6 +211,9 @@ class TuiResourceWithStreamingResponse:
def __init__(self, tui: TuiResource) -> None:
self._tui = tui
+ self.open_help = to_streamed_response_wrapper(
+ tui.open_help,
+ )
self.prompt = to_streamed_response_wrapper(
tui.prompt,
)
@@ -175,6 +223,9 @@ class AsyncTuiResourceWithStreamingResponse:
def __init__(self, tui: AsyncTuiResource) -> None:
self._tui = tui
+ self.open_help = async_to_streamed_response_wrapper(
+ tui.open_help,
+ )
self.prompt = async_to_streamed_response_wrapper(
tui.prompt,
)
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index 6621bb7..4a81598 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -73,6 +73,7 @@ from .file_part_source_param import FilePartSourceParam as FilePartSourceParam
from .session_abort_response import SessionAbortResponse as SessionAbortResponse
from .step_finish_part_param import StepFinishPartParam as StepFinishPartParam
from .tool_state_error_param import ToolStateErrorParam as ToolStateErrorParam
+from .tui_open_help_response import TuiOpenHelpResponse as TuiOpenHelpResponse
from .session_delete_response import SessionDeleteResponse as SessionDeleteResponse
from .session_summarize_params import SessionSummarizeParams as SessionSummarizeParams
from .tool_state_pending_param import ToolStatePendingParam as ToolStatePendingParam
diff --git a/src/opencode_ai/types/tui_open_help_response.py b/src/opencode_ai/types/tui_open_help_response.py
new file mode 100644
index 0000000..59df1f1
--- /dev/null
+++ b/src/opencode_ai/types/tui_open_help_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["TuiOpenHelpResponse"]
+
+TuiOpenHelpResponse: TypeAlias = bool
diff --git a/tests/api_resources/test_tui.py b/tests/api_resources/test_tui.py
index dbcfd75..6478963 100644
--- a/tests/api_resources/test_tui.py
+++ b/tests/api_resources/test_tui.py
@@ -9,7 +9,7 @@ import pytest
from opencode_ai import Opencode, AsyncOpencode
from tests.utils import assert_matches_type
-from opencode_ai.types import TuiPromptResponse
+from opencode_ai.types import TuiPromptResponse, TuiOpenHelpResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,6 +17,34 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestTui:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_open_help(self, client: Opencode) -> None:
+ tui = client.tui.open_help()
+ assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_raw_response_open_help(self, client: Opencode) -> None:
+ response = client.tui.with_raw_response.open_help()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ tui = response.parse()
+ assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_streaming_response_open_help(self, client: Opencode) -> None:
+ with client.tui.with_streaming_response.open_help() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ tui = response.parse()
+ assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip()
@parametrize
def test_method_prompt(self, client: Opencode) -> None:
@@ -84,6 +112,34 @@ class TestAsyncTui:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_open_help(self, async_client: AsyncOpencode) -> None:
+ tui = await async_client.tui.open_help()
+ assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_raw_response_open_help(self, async_client: AsyncOpencode) -> None:
+ response = await async_client.tui.with_raw_response.open_help()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ tui = await response.parse()
+ assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_streaming_response_open_help(self, async_client: AsyncOpencode) -> None:
+ async with async_client.tui.with_streaming_response.open_help() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ tui = await response.parse()
+ assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip()
@parametrize
async def test_method_prompt(self, async_client: AsyncOpencode) -> None:
From d0c8c5bb87d079153ebe965ae92c3a75b96e9a0e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 22 Jul 2025 02:01:37 +0000
Subject: [PATCH 20/50] fix(parsing): ignore empty metadata
---
src/opencode_ai/_models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/opencode_ai/_models.py b/src/opencode_ai/_models.py
index 528d568..ffcbf67 100644
--- a/src/opencode_ai/_models.py
+++ b/src/opencode_ai/_models.py
@@ -439,7 +439,7 @@ def construct_type(*, value: object, type_: object, metadata: Optional[List[Any]
type_ = type_.__value__ # type: ignore[unreachable]
# unwrap `Annotated[T, ...]` -> `T`
- if metadata is not None:
+ if metadata is not None and len(metadata) > 0:
meta: tuple[Any, ...] = tuple(metadata)
elif is_annotated_type(type_):
meta = get_args(type_)[1:]
From 60df30faf58600a9a89b208011be8c7800fba65c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 22 Jul 2025 02:03:26 +0000
Subject: [PATCH 21/50] release: 0.1.0-alpha.27
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 13 +++++++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 315f7d3..7657c56 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.26"
+ ".": "0.1.0-alpha.27"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d97d3d..de31979 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## 0.1.0-alpha.27 (2025-07-22)
+
+Full Changelog: [v0.1.0-alpha.26...v0.1.0-alpha.27](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.26...v0.1.0-alpha.27)
+
+### Features
+
+* **api:** api update ([50c887c](https://github.com/sst/opencode-sdk-python/commit/50c887c4202f587317afecb8998181c6de78b7b4))
+
+
+### Bug Fixes
+
+* **parsing:** ignore empty metadata ([8ee35ae](https://github.com/sst/opencode-sdk-python/commit/8ee35ae762cb0ade81b08cc41a9f496afe9fd484))
+
## 0.1.0-alpha.26 (2025-07-21)
Full Changelog: [v0.1.0-alpha.25...v0.1.0-alpha.26](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.25...v0.1.0-alpha.26)
diff --git a/pyproject.toml b/pyproject.toml
index 349aa84..5ab2607 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.26"
+version = "0.1.0-alpha.27"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 6d9c11d..f753b1d 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.26" # x-release-please-version
+__version__ = "0.1.0-alpha.27" # x-release-please-version
From 6e577d0bde1f4e96b1ec91e7f56097689ee89994 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 22 Jul 2025 16:06:10 +0000
Subject: [PATCH 22/50] feat(api): api update
---
.stats.yml | 6 +-
api.md | 4 +-
src/opencode_ai/resources/tui.py | 173 +++++++---------
src/opencode_ai/types/__init__.py | 15 +-
src/opencode_ai/types/event_list_response.py | 13 ++
src/opencode_ai/types/file_part_param.py | 28 ---
src/opencode_ai/types/part_param.py | 19 --
src/opencode_ai/types/snapshot_part_param.py | 21 --
.../types/step_finish_part_param.py | 39 ----
.../types/step_start_part_param.py | 19 --
src/opencode_ai/types/text_part_param.py | 31 ---
src/opencode_ai/types/tool_part_param.py | 32 ---
.../types/tool_state_completed_param.py | 28 ---
.../types/tool_state_error_param.py | 24 ---
.../types/tool_state_pending_param.py | 11 -
.../types/tool_state_running_param.py | 24 ---
..._params.py => tui_append_prompt_params.py} | 9 +-
...ponse.py => tui_append_prompt_response.py} | 4 +-
tests/api_resources/test_tui.py | 192 +++++++-----------
19 files changed, 171 insertions(+), 521 deletions(-)
delete mode 100644 src/opencode_ai/types/file_part_param.py
delete mode 100644 src/opencode_ai/types/part_param.py
delete mode 100644 src/opencode_ai/types/snapshot_part_param.py
delete mode 100644 src/opencode_ai/types/step_finish_part_param.py
delete mode 100644 src/opencode_ai/types/step_start_part_param.py
delete mode 100644 src/opencode_ai/types/text_part_param.py
delete mode 100644 src/opencode_ai/types/tool_part_param.py
delete mode 100644 src/opencode_ai/types/tool_state_completed_param.py
delete mode 100644 src/opencode_ai/types/tool_state_error_param.py
delete mode 100644 src/opencode_ai/types/tool_state_pending_param.py
delete mode 100644 src/opencode_ai/types/tool_state_running_param.py
rename src/opencode_ai/types/{tui_prompt_params.py => tui_append_prompt_params.py} (52%)
rename src/opencode_ai/types/{tui_prompt_response.py => tui_append_prompt_response.py} (61%)
diff --git a/.stats.yml b/.stats.yml
index 56337c0..1ec884c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 24
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-d10809ab68e48a338167e5504d69db2a0a80739adf6ecd3f065644a4139bc374.yml
-openapi_spec_hash: 4875565ef8df3446dbab11f450e04c51
-config_hash: 0032a76356d31c6b4c218b39fff635bb
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-7f559270c87d0cbb6779d0edd57a2efcb4d60932674cea4444c40cd4e7b72569.yml
+openapi_spec_hash: 531acdc4f16185743ec56b3e07857cde
+config_hash: 6d92d798d44906c9e43c6dee06615360
diff --git a/api.md b/api.md
index efcd86b..67407e9 100644
--- a/api.md
+++ b/api.md
@@ -140,10 +140,10 @@ Methods:
Types:
```python
-from opencode_ai.types import TuiOpenHelpResponse, TuiPromptResponse
+from opencode_ai.types import TuiAppendPromptResponse, TuiOpenHelpResponse
```
Methods:
+- client.tui.append_prompt(\*\*params) -> TuiAppendPromptResponse
- client.tui.open_help() -> TuiOpenHelpResponse
-- client.tui.prompt(\*\*params) -> TuiPromptResponse
diff --git a/src/opencode_ai/resources/tui.py b/src/opencode_ai/resources/tui.py
index 9a37ba8..7194e7a 100644
--- a/src/opencode_ai/resources/tui.py
+++ b/src/opencode_ai/resources/tui.py
@@ -2,11 +2,9 @@
from __future__ import annotations
-from typing import Iterable
-
import httpx
-from ..types import tui_prompt_params
+from ..types import tui_append_prompt_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -18,9 +16,8 @@ from .._response import (
async_to_streamed_response_wrapper,
)
from .._base_client import make_request_options
-from ..types.part_param import PartParam
-from ..types.tui_prompt_response import TuiPromptResponse
from ..types.tui_open_help_response import TuiOpenHelpResponse
+from ..types.tui_append_prompt_response import TuiAppendPromptResponse
__all__ = ["TuiResource", "AsyncTuiResource"]
@@ -45,6 +42,38 @@ class TuiResource(SyncAPIResource):
"""
return TuiResourceWithStreamingResponse(self)
+ def append_prompt(
+ self,
+ *,
+ text: str,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TuiAppendPromptResponse:
+ """
+ Append prompt to the TUI
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._post(
+ "/tui/append-prompt",
+ body=maybe_transform({"text": text}, tui_append_prompt_params.TuiAppendPromptParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TuiAppendPromptResponse,
+ )
+
def open_help(
self,
*,
@@ -64,45 +93,6 @@ class TuiResource(SyncAPIResource):
cast_to=TuiOpenHelpResponse,
)
- def prompt(
- self,
- *,
- parts: Iterable[PartParam],
- text: str,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
- ) -> TuiPromptResponse:
- """
- Send a prompt to the TUI
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._post(
- "/tui/prompt",
- body=maybe_transform(
- {
- "parts": parts,
- "text": text,
- },
- tui_prompt_params.TuiPromptParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=TuiPromptResponse,
- )
-
class AsyncTuiResource(AsyncAPIResource):
@cached_property
@@ -124,6 +114,38 @@ class AsyncTuiResource(AsyncAPIResource):
"""
return AsyncTuiResourceWithStreamingResponse(self)
+ async def append_prompt(
+ self,
+ *,
+ text: str,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TuiAppendPromptResponse:
+ """
+ Append prompt to the TUI
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self._post(
+ "/tui/append-prompt",
+ body=await async_maybe_transform({"text": text}, tui_append_prompt_params.TuiAppendPromptParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TuiAppendPromptResponse,
+ )
+
async def open_help(
self,
*,
@@ -143,89 +165,50 @@ class AsyncTuiResource(AsyncAPIResource):
cast_to=TuiOpenHelpResponse,
)
- async def prompt(
- self,
- *,
- parts: Iterable[PartParam],
- text: str,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
- ) -> TuiPromptResponse:
- """
- Send a prompt to the TUI
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return await self._post(
- "/tui/prompt",
- body=await async_maybe_transform(
- {
- "parts": parts,
- "text": text,
- },
- tui_prompt_params.TuiPromptParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=TuiPromptResponse,
- )
-
class TuiResourceWithRawResponse:
def __init__(self, tui: TuiResource) -> None:
self._tui = tui
+ self.append_prompt = to_raw_response_wrapper(
+ tui.append_prompt,
+ )
self.open_help = to_raw_response_wrapper(
tui.open_help,
)
- self.prompt = to_raw_response_wrapper(
- tui.prompt,
- )
class AsyncTuiResourceWithRawResponse:
def __init__(self, tui: AsyncTuiResource) -> None:
self._tui = tui
+ self.append_prompt = async_to_raw_response_wrapper(
+ tui.append_prompt,
+ )
self.open_help = async_to_raw_response_wrapper(
tui.open_help,
)
- self.prompt = async_to_raw_response_wrapper(
- tui.prompt,
- )
class TuiResourceWithStreamingResponse:
def __init__(self, tui: TuiResource) -> None:
self._tui = tui
+ self.append_prompt = to_streamed_response_wrapper(
+ tui.append_prompt,
+ )
self.open_help = to_streamed_response_wrapper(
tui.open_help,
)
- self.prompt = to_streamed_response_wrapper(
- tui.prompt,
- )
class AsyncTuiResourceWithStreamingResponse:
def __init__(self, tui: AsyncTuiResource) -> None:
self._tui = tui
+ self.append_prompt = async_to_streamed_response_wrapper(
+ tui.append_prompt,
+ )
self.open_help = async_to_streamed_response_wrapper(
tui.open_help,
)
- self.prompt = async_to_streamed_response_wrapper(
- tui.prompt,
- )
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index 4a81598..0da9c61 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -21,18 +21,14 @@ from .provider import Provider as Provider
from .file_part import FilePart as FilePart
from .text_part import TextPart as TextPart
from .tool_part import ToolPart as ToolPart
-from .part_param import PartParam as PartParam
from .file_source import FileSource as FileSource
from .mode_config import ModeConfig as ModeConfig
from .user_message import UserMessage as UserMessage
from .snapshot_part import SnapshotPart as SnapshotPart
from .symbol_source import SymbolSource as SymbolSource
from .app_log_params import AppLogParams as AppLogParams
-from .file_part_param import FilePartParam as FilePartParam
from .keybinds_config import KeybindsConfig as KeybindsConfig
from .step_start_part import StepStartPart as StepStartPart
-from .text_part_param import TextPartParam as TextPartParam
-from .tool_part_param import ToolPartParam as ToolPartParam
from .app_log_response import AppLogResponse as AppLogResponse
from .file_part_source import FilePartSource as FilePartSource
from .file_read_params import FileReadParams as FileReadParams
@@ -45,7 +41,6 @@ from .assistant_message import AssistantMessage as AssistantMessage
from .file_source_param import FileSourceParam as FileSourceParam
from .find_files_params import FindFilesParams as FindFilesParams
from .mcp_remote_config import McpRemoteConfig as McpRemoteConfig
-from .tui_prompt_params import TuiPromptParams as TuiPromptParams
from .app_modes_response import AppModesResponse as AppModesResponse
from .file_read_response import FileReadResponse as FileReadResponse
from .find_text_response import FindTextResponse as FindTextResponse
@@ -56,9 +51,7 @@ from .find_files_response import FindFilesResponse as FindFilesResponse
from .find_symbols_params import FindSymbolsParams as FindSymbolsParams
from .session_chat_params import SessionChatParams as SessionChatParams
from .session_init_params import SessionInitParams as SessionInitParams
-from .snapshot_part_param import SnapshotPartParam as SnapshotPartParam
from .symbol_source_param import SymbolSourceParam as SymbolSourceParam
-from .tui_prompt_response import TuiPromptResponse as TuiPromptResponse
from .file_status_response import FileStatusResponse as FileStatusResponse
from .tool_state_completed import ToolStateCompleted as ToolStateCompleted
from .file_part_input_param import FilePartInputParam as FilePartInputParam
@@ -66,19 +59,15 @@ from .file_part_source_text import FilePartSourceText as FilePartSourceText
from .find_symbols_response import FindSymbolsResponse as FindSymbolsResponse
from .session_init_response import SessionInitResponse as SessionInitResponse
from .session_list_response import SessionListResponse as SessionListResponse
-from .step_start_part_param import StepStartPartParam as StepStartPartParam
from .text_part_input_param import TextPartInputParam as TextPartInputParam
from .app_providers_response import AppProvidersResponse as AppProvidersResponse
from .file_part_source_param import FilePartSourceParam as FilePartSourceParam
from .session_abort_response import SessionAbortResponse as SessionAbortResponse
-from .step_finish_part_param import StepFinishPartParam as StepFinishPartParam
-from .tool_state_error_param import ToolStateErrorParam as ToolStateErrorParam
from .tui_open_help_response import TuiOpenHelpResponse as TuiOpenHelpResponse
from .session_delete_response import SessionDeleteResponse as SessionDeleteResponse
from .session_summarize_params import SessionSummarizeParams as SessionSummarizeParams
-from .tool_state_pending_param import ToolStatePendingParam as ToolStatePendingParam
-from .tool_state_running_param import ToolStateRunningParam as ToolStateRunningParam
+from .tui_append_prompt_params import TuiAppendPromptParams as TuiAppendPromptParams
from .session_messages_response import SessionMessagesResponse as SessionMessagesResponse
from .session_summarize_response import SessionSummarizeResponse as SessionSummarizeResponse
-from .tool_state_completed_param import ToolStateCompletedParam as ToolStateCompletedParam
+from .tui_append_prompt_response import TuiAppendPromptResponse as TuiAppendPromptResponse
from .file_part_source_text_param import FilePartSourceTextParam as FilePartSourceTextParam
diff --git a/src/opencode_ai/types/event_list_response.py b/src/opencode_ai/types/event_list_response.py
index fd8832b..c45c022 100644
--- a/src/opencode_ai/types/event_list_response.py
+++ b/src/opencode_ai/types/event_list_response.py
@@ -45,6 +45,8 @@ __all__ = [
"EventSessionErrorPropertiesErrorMessageOutputLengthError",
"EventFileWatcherUpdated",
"EventFileWatcherUpdatedProperties",
+ "EventIdeInstalled",
+ "EventIdeInstalledProperties",
]
@@ -214,6 +216,16 @@ class EventFileWatcherUpdated(BaseModel):
type: Literal["file.watcher.updated"]
+class EventIdeInstalledProperties(BaseModel):
+ ide: str
+
+
+class EventIdeInstalled(BaseModel):
+ properties: EventIdeInstalledProperties
+
+ type: Literal["ide.installed"]
+
+
EventListResponse: TypeAlias = Annotated[
Union[
EventLspClientDiagnostics,
@@ -229,6 +241,7 @@ EventListResponse: TypeAlias = Annotated[
EventSessionIdle,
EventSessionError,
EventFileWatcherUpdated,
+ EventIdeInstalled,
],
PropertyInfo(discriminator="type"),
]
diff --git a/src/opencode_ai/types/file_part_param.py b/src/opencode_ai/types/file_part_param.py
deleted file mode 100644
index 9de2723..0000000
--- a/src/opencode_ai/types/file_part_param.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-from .file_part_source_param import FilePartSourceParam
-
-__all__ = ["FilePartParam"]
-
-
-class FilePartParam(TypedDict, total=False):
- id: Required[str]
-
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- mime: Required[str]
-
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
- type: Required[Literal["file"]]
-
- url: Required[str]
-
- filename: str
-
- source: FilePartSourceParam
diff --git a/src/opencode_ai/types/part_param.py b/src/opencode_ai/types/part_param.py
deleted file mode 100644
index 8160b98..0000000
--- a/src/opencode_ai/types/part_param.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Union
-from typing_extensions import TypeAlias
-
-from .file_part_param import FilePartParam
-from .text_part_param import TextPartParam
-from .tool_part_param import ToolPartParam
-from .snapshot_part_param import SnapshotPartParam
-from .step_start_part_param import StepStartPartParam
-from .step_finish_part_param import StepFinishPartParam
-
-__all__ = ["PartParam"]
-
-PartParam: TypeAlias = Union[
- TextPartParam, FilePartParam, ToolPartParam, StepStartPartParam, StepFinishPartParam, SnapshotPartParam
-]
diff --git a/src/opencode_ai/types/snapshot_part_param.py b/src/opencode_ai/types/snapshot_part_param.py
deleted file mode 100644
index 847ba82..0000000
--- a/src/opencode_ai/types/snapshot_part_param.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["SnapshotPartParam"]
-
-
-class SnapshotPartParam(TypedDict, total=False):
- id: Required[str]
-
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
- snapshot: Required[str]
-
- type: Required[Literal["snapshot"]]
diff --git a/src/opencode_ai/types/step_finish_part_param.py b/src/opencode_ai/types/step_finish_part_param.py
deleted file mode 100644
index 4dabb28..0000000
--- a/src/opencode_ai/types/step_finish_part_param.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["StepFinishPartParam", "Tokens", "TokensCache"]
-
-
-class TokensCache(TypedDict, total=False):
- read: Required[float]
-
- write: Required[float]
-
-
-class Tokens(TypedDict, total=False):
- cache: Required[TokensCache]
-
- input: Required[float]
-
- output: Required[float]
-
- reasoning: Required[float]
-
-
-class StepFinishPartParam(TypedDict, total=False):
- id: Required[str]
-
- cost: Required[float]
-
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
- tokens: Required[Tokens]
-
- type: Required[Literal["step-finish"]]
diff --git a/src/opencode_ai/types/step_start_part_param.py b/src/opencode_ai/types/step_start_part_param.py
deleted file mode 100644
index a7d5655..0000000
--- a/src/opencode_ai/types/step_start_part_param.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["StepStartPartParam"]
-
-
-class StepStartPartParam(TypedDict, total=False):
- id: Required[str]
-
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
- type: Required[Literal["step-start"]]
diff --git a/src/opencode_ai/types/text_part_param.py b/src/opencode_ai/types/text_part_param.py
deleted file mode 100644
index 3129256..0000000
--- a/src/opencode_ai/types/text_part_param.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["TextPartParam", "Time"]
-
-
-class Time(TypedDict, total=False):
- start: Required[float]
-
- end: float
-
-
-class TextPartParam(TypedDict, total=False):
- id: Required[str]
-
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
- text: Required[str]
-
- type: Required[Literal["text"]]
-
- synthetic: bool
-
- time: Time
diff --git a/src/opencode_ai/types/tool_part_param.py b/src/opencode_ai/types/tool_part_param.py
deleted file mode 100644
index 559c770..0000000
--- a/src/opencode_ai/types/tool_part_param.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Union
-from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
-
-from .._utils import PropertyInfo
-from .tool_state_error_param import ToolStateErrorParam
-from .tool_state_pending_param import ToolStatePendingParam
-from .tool_state_running_param import ToolStateRunningParam
-from .tool_state_completed_param import ToolStateCompletedParam
-
-__all__ = ["ToolPartParam", "State"]
-
-State: TypeAlias = Union[ToolStatePendingParam, ToolStateRunningParam, ToolStateCompletedParam, ToolStateErrorParam]
-
-
-class ToolPartParam(TypedDict, total=False):
- id: Required[str]
-
- call_id: Required[Annotated[str, PropertyInfo(alias="callID")]]
-
- message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
-
- session_id: Required[Annotated[str, PropertyInfo(alias="sessionID")]]
-
- state: Required[State]
-
- tool: Required[str]
-
- type: Required[Literal["tool"]]
diff --git a/src/opencode_ai/types/tool_state_completed_param.py b/src/opencode_ai/types/tool_state_completed_param.py
deleted file mode 100644
index cea3758..0000000
--- a/src/opencode_ai/types/tool_state_completed_param.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Dict
-from typing_extensions import Literal, Required, TypedDict
-
-__all__ = ["ToolStateCompletedParam", "Time"]
-
-
-class Time(TypedDict, total=False):
- end: Required[float]
-
- start: Required[float]
-
-
-class ToolStateCompletedParam(TypedDict, total=False):
- input: Required[Dict[str, object]]
-
- metadata: Required[Dict[str, object]]
-
- output: Required[str]
-
- status: Required[Literal["completed"]]
-
- time: Required[Time]
-
- title: Required[str]
diff --git a/src/opencode_ai/types/tool_state_error_param.py b/src/opencode_ai/types/tool_state_error_param.py
deleted file mode 100644
index 7622868..0000000
--- a/src/opencode_ai/types/tool_state_error_param.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Dict
-from typing_extensions import Literal, Required, TypedDict
-
-__all__ = ["ToolStateErrorParam", "Time"]
-
-
-class Time(TypedDict, total=False):
- end: Required[float]
-
- start: Required[float]
-
-
-class ToolStateErrorParam(TypedDict, total=False):
- error: Required[str]
-
- input: Required[Dict[str, object]]
-
- status: Required[Literal["error"]]
-
- time: Required[Time]
diff --git a/src/opencode_ai/types/tool_state_pending_param.py b/src/opencode_ai/types/tool_state_pending_param.py
deleted file mode 100644
index d375cd5..0000000
--- a/src/opencode_ai/types/tool_state_pending_param.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-__all__ = ["ToolStatePendingParam"]
-
-
-class ToolStatePendingParam(TypedDict, total=False):
- status: Required[Literal["pending"]]
diff --git a/src/opencode_ai/types/tool_state_running_param.py b/src/opencode_ai/types/tool_state_running_param.py
deleted file mode 100644
index 1814d43..0000000
--- a/src/opencode_ai/types/tool_state_running_param.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Dict
-from typing_extensions import Literal, Required, TypedDict
-
-__all__ = ["ToolStateRunningParam", "Time"]
-
-
-class Time(TypedDict, total=False):
- start: Required[float]
-
-
-class ToolStateRunningParam(TypedDict, total=False):
- status: Required[Literal["running"]]
-
- time: Required[Time]
-
- input: object
-
- metadata: Dict[str, object]
-
- title: str
diff --git a/src/opencode_ai/types/tui_prompt_params.py b/src/opencode_ai/types/tui_append_prompt_params.py
similarity index 52%
rename from src/opencode_ai/types/tui_prompt_params.py
rename to src/opencode_ai/types/tui_append_prompt_params.py
index be85887..431f731 100644
--- a/src/opencode_ai/types/tui_prompt_params.py
+++ b/src/opencode_ai/types/tui_append_prompt_params.py
@@ -2,15 +2,10 @@
from __future__ import annotations
-from typing import Iterable
from typing_extensions import Required, TypedDict
-from .part_param import PartParam
-
-__all__ = ["TuiPromptParams"]
+__all__ = ["TuiAppendPromptParams"]
-class TuiPromptParams(TypedDict, total=False):
- parts: Required[Iterable[PartParam]]
-
+class TuiAppendPromptParams(TypedDict, total=False):
text: Required[str]
diff --git a/src/opencode_ai/types/tui_prompt_response.py b/src/opencode_ai/types/tui_append_prompt_response.py
similarity index 61%
rename from src/opencode_ai/types/tui_prompt_response.py
rename to src/opencode_ai/types/tui_append_prompt_response.py
index 95dde9e..85b6813 100644
--- a/src/opencode_ai/types/tui_prompt_response.py
+++ b/src/opencode_ai/types/tui_append_prompt_response.py
@@ -2,6 +2,6 @@
from typing_extensions import TypeAlias
-__all__ = ["TuiPromptResponse"]
+__all__ = ["TuiAppendPromptResponse"]
-TuiPromptResponse: TypeAlias = bool
+TuiAppendPromptResponse: TypeAlias = bool
diff --git a/tests/api_resources/test_tui.py b/tests/api_resources/test_tui.py
index 6478963..50f907a 100644
--- a/tests/api_resources/test_tui.py
+++ b/tests/api_resources/test_tui.py
@@ -9,7 +9,7 @@ import pytest
from opencode_ai import Opencode, AsyncOpencode
from tests.utils import assert_matches_type
-from opencode_ai.types import TuiPromptResponse, TuiOpenHelpResponse
+from opencode_ai.types import TuiOpenHelpResponse, TuiAppendPromptResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,6 +17,40 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestTui:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_append_prompt(self, client: Opencode) -> None:
+ tui = client.tui.append_prompt(
+ text="text",
+ )
+ assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_raw_response_append_prompt(self, client: Opencode) -> None:
+ response = client.tui.with_raw_response.append_prompt(
+ text="text",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ tui = response.parse()
+ assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_streaming_response_append_prompt(self, client: Opencode) -> None:
+ with client.tui.with_streaming_response.append_prompt(
+ text="text",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ tui = response.parse()
+ assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip()
@parametrize
def test_method_open_help(self, client: Opencode) -> None:
@@ -45,73 +79,46 @@ class TestTui:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
- @parametrize
- def test_method_prompt(self, client: Opencode) -> None:
- tui = client.tui.prompt(
- parts=[
- {
- "id": "id",
- "message_id": "messageID",
- "session_id": "sessionID",
- "text": "text",
- "type": "text",
- }
- ],
- text="text",
- )
- assert_matches_type(TuiPromptResponse, tui, path=["response"])
-
- @pytest.mark.skip()
- @parametrize
- def test_raw_response_prompt(self, client: Opencode) -> None:
- response = client.tui.with_raw_response.prompt(
- parts=[
- {
- "id": "id",
- "message_id": "messageID",
- "session_id": "sessionID",
- "text": "text",
- "type": "text",
- }
- ],
- text="text",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tui = response.parse()
- assert_matches_type(TuiPromptResponse, tui, path=["response"])
-
- @pytest.mark.skip()
- @parametrize
- def test_streaming_response_prompt(self, client: Opencode) -> None:
- with client.tui.with_streaming_response.prompt(
- parts=[
- {
- "id": "id",
- "message_id": "messageID",
- "session_id": "sessionID",
- "text": "text",
- "type": "text",
- }
- ],
- text="text",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tui = response.parse()
- assert_matches_type(TuiPromptResponse, tui, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
class TestAsyncTui:
parametrize = pytest.mark.parametrize(
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_append_prompt(self, async_client: AsyncOpencode) -> None:
+ tui = await async_client.tui.append_prompt(
+ text="text",
+ )
+ assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_raw_response_append_prompt(self, async_client: AsyncOpencode) -> None:
+ response = await async_client.tui.with_raw_response.append_prompt(
+ text="text",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ tui = await response.parse()
+ assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_streaming_response_append_prompt(self, async_client: AsyncOpencode) -> None:
+ async with async_client.tui.with_streaming_response.append_prompt(
+ text="text",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ tui = await response.parse()
+ assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip()
@parametrize
async def test_method_open_help(self, async_client: AsyncOpencode) -> None:
@@ -139,64 +146,3 @@ class TestAsyncTui:
assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip()
- @parametrize
- async def test_method_prompt(self, async_client: AsyncOpencode) -> None:
- tui = await async_client.tui.prompt(
- parts=[
- {
- "id": "id",
- "message_id": "messageID",
- "session_id": "sessionID",
- "text": "text",
- "type": "text",
- }
- ],
- text="text",
- )
- assert_matches_type(TuiPromptResponse, tui, path=["response"])
-
- @pytest.mark.skip()
- @parametrize
- async def test_raw_response_prompt(self, async_client: AsyncOpencode) -> None:
- response = await async_client.tui.with_raw_response.prompt(
- parts=[
- {
- "id": "id",
- "message_id": "messageID",
- "session_id": "sessionID",
- "text": "text",
- "type": "text",
- }
- ],
- text="text",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tui = await response.parse()
- assert_matches_type(TuiPromptResponse, tui, path=["response"])
-
- @pytest.mark.skip()
- @parametrize
- async def test_streaming_response_prompt(self, async_client: AsyncOpencode) -> None:
- async with async_client.tui.with_streaming_response.prompt(
- parts=[
- {
- "id": "id",
- "message_id": "messageID",
- "session_id": "sessionID",
- "text": "text",
- "type": "text",
- }
- ],
- text="text",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tui = await response.parse()
- assert_matches_type(TuiPromptResponse, tui, path=["response"])
-
- assert cast(Any, response.is_closed) is True
From 1bddb4b6c324a85a1164dc65b6d0e1662eb72c45 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 22 Jul 2025 16:09:10 +0000
Subject: [PATCH 23/50] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 1ec884c..f188454 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 24
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-7f559270c87d0cbb6779d0edd57a2efcb4d60932674cea4444c40cd4e7b72569.yml
-openapi_spec_hash: 531acdc4f16185743ec56b3e07857cde
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-9574184bd9e916aa69eae8e26e0679556038d3fcfb4009a445c97c6cc3e4f3ee.yml
+openapi_spec_hash: 93ba1215ab0dc853a1691b049cc47d75
config_hash: 6d92d798d44906c9e43c6dee06615360
From f2d28d2990839acdf5343694f6eb6366cef01b64 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 22 Jul 2025 16:09:26 +0000
Subject: [PATCH 24/50] release: 0.1.0-alpha.28
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 7657c56..f471069 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.27"
+ ".": "0.1.0-alpha.28"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de31979..d516cad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.28 (2025-07-22)
+
+Full Changelog: [v0.1.0-alpha.27...v0.1.0-alpha.28](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.27...v0.1.0-alpha.28)
+
+### Features
+
+* **api:** api update ([e8022cd](https://github.com/sst/opencode-sdk-python/commit/e8022cd6d313c1c710dc2721f7e962285d48b02e))
+
## 0.1.0-alpha.27 (2025-07-22)
Full Changelog: [v0.1.0-alpha.26...v0.1.0-alpha.27](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.26...v0.1.0-alpha.27)
diff --git a/pyproject.toml b/pyproject.toml
index 5ab2607..9d9158e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.27"
+version = "0.1.0-alpha.28"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index f753b1d..0c9d183 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.27" # x-release-please-version
+__version__ = "0.1.0-alpha.28" # x-release-please-version
From 5f9e3cd00428a3a99dcf3410f512e19ccf47f9d0 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 22 Jul 2025 21:55:21 +0000
Subject: [PATCH 25/50] feat(api): api update
---
.stats.yml | 8 +-
LICENSE | 202 +-----------------
api.md | 2 +
pyproject.toml | 4 +-
src/opencode_ai/resources/session.py | 176 ++++++++++++++-
src/opencode_ai/types/__init__.py | 1 +
src/opencode_ai/types/keybinds_config.py | 8 +-
src/opencode_ai/types/session.py | 2 +-
.../types/session_revert_params.py | 15 ++
tests/api_resources/test_session.py | 196 +++++++++++++++++
10 files changed, 407 insertions(+), 207 deletions(-)
create mode 100644 src/opencode_ai/types/session_revert_params.py
diff --git a/.stats.yml b/.stats.yml
index f188454..da0b08b 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 24
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-9574184bd9e916aa69eae8e26e0679556038d3fcfb4009a445c97c6cc3e4f3ee.yml
-openapi_spec_hash: 93ba1215ab0dc853a1691b049cc47d75
-config_hash: 6d92d798d44906c9e43c6dee06615360
+configured_endpoints: 26
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-1efc45c35b58e88b0550fbb0c7a204ef66522742f87c9e29c76a18b120c0d945.yml
+openapi_spec_hash: 5e15d85e4704624f9b13bae1c71aa416
+config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/LICENSE b/LICENSE
index a56ceac..821edeb 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,201 +1,7 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
+Copyright 2025 opencode
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- 1. Definitions.
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright 2025 Opencode
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/api.md b/api.md
index 67407e9..1758023 100644
--- a/api.md
+++ b/api.md
@@ -131,8 +131,10 @@ Methods:
- client.session.chat(id, \*\*params) -> AssistantMessage
- client.session.init(id, \*\*params) -> SessionInitResponse
- client.session.messages(id) -> SessionMessagesResponse
+- client.session.revert(id, \*\*params) -> Session
- client.session.share(id) -> Session
- client.session.summarize(id, \*\*params) -> SessionSummarizeResponse
+- client.session.unrevert(id) -> Session
- client.session.unshare(id) -> Session
# Tui
diff --git a/pyproject.toml b/pyproject.toml
index 9d9158e..2bcc1bd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -3,7 +3,7 @@ name = "opencode-ai"
version = "0.1.0-alpha.28"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
-license = "Apache-2.0"
+license = "MIT"
authors = [
{ name = "Opencode", email = "support@sst.dev" },
]
@@ -31,7 +31,7 @@ classifiers = [
"Operating System :: POSIX :: Linux",
"Operating System :: Microsoft :: Windows",
"Topic :: Software Development :: Libraries :: Python Modules",
- "License :: OSI Approved :: Apache Software License"
+ "License :: OSI Approved :: MIT License"
]
[project.urls]
diff --git a/src/opencode_ai/resources/session.py b/src/opencode_ai/resources/session.py
index baf2060..9096fec 100644
--- a/src/opencode_ai/resources/session.py
+++ b/src/opencode_ai/resources/session.py
@@ -6,7 +6,7 @@ from typing import Dict, Iterable
import httpx
-from ..types import session_chat_params, session_init_params, session_summarize_params
+from ..types import session_chat_params, session_init_params, session_revert_params, session_summarize_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -287,6 +287,48 @@ class SessionResource(SyncAPIResource):
cast_to=SessionMessagesResponse,
)
+ def revert(
+ self,
+ id: str,
+ *,
+ message_id: str,
+ part_id: str | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> Session:
+ """
+ Revert a message
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._post(
+ f"/session/{id}/revert",
+ body=maybe_transform(
+ {
+ "message_id": message_id,
+ "part_id": part_id,
+ },
+ session_revert_params.SessionRevertParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Session,
+ )
+
def share(
self,
id: str,
@@ -364,6 +406,39 @@ class SessionResource(SyncAPIResource):
cast_to=SessionSummarizeResponse,
)
+ def unrevert(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> Session:
+ """
+ Restore all reverted messages
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._post(
+ f"/session/{id}/unrevert",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Session,
+ )
+
def unshare(
self,
id: str,
@@ -655,6 +730,48 @@ class AsyncSessionResource(AsyncAPIResource):
cast_to=SessionMessagesResponse,
)
+ async def revert(
+ self,
+ id: str,
+ *,
+ message_id: str,
+ part_id: str | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> Session:
+ """
+ Revert a message
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._post(
+ f"/session/{id}/revert",
+ body=await async_maybe_transform(
+ {
+ "message_id": message_id,
+ "part_id": part_id,
+ },
+ session_revert_params.SessionRevertParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Session,
+ )
+
async def share(
self,
id: str,
@@ -732,6 +849,39 @@ class AsyncSessionResource(AsyncAPIResource):
cast_to=SessionSummarizeResponse,
)
+ async def unrevert(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> Session:
+ """
+ Restore all reverted messages
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._post(
+ f"/session/{id}/unrevert",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Session,
+ )
+
async def unshare(
self,
id: str,
@@ -791,12 +941,18 @@ class SessionResourceWithRawResponse:
self.messages = to_raw_response_wrapper(
session.messages,
)
+ self.revert = to_raw_response_wrapper(
+ session.revert,
+ )
self.share = to_raw_response_wrapper(
session.share,
)
self.summarize = to_raw_response_wrapper(
session.summarize,
)
+ self.unrevert = to_raw_response_wrapper(
+ session.unrevert,
+ )
self.unshare = to_raw_response_wrapper(
session.unshare,
)
@@ -827,12 +983,18 @@ class AsyncSessionResourceWithRawResponse:
self.messages = async_to_raw_response_wrapper(
session.messages,
)
+ self.revert = async_to_raw_response_wrapper(
+ session.revert,
+ )
self.share = async_to_raw_response_wrapper(
session.share,
)
self.summarize = async_to_raw_response_wrapper(
session.summarize,
)
+ self.unrevert = async_to_raw_response_wrapper(
+ session.unrevert,
+ )
self.unshare = async_to_raw_response_wrapper(
session.unshare,
)
@@ -863,12 +1025,18 @@ class SessionResourceWithStreamingResponse:
self.messages = to_streamed_response_wrapper(
session.messages,
)
+ self.revert = to_streamed_response_wrapper(
+ session.revert,
+ )
self.share = to_streamed_response_wrapper(
session.share,
)
self.summarize = to_streamed_response_wrapper(
session.summarize,
)
+ self.unrevert = to_streamed_response_wrapper(
+ session.unrevert,
+ )
self.unshare = to_streamed_response_wrapper(
session.unshare,
)
@@ -899,12 +1067,18 @@ class AsyncSessionResourceWithStreamingResponse:
self.messages = async_to_streamed_response_wrapper(
session.messages,
)
+ self.revert = async_to_streamed_response_wrapper(
+ session.revert,
+ )
self.share = async_to_streamed_response_wrapper(
session.share,
)
self.summarize = async_to_streamed_response_wrapper(
session.summarize,
)
+ self.unrevert = async_to_streamed_response_wrapper(
+ session.unrevert,
+ )
self.unshare = async_to_streamed_response_wrapper(
session.unshare,
)
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index 0da9c61..2dc9b99 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -59,6 +59,7 @@ from .file_part_source_text import FilePartSourceText as FilePartSourceText
from .find_symbols_response import FindSymbolsResponse as FindSymbolsResponse
from .session_init_response import SessionInitResponse as SessionInitResponse
from .session_list_response import SessionListResponse as SessionListResponse
+from .session_revert_params import SessionRevertParams as SessionRevertParams
from .text_part_input_param import TextPartInputParam as TextPartInputParam
from .app_providers_response import AppProvidersResponse as AppProvidersResponse
from .file_part_source_param import FilePartSourceParam as FilePartSourceParam
diff --git a/src/opencode_ai/types/keybinds_config.py b/src/opencode_ai/types/keybinds_config.py
index ca53231..c7cb57c 100644
--- a/src/opencode_ai/types/keybinds_config.py
+++ b/src/opencode_ai/types/keybinds_config.py
@@ -74,8 +74,14 @@ class KeybindsConfig(BaseModel):
messages_previous: str
"""Navigate to previous message"""
+ messages_redo: str
+ """Redo message"""
+
messages_revert: str
- """Revert message"""
+ """@deprecated use messages_undo. Revert message"""
+
+ messages_undo: str
+ """Undo message"""
api_model_list: str = FieldInfo(alias="model_list")
"""List available models"""
diff --git a/src/opencode_ai/types/session.py b/src/opencode_ai/types/session.py
index e7c4967..88b53ea 100644
--- a/src/opencode_ai/types/session.py
+++ b/src/opencode_ai/types/session.py
@@ -18,7 +18,7 @@ class Time(BaseModel):
class Revert(BaseModel):
message_id: str = FieldInfo(alias="messageID")
- part: float
+ part_id: Optional[str] = FieldInfo(alias="partID", default=None)
snapshot: Optional[str] = None
diff --git a/src/opencode_ai/types/session_revert_params.py b/src/opencode_ai/types/session_revert_params.py
new file mode 100644
index 0000000..e5361ee
--- /dev/null
+++ b/src/opencode_ai/types/session_revert_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["SessionRevertParams"]
+
+
+class SessionRevertParams(TypedDict, total=False):
+ message_id: Required[Annotated[str, PropertyInfo(alias="messageID")]]
+
+ part_id: Annotated[str, PropertyInfo(alias="partID")]
diff --git a/tests/api_resources/test_session.py b/tests/api_resources/test_session.py
index 08ecc09..c078c7b 100644
--- a/tests/api_resources/test_session.py
+++ b/tests/api_resources/test_session.py
@@ -361,6 +361,62 @@ class TestSession:
"",
)
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_revert(self, client: Opencode) -> None:
+ session = client.session.revert(
+ id="id",
+ message_id="msg",
+ )
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_revert_with_all_params(self, client: Opencode) -> None:
+ session = client.session.revert(
+ id="id",
+ message_id="msg",
+ part_id="prt",
+ )
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_raw_response_revert(self, client: Opencode) -> None:
+ response = client.session.with_raw_response.revert(
+ id="id",
+ message_id="msg",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = response.parse()
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_streaming_response_revert(self, client: Opencode) -> None:
+ with client.session.with_streaming_response.revert(
+ id="id",
+ message_id="msg",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = response.parse()
+ assert_matches_type(Session, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_path_params_revert(self, client: Opencode) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.session.with_raw_response.revert(
+ id="",
+ message_id="msg",
+ )
+
@pytest.mark.skip()
@parametrize
def test_method_share(self, client: Opencode) -> None:
@@ -453,6 +509,48 @@ class TestSession:
provider_id="providerID",
)
+ @pytest.mark.skip()
+ @parametrize
+ def test_method_unrevert(self, client: Opencode) -> None:
+ session = client.session.unrevert(
+ "id",
+ )
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_raw_response_unrevert(self, client: Opencode) -> None:
+ response = client.session.with_raw_response.unrevert(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = response.parse()
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_streaming_response_unrevert(self, client: Opencode) -> None:
+ with client.session.with_streaming_response.unrevert(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = response.parse()
+ assert_matches_type(Session, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip()
+ @parametrize
+ def test_path_params_unrevert(self, client: Opencode) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.session.with_raw_response.unrevert(
+ "",
+ )
+
@pytest.mark.skip()
@parametrize
def test_method_unshare(self, client: Opencode) -> None:
@@ -836,6 +934,62 @@ class TestAsyncSession:
"",
)
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_revert(self, async_client: AsyncOpencode) -> None:
+ session = await async_client.session.revert(
+ id="id",
+ message_id="msg",
+ )
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_revert_with_all_params(self, async_client: AsyncOpencode) -> None:
+ session = await async_client.session.revert(
+ id="id",
+ message_id="msg",
+ part_id="prt",
+ )
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_raw_response_revert(self, async_client: AsyncOpencode) -> None:
+ response = await async_client.session.with_raw_response.revert(
+ id="id",
+ message_id="msg",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = await response.parse()
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_streaming_response_revert(self, async_client: AsyncOpencode) -> None:
+ async with async_client.session.with_streaming_response.revert(
+ id="id",
+ message_id="msg",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = await response.parse()
+ assert_matches_type(Session, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_path_params_revert(self, async_client: AsyncOpencode) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.session.with_raw_response.revert(
+ id="",
+ message_id="msg",
+ )
+
@pytest.mark.skip()
@parametrize
async def test_method_share(self, async_client: AsyncOpencode) -> None:
@@ -928,6 +1082,48 @@ class TestAsyncSession:
provider_id="providerID",
)
+ @pytest.mark.skip()
+ @parametrize
+ async def test_method_unrevert(self, async_client: AsyncOpencode) -> None:
+ session = await async_client.session.unrevert(
+ "id",
+ )
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_raw_response_unrevert(self, async_client: AsyncOpencode) -> None:
+ response = await async_client.session.with_raw_response.unrevert(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = await response.parse()
+ assert_matches_type(Session, session, path=["response"])
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_streaming_response_unrevert(self, async_client: AsyncOpencode) -> None:
+ async with async_client.session.with_streaming_response.unrevert(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = await response.parse()
+ assert_matches_type(Session, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip()
+ @parametrize
+ async def test_path_params_unrevert(self, async_client: AsyncOpencode) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.session.with_raw_response.unrevert(
+ "",
+ )
+
@pytest.mark.skip()
@parametrize
async def test_method_unshare(self, async_client: AsyncOpencode) -> None:
From 646b99cd2434860a9a361f26b107b4e449b2965d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 22 Jul 2025 21:55:39 +0000
Subject: [PATCH 26/50] release: 0.1.0-alpha.29
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index f471069..c412e97 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.28"
+ ".": "0.1.0-alpha.29"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d516cad..5d3cd49 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.29 (2025-07-22)
+
+Full Changelog: [v0.1.0-alpha.28...v0.1.0-alpha.29](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.28...v0.1.0-alpha.29)
+
+### Features
+
+* **api:** api update ([08130f0](https://github.com/sst/opencode-sdk-python/commit/08130f0c068f4008ffda297c68a68a44dec34d95))
+
## 0.1.0-alpha.28 (2025-07-22)
Full Changelog: [v0.1.0-alpha.27...v0.1.0-alpha.28](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.27...v0.1.0-alpha.28)
diff --git a/pyproject.toml b/pyproject.toml
index 2bcc1bd..a58ac90 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.28"
+version = "0.1.0-alpha.29"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 0c9d183..5002818 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.28" # x-release-please-version
+__version__ = "0.1.0-alpha.29" # x-release-please-version
From 0a269c0379ce99d78459b0779c91821b61d3b0d1 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 23 Jul 2025 02:01:57 +0000
Subject: [PATCH 27/50] fix(parsing): parse extra field types
---
src/opencode_ai/_models.py | 25 +++++++++++++++++++++++--
src/opencode_ai/types/config.py | 1 +
tests/test_models.py | 29 ++++++++++++++++++++++++++++-
3 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/src/opencode_ai/_models.py b/src/opencode_ai/_models.py
index ffcbf67..b8387ce 100644
--- a/src/opencode_ai/_models.py
+++ b/src/opencode_ai/_models.py
@@ -208,14 +208,18 @@ class BaseModel(pydantic.BaseModel):
else:
fields_values[name] = field_get_default(field)
+ extra_field_type = _get_extra_fields_type(__cls)
+
_extra = {}
for key, value in values.items():
if key not in model_fields:
+ parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type is not None else value
+
if PYDANTIC_V2:
- _extra[key] = value
+ _extra[key] = parsed
else:
_fields_set.add(key)
- fields_values[key] = value
+ fields_values[key] = parsed
object.__setattr__(m, "__dict__", fields_values)
@@ -370,6 +374,23 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object:
return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None))
+def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None:
+ if not PYDANTIC_V2:
+ # TODO
+ return None
+
+ schema = cls.__pydantic_core_schema__
+ if schema["type"] == "model":
+ fields = schema["schema"]
+ if fields["type"] == "model-fields":
+ extras = fields.get("extras_schema")
+ if extras and "cls" in extras:
+ # mypy can't narrow the type
+ return extras["cls"] # type: ignore[no-any-return]
+
+ return None
+
+
def is_basemodel(type_: type) -> bool:
"""Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`"""
if is_union(type_):
diff --git a/src/opencode_ai/types/config.py b/src/opencode_ai/types/config.py
index 927bfc5..4073748 100644
--- a/src/opencode_ai/types/config.py
+++ b/src/opencode_ai/types/config.py
@@ -57,6 +57,7 @@ class Mode(BaseModel):
plan: Optional[ModeConfig] = None
+ __pydantic_extra__: Dict[str, ModeConfig] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
if TYPE_CHECKING:
# Stub to indicate that arbitrary properties are accepted.
# To access properties that are not valid identifiers you can use `getattr`, e.g.
diff --git a/tests/test_models.py b/tests/test_models.py
index 3c3774b..94fa22d 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -1,5 +1,5 @@
import json
-from typing import Any, Dict, List, Union, Optional, cast
+from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast
from datetime import datetime, timezone
from typing_extensions import Literal, Annotated, TypeAliasType
@@ -934,3 +934,30 @@ def test_nested_discriminated_union() -> None:
)
assert isinstance(model, Type1)
assert isinstance(model.value, InnerType2)
+
+
+@pytest.mark.skipif(not PYDANTIC_V2, reason="this is only supported in pydantic v2 for now")
+def test_extra_properties() -> None:
+ class Item(BaseModel):
+ prop: int
+
+ class Model(BaseModel):
+ __pydantic_extra__: Dict[str, Item] = Field(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
+
+ other: str
+
+ if TYPE_CHECKING:
+
+ def __getattr__(self, attr: str) -> Item: ...
+
+ model = construct_type(
+ type_=Model,
+ value={
+ "a": {"prop": 1},
+ "other": "foo",
+ },
+ )
+ assert isinstance(model, Model)
+ assert model.a.prop == 1
+ assert isinstance(model.a, Item)
+ assert model.other == "foo"
From 8b4a7b17fc36e06c7369c248589c13b2f37ca678 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 23 Jul 2025 02:02:42 +0000
Subject: [PATCH 28/50] release: 0.1.0-alpha.30
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index c412e97..52b3e83 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.29"
+ ".": "0.1.0-alpha.30"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5d3cd49..a130084 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.30 (2025-07-23)
+
+Full Changelog: [v0.1.0-alpha.29...v0.1.0-alpha.30](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.29...v0.1.0-alpha.30)
+
+### Bug Fixes
+
+* **parsing:** parse extra field types ([6817656](https://github.com/sst/opencode-sdk-python/commit/6817656ba347e8074960af1526763c134d75cf7d))
+
## 0.1.0-alpha.29 (2025-07-22)
Full Changelog: [v0.1.0-alpha.28...v0.1.0-alpha.29](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.28...v0.1.0-alpha.29)
diff --git a/pyproject.toml b/pyproject.toml
index a58ac90..45c2fa2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.29"
+version = "0.1.0-alpha.30"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 5002818..540b5ff 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.29" # x-release-please-version
+__version__ = "0.1.0-alpha.30" # x-release-please-version
From 4c0117a6c5c7ddd26540a6f98977f6347ad32956 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 24 Jul 2025 01:49:21 +0000
Subject: [PATCH 29/50] feat(api): api update
---
.stats.yml | 4 ++--
src/opencode_ai/types/assistant_message.py | 2 ++
src/opencode_ai/types/config.py | 16 +++++++++++++++-
src/opencode_ai/types/event_list_response.py | 15 +++++++++++++++
4 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index da0b08b..7bbe576 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 26
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-1efc45c35b58e88b0550fbb0c7a204ef66522742f87c9e29c76a18b120c0d945.yml
-openapi_spec_hash: 5e15d85e4704624f9b13bae1c71aa416
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-335697785b44f3928145853339226bd5e8accd5199bb9d79e2a3fd2d8ce62a57.yml
+openapi_spec_hash: 74fbaad0fa44496d0d8b11d9b98eab03
config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/src/opencode_ai/types/assistant_message.py b/src/opencode_ai/types/assistant_message.py
index c6b906e..490f829 100644
--- a/src/opencode_ai/types/assistant_message.py
+++ b/src/opencode_ai/types/assistant_message.py
@@ -59,6 +59,8 @@ class AssistantMessage(BaseModel):
cost: float
+ mode: str
+
api_model_id: str = FieldInfo(alias="modelID")
path: Path
diff --git a/src/opencode_ai/types/config.py b/src/opencode_ai/types/config.py
index 4073748..2a0bfff 100644
--- a/src/opencode_ai/types/config.py
+++ b/src/opencode_ai/types/config.py
@@ -24,6 +24,7 @@ __all__ = [
"ProviderModels",
"ProviderModelsCost",
"ProviderModelsLimit",
+ "ProviderOptions",
]
@@ -103,6 +104,19 @@ class ProviderModels(BaseModel):
tool_call: Optional[bool] = None
+class ProviderOptions(BaseModel):
+ api_key: Optional[str] = FieldInfo(alias="apiKey", default=None)
+
+ base_url: Optional[str] = FieldInfo(alias="baseURL", default=None)
+
+ __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
+ if TYPE_CHECKING:
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> object: ...
+
+
class Provider(BaseModel):
models: Dict[str, ProviderModels]
@@ -116,7 +130,7 @@ class Provider(BaseModel):
npm: Optional[str] = None
- options: Optional[Dict[str, object]] = None
+ options: Optional[ProviderOptions] = None
class Config(BaseModel):
diff --git a/src/opencode_ai/types/event_list_response.py b/src/opencode_ai/types/event_list_response.py
index c45c022..9c6d78f 100644
--- a/src/opencode_ai/types/event_list_response.py
+++ b/src/opencode_ai/types/event_list_response.py
@@ -31,6 +31,8 @@ __all__ = [
"EventMessageRemovedProperties",
"EventMessagePartUpdated",
"EventMessagePartUpdatedProperties",
+ "EventMessagePartRemoved",
+ "EventMessagePartRemovedProperties",
"EventStorageWrite",
"EventStorageWriteProperties",
"EventSessionUpdated",
@@ -136,6 +138,18 @@ class EventMessagePartUpdated(BaseModel):
type: Literal["message.part.updated"]
+class EventMessagePartRemovedProperties(BaseModel):
+ message_id: str = FieldInfo(alias="messageID")
+
+ part_id: str = FieldInfo(alias="partID")
+
+
+class EventMessagePartRemoved(BaseModel):
+ properties: EventMessagePartRemovedProperties
+
+ type: Literal["message.part.removed"]
+
+
class EventStorageWriteProperties(BaseModel):
key: str
@@ -235,6 +249,7 @@ EventListResponse: TypeAlias = Annotated[
EventMessageUpdated,
EventMessageRemoved,
EventMessagePartUpdated,
+ EventMessagePartRemoved,
EventStorageWrite,
EventSessionUpdated,
EventSessionDeleted,
From 10a8dac1d72870faddb55422ea45d04ef29a24d4 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 24 Jul 2025 01:49:37 +0000
Subject: [PATCH 30/50] release: 0.1.0-alpha.31
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 52b3e83..a899ac7 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.30"
+ ".": "0.1.0-alpha.31"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a130084..65e07bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.31 (2025-07-24)
+
+Full Changelog: [v0.1.0-alpha.30...v0.1.0-alpha.31](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.30...v0.1.0-alpha.31)
+
+### Features
+
+* **api:** api update ([35553a6](https://github.com/sst/opencode-sdk-python/commit/35553a6e3b3472562cdc38f0399fcd37af1b52e9))
+
## 0.1.0-alpha.30 (2025-07-23)
Full Changelog: [v0.1.0-alpha.29...v0.1.0-alpha.30](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.29...v0.1.0-alpha.30)
diff --git a/pyproject.toml b/pyproject.toml
index 45c2fa2..7b034c4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.30"
+version = "0.1.0-alpha.31"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 540b5ff..1e6659f 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.30" # x-release-please-version
+__version__ = "0.1.0-alpha.31" # x-release-please-version
From c75867efe79abf38fca282f72e9d7ba2820900d3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 24 Jul 2025 04:08:34 +0000
Subject: [PATCH 31/50] feat(api): api update
---
.stats.yml | 4 ++--
api.md | 1 +
src/opencode_ai/resources/app.py | 8 ++++----
src/opencode_ai/types/__init__.py | 1 +
src/opencode_ai/types/app_log_params.py | 6 ++++--
src/opencode_ai/types/log_level.py | 7 +++++++
6 files changed, 19 insertions(+), 8 deletions(-)
create mode 100644 src/opencode_ai/types/log_level.py
diff --git a/.stats.yml b/.stats.yml
index 7bbe576..59e6768 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 26
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-335697785b44f3928145853339226bd5e8accd5199bb9d79e2a3fd2d8ce62a57.yml
-openapi_spec_hash: 74fbaad0fa44496d0d8b11d9b98eab03
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-fb4caa8d0381531c44dd2d3c8c0b930b8c15a7bdde474d15bf7aeeb3b27aef56.yml
+openapi_spec_hash: 3a263e46f2369eeb2410430001c60d15
config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/api.md b/api.md
index 1758023..c5eafcf 100644
--- a/api.md
+++ b/api.md
@@ -23,6 +23,7 @@ Types:
```python
from opencode_ai.types import (
App,
+ LogLevel,
Mode,
Model,
Provider,
diff --git a/src/opencode_ai/resources/app.py b/src/opencode_ai/resources/app.py
index e9505ce..44fe939 100644
--- a/src/opencode_ai/resources/app.py
+++ b/src/opencode_ai/resources/app.py
@@ -3,11 +3,10 @@
from __future__ import annotations
from typing import Dict
-from typing_extensions import Literal
import httpx
-from ..types import app_log_params
+from ..types import LogLevel, app_log_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -20,6 +19,7 @@ from .._response import (
)
from ..types.app import App
from .._base_client import make_request_options
+from ..types.log_level import LogLevel
from ..types.app_log_response import AppLogResponse
from ..types.app_init_response import AppInitResponse
from ..types.app_modes_response import AppModesResponse
@@ -89,7 +89,7 @@ class AppResource(SyncAPIResource):
def log(
self,
*,
- level: Literal["debug", "info", "error", "warn"],
+ level: LogLevel,
message: str,
service: str,
extra: Dict[str, object] | NotGiven = NOT_GIVEN,
@@ -237,7 +237,7 @@ class AsyncAppResource(AsyncAPIResource):
async def log(
self,
*,
- level: Literal["debug", "info", "error", "warn"],
+ level: LogLevel,
message: str,
service: str,
extra: Dict[str, object] | NotGiven = NOT_GIVEN,
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index 2dc9b99..e7b46d8 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -19,6 +19,7 @@ from .message import Message as Message
from .session import Session as Session
from .provider import Provider as Provider
from .file_part import FilePart as FilePart
+from .log_level import LogLevel as LogLevel
from .text_part import TextPart as TextPart
from .tool_part import ToolPart as ToolPart
from .file_source import FileSource as FileSource
diff --git a/src/opencode_ai/types/app_log_params.py b/src/opencode_ai/types/app_log_params.py
index 8b24c11..105b5a4 100644
--- a/src/opencode_ai/types/app_log_params.py
+++ b/src/opencode_ai/types/app_log_params.py
@@ -3,13 +3,15 @@
from __future__ import annotations
from typing import Dict
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .log_level import LogLevel
__all__ = ["AppLogParams"]
class AppLogParams(TypedDict, total=False):
- level: Required[Literal["debug", "info", "error", "warn"]]
+ level: Required[LogLevel]
"""Log level"""
message: Required[str]
diff --git a/src/opencode_ai/types/log_level.py b/src/opencode_ai/types/log_level.py
new file mode 100644
index 0000000..c5138ea
--- /dev/null
+++ b/src/opencode_ai/types/log_level.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["LogLevel"]
+
+LogLevel: TypeAlias = Literal["debug", "info", "error", "warn"]
From 45b4e6015459b1bac420d985905effdb815d12cb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 24 Jul 2025 04:08:52 +0000
Subject: [PATCH 32/50] release: 0.1.0-alpha.32
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index a899ac7..2ce25fe 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.31"
+ ".": "0.1.0-alpha.32"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 65e07bb..5088d68 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.32 (2025-07-24)
+
+Full Changelog: [v0.1.0-alpha.31...v0.1.0-alpha.32](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.31...v0.1.0-alpha.32)
+
+### Features
+
+* **api:** api update ([988b38c](https://github.com/sst/opencode-sdk-python/commit/988b38ce1d4b7694083abe26f2198463d4555012))
+
## 0.1.0-alpha.31 (2025-07-24)
Full Changelog: [v0.1.0-alpha.30...v0.1.0-alpha.31](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.30...v0.1.0-alpha.31)
diff --git a/pyproject.toml b/pyproject.toml
index 7b034c4..7b258db 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.31"
+version = "0.1.0-alpha.32"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 1e6659f..21fbe42 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.31" # x-release-please-version
+__version__ = "0.1.0-alpha.32" # x-release-please-version
From 145229a92b0d7335a26d05b42da350e41fd8f4cd Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 24 Jul 2025 21:31:45 +0000
Subject: [PATCH 33/50] feat(api): api update
---
.stats.yml | 4 ++--
api.md | 1 -
src/opencode_ai/resources/app.py | 8 ++++----
src/opencode_ai/types/__init__.py | 1 -
src/opencode_ai/types/app_log_params.py | 6 ++----
src/opencode_ai/types/log_level.py | 7 -------
src/opencode_ai/types/part.py | 27 +++++++++++++++++++++----
7 files changed, 31 insertions(+), 23 deletions(-)
delete mode 100644 src/opencode_ai/types/log_level.py
diff --git a/.stats.yml b/.stats.yml
index 59e6768..e9e292b 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 26
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-fb4caa8d0381531c44dd2d3c8c0b930b8c15a7bdde474d15bf7aeeb3b27aef56.yml
-openapi_spec_hash: 3a263e46f2369eeb2410430001c60d15
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-5748199af356c3243a46a466e73b5d0bab7eaa0c56895e1d0f903d637f61d0bb.yml
+openapi_spec_hash: c04f6b6be54b05d9b1283c24e870163b
config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/api.md b/api.md
index c5eafcf..1758023 100644
--- a/api.md
+++ b/api.md
@@ -23,7 +23,6 @@ Types:
```python
from opencode_ai.types import (
App,
- LogLevel,
Mode,
Model,
Provider,
diff --git a/src/opencode_ai/resources/app.py b/src/opencode_ai/resources/app.py
index 44fe939..e9505ce 100644
--- a/src/opencode_ai/resources/app.py
+++ b/src/opencode_ai/resources/app.py
@@ -3,10 +3,11 @@
from __future__ import annotations
from typing import Dict
+from typing_extensions import Literal
import httpx
-from ..types import LogLevel, app_log_params
+from ..types import app_log_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -19,7 +20,6 @@ from .._response import (
)
from ..types.app import App
from .._base_client import make_request_options
-from ..types.log_level import LogLevel
from ..types.app_log_response import AppLogResponse
from ..types.app_init_response import AppInitResponse
from ..types.app_modes_response import AppModesResponse
@@ -89,7 +89,7 @@ class AppResource(SyncAPIResource):
def log(
self,
*,
- level: LogLevel,
+ level: Literal["debug", "info", "error", "warn"],
message: str,
service: str,
extra: Dict[str, object] | NotGiven = NOT_GIVEN,
@@ -237,7 +237,7 @@ class AsyncAppResource(AsyncAPIResource):
async def log(
self,
*,
- level: LogLevel,
+ level: Literal["debug", "info", "error", "warn"],
message: str,
service: str,
extra: Dict[str, object] | NotGiven = NOT_GIVEN,
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index e7b46d8..2dc9b99 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -19,7 +19,6 @@ from .message import Message as Message
from .session import Session as Session
from .provider import Provider as Provider
from .file_part import FilePart as FilePart
-from .log_level import LogLevel as LogLevel
from .text_part import TextPart as TextPart
from .tool_part import ToolPart as ToolPart
from .file_source import FileSource as FileSource
diff --git a/src/opencode_ai/types/app_log_params.py b/src/opencode_ai/types/app_log_params.py
index 105b5a4..8b24c11 100644
--- a/src/opencode_ai/types/app_log_params.py
+++ b/src/opencode_ai/types/app_log_params.py
@@ -3,15 +3,13 @@
from __future__ import annotations
from typing import Dict
-from typing_extensions import Required, TypedDict
-
-from .log_level import LogLevel
+from typing_extensions import Literal, Required, TypedDict
__all__ = ["AppLogParams"]
class AppLogParams(TypedDict, total=False):
- level: Required[LogLevel]
+ level: Required[Literal["debug", "info", "error", "warn"]]
"""Log level"""
message: Required[str]
diff --git a/src/opencode_ai/types/log_level.py b/src/opencode_ai/types/log_level.py
deleted file mode 100644
index c5138ea..0000000
--- a/src/opencode_ai/types/log_level.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import Literal, TypeAlias
-
-__all__ = ["LogLevel"]
-
-LogLevel: TypeAlias = Literal["debug", "info", "error", "warn"]
diff --git a/src/opencode_ai/types/part.py b/src/opencode_ai/types/part.py
index 198ea9e..5a74aa5 100644
--- a/src/opencode_ai/types/part.py
+++ b/src/opencode_ai/types/part.py
@@ -1,9 +1,12 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Union
-from typing_extensions import Annotated, TypeAlias
+from typing import List, Union
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from pydantic import Field as FieldInfo
from .._utils import PropertyInfo
+from .._models import BaseModel
from .file_part import FilePart
from .text_part import TextPart
from .tool_part import ToolPart
@@ -11,8 +14,24 @@ from .snapshot_part import SnapshotPart
from .step_start_part import StepStartPart
from .step_finish_part import StepFinishPart
-__all__ = ["Part"]
+__all__ = ["Part", "PatchPart"]
+
+
+class PatchPart(BaseModel):
+ id: str
+
+ files: List[str]
+
+ hash: str
+
+ message_id: str = FieldInfo(alias="messageID")
+
+ session_id: str = FieldInfo(alias="sessionID")
+
+ type: Literal["patch"]
+
Part: TypeAlias = Annotated[
- Union[TextPart, FilePart, ToolPart, StepStartPart, StepFinishPart, SnapshotPart], PropertyInfo(discriminator="type")
+ Union[TextPart, FilePart, ToolPart, StepStartPart, StepFinishPart, SnapshotPart, PatchPart],
+ PropertyInfo(discriminator="type"),
]
From 4d13992ad15edabc88c2f9c8745f5fafba96c580 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 25 Jul 2025 02:25:56 +0000
Subject: [PATCH 34/50] chore(project): add settings file for vscode
---
.gitignore | 1 -
.vscode/settings.json | 3 +++
2 files changed, 3 insertions(+), 1 deletion(-)
create mode 100644 .vscode/settings.json
diff --git a/.gitignore b/.gitignore
index 8779740..95ceb18 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
.prism.log
-.vscode
_dev
__pycache__
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..5b01030
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "python.analysis.importFormat": "relative",
+}
From 4e7027e1d9585c58661762f232b22fb045af17d8 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 25 Jul 2025 02:26:17 +0000
Subject: [PATCH 35/50] release: 0.1.0-alpha.33
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 13 +++++++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 2ce25fe..ff4f9a5 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.32"
+ ".": "0.1.0-alpha.33"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5088d68..df97c95 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## 0.1.0-alpha.33 (2025-07-25)
+
+Full Changelog: [v0.1.0-alpha.32...v0.1.0-alpha.33](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.32...v0.1.0-alpha.33)
+
+### Features
+
+* **api:** api update ([9002768](https://github.com/sst/opencode-sdk-python/commit/9002768edd617a44d4d686dd9e88f41fe6a56f2f))
+
+
+### Chores
+
+* **project:** add settings file for vscode ([7fff9af](https://github.com/sst/opencode-sdk-python/commit/7fff9af8fd66865dc933dce74f0385250377af87))
+
## 0.1.0-alpha.32 (2025-07-24)
Full Changelog: [v0.1.0-alpha.31...v0.1.0-alpha.32](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.31...v0.1.0-alpha.32)
diff --git a/pyproject.toml b/pyproject.toml
index 7b258db..770518f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.32"
+version = "0.1.0-alpha.33"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 21fbe42..eb5009a 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.32" # x-release-please-version
+__version__ = "0.1.0-alpha.33" # x-release-please-version
From 1de4987d5083e2c7ca55e92bc96b9598385aff8a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 28 Jul 2025 17:05:21 +0000
Subject: [PATCH 36/50] feat(api): api update
---
.stats.yml | 4 +-
api.md | 8 +-
src/opencode_ai/resources/session.py | 4 +
src/opencode_ai/types/__init__.py | 1 -
src/opencode_ai/types/config.py | 25 +++++
src/opencode_ai/types/event_list_response.py | 104 +++++++++----------
src/opencode_ai/types/find_text_response.py | 46 +++++++-
src/opencode_ai/types/match.py | 39 -------
src/opencode_ai/types/mode.py | 2 +
src/opencode_ai/types/mode_config.py | 4 +
src/opencode_ai/types/session.py | 2 +
src/opencode_ai/types/session_chat_params.py | 2 +
tests/api_resources/test_session.py | 2 +
13 files changed, 139 insertions(+), 104 deletions(-)
delete mode 100644 src/opencode_ai/types/match.py
diff --git a/.stats.yml b/.stats.yml
index e9e292b..55ffae9 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 26
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-5748199af356c3243a46a466e73b5d0bab7eaa0c56895e1d0f903d637f61d0bb.yml
-openapi_spec_hash: c04f6b6be54b05d9b1283c24e870163b
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-be4c3fb58765ee2b56c3b548182b9d0f1a9d5ebb7c340083bc578bcf3876b026.yml
+openapi_spec_hash: dd5d801d838fd6b522b1dd892a75fce1
config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/api.md b/api.md
index 1758023..a254328 100644
--- a/api.md
+++ b/api.md
@@ -46,13 +46,7 @@ Methods:
Types:
```python
-from opencode_ai.types import (
- Match,
- Symbol,
- FindFilesResponse,
- FindSymbolsResponse,
- FindTextResponse,
-)
+from opencode_ai.types import Symbol, FindFilesResponse, FindSymbolsResponse, FindTextResponse
```
Methods:
diff --git a/src/opencode_ai/resources/session.py b/src/opencode_ai/resources/session.py
index 9096fec..7e50413 100644
--- a/src/opencode_ai/resources/session.py
+++ b/src/opencode_ai/resources/session.py
@@ -163,6 +163,7 @@ class SessionResource(SyncAPIResource):
provider_id: str,
message_id: str | NotGiven = NOT_GIVEN,
mode: str | NotGiven = NOT_GIVEN,
+ system: str | NotGiven = NOT_GIVEN,
tools: Dict[str, bool] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -196,6 +197,7 @@ class SessionResource(SyncAPIResource):
"provider_id": provider_id,
"message_id": message_id,
"mode": mode,
+ "system": system,
"tools": tools,
},
session_chat_params.SessionChatParams,
@@ -606,6 +608,7 @@ class AsyncSessionResource(AsyncAPIResource):
provider_id: str,
message_id: str | NotGiven = NOT_GIVEN,
mode: str | NotGiven = NOT_GIVEN,
+ system: str | NotGiven = NOT_GIVEN,
tools: Dict[str, bool] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -639,6 +642,7 @@ class AsyncSessionResource(AsyncAPIResource):
"provider_id": provider_id,
"message_id": message_id,
"mode": mode,
+ "system": system,
"tools": tools,
},
session_chat_params.SessionChatParams,
diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py
index 2dc9b99..1d0663b 100644
--- a/src/opencode_ai/types/__init__.py
+++ b/src/opencode_ai/types/__init__.py
@@ -6,7 +6,6 @@ from .app import App as App
from .file import File as File
from .mode import Mode as Mode
from .part import Part as Part
-from .match import Match as Match
from .model import Model as Model
from .config import Config as Config
from .shared import (
diff --git a/src/opencode_ai/types/config.py b/src/opencode_ai/types/config.py
index 2a0bfff..76f9348 100644
--- a/src/opencode_ai/types/config.py
+++ b/src/opencode_ai/types/config.py
@@ -14,6 +14,9 @@ from .mcp_remote_config import McpRemoteConfig
__all__ = [
"Config",
+ "Agent",
+ "AgentGeneral",
+ "AgentAgentItem",
"Experimental",
"ExperimentalHook",
"ExperimentalHookFileEdited",
@@ -28,6 +31,25 @@ __all__ = [
]
+class AgentGeneral(ModeConfig):
+ description: str
+
+
+class AgentAgentItem(ModeConfig):
+ description: str
+
+
+class Agent(BaseModel):
+ general: Optional[AgentGeneral] = None
+
+ __pydantic_extra__: Dict[str, AgentAgentItem] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
+ if TYPE_CHECKING:
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> AgentAgentItem: ...
+
+
class ExperimentalHookFileEdited(BaseModel):
command: List[str]
@@ -137,6 +159,9 @@ class Config(BaseModel):
schema_: Optional[str] = FieldInfo(alias="$schema", default=None)
"""JSON schema reference for configuration validation"""
+ agent: Optional[Agent] = None
+ """Modes configuration, see https://opencode.ai/docs/modes"""
+
autoshare: Optional[bool] = None
"""@deprecated Use 'share' field instead.
diff --git a/src/opencode_ai/types/event_list_response.py b/src/opencode_ai/types/event_list_response.py
index 9c6d78f..1eb7421 100644
--- a/src/opencode_ai/types/event_list_response.py
+++ b/src/opencode_ai/types/event_list_response.py
@@ -16,15 +16,10 @@ from .shared.message_aborted_error import MessageAbortedError
__all__ = [
"EventListResponse",
- "EventLspClientDiagnostics",
- "EventLspClientDiagnosticsProperties",
- "EventPermissionUpdated",
- "EventPermissionUpdatedProperties",
- "EventPermissionUpdatedPropertiesTime",
- "EventFileEdited",
- "EventFileEditedProperties",
"EventInstallationUpdated",
"EventInstallationUpdatedProperties",
+ "EventLspClientDiagnostics",
+ "EventLspClientDiagnosticsProperties",
"EventMessageUpdated",
"EventMessageUpdatedProperties",
"EventMessageRemoved",
@@ -35,6 +30,11 @@ __all__ = [
"EventMessagePartRemovedProperties",
"EventStorageWrite",
"EventStorageWriteProperties",
+ "EventPermissionUpdated",
+ "EventPermissionUpdatedProperties",
+ "EventPermissionUpdatedPropertiesTime",
+ "EventFileEdited",
+ "EventFileEditedProperties",
"EventSessionUpdated",
"EventSessionUpdatedProperties",
"EventSessionDeleted",
@@ -52,6 +52,16 @@ __all__ = [
]
+class EventInstallationUpdatedProperties(BaseModel):
+ version: str
+
+
+class EventInstallationUpdated(BaseModel):
+ properties: EventInstallationUpdatedProperties
+
+ type: Literal["installation.updated"]
+
+
class EventLspClientDiagnosticsProperties(BaseModel):
path: str
@@ -64,48 +74,6 @@ class EventLspClientDiagnostics(BaseModel):
type: Literal["lsp.client.diagnostics"]
-class EventPermissionUpdatedPropertiesTime(BaseModel):
- created: float
-
-
-class EventPermissionUpdatedProperties(BaseModel):
- id: str
-
- metadata: Dict[str, object]
-
- session_id: str = FieldInfo(alias="sessionID")
-
- time: EventPermissionUpdatedPropertiesTime
-
- title: str
-
-
-class EventPermissionUpdated(BaseModel):
- properties: EventPermissionUpdatedProperties
-
- type: Literal["permission.updated"]
-
-
-class EventFileEditedProperties(BaseModel):
- file: str
-
-
-class EventFileEdited(BaseModel):
- properties: EventFileEditedProperties
-
- type: Literal["file.edited"]
-
-
-class EventInstallationUpdatedProperties(BaseModel):
- version: str
-
-
-class EventInstallationUpdated(BaseModel):
- properties: EventInstallationUpdatedProperties
-
- type: Literal["installation.updated"]
-
-
class EventMessageUpdatedProperties(BaseModel):
info: Message
@@ -162,6 +130,38 @@ class EventStorageWrite(BaseModel):
type: Literal["storage.write"]
+class EventPermissionUpdatedPropertiesTime(BaseModel):
+ created: float
+
+
+class EventPermissionUpdatedProperties(BaseModel):
+ id: str
+
+ metadata: Dict[str, object]
+
+ session_id: str = FieldInfo(alias="sessionID")
+
+ time: EventPermissionUpdatedPropertiesTime
+
+ title: str
+
+
+class EventPermissionUpdated(BaseModel):
+ properties: EventPermissionUpdatedProperties
+
+ type: Literal["permission.updated"]
+
+
+class EventFileEditedProperties(BaseModel):
+ file: str
+
+
+class EventFileEdited(BaseModel):
+ properties: EventFileEditedProperties
+
+ type: Literal["file.edited"]
+
+
class EventSessionUpdatedProperties(BaseModel):
info: Session
@@ -242,15 +242,15 @@ class EventIdeInstalled(BaseModel):
EventListResponse: TypeAlias = Annotated[
Union[
- EventLspClientDiagnostics,
- EventPermissionUpdated,
- EventFileEdited,
EventInstallationUpdated,
+ EventLspClientDiagnostics,
EventMessageUpdated,
EventMessageRemoved,
EventMessagePartUpdated,
EventMessagePartRemoved,
EventStorageWrite,
+ EventPermissionUpdated,
+ EventFileEdited,
EventSessionUpdated,
EventSessionDeleted,
EventSessionIdle,
diff --git a/src/opencode_ai/types/find_text_response.py b/src/opencode_ai/types/find_text_response.py
index 8f47178..4557834 100644
--- a/src/opencode_ai/types/find_text_response.py
+++ b/src/opencode_ai/types/find_text_response.py
@@ -3,8 +3,48 @@
from typing import List
from typing_extensions import TypeAlias
-from .match import Match
+from .._models import BaseModel
-__all__ = ["FindTextResponse"]
+__all__ = [
+ "FindTextResponse",
+ "FindTextResponseItem",
+ "FindTextResponseItemLines",
+ "FindTextResponseItemPath",
+ "FindTextResponseItemSubmatch",
+ "FindTextResponseItemSubmatchMatch",
+]
-FindTextResponse: TypeAlias = List[Match]
+
+class FindTextResponseItemLines(BaseModel):
+ text: str
+
+
+class FindTextResponseItemPath(BaseModel):
+ text: str
+
+
+class FindTextResponseItemSubmatchMatch(BaseModel):
+ text: str
+
+
+class FindTextResponseItemSubmatch(BaseModel):
+ end: float
+
+ match: FindTextResponseItemSubmatchMatch
+
+ start: float
+
+
+class FindTextResponseItem(BaseModel):
+ absolute_offset: float
+
+ line_number: float
+
+ lines: FindTextResponseItemLines
+
+ path: FindTextResponseItemPath
+
+ submatches: List[FindTextResponseItemSubmatch]
+
+
+FindTextResponse: TypeAlias = List[FindTextResponseItem]
diff --git a/src/opencode_ai/types/match.py b/src/opencode_ai/types/match.py
deleted file mode 100644
index 2f1ca3c..0000000
--- a/src/opencode_ai/types/match.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from .._models import BaseModel
-
-__all__ = ["Match", "Lines", "Path", "Submatch", "SubmatchMatch"]
-
-
-class Lines(BaseModel):
- text: str
-
-
-class Path(BaseModel):
- text: str
-
-
-class SubmatchMatch(BaseModel):
- text: str
-
-
-class Submatch(BaseModel):
- end: float
-
- match: SubmatchMatch
-
- start: float
-
-
-class Match(BaseModel):
- absolute_offset: float
-
- line_number: float
-
- lines: Lines
-
- path: Path
-
- submatches: List[Submatch]
diff --git a/src/opencode_ai/types/mode.py b/src/opencode_ai/types/mode.py
index 5e04502..041b7f3 100644
--- a/src/opencode_ai/types/mode.py
+++ b/src/opencode_ai/types/mode.py
@@ -23,3 +23,5 @@ class Mode(BaseModel):
model: Optional[Model] = None
prompt: Optional[str] = None
+
+ temperature: Optional[float] = None
diff --git a/src/opencode_ai/types/mode_config.py b/src/opencode_ai/types/mode_config.py
index 542232a..d7561c2 100644
--- a/src/opencode_ai/types/mode_config.py
+++ b/src/opencode_ai/types/mode_config.py
@@ -8,8 +8,12 @@ __all__ = ["ModeConfig"]
class ModeConfig(BaseModel):
+ disable: Optional[bool] = None
+
model: Optional[str] = None
prompt: Optional[str] = None
+ temperature: Optional[float] = None
+
tools: Optional[Dict[str, bool]] = None
diff --git a/src/opencode_ai/types/session.py b/src/opencode_ai/types/session.py
index 88b53ea..a0ed929 100644
--- a/src/opencode_ai/types/session.py
+++ b/src/opencode_ai/types/session.py
@@ -18,6 +18,8 @@ class Time(BaseModel):
class Revert(BaseModel):
message_id: str = FieldInfo(alias="messageID")
+ diff: Optional[str] = None
+
part_id: Optional[str] = FieldInfo(alias="partID", default=None)
snapshot: Optional[str] = None
diff --git a/src/opencode_ai/types/session_chat_params.py b/src/opencode_ai/types/session_chat_params.py
index b1f197a..e827282 100644
--- a/src/opencode_ai/types/session_chat_params.py
+++ b/src/opencode_ai/types/session_chat_params.py
@@ -23,6 +23,8 @@ class SessionChatParams(TypedDict, total=False):
mode: str
+ system: str
+
tools: Dict[str, bool]
diff --git a/tests/api_resources/test_session.py b/tests/api_resources/test_session.py
index c078c7b..9a3f384 100644
--- a/tests/api_resources/test_session.py
+++ b/tests/api_resources/test_session.py
@@ -203,6 +203,7 @@ class TestSession:
provider_id="providerID",
message_id="msg",
mode="mode",
+ system="system",
tools={"foo": True},
)
assert_matches_type(AssistantMessage, session, path=["response"])
@@ -776,6 +777,7 @@ class TestAsyncSession:
provider_id="providerID",
message_id="msg",
mode="mode",
+ system="system",
tools={"foo": True},
)
assert_matches_type(AssistantMessage, session, path=["response"])
From 206f54ea71db386a32c23dce340e8e7dcfebce39 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 28 Jul 2025 17:08:12 +0000
Subject: [PATCH 37/50] feat(api): api update
---
.stats.yml | 4 ++--
src/opencode_ai/types/event_list_response.py | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 55ffae9..a1fba29 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 26
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-be4c3fb58765ee2b56c3b548182b9d0f1a9d5ebb7c340083bc578bcf3876b026.yml
-openapi_spec_hash: dd5d801d838fd6b522b1dd892a75fce1
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-e43db0e3b4300d892558381c46238315784de13f980822a3224a956d94dbadb3.yml
+openapi_spec_hash: eb2421d12fc2ffb165659b1af40a67e1
config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/src/opencode_ai/types/event_list_response.py b/src/opencode_ai/types/event_list_response.py
index 1eb7421..1ac2771 100644
--- a/src/opencode_ai/types/event_list_response.py
+++ b/src/opencode_ai/types/event_list_response.py
@@ -111,6 +111,8 @@ class EventMessagePartRemovedProperties(BaseModel):
part_id: str = FieldInfo(alias="partID")
+ session_id: str = FieldInfo(alias="sessionID")
+
class EventMessagePartRemoved(BaseModel):
properties: EventMessagePartRemovedProperties
From 17f9c6532119a721de2fb56d27fdbfeadec9c850 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 28 Jul 2025 17:08:30 +0000
Subject: [PATCH 38/50] release: 0.1.0-alpha.34
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 9 +++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index ff4f9a5..36b2aff 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.33"
+ ".": "0.1.0-alpha.34"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index df97c95..dc6f9b5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 0.1.0-alpha.34 (2025-07-28)
+
+Full Changelog: [v0.1.0-alpha.33...v0.1.0-alpha.34](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.33...v0.1.0-alpha.34)
+
+### Features
+
+* **api:** api update ([0bc9251](https://github.com/sst/opencode-sdk-python/commit/0bc92517109d280c22e22639ee4ffa58d63d837b))
+* **api:** api update ([14ada9d](https://github.com/sst/opencode-sdk-python/commit/14ada9d7d1e93d85f357f417633b691b116c8ad5))
+
## 0.1.0-alpha.33 (2025-07-25)
Full Changelog: [v0.1.0-alpha.32...v0.1.0-alpha.33](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.32...v0.1.0-alpha.33)
diff --git a/pyproject.toml b/pyproject.toml
index 770518f..fc1b239 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.33"
+version = "0.1.0-alpha.34"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index eb5009a..4b13d68 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.33" # x-release-please-version
+__version__ = "0.1.0-alpha.34" # x-release-please-version
From 1c6a3700f10defd667b94db84e36a4b5446c847f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 29 Jul 2025 02:50:07 +0000
Subject: [PATCH 39/50] feat(api): api update
---
.stats.yml | 4 ++--
src/opencode_ai/types/event_list_response.py | 8 ++++++++
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index a1fba29..3f719fa 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 26
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-e43db0e3b4300d892558381c46238315784de13f980822a3224a956d94dbadb3.yml
-openapi_spec_hash: eb2421d12fc2ffb165659b1af40a67e1
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-62d8fccba4eb8dc3a80434e0849eab3352e49fb96a718bb7b6d17ed8e582b716.yml
+openapi_spec_hash: 4ff9376cf9634e91731e63fe482ea532
config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/src/opencode_ai/types/event_list_response.py b/src/opencode_ai/types/event_list_response.py
index 1ac2771..fa52d22 100644
--- a/src/opencode_ai/types/event_list_response.py
+++ b/src/opencode_ai/types/event_list_response.py
@@ -45,6 +45,7 @@ __all__ = [
"EventSessionErrorProperties",
"EventSessionErrorPropertiesError",
"EventSessionErrorPropertiesErrorMessageOutputLengthError",
+ "EventServerConnected",
"EventFileWatcherUpdated",
"EventFileWatcherUpdatedProperties",
"EventIdeInstalled",
@@ -220,6 +221,12 @@ class EventSessionError(BaseModel):
type: Literal["session.error"]
+class EventServerConnected(BaseModel):
+ properties: object
+
+ type: Literal["server.connected"]
+
+
class EventFileWatcherUpdatedProperties(BaseModel):
event: Literal["rename", "change"]
@@ -257,6 +264,7 @@ EventListResponse: TypeAlias = Annotated[
EventSessionDeleted,
EventSessionIdle,
EventSessionError,
+ EventServerConnected,
EventFileWatcherUpdated,
EventIdeInstalled,
],
From a4212485db24fb03c44ae27441947bba114e9f3e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 29 Jul 2025 02:50:24 +0000
Subject: [PATCH 40/50] release: 0.1.0-alpha.35
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 36b2aff..f996350 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.34"
+ ".": "0.1.0-alpha.35"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc6f9b5..deb98ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.1.0-alpha.35 (2025-07-29)
+
+Full Changelog: [v0.1.0-alpha.34...v0.1.0-alpha.35](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.34...v0.1.0-alpha.35)
+
+### Features
+
+* **api:** api update ([06ebf15](https://github.com/sst/opencode-sdk-python/commit/06ebf15e7ed0f782dbf51352a71fc5edb948a93c))
+
## 0.1.0-alpha.34 (2025-07-28)
Full Changelog: [v0.1.0-alpha.33...v0.1.0-alpha.34](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.33...v0.1.0-alpha.34)
diff --git a/pyproject.toml b/pyproject.toml
index fc1b239..ad62e55 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.34"
+version = "0.1.0-alpha.35"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 4b13d68..947b0c6 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.34" # x-release-please-version
+__version__ = "0.1.0-alpha.35" # x-release-please-version
From 34ccc7f7d7f51a72fefbd439c848a865286a0bca Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 31 Jul 2025 02:49:52 +0000
Subject: [PATCH 41/50] feat(client): support file upload requests
---
src/opencode_ai/_base_client.py | 5 ++++-
src/opencode_ai/_files.py | 8 ++++----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/opencode_ai/_base_client.py b/src/opencode_ai/_base_client.py
index f52a9ac..eb05756 100644
--- a/src/opencode_ai/_base_client.py
+++ b/src/opencode_ai/_base_client.py
@@ -532,7 +532,10 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
is_body_allowed = options.method.lower() != "get"
if is_body_allowed:
- kwargs["json"] = json_data if is_given(json_data) else None
+ if isinstance(json_data, bytes):
+ kwargs["content"] = json_data
+ else:
+ kwargs["json"] = json_data if is_given(json_data) else None
kwargs["files"] = files
else:
headers.pop("Content-Type", None)
diff --git a/src/opencode_ai/_files.py b/src/opencode_ai/_files.py
index 715cc20..cc14c14 100644
--- a/src/opencode_ai/_files.py
+++ b/src/opencode_ai/_files.py
@@ -69,12 +69,12 @@ def _transform_file(file: FileTypes) -> HttpxFileTypes:
return file
if is_tuple_t(file):
- return (file[0], _read_file_content(file[1]), *file[2:])
+ return (file[0], read_file_content(file[1]), *file[2:])
raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple")
-def _read_file_content(file: FileContent) -> HttpxFileContent:
+def read_file_content(file: FileContent) -> HttpxFileContent:
if isinstance(file, os.PathLike):
return pathlib.Path(file).read_bytes()
return file
@@ -111,12 +111,12 @@ async def _async_transform_file(file: FileTypes) -> HttpxFileTypes:
return file
if is_tuple_t(file):
- return (file[0], await _async_read_file_content(file[1]), *file[2:])
+ return (file[0], await async_read_file_content(file[1]), *file[2:])
raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple")
-async def _async_read_file_content(file: FileContent) -> HttpxFileContent:
+async def async_read_file_content(file: FileContent) -> HttpxFileContent:
if isinstance(file, os.PathLike):
return await anyio.Path(file).read_bytes()
From 63af9064ec0074a9f9c1a15e497e424d7ef5c925 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 6 Aug 2025 02:28:34 +0000
Subject: [PATCH 42/50] chore(internal): fix ruff target version
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index ad62e55..03658ff 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -159,7 +159,7 @@ reportPrivateUsage = false
[tool.ruff]
line-length = 120
output-format = "grouped"
-target-version = "py37"
+target-version = "py38"
[tool.ruff.format]
docstring-code-format = true
From bdbeff638a3ab16d81229677276cc4c3c492c1bf Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 9 Aug 2025 02:18:41 +0000
Subject: [PATCH 43/50] chore: update @stainless-api/prism-cli to v5.15.0
---
scripts/mock | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/mock b/scripts/mock
index d2814ae..0b28f6e 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -21,7 +21,7 @@ echo "==> Starting mock server with URL ${URL}"
# Run prism mock on the given spec
if [ "$1" == "--daemon" ]; then
- npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log &
+ npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log &
# Wait for server to come online
echo -n "Waiting for server"
@@ -37,5 +37,5 @@ if [ "$1" == "--daemon" ]; then
echo
else
- npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL"
+ npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL"
fi
From ec855544b2c24f13dbf96da6fd970ef9b32299b3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 9 Aug 2025 02:35:04 +0000
Subject: [PATCH 44/50] chore(internal): update comment in script
---
scripts/test | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/test b/scripts/test
index 2b87845..dbeda2d 100755
--- a/scripts/test
+++ b/scripts/test
@@ -43,7 +43,7 @@ elif ! prism_is_running ; then
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the prism command:"
echo
- echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}"
+ echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}"
echo
exit 1
From 5f8681cf63bd5582f71ddf7d5e00b46439516db2 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 12 Aug 2025 02:03:02 +0000
Subject: [PATCH 45/50] chore(internal): codegen related update
---
tests/api_resources/test_app.py | 64 +++++-----
tests/api_resources/test_config.py | 12 +-
tests/api_resources/test_event.py | 12 +-
tests/api_resources/test_file.py | 24 ++--
tests/api_resources/test_find.py | 36 +++---
tests/api_resources/test_session.py | 192 ++++++++++++++--------------
tests/api_resources/test_tui.py | 24 ++--
7 files changed, 182 insertions(+), 182 deletions(-)
diff --git a/tests/api_resources/test_app.py b/tests/api_resources/test_app.py
index 7cea873..e0f0670 100644
--- a/tests/api_resources/test_app.py
+++ b/tests/api_resources/test_app.py
@@ -23,13 +23,13 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestApp:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_get(self, client: Opencode) -> None:
app = client.app.get()
assert_matches_type(App, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_get(self, client: Opencode) -> None:
response = client.app.with_raw_response.get()
@@ -39,7 +39,7 @@ class TestApp:
app = response.parse()
assert_matches_type(App, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_get(self, client: Opencode) -> None:
with client.app.with_streaming_response.get() as response:
@@ -51,13 +51,13 @@ class TestApp:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_init(self, client: Opencode) -> None:
app = client.app.init()
assert_matches_type(AppInitResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_init(self, client: Opencode) -> None:
response = client.app.with_raw_response.init()
@@ -67,7 +67,7 @@ class TestApp:
app = response.parse()
assert_matches_type(AppInitResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_init(self, client: Opencode) -> None:
with client.app.with_streaming_response.init() as response:
@@ -79,7 +79,7 @@ class TestApp:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_log(self, client: Opencode) -> None:
app = client.app.log(
@@ -89,7 +89,7 @@ class TestApp:
)
assert_matches_type(AppLogResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_log_with_all_params(self, client: Opencode) -> None:
app = client.app.log(
@@ -100,7 +100,7 @@ class TestApp:
)
assert_matches_type(AppLogResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_log(self, client: Opencode) -> None:
response = client.app.with_raw_response.log(
@@ -114,7 +114,7 @@ class TestApp:
app = response.parse()
assert_matches_type(AppLogResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_log(self, client: Opencode) -> None:
with client.app.with_streaming_response.log(
@@ -130,13 +130,13 @@ class TestApp:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_modes(self, client: Opencode) -> None:
app = client.app.modes()
assert_matches_type(AppModesResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_modes(self, client: Opencode) -> None:
response = client.app.with_raw_response.modes()
@@ -146,7 +146,7 @@ class TestApp:
app = response.parse()
assert_matches_type(AppModesResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_modes(self, client: Opencode) -> None:
with client.app.with_streaming_response.modes() as response:
@@ -158,13 +158,13 @@ class TestApp:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_providers(self, client: Opencode) -> None:
app = client.app.providers()
assert_matches_type(AppProvidersResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_providers(self, client: Opencode) -> None:
response = client.app.with_raw_response.providers()
@@ -174,7 +174,7 @@ class TestApp:
app = response.parse()
assert_matches_type(AppProvidersResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_providers(self, client: Opencode) -> None:
with client.app.with_streaming_response.providers() as response:
@@ -192,13 +192,13 @@ class TestAsyncApp:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_get(self, async_client: AsyncOpencode) -> None:
app = await async_client.app.get()
assert_matches_type(App, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_get(self, async_client: AsyncOpencode) -> None:
response = await async_client.app.with_raw_response.get()
@@ -208,7 +208,7 @@ class TestAsyncApp:
app = await response.parse()
assert_matches_type(App, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_get(self, async_client: AsyncOpencode) -> None:
async with async_client.app.with_streaming_response.get() as response:
@@ -220,13 +220,13 @@ class TestAsyncApp:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_init(self, async_client: AsyncOpencode) -> None:
app = await async_client.app.init()
assert_matches_type(AppInitResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_init(self, async_client: AsyncOpencode) -> None:
response = await async_client.app.with_raw_response.init()
@@ -236,7 +236,7 @@ class TestAsyncApp:
app = await response.parse()
assert_matches_type(AppInitResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_init(self, async_client: AsyncOpencode) -> None:
async with async_client.app.with_streaming_response.init() as response:
@@ -248,7 +248,7 @@ class TestAsyncApp:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_log(self, async_client: AsyncOpencode) -> None:
app = await async_client.app.log(
@@ -258,7 +258,7 @@ class TestAsyncApp:
)
assert_matches_type(AppLogResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_log_with_all_params(self, async_client: AsyncOpencode) -> None:
app = await async_client.app.log(
@@ -269,7 +269,7 @@ class TestAsyncApp:
)
assert_matches_type(AppLogResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_log(self, async_client: AsyncOpencode) -> None:
response = await async_client.app.with_raw_response.log(
@@ -283,7 +283,7 @@ class TestAsyncApp:
app = await response.parse()
assert_matches_type(AppLogResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_log(self, async_client: AsyncOpencode) -> None:
async with async_client.app.with_streaming_response.log(
@@ -299,13 +299,13 @@ class TestAsyncApp:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_modes(self, async_client: AsyncOpencode) -> None:
app = await async_client.app.modes()
assert_matches_type(AppModesResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_modes(self, async_client: AsyncOpencode) -> None:
response = await async_client.app.with_raw_response.modes()
@@ -315,7 +315,7 @@ class TestAsyncApp:
app = await response.parse()
assert_matches_type(AppModesResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_modes(self, async_client: AsyncOpencode) -> None:
async with async_client.app.with_streaming_response.modes() as response:
@@ -327,13 +327,13 @@ class TestAsyncApp:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_providers(self, async_client: AsyncOpencode) -> None:
app = await async_client.app.providers()
assert_matches_type(AppProvidersResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_providers(self, async_client: AsyncOpencode) -> None:
response = await async_client.app.with_raw_response.providers()
@@ -343,7 +343,7 @@ class TestAsyncApp:
app = await response.parse()
assert_matches_type(AppProvidersResponse, app, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_providers(self, async_client: AsyncOpencode) -> None:
async with async_client.app.with_streaming_response.providers() as response:
diff --git a/tests/api_resources/test_config.py b/tests/api_resources/test_config.py
index eab370d..86e4c8f 100644
--- a/tests/api_resources/test_config.py
+++ b/tests/api_resources/test_config.py
@@ -17,13 +17,13 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestConfig:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_get(self, client: Opencode) -> None:
config = client.config.get()
assert_matches_type(Config, config, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_get(self, client: Opencode) -> None:
response = client.config.with_raw_response.get()
@@ -33,7 +33,7 @@ class TestConfig:
config = response.parse()
assert_matches_type(Config, config, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_get(self, client: Opencode) -> None:
with client.config.with_streaming_response.get() as response:
@@ -51,13 +51,13 @@ class TestAsyncConfig:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_get(self, async_client: AsyncOpencode) -> None:
config = await async_client.config.get()
assert_matches_type(Config, config, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_get(self, async_client: AsyncOpencode) -> None:
response = await async_client.config.with_raw_response.get()
@@ -67,7 +67,7 @@ class TestAsyncConfig:
config = await response.parse()
assert_matches_type(Config, config, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_get(self, async_client: AsyncOpencode) -> None:
async with async_client.config.with_streaming_response.get() as response:
diff --git a/tests/api_resources/test_event.py b/tests/api_resources/test_event.py
index ec909e9..95de55b 100644
--- a/tests/api_resources/test_event.py
+++ b/tests/api_resources/test_event.py
@@ -15,13 +15,13 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestEvent:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_list(self, client: Opencode) -> None:
event_stream = client.event.list()
event_stream.response.close()
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_list(self, client: Opencode) -> None:
response = client.event.with_raw_response.list()
@@ -30,7 +30,7 @@ class TestEvent:
stream = response.parse()
stream.close()
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_list(self, client: Opencode) -> None:
with client.event.with_streaming_response.list() as response:
@@ -48,13 +48,13 @@ class TestAsyncEvent:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_list(self, async_client: AsyncOpencode) -> None:
event_stream = await async_client.event.list()
await event_stream.response.aclose()
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_list(self, async_client: AsyncOpencode) -> None:
response = await async_client.event.with_raw_response.list()
@@ -63,7 +63,7 @@ class TestAsyncEvent:
stream = await response.parse()
await stream.close()
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_list(self, async_client: AsyncOpencode) -> None:
async with async_client.event.with_streaming_response.list() as response:
diff --git a/tests/api_resources/test_file.py b/tests/api_resources/test_file.py
index 7298335..cd09854 100644
--- a/tests/api_resources/test_file.py
+++ b/tests/api_resources/test_file.py
@@ -17,7 +17,7 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestFile:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_read(self, client: Opencode) -> None:
file = client.file.read(
@@ -25,7 +25,7 @@ class TestFile:
)
assert_matches_type(FileReadResponse, file, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_read(self, client: Opencode) -> None:
response = client.file.with_raw_response.read(
@@ -37,7 +37,7 @@ class TestFile:
file = response.parse()
assert_matches_type(FileReadResponse, file, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_read(self, client: Opencode) -> None:
with client.file.with_streaming_response.read(
@@ -51,13 +51,13 @@ class TestFile:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_status(self, client: Opencode) -> None:
file = client.file.status()
assert_matches_type(FileStatusResponse, file, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_status(self, client: Opencode) -> None:
response = client.file.with_raw_response.status()
@@ -67,7 +67,7 @@ class TestFile:
file = response.parse()
assert_matches_type(FileStatusResponse, file, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_status(self, client: Opencode) -> None:
with client.file.with_streaming_response.status() as response:
@@ -85,7 +85,7 @@ class TestAsyncFile:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_read(self, async_client: AsyncOpencode) -> None:
file = await async_client.file.read(
@@ -93,7 +93,7 @@ class TestAsyncFile:
)
assert_matches_type(FileReadResponse, file, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_read(self, async_client: AsyncOpencode) -> None:
response = await async_client.file.with_raw_response.read(
@@ -105,7 +105,7 @@ class TestAsyncFile:
file = await response.parse()
assert_matches_type(FileReadResponse, file, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_read(self, async_client: AsyncOpencode) -> None:
async with async_client.file.with_streaming_response.read(
@@ -119,13 +119,13 @@ class TestAsyncFile:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_status(self, async_client: AsyncOpencode) -> None:
file = await async_client.file.status()
assert_matches_type(FileStatusResponse, file, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_status(self, async_client: AsyncOpencode) -> None:
response = await async_client.file.with_raw_response.status()
@@ -135,7 +135,7 @@ class TestAsyncFile:
file = await response.parse()
assert_matches_type(FileStatusResponse, file, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_status(self, async_client: AsyncOpencode) -> None:
async with async_client.file.with_streaming_response.status() as response:
diff --git a/tests/api_resources/test_find.py b/tests/api_resources/test_find.py
index fe40d85..cd54e28 100644
--- a/tests/api_resources/test_find.py
+++ b/tests/api_resources/test_find.py
@@ -21,7 +21,7 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestFind:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_files(self, client: Opencode) -> None:
find = client.find.files(
@@ -29,7 +29,7 @@ class TestFind:
)
assert_matches_type(FindFilesResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_files(self, client: Opencode) -> None:
response = client.find.with_raw_response.files(
@@ -41,7 +41,7 @@ class TestFind:
find = response.parse()
assert_matches_type(FindFilesResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_files(self, client: Opencode) -> None:
with client.find.with_streaming_response.files(
@@ -55,7 +55,7 @@ class TestFind:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_symbols(self, client: Opencode) -> None:
find = client.find.symbols(
@@ -63,7 +63,7 @@ class TestFind:
)
assert_matches_type(FindSymbolsResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_symbols(self, client: Opencode) -> None:
response = client.find.with_raw_response.symbols(
@@ -75,7 +75,7 @@ class TestFind:
find = response.parse()
assert_matches_type(FindSymbolsResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_symbols(self, client: Opencode) -> None:
with client.find.with_streaming_response.symbols(
@@ -89,7 +89,7 @@ class TestFind:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_text(self, client: Opencode) -> None:
find = client.find.text(
@@ -97,7 +97,7 @@ class TestFind:
)
assert_matches_type(FindTextResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_text(self, client: Opencode) -> None:
response = client.find.with_raw_response.text(
@@ -109,7 +109,7 @@ class TestFind:
find = response.parse()
assert_matches_type(FindTextResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_text(self, client: Opencode) -> None:
with client.find.with_streaming_response.text(
@@ -129,7 +129,7 @@ class TestAsyncFind:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_files(self, async_client: AsyncOpencode) -> None:
find = await async_client.find.files(
@@ -137,7 +137,7 @@ class TestAsyncFind:
)
assert_matches_type(FindFilesResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_files(self, async_client: AsyncOpencode) -> None:
response = await async_client.find.with_raw_response.files(
@@ -149,7 +149,7 @@ class TestAsyncFind:
find = await response.parse()
assert_matches_type(FindFilesResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_files(self, async_client: AsyncOpencode) -> None:
async with async_client.find.with_streaming_response.files(
@@ -163,7 +163,7 @@ class TestAsyncFind:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_symbols(self, async_client: AsyncOpencode) -> None:
find = await async_client.find.symbols(
@@ -171,7 +171,7 @@ class TestAsyncFind:
)
assert_matches_type(FindSymbolsResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_symbols(self, async_client: AsyncOpencode) -> None:
response = await async_client.find.with_raw_response.symbols(
@@ -183,7 +183,7 @@ class TestAsyncFind:
find = await response.parse()
assert_matches_type(FindSymbolsResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_symbols(self, async_client: AsyncOpencode) -> None:
async with async_client.find.with_streaming_response.symbols(
@@ -197,7 +197,7 @@ class TestAsyncFind:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_text(self, async_client: AsyncOpencode) -> None:
find = await async_client.find.text(
@@ -205,7 +205,7 @@ class TestAsyncFind:
)
assert_matches_type(FindTextResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_text(self, async_client: AsyncOpencode) -> None:
response = await async_client.find.with_raw_response.text(
@@ -217,7 +217,7 @@ class TestAsyncFind:
find = await response.parse()
assert_matches_type(FindTextResponse, find, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_text(self, async_client: AsyncOpencode) -> None:
async with async_client.find.with_streaming_response.text(
diff --git a/tests/api_resources/test_session.py b/tests/api_resources/test_session.py
index 9a3f384..15b39d7 100644
--- a/tests/api_resources/test_session.py
+++ b/tests/api_resources/test_session.py
@@ -26,13 +26,13 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestSession:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_create(self, client: Opencode) -> None:
session = client.session.create()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_create(self, client: Opencode) -> None:
response = client.session.with_raw_response.create()
@@ -42,7 +42,7 @@ class TestSession:
session = response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_create(self, client: Opencode) -> None:
with client.session.with_streaming_response.create() as response:
@@ -54,13 +54,13 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_list(self, client: Opencode) -> None:
session = client.session.list()
assert_matches_type(SessionListResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_list(self, client: Opencode) -> None:
response = client.session.with_raw_response.list()
@@ -70,7 +70,7 @@ class TestSession:
session = response.parse()
assert_matches_type(SessionListResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_list(self, client: Opencode) -> None:
with client.session.with_streaming_response.list() as response:
@@ -82,7 +82,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_delete(self, client: Opencode) -> None:
session = client.session.delete(
@@ -90,7 +90,7 @@ class TestSession:
)
assert_matches_type(SessionDeleteResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_delete(self, client: Opencode) -> None:
response = client.session.with_raw_response.delete(
@@ -102,7 +102,7 @@ class TestSession:
session = response.parse()
assert_matches_type(SessionDeleteResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_delete(self, client: Opencode) -> None:
with client.session.with_streaming_response.delete(
@@ -116,7 +116,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_delete(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -124,7 +124,7 @@ class TestSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_abort(self, client: Opencode) -> None:
session = client.session.abort(
@@ -132,7 +132,7 @@ class TestSession:
)
assert_matches_type(SessionAbortResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_abort(self, client: Opencode) -> None:
response = client.session.with_raw_response.abort(
@@ -144,7 +144,7 @@ class TestSession:
session = response.parse()
assert_matches_type(SessionAbortResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_abort(self, client: Opencode) -> None:
with client.session.with_streaming_response.abort(
@@ -158,7 +158,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_abort(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -166,7 +166,7 @@ class TestSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_chat(self, client: Opencode) -> None:
session = client.session.chat(
@@ -182,7 +182,7 @@ class TestSession:
)
assert_matches_type(AssistantMessage, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_chat_with_all_params(self, client: Opencode) -> None:
session = client.session.chat(
@@ -208,7 +208,7 @@ class TestSession:
)
assert_matches_type(AssistantMessage, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_chat(self, client: Opencode) -> None:
response = client.session.with_raw_response.chat(
@@ -228,7 +228,7 @@ class TestSession:
session = response.parse()
assert_matches_type(AssistantMessage, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_chat(self, client: Opencode) -> None:
with client.session.with_streaming_response.chat(
@@ -250,7 +250,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_chat(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -266,7 +266,7 @@ class TestSession:
provider_id="providerID",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_init(self, client: Opencode) -> None:
session = client.session.init(
@@ -277,7 +277,7 @@ class TestSession:
)
assert_matches_type(SessionInitResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_init(self, client: Opencode) -> None:
response = client.session.with_raw_response.init(
@@ -292,7 +292,7 @@ class TestSession:
session = response.parse()
assert_matches_type(SessionInitResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_init(self, client: Opencode) -> None:
with client.session.with_streaming_response.init(
@@ -309,7 +309,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_init(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -320,7 +320,7 @@ class TestSession:
provider_id="providerID",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_messages(self, client: Opencode) -> None:
session = client.session.messages(
@@ -328,7 +328,7 @@ class TestSession:
)
assert_matches_type(SessionMessagesResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_messages(self, client: Opencode) -> None:
response = client.session.with_raw_response.messages(
@@ -340,7 +340,7 @@ class TestSession:
session = response.parse()
assert_matches_type(SessionMessagesResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_messages(self, client: Opencode) -> None:
with client.session.with_streaming_response.messages(
@@ -354,7 +354,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_messages(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -362,7 +362,7 @@ class TestSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_revert(self, client: Opencode) -> None:
session = client.session.revert(
@@ -371,7 +371,7 @@ class TestSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_revert_with_all_params(self, client: Opencode) -> None:
session = client.session.revert(
@@ -381,7 +381,7 @@ class TestSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_revert(self, client: Opencode) -> None:
response = client.session.with_raw_response.revert(
@@ -394,7 +394,7 @@ class TestSession:
session = response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_revert(self, client: Opencode) -> None:
with client.session.with_streaming_response.revert(
@@ -409,7 +409,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_revert(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -418,7 +418,7 @@ class TestSession:
message_id="msg",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_share(self, client: Opencode) -> None:
session = client.session.share(
@@ -426,7 +426,7 @@ class TestSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_share(self, client: Opencode) -> None:
response = client.session.with_raw_response.share(
@@ -438,7 +438,7 @@ class TestSession:
session = response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_share(self, client: Opencode) -> None:
with client.session.with_streaming_response.share(
@@ -452,7 +452,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_share(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -460,7 +460,7 @@ class TestSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_summarize(self, client: Opencode) -> None:
session = client.session.summarize(
@@ -470,7 +470,7 @@ class TestSession:
)
assert_matches_type(SessionSummarizeResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_summarize(self, client: Opencode) -> None:
response = client.session.with_raw_response.summarize(
@@ -484,7 +484,7 @@ class TestSession:
session = response.parse()
assert_matches_type(SessionSummarizeResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_summarize(self, client: Opencode) -> None:
with client.session.with_streaming_response.summarize(
@@ -500,7 +500,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_summarize(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -510,7 +510,7 @@ class TestSession:
provider_id="providerID",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_unrevert(self, client: Opencode) -> None:
session = client.session.unrevert(
@@ -518,7 +518,7 @@ class TestSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_unrevert(self, client: Opencode) -> None:
response = client.session.with_raw_response.unrevert(
@@ -530,7 +530,7 @@ class TestSession:
session = response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_unrevert(self, client: Opencode) -> None:
with client.session.with_streaming_response.unrevert(
@@ -544,7 +544,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_unrevert(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -552,7 +552,7 @@ class TestSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_unshare(self, client: Opencode) -> None:
session = client.session.unshare(
@@ -560,7 +560,7 @@ class TestSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_unshare(self, client: Opencode) -> None:
response = client.session.with_raw_response.unshare(
@@ -572,7 +572,7 @@ class TestSession:
session = response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_unshare(self, client: Opencode) -> None:
with client.session.with_streaming_response.unshare(
@@ -586,7 +586,7 @@ class TestSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_path_params_unshare(self, client: Opencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -600,13 +600,13 @@ class TestAsyncSession:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_create(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.create()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_create(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.create()
@@ -616,7 +616,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_create(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.create() as response:
@@ -628,13 +628,13 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_list(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.list()
assert_matches_type(SessionListResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_list(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.list()
@@ -644,7 +644,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(SessionListResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_list(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.list() as response:
@@ -656,7 +656,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_delete(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.delete(
@@ -664,7 +664,7 @@ class TestAsyncSession:
)
assert_matches_type(SessionDeleteResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_delete(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.delete(
@@ -676,7 +676,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(SessionDeleteResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_delete(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.delete(
@@ -690,7 +690,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_delete(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -698,7 +698,7 @@ class TestAsyncSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_abort(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.abort(
@@ -706,7 +706,7 @@ class TestAsyncSession:
)
assert_matches_type(SessionAbortResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_abort(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.abort(
@@ -718,7 +718,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(SessionAbortResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_abort(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.abort(
@@ -732,7 +732,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_abort(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -740,7 +740,7 @@ class TestAsyncSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_chat(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.chat(
@@ -756,7 +756,7 @@ class TestAsyncSession:
)
assert_matches_type(AssistantMessage, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_chat_with_all_params(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.chat(
@@ -782,7 +782,7 @@ class TestAsyncSession:
)
assert_matches_type(AssistantMessage, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_chat(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.chat(
@@ -802,7 +802,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(AssistantMessage, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_chat(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.chat(
@@ -824,7 +824,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_chat(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -840,7 +840,7 @@ class TestAsyncSession:
provider_id="providerID",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_init(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.init(
@@ -851,7 +851,7 @@ class TestAsyncSession:
)
assert_matches_type(SessionInitResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_init(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.init(
@@ -866,7 +866,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(SessionInitResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_init(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.init(
@@ -883,7 +883,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_init(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -894,7 +894,7 @@ class TestAsyncSession:
provider_id="providerID",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_messages(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.messages(
@@ -902,7 +902,7 @@ class TestAsyncSession:
)
assert_matches_type(SessionMessagesResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_messages(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.messages(
@@ -914,7 +914,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(SessionMessagesResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_messages(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.messages(
@@ -928,7 +928,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_messages(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -936,7 +936,7 @@ class TestAsyncSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_revert(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.revert(
@@ -945,7 +945,7 @@ class TestAsyncSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_revert_with_all_params(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.revert(
@@ -955,7 +955,7 @@ class TestAsyncSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_revert(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.revert(
@@ -968,7 +968,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_revert(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.revert(
@@ -983,7 +983,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_revert(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -992,7 +992,7 @@ class TestAsyncSession:
message_id="msg",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_share(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.share(
@@ -1000,7 +1000,7 @@ class TestAsyncSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_share(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.share(
@@ -1012,7 +1012,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_share(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.share(
@@ -1026,7 +1026,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_share(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -1034,7 +1034,7 @@ class TestAsyncSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_summarize(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.summarize(
@@ -1044,7 +1044,7 @@ class TestAsyncSession:
)
assert_matches_type(SessionSummarizeResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_summarize(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.summarize(
@@ -1058,7 +1058,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(SessionSummarizeResponse, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_summarize(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.summarize(
@@ -1074,7 +1074,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_summarize(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -1084,7 +1084,7 @@ class TestAsyncSession:
provider_id="providerID",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_unrevert(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.unrevert(
@@ -1092,7 +1092,7 @@ class TestAsyncSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_unrevert(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.unrevert(
@@ -1104,7 +1104,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_unrevert(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.unrevert(
@@ -1118,7 +1118,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_unrevert(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
@@ -1126,7 +1126,7 @@ class TestAsyncSession:
"",
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_unshare(self, async_client: AsyncOpencode) -> None:
session = await async_client.session.unshare(
@@ -1134,7 +1134,7 @@ class TestAsyncSession:
)
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_unshare(self, async_client: AsyncOpencode) -> None:
response = await async_client.session.with_raw_response.unshare(
@@ -1146,7 +1146,7 @@ class TestAsyncSession:
session = await response.parse()
assert_matches_type(Session, session, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_unshare(self, async_client: AsyncOpencode) -> None:
async with async_client.session.with_streaming_response.unshare(
@@ -1160,7 +1160,7 @@ class TestAsyncSession:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_path_params_unshare(self, async_client: AsyncOpencode) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
diff --git a/tests/api_resources/test_tui.py b/tests/api_resources/test_tui.py
index 50f907a..06145a5 100644
--- a/tests/api_resources/test_tui.py
+++ b/tests/api_resources/test_tui.py
@@ -17,7 +17,7 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
class TestTui:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_append_prompt(self, client: Opencode) -> None:
tui = client.tui.append_prompt(
@@ -25,7 +25,7 @@ class TestTui:
)
assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_append_prompt(self, client: Opencode) -> None:
response = client.tui.with_raw_response.append_prompt(
@@ -37,7 +37,7 @@ class TestTui:
tui = response.parse()
assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_append_prompt(self, client: Opencode) -> None:
with client.tui.with_streaming_response.append_prompt(
@@ -51,13 +51,13 @@ class TestTui:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_open_help(self, client: Opencode) -> None:
tui = client.tui.open_help()
assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_open_help(self, client: Opencode) -> None:
response = client.tui.with_raw_response.open_help()
@@ -67,7 +67,7 @@ class TestTui:
tui = response.parse()
assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_open_help(self, client: Opencode) -> None:
with client.tui.with_streaming_response.open_help() as response:
@@ -85,7 +85,7 @@ class TestAsyncTui:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_append_prompt(self, async_client: AsyncOpencode) -> None:
tui = await async_client.tui.append_prompt(
@@ -93,7 +93,7 @@ class TestAsyncTui:
)
assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_append_prompt(self, async_client: AsyncOpencode) -> None:
response = await async_client.tui.with_raw_response.append_prompt(
@@ -105,7 +105,7 @@ class TestAsyncTui:
tui = await response.parse()
assert_matches_type(TuiAppendPromptResponse, tui, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_append_prompt(self, async_client: AsyncOpencode) -> None:
async with async_client.tui.with_streaming_response.append_prompt(
@@ -119,13 +119,13 @@ class TestAsyncTui:
assert cast(Any, response.is_closed) is True
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_open_help(self, async_client: AsyncOpencode) -> None:
tui = await async_client.tui.open_help()
assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_open_help(self, async_client: AsyncOpencode) -> None:
response = await async_client.tui.with_raw_response.open_help()
@@ -135,7 +135,7 @@ class TestAsyncTui:
tui = await response.parse()
assert_matches_type(TuiOpenHelpResponse, tui, path=["response"])
- @pytest.mark.skip()
+ @pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_open_help(self, async_client: AsyncOpencode) -> None:
async with async_client.tui.with_streaming_response.open_help() as response:
From a1b54afef12a8ff33bf0a42d4fa559ab0da5ea82 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 22 Aug 2025 02:37:29 +0000
Subject: [PATCH 46/50] chore: update github action
---
.github/workflows/ci.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7da1c21..9b6824f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -36,7 +36,7 @@ jobs:
run: ./scripts/lint
build:
- if: github.repository == 'stainless-sdks/opencode-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork)
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
timeout-minutes: 10
name: build
permissions:
@@ -61,12 +61,14 @@ jobs:
run: rye build
- name: Get GitHub OIDC Token
+ if: github.repository == 'stainless-sdks/opencode-python'
id: github-oidc
uses: actions/github-script@v6
with:
script: core.setOutput('github_token', await core.getIDToken());
- name: Upload tarball
+ if: github.repository == 'stainless-sdks/opencode-python'
env:
URL: https://pkg.stainless.com/s
AUTH: ${{ steps.github-oidc.outputs.github_token }}
From c11a24e28e37c13a90a171f7937787f00c11e3bb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 26 Aug 2025 02:16:40 +0000
Subject: [PATCH 47/50] chore(internal): change ci workflow machines
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9b6824f..04808c6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,7 @@ jobs:
permissions:
contents: read
id-token: write
- runs-on: depot-ubuntu-24.04
+ runs-on: ${{ github.repository == 'stainless-sdks/opencode-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
From 6eae86427aed27f56dca4945430f0e2e6d9f2028 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 27 Aug 2025 02:22:11 +0000
Subject: [PATCH 48/50] fix: avoid newer type syntax
---
src/opencode_ai/_models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/opencode_ai/_models.py b/src/opencode_ai/_models.py
index b8387ce..92f7c10 100644
--- a/src/opencode_ai/_models.py
+++ b/src/opencode_ai/_models.py
@@ -304,7 +304,7 @@ class BaseModel(pydantic.BaseModel):
exclude_none=exclude_none,
)
- return cast(dict[str, Any], json_safe(dumped)) if mode == "json" else dumped
+ return cast("dict[str, Any]", json_safe(dumped)) if mode == "json" else dumped
@override
def model_dump_json(
From 7a6b7d16c473e922061c894674419c29a65d1c9f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 27 Aug 2025 02:30:29 +0000
Subject: [PATCH 49/50] chore(internal): update pyright exclude list
---
pyproject.toml | 1 +
1 file changed, 1 insertion(+)
diff --git a/pyproject.toml b/pyproject.toml
index 03658ff..e478afc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -148,6 +148,7 @@ exclude = [
"_dev",
".venv",
".nox",
+ ".git",
]
reportImplicitOverride = true
From 817f1a08163452fd7fcfbb1268b262cc78a9d629 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 27 Aug 2025 02:30:47 +0000
Subject: [PATCH 50/50] release: 0.1.0-alpha.36
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 24 ++++++++++++++++++++++++
pyproject.toml | 2 +-
src/opencode_ai/_version.py | 2 +-
4 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index f996350..a696b6a 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.35"
+ ".": "0.1.0-alpha.36"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index deb98ef..16b4106 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,29 @@
# Changelog
+## 0.1.0-alpha.36 (2025-08-27)
+
+Full Changelog: [v0.1.0-alpha.35...v0.1.0-alpha.36](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.35...v0.1.0-alpha.36)
+
+### Features
+
+* **client:** support file upload requests ([c2e1522](https://github.com/sst/opencode-sdk-python/commit/c2e1522ffba596910098e1e58eef7b4d00548e18))
+
+
+### Bug Fixes
+
+* avoid newer type syntax ([42779eb](https://github.com/sst/opencode-sdk-python/commit/42779eb3d7035b677ef213d6508658dbd56b50bf))
+
+
+### Chores
+
+* **internal:** change ci workflow machines ([14c918e](https://github.com/sst/opencode-sdk-python/commit/14c918ee18edc797d2d8dd1f1d462ffb004a7e89))
+* **internal:** codegen related update ([477ff58](https://github.com/sst/opencode-sdk-python/commit/477ff58aa920fd0c02378ff33c041d061923dee4))
+* **internal:** fix ruff target version ([359b956](https://github.com/sst/opencode-sdk-python/commit/359b95615445c2f675aa3520cb233c19b50dfe31))
+* **internal:** update comment in script ([9ac7cbb](https://github.com/sst/opencode-sdk-python/commit/9ac7cbb6dba85d18d18bd37f95dffc0eea3d2605))
+* **internal:** update pyright exclude list ([5d96f63](https://github.com/sst/opencode-sdk-python/commit/5d96f63f7a9aaebb2e85fcd11b380bbeca3b7310))
+* update @stainless-api/prism-cli to v5.15.0 ([88487ee](https://github.com/sst/opencode-sdk-python/commit/88487ee6dbc8ac60e9d26573c8f08ae3f1389e83))
+* update github action ([fe98742](https://github.com/sst/opencode-sdk-python/commit/fe98742cd53b1e8783f600879164dd16fea610d3))
+
## 0.1.0-alpha.35 (2025-07-29)
Full Changelog: [v0.1.0-alpha.34...v0.1.0-alpha.35](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.34...v0.1.0-alpha.35)
diff --git a/pyproject.toml b/pyproject.toml
index e478afc..f5c99e3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "opencode-ai"
-version = "0.1.0-alpha.35"
+version = "0.1.0-alpha.36"
description = "The official Python library for the opencode API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/opencode_ai/_version.py b/src/opencode_ai/_version.py
index 947b0c6..3e57475 100644
--- a/src/opencode_ai/_version.py
+++ b/src/opencode_ai/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "opencode_ai"
-__version__ = "0.1.0-alpha.35" # x-release-please-version
+__version__ = "0.1.0-alpha.36" # x-release-please-version