Skip to content

fix(opencode): avoid provider ID collision with OpenCode built-in loaders - #2520

Merged
jeffmaury merged 1 commit into
openkaiden:mainfrom
MarsKubeX:openai-compatible-provider-typescript-error
Jul 22, 2026
Merged

jeffmaury merged 1 commit into
openkaiden:mainfrom
MarsKubeX:openai-compatible-provider-typescript-error

Conversation

@MarsKubeX

Copy link
Copy Markdown
Contributor

Summary

  • Fix TypeError: sdk.responses is not a function when using the OpenAI Compatible provider with OpenCode agent workspaces
  • Suffix the provider ID to "openai-compat" when the configured npm package is @ai-sdk/openai-compatible and the ID would collide with OpenCode's built-in loaders (openai, azure, azure-cognitive-services)
  • Add unit test covering the provider ID renaming

Problem

OpenCode has built-in custom loaders for specific provider IDs (e.g. "openai") that unconditionally call sdk.responses(modelID). When a user connects via Kaiden's "OpenAI Compatible" extension (LiteMaaS, vLLM, etc.), llmMetadata.name is "openai", which was used directly as the provider key in the generated opencode.json. Since the SDK package @ai-sdk/openai-compatible does not expose .responses(), the workspace crashes immediately on start.

Fix

The extension now detects when the provider ID would collide with a built-in loader and suffixes it to "openai-compat". This bypasses the built-in loader, causing OpenCode to use sdk.languageModel() instead — which works correctly with @ai-sdk/openai-compatible.

Test plan

  • Unit tests pass (31/31)
  • Create a workspace with OpenCode + OpenAI Compatible provider (e.g. LiteMaaS with Qwen3.6-35B-A3B) → no sdk.responses error
  • Create a workspace with OpenCode + Anthropic (native) → still works as before
  • Create a workspace with OpenCode + Ollama → still works as before
  • Create a workspace with OpenCode + Vertex AI → still works as before

Closes #2519

…ders

The OpenAI Compatible extension sets llmMetadata.name to "openai", which
was used directly as the provider key in the generated opencode.json.
OpenCode's built-in "openai" loader unconditionally calls sdk.responses(),
which is unsupported by @ai-sdk/openai-compatible, causing a TypeError.
Suffix colliding IDs to "openai-compat" to bypass the built-in loader.

Closes openkaiden#2519

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Marcel Bertagnini <mbertagn@redhat.com>
@MarsKubeX
MarsKubeX requested a review from a team as a code owner July 21, 2026 15:30
@MarsKubeX
MarsKubeX requested review from benoitf and jeffmaury and removed request for a team July 21, 2026 15:30
@coderabbitai

coderabbitai Bot commented Jul 21, 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5e11f14f-a356-49a7-9b42-0f555959be6a

📥 Commits

Reviewing files that changed from the base of the PR and between 5773010 and f62193e.

📒 Files selected for processing (2)
  • extensions/opencode/src/extension.spec.ts
  • extensions/opencode/src/extension.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout. (10)
  • GitHub Check: smoke-e2e-tests (dev) / ubuntu-24.04 (ollama)
  • GitHub Check: unit tests / windows-2022
  • GitHub Check: Windows
  • GitHub Check: smoke-e2e-tests (prod) / ubuntu-24.04 (ollama)
  • GitHub Check: typecheck
  • GitHub Check: unit tests / ubuntu-24.04
  • GitHub Check: macOS
  • GitHub Check: unit tests / macos-15
  • GitHub Check: Linux
  • GitHub Check: linter, formatters
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use /@/ path aliases instead of relative paths for imports outside the current directory's module group; use relative imports only for sibling modules within the same directory

Files:

  • extensions/opencode/src/extension.spec.ts
  • extensions/opencode/src/extension.ts
