Skip to content

Fix OpenCode Go messages authentication - #1717

Merged
kevincodex1 merged 3 commits into
Twigpine:mainfrom
muhammetalan:codex/fix-opencode-go-minimax-m3-endpoint
Jun 22, 2026
Merged

kevincodex1 merged 3 commits into
Twigpine:mainfrom
muhammetalan:codex/fix-opencode-go-minimax-m3-endpoint

Conversation

@muhammetalan

@muhammetalan muhammetalan commented Jun 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Keep the affected OpenCode Go MiniMax/Qwen models on the Anthropic Messages endpoint and authenticate those requests with a raw x-api-key header instead of Authorization: Bearer.

This also aligns the local metadata comments and adds request-level regressions for the effective URL, auth headers, and Anthropic body shape.

Root cause

The original PR diagnosis was incorrect: these models did not move to /chat/completions.

OpenClaude already selected https://opencode.ai/zen/go/v1/messages and generated an Anthropic-shaped request body, but the OpenAI shim used its default Bearer authentication. OpenCode Go's Messages route treated that request as unauthenticated.

OpenCode's current model table documents MiniMax M3, MiniMax M2.7, MiniMax M2.5, and Qwen3.6 Plus on /zen/go/v1/messages with @ai-sdk/anthropic:

https://opencode.ai/docs/go/

Live verification on 2026-06-18 with the same valid credential:

Request Result
/messages + Authorization: Bearer 401 Missing API key
/messages + raw x-api-key 200

The existing legacy qwen3.5-plus catalog entry was also verified through the live /models response and /messages + x-api-key request path.

Changes

  • Preserve /messages routing for the five existing MiniMax/Qwen catalog entries.
  • Add a model-level raw x-api-key authentication override.
  • Align gateway and model-descriptor comments with the Anthropic Messages contract.
  • Add catalog metadata coverage for endpoint/auth selection.
  • Add request-level regressions asserting:
    • exact /zen/go/v1/messages URL;
    • raw x-api-key value;
    • absence of Authorization;
    • Anthropic model, messages, system, max_tokens, and stream body fields;
    • absence of OpenAI max_completion_tokens and store fields.

Validation

  • bun run check — 4,612 passed, 0 failed
  • bun run typecheck — passed
  • bun test src/integrations/gateways/opencode.test.ts — 59 passed
  • bun test src/services/api/openaiShim.test.ts --test-name-pattern 'opencode go' — 5 passed
  • bun run integrations:check — artifacts up to date
  • bun run security:pr-scan — no suspicious additions
  • Built CLI live smoke with minimax-m3 — OK
  • Built CLI live smoke with qwen3.6-plus — OK
node dist/cli.mjs --bare --provider opencode-go --model minimax-m3 \
  --print 'Return exactly OK' --max-turns 1 --no-session-persistence \
  --output-format json

node dist/cli.mjs --bare --provider opencode-go --model qwen3.6-plus \
  --print 'Return exactly OK' --max-turns 1 --no-session-persistence \
  --output-format json

Scope

The current OpenCode Go catalog also needs a separate refresh for newly advertised model IDs such as GLM-5.2, Kimi K2.7 Code, and Qwen3.7 Max/Plus. That additive catalog update is intentionally kept out of this focused authentication fix.

Summary by CodeRabbit

  • Chores

    • Updated OpenCode Go model catalog entries (MiniMax and Qwen variants) to consistently target the Anthropic Messages /messages endpoint and use x-api-key authentication.
  • Tests

    • Added coverage to verify OpenCode Go requests are routed to https://opencode.ai/zen/go/v1/messages with x-api-key auth (no authorization header), send the correct Anthropic Messages body (system, messages, max_tokens, stream: false), and omit unsupported fields.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1c9d28d5-3336-4230-846a-5ad6c87aa666

📥 Commits

Reviewing files that changed from the base of the PR and between c977040 and c2919f3.

