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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions