fix(plugins): keep OpenCode Go bundled (#120985)

* fix(plugins): keep OpenCode Go bundled

* fix(plugins): mark OpenCode Go dist bundled

* fix(docs): show OpenCode Go as bundled

* fix(release): defer bundled plugin publication
This commit is contained in:
Peter Steinberger
2026-08-09 03:09:47 -07:00
committed by GitHub
parent 8b0735e89f
commit c092900e3c
13 changed files with 155 additions and 28 deletions
+4 -4
View File
@@ -51,7 +51,7 @@ Each entry lists the package, distribution route, and description.
## Core npm package
54 plugins
55 plugins
- **[admin-http-rpc](/plugins/reference/admin-http-rpc)** (`@openclaw/admin-http-rpc`) - included in OpenClaw. OpenClaw admin HTTP RPC endpoint.
@@ -131,6 +131,8 @@ Each entry lists the package, distribution route, and description.
- **[openai](/plugins/reference/openai)** (`@openclaw/openai-provider`) - included in OpenClaw. Adds OpenAI model provider support to OpenClaw.
- **[opencode-go](/plugins/reference/opencode-go)** (`@openclaw/opencode-go-provider`) - included in OpenClaw. Adds OpenCode Go model provider support to OpenClaw.
- **[openrouter](/plugins/reference/openrouter)** (`@openclaw/openrouter-provider`) - included in OpenClaw. Adds OpenRouter model provider support to OpenClaw.
- **[policy](/plugins/reference/policy)** (`@openclaw/policy`) - included in OpenClaw. Adds policy-backed doctor checks for workspace conformance.
@@ -163,7 +165,7 @@ Each entry lists the package, distribution route, and description.
## Official external packages
91 plugins
90 plugins
- **[acpx](/plugins/reference/acpx)** (`@openclaw/acpx`) - npm; ClawHub. OpenClaw ACP runtime backend with plugin-owned session and transport management.
@@ -279,8 +281,6 @@ Each entry lists the package, distribution route, and description.
- **[opencode](/plugins/reference/opencode)** (`@openclaw/opencode-provider`) - npm; ClawHub: `clawhub:@openclaw/opencode-provider`. Adds OpenCode model provider support to OpenClaw.
- **[opencode-go](/plugins/reference/opencode-go)** (`@openclaw/opencode-go-provider`) - npm; ClawHub: `clawhub:@openclaw/opencode-go-provider`. Adds OpenCode Go 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.
+1 -1
View File
@@ -12,7 +12,7 @@ Adds OpenCode Go model provider support to OpenClaw.
## Distribution
- Package: `@openclaw/opencode-go-provider`
- Install route: npm; ClawHub: `clawhub:@openclaw/opencode-go-provider`
- Install route: included in OpenClaw
## Surface
+6 -9
View File
@@ -9,24 +9,21 @@ title: "OpenCode Go"
OpenCode Go is the Go catalog inside [OpenCode](/providers/opencode). It shares
the `OPENCODE_API_KEY` credential with the Zen catalog, but keeps its own
runtime provider id (`opencode-go`) so upstream per-model routing stays
correct. OpenClaw provides it as the official external
`@openclaw/opencode-go-provider` plugin.
correct. OpenCode Go is bundled in the OpenClaw package for this release, so
onboarding and configuration are sufficient; no separate plugin install is
required.
| Property | Value |
| ---------------- | -------------------------------------------------- |
| Runtime provider | `opencode-go` |
| Plugin | `@openclaw/opencode-go-provider` |
| Plugin | Bundled (`opencode-go`) |
| Auth | `OPENCODE_API_KEY` (alias: `OPENCODE_ZEN_API_KEY`) |
| Parent setup | [OpenCode](/providers/opencode) |
## Getting started
Install the official plugin and restart the Gateway:
```bash
openclaw plugins install @openclaw/opencode-go-provider
openclaw gateway restart
```
OpenCode Go is already included with OpenClaw for this release. Continue with
interactive onboarding or pass the shared OpenCode API key directly.
<Tabs>
<Tab title="Interactive">
+3 -5
View File
@@ -55,11 +55,9 @@ one OpenCode setup.
**Best for:** the OpenCode-hosted Kimi, GLM, MiniMax, Qwen, and DeepSeek lineup.
<Steps>
<Step title="Install the Go catalog plugin">
```bash
openclaw plugins install @openclaw/opencode-go-provider
openclaw gateway restart
```
<Step title="Use the bundled Go catalog">
OpenCode Go is included with OpenClaw for this release, so no separate
plugin installation or Gateway restart is required.
</Step>
<Step title="Run onboarding">
```bash
+2 -6
View File
@@ -2,12 +2,8 @@
Official OpenClaw provider plugin for the OpenCode Go model catalog.
Install from OpenClaw:
```bash
openclaw plugins install @openclaw/opencode-go-provider
openclaw gateway restart
```
OpenCode Go is bundled with OpenClaw for this release; no separate plugin
installation is required.
Configure `OPENCODE_API_KEY` or `OPENCODE_ZEN_API_KEY`, then select an
`opencode-go/...` model.
+1 -1
View File
@@ -25,7 +25,7 @@
},
"build": {
"openclawVersion": "2026.8.1",
"bundledDist": false
"bundledDist": true
},
"release": {
"publishToClawHub": true,
-1
View File
@@ -307,7 +307,6 @@
"!dist/extensions/nostr/**",
"!dist/extensions/novita/**",
"!dist/extensions/opencode/**",
"!dist/extensions/opencode-go/**",
"!dist/extensions/parallel/**",
"!dist/extensions/perplexity/**",
"!dist/extensions/qianfan/**",
@@ -334,6 +334,10 @@ function resolveInstallRoute(packageJson, status) {
return "source checkout only";
}
if (status === "core") {
// Explicit bundle ownership describes the current install surface; release flags may stage future publication.
if (packageJson.openclaw?.build?.bundledDist === true) {
return "included in OpenClaw";
}
const release = packageJson.openclaw?.release;
if (release?.publishToClawHub === true || release?.publishToNpm === true) {
return `included in OpenClaw; ${resolveInstallRoute(packageJson, "external")}`;
+5
View File
@@ -13,6 +13,7 @@ import {
collectChangedExtensionIdsFromPaths,
collectPublishablePluginPackageErrors,
collectRequiredLatestDependencies,
isPluginExternalPublicationDeferred,
assertPluginReleaseVersionFloors,
parsePluginReleaseArgs,
resolvePublishablePluginVersion,
@@ -45,6 +46,7 @@ type PluginPackageJson = {
minGatewayVersion?: string;
};
build?: {
bundledDist?: boolean;
openclawVersion?: string;
pluginSdkVersion?: string;
};
@@ -283,6 +285,9 @@ export function collectClawHubPublishablePluginPackages(
if (hasSelectedPackageNames && !selectedPackageNames.has(packageName)) {
continue;
}
if (isPluginExternalPublicationDeferred(packageJson)) {
continue;
}
if (packageJson.openclaw?.release?.publishToClawHub !== true) {
continue;
}
+11
View File
@@ -34,6 +34,7 @@ type PluginPackageJson = {
minGatewayVersion?: string;
};
build?: {
bundledDist?: boolean;
openclawVersion?: string;
pluginSdkVersion?: string;
};
@@ -45,6 +46,13 @@ type PluginPackageJson = {
};
};
/** Explicit core ownership defers staged external publication until the plugin is externalized. */
export function isPluginExternalPublicationDeferred(packageJson: {
openclaw?: { build?: { bundledDist?: unknown } };
}): boolean {
return packageJson.openclaw?.build?.bundledDist === true;
}
export type RequiredLatestDependency = {
packageName: string;
version: string;
@@ -430,6 +438,9 @@ export function collectPublishablePluginPackages(
if (hasSelectedPackageNames && !selectedPackageNames.has(packageName)) {
continue;
}
if (isPluginExternalPublicationDeferred(packageJson)) {
continue;
}
if (packageJson.openclaw?.release?.publishToNpm !== true) {
continue;
}
@@ -45,6 +45,41 @@ function writeProviderPlugin(rootDir: string): void {
);
}
function writeBundledOpenCodeGoPlugin(bundledPluginsDir: string): void {
const pluginDir = path.join(bundledPluginsDir, "opencode-go");
fs.mkdirSync(pluginDir, { recursive: true });
fs.writeFileSync(path.join(pluginDir, "index.js"), "export default {};\n", "utf8");
fs.writeFileSync(
path.join(pluginDir, "package.json"),
JSON.stringify({
name: "@openclaw/opencode-go-provider",
version: "2026.8.1",
openclaw: {
extensions: ["./index.js"],
install: {
clawhubSpec: "clawhub:@openclaw/opencode-go-provider",
npmSpec: "@openclaw/opencode-go-provider",
defaultChoice: "npm",
},
build: { openclawVersion: "2026.8.1" },
release: { publishToClawHub: true, publishToNpm: true },
},
}),
"utf8",
);
fs.writeFileSync(
path.join(pluginDir, "openclaw.plugin.json"),
JSON.stringify({
id: "opencode-go",
activation: { onStartup: false },
enabledByDefault: true,
providers: ["opencode-go"],
configSchema: { type: "object", additionalProperties: false, properties: {} },
}),
"utf8",
);
}
describe("configured plugin install health for explicit load paths", () => {
it("does not install a provider plugin already present at a configured load path", async () => {
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-load-path-provider-"));
@@ -80,4 +115,53 @@ describe("configured plugin install health for explicit load paths", () => {
warnings: [],
});
});
it("discovers packaged OpenCode Go before configured-plugin repair", async () => {
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-bundled-opencode-go-"));
tempDirs.push(rootDir);
const homeDir = path.join(rootDir, "home");
const stateDir = path.join(rootDir, "state");
const configPath = path.join(stateDir, "openclaw.json");
const bundledPluginsDir = path.join(rootDir, "dist", "extensions");
fs.mkdirSync(homeDir, { recursive: true });
fs.mkdirSync(stateDir, { recursive: true });
writeBundledOpenCodeGoPlugin(bundledPluginsDir);
const cfg = {
auth: {
profiles: {
"opencode-go:default": { provider: "opencode-go", mode: "api_key" as const },
},
},
};
fs.writeFileSync(configPath, `${JSON.stringify(cfg)}\n`, "utf8");
const env = {
HOME: homeDir,
USERPROFILE: homeDir,
OPENCLAW_HOME: homeDir,
OPENCLAW_STATE_DIR: stateDir,
OPENCLAW_CONFIG_PATH: configPath,
OPENCLAW_BUNDLED_PLUGINS_DIR: bundledPluginsDir,
OPENCLAW_DISABLE_BUNDLED_SOURCE_OVERLAYS: "1",
OPENCLAW_TEST_TRUST_BUNDLED_PLUGINS_DIR: "1",
NPM_CONFIG_REGISTRY: "http://127.0.0.1:9",
npm_config_registry: "http://127.0.0.1:9",
XDG_CONFIG_HOME: path.join(rootDir, "xdg-config"),
VITEST: "true",
};
const snapshot = loadManifestMetadataSnapshot({ config: cfg, env });
expect(snapshot.plugins).toEqual(
expect.arrayContaining([expect.objectContaining({ id: "opencode-go", origin: "bundled" })]),
);
const issues = await detectConfiguredPluginInstallHealthIssues({ cfg, env });
expect(issues).toStrictEqual([]);
const repair = await repairMissingConfiguredPluginInstalls({ cfg, env });
expect(repair).toStrictEqual({
changes: [],
records: {},
warnings: [],
});
});
});
+22
View File
@@ -540,6 +540,28 @@ describe("collectPluginReleasePlan", () => {
});
describe("collectPublishablePluginPackages", () => {
it("defers explicitly bundled plugins from npm and ClawHub release plans", () => {
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
mkdirSync(join(repoDir, "extensions", "demo-plugin"), { recursive: true });
writePluginReadme(repoDir, "demo-plugin");
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
name: "@openclaw/demo-plugin",
version: "2026.4.10",
type: "module",
repository: { type: "git", url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL },
openclaw: {
extensions: ["./index.ts"],
...externalPluginContract("2026.4.10"),
build: { openclawVersion: "2026.4.10", bundledDist: true },
install: { npmSpec: "@openclaw/demo-plugin" },
release: { publishToClawHub: true, publishToNpm: true },
},
});
expect(collectPublishablePluginPackages(repoDir)).toStrictEqual([]);
expect(collectClawHubPublishablePluginPackages(repoDir)).toStrictEqual([]);
});
it("keeps publishable plugin dist trees out of the core npm package unless bundled", () => {
const corePackageRuntimePluginIds = new Set(["discord"]);
const rootPackage = JSON.parse(readFileSync("package.json", "utf8")) as {
@@ -356,7 +356,6 @@ describe("bundled plugin build entries", () => {
"mistral",
"novita",
"opencode",
"opencode-go",
"xiaomi",
]) {
expect(artifacts).not.toContain(`dist/extensions/${pluginId}/index.js`);
@@ -365,6 +364,18 @@ describe("bundled plugin build entries", () => {
}
});
it("keeps OpenCode Go bundled until its companion artifact is available", () => {
const artifacts = listBundledPluginPackArtifacts();
expect(artifacts).toEqual(
expect.arrayContaining([
"dist/extensions/opencode-go/index.js",
"dist/extensions/opencode-go/openclaw.plugin.json",
"dist/extensions/opencode-go/package.json",
]),
);
});
it("excludes the externalized Vydra provider from bundled artifacts", () => {
const artifacts = listBundledPluginPackArtifacts();