Custom OpenAI-compatible providers: add per-model display_name, reasoning, max_output_tokens, cost, and provider display_name (opencode parity)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
Summary
Custom OpenAI-compatible providers configured via [providers.<name>] in ~/.jcode/config.toml were missing several fields that opencode supports for its custom OpenAI-compatible provider spec. This made it harder to get a clean model picker experience and correct cost display for self-hosted or third-party gateways.
Gaps identified
| Feature | opencode | jcode (before) | Status |
|---|---|---|---|
Provider display name (name) |
✅ | ❌ (raw profile key) | Fixed |
Per-model display name (name) |
✅ | ❌ (raw model id) | Fixed |
Per-model cost (cost.input/output/cache_read/cache_write) |
✅ | ❌ | Fixed |
Per-model max output tokens (limit.output) |
✅ | ❌ | Fixed |
Per-model reasoning bool (reasoning) |
✅ | provider-level only | Fixed |
| Per-model context_window | ✅ | ✅ | Already present |
Per-model image input (input) |
✅ | ✅ | Already present |
Changes
Config schema (jcode-config-types)
- New
ModelCostConfigstruct:input,output,cache_read,cache_write(USD per million tokens) - New fields on
NamedProviderModelConfig:display_name(aliasname),max_output_tokens(aliasoutput_limit),reasoning(bool),cost(ModelCostConfig) - New field on
NamedProviderConfig:display_name(provider-level)
Runtime wiring (jcode-provider-openrouter-runtime)
available_models_display(): applies per-model display name aliases in the pickerruntime_display_name()+direct_openai_compatible_route_parts(): use providerdisplay_namesupports_deepseek_reasoning_effort()/supports_openai_reasoning_effort(): check per-modelreasoningoverride firstcomplete(): per-modelmax_output_tokensoverrides runtime default in the request bodyfork(): carries all new fields
Picker routes (jcode-base/provider/catalog_routes.rs)
named_provider_profile_routes(): uses providerdisplay_nameas route label, per-modeldisplay_nameas routemodelfield, and convertscostconfig intoRouteCheapnessEstimatefor the picker cost overlay- New
cost_to_route_cheapness()helper
Tests
- 7 new tests in
openrouter_tests.rscovering display name, reasoning, max_output_tokens, and cost - 2 new tests in
catalog_routes.rscovering route display name + cost cheapness conversion
Docs
- README updated with new config field descriptions and enriched
config.tomlexample
Config example
[providers.my-api]
type = "openai-compatible"
base_url = "https://llm.example.com/v1"
api_key_env = "JCODE_PROVIDER_MY_API_API_KEY"
default_model = "my-model-id"
display_name = "My Custom API"
[[providers.my-api.models]]
id = "my-model-id"
context_window = 128000
display_name = "My Model"
max_output_tokens = 8192
reasoning = true
cost = { input = 0.15, output = 0.60, cache_read = 0.015 }
Branch
Verification
- Full workspace
cargo checkpasses cleanly - 99
jcode-provider-openrouter-runtimelib tests pass (7 new) - 2
jcode-basecatalog_routes tests pass (2 new) - All existing tests unaffected
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the config types in jcode-config-types, then trace provider handling through jcode-provider-openrouter-runtime and jcode-base/provider/catalog_routes.rs. Run the named openrouter_tests.rs and catalog_routes.rs tests; done means the documented provider and model fields are represented in runtime requests and picker routes, with the README example consistent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, cli
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100