mirror of https://github.com/openclaw/openclaw.git
fix(channels): use pinned channel registry for outbound adapter resolution
loadChannelOutboundAdapter (via createChannelRegistryLoader) was reading from getActivePluginRegistry() — the unpinned active registry that gets replaced whenever loadOpenClawPlugins() runs (config schema reads, plugin status queries, tool listings, etc.). After replacement, the active registry may omit channel entries or carry them in setup mode without outbound adapters, causing: Outbound not configured for channel: telegram The channel inbound path already uses the pinned registry (getActivePluginChannelRegistry) which is frozen at gateway startup and survives all subsequent registry replacements. This commit aligns the outbound path to use the same pinned surface. Adds a regression test that pins a registry with a telegram outbound adapter, replaces the active registry with an empty one, then asserts loadChannelOutboundAdapter still resolves the adapter. Fixes #54745 Fixes #54013
This commit is contained in:
parent
b29e180ef4
commit
bc9c074b2c
|
|
@ -1,5 +1,5 @@
|
|||
import type { PluginChannelRegistration, PluginRegistry } from "../../plugins/registry.js";
|
||||
import { getActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
import { getActivePluginChannelRegistry } from "../../plugins/runtime.js";
|
||||
import type { ChannelId } from "./types.js";
|
||||
|
||||
type ChannelRegistryValueResolver<TValue> = (
|
||||
|
|
@ -13,7 +13,7 @@ export function createChannelRegistryLoader<TValue>(
|
|||
let lastRegistry: PluginRegistry | null = null;
|
||||
|
||||
return async (id: ChannelId): Promise<TValue | undefined> => {
|
||||
const registry = getActivePluginRegistry();
|
||||
const registry = getActivePluginChannelRegistry();
|
||||
if (registry !== lastRegistry) {
|
||||
cache.clear();
|
||||
lastRegistry = registry;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { loadChannelOutboundAdapter } from "../channels/plugins/outbound/load.js";
|
||||
import { getChannelPlugin } from "../channels/plugins/registry.js";
|
||||
import { createEmptyPluginRegistry } from "./registry-empty.js";
|
||||
import {
|
||||
|
|
@ -173,4 +174,26 @@ describe("channel registry pinning", () => {
|
|||
freshRegistry: fresh,
|
||||
});
|
||||
});
|
||||
|
||||
it("loadChannelOutboundAdapter resolves from pinned registry after active registry replacement", async () => {
|
||||
const outboundAdapter = { send: async () => ({ messageId: "1" }) };
|
||||
const startup = createEmptyPluginRegistry();
|
||||
startup.channels = [
|
||||
{
|
||||
pluginId: "telegram",
|
||||
plugin: { id: "telegram", meta: {}, outbound: outboundAdapter },
|
||||
source: "test",
|
||||
},
|
||||
] as never;
|
||||
setActivePluginRegistry(startup);
|
||||
pinActivePluginChannelRegistry(startup);
|
||||
|
||||
// Simulate a post-boot registry replacement (e.g. config-schema load, plugin status query).
|
||||
const replacement = createEmptyPluginRegistry();
|
||||
setActivePluginRegistry(replacement);
|
||||
|
||||
// The outbound loader must still find the telegram adapter from the pinned registry.
|
||||
const adapter = await loadChannelOutboundAdapter("telegram");
|
||||
expect(adapter).toBe(outboundAdapter);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue