Skip to content

fix: Ollama API compatibility — allow bare model names and smart openai/ prefix handling on wire#3167

Open
GeorgijeSav wants to merge 1 commit into
ultraworkers:mainfrom
GeorgijeSav:main
Open

fix: Ollama API compatibility — allow bare model names and smart openai/ prefix handling on wire#3167
GeorgijeSav wants to merge 1 commit into
ultraworkers:mainfrom
GeorgijeSav:main

Conversation

@GeorgijeSav
Copy link
Copy Markdown

fix: Ollama API compatibility — allow bare model names and smart openai/ prefix handling on wire

Fixes: ultraworkers/claw-code#3123
PR: GeorgijeSav/claw-code#1
Related: #3051, #3044


Summary

Ollama and other local OpenAI-compatible providers expose bare model names such as:

qwen2.5-coder:7b

without a provider/ prefix.

This caused two cascading failures reported in #3123:

  1. validate_model_syntax rejected bare model names outright because it required provider/model format.
  2. Prefixing the model as:
openai/qwen2.5-coder:7b

to satisfy validation still failed because the full slug was forwarded on the wire, producing:

404: model 'openai/qwen2.5-coder:7b' not found

from the local provider.

This PR fixes both layers.


Changes

validate_model_syntax

Bare model names (without /) are now accepted when OPENAI_BASE_URL resolves to a loopback host:

  • localhost
  • 127.0.0.1
  • ::1

Non-local gateways (e.g. OpenRouter) still require provider/model format.


wire_model_for_base_url

The openai/ prefix is now stripped for:

  • the default OpenAI endpoint
  • all known local endpoints

The prefix is preserved for custom non-local gateways.

Example:

openai/gpt-4.1-mini

continues to route correctly through providers such as OpenRouter.


Tests

Added:

  • unit tests for both new bypass paths
  • integration test for non-routing slash model IDs

Updated:

  • existing integration test renamed to reflect its actual assertion

Anti-slop triage

Classification

actionable-fix

Evidence

ultraworkers/claw-code#3123

Reproduction:

claw --model "qwen2.5-coder:7b" prompt "hi"

Result:

invalid model syntax

and:

claw --model "openai/qwen2.5-coder:7b" prompt "hi"

Result:

404: model 'openai/qwen2.5-coder:7b' not found

Both failure modes are now covered and fixed by tests.

Non-destructive review result

merge candidate

Changes are additive and guarded behind loopback URL detection.

Behaviour for non-local gateways remains unchanged.

No existing tests were removed.

Regression coverage includes:

  • trailing slash handling
  • /chat/completions suffix handling
  • IPv6 loopback support
  • userinfo in URL
  • case-insensitive host matching

Verification

  • cargo test --workspace passes
  • all new code paths covered by unit and integration tests
  • git diff --check passes
  • no secrets, tokens, private logs, or unrelated generated churn included

Resolution gate

Resolves ultraworkers/claw-code#3123.

Verification evidence:

  • test_bare_model_name_passes_when_openai_base_url_set
  • wire_model_strips_openai_prefix_for_custom_base_url
  • updated integration test

All pass successfully.


Merge status

  • This PR is ready to merge.
  • No remote PRs or issues were merged or closed automatically without owner approval.

…ai/ prefix handling on wire

fix: Ollama API compatibility — allow bare model names and smart openai/ prefix handling on wire
Copilot AI review requested due to automatic review settings May 27, 2026 17:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adjusts model ID handling for OpenAI-compatible endpoints, allowing “bare” model names for local gateways and refining when the openai/ routing prefix is stripped vs preserved.

Changes:

  • Add loopback base-URL detection to allow bare model IDs in the CLI when OPENAI_BASE_URL targets localhost/loopback.
  • Update OpenAI-compat provider logic to strip openai/ only for default OpenAI and loopback endpoints, preserving it for non-local gateways.
  • Expand/adjust unit and integration tests to cover the new routing/validation behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
rust/crates/rusty-claude-cli/src/main.rs Adds local base URL detection and updates model syntax validation + tests to allow bare model names when pointing at loopback.
rust/crates/api/src/providers/openai_compat.rs Refines openai/ prefix stripping decisions based on normalized base URL and loopback host detection; adds focused tests.
rust/crates/api/tests/openai_compat_integration.rs Updates integration expectations and adds coverage for non-routing slash-containing model IDs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1931 to +1935
fn is_local_base_url(url: &str) -> bool {
let rest = match url.split_once("://") {
Some((_, r)) => r,
None => return false,
};
Comment on lines +942 to +956
fn normalize_base_url(url: &str) -> &str {
let url = url.trim_end_matches('/');
url.strip_suffix("/chat/completions")
.map(|s| s.trim_end_matches('/'))
.unwrap_or(url)
}

/// Extract the host (without port) from a URL string.
/// Returns an empty string if the URL cannot be parsed.
fn url_host(url: &str) -> &str {
// Strip scheme ("https://", "http://", etc.)
let rest = match url.split_once("://") {
Some((_, r)) => r,
None => return "",
};
Comment on lines +2779 to +2780
#[test]
fn wire_model_strips_openai_prefix_for_custom_base_url() {
@petterreinholdtsen
Copy link
Copy Markdown

Note, my corporate LLM API server do not present itself as localhost, and still need to accept model names without slashes in them. The assumtion that this only is relevant for localhost/127.0.0.1/::1 is not correct in my case. Also, it is worth noting that 127.0.0.2 and all other IPv4 addresses starting with 127 are also localhost.

@V-E-O
Copy link
Copy Markdown

V-E-O commented May 29, 2026

To be simplified why not completely remove function validate_model_syntax?
Some model services even do not have "provider/"
I believe only Claude code need to strictly check model name.

.eq_ignore_ascii_case(normalize_base_url(config.default_base_url));
let host = url_host(base_url);
let is_local_url =
host.eq_ignore_ascii_case("localhost") || matches!(host, "127.0.0.1" | "::1");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should not be limited to localhost IP.
I may understand that local is implied to be really local (as one machine) but there is the case where the open endpoint can be at a totally :

  • different IP address locally (in example the Nividia DGX Spark as a inference only server) at 10.0.0.0/8, 127.x.x.x ,172.16/12, 192.168/16
  • an custom url with a DNS (example : vllm-prod-inference.github/v1)
  • public IP address or URL (with a token as a payload for instance)

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.

Ollama API compatibility issue for model name (model not found + wrong provider) 2

6 participants