mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
fix(models): add kimi-coding implicit provider template (openclaw#22526) thanks @lailoo
Verified: - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -47,6 +47,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Security/Browser: block non-network browser navigation protocols (including `file:`, `data:`, and `javascript:`) while preserving `about:blank`, preventing local file reads via browser tool navigation. This ships in the next npm release. Thanks @q1uf3ng for reporting.
|
||||
- Security/Exec: block shell startup-file env injection (`BASH_ENV`, `ENV`, `BASH_FUNC_*`, `LD_*`, `DYLD_*`) across config env ingestion, node-host inherited environment sanitization, and macOS exec host runtime to prevent pre-command execution from attacker-controlled environment variables. This ships in the next npm release. Thanks @tdjackey.
|
||||
- Security/Exec (Windows): canonicalize `cmd.exe /c` command text across validation, approval binding, and audit/event rendering to prevent trailing-argument approval mismatches in `system.run`. This ships in the next npm release. Thanks @tdjackey for reporting.
|
||||
- Models/Kimi-Coding: add missing implicit provider template for `kimi-coding` with correct `anthropic-messages` API type and base URL, fixing 403 errors when using Kimi for Coding. (#22409)
|
||||
- Security/Gateway/Hooks: block `__proto__`, `constructor`, and `prototype` traversal in webhook template path resolution to prevent prototype-chain payload data leakage in `messageTemplate` rendering. (#22213) Thanks @SleuthCo.
|
||||
- Security/OpenClawKit/UI: prevent injected inbound user context metadata blocks from leaking into chat history in TUI, webchat, and macOS surfaces by stripping all untrusted metadata prefixes at display boundaries. (#22142) Thanks @Mellowambience, @vincentkoc.
|
||||
- Security/OpenClawKit/UI: strip inbound metadata blocks from user messages in TUI rendering while preserving user-authored content. (#22345) Thanks @kansodata, @vincentkoc.
|
||||
|
||||
45
src/agents/models-config.providers.kimi-coding.test.ts
Normal file
45
src/agents/models-config.providers.kimi-coding.test.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { mkdtempSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { captureEnv } from "../test-utils/env.js";
|
||||
import { buildKimiCodingProvider, resolveImplicitProviders } from "./models-config.providers.js";
|
||||
|
||||
describe("kimi-coding implicit provider (#22409)", () => {
|
||||
it("should include kimi-coding when KIMI_API_KEY is configured", 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 resolveImplicitProviders({ agentDir });
|
||||
expect(providers?.["kimi-coding"]).toBeDefined();
|
||||
expect(providers?.["kimi-coding"]?.api).toBe("anthropic-messages");
|
||||
expect(providers?.["kimi-coding"]?.baseUrl).toBe("https://api.kimi.com/coding/");
|
||||
} finally {
|
||||
envSnapshot.restore();
|
||||
}
|
||||
});
|
||||
|
||||
it("should build kimi-coding provider with anthropic-messages API", () => {
|
||||
const provider = buildKimiCodingProvider();
|
||||
expect(provider.api).toBe("anthropic-messages");
|
||||
expect(provider.baseUrl).toBe("https://api.kimi.com/coding/");
|
||||
expect(provider.models).toBeDefined();
|
||||
expect(provider.models.length).toBeGreaterThan(0);
|
||||
expect(provider.models[0].id).toBe("k2p5");
|
||||
});
|
||||
|
||||
it("should not include kimi-coding when no API key is configured", async () => {
|
||||
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
|
||||
const envSnapshot = captureEnv(["KIMI_API_KEY"]);
|
||||
delete process.env.KIMI_API_KEY;
|
||||
|
||||
try {
|
||||
const providers = await resolveImplicitProviders({ agentDir });
|
||||
expect(providers?.["kimi-coding"]).toBeUndefined();
|
||||
} finally {
|
||||
envSnapshot.restore();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -96,6 +96,17 @@ const MOONSHOT_DEFAULT_COST = {
|
||||
cacheWrite: 0,
|
||||
};
|
||||
|
||||
const KIMI_CODING_BASE_URL = "https://api.kimi.com/coding/";
|
||||
const KIMI_CODING_DEFAULT_MODEL_ID = "k2p5";
|
||||
const KIMI_CODING_DEFAULT_CONTEXT_WINDOW = 262144;
|
||||
const KIMI_CODING_DEFAULT_MAX_TOKENS = 32768;
|
||||
const KIMI_CODING_DEFAULT_COST = {
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
};
|
||||
|
||||
const QWEN_PORTAL_BASE_URL = "https://portal.qwen.ai/v1";
|
||||
const QWEN_PORTAL_OAUTH_PLACEHOLDER = "qwen-oauth";
|
||||
const QWEN_PORTAL_DEFAULT_CONTEXT_WINDOW = 128000;
|
||||
@@ -483,6 +494,24 @@ function buildMoonshotProvider(): ProviderConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export function buildKimiCodingProvider(): ProviderConfig {
|
||||
return {
|
||||
baseUrl: KIMI_CODING_BASE_URL,
|
||||
api: "anthropic-messages",
|
||||
models: [
|
||||
{
|
||||
id: KIMI_CODING_DEFAULT_MODEL_ID,
|
||||
name: "Kimi for Coding",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: KIMI_CODING_DEFAULT_COST,
|
||||
contextWindow: KIMI_CODING_DEFAULT_CONTEXT_WINDOW,
|
||||
maxTokens: KIMI_CODING_DEFAULT_MAX_TOKENS,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function buildQwenPortalProvider(): ProviderConfig {
|
||||
return {
|
||||
baseUrl: QWEN_PORTAL_BASE_URL,
|
||||
@@ -687,6 +716,13 @@ export async function resolveImplicitProviders(params: {
|
||||
providers.moonshot = { ...buildMoonshotProvider(), apiKey: moonshotKey };
|
||||
}
|
||||
|
||||
const kimiCodingKey =
|
||||
resolveEnvApiKeyVarName("kimi-coding") ??
|
||||
resolveApiKeyFromProfiles({ provider: "kimi-coding", store: authStore });
|
||||
if (kimiCodingKey) {
|
||||
providers["kimi-coding"] = { ...buildKimiCodingProvider(), apiKey: kimiCodingKey };
|
||||
}
|
||||
|
||||
const syntheticKey =
|
||||
resolveEnvApiKeyVarName("synthetic") ??
|
||||
resolveApiKeyFromProfiles({ provider: "synthetic", store: authStore });
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
HUGGINGFACE_MODEL_CATALOG,
|
||||
} from "../agents/huggingface-models.js";
|
||||
import {
|
||||
buildKimiCodingProvider,
|
||||
buildQianfanProvider,
|
||||
buildXiaomiProvider,
|
||||
QIANFAN_DEFAULT_MODEL_ID,
|
||||
@@ -61,6 +62,7 @@ import {
|
||||
buildXaiModelDefinition,
|
||||
QIANFAN_BASE_URL,
|
||||
QIANFAN_DEFAULT_MODEL_REF,
|
||||
KIMI_CODING_MODEL_ID,
|
||||
KIMI_CODING_MODEL_REF,
|
||||
MOONSHOT_BASE_URL,
|
||||
MOONSHOT_CN_BASE_URL,
|
||||
@@ -206,19 +208,19 @@ export function applyKimiCodeProviderConfig(cfg: OpenClawConfig): OpenClawConfig
|
||||
const models = { ...cfg.agents?.defaults?.models };
|
||||
models[KIMI_CODING_MODEL_REF] = {
|
||||
...models[KIMI_CODING_MODEL_REF],
|
||||
alias: models[KIMI_CODING_MODEL_REF]?.alias ?? "Kimi K2.5",
|
||||
alias: models[KIMI_CODING_MODEL_REF]?.alias ?? "Kimi for Coding",
|
||||
};
|
||||
|
||||
return {
|
||||
...cfg,
|
||||
agents: {
|
||||
...cfg.agents,
|
||||
defaults: {
|
||||
...cfg.agents?.defaults,
|
||||
models,
|
||||
},
|
||||
},
|
||||
};
|
||||
const defaultModel = buildKimiCodingProvider().models[0];
|
||||
|
||||
return applyProviderConfigWithDefaultModel(cfg, {
|
||||
agentModels: models,
|
||||
providerId: "kimi-coding",
|
||||
api: "anthropic-messages",
|
||||
baseUrl: "https://api.kimi.com/coding/",
|
||||
defaultModel,
|
||||
defaultModelId: KIMI_CODING_MODEL_ID,
|
||||
});
|
||||
}
|
||||
|
||||
export function applyKimiCodeConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
|
||||
Reference in New Issue
Block a user