**/*.spec.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.spec.{ts,tsx,js,jsx}: Use test() instead of it() for test cases in Vitest unit tests
Use vi.mock(import('...')) for auto-mocking modules in unit tests; avoid manual mock factories when possible
Use vi.resetAllMocks() in beforeEach hooks instead of vi.clearAllMocks() for resetting mocks between tests
When an auto-mocked function or class method needs a real implementation, use vi.mocked(...) with the prototype pattern for class methods: vi.mocked(MyClass.prototype.myMethod).mockImplementation(...)

Files:

  • extensions/opencode/src/extension.spec.ts
extensions/*/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Register inference, container, and Kubernetes providers through the ProviderRegistry via extension APIs

Files:

  • extensions/opencode/src/extension.spec.ts
  • extensions/opencode/src/extension.ts
extensions/*/src/extension.ts

📄 CodeRabbit inference engine (AGENTS.md)

Extensions should export a standard activation API from their entry point

Files:

  • extensions/opencode/src/extension.ts
🧠 Learnings (7)
📚 Learning: 2026-05-05T17:30:20.418Z
Learnt from: MarsKubeX
Repo: openkaiden/kaiden PR: 1671
File: extensions/vertex-ai/src/vertex-ai.ts:272-302
Timestamp: 2026-05-05T17:30:20.418Z
Learning: In the openkaiden/kaiden repo, for cloud inference provider extension code under `extensions/*/src/*.ts`, treat `ProviderConnectionStatus = 'unknown'` as a valid/expected value when registering provider connections (e.g., Gemini/Claude/Mistral/OpenAI-compatible/Vertex AI). `'unknown'` indicates the connection was set up but is not continuously monitored—so do not flag it as incorrect. Only Ollama is expected to use `'started'` because it actively polls a local server.

Applied to files:

  • extensions/opencode/src/extension.spec.ts
  • extensions/opencode/src/extension.ts
📚 Learning: 2026-05-05T17:44:50.991Z
Learnt from: MarsKubeX
Repo: openkaiden/kaiden PR: 1671
File: extensions/vertex-ai/src/vertex-ai.ts:363-387
Timestamp: 2026-05-05T17:44:50.991Z
Learning: In this repo (openkaiden/kaiden), do not raise a code review issue when an extension’s `InferenceProviderConnectionFactory.create` factory method implementation omits (or does not use) the optional `logger` and/or `CancellationToken` parameters in its method signature/implementation. Current extensions (e.g., Vertex AI, Gemini, Claude, Mistral, OpenAI-compatible) follow this pattern, so reviewers should treat it as acceptable for `extensions/*` TypeScript source files.

Applied to files:

  • extensions/opencode/src/extension.spec.ts
  • extensions/opencode/src/extension.ts
📚 Learning: 2026-05-12T10:01:14.248Z
Learnt from: MarsKubeX
Repo: openkaiden/kaiden PR: 1810
File: extensions/kdn/src/kdn-extension.ts:43-46
Timestamp: 2026-05-12T10:01:14.248Z
Learning: In this repo’s extension code, when logging from binary discovery/resolution logic (e.g., choosing/validating custom paths, extension storage locations, or bundled resource paths), it’s intentional to include full filesystem paths in `console.log`/`console.warn` (such as in `extensions/**/src/*-extension.ts`). During review, do not flag these specific full-path messages as a privacy/security issue as long as they are clearly part of the binary resolution steps. If full-path logging appears outside binary discovery/resolution, review/flag it as usual.

Applied to files:

  • extensions/opencode/src/extension.spec.ts
  • extensions/opencode/src/extension.ts
📚 Learning: 2026-05-12T17:14:02.153Z
Learnt from: MarsKubeX
Repo: openkaiden/kaiden PR: 1850
File: packages/renderer/src/lib/agent-workspaces/AgentWorkspaceList.svelte:66-70
Timestamp: 2026-05-12T17:14:02.153Z
Learning: When reviewing code that uses `AgentWorkspaceSummaryUI.runtime`, treat it as a required, non-null `string` per the `openkaiden/kdn-api` 0.12.0 schema. Therefore, code like `a.runtime.localeCompare(b.runtime)` is safe and should not trigger warnings about possible `undefined`/`null` values or suggestions to use nullish coalescing/optional chaining for `runtime` (unless the current local types still mark `runtime` as optional, indicating a schema/version mismatch).

Applied to files:

  • extensions/opencode/src/extension.spec.ts
  • extensions/opencode/src/extension.ts
📚 Learning: 2026-06-29T13:16:53.102Z
Learnt from: benoitf
Repo: openkaiden/kaiden PR: 2296
File: extensions/container/packages/extension/src/helper/socket-finder/_socket-finder-module.ts:28-29
Timestamp: 2026-06-29T13:16:53.102Z
Learning: When reviewing imports in openkaiden/kaiden TypeScript/JavaScript files, prefer the configured `/@/` path alias instead of relative imports that would require traversing out of the current directory/module group (i.e., paths containing `..` that cross boundaries). 

Do not require alias conversion for descendant-path relative imports within the socket-finder module directory—for example, in `extensions/container/packages/extension/src/helper/socket-finder/**`, imports like `./podman/podman-version-detector` and `./podman/podman-windows-finder` are acceptable and should not be flagged.

Applied to files:

  • extensions/opencode/src/extension.spec.ts
  • extensions/opencode/src/extension.ts
📚 Learning: 2026-05-06T11:15:56.238Z
Learnt from: MarsKubeX
Repo: openkaiden/kaiden PR: 1671
File: extensions/vertex-ai/src/extension.spec.ts:43-51
Timestamp: 2026-05-06T11:15:56.238Z
Learning: In all extensions under extensions/*/src/extension.ts, deactivate() should only clear the module-level instance reference (e.g., set the instance to undefined) and must not call dispose() directly. The dispose() method is invoked by the extension host when processing extensionContext.subscriptions. Do not suggest asserting dispose() in tests for deactivate(); such assertions are unnecessary because disposal is handled by the host and CI checks should validate subscriptions handling instead.

