Skip to content

Commit 59bcac4

Browse files
committed
fix: gate setup-only plugin side effects
1 parent ae6ee73 commit 59bcac4

14 files changed

Lines changed: 106 additions & 9 deletions

File tree

extensions/discord/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ const plugin = {
1212
register(api: OpenClawPluginApi) {
1313
setDiscordRuntime(api.runtime);
1414
api.registerChannel({ plugin: discordPlugin });
15+
if (api.registrationMode !== "full") {
16+
return;
17+
}
1518
registerDiscordSubagentHooks(api);
1619
},
1720
};

extensions/discord/src/monitor/provider.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ const {
4646
resolveDiscordAllowlistConfigMock,
4747
resolveNativeCommandsEnabledMock,
4848
resolveNativeSkillsEnabledMock,
49+
shouldLogVerboseMock,
4950
voiceRuntimeModuleLoadedMock,
5051
} = vi.hoisted(() => {
5152
const createdBindingManagers: Array<{ stop: ReturnType<typeof vi.fn> }> = [];
53+
const shouldLogVerboseMock = vi.fn(() => false);
5254
return {
5355
clientHandleDeployRequestMock: vi.fn(async () => undefined),
5456
clientConstructorOptionsMock: vi.fn(),
@@ -110,6 +112,7 @@ const {
110112
})),
111113
resolveNativeCommandsEnabledMock: vi.fn(() => true),
112114
resolveNativeSkillsEnabledMock: vi.fn(() => false),
115+
shouldLogVerboseMock,
113116
voiceRuntimeModuleLoadedMock: vi.fn(),
114117
};
115118
});
@@ -211,7 +214,7 @@ vi.mock("../../../../src/config/config.js", () => ({
211214
vi.mock("../../../../src/globals.js", () => ({
212215
danger: (v: string) => v,
213216
logVerbose: vi.fn(),
214-
shouldLogVerbose: () => false,
217+
shouldLogVerbose: shouldLogVerboseMock,
215218
warn: (v: string) => v,
216219
}));
217220

@@ -435,6 +438,7 @@ describe("monitorDiscordProvider", () => {
435438
});
436439
resolveNativeCommandsEnabledMock.mockClear().mockReturnValue(true);
437440
resolveNativeSkillsEnabledMock.mockClear().mockReturnValue(false);
441+
shouldLogVerboseMock.mockClear().mockReturnValue(false);
438442
voiceRuntimeModuleLoadedMock.mockClear();
439443
});
440444

@@ -842,6 +846,7 @@ describe("monitorDiscordProvider", () => {
842846
emitter.emit("debug", "WebSocket connection opened");
843847
return { id: "bot-1", username: "Molty" };
844848
});
849+
shouldLogVerboseMock.mockReturnValue(true);
845850

846851
await monitorDiscordProvider({
847852
config: baseConfig(),
@@ -861,4 +866,17 @@ describe("monitorDiscordProvider", () => {
861866
),
862867
).toBe(true);
863868
});
869+
870+
it("keeps Discord startup chatter quiet by default", async () => {
871+
const { monitorDiscordProvider } = await import("./provider.js");
872+
const runtime = baseRuntime();
873+
874+
await monitorDiscordProvider({
875+
config: baseConfig(),
876+
runtime,
877+
});
878+
879+
const messages = vi.mocked(runtime.log).mock.calls.map((call) => String(call[0]));
880+
expect(messages.some((msg) => msg.includes("discord startup ["))).toBe(false);
881+
});
864882
});

