





















@@ -7,6 +7,7 @@ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
77export type SignalRpcOptions = {
88baseUrl: string;
99timeoutMs?: number;
10+maxResponseBytes?: number;
1011};
11121213export type SignalRpcError = {
@@ -29,7 +30,7 @@ export type SignalSseEvent = {
2930};
30313132const DEFAULT_TIMEOUT_MS = 10_000;
32-const MAX_SIGNAL_HTTP_RESPONSE_BYTES = 1_048_576;
33+const DEFAULT_SIGNAL_HTTP_RESPONSE_MAX_BYTES = 1_048_576;
3334const MAX_SIGNAL_SSE_BUFFER_BYTES = 1_048_576;
3435const MAX_SIGNAL_SSE_EVENT_DATA_BYTES = 1_048_576;
3536@@ -94,13 +95,28 @@ function assertSignalHttpProtocol(url: URL, label: string): void {
9495}
9596}
969798+function normalizeSignalHttpResponseMaxBytes(value: number | undefined): number {
99+if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
100+return DEFAULT_SIGNAL_HTTP_RESPONSE_MAX_BYTES;
101+}
102+return Math.floor(value);
103+}
104+105+function normalizeSignalSseTimeoutMs(timeoutMs: number): number | null {
106+if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
107+return null;
108+}
109+return timeoutMs;
110+}
111+97112function requestSignalHttpText(
98113url: URL,
99114options: {
100115method: "GET" | "POST";
101116headers?: Record<string, string>;
102117body?: string;
103118timeoutMs: number;
119+maxResponseBytes?: number;
104120},
105121): Promise<SignalHttpResponse> {
106122assertSignalHttpProtocol(url, "HTTP");
@@ -132,6 +148,7 @@ function requestSignalHttpText(
132148cleanup();
133149resolve(response);
134150};
151+const maxResponseBytes = normalizeSignalHttpResponseMaxBytes(options.maxResponseBytes);
135152request = client.request(
136153url,
137154{
@@ -144,7 +161,7 @@ function requestSignalHttpText(
144161res.on("data", (chunk: Buffer | string) => {
145162const next = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
146163totalBytes += next.byteLength;
147-if (totalBytes > MAX_SIGNAL_HTTP_RESPONSE_BYTES) {
164+if (totalBytes > maxResponseBytes) {
148165const error = new Error("Signal HTTP response exceeded size limit");
149166request?.destroy(error);
150167res.destroy(error);
@@ -194,6 +211,7 @@ export async function signalRpcRequest<T = unknown>(
194211},
195212 body,
196213timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
214+maxResponseBytes: opts.maxResponseBytes,
197215});
198216if (res.status === 201) {
199217return undefined as T;
@@ -248,15 +266,23 @@ function openSignalEventStream(
248266let response: IncomingMessage | undefined;
249267let onAbort: () => void = () => {};
250268let request: ClientRequest;
251-const headerDeadline = setTimeout(() => {
252-const error = new Error(`Signal SSE connection timed out after ${timeoutMs}ms`);
253-response?.destroy(error);
254-request.destroy(error);
255-rejectOnce(error);
256-}, timeoutMs);
257-headerDeadline.unref?.();
269+const effectiveTimeoutMs = normalizeSignalSseTimeoutMs(timeoutMs);
270+const headerDeadline =
271+effectiveTimeoutMs === null
272+ ? undefined
273+ : setTimeout(() => {
274+const error = new Error(
275+`Signal SSE connection timed out after ${effectiveTimeoutMs}ms`,
276+);
277+response?.destroy(error);
278+request.destroy(error);
279+rejectOnce(error);
280+}, effectiveTimeoutMs);
281+headerDeadline?.unref?.();
258282const cleanup = () => {
259-clearTimeout(headerDeadline);
283+if (headerDeadline) {
284+clearTimeout(headerDeadline);
285+}
260286abortSignal?.removeEventListener("abort", onAbort);
261287};
262288const rejectOnce = (error: unknown) => {
@@ -284,7 +310,9 @@ function openSignalEventStream(
284310res.destroy();
285311return;
286312}
287-clearTimeout(headerDeadline);
313+if (headerDeadline) {
314+clearTimeout(headerDeadline);
315+}
288316settled = true;
289317response = res;
290318resolve({ response: res, cleanup });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。