From e84e2a49fca702bfa22d218ba0c9746ffc2b96c7 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 1 Aug 2026 03:53:46 +0800 Subject: [PATCH] feat(plugins): externalize NovitaAI provider (#117007) --- docs/docs_map.md | 2 +- docs/plugins/plugin-inventory.md | 8 +-- docs/plugins/reference/novita.md | 2 +- docs/providers/novita.md | 16 ++++-- extensions/novita/README.md | 15 ++++++ extensions/novita/index.ts | 2 +- extensions/novita/package.json | 24 ++++++++- package.json | 1 + .../official-external-provider-catalog.json | 50 +++++++++++++++++++ src/cli/plugins-location-bridges.test.ts | 1 + .../official-external-plugin-catalog.test.ts | 13 +++++ ...ficial-external-provider-endpoints.test.ts | 1 + test/plugin-clawhub-release.test.ts | 10 ++++ .../bundled-plugin-build-entries.test.ts | 2 +- 14 files changed, 133 insertions(+), 14 deletions(-) create mode 100644 extensions/novita/README.md diff --git a/docs/docs_map.md b/docs/docs_map.md index bc65f7d97555..5dc0e9250055 100644 --- a/docs/docs_map.md +++ b/docs/docs_map.md @@ -8504,7 +8504,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`. - Headings: - H2: Setup - H2: Defaults - - H2: Bundled model catalog + - H2: Model catalog - H2: When to choose Novita - H2: Troubleshooting - H2: Related diff --git a/docs/plugins/plugin-inventory.md b/docs/plugins/plugin-inventory.md index 6fd2067d543b..0cdc8038ba36 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 -58 plugins +57 plugins - **[admin-http-rpc](/plugins/reference/admin-http-rpc)** (`@openclaw/admin-http-rpc`) - included in OpenClaw. OpenClaw admin HTTP RPC endpoint. @@ -121,8 +121,6 @@ Each entry lists the package, distribution route, and description. - **[minimax](/plugins/reference/minimax)** (`@openclaw/minimax-provider`) - included in OpenClaw. Adds MiniMax, MiniMax Portal model provider support to OpenClaw. -- **[novita](/plugins/reference/novita)** (`@openclaw/novita-provider`) - included in OpenClaw. Adds Novita, Novita AI, Novitaai model provider support to OpenClaw. - - **[nvidia](/plugins/reference/nvidia)** (`@openclaw/nvidia-provider`) - included in OpenClaw. Adds NVIDIA model provider support to OpenClaw. - **[oc-path](/plugins/reference/oc-path)** (`@openclaw/oc-path`) - included in OpenClaw. Adds the openclaw path CLI for oc:// workspace file addressing. @@ -171,7 +169,7 @@ Each entry lists the package, distribution route, and description. ## Official external packages -87 plugins +88 plugins - **[acpx](/plugins/reference/acpx)** (`@openclaw/acpx`) - npm; ClawHub. OpenClaw ACP runtime backend with plugin-owned session and transport management. @@ -281,6 +279,8 @@ Each entry lists the package, distribution route, and description. - **[nostr](/plugins/reference/nostr)** (`@openclaw/nostr`) - npm; ClawHub. OpenClaw Nostr channel plugin for NIP-04 encrypted direct messages. +- **[novita](/plugins/reference/novita)** (`@openclaw/novita-provider`) - npm; ClawHub: `clawhub:@openclaw/novita-provider`. Adds Novita, Novita AI, Novitaai model provider support to OpenClaw. + - **[openshell](/plugins/reference/openshell)** (`@openclaw/openshell-sandbox`) - npm; ClawHub. OpenClaw sandbox backend for the NVIDIA OpenShell CLI with mirrored local workspaces and SSH command execution. - **[parallel](/tools/parallel-search)** (`@openclaw/parallel-plugin`) - npm; ClawHub: `clawhub:@openclaw/parallel-plugin`. Adds web search provider support. diff --git a/docs/plugins/reference/novita.md b/docs/plugins/reference/novita.md index 2e9485426a10..93a57f41d00e 100644 --- a/docs/plugins/reference/novita.md +++ b/docs/plugins/reference/novita.md @@ -12,7 +12,7 @@ Adds Novita, Novita AI, Novitaai model provider support to OpenClaw. ## Distribution - Package: `@openclaw/novita-provider` -- Install route: included in OpenClaw +- Install route: npm; ClawHub: `clawhub:@openclaw/novita-provider` ## Surface diff --git a/docs/providers/novita.md b/docs/providers/novita.md index ae69d6f2eeab..2f45fb9abc7a 100644 --- a/docs/providers/novita.md +++ b/docs/providers/novita.md @@ -7,12 +7,19 @@ title: "NovitaAI" --- NovitaAI is a hosted AI infrastructure provider with an OpenAI-compatible API. -It ships as a bundled OpenClaw provider (no separate plugin install), so -credentials go through the normal model auth flow and model refs look like -`novita/deepseek/deepseek-v4-pro`. +OpenClaw provides NovitaAI through the official external +`@openclaw/novita-provider` plugin. Model refs use the +`novita/deepseek/deepseek-v4-pro` form. ## Setup +Install the plugin and restart the Gateway: + +```bash +openclaw plugins install @openclaw/novita-provider +openclaw gateway restart +``` + Create an API key at [novita.ai/settings/key-management](https://novita.ai/settings/key-management), then run: ```bash @@ -29,13 +36,14 @@ export NOVITA_API_KEY="" # pragma: allowlist secret | Setting | Value | | ------------- | --------------------------------- | +| Plugin | `@openclaw/novita-provider` | | Provider id | `novita` | | Aliases | `novita-ai`, `novitaai` | | Base URL | `https://api.novita.ai/openai/v1` | | Env var | `NOVITA_API_KEY` | | Default model | `novita/deepseek/deepseek-v4-pro` | -## Bundled model catalog +## Model catalog - `novita/moonshotai/kimi-k3` - `novita/moonshotai/kimi-k2.7-code` diff --git a/extensions/novita/README.md b/extensions/novita/README.md new file mode 100644 index 000000000000..0266a92f7a1d --- /dev/null +++ b/extensions/novita/README.md @@ -0,0 +1,15 @@ +# OpenClaw NovitaAI provider + +Official OpenClaw provider plugin for NovitaAI's OpenAI-compatible API. + +## Install + +```sh +openclaw plugins install @openclaw/novita-provider +openclaw gateway restart +``` + +## Docs + +See `docs/providers/novita.md` in the OpenClaw repository, or the published +docs at `https://docs.openclaw.ai/providers/novita`. diff --git a/extensions/novita/index.ts b/extensions/novita/index.ts index 3f8b7ec302fb..8dc79d67bb00 100644 --- a/extensions/novita/index.ts +++ b/extensions/novita/index.ts @@ -10,7 +10,7 @@ const PROVIDER_ID = "novita"; export default defineSingleProviderPluginEntry({ id: PROVIDER_ID, name: "NovitaAI Provider", - description: "Bundled NovitaAI provider plugin", + description: "Official OpenClaw NovitaAI provider plugin", manifest, provider: { label: "NovitaAI", diff --git a/extensions/novita/package.json b/extensions/novita/package.json index 4dd80513c28d..ce10dd44cf6e 100644 --- a/extensions/novita/package.json +++ b/extensions/novita/package.json @@ -1,8 +1,11 @@ { "name": "@openclaw/novita-provider", "version": "2026.7.2", - "private": true, "description": "OpenClaw NovitaAI 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/novita-provider", + "npmSpec": "@openclaw/novita-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 7d658a3c0d0c..74e01cd249ce 100644 --- a/package.json +++ b/package.json @@ -293,6 +293,7 @@ "!dist/extensions/mxc/**", "!dist/extensions/nextcloud-talk/**", "!dist/extensions/nostr/**", + "!dist/extensions/novita/**", "!dist/extensions/parallel/**", "!dist/extensions/perplexity/**", "!dist/extensions/qianfan/**", diff --git a/scripts/lib/official-external-provider-catalog.json b/scripts/lib/official-external-provider-catalog.json index 8fad01258873..56d0d50337ff 100644 --- a/scripts/lib/official-external-provider-catalog.json +++ b/scripts/lib/official-external-provider-catalog.json @@ -912,6 +912,56 @@ } } }, + { + "name": "@openclaw/novita-provider", + "description": "OpenClaw NovitaAI provider plugin", + "source": "official", + "kind": "provider", + "openclaw": { + "plugin": { + "id": "novita", + "label": "NovitaAI" + }, + "providerEndpoints": [ + { + "endpointClass": "novita-native", + "hosts": ["api.novita.ai"] + } + ], + "providers": [ + { + "id": "novita", + "aliases": ["novita-ai", "novitaai"], + "name": "NovitaAI", + "docs": "/providers/novita", + "categories": ["cloud", "llm"], + "envVars": ["NOVITA_API_KEY"], + "authChoices": [ + { + "method": "api-key", + "choiceId": "novita-api-key", + "choiceLabel": "NovitaAI API key", + "choiceHint": "OpenAI-compatible NovitaAI endpoint", + "groupId": "novita", + "groupLabel": "NovitaAI", + "groupHint": "OpenAI-compatible NovitaAI endpoint", + "optionKey": "novitaApiKey", + "cliFlag": "--novita-api-key", + "cliOption": "--novita-api-key ", + "cliDescription": "NovitaAI API key", + "onboardingScopes": ["text-inference"] + } + ] + } + ], + "install": { + "clawhubSpec": "clawhub:@openclaw/novita-provider", + "npmSpec": "@openclaw/novita-provider", + "defaultChoice": "npm", + "minHostVersion": ">=2026.7.2" + } + } + }, { "name": "@openclaw/groq-provider", "description": "OpenClaw Groq media-understanding provider.", diff --git a/src/cli/plugins-location-bridges.test.ts b/src/cli/plugins-location-bridges.test.ts index d9294c6fdf12..cb7b9b71b335 100644 --- a/src/cli/plugins-location-bridges.test.ts +++ b/src/cli/plugins-location-bridges.test.ts @@ -168,6 +168,7 @@ describe("listPersistedBundledPluginLocationBridges", () => { ["byteplus", "@openclaw/byteplus-provider", true], ["duckduckgo", "@openclaw/duckduckgo-plugin", false], ["mistral", "@openclaw/mistral-provider", true], + ["novita", "@openclaw/novita-provider", true], ["synthetic", "@openclaw/synthetic-provider", true], ["teams-meetings", "@openclaw/teams-meetings", true], ["volcengine", "@openclaw/volcengine-provider", true], diff --git a/src/plugins/official-external-plugin-catalog.test.ts b/src/plugins/official-external-plugin-catalog.test.ts index b9637d215930..1c8b1b412530 100644 --- a/src/plugins/official-external-plugin-catalog.test.ts +++ b/src/plugins/official-external-plugin-catalog.test.ts @@ -2171,6 +2171,19 @@ describe("official external plugin catalog", () => { }); }); + it("maps NovitaAI provider aliases and credentials to the external plugin", () => { + expect( + resolveOfficialExternalProviderPluginIds({ + providerIds: new Set(["novita", "novita-ai", "novitaai"]), + }), + ).toEqual(["novita"]); + expect( + resolveOfficialExternalProviderPluginIdsForEnv({ + NOVITA_API_KEY: "novita-key", + }), + ).toEqual(["novita"]); + }); + it.each([ ["teams-meetings", "@openclaw/teams-meetings", "teams_meetings", "teams"], ["zoom-meetings", "@openclaw/zoom-meetings", "zoom_meetings", "zoom"], diff --git a/src/plugins/official-external-provider-endpoints.test.ts b/src/plugins/official-external-provider-endpoints.test.ts index 802ecdcc07f2..d9c3d4a219da 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("novita-native"); expect(endpointClasses).toContain("xiaomi-native"); expect(endpointClasses).toContain("zai-native"); }); diff --git a/test/plugin-clawhub-release.test.ts b/test/plugin-clawhub-release.test.ts index d737c6766ae5..155d22400dfd 100644 --- a/test/plugin-clawhub-release.test.ts +++ b/test/plugin-clawhub-release.test.ts @@ -236,6 +236,16 @@ describe("OpenClaw dual-published plugin metadata", () => { npmSpec: "@openclaw/gmi-provider", }, }, + { + extensionId: "novita", + packageName: "@openclaw/novita-provider", + install: { + clawhubSpec: "clawhub:@openclaw/novita-provider", + defaultChoice: "npm", + minHostVersion: ">=2026.7.2", + npmSpec: "@openclaw/novita-provider", + }, + }, ] as const; it("keeps dual-published plugins selectable through both ClawHub and npm release paths", () => { diff --git a/test/scripts/bundled-plugin-build-entries.test.ts b/test/scripts/bundled-plugin-build-entries.test.ts index f71c6a04e57b..107d7b413233 100644 --- a/test/scripts/bundled-plugin-build-entries.test.ts +++ b/test/scripts/bundled-plugin-build-entries.test.ts @@ -342,7 +342,7 @@ describe("bundled plugin build entries", () => { it("excludes externalized model providers from bundled artifacts", () => { const artifacts = listBundledPluginPackArtifacts(); - for (const pluginId of ["byteplus", "cohere", "meta", "mistral", "xiaomi"]) { + for (const pluginId of ["byteplus", "cohere", "meta", "mistral", "novita", "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`);