mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
feat: externalize GMI provider plugin (#94350)
* feat: externalize gmi provider plugin * fix(plugins): repair gmi alias installs --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -301,7 +301,6 @@ See [/providers/kilocode](/providers/kilocode) for setup details.
|
||||
| DeepInfra | `deepinfra` | `DEEPINFRA_API_KEY` | `deepinfra/deepseek-ai/DeepSeek-V4-Flash` |
|
||||
| DeepSeek | `deepseek` | `DEEPSEEK_API_KEY` | `deepseek/deepseek-v4-flash` |
|
||||
| GitHub Copilot | `github-copilot` | `COPILOT_GITHUB_TOKEN` / `GH_TOKEN` / `GITHUB_TOKEN` | - |
|
||||
| GMI Cloud | `gmi` | `GMI_API_KEY` | `gmi/google/gemini-3.1-flash-lite` |
|
||||
| Groq | `groq` | `GROQ_API_KEY` | - |
|
||||
| Hugging Face Inference | `huggingface` | `HUGGINGFACE_HUB_TOKEN` or `HF_TOKEN` | `huggingface/deepseek-ai/DeepSeek-R1` |
|
||||
| Kilo Gateway | `kilocode` | `KILOCODE_API_KEY` | `kilocode/kilo/auto` |
|
||||
|
||||
@@ -51,7 +51,7 @@ Each entry lists the package, distribution route, and description.
|
||||
|
||||
## Core npm package
|
||||
|
||||
91 plugins
|
||||
90 plugins
|
||||
|
||||
- **[admin-http-rpc](/plugins/reference/admin-http-rpc)** (`@openclaw/admin-http-rpc`) - included in OpenClaw. OpenClaw admin HTTP RPC endpoint.
|
||||
|
||||
@@ -111,8 +111,6 @@ Each entry lists the package, distribution route, and description.
|
||||
|
||||
- **[github-copilot](/plugins/reference/github-copilot)** (`@openclaw/github-copilot-provider`) - included in OpenClaw. Adds GitHub Copilot model provider support to OpenClaw.
|
||||
|
||||
- **[gmi](/plugins/reference/gmi)** (`@openclaw/gmi-provider`) - included in OpenClaw. Adds Gmi, Gmi Cloud, Gmicloud model provider support to OpenClaw.
|
||||
|
||||
- **[google](/plugins/reference/google)** (`@openclaw/google-plugin`) - included in OpenClaw. Adds Google, Google Gemini CLI, Google Vertex model provider support to OpenClaw.
|
||||
|
||||
- **[gradium](/plugins/reference/gradium)** (`@openclaw/gradium-speech`) - included in OpenClaw. Adds text-to-speech provider support.
|
||||
@@ -237,7 +235,7 @@ Each entry lists the package, distribution route, and description.
|
||||
|
||||
## Official external packages
|
||||
|
||||
35 plugins
|
||||
36 plugins
|
||||
|
||||
- **[acpx](/plugins/reference/acpx)** (`@openclaw/acpx`) - npm; ClawHub. OpenClaw ACP runtime backend with plugin-owned session and transport management.
|
||||
|
||||
@@ -265,6 +263,8 @@ Each entry lists the package, distribution route, and description.
|
||||
|
||||
- **[feishu](/plugins/reference/feishu)** (`@openclaw/feishu`) - npm; ClawHub. OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng).
|
||||
|
||||
- **[gmi](/plugins/reference/gmi)** (`@openclaw/gmi-provider`) - npm; ClawHub: `clawhub:@openclaw/gmi-provider`. OpenClaw GMI Cloud provider plugin.
|
||||
|
||||
- **[google-meet](/plugins/reference/google-meet)** (`@openclaw/google-meet`) - npm; ClawHub. OpenClaw Google Meet participant plugin for joining calls through Chrome or Twilio transports.
|
||||
|
||||
- **[googlechat](/plugins/reference/googlechat)** (`@openclaw/googlechat`) - npm; ClawHub. OpenClaw Google Chat channel plugin for spaces and direct messages.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
summary: "Adds Gmi, Gmi Cloud, Gmicloud model provider support to OpenClaw."
|
||||
summary: "OpenClaw GMI Cloud provider plugin."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the gmi plugin
|
||||
title: "Gmi plugin"
|
||||
@@ -7,12 +7,12 @@ title: "Gmi plugin"
|
||||
|
||||
# Gmi plugin
|
||||
|
||||
Adds Gmi, Gmi Cloud, Gmicloud model provider support to OpenClaw.
|
||||
OpenClaw GMI Cloud provider plugin.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/gmi-provider`
|
||||
- Install route: included in OpenClaw
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/gmi-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
|
||||
+12
-5
@@ -7,9 +7,9 @@ title: "GMI Cloud"
|
||||
---
|
||||
|
||||
GMI Cloud is a hosted inference platform for frontier and open-weight models
|
||||
behind an OpenAI-compatible API. In OpenClaw it is a bundled model provider,
|
||||
which means you can select it with the provider id `gmi`, store credentials
|
||||
through normal model auth, and use model refs like
|
||||
behind an OpenAI-compatible API. In OpenClaw it is an official external provider
|
||||
plugin, which means you install it once, select it with the provider id `gmi`,
|
||||
store credentials through normal model auth, and use model refs like
|
||||
`gmi/google/gemini-3.1-flash-lite`.
|
||||
|
||||
Use GMI when you want one API key for several hosted model families, including
|
||||
@@ -24,7 +24,14 @@ model availability, billing, rate limits, and any provider-side routing policy.
|
||||
|
||||
## Setup
|
||||
|
||||
Create an API key in GMI Cloud, then run:
|
||||
Install the plugin, restart the gateway, then create an API key in GMI Cloud:
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/gmi-provider
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
openclaw onboard --auth-choice gmi-api-key
|
||||
@@ -60,7 +67,7 @@ GPU control matters more than hosted convenience.
|
||||
|
||||
## Models
|
||||
|
||||
The bundled catalog seeds commonly available GMI Cloud route ids, including:
|
||||
The plugin catalog seeds commonly available GMI Cloud route ids, including:
|
||||
|
||||
- `gmi/zai-org/GLM-5.1-FP8`
|
||||
- `gmi/deepseek-ai/DeepSeek-V3.2`
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# OpenClaw GMI Cloud Provider
|
||||
|
||||
Official OpenClaw provider plugin for hosted GMI Cloud models through an
|
||||
OpenAI-compatible API.
|
||||
|
||||
Install from OpenClaw:
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/gmi-provider
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
Configure a GMI Cloud API key, then select models with refs such as
|
||||
`gmi/google/gemini-3.1-flash-lite`.
|
||||
@@ -11,7 +11,7 @@ const PROVIDER_ID = "gmi";
|
||||
export default defineSingleProviderPluginEntry({
|
||||
id: PROVIDER_ID,
|
||||
name: "GMI Cloud Provider",
|
||||
description: "Bundled GMI Cloud provider plugin",
|
||||
description: "GMI Cloud provider plugin",
|
||||
provider: {
|
||||
label: "GMI Cloud",
|
||||
docsPath: "/providers/gmi",
|
||||
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@openclaw/gmi-provider",
|
||||
"version": "2026.6.8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@openclaw/gmi-provider",
|
||||
"version": "2026.6.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"id": "gmi",
|
||||
"name": "GMI Cloud",
|
||||
"description": "OpenClaw GMI Cloud provider plugin.",
|
||||
"activation": {
|
||||
"onStartup": false
|
||||
},
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
{
|
||||
"name": "@openclaw/gmi-provider",
|
||||
"version": "2026.6.8",
|
||||
"private": true,
|
||||
"description": "OpenClaw GMI Cloud provider plugin",
|
||||
"description": "OpenClaw GMI Cloud 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/gmi-provider",
|
||||
"npmSpec": "@openclaw/gmi-provider",
|
||||
"defaultChoice": "npm",
|
||||
"minHostVersion": ">=2026.6.8"
|
||||
},
|
||||
"compat": {
|
||||
"pluginApi": ">=2026.6.8"
|
||||
},
|
||||
"build": {
|
||||
"openclawVersion": "2026.6.8",
|
||||
"bundledDist": false
|
||||
},
|
||||
"release": {
|
||||
"publishToClawHub": true,
|
||||
"publishToNpm": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
"!dist/extensions/feishu/**",
|
||||
"!dist/extensions/google-meet/**",
|
||||
"!dist/extensions/googlechat/**",
|
||||
"!dist/extensions/gmi/**",
|
||||
"!dist/extensions/line/**",
|
||||
"!dist/extensions/llama-cpp/**",
|
||||
"!dist/extensions/lobster/**",
|
||||
|
||||
@@ -113,6 +113,49 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "@openclaw/gmi-provider",
|
||||
"description": "OpenClaw GMI Cloud provider plugin",
|
||||
"source": "official",
|
||||
"kind": "provider",
|
||||
"openclaw": {
|
||||
"plugin": {
|
||||
"id": "gmi",
|
||||
"label": "GMI Cloud"
|
||||
},
|
||||
"providers": [
|
||||
{
|
||||
"id": "gmi",
|
||||
"aliases": ["gmi-cloud", "gmicloud"],
|
||||
"name": "GMI Cloud",
|
||||
"docs": "/providers/gmi",
|
||||
"categories": ["cloud", "llm"],
|
||||
"authChoices": [
|
||||
{
|
||||
"method": "api-key",
|
||||
"choiceId": "gmi-api-key",
|
||||
"choiceLabel": "GMI Cloud API key",
|
||||
"choiceHint": "OpenAI-compatible GMI Cloud endpoint.",
|
||||
"groupId": "gmi",
|
||||
"groupLabel": "GMI Cloud",
|
||||
"groupHint": "OpenAI-compatible GMI Cloud endpoint",
|
||||
"optionKey": "gmiApiKey",
|
||||
"cliFlag": "--gmi-api-key",
|
||||
"cliOption": "--gmi-api-key <key>",
|
||||
"cliDescription": "GMI Cloud API key",
|
||||
"onboardingScopes": ["text-inference"]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"install": {
|
||||
"clawhubSpec": "clawhub:@openclaw/gmi-provider",
|
||||
"npmSpec": "@openclaw/gmi-provider",
|
||||
"defaultChoice": "npm",
|
||||
"minHostVersion": ">=2026.6.8"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "@openclaw/pixverse-provider",
|
||||
"description": "OpenClaw PixVerse video provider plugin",
|
||||
|
||||
@@ -257,6 +257,48 @@ describe("configured plugin install release step", () => {
|
||||
expect(result.channelIds).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("collects provider plugins from documented external provider aliases", async () => {
|
||||
mocks.resolveProviderInstallCatalogEntries.mockReturnValue([
|
||||
{
|
||||
pluginId: "gmi",
|
||||
providerId: "gmi",
|
||||
providerAliases: ["gmi-cloud", "gmicloud"],
|
||||
},
|
||||
]);
|
||||
|
||||
const { collectReleaseConfiguredPluginIds } =
|
||||
await import("./release-configured-plugin-installs.js");
|
||||
const result = collectReleaseConfiguredPluginIds({
|
||||
cfg: {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "gmi-cloud/google/gemini-3.1-flash-lite",
|
||||
},
|
||||
},
|
||||
auth: {
|
||||
profiles: {
|
||||
gmi: {
|
||||
provider: "gmi-cloud",
|
||||
mode: "api_key",
|
||||
},
|
||||
},
|
||||
},
|
||||
models: {
|
||||
providers: {
|
||||
gmicloud: {
|
||||
baseUrl: "https://api.gmi-serving.com/v1",
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
env: {},
|
||||
});
|
||||
|
||||
expect(result.pluginIds).toEqual(["gmi"]);
|
||||
expect(result.channelIds).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("collects Codex from selectable OpenAI agent models even without integration discovery", async () => {
|
||||
const { collectReleaseConfiguredPluginIds } =
|
||||
await import("./release-configured-plugin-installs.js");
|
||||
|
||||
@@ -192,7 +192,11 @@ function collectProviderPluginIds(cfg: OpenClawConfig, env: NodeJS.ProcessEnv):
|
||||
env,
|
||||
includeUntrustedWorkspacePlugins: false,
|
||||
})) {
|
||||
if (configuredProviders.has(entry.providerId.toLowerCase())) {
|
||||
if (
|
||||
[entry.providerId, ...(entry.providerAliases ?? [])].some((providerId) =>
|
||||
configuredProviders.has(providerId.toLowerCase()),
|
||||
)
|
||||
) {
|
||||
ids.add(entry.pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,18 @@ describe("official external plugin catalog", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("lists GMI Cloud as an official external provider", () => {
|
||||
const gmi = expectCatalogEntry("gmi");
|
||||
|
||||
expect(resolveOfficialExternalPluginId(gmi)).toBe("gmi");
|
||||
expect(resolveOfficialExternalPluginInstall(gmi)).toEqual({
|
||||
clawhubSpec: "clawhub:@openclaw/gmi-provider",
|
||||
npmSpec: "@openclaw/gmi-provider",
|
||||
defaultChoice: "npm",
|
||||
minHostVersion: ">=2026.6.8",
|
||||
});
|
||||
});
|
||||
|
||||
it("allows invalid-config recovery for externalized stock plugins", () => {
|
||||
expect(resolveOfficialExternalPluginInstall(expectCatalogEntry("brave"))).toMatchObject({
|
||||
npmSpec: "@openclaw/brave-plugin",
|
||||
|
||||
@@ -33,6 +33,7 @@ export type OfficialExternalProviderAuthChoice = {
|
||||
|
||||
export type OfficialExternalProviderCatalogProvider = {
|
||||
id?: string;
|
||||
aliases?: readonly string[];
|
||||
name?: string;
|
||||
docs?: string;
|
||||
categories?: readonly string[];
|
||||
|
||||
@@ -620,6 +620,43 @@ describe("provider install catalog", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves official external provider aliases for configured-plugin repair", () => {
|
||||
listOfficialExternalProviderCatalogEntries.mockReturnValue([
|
||||
{
|
||||
name: "@openclaw/gmi-provider",
|
||||
source: "official",
|
||||
kind: "provider",
|
||||
openclaw: {
|
||||
plugin: { id: "gmi", label: "GMI Cloud" },
|
||||
providers: [
|
||||
{
|
||||
id: "gmi",
|
||||
aliases: ["gmi-cloud", "gmicloud"],
|
||||
name: "GMI Cloud",
|
||||
authChoices: [
|
||||
{
|
||||
method: "api-key",
|
||||
choiceId: "gmi-api-key",
|
||||
choiceLabel: "GMI Cloud API key",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
install: {
|
||||
npmSpec: "@openclaw/gmi-provider",
|
||||
defaultChoice: "npm",
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
expect(resolveProviderInstallCatalogEntry("gmi-api-key")).toMatchObject({
|
||||
pluginId: "gmi",
|
||||
providerId: "gmi",
|
||||
providerAliases: ["gmi-cloud", "gmicloud"],
|
||||
});
|
||||
});
|
||||
|
||||
it("surfaces provider-index ClawHub install metadata as the preferred source", () => {
|
||||
loadOpenClawProviderIndex.mockReturnValue({
|
||||
version: 1,
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
|
||||
/** Provider setup choice paired with install metadata for the owning plugin. */
|
||||
export type ProviderInstallCatalogEntry = ProviderAuthChoiceMetadata & {
|
||||
providerAliases?: string[];
|
||||
label: string;
|
||||
origin: PluginOrigin;
|
||||
install: PluginPackageInstall;
|
||||
@@ -332,6 +333,13 @@ function resolveOfficialExternalProviderInstallCatalogEntries(params: {
|
||||
if (!providerId || !label) {
|
||||
continue;
|
||||
}
|
||||
const providerAliases = [
|
||||
...new Set(
|
||||
(provider.aliases ?? [])
|
||||
.map((alias) => alias.trim())
|
||||
.filter((alias) => alias && alias !== providerId),
|
||||
),
|
||||
];
|
||||
for (const choice of provider.authChoices ?? []) {
|
||||
const methodId = choice.method?.trim();
|
||||
const choiceId = choice.choiceId?.trim();
|
||||
@@ -342,6 +350,7 @@ function resolveOfficialExternalProviderInstallCatalogEntries(params: {
|
||||
entries.push({
|
||||
pluginId,
|
||||
providerId,
|
||||
...(providerAliases.length > 0 ? { providerAliases } : {}),
|
||||
methodId,
|
||||
choiceId,
|
||||
choiceLabel,
|
||||
|
||||
@@ -122,10 +122,32 @@ describe("OpenClaw dual-published plugin metadata", () => {
|
||||
{
|
||||
extensionId: "diagnostics-otel",
|
||||
packageName: "@openclaw/diagnostics-otel",
|
||||
install: {
|
||||
clawhubSpec: "clawhub:@openclaw/diagnostics-otel",
|
||||
defaultChoice: "npm",
|
||||
minHostVersion: ">=2026.4.25",
|
||||
npmSpec: "@openclaw/diagnostics-otel",
|
||||
},
|
||||
},
|
||||
{
|
||||
extensionId: "diagnostics-prometheus",
|
||||
packageName: "@openclaw/diagnostics-prometheus",
|
||||
install: {
|
||||
clawhubSpec: "clawhub:@openclaw/diagnostics-prometheus",
|
||||
defaultChoice: "npm",
|
||||
minHostVersion: ">=2026.4.25",
|
||||
npmSpec: "@openclaw/diagnostics-prometheus",
|
||||
},
|
||||
},
|
||||
{
|
||||
extensionId: "gmi",
|
||||
packageName: "@openclaw/gmi-provider",
|
||||
install: {
|
||||
clawhubSpec: "clawhub:@openclaw/gmi-provider",
|
||||
defaultChoice: "npm",
|
||||
minHostVersion: ">=2026.6.8",
|
||||
npmSpec: "@openclaw/gmi-provider",
|
||||
},
|
||||
},
|
||||
] as const;
|
||||
|
||||
@@ -158,12 +180,7 @@ describe("OpenClaw dual-published plugin metadata", () => {
|
||||
};
|
||||
};
|
||||
|
||||
expect(packageJson.openclaw?.install).toEqual({
|
||||
clawhubSpec: `clawhub:${plugin.packageName}`,
|
||||
defaultChoice: "npm",
|
||||
minHostVersion: ">=2026.4.25",
|
||||
npmSpec: plugin.packageName,
|
||||
});
|
||||
expect(packageJson.openclaw?.install).toEqual(plugin.install);
|
||||
expect(packageJson.openclaw?.release).toEqual({
|
||||
publishToClawHub: true,
|
||||
publishToNpm: true,
|
||||
|
||||
Reference in New Issue
Block a user