Skip to content

feat(opencode): Add Databricks provider support#7984

Open
dgokeeffe wants to merge 31 commits intoanomalyco:devfrom
dgokeeffe:feat/databricks-provider
Open

feat(opencode): Add Databricks provider support#7984
dgokeeffe wants to merge 31 commits intoanomalyco:devfrom
dgokeeffe:feat/databricks-provider

Conversation

@dgokeeffe
Copy link

Summary

Adds Databricks Foundation Model APIs as a new provider, enabling opencode users to connect to their Databricks workspace's pay-per-token LLM endpoints.

Fixes #7983

Changes

  • Provider implementation (provider.ts): Full Databricks provider with OpenAI-compatible endpoint support at /serving-endpoints
  • Auth guidance (auth.ts): Added Databricks to auth login flow with clear authentication instructions
  • Test cleanup (preload.ts): Clear Databricks env vars between tests
  • Unit tests (databricks.test.ts): 12 tests covering config parsing, auth precedence, URL handling, and model capabilities

Authentication Methods

Supports three auth methods (in priority order):

  1. PAT token via DATABRICKS_TOKEN or opencode auth login
  2. OAuth M2M via DATABRICKS_CLIENT_ID + DATABRICKS_CLIENT_SECRET
  3. Azure AD Service Principal via ARM_CLIENT_ID + ARM_CLIENT_SECRET + ARM_TENANT_ID

Default Models

Includes default definitions for common Foundation Model API endpoints (Claude, Llama, GPT-5, Gemini). Users can add custom model endpoints via opencode.json.

Verification

  • All 12 new tests pass: bun test packages/opencode/test/provider/databricks.test.ts
  • Tested locally with PAT authentication against a Databricks workspace

@github-actions
Copy link
Contributor

The following comment was made by an LLM, it may be inaccurate:

No duplicate PRs found

@dgokeeffe dgokeeffe force-pushed the feat/databricks-provider branch from 0c9f889 to 7ae4802 Compare January 17, 2026 03:26
@cbcoutinho
Copy link

cbcoutinho commented Jan 17, 2026

@dgokeeffe I am really looking forward to this PR landing, especially after seeing your post on LinkedIn regarding running opencode on a cluster via databricks ssh .... Great work!

I'm interested in running this locally, although without a Databricks PAT if possible. Can you provide a comment regarding auth via azure-cli or databricks-cli?

@mdlam92
Copy link

mdlam92 commented Jan 21, 2026

2026-01-21-124311_1670x490_scrot

is this PR supposed to make databricks show up as a provider in the /connect command?

i checked out your branch locally and built it and was trying to use it to use models in databricks but not sure if this implements all that

@mdlam92
Copy link

mdlam92 commented Jan 21, 2026

2026-01-21-124311_1670x490_scrot is this PR supposed to make databricks show up as a provider in the `/connect` command?

i checked out your branch locally and built it and was trying to use it to use models in databricks but not sure if this implements all that

oh i got it working, i guess i had to manually add my provider to my opencode.json?? im not entirely sure why that worked tho

@dgokeeffe dgokeeffe force-pushed the feat/databricks-provider branch from 6d7ed29 to 3843161 Compare January 23, 2026 06:13
@dgokeeffe
Copy link
Author

dgokeeffe commented Jan 25, 2026

@mdlam92 - I pulled the trigger a bit too quick on this PR. As I tested it more and more, I had to make some changes. Databricks should now appear as a provider on the Connect screen.

