Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions langsmith-fleet-worker-attempt.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"agent": "codex",
"cli_version": "0.125.0",
"emitted_at": "2026-07-24T21:53:26.737479Z",
"emitted_at": "2026-07-24T22:55:53.506408Z",
"execution_profile": "codex-default",
"fallback_models": [
"gpt-5.4"
],
"operation_role": "worker",
"pr_number": "2822",
"pr_number": "2825",
"requested_model": "gpt-5.5",
"runner": "reusable-codex-run",
"schema": "langsmith-fleet/v1",
Expand Down
5 changes: 4 additions & 1 deletion tests/scripts/test_task_decomposer.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,10 +508,13 @@ def test_get_llm_client_github_token_defaults(monkeypatch) -> None:
client, provider = client_info
assert provider == "github-models"
assert isinstance(client, FakeChatOpenAI)
from tools.langchain_client import _github_model_id
from tools.llm_provider import GITHUB_MODELS_BASE_URL
from tools.llm_registry import configured_model_for_provider

assert client.kwargs["model"] == configured_model_for_provider("github-models")
assert client.kwargs["model"] == _github_model_id(
configured_model_for_provider("github-models")
)
assert client.kwargs["base_url"] == GITHUB_MODELS_BASE_URL


Expand Down
37 changes: 35 additions & 2 deletions tests/tools/test_langchain_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ def test_explicit_github_provider_uses_reviewed_model_when_model_is_omitted(
assert resolved.provider == langchain_client.PROVIDER_GITHUB
assert resolved.model == "github-reviewed"
assert isinstance(resolved.client, FakeChatOpenAI)
assert resolved.client.kwargs["model"] == "github-reviewed"
# github-models GA namespaces bare ids with the openai/ publisher
assert resolved.client.kwargs["model"] == "openai/github-reviewed"


def test_build_chat_client_env_model_override(monkeypatch: pytest.MonkeyPatch) -> None:
Expand All @@ -175,7 +176,7 @@ def test_build_chat_client_env_model_override(monkeypatch: pytest.MonkeyPatch) -
assert resolved is not None
assert resolved.model == "gpt-4o-mini"
assert isinstance(resolved.client, FakeChatOpenAI)
assert resolved.client.kwargs["model"] == "gpt-4o-mini"
assert resolved.client.kwargs["model"] == "openai/gpt-4o-mini"


def test_build_chat_client_blocked_model_override_does_not_shift_provider(
Expand Down Expand Up @@ -801,11 +802,43 @@ def test_build_openai_client_normal_model_has_temperature(
assert resolved.client.kwargs["temperature"] == 0.1


class _CaptureChatOpenAI:
def __init__(self, **kwargs):
self.kwargs = kwargs


class _CaptureChatAnthropic:
def __init__(self, **kwargs):
self.kwargs = kwargs


def test_github_model_id_namespaces_bare_ids():
assert langchain_client._github_model_id("codex-mini-latest") == "openai/codex-mini-latest"
assert langchain_client._github_model_id("gpt-5") == "openai/gpt-5"


def test_github_model_id_leaves_namespaced_ids_unchanged():
assert langchain_client._github_model_id("openai/gpt-5") == "openai/gpt-5"
assert (
langchain_client._github_model_id("mistral-ai/mistral-large") == "mistral-ai/mistral-large"
)


def test_build_github_client_sends_namespaced_model():
client = langchain_client._build_github_client(
_CaptureChatOpenAI, model="codex-mini-latest", token="t", timeout=30, max_retries=2
)
assert client.kwargs["model"] == "openai/codex-mini-latest"
assert client.kwargs["base_url"] == langchain_client.GITHUB_MODELS_BASE_URL


def test_build_github_client_preserves_already_namespaced():
client = langchain_client._build_github_client(
_CaptureChatOpenAI, model="openai/gpt-5", token="t", timeout=30, max_retries=2
)
assert client.kwargs["model"] == "openai/gpt-5"


def _build_anthropic(model: str):
return langchain_client._build_anthropic_client(
_CaptureChatAnthropic, model=model, token="t", timeout=30, max_retries=2
Expand Down
17 changes: 16 additions & 1 deletion tools/langchain_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,26 @@ def _build_anthropic_client(
return chat_anthropic(**kwargs)


def _github_model_id(model: str) -> str:
"""Return a GitHub Models GA-compatible model id (``publisher/model``).

The GA endpoint (``models.github.ai/inference``) requires publisher-namespaced ids
such as ``openai/gpt-5``. A bare id (e.g. ``codex-mini-latest``) 404s ("page not
found") there. Default a bare id to the ``openai/`` publisher; already-namespaced
ids (containing ``/``) are returned unchanged. (If a bare id maps to a model the
GitHub Models catalog does not offer at all, the durable fix is an owner-reviewed
change of the github-models selection to a catalogued id — this only normalizes
the id format.)
"""
name = model.strip()
return name if "/" in name else f"openai/{name}"


def _build_github_client(
chat_openai: type, *, model: str, token: str, timeout: int, max_retries: int
) -> object:
kwargs: dict = {
"model": model,
"model": _github_model_id(model),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update the task decomposer's model assertion

When the broader test suite exercises the GitHub Models path, this normalization makes tests/scripts/test_task_decomposer.py::test_get_llm_client_github_token_defaults fail because line 514 still expects the registry's bare codex-mini-latest, while the constructed client now contains openai/codex-mini-latest. Running pytest -q tests/scripts/test_task_decomposer.py tests/tools/test_llm_provider.py tests/test_github_models_provider.py reproduces the failure (1 failed, 161 passed), so the change cannot pass Gate until that downstream contract is updated.

Useful? React with 👍 / 👎.

"base_url": GITHUB_MODELS_BASE_URL,
"api_key": token,
"timeout": timeout,
Expand Down
Loading