diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3cf71e6..b386bef 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.18" + ".": "0.1.0-alpha.19" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 011dd2c..22b27ac 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 -config_hash: 2a888f284ea87b2dfdb7e548938a55ea +config_hash: b7f3d9742335715c458494988498b183 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b63c73..36c737a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 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) + +### Features + +* **api:** api update ([07b8550](https://github.com/sst/opencode-sdk-python/commit/07b8550e658373298ac5d64eed102f21d03a29fa)) + ## 0.1.0-alpha.18 (2025-07-16) Full Changelog: [v0.1.0-alpha.17...v0.1.0-alpha.18](https://github.com/sst/opencode-sdk-python/compare/v0.1.0-alpha.17...v0.1.0-alpha.18) diff --git a/api.md b/api.md index f9f46d2..8ba2145 100644 --- a/api.md +++ b/api.md @@ -21,7 +21,17 @@ Methods: Types: ```python -from opencode_ai.types import App, LogLevel, Mode, AppInitResponse, AppLogResponse, AppModesResponse +from opencode_ai.types import ( + App, + LogLevel, + Mode, + Model, + Provider, + AppInitResponse, + AppLogResponse, + AppModesResponse, + AppProvidersResponse, +) ``` Methods: @@ -30,6 +40,7 @@ Methods: - client.app.init() -> AppInitResponse - client.app.log(\*\*params) -> AppLogResponse - client.app.modes() -> AppModesResponse +- client.app.providers() -> AppProvidersResponse # Find @@ -71,20 +82,17 @@ Types: ```python from opencode_ai.types import ( Config, - Keybinds, - McpLocal, - McpRemote, - Mode, - Model, - Provider, - ConfigProvidersResponse, + KeybindsConfig, + LayoutConfig, + McpLocalConfig, + McpRemoteConfig, + ModeConfig, ) ``` Methods: - client.config.get() -> Config -- client.config.providers() -> ConfigProvidersResponse # Session diff --git a/pyproject.toml b/pyproject.toml index b225d61..a0d2553 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "opencode-ai" -version = "0.1.0-alpha.18" +version = "0.1.0-alpha.19" 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 cb4e690..0e1e5de 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.18" # x-release-please-version +__version__ = "0.1.0-alpha.19" # x-release-please-version diff --git a/src/opencode_ai/resources/app.py b/src/opencode_ai/resources/app.py index bbe2789..e9505ce 100644 --- a/src/opencode_ai/resources/app.py +++ b/src/opencode_ai/resources/app.py @@ -23,6 +23,7 @@ from ..types.app_log_response import AppLogResponse from ..types.app_init_response import AppInitResponse from ..types.app_modes_response import AppModesResponse +from ..types.app_providers_response import AppProvidersResponse __all__ = ["AppResource", "AsyncAppResource"] @@ -155,6 +156,25 @@ def modes( cast_to=AppModesResponse, ) + def providers( + 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, + ) -> AppProvidersResponse: + """List all providers""" + return self._get( + "/config/providers", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AppProvidersResponse, + ) + class AsyncAppResource(AsyncAPIResource): @cached_property @@ -284,6 +304,25 @@ async def modes( cast_to=AppModesResponse, ) + async def providers( + 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, + ) -> AppProvidersResponse: + """List all providers""" + return await self._get( + "/config/providers", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AppProvidersResponse, + ) + class AppResourceWithRawResponse: def __init__(self, app: AppResource) -> None: @@ -301,6 +340,9 @@ def __init__(self, app: AppResource) -> None: self.modes = to_raw_response_wrapper( app.modes, ) + self.providers = to_raw_response_wrapper( + app.providers, + ) class AsyncAppResourceWithRawResponse: @@ -319,6 +361,9 @@ def __init__(self, app: AsyncAppResource) -> None: self.modes = async_to_raw_response_wrapper( app.modes, ) + self.providers = async_to_raw_response_wrapper( + app.providers, + ) class AppResourceWithStreamingResponse: @@ -337,6 +382,9 @@ def __init__(self, app: AppResource) -> None: self.modes = to_streamed_response_wrapper( app.modes, ) + self.providers = to_streamed_response_wrapper( + app.providers, + ) class AsyncAppResourceWithStreamingResponse: @@ -355,3 +403,6 @@ def __init__(self, app: AsyncAppResource) -> None: self.modes = async_to_streamed_response_wrapper( app.modes, ) + self.providers = async_to_streamed_response_wrapper( + app.providers, + ) diff --git a/src/opencode_ai/resources/config.py b/src/opencode_ai/resources/config.py index 97e4644..88ff3a3 100644 --- a/src/opencode_ai/resources/config.py +++ b/src/opencode_ai/resources/config.py @@ -15,7 +15,6 @@ ) from .._base_client import make_request_options from ..types.config import Config -from ..types.config_providers_response import ConfigProvidersResponse __all__ = ["ConfigResource", "AsyncConfigResource"] @@ -59,25 +58,6 @@ def get( cast_to=Config, ) - def providers( - 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, - ) -> ConfigProvidersResponse: - """List all providers""" - return self._get( - "/config/providers", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ConfigProvidersResponse, - ) - class AsyncConfigResource(AsyncAPIResource): @cached_property @@ -118,25 +98,6 @@ async def get( cast_to=Config, ) - async def providers( - 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, - ) -> ConfigProvidersResponse: - """List all providers""" - return await self._get( - "/config/providers", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ConfigProvidersResponse, - ) - class ConfigResourceWithRawResponse: def __init__(self, config: ConfigResource) -> None: @@ -145,9 +106,6 @@ def __init__(self, config: ConfigResource) -> None: self.get = to_raw_response_wrapper( config.get, ) - self.providers = to_raw_response_wrapper( - config.providers, - ) class AsyncConfigResourceWithRawResponse: @@ -157,9 +115,6 @@ def __init__(self, config: AsyncConfigResource) -> None: self.get = async_to_raw_response_wrapper( config.get, ) - self.providers = async_to_raw_response_wrapper( - config.providers, - ) class ConfigResourceWithStreamingResponse: @@ -169,9 +124,6 @@ def __init__(self, config: ConfigResource) -> None: self.get = to_streamed_response_wrapper( config.get, ) - self.providers = to_streamed_response_wrapper( - config.providers, - ) class AsyncConfigResourceWithStreamingResponse: @@ -181,6 +133,3 @@ def __init__(self, config: AsyncConfigResource) -> None: self.get = async_to_streamed_response_wrapper( config.get, ) - self.providers = async_to_streamed_response_wrapper( - config.providers, - ) diff --git a/src/opencode_ai/types/__init__.py b/src/opencode_ai/types/__init__.py index be3befd..f07c40b 100644 --- a/src/opencode_ai/types/__init__.py +++ b/src/opencode_ai/types/__init__.py @@ -17,28 +17,30 @@ from .symbol import Symbol as Symbol from .message import Message as Message from .session import Session as Session -from .keybinds import Keybinds as Keybinds from .provider import Provider as Provider from .file_part import FilePart as FilePart from .log_level import LogLevel as LogLevel -from .mcp_local import McpLocal as McpLocal from .text_part import TextPart as TextPart from .tool_part import ToolPart as ToolPart -from .mcp_remote import McpRemote as McpRemote +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 .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 +from .mcp_local_config import McpLocalConfig as McpLocalConfig 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 .find_files_params import FindFilesParams as FindFilesParams +from .mcp_remote_config import McpRemoteConfig as McpRemoteConfig from .app_modes_response import AppModesResponse as AppModesResponse from .file_read_response import FileReadResponse as FileReadResponse from .find_text_response import FindTextResponse as FindTextResponse @@ -54,9 +56,9 @@ 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 .app_providers_response import AppProvidersResponse as AppProvidersResponse 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 .config_providers_response import ConfigProvidersResponse as ConfigProvidersResponse from .session_messages_response import SessionMessagesResponse as SessionMessagesResponse from .session_summarize_response import SessionSummarizeResponse as SessionSummarizeResponse diff --git a/src/opencode_ai/types/config_providers_response.py b/src/opencode_ai/types/app_providers_response.py similarity index 75% rename from src/opencode_ai/types/config_providers_response.py rename to src/opencode_ai/types/app_providers_response.py index 27cd70d..62912e8 100644 --- a/src/opencode_ai/types/config_providers_response.py +++ b/src/opencode_ai/types/app_providers_response.py @@ -5,10 +5,10 @@ from .._models import BaseModel from .provider import Provider -__all__ = ["ConfigProvidersResponse"] +__all__ = ["AppProvidersResponse"] -class ConfigProvidersResponse(BaseModel): +class AppProvidersResponse(BaseModel): default: Dict[str, str] providers: List[Provider] diff --git a/src/opencode_ai/types/config.py b/src/opencode_ai/types/config.py index bb33dfb..9f1490d 100644 --- a/src/opencode_ai/types/config.py +++ b/src/opencode_ai/types/config.py @@ -5,13 +5,14 @@ from pydantic import Field as FieldInfo -from . import mode from .._utils import PropertyInfo from .._models import BaseModel -from .keybinds import Keybinds from .log_level import LogLevel -from .mcp_local import McpLocal -from .mcp_remote import McpRemote +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 __all__ = [ "Config", @@ -50,19 +51,19 @@ class Experimental(BaseModel): hook: Optional[ExperimentalHook] = None -Mcp: TypeAlias = Annotated[Union[McpLocal, McpRemote], PropertyInfo(discriminator="type")] +Mcp: TypeAlias = Annotated[Union[McpLocalConfig, McpRemoteConfig], PropertyInfo(discriminator="type")] class Mode(BaseModel): - build: Optional[mode.Mode] = None + build: Optional[ModeConfig] = None - plan: Optional[mode.Mode] = None + plan: Optional[ModeConfig] = None 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) -> mode.Mode: ... + def __getattr__(self, attr: str) -> ModeConfig: ... class ProviderModelsCost(BaseModel): @@ -140,10 +141,10 @@ class Config(BaseModel): instructions: Optional[List[str]] = None """Additional instruction files or patterns to include""" - keybinds: Optional[Keybinds] = None + keybinds: Optional[KeybindsConfig] = None """Custom keybind configurations""" - layout: Optional[Literal["auto", "stretch"]] = None + layout: Optional[LayoutConfig] = None """Layout to use for the TUI""" log_level: Optional[LogLevel] = None diff --git a/src/opencode_ai/types/keybinds.py b/src/opencode_ai/types/keybinds_config.py similarity index 97% rename from src/opencode_ai/types/keybinds.py rename to src/opencode_ai/types/keybinds_config.py index 843a093..0513d8f 100644 --- a/src/opencode_ai/types/keybinds.py +++ b/src/opencode_ai/types/keybinds_config.py @@ -4,10 +4,10 @@ from .._models import BaseModel -__all__ = ["Keybinds"] +__all__ = ["KeybindsConfig"] -class Keybinds(BaseModel): +class KeybindsConfig(BaseModel): app_exit: str """Exit the application""" diff --git a/src/opencode_ai/types/layout_config.py b/src/opencode_ai/types/layout_config.py new file mode 100644 index 0000000..99b69ee --- /dev/null +++ b/src/opencode_ai/types/layout_config.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__ = ["LayoutConfig"] + +LayoutConfig: TypeAlias = Literal["auto", "stretch"] diff --git a/src/opencode_ai/types/mcp_local.py b/src/opencode_ai/types/mcp_local_config.py similarity index 89% rename from src/opencode_ai/types/mcp_local.py rename to src/opencode_ai/types/mcp_local_config.py index 5296819..27118c2 100644 --- a/src/opencode_ai/types/mcp_local.py +++ b/src/opencode_ai/types/mcp_local_config.py @@ -5,10 +5,10 @@ from .._models import BaseModel -__all__ = ["McpLocal"] +__all__ = ["McpLocalConfig"] -class McpLocal(BaseModel): +class McpLocalConfig(BaseModel): command: List[str] """Command and arguments to run the MCP server""" diff --git a/src/opencode_ai/types/mcp_remote.py b/src/opencode_ai/types/mcp_remote_config.py similarity index 86% rename from src/opencode_ai/types/mcp_remote.py rename to src/opencode_ai/types/mcp_remote_config.py index 83a02a2..ddbb7d4 100644 --- a/src/opencode_ai/types/mcp_remote.py +++ b/src/opencode_ai/types/mcp_remote_config.py @@ -5,10 +5,10 @@ from .._models import BaseModel -__all__ = ["McpRemote"] +__all__ = ["McpRemoteConfig"] -class McpRemote(BaseModel): +class McpRemoteConfig(BaseModel): type: Literal["remote"] """Type of MCP server connection""" diff --git a/src/opencode_ai/types/mode1.py b/src/opencode_ai/types/mode_config.py similarity index 83% rename from src/opencode_ai/types/mode1.py rename to src/opencode_ai/types/mode_config.py index 9bccdc5..542232a 100644 --- a/src/opencode_ai/types/mode1.py +++ b/src/opencode_ai/types/mode_config.py @@ -4,10 +4,10 @@ from .._models import BaseModel -__all__ = ["Mode"] +__all__ = ["ModeConfig"] -class Mode(BaseModel): +class ModeConfig(BaseModel): model: Optional[str] = None prompt: Optional[str] = None diff --git a/tests/api_resources/test_app.py b/tests/api_resources/test_app.py index 87123dc..7cea873 100644 --- a/tests/api_resources/test_app.py +++ b/tests/api_resources/test_app.py @@ -9,7 +9,13 @@ from opencode_ai import Opencode, AsyncOpencode from tests.utils import assert_matches_type -from opencode_ai.types import App, AppLogResponse, AppInitResponse, AppModesResponse +from opencode_ai.types import ( + App, + AppLogResponse, + AppInitResponse, + AppModesResponse, + AppProvidersResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -152,6 +158,34 @@ def test_streaming_response_modes(self, client: Opencode) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip() + @parametrize + def test_method_providers(self, client: Opencode) -> None: + app = client.app.providers() + assert_matches_type(AppProvidersResponse, app, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_raw_response_providers(self, client: Opencode) -> None: + response = client.app.with_raw_response.providers() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + app = response.parse() + assert_matches_type(AppProvidersResponse, app, path=["response"]) + + @pytest.mark.skip() + @parametrize + def test_streaming_response_providers(self, client: Opencode) -> None: + with client.app.with_streaming_response.providers() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + app = response.parse() + assert_matches_type(AppProvidersResponse, app, path=["response"]) + + assert cast(Any, response.is_closed) is True + class TestAsyncApp: parametrize = pytest.mark.parametrize( @@ -292,3 +326,31 @@ async def test_streaming_response_modes(self, async_client: AsyncOpencode) -> No assert_matches_type(AppModesResponse, app, path=["response"]) assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @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() + @parametrize + async def test_raw_response_providers(self, async_client: AsyncOpencode) -> None: + response = await async_client.app.with_raw_response.providers() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + app = await response.parse() + assert_matches_type(AppProvidersResponse, app, path=["response"]) + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_providers(self, async_client: AsyncOpencode) -> None: + async with async_client.app.with_streaming_response.providers() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + app = await response.parse() + assert_matches_type(AppProvidersResponse, app, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_config.py b/tests/api_resources/test_config.py index 5131373..eab370d 100644 --- a/tests/api_resources/test_config.py +++ b/tests/api_resources/test_config.py @@ -9,7 +9,7 @@ from opencode_ai import Opencode, AsyncOpencode from tests.utils import assert_matches_type -from opencode_ai.types import Config, ConfigProvidersResponse +from opencode_ai.types import Config base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -45,34 +45,6 @@ def test_streaming_response_get(self, client: Opencode) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() - @parametrize - def test_method_providers(self, client: Opencode) -> None: - config = client.config.providers() - assert_matches_type(ConfigProvidersResponse, config, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_providers(self, client: Opencode) -> None: - response = client.config.with_raw_response.providers() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - config = response.parse() - assert_matches_type(ConfigProvidersResponse, config, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_providers(self, client: Opencode) -> None: - with client.config.with_streaming_response.providers() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - config = response.parse() - assert_matches_type(ConfigProvidersResponse, config, path=["response"]) - - assert cast(Any, response.is_closed) is True - class TestAsyncConfig: parametrize = pytest.mark.parametrize( @@ -106,31 +78,3 @@ async def test_streaming_response_get(self, async_client: AsyncOpencode) -> None assert_matches_type(Config, config, path=["response"]) assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_method_providers(self, async_client: AsyncOpencode) -> None: - config = await async_client.config.providers() - assert_matches_type(ConfigProvidersResponse, config, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_providers(self, async_client: AsyncOpencode) -> None: - response = await async_client.config.with_raw_response.providers() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - config = await response.parse() - assert_matches_type(ConfigProvidersResponse, config, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_providers(self, async_client: AsyncOpencode) -> None: - async with async_client.config.with_streaming_response.providers() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - config = await response.parse() - assert_matches_type(ConfigProvidersResponse, config, path=["response"]) - - assert cast(Any, response.is_closed) is True