mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 01:50:24 +00:00
fix(outbound): preserve channel registry during provider snapshots
This commit is contained in:
@@ -18,7 +18,10 @@ import {
|
||||
pickGatewaySelfPresence,
|
||||
resolveGatewayProbeAuthResolution,
|
||||
} from "./status.gateway-probe.js";
|
||||
import type { buildChannelsTable, collectChannelStatusIssues } from "./status.scan.runtime.js";
|
||||
import type {
|
||||
buildChannelsTable as buildChannelsTableFn,
|
||||
collectChannelStatusIssues as collectChannelStatusIssuesFn,
|
||||
} from "./status.scan.runtime.js";
|
||||
import { getStatusSummary } from "./status.summary.js";
|
||||
import { getUpdateCheckResult } from "./status.update.js";
|
||||
|
||||
@@ -164,9 +167,9 @@ export type StatusScanResult = {
|
||||
gatewayProbe: Awaited<ReturnType<typeof probeGateway>> | null;
|
||||
gatewayReachable: boolean;
|
||||
gatewaySelf: ReturnType<typeof pickGatewaySelfPresence>;
|
||||
channelIssues: ChannelStatusIssues;
|
||||
channelIssues: ReturnType<typeof collectChannelStatusIssuesFn>;
|
||||
agentStatus: Awaited<ReturnType<typeof getAgentLocalStatuses>>;
|
||||
channels: ChannelsTable;
|
||||
channels: Awaited<ReturnType<typeof buildChannelsTableFn>>;
|
||||
summary: Awaited<ReturnType<typeof getStatusSummary>>;
|
||||
memory: MemoryStatusSnapshot | null;
|
||||
memoryPlugin: MemoryPluginStatus;
|
||||
|
||||
@@ -133,6 +133,23 @@ describe("outbound channel resolution", () => {
|
||||
expect(loadOpenClawPluginsMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("bootstraps when the active registry has other channels but not the requested one", async () => {
|
||||
const plugin = { id: "telegram" };
|
||||
getChannelPluginMock.mockReturnValueOnce(undefined).mockReturnValueOnce(plugin);
|
||||
getActivePluginRegistryMock.mockReturnValue({
|
||||
channels: [{ plugin: { id: "discord" } }],
|
||||
});
|
||||
const channelResolution = await importChannelResolution("bootstrap-missing-target");
|
||||
|
||||
expect(
|
||||
channelResolution.resolveOutboundChannelPlugin({
|
||||
channel: "telegram",
|
||||
cfg: { channels: {} } as never,
|
||||
}),
|
||||
).toBe(plugin);
|
||||
expect(loadOpenClawPluginsMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("retries bootstrap after a transient load failure", async () => {
|
||||
getChannelPluginMock.mockReturnValue(undefined);
|
||||
loadOpenClawPluginsMock.mockImplementationOnce(() => {
|
||||
|
||||
@@ -33,7 +33,10 @@ function maybeBootstrapChannelPlugin(params: {
|
||||
}
|
||||
|
||||
const activeRegistry = getActivePluginRegistry();
|
||||
if ((activeRegistry?.channels?.length ?? 0) > 0) {
|
||||
const activeHasRequestedChannel = activeRegistry?.channels?.some(
|
||||
(entry) => entry?.plugin?.id === params.channel,
|
||||
);
|
||||
if (activeHasRequestedChannel) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import { createSubsystemLogger } from "../../logging/subsystem.js";
|
||||
import { getAgentScopedMediaLocalRoots } from "../../media/local-roots.js";
|
||||
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
|
||||
import { throwIfAborted } from "./abort.js";
|
||||
import { resolveOutboundChannelPlugin } from "./channel-resolution.js";
|
||||
import { ackDelivery, enqueueDelivery, failDelivery } from "./delivery-queue.js";
|
||||
import type { OutboundIdentity } from "./identity.js";
|
||||
import type { DeliveryMirror } from "./mirror.js";
|
||||
@@ -113,6 +114,13 @@ type ChannelHandlerParams = {
|
||||
|
||||
// Channel docking: outbound delivery delegates to plugin.outbound adapters.
|
||||
async function createChannelHandler(params: ChannelHandlerParams): Promise<ChannelHandler> {
|
||||
// Recover channel plugins the same way target resolution does so direct cron
|
||||
// delivery still works when a prior test or lazy path left the active plugin
|
||||
// registry empty.
|
||||
resolveOutboundChannelPlugin({
|
||||
channel: params.channel,
|
||||
cfg: params.cfg,
|
||||
});
|
||||
const outbound = await loadChannelOutboundAdapter(params.channel);
|
||||
const handler = createPluginHandler({ ...params, outbound });
|
||||
if (!handler) {
|
||||
|
||||
@@ -38,6 +38,8 @@ describe("resolvePluginProviders", () => {
|
||||
expect.objectContaining({
|
||||
workspaceDir: "/workspace/explicit",
|
||||
env,
|
||||
cache: false,
|
||||
activate: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -59,6 +61,8 @@ describe("resolvePluginProviders", () => {
|
||||
allow: expect.arrayContaining(["openrouter", "google", "kilocode", "moonshot"]),
|
||||
}),
|
||||
}),
|
||||
cache: false,
|
||||
activate: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -76,6 +80,8 @@ describe("resolvePluginProviders", () => {
|
||||
allow: expect.arrayContaining(["openai", "moonshot", "zai"]),
|
||||
}),
|
||||
}),
|
||||
cache: false,
|
||||
activate: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -35,6 +35,7 @@ const BUNDLED_PROVIDER_ALLOWLIST_COMPAT_PLUGIN_IDS = [
|
||||
"venice",
|
||||
"vercel-ai-gateway",
|
||||
"volcengine",
|
||||
"xai",
|
||||
"vllm",
|
||||
"xiaomi",
|
||||
"zai",
|
||||
@@ -142,8 +143,8 @@ export function resolvePluginProviders(params: {
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
onlyPluginIds: params.onlyPluginIds,
|
||||
activate: params.activate,
|
||||
cache: params.cache,
|
||||
cache: params.cache ?? false,
|
||||
activate: params.activate ?? false,
|
||||
logger: createPluginLoaderLogger(log),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user