There were a few changes I had to make that are in this PR:

  1. Empty content handling - The AI SDK sends content: "" for assistant messages that only have tool calls. Databricks Model Serving (which uses OpenAI-compatible endpoints) rejects these empty strings. This PR filters out empty content and transforms it to content: null where needed.
  2. Prompt caching - Added support for Databricks prompt caching via cache_control on system messages and recent conversation turns. This works for models that support it (GPT, Gemini, Claude via Databricks).
  3. Host URL prompt in Connect screen - Unlike other providers with fixed API endpoints, Databricks requires your workspace-specific URL (e.g., https://your-workspace.cloud.databricks.com). I added an extra prompt in the /connect flow to capture the host URL along with your API key.

Authentication options (in order of precedence):

  1. PAT Token - Set DATABRICKS_HOST and DATABRICKS_TOKEN environment variables
  2. Databricks CLI - Run databricks auth login, and the provider will use your cached token from ~/.databricks/token-cache.json
  3. Azure CLI (for Azure Databricks) - If you're logged in with az login, it will use that for workspaces on *.azuredatabricks.net
  4. OAuth M2M - Set DATABRICKS_HOST, DATABRICKS_CLIENT_ID, and DATABRICKS_CLIENT_SECRET

Quick start

Option 1: Using Databricks CLI (easiest)

databricks auth login --host https://your-workspace.cloud.databricks.com

Option 2: Using environment variables

export DATABRICKS_HOST="https://your-workspace.cloud.databricks.com"                                                                                                                                               
export DATABRICKS_TOKEN="your-pat-token" 

Once auth is configured, Databricks should auto-load with default models (Claude, GPT-5, Gemini). You shouldn't need to manually edit opencode.json unless you want to add custom model endpoints.

Let me know if you run into any issues, and anything I need to do to get this merged in.

@hellomikelo
Copy link

hellomikelo commented Jan 30, 2026

Just tested this PR and can confirm Databricks can be connected as a model provider.

But gpt 5.2 endpoint needs to change to use the /responses endpoint.

Bad Request: Model databricks-gpt-5-1-codex-max only supports the Responses API. Please use /serving-endpoints/responses instead.

Add Databricks Foundation Model APIs as a new provider supporting
OpenAI-compatible endpoints via /serving-endpoints.

Authentication methods (in priority order):
- Personal Access Token (DATABRICKS_TOKEN or stored auth)
- OAuth M2M (DATABRICKS_CLIENT_ID + DATABRICKS_CLIENT_SECRET)
- Azure AD Service Principal (ARM_CLIENT_ID/SECRET/TENANT_ID)
- Azure CLI (for Azure Databricks workspaces)

Includes default model definitions for Claude, Llama, GPT-5, and
Gemini models available through Databricks pay-per-token endpoints.

Fixes model transformation to use Provider.Model format with proper
capabilities and API configuration.
Add optional host field to API authentication schema to support
providers like Databricks that require both workspace URL and API key.

Update ProviderAuth.api to accept optional host parameter and modify
Databricks provider loader to prioritize stored auth host over config
or environment variables for workspace URL resolution.
Implement DatabricksApiMethod component that prompts users for both
workspace URL and Personal Access Token in sequence, eliminating the
need for environment variables or custom configuration files.

Enhance 'opencode auth login' to prompt for Databricks workspace URL
before API key, storing both values for complete authentication.
Update generated TypeScript SDK types to reflect optional host field
in API authentication schema.
- Make description prop a function in DatabricksApiMethod
- Add escape key support to cancel dialog
- Prevent default behavior on return key press
Apply message caching to Databricks models that support it (GPT and
Gemini models with cache_read cost > 0). This improves performance
and reduces costs for repeated requests.
…vider

Add comprehensive model support including:
- GPT-5 variants: GPT-5.2, GPT-5.1, GPT-5 (base), Codex variants, mini/nano
- GPT-OSS models: 120B and 20B
- Gemini models: Gemini 3 Pro/Flash, Gemini 2.5 Pro/Flash
- Gemma 3 12B model

All models include proper capabilities, cost, and limit
configurations for pay-per-token Databricks endpoints.
Add comprehensive documentation for Databricks Foundation Model APIs
provider including:
- Setup instructions via /connect command
- Authentication methods (PAT, OAuth M2M, Azure AD, Azure CLI)
- Configuration options
- Workspace URL formats for different cloud providers
- Extract Azure Databricks resource ID to constant
- Improve error handling: use debug logging for OAuth failures instead of error
- Add clarifying comments for OAuth M2M credential handling
- Use constant instead of hardcoded resource ID value
Add proper auth.json backup and restoration in test to prevent
test pollution and ensure tests don't affect each other.
Refactor dialog provider to split host and API key prompts
Add support for reading Databricks CLI token cache for auth
Implement token refresh logic for expired tokens
Use DATABRICKS_HOST env var as default placeholder
Skip authentication prompts when valid CLI token cache exists
Automatically bootstrap provider if CLI credentials are available
Read host from ~/.databrickscfg profiles via DATABRICKS_CONFIG_PROFILE
Add getFreshToken function to refresh expired tokens from CLI cache
Use custom fetch that refreshes tokens before each API request
Support profile configuration in opencode.json config
Filter empty content messages for Databricks provider
Ensure type: object on tool parameter schemas for Databricks
Match Anthropic behavior for message normalization
Add quick start guide for Databricks CLI authentication
Document CLI profile support and token refresh behavior
Update authentication method priority order
dgokeeffe and others added 10 commits January 31, 2026 13:27
Add @types/dompurify and @types/strip-ansi to fix typecheck errors
after rebasing to dev branch.

Co-Authored-By: Claude <noreply@anthropic.com>
Databricks and other OpenAI-compatible APIs reject messages with empty
text content blocks. This fix ensures tool results always have non-empty
text by using "[No output]" as a placeholder when the output is empty.

Co-Authored-By: Claude <noreply@anthropic.com>
Add tests for all Databricks model families:
- GPT-5 models (5.2, 5.1, Codex, mini, nano, OSS)
- Gemini models (3 Pro/Flash, 2.5 Pro/Flash, Gemma 3)
- Claude models (Sonnet 4/4.5, Haiku 4.5, Opus 4.1/4.5, 3.7)
- Llama models (4 Maverick, 3.3, 3.1)
- Qwen models (Qwen3 Next)

Tests verify capabilities, costs, API configuration, and model families
are correctly set for each model type.

Co-Authored-By: Claude <noreply@anthropic.com>
OpenCode requires tool calling for its agentic workflows, so models
without reliable tool support are now excluded from the default list:
- GPT OSS models (120B, 20B)
- Gemma 3 12B
- All Llama models (4 Maverick, 3.3 70B, 3.1 405B/8B)
- Qwen3 Next 80B

Tool-calling models still included:
- GPT-5 family (5.2, 5.1, Codex variants, mini, nano)
- Gemini family (3 Pro/Flash, 2.5 Pro/Flash)
- Claude family (Sonnet 4/4.5, Haiku 4.5, Opus 4.1/4.5, 3.7)

Updated tests to verify only tool-capable models are loaded.

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive tests for empty content filtering and tool calling
across all Databricks model types:
- Databricks Claude (Anthropic model via OpenAI-compatible API)
- Databricks GPT-5 (OpenAI model via OpenAI-compatible API)
- Databricks Gemini (Google model via OpenAI-compatible API)

Tests verify:
- Empty text parts are filtered while tool calls are preserved
- Multiple tool calls in single message work correctly
- Multi-turn conversations with tools maintain correct structure
- Reasoning parts with empty text are properly filtered

Co-Authored-By: Claude <noreply@anthropic.com>
The Databricks API rejects messages with empty string content, but the
AI SDK sends content: "" for assistant messages that only contain tool
calls. This fix implements a custom fetch wrapper that intercepts the
request payload and converts content: "" to content: null for assistant
messages with tool_calls.

Also includes defensive improvements in message-v2.ts to skip empty
text/reasoning parts and ensure non-empty tool output text.

Co-Authored-By: Claude <noreply@anthropic.com>
- Add documentation link for Azure Databricks resource ID constant
- Update model comments to be more specific about limitations:
  - GPT-5.1 Codex Mini: Only supports Responses API
  - GPT OSS models: Don't support full JSON Schema (maxLength)
- Fix test isolation for auth/token-cache interference
- Update test to exclude GPT-5.1 Codex Mini (not compatible)

Co-Authored-By: Claude <noreply@anthropic.com>
…kens

The getFreshToken function now attempts to refresh expired tokens using
the refresh_token, matching the behavior of the initialization code.
Previously, if a token expired during a session, the function would just
log a warning and return the stale token, causing API calls to fail.

Changes:
- Added refresh_token and expires_in fields to cache type definition
- Added token refresh logic when cached token is expired but has refresh_token
- Updates token cache file after successful refresh
- Falls back gracefully with warning if refresh fails

Also adds tests for:
- Successful token refresh with cache update verification
- Graceful fallback when token refresh fails

Co-Authored-By: Claude <noreply@anthropic.com>
@dgokeeffe dgokeeffe force-pushed the feat/databricks-provider branch from 21aeb63 to 211b238 Compare January 31, 2026 02:28
@elementalvoid
Copy link

I'm super stoked to see this! I searched for such a provider a few weeks ago but it had to have been just before you created the issue. Last week I took a go at adding support, but I did so as a plugin where you decided to integrate into the CLI. Official in-built support will be great but I had no idea what I was getting myself into so I wanted to start a bit more out of band. I got a working version and was just publishing it internally to my company today for folks to try out when someone informed me of your PR!

I've a couple of thoughts/questions as I read and compare where I landed...

  1. I am spoiled by the GH Copilot provider autoloading available models so I chose to use a Databricks API (${workspace_host}/api/2.0/serving-endpoints) to enumerate the available models.
    • This meant my plugin picks up the foundational models plus any custom and external models automatically. This API provides detailed model information (cost, capabilities, etc.).
    • It meant that I only show available models whether that be due to permissions or other availability requirements (related to your comment that "These are the pay-per-token endpoints available in most workspaces").
    • Sadly, this API does not provide context window sizing so maybe that's reason enough to use hard coded model configs.
  2. Model costs: Since the models returned from (1) included costs in DBU units, I created a configurable dbu_rate so that if my DBU cost or rate was different than someone else's it could be adjusted. But I see you are already converting from DBUs to USD. Super transparently, I have no clue if their DBUs are static across users or not. Do you know?

I ran into some other issues (errors about stream_options, parallel tool calls, gemini thoughtSignatures, etc.) that lead me to do much more transformation than you did. I'm hoping that was due to my implementation. But I'll try to test your version out soon and see if I run into any similar issues.

@elementalvoid
Copy link

I got a chance to test last night. I'm excited to see this work happening but I had some pretty major troubles....

I'm going to detail my issues below. I'll post a second comment with a summary of all the translations that I had to make. Sorry/not-sorry about the amount of text that is about to appear.

I'm happy to participate however you find it most helpful. I'm unsure at the moment about making my provider plugin public but I can pursue that internally if it would help.


1. /connect and auth login don't work

Like @mdlam92, /connect (and opencode auth login) does not show the new provider. I exported the host/key env vars and it gets enabled automatically.

2. GPT Codex doesn't work

I can replicate @hellomikelo's databricks-gpt-5-1-codex-max issue.

❯ ./packages/opencode/dist/opencode-darwin-arm64/bin/opencode run --model databricks/databricks-gpt-5-1-codex-max 'hello'
Error: Bad Request: Model databricks-gpt-5-1-codex-max only supports the Responses API. Please use /serving-endpoints/responses instead.

I will note that non-codex gpt models work fine:

❯ ./packages/opencode/dist/opencode-darwin-arm64/bin/opencode run --model databricks/databricks-gpt-5-1 'hello'

Hi! What are you working on today, or how can I help with your code?

3. Model availability

Not all of the hard coded models are available. Notably the gemma, gpt-oss, and llama models are missing.

❯ ./packages/opencode/dist/opencode-darwin-arm64/bin/opencode models
databricks/databricks-claude-3-7-sonnet
databricks/databricks-claude-haiku-4-5
databricks/databricks-claude-opus-4-1
databricks/databricks-claude-opus-4-5
databricks/databricks-claude-sonnet-4
databricks/databricks-claude-sonnet-4-5
databricks/databricks-gemini-2-5-flash
databricks/databricks-gemini-2-5-pro
databricks/databricks-gemini-3-flash
databricks/databricks-gemini-3-pro
databricks/databricks-gpt-5
databricks/databricks-gpt-5-1
databricks/databricks-gpt-5-1-codex-max
databricks/databricks-gpt-5-2
databricks/databricks-gpt-5-mini
databricks/databricks-gpt-5-nano

4. Gemini models don't work

4a. MCP tool calls

When using a Databricks hosted Gemini model, MCP Tool calls need to have the JSON Schema sanitized to remove the $schema entry. Without this we get the following:

❯ ./packages/opencode/dist/opencode-darwin-arm64/bin/opencode run --model databricks/databricks-gemini-3-flash 'hello'
Error: Bad Request: {
  "error": {
    "code": 400,
    "message": "Invalid JSON payload received. Unknown name \"$schema\" at 'tools[0].function_declarations[0].parameters': Cannot find field.\nInvalid JSON payload received. Unknown name \"$schema\" at 'tools[0].function_declarations[1].parameters': Cannot find field.\nInvalid JSON payload received.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "tools[0].function_declarations[0].parameters",
            "description": "Invalid JSON payload received. Unknown name \"$schema\" at 'tools[0].function_declarations[0].parameters': Cannot find field."
          },
          {
            "field": "tools[0].function_declarations[1].parameters",
            "description": "Invalid JSON payload received. Unknown name \"$schema\" at 'tools[0].function_declarations[1].parameters': Cannot find field."
          }
        ]
      }
    ]
  }
}

