Skip to content

[BUG] model selection issue #42

@jhargis

Description

@jhargis

Summary

The Python SDK sends modelID/providerID as flat top-level fields in the request body, but the OpenCode server expects them nested inside a model object. This causes the server to ignore model selection entirely.

Evidence

Python SDK Source (session_chat_params.py, lines 15-20):

class SessionChatParams(TypedDict, total=False):
    model_id: Required[Annotated[str, PropertyInfo(alias="modelID")]]
    provider_id: Required[Annotated[str, PropertyInfo(alias="providerID")]]
    parts: Required[Iterable[Part]]

Python SDK Source (session.py, lines 638-648):

body=await async_maybe_transform(
    {
        "model_id": model_id,
        "provider_id": provider_id,
        "parts": parts,
        ...
    },
    session_chat_params.SessionChatParams,
)

What the Python SDK sends:

{ "modelID": "claude-opus-4-5-20251101", "providerID": "anthropic", "parts": [...] }

What the server expects (per JS/TS SDK docs at https://opencode.ai/docs/sdk.md):

{ "model": { "providerID": "anthropic", "modelID": "claude-opus-4-5-20251101" }, "parts": [...] }

Reproduction

import asyncio
from opencode_ai import AsyncOpencode

async def test():
    client = AsyncOpencode(base_url='http://127.0.0.1:4096', timeout=60.0)

    session = await client.session.create(extra_body={})

    # This DOES NOT work - server ignores model selection
    result = await client.session.chat(
        id=session.id,
        provider_id='anthropic',
        model_id='claude-opus-4-5-20251101',
        parts=[{'type': 'text', 'text': 'What model are you?'}],
    )
    # Server uses default model instead of requested one

    # Workaround using extra_body - this DOES work
    result = await client.session.chat(
        id=session.id,
        provider_id='anthropic',
        model_id='claude-opus-4-5-20251101',
        parts=[{'type': 'text', 'text': 'What model are you?'}],
        extra_body={
            "model": {
                "providerID": "anthropic",
                "modelID": "claude-opus-4-5-20251101"
            }
        },
    )
    # Server correctly uses the specified model

asyncio.run(test())

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions