mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-24 08:21:39 +00:00
Gateway: resolve fallback plugin context lazily
This commit is contained in:
@@ -616,4 +616,31 @@ describe("loadGatewayPlugins", () => {
|
||||
| undefined;
|
||||
expect(dispatched?.marker).toBe("after-mutation");
|
||||
});
|
||||
|
||||
test("resolves fallback context lazily when a resolver is registered", async () => {
|
||||
const serverPlugins = serverPluginsModule;
|
||||
const runtime = await createSubagentRuntime(serverPlugins);
|
||||
let currentContext = createTestContext("before-resolver-update");
|
||||
|
||||
serverPlugins.setFallbackGatewayContextResolver(() => currentContext);
|
||||
await runtime.run({ sessionKey: "s-4", message: "before resolver update" });
|
||||
expect(getLastDispatchedContext()).toBe(currentContext);
|
||||
|
||||
currentContext = createTestContext("after-resolver-update");
|
||||
await runtime.run({ sessionKey: "s-4", message: "after resolver update" });
|
||||
expect(getLastDispatchedContext()).toBe(currentContext);
|
||||
});
|
||||
|
||||
test("prefers resolver output over an older fallback context snapshot", async () => {
|
||||
const serverPlugins = serverPluginsModule;
|
||||
const runtime = await createSubagentRuntime(serverPlugins);
|
||||
const staleContext = createTestContext("stale-snapshot");
|
||||
const freshContext = createTestContext("fresh-resolver");
|
||||
|
||||
serverPlugins.setFallbackGatewayContext(staleContext);
|
||||
serverPlugins.setFallbackGatewayContextResolver(() => freshContext);
|
||||
|
||||
await runtime.run({ sessionKey: "s-5", message: "prefer resolver" });
|
||||
expect(getLastDispatchedContext()).toBe(freshContext);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,16 +32,28 @@ const FALLBACK_GATEWAY_CONTEXT_STATE_KEY: unique symbol = Symbol.for(
|
||||
|
||||
type FallbackGatewayContextState = {
|
||||
context: GatewayRequestContext | undefined;
|
||||
resolveContext: (() => GatewayRequestContext | undefined) | undefined;
|
||||
};
|
||||
|
||||
const fallbackGatewayContextState = resolveGlobalSingleton<FallbackGatewayContextState>(
|
||||
FALLBACK_GATEWAY_CONTEXT_STATE_KEY,
|
||||
() => ({ context: undefined }),
|
||||
() => ({ context: undefined, resolveContext: undefined }),
|
||||
);
|
||||
|
||||
export function setFallbackGatewayContext(ctx: GatewayRequestContext): void {
|
||||
// TODO: This startup snapshot can become stale if runtime config/context changes.
|
||||
fallbackGatewayContextState.context = ctx;
|
||||
fallbackGatewayContextState.resolveContext = undefined;
|
||||
}
|
||||
|
||||
export function setFallbackGatewayContextResolver(
|
||||
resolveContext: () => GatewayRequestContext | undefined,
|
||||
): void {
|
||||
fallbackGatewayContextState.resolveContext = resolveContext;
|
||||
}
|
||||
|
||||
function getFallbackGatewayContext(): GatewayRequestContext | undefined {
|
||||
const resolved = fallbackGatewayContextState.resolveContext?.();
|
||||
return resolved ?? fallbackGatewayContextState.context;
|
||||
}
|
||||
|
||||
type PluginSubagentOverridePolicy = {
|
||||
@@ -238,7 +250,7 @@ async function dispatchGatewayMethod<T>(
|
||||
},
|
||||
): Promise<T> {
|
||||
const scope = getPluginRuntimeGatewayRequestScope();
|
||||
const context = scope?.context ?? fallbackGatewayContextState.context;
|
||||
const context = scope?.context ?? getFallbackGatewayContext();
|
||||
const isWebchatConnect = scope?.isWebchatConnect ?? (() => false);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
|
||||
@@ -103,7 +103,7 @@ import { createSecretsHandlers } from "./server-methods/secrets.js";
|
||||
import { hasConnectedMobileNode } from "./server-mobile-nodes.js";
|
||||
import { loadGatewayModelCatalog } from "./server-model-catalog.js";
|
||||
import { createNodeSubscriptionManager } from "./server-node-subscriptions.js";
|
||||
import { loadGatewayPlugins, setFallbackGatewayContext } from "./server-plugins.js";
|
||||
import { loadGatewayPlugins, setFallbackGatewayContextResolver } from "./server-plugins.js";
|
||||
import { createGatewayReloadHandlers } from "./server-reload-handlers.js";
|
||||
import { resolveGatewayRuntimeConfig } from "./server-runtime-config.js";
|
||||
import { createGatewayRuntimeState } from "./server-runtime-state.js";
|
||||
@@ -1126,10 +1126,10 @@ export async function startGatewayServer(
|
||||
broadcastVoiceWakeChanged,
|
||||
};
|
||||
|
||||
// Store the gateway context as a fallback for plugin subagent dispatch
|
||||
// in non-WS paths (Telegram polling, WhatsApp, etc.) where no per-request
|
||||
// scope is set via AsyncLocalStorage.
|
||||
setFallbackGatewayContext(gatewayRequestContext);
|
||||
// Register a lazy fallback for plugin subagent dispatch in non-WS paths
|
||||
// (Telegram polling, WhatsApp, etc.) so later runtime swaps can expose the
|
||||
// current gateway context without relying on a startup snapshot.
|
||||
setFallbackGatewayContextResolver(() => gatewayRequestContext);
|
||||
|
||||
attachGatewayWsHandlers({
|
||||
wss,
|
||||
|
||||
Reference in New Issue
Block a user