Skip to content

fix(opencode): add GPT routing alongside OSS discovery - #239

Open
dgokeeffe wants to merge 4 commits into
databricks:mainfrom
dgokeeffe:fix/opencode-model-routing-followup
Open

fix(opencode): add GPT routing alongside OSS discovery#239
dgokeeffe wants to merge 4 commits into
databricks:mainfrom
dgokeeffe:fix/opencode-model-routing-followup

Conversation

@dgokeeffe

@dgokeeffe dgokeeffe commented Jul 24, 2026

Copy link
Copy Markdown

Summary

Adds the OpenCode routing and discovery follow-up on top of #223.

Changes

  • Add the databricks-openai provider so GPT-5, GPT-5.6, and Codex models use the Databricks Responses API alongside the databricks-oss provider.
  • Discover Codex models for OpenCode and emit their provider configuration.
  • Fall back to AI Gateway foundation-model serving endpoints when UC model-services does not expose the validated GLM/Kimi models.
  • Apply the same GLM/Kimi allowlist to fallback discovery so Claude, Gemini, Inkling, and other MLflow-dialect endpoints are not misclassified.

Review scope

This branch is stacked on #223. The incremental change is one commit across the OpenCode/discovery implementation and focused tests:

636c3b6...3f1c227

The parent PR no longer contains the rejected proxy or broad OSS cohort.

Validation

  • Final changed-area suite — 588 passed, 29 workspace-gated skips
  • uv run ruff check . — passed
  • uv run pytest --ignore=tests/test_e2e_user_agent.py -q — 1062 passed, 36 skipped

The installed-agent User-Agent capture module was excluded from the full run because local Claude/Pi installations can return from existing managed state without contacting its capture server; all affected routing and rendering paths are covered by the focused tests above.

Replaces the larger consolidated #238 with a clean linear stack.

@dgokeeffe

Copy link
Copy Markdown
Author

This stack has been rebuilt on current main with one clean commit per layer. The incremental OpenCode diff is linked in the description; the rejected proxy and broad OSS cohort are gone. Local focused validation is 480 passing with Ruff clean. A maintainer CI approval/review is now the remaining gate.

@dgokeeffe
dgokeeffe force-pushed the fix/opencode-model-routing-followup branch from b53813f to 3f1c227 Compare July 26, 2026 04:38
@dgokeeffe

Copy link
Copy Markdown
Author

Post-review update: OpenCode GPT entries now carry shared context/output limits and prefer the newest eligible GPT; foundation endpoint parsing is defensive against malformed records; CLI fallback tests are deterministic; and the live e2e fixture now populates OpenAI/OSS models and isolates Pi settings paths. Round-3 reviewers found no production blocker; final validation is 588 passed/29 skipped focused and 1062 passed/36 skipped excluding environment-sensitive installed-agent capture tests.

@dgokeeffe

dgokeeffe commented Aug 7, 2026

Copy link
Copy Markdown
Author

Rebased this PR stack onto current main (67429ec) and force-pushed the existing branch. New head: 816588f.

Hard stack dependency

This is 3 of 3 and must land after #223:

  1. feat(pi): add validated GLM/Kimi MLflow provider #217 — Pi MLflow OSS provider
  2. fix: declare long-context Claude and GPT metadata #223 — shared Claude/GPT metadata + Pi GPT thinking-off fix
  3. fix(opencode): add GPT routing alongside OSS discovery #239 — OpenCode GPT routing + OSS discovery fallback (this PR)

This is a code dependency, not just a review preference: #239's preferred_gpt_model uses _normalized_foundation_model_id, and its per-model overlay uses gpt_model_token_limits; both are introduced by #223. #239 cannot safely apply directly to main before #223.

The helper and its tests now live in this PR with their only consumer (src/ucode/agents/opencode.py), rather than leaking into #223.

If #217/#223 are squash-merged, please rebase this branch onto the updated main before merging.

Validation

  • CI-parity suite: 1,648 passed, 6 skipped
  • Only local failures: the two pre-existing CLI capture-server tests (TestClaudeUserAgent, TestPiUserAgent), which skip in CI's unit-test job
  • ruff check and ruff format --check: clean
  • No committed uv.lock churn or conflict markers

This PR adds lower-level OpenCode GPT routing, but managed-config OpenCode GPT mapping and admin allowlist intersection are deliberately deferred to #290.

Expose the GLM and Kimi coding-model cohort through Pi and OpenCode with shared token limits and reasoning metadata. Keep unsupported chat models out of discovery, including Inkling until gateway issue databricks#215 is fixed, and retain the GPT-OSS Responses API routing guard.
Centralize Claude family/version parsing so Pi metadata, adaptive-thinking compatibility, and Claude Code's [1m] selector cannot drift. Cover Sonnet 4.5, Opus 4.6, future major versions, Fable fallback, and prefixed model IDs.
`_pi_gpt_model_entry` declared `reasoning: True` without an off-state, so for
the thinking-off case Pi's Responses builder fell back to
`reasoning: {effort: "none"}` (pi-ai openai-responses.js, the
`thinkingLevelMap?.off !== null` branch). `"none"` is only valid on gpt-5.1+,
so every request to gpt-5, gpt-5-mini, gpt-5-nano and gpt-5-5-pro was rejected:

  BAD_REQUEST: Unsupported value: 'none' is not supported with the 'gpt-5'
  model. Supported values are: 'minimal', 'low', 'medium', and 'high'.

Setting `thinkingLevelMap: {"off": None}` makes Pi omit `reasoning` entirely,
which the gateway accepts for all 14 codex ids. Verified against
/ai-gateway/codex/v1/responses: effort="none" 400s on gpt-5/-mini/-nano/-5-5-pro
and 200s on gpt-5-1..-5-6; omitting `reasoning` is 200 everywhere.
`{"off": "minimal"}` was rejected as an alternative because gpt-5-5-pro 400s on
it too. Same pattern already used for the Gemini 3.x entries.

The rest of Pi's Responses payload was bisected against the gateway and is
fine: store:false, prompt_cache_key, prompt_cache_retention:"24h",
prompt_cache_options, include:["reasoning.encrypted_content"], developer role,
flat tool schemas, and the session_id / x-client-request-id affinity headers.

Regression was hard to spot because the gateway returns
{"error_code","message"} rather than OpenAI's {"error":...}, so Pi's
error-body.js recovery no-ops and every 400 renders as
"OpenAI API error (400): 400 status code (no body)". Reported upstream as
earendil-works/pi#7748.

Refs databricks#286
Configure the Databricks OpenAI Responses provider alongside the validated GLM/Kimi provider, and fall back to foundation-model serving endpoints when UC model services are unavailable.
@dgokeeffe
dgokeeffe force-pushed the fix/opencode-model-routing-followup branch from 48a91ba to 816588f Compare August 7, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant