fix(providers): respect user-configured baseUrl for kimi-coding (#36647)

* fix(providers): respect user-configured baseUrl for kimi-coding

The kimi-coding provider was built exclusively from
`buildKimiCodingProvider()` defaults, ignoring any user-specified
`baseUrl` or other overrides in `openclaw.json` providers config.
This caused 404 errors when users configured a custom endpoint.

Now merge `explicitProviders["kimi-coding"]` on top of defaults,
matching the pattern used by ollama/vllm. User's `baseUrl`, `api`,
and `models` take precedence; env/profile API key still wins.

Fixes #36353

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Tests: use Kimi implicit provider harness

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
2233admin
2026-03-13 00:14:07 +08:00
committed by GitHub
parent 3e28e10c2f
commit 9342739d71
3 changed files with 33 additions and 1 deletions

View File

@@ -30,6 +30,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Moonshot CN API: respect explicit `baseUrl` (api.moonshot.cn) in implicit provider resolution so platform.moonshot.cn API keys authenticate correctly instead of returning HTTP 401. (#33637) Thanks @chengzhichao-xydt.
- Kimi Coding/provider config: respect explicit `models.providers["kimi-coding"].baseUrl` when resolving the implicit provider so custom Kimi Coding endpoints no longer get overwritten by the built-in default. (#36353) Thanks @2233admin.
- Cron/proactive delivery: keep isolated direct cron sends out of the write-ahead resend queue so transient-send retries do not replay duplicate proactive messages after restart. (#40646) Thanks @openperf and @vincentkoc.
- TUI/chat log: reuse the active assistant message component for the same streaming run so `openclaw tui` no longer renders duplicate assistant replies. (#35364) Thanks @lisitan.
- macOS/Reminders: add the missing `NSRemindersUsageDescription` to the bundled app so `apple-reminders` can trigger the system permission prompt from OpenClaw.app. (#8559) Thanks @dinakars777.

View File

@@ -43,4 +43,26 @@ describe("kimi-coding implicit provider (#22409)", () => {
envSnapshot.restore();
}
});
it("uses explicit kimi-coding baseUrl when provided", async () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
const envSnapshot = captureEnv(["KIMI_API_KEY"]);
process.env.KIMI_API_KEY = "test-key";
try {
const providers = await resolveImplicitProvidersForTest({
agentDir,
explicitProviders: {
"kimi-coding": {
baseUrl: "https://kimi.example.test/coding/",
api: "anthropic-messages",
models: buildKimiCodingProvider().models,
},
},
});
expect(providers?.["kimi-coding"]?.baseUrl).toBe("https://kimi.example.test/coding/");
} finally {
envSnapshot.restore();
}
});
});

View File

@@ -666,7 +666,16 @@ const SIMPLE_IMPLICIT_PROVIDER_LOADERS: ImplicitProviderLoader[] = [
apiKey,
};
}),
withApiKey("kimi-coding", async ({ apiKey }) => ({ ...buildKimiCodingProvider(), apiKey })),
withApiKey("kimi-coding", async ({ apiKey, explicitProvider }) => {
const explicitBaseUrl = explicitProvider?.baseUrl;
return {
...buildKimiCodingProvider(),
...(typeof explicitBaseUrl === "string" && explicitBaseUrl.trim()
? { baseUrl: explicitBaseUrl.trim() }
: {}),
apiKey,
};
}),
withApiKey("synthetic", async ({ apiKey }) => ({ ...buildSyntheticProvider(), apiKey })),
withApiKey("venice", async ({ apiKey }) => ({ ...(await buildVeniceProvider()), apiKey })),
withApiKey("xiaomi", async ({ apiKey }) => ({ ...buildXiaomiProvider(), apiKey })),