Applied to files:

  • extensions/opencode/src/extension.ts
📚 Learning: 2026-06-18T08:20:05.553Z
Learnt from: MarsKubeX
Repo: openkaiden/kaiden PR: 2185
File: extensions/gemini/src/extension.ts:45-52
Timestamp: 2026-06-18T08:20:05.553Z
Learning: When reviewing openkaiden/kaiden extension code that registers `configurationFiles` via `agents.registerAgent()` (typically in `extensions/*/src/extension.ts`), do not flag an intentionally stub `read()` (e.g., returning `'{}'`) as causing data loss or as a missing file-I/O implementation. Per the framework, runtime behavior uses the declared `path` and the real, file-backed `read()`/`update()` implementations are supplied through `context.configurationFiles` during `preWorkspaceStart`.

Applied to files:

  • extensions/opencode/src/extension.ts
🔇 Additional comments (2)
extensions/opencode/src/extension.ts (1)

70-74: LGTM!

Also applies to: 131-155

extensions/opencode/src/extension.spec.ts (1)

237-262: LGTM!


📝 Walkthrough

Walkthrough

OpenCode custom-endpoint handling now avoids provider-ID collisions by deriving an openai-compat namespace for selected providers. Tests verify the generated model and provider configuration, including the absence of the original openai provider key.

Changes

OpenCode provider compatibility

Layer / File(s) Summary
Provider configuration mapping
extensions/opencode/src/extension.ts, extensions/opencode/src/extension.spec.ts
Selected providers receive a -compat configuration identifier for OpenAI-compatible endpoints, and tests verify the resulting model path and provider block.
Estimated code review effort: 2 (Simple) ~10 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: benoitf, jeffmaury, fbricon

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main fix: preventing provider ID collisions with OpenCode built-in loaders.
Description check ✅ Passed The description directly matches the changeset, explaining the collision fix, the rename behavior, and the added test.
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.

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.

@jeffmaury jeffmaury left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@MarsKubeX
MarsKubeX requested review from a team and gastoner and removed request for a team July 22, 2026 07:17
@jeffmaury
jeffmaury merged commit 890596f into openkaiden:main Jul 22, 2026
44 checks passed
@MarsKubeX
MarsKubeX deleted the openai-compatible-provider-typescript-error branch July 22, 2026 13:34
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.

TypeError: sdk.responses is not a function when using OpenAI Compatible provider with OpenCode

2 participants