I condensed that to two tools but it is dependent on how many tools you have.

I have a set of changes that resolve this but they're very likely not the right way to resolve it as I sanitized both the gemini model requests and all mcp tool requests (for all models and providers .. gross).

4b. Response structure string vs. array

With MCPC resolved, requests with a gemini model now get a response but Databricks returns an array of object for the content instead of a string as expected:

❯ ./packages/opencode/dist/opencode-darwin-arm64/bin/opencode run --model databricks/databricks-gemini-3-flash 'hello'

Error: AI_TypeValidationError: Type validation failed: Value: {"model":"gemini-3-flash-preview","choices":[{"delta":{"role":"assistant","content":[{"type":"text","text":"Hello! How can I help you with your codebase today?","thoughtSignature":"CiEBjz1rXyr7BGOKA1RF3FdIrRxBsGEHM2WT7j+0CLfurTo="}]},"index":0,"finish_reason":"stop"}],"usage":{"prompt_tokens":18295,"completion_tokens":12,"total_tokens":18307},"object":"chat.completion.chunk","id":null,"created":1770142691}.
Error message: [{"code":"invalid_union","errors":[[{"expected":"string","code":"invalid_type","path":["choices",0,"delta","content"],"message":"Invalid input: expected string, received array"}],[{"expected":"object","code":"invalid_type","path":["error"],"message":"Invalid input: expected object, received undefined"}]],"path":[],"message":"Invalid input"}]

