feat: add Xiaomi MiMo provider onboarding (#3454)
Thanks @WqyJh. Co-authored-by: Qiying Wang <15232241+WqyJh@users.noreply.github.com>
This commit is contained in:
parent
50d44d0bd9
commit
78b9876641
@ -15,6 +15,7 @@ Status: beta.
|
|||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
- Providers: add Venice AI integration; update Moonshot Kimi references to kimi-k2.5; update MiniMax API endpoint/format. (#2762, #3064)
|
- Providers: add Venice AI integration; update Moonshot Kimi references to kimi-k2.5; update MiniMax API endpoint/format. (#2762, #3064)
|
||||||
|
- Providers: add Xiaomi MiMo (mimo-v2-flash) support and onboarding flow. (#3454) Thanks @WqyJh.
|
||||||
- Telegram: quote replies, edit-message action, silent sends, sticker support + vision caching, linkPreview toggle, plugin sendPayload support. (#2900, #2394, #2382, #2548, #1700, #1917)
|
- Telegram: quote replies, edit-message action, silent sends, sticker support + vision caching, linkPreview toggle, plugin sendPayload support. (#2900, #2394, #2382, #2548, #1700, #1917)
|
||||||
- Discord: configurable privileged gateway intents for presences/members. (#2266) Thanks @kentaro.
|
- Discord: configurable privileged gateway intents for presences/members. (#2266) Thanks @kentaro.
|
||||||
- Browser: route browser control via gateway/node; fallback URL matching for relay targets. (#1999)
|
- Browser: route browser control via gateway/node; fallback URL matching for relay targets. (#1999)
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const MINIMAX_API_COST = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const XIAOMI_BASE_URL = "https://api.xiaomimimo.com/anthropic";
|
const XIAOMI_BASE_URL = "https://api.xiaomimimo.com/anthropic";
|
||||||
const XIAOMI_DEFAULT_MODEL_ID = "mimo-v2-flash";
|
export const XIAOMI_DEFAULT_MODEL_ID = "mimo-v2-flash";
|
||||||
const XIAOMI_DEFAULT_CONTEXT_WINDOW = 262144;
|
const XIAOMI_DEFAULT_CONTEXT_WINDOW = 262144;
|
||||||
const XIAOMI_DEFAULT_MAX_TOKENS = 8192;
|
const XIAOMI_DEFAULT_MAX_TOKENS = 8192;
|
||||||
const XIAOMI_DEFAULT_COST = {
|
const XIAOMI_DEFAULT_COST = {
|
||||||
|
|||||||
@ -53,6 +53,7 @@ describe("models-config", () => {
|
|||||||
const previousMoonshot = process.env.MOONSHOT_API_KEY;
|
const previousMoonshot = process.env.MOONSHOT_API_KEY;
|
||||||
const previousSynthetic = process.env.SYNTHETIC_API_KEY;
|
const previousSynthetic = process.env.SYNTHETIC_API_KEY;
|
||||||
const previousVenice = process.env.VENICE_API_KEY;
|
const previousVenice = process.env.VENICE_API_KEY;
|
||||||
|
const previousXiaomi = process.env.XIAOMI_API_KEY;
|
||||||
delete process.env.COPILOT_GITHUB_TOKEN;
|
delete process.env.COPILOT_GITHUB_TOKEN;
|
||||||
delete process.env.GH_TOKEN;
|
delete process.env.GH_TOKEN;
|
||||||
delete process.env.GITHUB_TOKEN;
|
delete process.env.GITHUB_TOKEN;
|
||||||
@ -61,6 +62,7 @@ describe("models-config", () => {
|
|||||||
delete process.env.MOONSHOT_API_KEY;
|
delete process.env.MOONSHOT_API_KEY;
|
||||||
delete process.env.SYNTHETIC_API_KEY;
|
delete process.env.SYNTHETIC_API_KEY;
|
||||||
delete process.env.VENICE_API_KEY;
|
delete process.env.VENICE_API_KEY;
|
||||||
|
delete process.env.XIAOMI_API_KEY;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
@ -93,6 +95,8 @@ describe("models-config", () => {
|
|||||||
else process.env.SYNTHETIC_API_KEY = previousSynthetic;
|
else process.env.SYNTHETIC_API_KEY = previousSynthetic;
|
||||||
if (previousVenice === undefined) delete process.env.VENICE_API_KEY;
|
if (previousVenice === undefined) delete process.env.VENICE_API_KEY;
|
||||||
else process.env.VENICE_API_KEY = previousVenice;
|
else process.env.VENICE_API_KEY = previousVenice;
|
||||||
|
if (previousXiaomi === undefined) delete process.env.XIAOMI_API_KEY;
|
||||||
|
else process.env.XIAOMI_API_KEY = previousXiaomi;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { buildXiaomiProvider } from "../agents/models-config.providers.js";
|
import { buildXiaomiProvider, XIAOMI_DEFAULT_MODEL_ID } from "../agents/models-config.providers.js";
|
||||||
import {
|
import {
|
||||||
buildSyntheticModelDefinition,
|
buildSyntheticModelDefinition,
|
||||||
SYNTHETIC_BASE_URL,
|
SYNTHETIC_BASE_URL,
|
||||||
@ -349,7 +349,14 @@ export function applyXiaomiProviderConfig(cfg: MoltbotConfig): MoltbotConfig {
|
|||||||
const existingProvider = providers.xiaomi;
|
const existingProvider = providers.xiaomi;
|
||||||
const defaultProvider = buildXiaomiProvider();
|
const defaultProvider = buildXiaomiProvider();
|
||||||
const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : [];
|
const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : [];
|
||||||
const mergedModels = existingModels.length > 0 ? existingModels : (defaultProvider.models ?? []);
|
const defaultModels = defaultProvider.models ?? [];
|
||||||
|
const hasDefaultModel = existingModels.some((model) => model.id === XIAOMI_DEFAULT_MODEL_ID);
|
||||||
|
const mergedModels =
|
||||||
|
existingModels.length > 0
|
||||||
|
? hasDefaultModel
|
||||||
|
? existingModels
|
||||||
|
: [...existingModels, ...defaultModels]
|
||||||
|
: defaultModels;
|
||||||
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record<
|
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record<
|
||||||
string,
|
string,
|
||||||
unknown
|
unknown
|
||||||
|
|||||||
@ -15,6 +15,8 @@ import {
|
|||||||
applyOpenrouterProviderConfig,
|
applyOpenrouterProviderConfig,
|
||||||
applySyntheticConfig,
|
applySyntheticConfig,
|
||||||
applySyntheticProviderConfig,
|
applySyntheticProviderConfig,
|
||||||
|
applyXiaomiConfig,
|
||||||
|
applyXiaomiProviderConfig,
|
||||||
OPENROUTER_DEFAULT_MODEL_REF,
|
OPENROUTER_DEFAULT_MODEL_REF,
|
||||||
SYNTHETIC_DEFAULT_MODEL_ID,
|
SYNTHETIC_DEFAULT_MODEL_ID,
|
||||||
SYNTHETIC_DEFAULT_MODEL_REF,
|
SYNTHETIC_DEFAULT_MODEL_REF,
|
||||||
@ -343,6 +345,50 @@ describe("applySyntheticConfig", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("applyXiaomiConfig", () => {
|
||||||
|
it("adds Xiaomi provider with correct settings", () => {
|
||||||
|
const cfg = applyXiaomiConfig({});
|
||||||
|
expect(cfg.models?.providers?.xiaomi).toMatchObject({
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/anthropic",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
});
|
||||||
|
expect(cfg.agents?.defaults?.model?.primary).toBe("xiaomi/mimo-v2-flash");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("merges Xiaomi models and keeps existing provider overrides", () => {
|
||||||
|
const cfg = applyXiaomiProviderConfig({
|
||||||
|
models: {
|
||||||
|
providers: {
|
||||||
|
xiaomi: {
|
||||||
|
baseUrl: "https://old.example.com",
|
||||||
|
apiKey: "old-key",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "custom-model",
|
||||||
|
name: "Custom",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 1000,
|
||||||
|
maxTokens: 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(cfg.models?.providers?.xiaomi?.baseUrl).toBe("https://api.xiaomimimo.com/anthropic");
|
||||||
|
expect(cfg.models?.providers?.xiaomi?.api).toBe("anthropic-messages");
|
||||||
|
expect(cfg.models?.providers?.xiaomi?.apiKey).toBe("old-key");
|
||||||
|
expect(cfg.models?.providers?.xiaomi?.models.map((m) => m.id)).toEqual([
|
||||||
|
"custom-model",
|
||||||
|
"mimo-v2-flash",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("applyOpencodeZenProviderConfig", () => {
|
describe("applyOpencodeZenProviderConfig", () => {
|
||||||
it("adds allowlist entry for the default model", () => {
|
it("adds allowlist entry for the default model", () => {
|
||||||
const cfg = applyOpencodeZenProviderConfig({});
|
const cfg = applyOpencodeZenProviderConfig({});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user