discord: expose EventQueue listenerTimeout as configurable option (fixes #24458)

This commit is contained in:
Glucksberg
2026-02-27 05:28:43 +00:00
committed by Peter Steinberger
parent 8629b996a1
commit a25a73e707
4 changed files with 79 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ import type { RuntimeEnv } from "../../runtime.js";
const {
clientFetchUserMock,
clientGetPluginMock,
clientConstructorOptionsMock,
createDiscordNativeCommandMock,
createNoopThreadBindingManagerMock,
createThreadBindingManagerMock,
@@ -21,6 +22,7 @@ const {
} = vi.hoisted(() => {
const createdBindingManagers: Array<{ stop: ReturnType<typeof vi.fn> }> = [];
return {
clientConstructorOptionsMock: vi.fn(),
clientFetchUserMock: vi.fn(async (_target: string) => ({ id: "bot-1" })),
clientGetPluginMock: vi.fn<(_name: string) => unknown>(() => undefined),
createDiscordNativeCommandMock: vi.fn(() => ({ name: "mock-command" })),
@@ -69,9 +71,12 @@ vi.mock("@buape/carbon", () => {
class Client {
listeners: unknown[];
rest: { put: ReturnType<typeof vi.fn> };
constructor(_options: unknown, handlers: { listeners?: unknown[] }) {
options: unknown;
constructor(options: unknown, handlers: { listeners?: unknown[] }) {
this.options = options;
this.listeners = handlers.listeners ?? [];
this.rest = { put: vi.fn(async () => undefined) };
clientConstructorOptionsMock(options);
}
async handleDeployRequest() {
return undefined;
@@ -254,6 +259,7 @@ describe("monitorDiscordProvider", () => {
}) as OpenClawConfig;
beforeEach(() => {
clientConstructorOptionsMock.mockClear();
clientFetchUserMock.mockClear().mockResolvedValue({ id: "bot-1" });
clientGetPluginMock.mockClear().mockReturnValue(undefined);
createDiscordNativeCommandMock.mockClear().mockReturnValue({ name: "mock-command" });
@@ -334,4 +340,47 @@ describe("monitorDiscordProvider", () => {
expect(lifecycleArgs.pendingGatewayErrors).toHaveLength(1);
expect(String(lifecycleArgs.pendingGatewayErrors?.[0])).toContain("4014");
});
it("passes default eventQueue.listenerTimeout of 120s to Carbon Client", async () => {
const { monitorDiscordProvider } = await import("./provider.js");
await monitorDiscordProvider({
config: baseConfig(),
runtime: baseRuntime(),
});
expect(clientConstructorOptionsMock).toHaveBeenCalledTimes(1);
const opts = clientConstructorOptionsMock.mock.calls[0]?.[0] as {
eventQueue?: { listenerTimeout?: number };
};
expect(opts.eventQueue).toBeDefined();
expect(opts.eventQueue?.listenerTimeout).toBe(120_000);
});
it("forwards custom eventQueue config from discord config to Carbon Client", async () => {
const { monitorDiscordProvider } = await import("./provider.js");
resolveDiscordAccountMock.mockImplementation(() => ({
accountId: "default",
token: "cfg-token",
config: {
commands: { native: true, nativeSkills: false },
voice: { enabled: false },
agentComponents: { enabled: false },
execApprovals: { enabled: false },
eventQueue: { listenerTimeout: 300_000 },
},
}));
await monitorDiscordProvider({
config: baseConfig(),
runtime: baseRuntime(),
});
expect(clientConstructorOptionsMock).toHaveBeenCalledTimes(1);
const opts = clientConstructorOptionsMock.mock.calls[0]?.[0] as {
eventQueue?: { listenerTimeout?: number };
};
expect(opts.eventQueue?.listenerTimeout).toBe(300_000);
});
});

View File

@@ -517,6 +517,12 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
if (voiceEnabled) {
clientPlugins.push(new VoicePlugin());
}
// Pass eventQueue config to Carbon so the listener timeout can be tuned.
// Default listenerTimeout is 120s (Carbon defaults to 30s which is too short for LLM calls).
const eventQueueOpts = {
listenerTimeout: 120_000,
...discordCfg.eventQueue,
};
const client = new Client(
{
baseUrl: "http://localhost",
@@ -525,6 +531,7 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
publicKey: "a",
token,
autoDeploy: false,
eventQueue: eventQueueOpts,
},
{
commands,