We need to transform the response's choices.content (returned as an array of object). We need to give back content as a string and deal with the thoughtSignature which is in the object. But we quickly spiral into other transformations too (see next comment).

@elementalvoid
Copy link

elementalvoid commented Feb 3, 2026

Regarding the rest of the transformations I had to make, I had Opus create the following summary of all of the specializations that I added. I honestly don't know if all of them are strictly required, but with these I found that all of my models worked without issue.

1. Gemini-Specific Transformations
Tool Schema Sanitization (utils/sanitize-tools.ts)

Gemini has strict JSON Schema requirements. The following sanitizations are applied:

  • Strips $schema field - Gemini doesn't support this standard JSON Schema field
  • Resolves $ref inline - Gemini poorly handles JSON Schema references, so they're inlined
  • Removes definitions/$defs - After inlining refs, these are deleted
  • Strips non-standard ref field - Some tools use ref (without $) which Gemini interprets incorrectly
  • Preserves only $ref, description, default when a ref is present
Tool Call History Handling (convert-to-openai-messages.ts:281-314)

Gemini has thought_signature requirements that break multi-turn tool conversations:

  • Historical tool calls → text - Converted to [Called tool: name(args)] format
  • Historical tool results → user messages - Become user messages with [Tool result for name: content] format
  • Only current-turn tool calls preserved - The most recent assistant message retains actual tool call structure
