From a550827dad3006cb461a89402080638545454818 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Fri, 31 Jul 2026 17:19:43 +0800 Subject: [PATCH] feat(plugins): externalize Synthetic provider (#116720) --- docs/plugins/plugin-inventory.md | 8 +-- docs/plugins/reference/synthetic.md | 2 +- docs/providers/synthetic.md | 10 +++- extensions/synthetic/README.md | 16 ++++++ extensions/synthetic/index.ts | 2 +- extensions/synthetic/package.json | 26 ++++++++-- package.json | 1 + .../official-external-provider-catalog.json | 49 +++++++++++++++++++ src/cli/plugins-location-bridges.test.ts | 1 + .../official-external-plugin-catalog.test.ts | 12 +++++ .../bundled-plugin-build-entries.test.ts | 8 +++ 11 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 extensions/synthetic/README.md diff --git a/docs/plugins/plugin-inventory.md b/docs/plugins/plugin-inventory.md index a66bc377a0ad..d79d99948bae 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 -67 plugins +66 plugins - **[admin-http-rpc](/plugins/reference/admin-http-rpc)** (`@openclaw/admin-http-rpc`) - included in OpenClaw. OpenClaw admin HTTP RPC endpoint. @@ -159,8 +159,6 @@ Each entry lists the package, distribution route, and description. - **[sglang](/plugins/reference/sglang)** (`@openclaw/sglang-provider`) - included in OpenClaw. Adds SGLang model provider support to OpenClaw. -- **[synthetic](/plugins/reference/synthetic)** (`@openclaw/synthetic-provider`) - included in OpenClaw. Adds Synthetic model provider support to OpenClaw. - - **[telegram](/plugins/reference/telegram)** (`@openclaw/telegram`) - included in OpenClaw. Adds the Telegram channel surface for sending and receiving OpenClaw messages. - **[together](/plugins/reference/together)** (`@openclaw/together-provider`) - included in OpenClaw. Adds Together model provider support to OpenClaw. @@ -189,7 +187,7 @@ Each entry lists the package, distribution route, and description. ## Official external packages -78 plugins +79 plugins - **[acpx](/plugins/reference/acpx)** (`@openclaw/acpx`) - npm; ClawHub. OpenClaw ACP runtime backend with plugin-owned session and transport management. @@ -319,6 +317,8 @@ Each entry lists the package, distribution route, and description. - **[synology-chat](/plugins/reference/synology-chat)** (`@openclaw/synology-chat`) - npm; ClawHub. Synology Chat channel plugin for OpenClaw channels and direct messages. +- **[synthetic](/plugins/reference/synthetic)** (`@openclaw/synthetic-provider`) - npm; ClawHub: `clawhub:@openclaw/synthetic-provider`. Adds Synthetic model provider support to OpenClaw. + - **[tavily](/plugins/reference/tavily)** (`@openclaw/tavily-plugin`) - npm; ClawHub: `clawhub:@openclaw/tavily-plugin`. Adds agent-callable tools. Adds web search provider support. - **[teams-meetings](/plugins/reference/teams-meetings)** (`@openclaw/teams-meetings`) - npm; ClawHub: `clawhub:@openclaw/teams-meetings`. Join Microsoft Teams meetings as a Chrome browser guest. diff --git a/docs/plugins/reference/synthetic.md b/docs/plugins/reference/synthetic.md index 8eacd887529b..ca38a2076a2f 100644 --- a/docs/plugins/reference/synthetic.md +++ b/docs/plugins/reference/synthetic.md @@ -12,7 +12,7 @@ Adds Synthetic model provider support to OpenClaw. ## Distribution - Package: `@openclaw/synthetic-provider` -- Install route: included in OpenClaw +- Install route: npm; ClawHub: `clawhub:@openclaw/synthetic-provider` ## Surface diff --git a/docs/providers/synthetic.md b/docs/providers/synthetic.md index 29b1d7649e6f..073cdc93a2f9 100644 --- a/docs/providers/synthetic.md +++ b/docs/providers/synthetic.md @@ -7,8 +7,8 @@ title: "Synthetic" --- [Synthetic](https://synthetic.new) exposes Anthropic-compatible endpoints. -OpenClaw bundles it as the `synthetic` provider and uses the Anthropic -Messages API. +OpenClaw provides it through the official `@openclaw/synthetic-provider` +plugin and uses the Anthropic Messages API. | Property | Value | | -------- | ------------------------------------- | @@ -20,6 +20,12 @@ Messages API. ## Getting started + + ```bash + openclaw plugins install @openclaw/synthetic-provider + openclaw gateway restart + ``` + Get a `SYNTHETIC_API_KEY` from your Synthetic account, or let onboarding prompt you for one. diff --git a/extensions/synthetic/README.md b/extensions/synthetic/README.md new file mode 100644 index 000000000000..782a114cfe2c --- /dev/null +++ b/extensions/synthetic/README.md @@ -0,0 +1,16 @@ +# OpenClaw Synthetic Provider + +Official OpenClaw provider plugin for Synthetic's hosted Anthropic-compatible +API. + +Install from OpenClaw: + +```bash +openclaw plugins install @openclaw/synthetic-provider +openclaw gateway restart +``` + +Configure `SYNTHETIC_API_KEY`, then select a `synthetic/` model. + +See https://docs.openclaw.ai/providers/synthetic for model and configuration +details. diff --git a/extensions/synthetic/index.ts b/extensions/synthetic/index.ts index 32e57a5b7426..a5e24eba3291 100644 --- a/extensions/synthetic/index.ts +++ b/extensions/synthetic/index.ts @@ -9,7 +9,7 @@ const PROVIDER_ID = "synthetic"; export default defineSingleProviderPluginEntry({ id: PROVIDER_ID, name: "Synthetic Provider", - description: "Bundled Synthetic provider plugin", + description: "Synthetic provider plugin", manifest, provider: { label: "Synthetic", diff --git a/extensions/synthetic/package.json b/extensions/synthetic/package.json index 0c61cceb2f3d..64d899c8ba6c 100644 --- a/extensions/synthetic/package.json +++ b/extensions/synthetic/package.json @@ -1,8 +1,11 @@ { "name": "@openclaw/synthetic-provider", "version": "2026.7.2", - "private": true, - "description": "OpenClaw Synthetic provider plugin", + "description": "OpenClaw Synthetic 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/synthetic-provider", + "npmSpec": "@openclaw/synthetic-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 f6aa93bd248f..1fd62961b564 100644 --- a/package.json +++ b/package.json @@ -304,6 +304,7 @@ "!dist/extensions/slack/**", "!dist/extensions/sms/**", "!dist/extensions/stepfun/**", + "!dist/extensions/synthetic/**", "!dist/extensions/synology-chat/**", "!dist/extensions/tavily/**", "!dist/extensions/teams-meetings/**", diff --git a/scripts/lib/official-external-provider-catalog.json b/scripts/lib/official-external-provider-catalog.json index 6590b6abd679..882145a98922 100644 --- a/scripts/lib/official-external-provider-catalog.json +++ b/scripts/lib/official-external-provider-catalog.json @@ -1659,6 +1659,55 @@ } } }, + { + "name": "@openclaw/synthetic-provider", + "description": "OpenClaw Synthetic provider plugin.", + "source": "official", + "kind": "provider", + "openclaw": { + "plugin": { + "id": "synthetic", + "label": "Synthetic" + }, + "providers": [ + { + "id": "synthetic", + "name": "Synthetic", + "docs": "/providers/synthetic", + "categories": [ + "cloud", + "llm" + ], + "envVars": [ + "SYNTHETIC_API_KEY" + ], + "authChoices": [ + { + "method": "api-key", + "choiceId": "synthetic-api-key", + "choiceLabel": "Synthetic API key", + "groupId": "synthetic", + "groupLabel": "Synthetic", + "groupHint": "Anthropic-compatible (multi-model)", + "optionKey": "syntheticApiKey", + "cliFlag": "--synthetic-api-key", + "cliOption": "--synthetic-api-key ", + "cliDescription": "Synthetic API key", + "onboardingScopes": [ + "text-inference" + ] + } + ] + } + ], + "install": { + "clawhubSpec": "clawhub:@openclaw/synthetic-provider", + "npmSpec": "@openclaw/synthetic-provider", + "defaultChoice": "npm", + "minHostVersion": ">=2026.7.2" + } + } + }, { "name": "@openclaw/stepfun-provider", "description": "OpenClaw StepFun provider plugin.", diff --git a/src/cli/plugins-location-bridges.test.ts b/src/cli/plugins-location-bridges.test.ts index 1ab8b5a7c718..d76637285bfc 100644 --- a/src/cli/plugins-location-bridges.test.ts +++ b/src/cli/plugins-location-bridges.test.ts @@ -165,6 +165,7 @@ describe("listPersistedBundledPluginLocationBridges", () => { }); it.each([ + ["synthetic", "@openclaw/synthetic-provider"], ["teams-meetings", "@openclaw/teams-meetings"], ["zoom-meetings", "@openclaw/zoom-meetings"], ])( diff --git a/src/plugins/official-external-plugin-catalog.test.ts b/src/plugins/official-external-plugin-catalog.test.ts index 637755ebe992..72c2c481ba13 100644 --- a/src/plugins/official-external-plugin-catalog.test.ts +++ b/src/plugins/official-external-plugin-catalog.test.ts @@ -1960,6 +1960,18 @@ describe("official external plugin catalog", () => { }); }); + it("lists Synthetic as an official external provider", () => { + const synthetic = expectCatalogEntry("synthetic"); + + expect(resolveOfficialExternalPluginId(synthetic)).toBe("synthetic"); + expect(resolveOfficialExternalPluginInstall(synthetic)).toEqual({ + clawhubSpec: "clawhub:@openclaw/synthetic-provider", + npmSpec: "@openclaw/synthetic-provider", + defaultChoice: "npm", + minHostVersion: ">=2026.7.2", + }); + }); + it.each([ ["teams-meetings", "@openclaw/teams-meetings", "teams_meetings", "teams"], ["zoom-meetings", "@openclaw/zoom-meetings", "zoom_meetings", "zoom"], diff --git a/test/scripts/bundled-plugin-build-entries.test.ts b/test/scripts/bundled-plugin-build-entries.test.ts index c144c7fb101a..bb18e4c1531c 100644 --- a/test/scripts/bundled-plugin-build-entries.test.ts +++ b/test/scripts/bundled-plugin-build-entries.test.ts @@ -359,6 +359,14 @@ describe("bundled plugin build entries", () => { } }); + it("excludes the externalized Synthetic provider from bundled artifacts", () => { + const entries = listBundledPluginBuildEntries(); + const artifacts = listBundledPluginPackArtifacts(); + + expectNoPrefixMatches(Object.keys(entries), "extensions/synthetic/"); + expectNoPrefixMatches(artifacts, "dist/extensions/synthetic/"); + }); + it("keeps bundled channel secret contracts on packed top-level sidecars", () => { const artifacts = listBundledPluginPackArtifacts(); const excludedPackageDirs = collectRootPackageExcludedExtensionDirs();