@@ -10,6 +10,7 @@ import { stageQaMockAuthProfiles } from "../extensions/qa-lab/src/providers/shar
|
10 | 10 | import { buildQaGatewayConfig } from "../extensions/qa-lab/src/qa-gateway-config.js"; |
11 | 11 | import { resetConfigRuntimeState } from "../src/config/config.js"; |
12 | 12 | import { startGatewayServer } from "../src/gateway/server.js"; |
| 13 | +import { readPositiveIntEnv } from "./e2e/lib/env-limits.mjs"; |
13 | 14 | import { readBoundedResponseText } from "./lib/bounded-response.ts"; |
14 | 15 | |
15 | 16 | type Lane = "normal" | "code"; |
@@ -34,26 +35,36 @@ type LaneResult = {
|
34 | 35 | }; |
35 | 36 | |
36 | 37 | const FAKE_PLUGIN_ID = "tool-search-e2e-fixture"; |
37 | | -const DEFAULT_FETCH_TIMEOUT_MS = readPositiveInt( |
38 | | -process.env.OPENCLAW_TOOL_SEARCH_GATEWAY_E2E_FETCH_TIMEOUT_MS, |
39 | | -180_000, |
40 | | -); |
41 | | -const DEFAULT_FETCH_BODY_MAX_BYTES = readPositiveInt( |
42 | | -process.env.OPENCLAW_TOOL_SEARCH_GATEWAY_E2E_FETCH_BODY_MAX_BYTES, |
43 | | -1024 * 1024, |
44 | | -); |
| 38 | +export type ToolSearchGatewayFetchLimits = { |
| 39 | +bodyMaxBytes: number; |
| 40 | +timeoutMs: number; |
| 41 | +}; |
45 | 42 | |
46 | 43 | function assert(condition: unknown, message: string): asserts condition { |
47 | 44 | if (!condition) { |
48 | 45 | throw new Error(message); |
49 | 46 | } |
50 | 47 | } |
51 | 48 | |
52 | | -function readPositiveInt(raw: string | undefined, fallback: number) { |
53 | | -const parsed = Number.parseInt(raw ?? "", 10); |
54 | | -return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback; |
| 49 | +export function readToolSearchGatewayFetchLimits( |
| 50 | +env: NodeJS.ProcessEnv = process.env, |
| 51 | +): ToolSearchGatewayFetchLimits { |
| 52 | +return { |
| 53 | +bodyMaxBytes: readPositiveIntEnv( |
| 54 | +"OPENCLAW_TOOL_SEARCH_GATEWAY_E2E_FETCH_BODY_MAX_BYTES", |
| 55 | +1024 * 1024, |
| 56 | +env, |
| 57 | +), |
| 58 | +timeoutMs: readPositiveIntEnv( |
| 59 | +"OPENCLAW_TOOL_SEARCH_GATEWAY_E2E_FETCH_TIMEOUT_MS", |
| 60 | +180_000, |
| 61 | +env, |
| 62 | +), |
| 63 | +}; |
55 | 64 | } |
56 | 65 | |
| 66 | +const DEFAULT_FETCH_LIMITS = readToolSearchGatewayFetchLimits(); |
| 67 | + |
57 | 68 | function timeoutError(message: string) { |
58 | 69 | return Object.assign(new Error(message), { code: "ETIMEDOUT" }); |
59 | 70 | } |
@@ -145,8 +156,8 @@ export async function fetchJson(
|
145 | 156 | init: RequestInit = {}, |
146 | 157 | options: FetchJsonOptions = {}, |
147 | 158 | ): Promise<unknown> { |
148 | | -const timeoutMs = Math.max(1, options.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS); |
149 | | -const maxBodyBytes = Math.max(1, options.maxBodyBytes ?? DEFAULT_FETCH_BODY_MAX_BYTES); |
| 159 | +const timeoutMs = Math.max(1, options.timeoutMs ?? DEFAULT_FETCH_LIMITS.timeoutMs); |
| 160 | +const maxBodyBytes = Math.max(1, options.maxBodyBytes ?? DEFAULT_FETCH_LIMITS.bodyMaxBytes); |
150 | 161 | const controller = new AbortController(); |
151 | 162 | const error = timeoutError(`HTTP request to ${url} timed out after ${timeoutMs}ms`); |
152 | 163 | let timeout: ReturnType<typeof setNodeTimeout> | undefined; |
|