Thought Signature Preservation (databricks-chat-model.ts:471-556)

Gemini's thoughtSignature is extracted and passed through providerMetadata.databricks.thoughtSignature.

2. Stream Options Handling

Some models reject stream_options (databricks-chat-model.ts:232-237):

Model Family stream_options
Llama Omitted
Qwen Omitted
Gemma Omitted
GPT-OSS Omitted
Claude Included
Gemini Included
Other Included
3. Message Format Transformations
AI SDK → OpenAI-compatible format (convert-to-openai-messages.ts)
Message Type Transformation
System Passed through directly
User Text and file parts converted; images formatted to data URLs
Assistant Text extracted, tool calls converted, empty content → null
Tool Result output converted to string (handles text, json, error-text, error-json types)
Empty Content Normalization

When assistant has tool calls but no text, content becomes null (not empty string) - this is a Databricks requirement.

content: textContent || (toolCalls.length > 0 ? null : '')
4. Image Formatting (utils/format-image.ts)

Normalizes image data to proper URLs:

Input Type Output
URL objects String URL
Binary data (Uint8Array/ArrayBuffer) Base64 data URL (chunked encoding to avoid stack overflow)
String data URLs Passed through
HTTP/HTTPS URLs Passed through
Raw base64 string Prefixed with data:{mediaType};base64,
5. Finish Reason Mapping (map-openai-finish-reason.ts)