extensions/discord/src/monitor/provider.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -273,14 +273,18 @@ async function deployDiscordCommands(params: {
273273
body === undefined
274274
? undefined
275275
: Buffer.byteLength(typeof body === "string" ? body : JSON.stringify(body), "utf8");
276-
params.runtime.log?.(
277-
`discord startup [${accountId}] deploy-rest:put:start ${Math.max(0, Date.now() - startupStartedAt)}ms path=${path}${typeof commandCount === "number" ? ` commands=${commandCount}` : ""}${typeof bodyBytes === "number" ? ` bytes=${bodyBytes}` : ""}`,
278-
);
279-
try {
280-
const result = await originalPut(path, data, query);
276+
if (shouldLogVerbose()) {
281277
params.runtime.log?.(
282-
`discord startup [${accountId}] deploy-rest:put:done ${Math.max(0, Date.now() - startupStartedAt)}ms path=${path} requestMs=${Date.now() - startedAt}`,
278+
`discord startup [${accountId}] deploy-rest:put:start ${Math.max(0, Date.now() - startupStartedAt)}ms path=${path}${typeof commandCount === "number" ? ` commands=${commandCount}` : ""}${typeof bodyBytes === "number" ? ` bytes=${bodyBytes}` : ""}`,
283279
);
280+
}
281+
try {
282+
const result = await originalPut(path, data, query);
283+
if (shouldLogVerbose()) {
284+
params.runtime.log?.(
285+
`discord startup [${accountId}] deploy-rest:put:done ${Math.max(0, Date.now() - startupStartedAt)}ms path=${path} requestMs=${Date.now() - startedAt}`,
286+
);
287+
}
284288
return result;
285289
} catch (err) {
286290
params.runtime.error?.(
@@ -359,6 +363,9 @@ function logDiscordStartupPhase(params: {
359363
gateway?: GatewayPlugin;
360364
details?: string;
361365
}) {
366+
if (!shouldLogVerbose()) {
367+
return;
368+
}
362369
const elapsedMs = Math.max(0, Date.now() - params.startAt);
363370
const suffix = [params.details, formatDiscordStartupGatewayState(params.gateway)]
364371
.filter((value): value is string => Boolean(value))
@@ -768,6 +775,9 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
768775
const lifecycleGateway = client.getPlugin<GatewayPlugin>("gateway");
769776
earlyGatewayEmitter = getDiscordGatewayEmitter(lifecycleGateway);
770777
onEarlyGatewayDebug = (msg: unknown) => {
778+
if (!shouldLogVerbose()) {
779+
return;
780+
}
771781
runtime.log?.(
772782
`discord startup [${account.accountId}] gateway-debug ${Math.max(0, Date.now() - startupStartedAt)}ms ${String(msg)}`,
773783
);

extensions/feishu/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ const plugin = {
5454
register(api: OpenClawPluginApi) {
5555
setFeishuRuntime(api.runtime);
5656
api.registerChannel({ plugin: feishuPlugin });
57+
if (api.registrationMode !== "full") {
58+
return;
59+
}
5760
registerFeishuSubagentHooks(api);
5861
registerFeishuDocTools(api);
5962
registerFeishuChatTools(api);

extensions/line/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ const plugin = {
1212
register(api: OpenClawPluginApi) {
1313
setLineRuntime(api.runtime);
1414
api.registerChannel({ plugin: linePlugin });
15+
if (api.registrationMode !== "full") {
16+
return;
17+
}
1518
registerLineCardCommand(api);
1619
},
1720
};

extensions/lobster/src/lobster-tool.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function fakeApi(overrides: Partial<OpenClawPluginApi> = {}): OpenClawPluginApi
3232
id: "lobster",
3333
name: "lobster",
3434
source: "test",
35+
registrationMode: "full",
3536
config: {},
3637
pluginConfig: {},
3738
// oxlint-disable-next-line typescript/no-explicit-any
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/mattermost";
2+
import { describe, expect, it, vi } from "vitest";
3+
import { createTestPluginApi } from "../test-utils/plugin-api.js";
4+
import plugin from "./index.js";
5+
6+
function createApi(
7+
registrationMode: OpenClawPluginApi["registrationMode"],
8+
registerHttpRoute = vi.fn(),
9+
): OpenClawPluginApi {
10+
return createTestPluginApi({
11+
id: "mattermost",
12+
name: "Mattermost",
13+
source: "test",
14+
config: {},
15+
runtime: {} as OpenClawPluginApi["runtime"],
16+
registrationMode,
17+
registerHttpRoute,
18+
});
19+
}
20+
21+
describe("mattermost plugin register", () => {
22+
it("skips slash callback registration in setup-only mode", () => {
23+
const registerHttpRoute = vi.fn();
24+
25+
plugin.register(createApi("setup-only", registerHttpRoute));
26+
27+
expect(registerHttpRoute).not.toHaveBeenCalled();
28+
});
29+
30+
it("registers slash callback routes in full mode", () => {
31+
const registerHttpRoute = vi.fn();
32+
33+
plugin.register(createApi("full", registerHttpRoute));
34+
35+
expect(registerHttpRoute).toHaveBeenCalledTimes(1);
36+
expect(registerHttpRoute).toHaveBeenCalledWith(
37+
expect.objectContaining({
38+
path: "/api/channels/mattermost/command",
39+
auth: "plugin",
40+
}),
41+
);
42+
});
43+
});

extensions/mattermost/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ const plugin = {
1212
register(api: OpenClawPluginApi) {
1313
setMattermostRuntime(api.runtime);
1414
api.registerChannel({ plugin: mattermostPlugin });
15+
if (api.registrationMode !== "full") {
16+
return;
17+
}
1518

1619
// Register the HTTP route for slash command callbacks.
1720
// The actual command registration with MM happens in the monitor

extensions/nostr/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ const plugin = {
1414
register(api: OpenClawPluginApi) {
1515
setNostrRuntime(api.runtime);
1616
api.registerChannel({ plugin: nostrPlugin });
17+
if (api.registrationMode !== "full") {
18+
return;
19+
}
1720

1821
// Register HTTP handler for profile management
1922
const httpHandler = createNostrProfileHttpHandler({

extensions/test-utils/plugin-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ type TestPluginApiInput = Partial<OpenClawPluginApi> &
55

66
export function createTestPluginApi(api: TestPluginApiInput): OpenClawPluginApi {
77
return {
8+
registrationMode: "full",
89
logger: { info() {}, warn() {}, error() {}, debug() {} },
910
registerTool() {},
1011
registerHook() {},

0 commit comments

Comments
 (0)