Skip to content

feat(core): add LiteLLM provider - #54558

Open
misbahsy wants to merge 2 commits into
anomalyco:devfrom
misbahsy:litellm-provider
Open

misbahsy wants to merge 2 commits into
anomalyco:devfrom
misbahsy:litellm-provider

Conversation

@misbahsy

@misbahsy misbahsy commented Oct 11, 2026 •

Copy link
Copy Markdown

Issue for this PR

Refs #48938

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

I add LiteLLM as a built-in provider with the id litellm, with tests and docs. It reuses the local-provider code that vLLM and Ollama use.

OpenCode reads /v1/models from http://127.0.0.1:4000 in the background. A user can set providers.litellm.settings.baseURL and an optional apiKey. It sends the key as a Bearer token. I do not hardcode a model catalog.

#48938 asks for this. PR #29937 closed because of the V2 move, so this change targets V2.

The models.dev entry is a separate PR. This change does not need it. Gateway cost (#43818, #52127) is out of scope.

A proxy with auth needs apiKey in config. /v1/models does not report tool or image support, so discovered models start with both off.

How did you verify your code works?

  • bun test test/plugin/provider-litellm.test.ts test/plugin/provider-vllm.test.ts in packages/core: 7 pass.
  • bun run typecheck in packages/core: errors only in unrelated files.
  • prettier --check passes on the new TypeScript files. oxlint with default rules finds nothing. I did not run the repo oxlint config.
  • The tests use a mock server. I did not run a real LiteLLM proxy.

Screenshots / recordings

No UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

If you do not follow this template your PR will be automatically rejected.


Added by the opencode bot (AI-generated).

Fixes #48938

Related: #53235, #47480, #52127, #43818

Public API: adds the built-in litellm provider (plugin opencode.provider.litellm, providers.litellm.settings.baseURL/apiKey), which auto-discovers models from 127.0.0.1:4000 (backwards compatible)

@github-actions

Copy link
Copy Markdown
Contributor

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

@opencode-agent opencode-agent Bot 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.

This works as described. I ran a mock LiteLLM proxy on 127.0.0.1:4000 and ran opencode models from source. On the base, no litellm models appear. With this PR, chat models are discovered, the embedding model is left out, and max_input_tokens becomes the context limit. I also tried a config that already defines a custom providers.litellm provider (headers, apiKey, models with tools/image capabilities, and a model the proxy doesn't list). All of those settings were kept, and discovery sent the Bearer key. The LiteLLM and vLLM tests pass, and typecheck in packages/core is clean.

Public API: this adds the built-in provider ID litellm and the plugin ID opencode.provider.litellm. Settings are providers.litellm.settings.baseURL/apiKey, and discovery can be turned off with -opencode.provider.litellm. OpenCode now also checks 127.0.0.1:4000 by default. It is backwards compatible: existing custom litellm provider configs keep working, and I tested this.

Two optional suggestions, noted inline: the default check on port 4000 could confirm the server is actually LiteLLM, and the docs could explain how to turn tools and images back on.

Fixes #48938
Related: #53235, #47480, #52127, #43818

discover: (client) =>
Effect.gen(function* () {
const response = yield* client.getJson("/v1/models", Response)
return response.data

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.

This now checks 127.0.0.1:4000 every 30s for every user, and port 4000 is a common dev-server port (Phoenix, Jekyll, …). The vLLM plugin checks /health and only accepts models where owned_by === "vllm", so other servers aren't mistaken for it. Here, any OpenAI-compatible server on port 4000 would appear as "LiteLLM". Could you first check something only LiteLLM serves, such as the unauthenticated /health/liveliness endpoint, before reading /v1/models?

OpenCode refreshes `/v1/models` in the background. It uses `max_input_tokens` as the context limit when the proxy
reports it, and it excludes models whose `mode` is not `chat`.

Discovered models advertise text input and output, but not vision or tools. `/v1/models` does not report what the model

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.

Most LiteLLM proxies sit in front of models that support tools and images (Claude, GPT, …). With input: ["text"], pasted images are replaced with a text placeholder (see #47480). Overriding this per model in providers.litellm.models.<id>.capabilities works: I tested it, and the override is kept after discovery. A short example of that override here would save users from getting stuck.

Another OpenAI-compatible server on port 4000 is no longer shown as LiteLLM. The docs show how to set tools and image input for a discovered model.
@misbahsy

Copy link
Copy Markdown
Author

Thanks for the review. I changed both points:

  1. Port 4000 check. Before it reads /v1/models, the plugin now checks /health/liveliness. This endpoint does not need a key, and only LiteLLM returns "I'm alive!" there. If another server on port 4000 gives a different response, OpenCode does not show it as LiteLLM. A new test covers a server that returns 200 for all paths and also serves /v1/models.
  2. Tools and images. The LiteLLM docs now show how to set capabilities for a discovered model. Discovery keeps this setting.

The LiteLLM and vLLM tests pass, and typecheck in packages/core is clean.

@old-square-eyes

Copy link
Copy Markdown

Thanks for implementing this. One missing piece for local coding-agent use is enriching discovery with LiteLLM’s /model/info metadata.
With aliases such as primary and default, /v1/models may provide only an ID. That means:

  • max_input_tokens is absent, so OpenCode uses a fallback rather than the deployed context limit.
  • Tool support remains disabled, even when the backend supports function calling.
  • Output limits and reasoning capabilities aren’t discovered.
    For example, my backend serves Qwen3.8-27B with 32K context, 4K maximum output and working tool calls. Discovering its alias alone doesn’t give OpenCode enough information to use it correctly as a coding agent.
    Could this also read /model/info, matching model_name to the discovered ID, and map:
  • max_input_tokens / max_output_tokens
  • supports_function_calling
  • supports_reasoning
  • Supported input/output modalities
    Ideally, discovery would reuse saved provider credentials, with /model/info enrichment optional when the client key lacks access—without requiring a LiteLLM master key or losing the basic model list.

This branch has not been deployed

No deployments
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.

[FEATURE]: Add LiteLLM as a provider

2 participants