Maps OpenAI finish reasons to AI SDK format:

OpenAI AI SDK
stop stop
length length
content_filter content-filter
tool_calls tool-calls
function_call tool-calls
(other) unknown
6. Response Content Handling

Handles both response formats (databricks-chat-model.ts:291-309, 433-458):

  • String content - Directly used
  • Array of content parts - Text parts extracted and concatenated (for multi-modal responses)
Key Design Decisions
  1. parallel_tool_calls omitted - Databricks doesn't support this parameter
  2. No cache_control - Stripped from text parts (Anthropic-specific)
  3. Model-agnostic tool format - Converts to OpenAI function calling format universally

- Add Databricks to /connect provider list (was missing from models.dev)
- Strip $schema and resolve $ref for Gemini tool schemas (Gemini rejects $schema)
- Transform Gemini streaming responses (content array to string)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@elementalvoid elementalvoid left a comment

Choose a reason for hiding this comment

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

I saw your update and thought I'd give it another go. Here's what I found...

Side note: I said in a prior comment that not all of the hard coded models are available/are missing. I see now this is by design due to no or poor tool_use. 👍

// For Databricks Gemini models, strip $schema and resolve $ref references
// Gemini API rejects tool schemas containing $schema field
if (model.id.includes("gemini")) {
const sanitizeForGemini = (obj: any, defs?: Record<string, any>): any => {

Choose a reason for hiding this comment

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

Looks like this works for (most?) built-in tools, but not MCP tools.

With context7 enabled:

❯ grep -A5 '"mcp":' .opencode/opencode.jsonc
  "mcp": {
    "context7": {
      "enabled": true,
      "type": "remote",
      "url": "https://mcp.context7.com/mcp",
    },

❯ ./packages/opencode/dist/opencode-darwin-arm64/bin/opencode run --model databricks/databricks-gemini-3-flash 'hello'
Error: Bad Request: {
  "error": {
    "code": 400,
    "message": "Invalid JSON payload received. Unknown name \"$schema\" at 'tools[0].function_declarations[31].parameters': Cannot find field.\nInvalid JSON payload received. Unknown name \"$schema\" at 'tools[0].function_declarations[32].parameters': Cannot find field.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "tools[0].function_declarations[31].parameters",
            "description": "Invalid JSON payload received. Unknown name \"$schema\" at 'tools[0].function_declarations[31].parameters': Cannot find field."
          },
          {
            "field": "tools[0].function_declarations[32].parameters",
            "description": "Invalid JSON payload received. Unknown name \"$schema\" at 'tools[0].function_declarations[32].parameters': Cannot find field."
          }
        ]
      }
    ]
  }
}

