diff --git a/docs/plugins/plugin-inventory.md b/docs/plugins/plugin-inventory.md index c2bb6c7a166d..78a4ed4fcbb5 100644 --- a/docs/plugins/plugin-inventory.md +++ b/docs/plugins/plugin-inventory.md @@ -51,7 +51,7 @@ Each entry lists the package, distribution route, and description. ## Core npm package -62 plugins +61 plugins - **[admin-http-rpc](/plugins/reference/admin-http-rpc)** (`@openclaw/admin-http-rpc`) - included in OpenClaw. OpenClaw admin HTTP RPC endpoint. @@ -175,11 +175,9 @@ Each entry lists the package, distribution route, and description. - **[xai](/plugins/reference/xai)** (`@openclaw/xai-plugin`) - included in OpenClaw. Adds xAI model provider support to OpenClaw. -- **[xiaomi](/plugins/reference/xiaomi)** (`@openclaw/xiaomi-provider`) - included in OpenClaw. Adds Xiaomi, Xiaomi Token Plan model provider support to OpenClaw. - ## Official external packages -83 plugins +84 plugins - **[acpx](/plugins/reference/acpx)** (`@openclaw/acpx`) - npm; ClawHub. OpenClaw ACP runtime backend with plugin-owned session and transport management. @@ -339,6 +337,8 @@ Each entry lists the package, distribution route, and description. - **[whatsapp](/plugins/reference/whatsapp)** (`@openclaw/whatsapp`) - ClawHub: `clawhub:@openclaw/whatsapp`; npm. OpenClaw WhatsApp channel plugin for WhatsApp Web chats. +- **[xiaomi](/plugins/reference/xiaomi)** (`@openclaw/xiaomi-provider`) - npm; ClawHub: `clawhub:@openclaw/xiaomi-provider`. Adds Xiaomi, Xiaomi Token Plan model provider support to OpenClaw. + - **[zai](/plugins/reference/zai)** (`@openclaw/zai-provider`) - npm; ClawHub: `clawhub:@openclaw/zai-provider`. Adds Z.AI model provider support to OpenClaw. - **[zalo](/plugins/reference/zalo)** (`@openclaw/zalo`) - npm; ClawHub. OpenClaw Zalo channel plugin for bot and webhook chats. diff --git a/docs/plugins/reference/xiaomi.md b/docs/plugins/reference/xiaomi.md index 97fd54230ef1..692193b42924 100644 --- a/docs/plugins/reference/xiaomi.md +++ b/docs/plugins/reference/xiaomi.md @@ -12,7 +12,7 @@ Adds Xiaomi, Xiaomi Token Plan model provider support to OpenClaw. ## Distribution - Package: `@openclaw/xiaomi-provider` -- Install route: included in OpenClaw +- Install route: npm; ClawHub: `clawhub:@openclaw/xiaomi-provider` ## Surface diff --git a/docs/providers/xiaomi.md b/docs/providers/xiaomi.md index 99644bf68def..76aefc368274 100644 --- a/docs/providers/xiaomi.md +++ b/docs/providers/xiaomi.md @@ -6,9 +6,8 @@ read_when: title: "Xiaomi MiMo" --- -Xiaomi MiMo is the API platform for **MiMo** models. The bundled `xiaomi` -plugin (`enabledByDefault: true`, no install step) registers two text -providers plus a speech (TTS) provider: +Xiaomi MiMo is the API platform for **MiMo** models. The official external +`xiaomi` plugin registers two text providers plus a speech (TTS) provider: - `xiaomi` - pay-as-you-go keys (`sk-...`) - `xiaomi-token-plan` - Token Plan keys (`tp-...`) with regional endpoint presets @@ -28,6 +27,13 @@ providers plus a speech (TTS) provider: ## Getting started + + ```bash + openclaw plugins install @openclaw/xiaomi-provider + openclaw gateway restart + ``` + + Create a pay-as-you-go key in the [Xiaomi MiMo console](https://platform.xiaomimimo.com/#/console/api-keys), or open your Token Plan subscription page and copy the regional OpenAI-compatible base URL plus the matching `tp-...` key. @@ -88,7 +94,7 @@ Choose the Token Plan auth choice that matches the regional base URL shown in Xi | `xiaomi-token-plan/mimo-v2.5` | text, image | 1,048,576 | 131,072 | Yes | Multimodal | `xiaomi-token-plan` needs a regional base URL to resolve. The supported path -is a bundled Token Plan onboarding choice or an explicit +is a Token Plan onboarding choice or an explicit `models.providers.xiaomi-token-plan` config block with `baseUrl` set; the provider is not offered without one of those. @@ -100,7 +106,7 @@ OpenClaw's [`/think` directive](/tools/thinking) with levels `off`, ## Text-to-speech -The bundled `xiaomi` plugin also registers Xiaomi MiMo as a speech provider +The `xiaomi` plugin also registers Xiaomi MiMo as a speech provider for `tts`. It calls Xiaomi's chat-completions TTS contract with the text as an `assistant` message and optional style guidance as a `user` message. @@ -197,7 +203,8 @@ mono Opus with `ffmpeg` before delivery. } ``` -Pricing and compat flags come from the bundled plugin manifest, so the config example omits `cost` and `compat` to avoid diverging from runtime behavior. +Pricing and compat flags come from the plugin manifest, so the config example +omits `cost` and `compat` to avoid diverging from runtime behavior. Token Plan: @@ -236,11 +243,13 @@ Token Plan: } ``` -Token Plan charges against a fixed subscription's Credits rather than per-token USD pricing, so its bundled catalog rows use zero USD cost and the config example omits `cost`. +Token Plan charges against a fixed subscription's Credits rather than per-token +USD pricing, so its catalog rows use zero USD cost and the config example omits +`cost`. - The `xiaomi` provider is auto-enabled when `XIAOMI_API_KEY` is set in your environment or an auth profile exists. `xiaomi-token-plan` needs a regional base URL, so the supported path is the bundled Token Plan onboarding choice or an explicit `models.providers.xiaomi-token-plan` config block. + The `xiaomi` provider is auto-enabled when `XIAOMI_API_KEY` is set in your environment or an auth profile exists. `xiaomi-token-plan` needs a regional base URL, so the supported path is the Token Plan onboarding choice or an explicit `models.providers.xiaomi-token-plan` config block. diff --git a/extensions/xiaomi/README.md b/extensions/xiaomi/README.md new file mode 100644 index 000000000000..d49dae3999f3 --- /dev/null +++ b/extensions/xiaomi/README.md @@ -0,0 +1,16 @@ +# OpenClaw Xiaomi Provider + +Official OpenClaw provider plugin for Xiaomi MiMo pay-as-you-go and Token Plan +models, usage tracking, and text-to-speech. + +Install from OpenClaw: + +```bash +openclaw plugins install @openclaw/xiaomi-provider +openclaw gateway restart +``` + +Configure `XIAOMI_API_KEY` for `xiaomi/*` models and speech, or +`XIAOMI_TOKEN_PLAN_API_KEY` for `xiaomi-token-plan/*` models. See +https://docs.openclaw.ai/providers/xiaomi for regional Token Plan setup and +the full model and speech configuration. diff --git a/extensions/xiaomi/index.ts b/extensions/xiaomi/index.ts index 376bf9a6b5a2..6b222d7fc384 100644 --- a/extensions/xiaomi/index.ts +++ b/extensions/xiaomi/index.ts @@ -364,7 +364,7 @@ function createTokenPlanAuthMethod(region: XiaomiTokenPlanRegion): ProviderAuthM export default definePluginEntry({ id: XIAOMI_PROVIDER_ID, name: "Xiaomi Provider", - description: "Bundled Xiaomi provider plugin", + description: "Xiaomi provider plugin", register(api) { api.registerProvider({ id: XIAOMI_PROVIDER_ID, diff --git a/extensions/xiaomi/package.json b/extensions/xiaomi/package.json index b2d2b8fd7f69..9ae9039ad446 100644 --- a/extensions/xiaomi/package.json +++ b/extensions/xiaomi/package.json @@ -1,8 +1,11 @@ { "name": "@openclaw/xiaomi-provider", "version": "2026.7.2", - "private": true, - "description": "OpenClaw Xiaomi provider plugin", + "description": "OpenClaw Xiaomi provider plugin.", + "repository": { + "type": "git", + "url": "https://github.com/openclaw/openclaw" + }, "type": "module", "devDependencies": { "@openclaw/plugin-sdk": "workspace:*" @@ -10,6 +13,23 @@ "openclaw": { "extensions": [ "./index.ts" - ] + ], + "install": { + "clawhubSpec": "clawhub:@openclaw/xiaomi-provider", + "npmSpec": "@openclaw/xiaomi-provider", + "defaultChoice": "npm", + "minHostVersion": ">=2026.7.2" + }, + "compat": { + "pluginApi": ">=2026.7.2" + }, + "build": { + "openclawVersion": "2026.7.2", + "bundledDist": false + }, + "release": { + "publishToClawHub": true, + "publishToNpm": true + } } } diff --git a/package.json b/package.json index 6977b4672f7b..2b2d816841c5 100644 --- a/package.json +++ b/package.json @@ -320,6 +320,7 @@ "!dist/extensions/voyage/**", "!dist/extensions/vydra/**", "!dist/extensions/whatsapp/**", + "!dist/extensions/xiaomi/**", "!dist/extensions/zai/**", "!dist/extensions/zalo/**", "!dist/extensions/zalouser/**", diff --git a/scripts/lib/official-external-provider-catalog.json b/scripts/lib/official-external-provider-catalog.json index 44b6d098c740..fb152f3178dd 100644 --- a/scripts/lib/official-external-provider-catalog.json +++ b/scripts/lib/official-external-provider-catalog.json @@ -1588,6 +1588,138 @@ } } }, + { + "name": "@openclaw/xiaomi-provider", + "description": "OpenClaw Xiaomi provider plugin.", + "source": "official", + "kind": "provider", + "openclaw": { + "plugin": { + "id": "xiaomi", + "label": "Xiaomi" + }, + "providerEndpoints": [ + { + "endpointClass": "xiaomi-native", + "hosts": [ + "api.xiaomimimo.com", + "token-plan-ams.xiaomimimo.com", + "token-plan-cn.xiaomimimo.com", + "token-plan-sgp.xiaomimimo.com" + ] + } + ], + "providers": [ + { + "id": "xiaomi", + "name": "Xiaomi", + "docs": "/providers/xiaomi", + "categories": [ + "cloud", + "llm" + ], + "envVars": [ + "XIAOMI_API_KEY" + ], + "authChoices": [ + { + "method": "api-key", + "choiceId": "xiaomi-api-key", + "choiceLabel": "Xiaomi API key (Pay-as-you-go)", + "choiceHint": "Endpoint: api.xiaomimimo.com/v1", + "groupId": "xiaomi", + "groupLabel": "Xiaomi", + "groupHint": "Pay-as-you-go / Token Plan", + "optionKey": "xiaomiApiKey", + "cliFlag": "--xiaomi-api-key", + "cliOption": "--xiaomi-api-key ", + "cliDescription": "Xiaomi MiMo pay-as-you-go API key", + "onboardingScopes": [ + "text-inference" + ] + } + ] + }, + { + "id": "xiaomi-token-plan", + "name": "Xiaomi Token Plan", + "docs": "/providers/xiaomi", + "categories": [ + "cloud", + "llm" + ], + "envVars": [ + "XIAOMI_TOKEN_PLAN_API_KEY" + ], + "authChoices": [ + { + "method": "token-plan-ams", + "choiceId": "xiaomi-token-plan-ams", + "choiceLabel": "Xiaomi Token Plan (Europe)", + "choiceHint": "Endpoint preset: token-plan-ams.xiaomimimo.com/v1", + "groupId": "xiaomi", + "groupLabel": "Xiaomi", + "groupHint": "Pay-as-you-go / Token Plan", + "optionKey": "xiaomiTokenPlanApiKey", + "cliFlag": "--xiaomi-token-plan-api-key", + "cliOption": "--xiaomi-token-plan-api-key ", + "cliDescription": "Xiaomi MiMo Token Plan API key", + "onboardingScopes": [ + "text-inference" + ] + }, + { + "method": "token-plan-cn", + "choiceId": "xiaomi-token-plan-cn", + "choiceLabel": "Xiaomi Token Plan (China)", + "choiceHint": "Endpoint preset: token-plan-cn.xiaomimimo.com/v1", + "groupId": "xiaomi", + "groupLabel": "Xiaomi", + "groupHint": "Pay-as-you-go / Token Plan", + "optionKey": "xiaomiTokenPlanApiKey", + "cliFlag": "--xiaomi-token-plan-api-key", + "cliOption": "--xiaomi-token-plan-api-key ", + "cliDescription": "Xiaomi MiMo Token Plan API key", + "onboardingScopes": [ + "text-inference" + ] + }, + { + "method": "token-plan-sgp", + "choiceId": "xiaomi-token-plan-sgp", + "choiceLabel": "Xiaomi Token Plan (Singapore)", + "choiceHint": "Endpoint preset: token-plan-sgp.xiaomimimo.com/v1", + "groupId": "xiaomi", + "groupLabel": "Xiaomi", + "groupHint": "Pay-as-you-go / Token Plan", + "optionKey": "xiaomiTokenPlanApiKey", + "cliFlag": "--xiaomi-token-plan-api-key", + "cliOption": "--xiaomi-token-plan-api-key ", + "cliDescription": "Xiaomi MiMo Token Plan API key", + "onboardingScopes": [ + "text-inference" + ] + } + ] + } + ], + "contracts": { + "speechProviders": [ + "xiaomi" + ], + "usageProviders": [ + "xiaomi", + "xiaomi-token-plan" + ] + }, + "install": { + "clawhubSpec": "clawhub:@openclaw/xiaomi-provider", + "npmSpec": "@openclaw/xiaomi-provider", + "defaultChoice": "npm", + "minHostVersion": ">=2026.7.2" + } + } + }, { "name": "@openclaw/zai-provider", "description": "OpenClaw Z.AI provider plugin", diff --git a/src/cli/plugins-location-bridges.test.ts b/src/cli/plugins-location-bridges.test.ts index aeba06cc563d..4ab519844c4c 100644 --- a/src/cli/plugins-location-bridges.test.ts +++ b/src/cli/plugins-location-bridges.test.ts @@ -171,6 +171,7 @@ describe("listPersistedBundledPluginLocationBridges", () => { ["volcengine", "@openclaw/volcengine-provider", true], ["voyage", "@openclaw/voyage-provider", true], ["vydra", "@openclaw/vydra-provider", true], + ["xiaomi", "@openclaw/xiaomi-provider", true], ["zoom-meetings", "@openclaw/zoom-meetings", true], ] as const)( "externalizes the shipped bundled %s plugin using official install metadata", diff --git a/src/plugin-sdk/xiaomi.ts b/src/plugin-sdk/xiaomi.ts index 1836410cb4c8..d9a3bb6c1809 100644 --- a/src/plugin-sdk/xiaomi.ts +++ b/src/plugin-sdk/xiaomi.ts @@ -1,6 +1,6 @@ // Manual facade. Keep loader boundary explicit. import type { ModelProviderConfig, OpenClawConfig } from "../config/types.js"; -import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js"; type FacadeModule = { applyXiaomiConfig: (cfg: OpenClawConfig) => OpenClawConfig; @@ -27,7 +27,7 @@ export const applyXiaomiProviderConfig: FacadeModule["applyXiaomiProviderConfig" /** Build the Xiaomi model provider entry used by setup/config helpers. */ export const buildXiaomiProvider: FacadeModule["buildXiaomiProvider"] = ((...args) => loadFacadeModule()["buildXiaomiProvider"](...args)) as FacadeModule["buildXiaomiProvider"]; -/** Default Xiaomi model id advertised by the bundled provider facade. */ +/** Default Xiaomi model id advertised by the provider facade. */ export const XIAOMI_DEFAULT_MODEL_ID: FacadeModule["XIAOMI_DEFAULT_MODEL_ID"] = loadFacadeModule()["XIAOMI_DEFAULT_MODEL_ID"]; /** Default Xiaomi provider/model reference written by setup flows. */ diff --git a/src/plugins/contracts/package-manifest.contract.test.ts b/src/plugins/contracts/package-manifest.contract.test.ts index ffdd20f58345..b3d721bfdbe8 100644 --- a/src/plugins/contracts/package-manifest.contract.test.ts +++ b/src/plugins/contracts/package-manifest.contract.test.ts @@ -79,6 +79,7 @@ const packageManifestContractTests: PackageManifestContractParams[] = [ pluginLocalRuntimeDeps: ["audio-decode", "baileys"], minHostVersionBaseline: "2026.3.22", }, + { pluginId: "xiaomi", minHostVersionBaseline: "2026.7.2" }, { pluginId: "zalo", minHostVersionBaseline: "2026.3.22" }, { pluginId: "zalouser", minHostVersionBaseline: "2026.3.22" }, ]; diff --git a/src/plugins/contracts/plugin-sdk-subpaths.test.ts b/src/plugins/contracts/plugin-sdk-subpaths.test.ts index 55b7a838ea8c..a6b0f7037fec 100644 --- a/src/plugins/contracts/plugin-sdk-subpaths.test.ts +++ b/src/plugins/contracts/plugin-sdk-subpaths.test.ts @@ -1240,6 +1240,8 @@ describe("plugin-sdk subpath exports", () => { expectSourceOmitsSnippet("google-model-id", "./google.js"); expectSourceOmitsSnippet("google-model-id", "./facade-runtime.js"); expectSourceOmitsSnippet("google-model-id", "../../extensions/"); + expectSourceMentions("xiaomi", ["./facade-runtime.js"]); + expectSourceOmitsSnippet("xiaomi", "./facade-loader.js"); expectRepoSourceOmitsSnippet("extensions/xai/model-id.ts", "./xai.js"); expectRepoSourceOmitsSnippet("extensions/xai/model-id.ts", "./facade-runtime.js"); expectRepoSourceOmitsSnippet("extensions/xai/model-id.ts", "../../extensions/"); diff --git a/src/plugins/official-external-plugin-catalog.test.ts b/src/plugins/official-external-plugin-catalog.test.ts index 8e9db871abb9..934234499d75 100644 --- a/src/plugins/official-external-plugin-catalog.test.ts +++ b/src/plugins/official-external-plugin-catalog.test.ts @@ -2065,6 +2065,47 @@ describe("official external plugin catalog", () => { expect(manifest?.contracts?.speechProviders).toEqual(["volcengine"]); }); + it("lists Xiaomi's model, speech, and usage surfaces as one official external provider", () => { + const xiaomi = expectCatalogEntry("xiaomi"); + const manifest = getOfficialExternalPluginCatalogManifest(xiaomi); + + expect(resolveOfficialExternalPluginId(xiaomi)).toBe("xiaomi"); + expect(getOfficialExternalPluginCatalogEntry("xiaomi-token-plan")).toBe(xiaomi); + expect(resolveOfficialExternalPluginInstall(xiaomi)).toEqual({ + clawhubSpec: "clawhub:@openclaw/xiaomi-provider", + npmSpec: "@openclaw/xiaomi-provider", + defaultChoice: "npm", + minHostVersion: ">=2026.7.2", + }); + expect(manifest?.providers?.map((provider) => provider.id)).toEqual([ + "xiaomi", + "xiaomi-token-plan", + ]); + expect(manifest?.providers?.[0]?.authChoices?.map((choice) => choice.choiceId)).toEqual([ + "xiaomi-api-key", + ]); + expect(manifest?.providers?.[1]?.authChoices?.map((choice) => choice.choiceId)).toEqual([ + "xiaomi-token-plan-ams", + "xiaomi-token-plan-cn", + "xiaomi-token-plan-sgp", + ]); + expect(manifest?.contracts).toMatchObject({ + speechProviders: ["xiaomi"], + usageProviders: ["xiaomi", "xiaomi-token-plan"], + }); + expect(manifest?.providerEndpoints).toEqual([ + { + endpointClass: "xiaomi-native", + hosts: [ + "api.xiaomimimo.com", + "token-plan-ams.xiaomimimo.com", + "token-plan-cn.xiaomimimo.com", + "token-plan-sgp.xiaomimimo.com", + ], + }, + ]); + }); + it.each([ ["teams-meetings", "@openclaw/teams-meetings", "teams_meetings", "teams"], ["zoom-meetings", "@openclaw/zoom-meetings", "zoom_meetings", "zoom"], @@ -2117,9 +2158,9 @@ describe("official external plugin catalog", () => { expect( resolveOfficialExternalProviderContractPluginIds({ contract: "speechProviders", - providerIds: new Set(["gradium", "inworld"]), + providerIds: new Set(["gradium", "inworld", "xiaomi"]), }), - ).toEqual(["gradium", "inworld"]); + ).toEqual(["gradium", "inworld", "xiaomi"]); expect( resolveOfficialExternalProviderContractPluginIds({ contract: "webFetchProviders", @@ -2188,6 +2229,8 @@ describe("official external plugin catalog", () => { VENICE_API_KEY: "venice-key", AI_GATEWAY_API_KEY: "gateway-key", VOYAGE_API_KEY: "voyage-key", + XIAOMI_API_KEY: "xiaomi-key", + XIAOMI_TOKEN_PLAN_API_KEY: "xiaomi-token-plan-key", ZAI_API_KEY: "zai-key", }), ).toEqual([ @@ -2211,6 +2254,7 @@ describe("official external plugin catalog", () => { "venice", "vercel-ai-gateway", "voyage", + "xiaomi", "zai", ]); expect(resolveOfficialExternalProviderPluginIdsForEnv({ GROQ_API_KEY: " " })).toEqual([]); diff --git a/src/plugins/official-external-provider-endpoints.test.ts b/src/plugins/official-external-provider-endpoints.test.ts index 1c3e4148cd5b..802ecdcc07f2 100644 --- a/src/plugins/official-external-provider-endpoints.test.ts +++ b/src/plugins/official-external-provider-endpoints.test.ts @@ -133,6 +133,7 @@ describe("official external provider endpoint catalog mirror", () => { expect(endpointClasses).toContain("modelstudio-native"); expect(endpointClasses).toContain("moonshot-native"); expect(endpointClasses).toContain("meta-native"); + expect(endpointClasses).toContain("xiaomi-native"); expect(endpointClasses).toContain("zai-native"); }); }); diff --git a/test/scripts/bundled-plugin-build-entries.test.ts b/test/scripts/bundled-plugin-build-entries.test.ts index fb4f9fb1619d..09e32a62f017 100644 --- a/test/scripts/bundled-plugin-build-entries.test.ts +++ b/test/scripts/bundled-plugin-build-entries.test.ts @@ -339,10 +339,10 @@ describe("bundled plugin build entries", () => { } }); - it("excludes externalized Cohere and Meta providers from bundled artifacts", () => { + it("excludes externalized Cohere, Meta, and Xiaomi providers from bundled artifacts", () => { const artifacts = listBundledPluginPackArtifacts(); - for (const pluginId of ["cohere", "meta"]) { + for (const pluginId of ["cohere", "meta", "xiaomi"]) { expect(artifacts).not.toContain(`dist/extensions/${pluginId}/index.js`); expect(artifacts).not.toContain(`dist/extensions/${pluginId}/openclaw.plugin.json`); expect(artifacts).not.toContain(`dist/extensions/${pluginId}/package.json`);