




























@@ -49,10 +49,21 @@ type ServerNotification = {
49495050const CLAUDE_PERMISSION_REPLY_RE = /^(yes|no)\s+([a-km-z]{5})$/i;
5151const QUEUE_LIMIT = 1_000;
52+const CONVERSATIONS_LIST_LIMIT = 500;
53+const MESSAGES_READ_LIMIT = 200;
54+const EVENTS_POLL_LIMIT = 200;
55+const EVENTS_WAIT_TIMEOUT_LIMIT_MS = 300_000;
5256const PENDING_CLAUDE_PERMISSION_TTL_MS = 60 * 60 * 1_000;
5357const PENDING_APPROVAL_DEFAULT_TTL_MS = 30 * 60 * 1_000;
5458const PENDING_SWEEP_INTERVAL_MS = 5 * 60 * 1_000;
555960+function clampPositiveInteger(value: number | undefined, fallback: number, max: number): number {
61+if (typeof value !== "number" || !Number.isFinite(value)) {
62+return fallback;
63+}
64+return Math.min(max, Math.max(1, Math.floor(value)));
65+}
66+5667/** Connects the MCP server surface to a Gateway client and queues channel events for polling. */
5768export class OpenClawChannelBridge {
5869private gateway: GatewayClient | null = null;
@@ -212,8 +223,9 @@ export class OpenClawChannelBridge {
212223includeLastMessage?: boolean;
213224}): Promise<ConversationDescriptor[]> {
214225await this.waitUntilReady();
226+const limit = clampPositiveInteger(params?.limit, 50, CONVERSATIONS_LIST_LIMIT);
215227const response: SessionListResult = await this.requestGateway("sessions.list", {
216-limit: params?.limit ?? 50,
228+ limit,
217229search: params?.search,
218230includeDerivedTitles: params?.includeDerivedTitles ?? true,
219231includeLastMessage: params?.includeLastMessage ?? true,
@@ -250,9 +262,10 @@ export class OpenClawChannelBridge {
250262limit = 20,
251263): Promise<NonNullable<ChatHistoryResult["messages"]>> {
252264await this.waitUntilReady();
265+const requestLimit = clampPositiveInteger(limit, 20, MESSAGES_READ_LIMIT);
253266const response: ChatHistoryResult = await this.requestGateway("sessions.get", {
254267key: sessionKey,
255- limit,
268+limit: requestLimit,
256269});
257270return response.messages ?? [];
258271}
@@ -307,7 +320,10 @@ export class OpenClawChannelBridge {
307320308321/** Poll queued events after a cursor without consuming them. */
309322pollEvents(filter: WaitFilter, limit = 20): { events: QueueEvent[]; nextCursor: number } {
310-const events = this.queue.filter((event) => matchEventFilter(event, filter)).slice(0, limit);
323+const eventLimit = clampPositiveInteger(limit, 20, EVENTS_POLL_LIMIT);
324+const events = this.queue
325+.filter((event) => matchEventFilter(event, filter))
326+.slice(0, eventLimit);
311327const nextCursor = events.at(-1)?.cursor ?? filter.afterCursor;
312328return { events, nextCursor };
313329}
@@ -318,6 +334,7 @@ export class OpenClawChannelBridge {
318334if (existing) {
319335return existing;
320336}
337+const waitTimeoutMs = clampPositiveInteger(timeoutMs, 30_000, EVENTS_WAIT_TIMEOUT_LIMIT_MS);
321338return await new Promise<QueueEvent | null>((resolve) => {
322339const waiter: PendingWaiter = {
323340 filter,
@@ -327,11 +344,9 @@ export class OpenClawChannelBridge {
327344},
328345timeout: null,
329346};
330-if (timeoutMs > 0) {
331-waiter.timeout = setTimeout(() => {
332-waiter.resolve(null);
333-}, timeoutMs);
334-}
347+waiter.timeout = setTimeout(() => {
348+waiter.resolve(null);
349+}, waitTimeoutMs);
335350this.pendingWaiters.add(waiter);
336351});
337352}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。