Skip to content

fix(provider): OpenRouterProvider::name() should return profile_id for named OpenAI-compatible profiles #691

Description

@hoa1982rp

Problem

OpenRouterProvider::name() hardcodes the return value to "openrouter" regardless of the profile. When a named OpenAI-compatible profile is configured (e.g., [providers.my-gateway] with type = "open-ai-compatible"), the provider is still identified as "openrouter" instead of using the actual profile ID.

This breaks several integration points for named profiles:

  1. Auth refresh identity — the auth lifecycle cannot distinguish between different OpenAI-compatible profiles because they all report the same name.
  2. Model catalog cache namespace — cached catalogs from different profiles collide under the same "openrouter" key.
  3. Provider identification in logs — all named profiles log as provider=openrouter instead of their actual profile name, making debugging multi-gateway setups difficult.
  4. Profile-specific behavior gates — checks like profile_id.as_deref() != Some("fpt") exist elsewhere in the same impl, confirming that profile-aware logic is expected; name() should follow the same pattern.

Affected code

File: crates/jcode-provider-openrouter-runtime/src/openrouter_provider_impl.rs
Line: ~324

Current (v0.64.2):

fn name(&self) -> &str {
    "openrouter"
}

Proposed fix

The profile_id field already exists on the struct and is used extensively throughout the same implementation for profile-specific logic. Return it when available:

fn name(&self) -> &str {
    self.profile_id.as_deref().unwrap_or("openrouter")
}

This preserves backward compatibility — when profile_id is None (vanilla OpenRouter), it still returns "openrouter". When a named profile is active, it returns the actual profile name.

Additional note

I noticed the upstream repo contains a companion test named_openai_compatible_provider_reports_profile_name (in openrouter_tests.rs as of a local hotfix on v0.32.0) that validates this exact behavior — but it was never merged upstream. That test should be included alongside this fix:

#[test]
fn named_openai_compatible_provider_reports_profile_name() {
    let _lock = ENV_LOCK.lock();
    let _key = EnvVarGuard::set("TEST_NAMED_COMPAT_KEY", "test-key");

    let profile = crate::config::NamedProviderConfig {
        base_url: "https://llm.example.com/v1".to_string(),
        api_key_env: Some("TEST_NAMED_COMPAT_KEY".to_string()),
        default_model: Some("example-model".to_string()),
        ..Default::default()
    };

    let provider = OpenRouterProvider::new_named_openai_compatible("example-compat", &profile)
        .expect("named profile should initialize");

    assert_eq!(provider.name(), "example-compat");
}

Impact

This is a one-line change with zero risk to vanilla OpenRouter users (profile_id is None → falls back to "openrouter"). It unblocks production use of multiple named OpenAI-compatible profiles behind different gateways (LiteLLM, local proxies, etc.) without identity collision.

Thank you for jcode — it has been an excellent harness for our autonomous agent pipeline (SAORI).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    autonomous: noNeeds your brain: a product/design decision is required before anyone acts.priority: lowP3 - nice to have / minor / cosmeticquestionFurther information is requestedtriage: needs-decisionNeeds maintainer decision/design thought

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions