From 6f139822127a227cf7c798cb78ca7534336c4f3a Mon Sep 17 00:00:00 2001 From: Shakker Date: Tue, 28 Apr 2026 03:57:56 +0100 Subject: [PATCH] test: assert bundled startup plan metadata --- src/plugins/bundled-plugin-metadata.test.ts | 95 +++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/plugins/bundled-plugin-metadata.test.ts b/src/plugins/bundled-plugin-metadata.test.ts index 3f460e9d4e1..9b80a107ac7 100644 --- a/src/plugins/bundled-plugin-metadata.test.ts +++ b/src/plugins/bundled-plugin-metadata.test.ts @@ -9,12 +9,15 @@ import { resolveBundledPluginGeneratedPath, resolveBundledPluginRepoEntryPath, } from "./bundled-plugin-metadata.js"; +import { resolveGatewayStartupPluginIdsFromRegistry } from "./gateway-startup-plugin-ids.js"; import { createGeneratedPluginTempRoot, installGeneratedPluginTempRootCleanup, pluginTestRepoRoot as repoRoot, writeJson, } from "./generated-plugin-test-helpers.js"; +import type { InstalledPluginIndex, InstalledPluginIndexRecord } from "./installed-plugin-index.js"; +import type { PluginManifestRecord, PluginManifestRegistry } from "./manifest-registry.js"; import { getPackageManifestMetadata, loadPluginManifest, @@ -45,6 +48,15 @@ const EXPECTED_BUNDLED_STARTUP_PLUGIN_IDS = [ "voice-call", "webhooks", ] as const; +const EXPECTED_EMPTY_CONFIG_GATEWAY_STARTUP_PLUGIN_IDS = [ + "acpx", + "bonjour", + "browser", + "device-pair", + "memory-core", + "phone-control", + "talk-voice", +] as const; installGeneratedPluginTempRootCleanup(); @@ -140,6 +152,51 @@ function collectRepoBundledChannelConfigsForTest(dirName: string) { }); } +function hasPluginKind(record: PluginManifestRecord, kind: string): boolean { + return Array.isArray(record.kind) ? record.kind.includes(kind as never) : record.kind === kind; +} + +function createInstalledPluginRecordForManifest( + record: PluginManifestRecord, +): InstalledPluginIndexRecord { + return { + pluginId: record.id, + manifestPath: record.manifestPath, + manifestHash: `test-${record.id}`, + source: record.source, + rootDir: record.rootDir, + origin: record.origin, + enabled: record.enabledByDefault === true, + ...(record.enabledByDefault === true ? { enabledByDefault: true } : {}), + startup: { + sidecar: record.activation?.onStartup === true, + memory: hasPluginKind(record, "memory"), + deferConfiguredChannelFullLoadUntilAfterListen: + record.startupDeferConfiguredChannelFullLoadUntilAfterListen === true, + agentHarnesses: [ + ...new Set([...(record.activation?.onAgentHarnesses ?? []), ...record.cliBackends]), + ].toSorted((left, right) => left.localeCompare(right)), + }, + compat: [], + }; +} + +function createInstalledPluginIndexForManifests( + manifestRegistry: PluginManifestRegistry, +): InstalledPluginIndex { + return { + version: 1, + hostContractVersion: "test", + compatRegistryVersion: "test", + migrationVersion: 1, + policyHash: "test", + generatedAtMs: 0, + installRecords: {}, + plugins: manifestRegistry.plugins.map(createInstalledPluginRecordForManifest), + diagnostics: [], + }; +} + describe("bundled plugin metadata", () => { it( "matches the runtime metadata snapshot", @@ -323,6 +380,44 @@ describe("bundled plugin metadata", () => { ); }); + it("keeps empty-config Gateway startup narrower than declared startup sidecars", () => { + const manifestRegistry = { + plugins: listRepoBundledPluginManifests().map(({ manifest, dirName }) => ({ + id: manifest.id, + name: manifest.name, + description: manifest.description, + version: manifest.version, + enabledByDefault: manifest.enabledByDefault === true ? true : undefined, + kind: manifest.kind, + channels: manifest.channels ?? [], + providers: manifest.providers ?? [], + cliBackends: manifest.cliBackends ?? [], + syntheticAuthRefs: manifest.syntheticAuthRefs ?? [], + nonSecretAuthMarkers: manifest.nonSecretAuthMarkers ?? [], + skills: manifest.skills ?? [], + origin: "bundled", + rootDir: path.join(repoRoot, "extensions", dirName), + source: path.join(repoRoot, "extensions", dirName, "index.ts"), + manifestPath: path.join(repoRoot, "extensions", dirName, "openclaw.plugin.json"), + activation: manifest.activation, + setup: manifest.setup, + hooks: [], + contracts: manifest.contracts, + })), + diagnostics: [], + } satisfies PluginManifestRegistry; + const index = createInstalledPluginIndexForManifests(manifestRegistry); + + expect( + resolveGatewayStartupPluginIdsFromRegistry({ + config: {}, + env: process.env, + index, + manifestRegistry, + }), + ).toEqual(EXPECTED_EMPTY_CONFIG_GATEWAY_STARTUP_PLUGIN_IDS); + }); + it("prefers built generated paths when present and falls back to source paths", () => { const tempRoot = createGeneratedPluginTempRoot("openclaw-bundled-plugin-metadata-"); const pluginRoot = path.join(tempRoot, "extensions", "plugin");