fix: keep minimal gateway channel registry live (#53944) (thanks @affsantos)

This commit is contained in:
Ayaan Zaidi
2026-03-25 09:59:15 +05:30
committed by Peter Steinberger
parent 5eb6fdca6f
commit 03dc287a29
3 changed files with 67 additions and 2 deletions

View File

@@ -66,6 +66,7 @@ export async function createGatewayRuntimeState(params: {
hooksConfig: () => HooksConfigResolved | null;
getHookClientIpConfig: () => HookClientIpConfig;
pluginRegistry: PluginRegistry;
pinChannelRegistry?: boolean;
deps: CliDeps;
canvasRuntime: RuntimeEnv;
canvasHostEnabled: boolean;
@@ -101,7 +102,11 @@ export async function createGatewayRuntimeState(params: {
toolEventRecipients: ReturnType<typeof createToolEventRecipientRegistry>;
}> {
pinActivePluginHttpRouteRegistry(params.pluginRegistry);
pinActivePluginChannelRegistry(params.pluginRegistry);
if (params.pinChannelRegistry !== false) {
pinActivePluginChannelRegistry(params.pluginRegistry);
} else {
releasePinnedPluginChannelRegistry();
}
try {
let canvasHost: CanvasHostHandler | null = null;
if (params.canvasHostEnabled) {

View File

@@ -53,7 +53,7 @@ import { createSubsystemLogger, runtimeForLogger } from "../logging/subsystem.js
import { resolveConfiguredDeferredChannelPluginIds } from "../plugins/channel-plugin-ids.js";
import { getGlobalHookRunner, runGlobalGatewayStopSafely } from "../plugins/hook-runner-global.js";
import { createEmptyPluginRegistry } from "../plugins/registry.js";
import { pinActivePluginChannelRegistry } from "../plugins/runtime.js";
import { pinActivePluginChannelRegistry, setActivePluginRegistry } from "../plugins/runtime.js";
import { createPluginRuntime } from "../plugins/runtime/index.js";
import type { PluginServicesHandle } from "../plugins/services.js";
import { getTotalQueueSize } from "../process/command-queue.js";
@@ -570,6 +570,8 @@ export async function startGatewayServer(
baseMethods,
preferSetupRuntimeForChannelPlugins: deferredConfiguredChannelPluginIds.length > 0,
}));
} else {
setActivePluginRegistry(emptyPluginRegistry);
}
const channelLogs = Object.fromEntries(
listChannelPlugins().map((plugin) => [plugin.id, logChannels.child(plugin.id)]),
@@ -713,6 +715,7 @@ export async function startGatewayServer(
hooksConfig: () => hooksConfig,
getHookClientIpConfig: () => hookClientIpConfig,
pluginRegistry,
pinChannelRegistry: !minimalTestGateway,
deps,
canvasRuntime,
canvasHostEnabled,

View File

@@ -0,0 +1,57 @@
import { afterEach, expect, test } from "vitest";
import { getChannelPlugin } from "../channels/plugins/index.js";
import {
getActivePluginRegistry,
resetPluginRuntimeStateForTest,
setActivePluginRegistry,
} from "../plugins/runtime.js";
import { createOutboundTestPlugin } from "../test-utils/channel-plugins.js";
import { createRegistry } from "./server.e2e-registry-helpers.js";
import { getFreePort, installGatewayTestHooks, startGatewayServer } from "./test-helpers.js";
installGatewayTestHooks({ scope: "suite" });
const whatsappOutbound = {
deliveryMode: "direct" as const,
sendText: async () => ({ channel: "whatsapp", messageId: "text-1" }),
sendMedia: async () => ({ channel: "whatsapp", messageId: "media-1" }),
};
const replacementPlugin = createOutboundTestPlugin({
id: "whatsapp",
outbound: whatsappOutbound,
label: "WhatsApp Replacement",
});
const replacementRegistry = createRegistry([
{
pluginId: "whatsapp",
source: "test-replacement",
plugin: replacementPlugin,
},
]);
afterEach(() => {
resetPluginRuntimeStateForTest();
});
test("minimal gateway tracks later channel registry updates", async () => {
const prevRegistry = getActivePluginRegistry();
const prevVitest = process.env.VITEST;
resetPluginRuntimeStateForTest();
process.env.VITEST = "1";
const port = await getFreePort();
const server = await startGatewayServer(port);
try {
expect(getChannelPlugin("whatsapp")).not.toBe(replacementPlugin);
setActivePluginRegistry(replacementRegistry);
expect(getChannelPlugin("whatsapp")).toBe(replacementPlugin);
} finally {
await server.close();
process.env.VITEST = prevVitest;
resetPluginRuntimeStateForTest();
if (prevRegistry) {
setActivePluginRegistry(prevRegistry);
}
}
});