If we disable context7 we get a fun new error on the builtin question tool:

❯ grep -A5 '"mcp":' .opencode/opencode.jsonc
  "mcp": {
    "context7": {
      "enabled": false,
      "type": "remote",
      "url": "https://mcp.context7.com/mcp",
    },


❯ ./packages/opencode/dist/opencode-darwin-arm64/bin/opencode run --model databricks/databricks-gemini-3-flash 'hello'
Error: Bad Request: {
  "error": {
    "code": 400,
    "message": "Schema.ref 'QuestionOption' was set alongside unsupported fields.  If a schema node has Schema.ref set, then only description and default can be set alongside it; other fields they would be replaced by the expanded reference.",
    "status": "INVALID_ARGUMENT"
  }
}

Choose a reason for hiding this comment

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

I noticed a PR today that fixes just the Gemini issues... #12292

Might wait for / integrate that? ¯\_(ツ)_/¯

id: "databricks",
name: "Databricks",
env: ["DATABRICKS_TOKEN"],
models: {},

Choose a reason for hiding this comment

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

I'm not sure the best way to populate this, but I think models here being empty causes this error when no auth is configured (not in auth.json and not via env var):

❯ env | grep -c DATABRICKS
0

❯ grep -ic databricks ~/.local/share/opencode/auth.json
0

❯ ./packages/opencode/dist/opencode-darwin-arm64/bin/opencode
{
  "name": "UnknownError",
  "data": {
    "message": "TypeError: undefined is not an object (evaluating 'Provider2.sort(Object.values(item.models))[0].id')\n    at <anonymous> (src/server/routes/provider.ts:68:93)\n    at o3 (../../node_modules/.bun/remeda@2.26.0/node_modules/remeda/dist/chunk-3ZJAREUD.js:1:137)\n    at <anonymous> (src/server/routes/provider.ts:68:20)\n    at processTicksAndRejections (native:7:39)"
  }
}

A similar error condition might exist in packages/opencode/src/provider/provider.ts where the databricks provider is added to the models.dev "database"? It doesn't appear that that location uses the models array in any way, but I'm not positive on way or another.

Choose a reason for hiding this comment

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

What this means in a usability sense is that you cannot use /connect inside of the TUI to configure the provider. You can use env vars or you can use opencode auth login though. Once env vars are set, models are accessible.

dgokeeffe and others added 3 commits February 8, 2026 14:11
When Databricks auth is not configured, the provider has models: {}.
Provider.sort(Object.values({}))[0].id crashed with TypeError because
the sorted array is empty. Changed mapValues to Object.fromEntries
with a filter to skip providers with no models from the default map.

This also fixes /connect not showing the Databricks provider.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The sanitizeForGemini function could infinite loop when a schema
contained circular $ref references (e.g., TreeNode referencing itself).
Added a Set to track refs currently being resolved. When a circular
ref is detected, returns {type: "object"} as a safe fallback,
matching the approach in PR anomalyco#12292.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Empty models crash: Provider.sort with empty array, route default map
- Gemini stream transform: content array to string, multiple text parts,
  thoughtSignature filtering, empty array, string passthrough
- Gemini schema: MCP $schema deeply nested, circular $ref, legacy
  definitions format, description preservation alongside $ref,
  non-Databricks providers keep $ref, $ref in array items

Total: 163 tests (was 150), 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

Support for Databricks Foundation Model APIs provider

5 participants