openclaw - ✅(Solved) Fix Bug Report: `normalizeProviderId` breaks provider-namespaced models like `kimi-coding/k2p5` [1 pull requests, 2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#74310Fetched 2026-04-30 06:25:43
View on GitHub
Comments
2
Participants
3
Timeline
4
Reactions
2
Author
Timeline (top)
commented ×2cross-referenced ×2

normalizeProviderId() in src/agents/provider-id.ts collapses the distinct provider ID kimi-coding into kimi. When a user configures a model under the kimi-coding provider namespace (e.g. kimi-coding/k2p5), the normalization causes the resolver to look for a kimi/k2p5 model entry instead. Because that entry does not exist, the system falls back to kimi-coding/k2p5 with a confusing Fallback: kimi-coding/k2p5 (selected model unavailable) message. New sessions are also initialized with the wrong kimi/k2p5 label.

Root Cause

normalizeProviderId() treats kimi-coding as an alias of kimi:

// src/agents/provider-id.ts
function normalizeProviderId(provider: string): string {
  const normalized = normalizeLowercaseStringOrEmpty(provider);
  if (normalized === "modelstudio" || normalized === "qwencloud") return "qwen";
  // ... other aliases ...
  if (normalized === "kimi" || normalized === "kimi-code" || normalized === "kimi-coding") return "kimi";
  // ...
  return normalized;
}

Because kimi-coding is a separate, namespaced provider in the user's config (with its own base URL, headers, and models), collapsing it to kimi breaks the lookup chain:

  1. normalizeModelRef("kimi-coding", "k2p5"){ provider: "kimi", model: "k2p5" }
  2. Resolver searches catalog for kimi/k2p5 → not found
  3. Fallback to raw string kimi-coding/k2p5

This also affects:

  • findNormalizedProviderValue()
  • findNormalizedProviderKey()
  • normalizeModelRef() (via src/agents/model-selection-shared.ts)

Fix Action

Fix / Workaround

Workaround (for users until fix is released)

PR fix notes

PR #74315: fix(agents): remove kimi-coding from normalizeProviderId alias chain

Description (problem / solution / changelog)

Problem

Closes #74310.

`normalizeProviderId()` in `src/agents/provider-id.ts` mapped `kimi-coding` → `kimi`. When a user configures a custom provider under the key `kimi-coding` (distinct base URL, auth, model list), the resolver collapses `kimi-coding/k2p5` into `kimi/k2p5`, can't find that entry in the catalog, and falls back to the raw string with a confusing message:

``` ↪️ Fallback: kimi-coding/k2p5 (selected model unavailable) ```

Root cause

```typescript // Before if (normalized === "kimi" || normalized === "kimi-code" || normalized === "kimi-coding") return "kimi"; ```

`kimi-code` is a short-form alias for the canonical `kimi` provider — collapsing it is correct. `kimi-coding` is the identifier used by the kimi-coding extension, which has its own base URL and model set. Collapsing it into `kimi` breaks catalog lookup for users who configure it as a standalone provider.

Fix

```typescript // After if (normalized === "kimi" || normalized === "kimi-code") return "kimi"; ```

Remove `kimi-coding` from the alias branch so it passes through as-is. Three test assertions that encoded the old (incorrect) expectation are updated to match the new behaviour.

Testing

  • Updated `normalizeProviderId("kimi-coding")` assertion in `model-selection.test.ts` to expect `"kimi-coding"`.
  • Updated two `resolvePersistedModelRef` / `resolvePersistedOverrideModelRef` assertions that used `overrideProvider: "kimi-coding"` to expect `provider: "kimi-coding"`.
  • All other kimi-related tests (`kimi`, `kimi-code`, NVIDIA Kimi K2.5, opencode-go/kimi-k2.6) remain unchanged and pass.

🤖 AI-assisted PR (Claude Sonnet 4.6 via Claude Code). Degree of testing: lightly tested — changes are a one-line removal with three corresponding test updates; no local build environment set up. I understand what the code does: `normalizeProviderId` is a string-normalization helper that maps legacy/variant provider spellings to canonical IDs. Removing `kimi-coding` from the alias branch lets it pass through as a distinct provider key rather than being folded into `kimi`.

Changed files

  • src/agents/model-selection.test.ts (modified, +3/-3)
  • src/agents/provider-id.ts (modified, +1/-1)

Code Example

{
  "models": {
    "providers": {
      "kimi-coding": {
        "baseUrl": "https://agent-gw.kimi.com/coding",
        "api": "anthropic-messages",
        "models": [
          {
            "id": "k2p5",
            "name": "k2p5",
            "reasoning": true,
            "contextWindow": 131072,
            "maxTokens": 32768
          }
        ]
      }
    }
  }
}

---

{
  "agents": {
    "defaults": {
      "model": {
        "primary": "kimi-coding/k2p5"
      }
    }
  }
}

---

🧠 Model: kimi-coding/k2p5 · 🔑 api-key (models.json)

---

🧠 Model: kimi/k2p5 · 🔑 api-key (models.json)
↪️ Fallback: kimi-coding/k2p5 (selected model unavailable)

---

// src/agents/provider-id.ts
function normalizeProviderId(provider: string): string {
  const normalized = normalizeLowercaseStringOrEmpty(provider);
  if (normalized === "modelstudio" || normalized === "qwencloud") return "qwen";
  // ... other aliases ...
  if (normalized === "kimi" || normalized === "kimi-code" || normalized === "kimi-coding") return "kimi";
  // ...
  return normalized;
}

---

// src/agents/provider-id.ts
// BEFORE:
if (normalized === "kimi" || normalized === "kimi-code" || normalized === "kimi-coding") return "kimi";

// AFTER:
if (normalized === "kimi" || normalized === "kimi-code") return "kimi";

---

🧠 Model: kimi-coding/k2p5 · 🔑 api-key (models.json)
RAW_BUFFERClick to expand / collapse

Bug Report: normalizeProviderId breaks provider-namespaced models like kimi-coding/k2p5

Component: Core model resolution (src/agents/provider-id.ts) Severity: Medium — breaks model selection for users with custom provider namespaces Affected versions: 2026.4.26 (and likely earlier)

Summary

normalizeProviderId() in src/agents/provider-id.ts collapses the distinct provider ID kimi-coding into kimi. When a user configures a model under the kimi-coding provider namespace (e.g. kimi-coding/k2p5), the normalization causes the resolver to look for a kimi/k2p5 model entry instead. Because that entry does not exist, the system falls back to kimi-coding/k2p5 with a confusing Fallback: kimi-coding/k2p5 (selected model unavailable) message. New sessions are also initialized with the wrong kimi/k2p5 label.

Steps to Reproduce

  1. In openclaw.json, add a provider entry under the key kimi-coding (not kimi):
{
  "models": {
    "providers": {
      "kimi-coding": {
        "baseUrl": "https://agent-gw.kimi.com/coding",
        "api": "anthropic-messages",
        "models": [
          {
            "id": "k2p5",
            "name": "k2p5",
            "reasoning": true,
            "contextWindow": 131072,
            "maxTokens": 32768
          }
        ]
      }
    }
  }
}
  1. Set the agent default model to kimi-coding/k2p5:
{
  "agents": {
    "defaults": {
      "model": {
        "primary": "kimi-coding/k2p5"
      }
    }
  }
}
  1. Start a new session and run /status.

Expected Behavior

🧠 Model: kimi-coding/k2p5 · 🔑 api-key (models.json)

Direct resolution with no fallback message.

Actual Behavior

🧠 Model: kimi/k2p5 · 🔑 api-key (models.json)
↪️ Fallback: kimi-coding/k2p5 (selected model unavailable)

The provider is normalized to kimi before the model catalog is consulted. When kimi/k2p5 is not found, the system falls back to the original string.

Root Cause

normalizeProviderId() treats kimi-coding as an alias of kimi:

// src/agents/provider-id.ts
function normalizeProviderId(provider: string): string {
  const normalized = normalizeLowercaseStringOrEmpty(provider);
  if (normalized === "modelstudio" || normalized === "qwencloud") return "qwen";
  // ... other aliases ...
  if (normalized === "kimi" || normalized === "kimi-code" || normalized === "kimi-coding") return "kimi";
  // ...
  return normalized;
}

Because kimi-coding is a separate, namespaced provider in the user's config (with its own base URL, headers, and models), collapsing it to kimi breaks the lookup chain:

  1. normalizeModelRef("kimi-coding", "k2p5"){ provider: "kimi", model: "k2p5" }
  2. Resolver searches catalog for kimi/k2p5 → not found
  3. Fallback to raw string kimi-coding/k2p5

This also affects:

  • findNormalizedProviderValue()
  • findNormalizedProviderKey()
  • normalizeModelRef() (via src/agents/model-selection-shared.ts)

Proposed Fix

Option A — Minimal / Recommended:

Remove kimi-coding from the Kimi alias branch so it remains a distinct provider ID. kimi and kimi-code can still normalize to kimi if that behavior is needed for backward compatibility.

// src/agents/provider-id.ts
// BEFORE:
if (normalized === "kimi" || normalized === "kimi-code" || normalized === "kimi-coding") return "kimi";

// AFTER:
if (normalized === "kimi" || normalized === "kimi-code") return "kimi";

Option B — Structural:

Reverse the lookup order in normalizeModelRef / findNormalizedProviderKey:

  1. First attempt an exact lookup using the raw provider ID.
  2. Only if that fails, fall back to the normalized form.

This makes normalization a true fallback rather than an unconditional rewrite, which is safer for custom provider namespaces.

Files to Modify (upstream source)

FileChange
src/agents/provider-id.tsRemove `

If Option B is preferred, also modify:

  • src/agents/model-selection-shared.ts (normalizeModelRef)
  • src/agents/provider-id.ts (findNormalizedProviderValue, findNormalizedProviderKey)

Workaround (for users until fix is released)

Rename the provider key from kimi-coding to kimi in models.providers. Note: this may conflict if you also need a separate kimi provider entry.

Verification

After applying Option A and restarting the gateway, start a new session with the config above and run /status. Expected output:

🧠 Model: kimi-coding/k2p5 · 🔑 api-key (models.json)

No fallback arrow should appear.

Additional Context

  • The normalizeProviderId function is also bundled into the Control UI (control-ui/assets/index-*.js), so the fix must be reflected there as well in the build output.
  • The kimi-coding plugin (extensions/kimi-coding/index.ts) references the provider ID directly; it does not need changes because it imports normalizeProviderId from core.

extent analysis

TL;DR

Remove kimi-coding from the Kimi alias branch in normalizeProviderId() to prevent it from normalizing to kimi.

Guidance

  • Identify and modify the normalizeProviderId() function in src/agents/provider-id.ts to exclude kimi-coding from the Kimi alias branch.
  • Consider implementing Option B, which reverses the lookup order in normalizeModelRef and findNormalizedProviderKey to prioritize exact lookups over normalized forms.
  • Verify the fix by restarting the gateway, starting a new session, and running /status to ensure the expected output is displayed without a fallback message.
  • Be aware that the fix must also be reflected in the Control UI build output (control-ui/assets/index-*.js).

Example

// src/agents/provider-id.ts
// BEFORE:
if (normalized === "kimi" || normalized === "kimi-code" || normalized === "kimi-coding") return "kimi";

// AFTER:
if (normalized === "kimi" || normalized === "kimi-code") return "kimi";

Notes

The provided fix assumes that kimi-coding is a separate, namespaced provider that should not be normalized to kimi. The workaround of renaming the provider key to kimi may conflict with existing kimi provider entries.

Recommendation

Apply the minimal fix (Option A) by removing kimi-coding from the Kimi alias branch, as it is the most straightforward solution that addresses the issue without introducing additional complexity.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Bug Report: `normalizeProviderId` breaks provider-namespaced models like `kimi-coding/k2p5` [1 pull requests, 2 comments, 3 participants]