fix(regression): auto-enable channel status state

This commit is contained in:
Tak Hoffman
2026-03-27 23:56:18 -05:00
parent dc87ffa46d
commit 0bcf076901
2 changed files with 122 additions and 1 deletions

View File

@@ -0,0 +1,117 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
loadConfig: vi.fn(),
applyPluginAutoEnable: vi.fn(),
listChannelPlugins: vi.fn(),
buildChannelUiCatalog: vi.fn(),
buildChannelAccountSnapshot: vi.fn(),
getChannelActivity: vi.fn(),
}));
vi.mock("../../config/config.js", async () => {
const actual =
await vi.importActual<typeof import("../../config/config.js")>("../../config/config.js");
return {
...actual,
loadConfig: mocks.loadConfig,
};
});
vi.mock("../../config/plugin-auto-enable.js", () => ({
applyPluginAutoEnable: mocks.applyPluginAutoEnable,
}));
vi.mock("../../channels/plugins/index.js", () => ({
listChannelPlugins: mocks.listChannelPlugins,
getChannelPlugin: vi.fn(),
normalizeChannelId: (value: string) => value,
}));
vi.mock("../../channels/plugins/catalog.js", () => ({
buildChannelUiCatalog: mocks.buildChannelUiCatalog,
}));
vi.mock("../../channels/plugins/status.js", () => ({
buildChannelAccountSnapshot: mocks.buildChannelAccountSnapshot,
}));
vi.mock("../../infra/channel-activity.js", () => ({
getChannelActivity: mocks.getChannelActivity,
}));
import { channelsHandlers } from "./channels.js";
describe("channelsHandlers channels.status", () => {
beforeEach(() => {
vi.clearAllMocks();
mocks.loadConfig.mockReturnValue({});
mocks.applyPluginAutoEnable.mockImplementation(({ config }) => ({ config, changes: [] }));
mocks.buildChannelUiCatalog.mockReturnValue({
order: ["whatsapp"],
labels: { whatsapp: "WhatsApp" },
detailLabels: { whatsapp: "WhatsApp" },
systemImages: { whatsapp: undefined },
entries: { whatsapp: { id: "whatsapp" } },
});
mocks.buildChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: true,
});
mocks.getChannelActivity.mockReturnValue({
inboundAt: null,
outboundAt: null,
});
mocks.listChannelPlugins.mockReturnValue([
{
id: "whatsapp",
config: {
listAccountIds: () => ["default"],
resolveAccount: () => ({}),
isEnabled: () => true,
isConfigured: async (_account: unknown, cfg: { autoEnabled?: boolean }) =>
Boolean(cfg.autoEnabled),
},
},
]);
});
it("uses the auto-enabled config snapshot for channel account state", async () => {
const autoEnabledConfig = { autoEnabled: true };
mocks.applyPluginAutoEnable.mockReturnValue({ config: autoEnabledConfig, changes: [] });
const respond = vi.fn();
await channelsHandlers["channels.status"]({
params: { probe: false, timeoutMs: 2000 } as never,
respond,
context: {
getRuntimeSnapshot: () => ({
channels: {},
channelAccounts: {},
}),
} as never,
});
expect(mocks.applyPluginAutoEnable).toHaveBeenCalledWith({
config: {},
env: process.env,
});
expect(mocks.buildChannelAccountSnapshot).toHaveBeenCalledWith(
expect.objectContaining({
cfg: autoEnabledConfig,
accountId: "default",
}),
);
expect(respond).toHaveBeenCalledWith(
true,
expect.objectContaining({
channels: {
whatsapp: expect.objectContaining({
configured: true,
}),
},
}),
undefined,
);
});
});

View File

@@ -10,6 +10,7 @@ import { buildChannelAccountSnapshot } from "../../channels/plugins/status.js";
import type { ChannelAccountSnapshot, ChannelPlugin } from "../../channels/plugins/types.js";
import type { OpenClawConfig } from "../../config/config.js";
import { loadConfig, readConfigFileSnapshot } from "../../config/config.js";
import { applyPluginAutoEnable } from "../../config/plugin-auto-enable.js";
import { getChannelActivity } from "../../infra/channel-activity.js";
import { DEFAULT_ACCOUNT_ID } from "../../routing/session-key.js";
import { defaultRuntime } from "../../runtime.js";
@@ -82,7 +83,10 @@ export const channelsHandlers: GatewayRequestHandlers = {
const probe = (params as { probe?: boolean }).probe === true;
const timeoutMsRaw = (params as { timeoutMs?: unknown }).timeoutMs;
const timeoutMs = typeof timeoutMsRaw === "number" ? Math.max(1000, timeoutMsRaw) : 10_000;
const cfg = loadConfig();
const cfg = applyPluginAutoEnable({
config: loadConfig(),
env: process.env,
}).config;
const runtime = context.getRuntimeSnapshot();
const plugins = listChannelPlugins();
const pluginMap = new Map<ChannelId, ChannelPlugin>(