From 8a6bb1b80e943f03d30286c5a5cb2a4b72d9715a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 7 Apr 2026 08:23:36 +0100 Subject: [PATCH] refactor(gateway): isolate minimal test startup --- src/gateway/gateway.test.ts | 66 +++++++++++++++++++++++++++++++++++++ src/gateway/server.impl.ts | 48 ++++++++++++++++----------- 2 files changed, 94 insertions(+), 20 deletions(-) diff --git a/src/gateway/gateway.test.ts b/src/gateway/gateway.test.ts index 2cbf8d1a5a0..aa741e50507 100644 --- a/src/gateway/gateway.test.ts +++ b/src/gateway/gateway.test.ts @@ -426,4 +426,70 @@ module.exports = { } }, ); + + it( + "ignores env-driven plugin auto-enable in minimal gateway mode", + { timeout: GATEWAY_E2E_TIMEOUT_MS }, + async () => { + const envSnapshot = captureEnv([ + "HOME", + "OPENCLAW_STATE_DIR", + "OPENCLAW_CONFIG_PATH", + "OPENCLAW_GATEWAY_TOKEN", + "OPENCLAW_SKIP_CHANNELS", + "OPENCLAW_SKIP_GMAIL_WATCHER", + "OPENCLAW_SKIP_CRON", + "OPENCLAW_SKIP_CANVAS_HOST", + "OPENCLAW_SKIP_BROWSER_CONTROL_SERVER", + "OPENCLAW_SKIP_PROVIDERS", + "OPENCLAW_BUNDLED_PLUGINS_DIR", + "OPENCLAW_TEST_MINIMAL_GATEWAY", + "DISCORD_BOT_TOKEN", + ]); + + const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-minimal-gateway-home-")); + const configPath = path.join(tempHome, ".openclaw", "openclaw.json"); + const bundledPluginsDir = path.join(tempHome, "openclaw-test-no-bundled-extensions"); + process.env.HOME = tempHome; + process.env.OPENCLAW_STATE_DIR = path.join(tempHome, ".openclaw"); + process.env.OPENCLAW_CONFIG_PATH = configPath; + process.env.OPENCLAW_SKIP_CHANNELS = "1"; + process.env.OPENCLAW_SKIP_GMAIL_WATCHER = "1"; + process.env.OPENCLAW_SKIP_CRON = "1"; + process.env.OPENCLAW_SKIP_CANVAS_HOST = "1"; + process.env.OPENCLAW_SKIP_BROWSER_CONTROL_SERVER = "1"; + process.env.OPENCLAW_SKIP_PROVIDERS = "1"; + process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledPluginsDir; + process.env.OPENCLAW_TEST_MINIMAL_GATEWAY = "1"; + process.env.DISCORD_BOT_TOKEN = "discord-test-token"; + + const token = nextGatewayId("minimal-token"); + process.env.OPENCLAW_GATEWAY_TOKEN = token; + await fs.mkdir(path.dirname(configPath), { recursive: true }); + await fs.mkdir(bundledPluginsDir, { recursive: true }); + await fs.writeFile( + configPath, + `${JSON.stringify({ gateway: { auth: { mode: "token", token } } }, null, 2)}\n`, + ); + + const port = await getFreeGatewayPort(); + const server = await startGatewayServer(port, { + bind: "loopback", + auth: { mode: "token", token }, + controlUiEnabled: false, + }); + + try { + const parsed = JSON.parse(await fs.readFile(configPath, "utf8")) as { + channels?: Record; + plugins?: { entries?: Record }; + }; + expect(parsed.plugins?.entries?.discord).toBeUndefined(); + } finally { + await server.close({ reason: "minimal gateway auto-enable verify" }); + await fs.rm(tempHome, { recursive: true, force: true }); + envSnapshot.restore(); + } + }, + ); }); diff --git a/src/gateway/server.impl.ts b/src/gateway/server.impl.ts index 040493a22ff..2583f874bcc 100644 --- a/src/gateway/server.impl.ts +++ b/src/gateway/server.impl.ts @@ -438,7 +438,9 @@ export async function startGatewayServer( assertValidGatewayStartupConfigSnapshot(configSnapshot, { includeDoctorHint: true }); } - const autoEnable = applyPluginAutoEnable({ config: configSnapshot.config, env: process.env }); + const autoEnable = minimalTestGateway + ? { config: configSnapshot.config, changes: [] as string[] } + : applyPluginAutoEnable({ config: configSnapshot.config, env: process.env }); if (autoEnable.changes.length > 0) { try { await writeConfigFile(autoEnable.config); @@ -558,11 +560,13 @@ export async function startGatewayServer( ); // Unconditional startup migration: seed gateway.controlUi.allowedOrigins for existing // non-loopback installs that upgraded to v2026.2.26+ without required origins. - const controlUiSeed = await maybeSeedControlUiAllowedOriginsAtStartup({ - config: cfgAtStart, - writeConfig: writeConfigFile, - log, - }); + const controlUiSeed = minimalTestGateway + ? { config: cfgAtStart, persistedAllowedOriginsSeed: false } + : await maybeSeedControlUiAllowedOriginsAtStartup({ + config: cfgAtStart, + writeConfig: writeConfigFile, + log, + }); cfgAtStart = controlUiSeed.config; if (authBootstrap.persistedGeneratedToken || controlUiSeed.persistedAllowedOriginsSeed) { const startupSnapshot = await readConfigFileSnapshot(); @@ -575,21 +579,25 @@ export async function startGatewayServer( channels: startupRuntimeConfig.channels, } : cfgAtStart; - await runChannelPluginStartupMaintenance({ - cfg: startupMaintenanceConfig, - env: process.env, - log, - }); - await runStartupSessionMigration({ - cfg: cfgAtStart, - env: process.env, - log, - }); + if (!minimalTestGateway) { + await runChannelPluginStartupMaintenance({ + cfg: startupMaintenanceConfig, + env: process.env, + log, + }); + await runStartupSessionMigration({ + cfg: cfgAtStart, + env: process.env, + log, + }); + } initSubagentRegistry(); - const gatewayPluginConfigAtStart = applyPluginAutoEnable({ - config: cfgAtStart, - env: process.env, - }).config; + const gatewayPluginConfigAtStart = minimalTestGateway + ? cfgAtStart + : applyPluginAutoEnable({ + config: cfgAtStart, + env: process.env, + }).config; const defaultAgentId = resolveDefaultAgentId(gatewayPluginConfigAtStart); const defaultWorkspaceDir = resolveAgentWorkspaceDir(gatewayPluginConfigAtStart, defaultAgentId); const deferredConfiguredChannelPluginIds = minimalTestGateway