📒 Files selected for processing (2)
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (13)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
{src/integrations/**/*.ts,src/services/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Test the exact provider/model path you changed when possible for provider modifications

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py,json,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow the existing code style in the touched files

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow TypeScript strict mode and type safety practices by running typecheck before submitting

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}

⚙️ CodeRabbit configuration file

{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.

Project Snapshot

OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.

The installed CLI runs on Node.js >=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.

Work Style

  • Keep changes focused on one problem.
  • Prefer existing patterns in the file or nearby module.
  • Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
  • Add or update tests when behavior changes.
  • Update docs when setup, commands, provider behavior, or user-facing behavior changes.
  • For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.

Stack And Conventions

  • TypeScript with strict mode and ESM imports.
  • React + Ink for terminal UI.
  • Bun lockfile and Bun scripts for development workflows.
  • Node runtime for the built CLI.
  • Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.

Common libraries and patterns:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for child processes.
  • Existing service, provider, settings, permission, and UI patterns over new abstractions.

Repository Map

  • src/commands/ - slash and CLI command implementations.
  • src/components/ - React/Ink UI components.
  • src/services/ - API, MCP, OAuth, wiki, voice, and other service integrations.
  • src/tools/ - tool implementations.
  • src/utils/ - shared utilities.
  • `src/integration...

Files:

  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • src/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • src/services/api/openaiShim.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}

⚙️ CodeRabbit configuration file

{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.

Files:

  • src/services/api/openaiShim.test.ts
🔇 Additional comments (3)
src/services/api/openaiShim.ts (1)

2804-2818: LGTM!

src/services/api/openaiShim.test.ts (2)

2458-2467: LGTM!


2468-2470: Stale auth env var cleanup is properly implemented. All three (OPENAI_AUTH_HEADER, OPENAI_AUTH_SCHEME, OPENAI_AUTH_HEADER_VALUE) are captured in originalEnv at file initialization and restored in afterEach via restoreEnv(). Test isolation is correct.


📝 Walkthrough

Walkthrough

Five opencode-go model catalog entries (minimax-m3, m2.7, m2.5, qwen3.6-plus, qwen3.5-plus) are configured to use the Anthropic-format /messages endpoint with default x-api-key authentication. The openaiShim service is extended to recognize catalog-level auth header overrides. Configuration is verified by a catalog test and an integration test validating the outgoing request contract and Anthropic Messages shape. Test environment isolation ensures OPENCODE_API_KEY does not leak between test runs.

Changes

OpenCode Go Anthropic Messages API configuration

Layer / File(s) Summary
Catalog configuration and documentation update
src/integrations/gateways/opencode-go.ts, src/integrations/models/opencode.ts
Five MiniMax and Qwen model entries gain transportOverrides.openaiShim with endpointPath: '/messages' and a default auth header using x-api-key (scheme: 'raw'). Section comment now explicitly identifies the Anthropic Messages API and x-api-key authentication.
Catalog-level auth header override support
src/services/api/openaiShim.ts
Auth header selection logic now reads defaultAuthHeader from catalog entry's transportOverrides.openaiShim and uses it when present, suppressing environment-based OPENAI_AUTH_HEADER_VALUE and OPENAI_AUTH_HEADER configuration.
Model catalog verification test
src/integrations/gateways/opencode.test.ts
New test asserts that each of the five opencode-go model IDs has catalog entry with transportOverrides.openaiShim configured as { endpointPath: '/messages', defaultAuthHeader: { name: 'x-api-key', scheme: 'raw' } }.
Integration test with environment isolation
src/services/api/openaiShim.test.ts
Environment setup now manages process.env.OPENCODE_API_KEY lifecycle (capture, delete, restore) for test isolation. New parameterized test applies the opencode-go provider flag across multiple models, verifies requests go to /zen/go/v1/messages with x-api-key auth (no authorization header), validates Anthropic Messages request contract (system, messages, max_tokens, stream: false), and asserts absence of max_completion_tokens and store.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • jatmn
  • kevincodex1

Suggested labels

bug

🚥 Pre-merge checks | ✅ 6 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
No Hidden Policy Change ⚠️ Warning PR introduces a hidden trust-model and permission-policy change: a new defaultAuthHeader override mechanism in openaiShim.ts that silently suppresses global OPENAI_AUTH_HEADER* environmen... Document the policy change explicitly: (1) clarify that defaultAuthHeader in catalog creates a non-overridable auth contract; (2) discuss implications for users relying on env var overrides; (3) ensure this represents agreed maintainer...
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly summarizes the main change: fixing authentication for OpenCode Go messages endpoint models.
Description check ✅ Passed Description covers root cause, changes, validation, and scope. All required template sections are present and well-populated.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Risk Surface Disclosed ✅ Passed PR touches authentication, provider routing, and outbound network behavior. Risk surface (global env variables bypassing model-level auth headers) is explicitly documented in code comments and PR o...

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026
@muhammetalan
muhammetalan marked this pull request as ready for review June 18, 2026 15:37

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I found an issue that needs to be addressed before this is ready.

Findings

  • [P2] Complete the OpenCode Go endpoint migration
    src/integrations/gateways/opencode-go.ts:48
    If these OpenCode Go models now require the OpenAI-compatible /chat/completions endpoint, this change is only part of the migration. The current OpenCode Go API docs still list MiniMax M3, MiniMax M2.7, MiniMax M2.5, and Qwen3.6 Plus on https://opencode.ai/zen/go/v1/messages with the Anthropic SDK package, and the adjacent model descriptor section in this repo still groups these Go MiniMax/Qwen entries under the Anthropic messages endpoint. As written, the PR leaves reviewers and future maintainers with contradictory source-of-truth signals and only tests that the override is absent, not that the effective request is correctly chat-completions shaped. Please complete the migration by updating the local model metadata/comments, documenting or linking the live OpenCode evidence that these specific models moved to /chat/completions, and adding a regression that proves the effective OpenAI shim request for the affected models uses the chat-completions endpoint/body shape.

@muhammetalan muhammetalan changed the title Fix OpenCode Go open model endpoints Fix OpenCode Go messages authentication Jun 18, 2026
@muhammetalan

Copy link
Copy Markdown
Contributor Author

Thanks for catching the source-of-truth mismatch. I rechecked both the documented route and the live behavior, and my original endpoint-migration diagnosis was incorrect: these models have not moved to /chat/completions.

The actual failure was authentication. OpenClaude already generated an Anthropic-shaped body for /zen/go/v1/messages, but sent Authorization: Bearer. With the same valid credential, that request returns 401 Missing API key, while a raw x-api-key request succeeds.

I updated the patch to:

  • keep the five existing catalog entries on /messages;
  • apply raw x-api-key auth only to those entries;
  • align the local gateway/model comments;
  • add request-level regressions for the exact URL, auth header, absence of Bearer auth, and Anthropic body shape.

Official model/endpoint table: https://opencode.ai/docs/go/

Validation includes the full bun run check suite (4,612 passed, 0 failed), focused metadata/request tests, typecheck, integration artifact validation, security scan, and successful built-CLI live smokes for MiniMax M3 and Qwen3.6 Plus.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the update. I rechecked the changed paths and found one issue that still needs to be addressed.

Findings

  • [P2] Handle stale custom auth before relying on the x-api-key override
    src/services/api/openaiShim.test.ts:2463
    The new request regression covers the clean environment, but it does not cover the stale custom-auth path that users can carry from another OpenAI-compatible provider. OPENAI_AUTH_HEADER is global, applyProviderFlag('opencode-go') falls through the descriptor-backed default branch without clearing it, and _doOpenAIRequest gives that custom header precedence over the new shimConfig.defaultAuthHeader. I reproduced this by setting OPENCODE_API_KEY=fake-opencode-key plus OPENAI_AUTH_HEADER=Authorization, selecting opencode-go with minimax-m3, and capturing the outgoing /zen/go/v1/messages request: it sent Authorization: Bearer fake-opencode-key and no x-api-key, so the OpenCode Go Messages route still hits the 401 path this PR is meant to fix. Please complete the effective-request regression from the earlier review by covering this stale custom-auth case and ensuring these model-level x-api-key overrides cannot be bypassed by leftover OpenAI-compatible auth-header env when the user selects OpenCode Go.

A global OPENAI_AUTH_HEADER left over from another OpenAI-compatible
route took precedence over the model-level x-api-key in
_doOpenAIRequest, so OpenCode Go /messages models still sent
Authorization: Bearer and hit the 401 this PR fixes. Ignore the global
custom-auth env when the selected model's catalog entry defines an
openaiShim.defaultAuthHeader, so the model-level x-api-key contract
cannot be bypassed. Adds a stale-custom-auth regression for all five
models via the direct-env path.
@muhammetalan

Copy link
Copy Markdown
Contributor Author

Thanks for the careful re-review — you're right, and I reproduced the exact case you described.

With OPENCODE_API_KEY set plus a stale OPENAI_AUTH_HEADER=Authorization left over from another OpenAI-compatible route, selecting opencode-go + minimax-m3 sent Authorization: Bearer … and no x-api-key, so the Messages route still hit the 401 Missing API key path this PR is meant to fix.

Root of it: the custom auth-header env is global and took precedence in _doOpenAIRequest over the model's new defaultAuthHeader. I moved the fix to the request layer so it's path-independent: when the selected model's catalog entry defines an openaiShim.defaultAuthHeader (the five Go /messages models), the leftover global OPENAI_AUTH_HEADER / OPENAI_AUTH_HEADER_VALUE / OPENAI_AUTH_SCHEME are ignored, so they can't bypass the model-level x-api-key contract. The other Go models (GLM/Kimi/DeepSeek/MiMo) and legitimate custom-auth users for routes without a defaultAuthHeader are unaffected.

Regression coverage now includes the stale-custom-auth scenario for all five models via the direct-env path, asserting the effective request still goes to /zen/go/v1/messages with raw x-api-key and no Authorization. I confirmed it fails on main (no x-api-key) and passes with the fix.

Validation:

  • bun run check — 4,612 passed, 0 failed
  • bun test src/services/api/openaiShim.test.ts --test-name-pattern 'opencode go' — 5 passed (5/5 fail without the fix)
  • bun run typecheck / integrations:check / security:pr-scan — clean
  • Built-CLI live smoke with a stale Authorization env still set: minimax-m3, qwen3.6-plus, and the direct-env path all returned OK

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the update. I rechecked the previously discussed paths and do not see any remaining actionable issues from my side.

@kevincodex1 LGTM

@kevincodex1 kevincodex1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM!

@kevincodex1
kevincodex1 merged commit 0e1fce4 into Twigpine:main Jun 22, 2026
4 checks passed
Gravirei pushed a commit to Gravirei/openclaude that referenced this pull request Jun 22, 2026
* fix opencode go open model endpoints

* fix(opencode): use x-api-key for Go messages

* fix(opencode): keep Go x-api-key over stale auth

A global OPENAI_AUTH_HEADER left over from another OpenAI-compatible
route took precedence over the model-level x-api-key in
_doOpenAIRequest, so OpenCode Go /messages models still sent
Authorization: Bearer and hit the 401 this PR fixes. Ignore the global
custom-auth env when the selected model's catalog entry defines an
openaiShim.defaultAuthHeader, so the model-level x-api-key contract
cannot be bypassed. Adds a stale-custom-auth regression for all five
models via the direct-env path.
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.

3 participants