fix: gate setup-only plugin side effects
This commit is contained in:
parent
ae6ee73097
commit
59bcac472e
@ -12,6 +12,9 @@ const plugin = {
|
||||
register(api: OpenClawPluginApi) {
|
||||
setDiscordRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: discordPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
registerDiscordSubagentHooks(api);
|
||||
},
|
||||
};
|
||||
|
||||
@ -46,9 +46,11 @@ const {
|
||||
resolveDiscordAllowlistConfigMock,
|
||||
resolveNativeCommandsEnabledMock,
|
||||
resolveNativeSkillsEnabledMock,
|
||||
shouldLogVerboseMock,
|
||||
voiceRuntimeModuleLoadedMock,
|
||||
} = vi.hoisted(() => {
|
||||
const createdBindingManagers: Array<{ stop: ReturnType<typeof vi.fn> }> = [];
|
||||
const shouldLogVerboseMock = vi.fn(() => false);
|
||||
return {
|
||||
clientHandleDeployRequestMock: vi.fn(async () => undefined),
|
||||
clientConstructorOptionsMock: vi.fn(),
|
||||
@ -110,6 +112,7 @@ const {
|
||||
})),
|
||||
resolveNativeCommandsEnabledMock: vi.fn(() => true),
|
||||
resolveNativeSkillsEnabledMock: vi.fn(() => false),
|
||||
shouldLogVerboseMock,
|
||||
voiceRuntimeModuleLoadedMock: vi.fn(),
|
||||
};
|
||||
});
|
||||
@ -211,7 +214,7 @@ vi.mock("../../../../src/config/config.js", () => ({
|
||||
vi.mock("../../../../src/globals.js", () => ({
|
||||
danger: (v: string) => v,
|
||||
logVerbose: vi.fn(),
|
||||
shouldLogVerbose: () => false,
|
||||
shouldLogVerbose: shouldLogVerboseMock,
|
||||
warn: (v: string) => v,
|
||||
}));
|
||||
|
||||
@ -435,6 +438,7 @@ describe("monitorDiscordProvider", () => {
|
||||
});
|
||||
resolveNativeCommandsEnabledMock.mockClear().mockReturnValue(true);
|
||||
resolveNativeSkillsEnabledMock.mockClear().mockReturnValue(false);
|
||||
shouldLogVerboseMock.mockClear().mockReturnValue(false);
|
||||
voiceRuntimeModuleLoadedMock.mockClear();
|
||||
});
|
||||
|
||||
@ -842,6 +846,7 @@ describe("monitorDiscordProvider", () => {
|
||||
emitter.emit("debug", "WebSocket connection opened");
|
||||
return { id: "bot-1", username: "Molty" };
|
||||
});
|
||||
shouldLogVerboseMock.mockReturnValue(true);
|
||||
|
||||
await monitorDiscordProvider({
|
||||
config: baseConfig(),
|
||||
@ -861,4 +866,17 @@ describe("monitorDiscordProvider", () => {
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps Discord startup chatter quiet by default", async () => {
|
||||
const { monitorDiscordProvider } = await import("./provider.js");
|
||||
const runtime = baseRuntime();
|
||||
|
||||
await monitorDiscordProvider({
|
||||
config: baseConfig(),
|
||||
runtime,
|
||||
});
|
||||
|
||||
const messages = vi.mocked(runtime.log).mock.calls.map((call) => String(call[0]));
|
||||
expect(messages.some((msg) => msg.includes("discord startup ["))).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -273,14 +273,18 @@ async function deployDiscordCommands(params: {
|
||||
body === undefined
|
||||
? undefined
|
||||
: Buffer.byteLength(typeof body === "string" ? body : JSON.stringify(body), "utf8");
|
||||
params.runtime.log?.(
|
||||
`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}` : ""}`,
|
||||
);
|
||||
if (shouldLogVerbose()) {
|
||||
params.runtime.log?.(
|
||||
`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}` : ""}`,
|
||||
);
|
||||
}
|
||||
try {
|
||||
const result = await originalPut(path, data, query);
|
||||
params.runtime.log?.(
|
||||
`discord startup [${accountId}] deploy-rest:put:done ${Math.max(0, Date.now() - startupStartedAt)}ms path=${path} requestMs=${Date.now() - startedAt}`,
|
||||
);
|
||||
if (shouldLogVerbose()) {
|
||||
params.runtime.log?.(
|
||||
`discord startup [${accountId}] deploy-rest:put:done ${Math.max(0, Date.now() - startupStartedAt)}ms path=${path} requestMs=${Date.now() - startedAt}`,
|
||||
);
|
||||
}
|
||||
return result;
|
||||
} catch (err) {
|
||||
params.runtime.error?.(
|
||||
@ -359,6 +363,9 @@ function logDiscordStartupPhase(params: {
|
||||
gateway?: GatewayPlugin;
|
||||
details?: string;
|
||||
}) {
|
||||
if (!shouldLogVerbose()) {
|
||||
return;
|
||||
}
|
||||
const elapsedMs = Math.max(0, Date.now() - params.startAt);
|
||||
const suffix = [params.details, formatDiscordStartupGatewayState(params.gateway)]
|
||||
.filter((value): value is string => Boolean(value))
|
||||
@ -768,6 +775,9 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
|
||||
const lifecycleGateway = client.getPlugin<GatewayPlugin>("gateway");
|
||||
earlyGatewayEmitter = getDiscordGatewayEmitter(lifecycleGateway);
|
||||
onEarlyGatewayDebug = (msg: unknown) => {
|
||||
if (!shouldLogVerbose()) {
|
||||
return;
|
||||
}
|
||||
runtime.log?.(
|
||||
`discord startup [${account.accountId}] gateway-debug ${Math.max(0, Date.now() - startupStartedAt)}ms ${String(msg)}`,
|
||||
);
|
||||
|
||||
@ -54,6 +54,9 @@ const plugin = {
|
||||
register(api: OpenClawPluginApi) {
|
||||
setFeishuRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: feishuPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
registerFeishuSubagentHooks(api);
|
||||
registerFeishuDocTools(api);
|
||||
registerFeishuChatTools(api);
|
||||
|
||||
@ -12,6 +12,9 @@ const plugin = {
|
||||
register(api: OpenClawPluginApi) {
|
||||
setLineRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: linePlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
registerLineCardCommand(api);
|
||||
},
|
||||
};
|
||||
|
||||
@ -32,6 +32,7 @@ function fakeApi(overrides: Partial<OpenClawPluginApi> = {}): OpenClawPluginApi
|
||||
id: "lobster",
|
||||
name: "lobster",
|
||||
source: "test",
|
||||
registrationMode: "full",
|
||||
config: {},
|
||||
pluginConfig: {},
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
|
||||
43
extensions/mattermost/index.test.ts
Normal file
43
extensions/mattermost/index.test.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/mattermost";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createTestPluginApi } from "../test-utils/plugin-api.js";
|
||||
import plugin from "./index.js";
|
||||
|
||||
function createApi(
|
||||
registrationMode: OpenClawPluginApi["registrationMode"],
|
||||
registerHttpRoute = vi.fn(),
|
||||
): OpenClawPluginApi {
|
||||
return createTestPluginApi({
|
||||
id: "mattermost",
|
||||
name: "Mattermost",
|
||||
source: "test",
|
||||
config: {},
|
||||
runtime: {} as OpenClawPluginApi["runtime"],
|
||||
registrationMode,
|
||||
registerHttpRoute,
|
||||
});
|
||||
}
|
||||
|
||||
describe("mattermost plugin register", () => {
|
||||
it("skips slash callback registration in setup-only mode", () => {
|
||||
const registerHttpRoute = vi.fn();
|
||||
|
||||
plugin.register(createApi("setup-only", registerHttpRoute));
|
||||
|
||||
expect(registerHttpRoute).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("registers slash callback routes in full mode", () => {
|
||||
const registerHttpRoute = vi.fn();
|
||||
|
||||
plugin.register(createApi("full", registerHttpRoute));
|
||||
|
||||
expect(registerHttpRoute).toHaveBeenCalledTimes(1);
|
||||
expect(registerHttpRoute).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
path: "/api/channels/mattermost/command",
|
||||
auth: "plugin",
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -12,6 +12,9 @@ const plugin = {
|
||||
register(api: OpenClawPluginApi) {
|
||||
setMattermostRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: mattermostPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the HTTP route for slash command callbacks.
|
||||
// The actual command registration with MM happens in the monitor
|
||||
|
||||
@ -14,6 +14,9 @@ const plugin = {
|
||||
register(api: OpenClawPluginApi) {
|
||||
setNostrRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: nostrPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register HTTP handler for profile management
|
||||
const httpHandler = createNostrProfileHttpHandler({
|
||||
|
||||
@ -5,6 +5,7 @@ type TestPluginApiInput = Partial<OpenClawPluginApi> &
|
||||
|
||||
export function createTestPluginApi(api: TestPluginApiInput): OpenClawPluginApi {
|
||||
return {
|
||||
registrationMode: "full",
|
||||
logger: { info() {}, warn() {}, error() {}, debug() {} },
|
||||
registerTool() {},
|
||||
registerHook() {},
|
||||
|
||||
@ -138,6 +138,9 @@ const plugin = {
|
||||
register(api: OpenClawPluginApi) {
|
||||
setTlonRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: tlonPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
|
||||
api.logger.debug?.("[tlon] Registering tlon tool");
|
||||
api.registerTool({
|
||||
|
||||
@ -12,6 +12,9 @@ const plugin = {
|
||||
register(api: OpenClawPluginApi) {
|
||||
setZalouserRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: zalouserPlugin, dock: zalouserDock });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
|
||||
api.registerTool({
|
||||
name: "zalouser",
|
||||
|
||||
@ -43,6 +43,7 @@ import type {
|
||||
PluginLogger,
|
||||
PluginOrigin,
|
||||
PluginKind,
|
||||
PluginRegistrationMode,
|
||||
PluginHookName,
|
||||
PluginHookHandlerMap,
|
||||
PluginHookRegistration as TypedPluginHookRegistration,
|
||||
@ -186,8 +187,6 @@ type PluginTypedHookPolicy = {
|
||||
allowPromptInjection?: boolean;
|
||||
};
|
||||
|
||||
type PluginRegistrationMode = "full" | "setup-only";
|
||||
|
||||
const constrainLegacyPromptInjectionHook = (
|
||||
handler: PluginHookHandlerMap["before_agent_start"],
|
||||
): PluginHookHandlerMap["before_agent_start"] => {
|
||||
@ -734,6 +733,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
description: record.description,
|
||||
source: record.source,
|
||||
rootDir: record.rootDir,
|
||||
registrationMode,
|
||||
config: params.config,
|
||||
pluginConfig: params.pluginConfig,
|
||||
runtime: registryParams.runtime,
|
||||
|
||||
@ -839,6 +839,8 @@ export type OpenClawPluginModule =
|
||||
| OpenClawPluginDefinition
|
||||
| ((api: OpenClawPluginApi) => void | Promise<void>);
|
||||
|
||||
export type PluginRegistrationMode = "full" | "setup-only";
|
||||
|
||||
export type OpenClawPluginApi = {
|
||||
id: string;
|
||||
name: string;
|
||||
@ -846,6 +848,7 @@ export type OpenClawPluginApi = {
|
||||
description?: string;
|
||||
source: string;
|
||||
rootDir?: string;
|
||||
registrationMode: PluginRegistrationMode;
|
||||
config: OpenClawConfig;
|
||||
pluginConfig?: Record<string, unknown>;
|
||||
runtime: PluginRuntime;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user