fix(gateway): make handshake timeout configurable · openclaw/openclaw@bcc6a24
steipete
·
2026-04-29
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai
|
24 | 24 | - Plugins/runtime-deps: cache unchanged bundled runtime mirror dist-file materialization decisions and close file-lock handles on owner-write failures, reducing repeated startup chunk scans and avoiding FileHandle-GC recovery stalls. Refs #73532. Thanks @oadiazp and @bstanbury. |
25 | 25 | - CLI/TUI: keep `chat.history` off model-catalog discovery so initial Gateway-backed TUI history loads cannot block behind slow provider/plugin model scans on low-core hosts. Refs #73524. Thanks @harshcatsystems-collab. |
26 | 26 | - Channels/WhatsApp: flag recently reconnected linked accounts in channel status even when the socket is currently healthy, so flapping WhatsApp Web sessions no longer look clean after a brief reconnect. Refs #73602. Thanks @Vksh07. |
| 27 | +- Gateway: expose `gateway.handshakeTimeoutMs` in config, schema, and docs while preserving `OPENCLAW_HANDSHAKE_TIMEOUT_MS` precedence, so loaded or low-powered hosts can tune local WebSocket pre-auth handshakes without patching dist files. Supersedes #51282; refs #73592 and #73652. Thanks @henry-the-frog. |
27 | 28 | - Agents/model selection: resolve slash-form aliases before provider/model parsing and keep alias-resolved primary models subject to transient provider cooldowns, so cron and persisted sessions do not retry cooled-down raw aliases. Fixes #73573 and #73657. Thanks @akai-shuuichi and @hashslingers. |
28 | 29 | - Agents/Claude CLI: reuse already-cached macOS Keychain credentials for no-prompt Claude credential reads, so doctor/runtime checks do not miss fresh interactive Claude auth. Fixes #73682. Thanks @RyanSandoval. |
29 | 30 | - Agents/transcripts: strip empty assistant text blocks while preserving valid text, images, and signatures, so Anthropic-style providers no longer reject sanitized transcript turns. Fixes #73640. Thanks @jowhee327. |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | | -1265c4249f2740b6786b295d5a88391ba7eb0c30bdf460c60dfb4dfcb4153685 config-baseline.json |
2 | | -805bd3f63ff7327da45c01b78dbc990ed53bd13b89e0cbf50f319aa99334ba92 config-baseline.core.json |
| 1 | +d4c98bce7b547349b9cbbe08ec1018eafce9900502d7794df993d07fdec0e2e0 config-baseline.json |
| 2 | +6ce74b2ab3544e5375009a435a2360a3095e6bd759bb7dd8114293fb8a0e2b25 config-baseline.core.json |
3 | 3 | 0e38bad86bdc96c38573f6d51ac9e6fc5306cc20fb4a454399c57c105a61ba87 config-baseline.channel.json |
4 | 4 | 0dd6583fafae6c9134e46c4cf9bddee9822d6436436dcb1a6dcba6d012962e51 config-baseline.plugin.json |
| Original file line number | Diff line number | Diff line change |
|---|
@@ -441,6 +441,7 @@ See [Plugins](/tools/plugin).
|
441 | 441 | - Relay-backed registrations are delegated to a specific gateway identity. The paired iOS app fetches `gateway.identity.get`, includes that identity in the relay registration, and forwards a registration-scoped send grant to the gateway. Another gateway cannot reuse that stored registration. |
442 | 442 | - `OPENCLAW_APNS_RELAY_BASE_URL` / `OPENCLAW_APNS_RELAY_TIMEOUT_MS`: temporary env overrides for the relay config above. |
443 | 443 | - `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true`: development-only escape hatch for loopback HTTP relay URLs. Production relay URLs should stay on HTTPS. |
| 444 | +- `gateway.handshakeTimeoutMs`: pre-auth Gateway WebSocket handshake timeout in milliseconds. Default: `15000`. `OPENCLAW_HANDSHAKE_TIMEOUT_MS` takes precedence when set. Increase this on loaded or low-powered hosts where local clients can connect while startup warmup is still settling. |
444 | 445 | - `gateway.channelHealthCheckMinutes`: channel health-monitor interval in minutes. Set `0` to disable health-monitor restarts globally. Default: `5`. |
445 | 446 | - `gateway.channelStaleEventThresholdMinutes`: stale-socket threshold in minutes. Keep this greater than or equal to `gateway.channelHealthCheckMinutes`. Default: `30`. |
446 | 447 | - `gateway.channelMaxRestartsPerHour`: maximum health-monitor restarts per channel/account in a rolling hour. Default: `10`. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -270,6 +270,24 @@ cannot roll back unrelated user settings.
|
270 | 270 | |
271 | 271 | </Accordion> |
272 | 272 | |
| 273 | +<Accordion title="Tune gateway WebSocket handshake timeout"> |
| 274 | +Give local clients more time to complete the pre-auth WebSocket handshake on |
| 275 | +loaded or low-powered hosts: |
| 276 | + |
| 277 | +```json5 |
| 278 | +{ |
| 279 | + gateway: { |
| 280 | + handshakeTimeoutMs: 30000, |
| 281 | + }, |
| 282 | +} |
| 283 | +``` |
| 284 | + |
| 285 | +- Default is `15000` milliseconds. |
| 286 | +- `OPENCLAW_HANDSHAKE_TIMEOUT_MS` still takes precedence for one-off service or shell overrides. |
| 287 | +- Prefer fixing startup/event-loop stalls first; this knob is for hosts that are healthy but slow during warmup. |
| 288 | + |
| 289 | +</Accordion> |
| 290 | + |
273 | 291 | <Accordion title="Configure sessions and resets"> |
274 | 292 | Sessions control conversation continuity and isolation: |
275 | 293 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -409,6 +409,27 @@ describe("gateway.tools config", () => {
|
409 | 409 | }); |
410 | 410 | |
411 | 411 | describe("gateway.channelHealthCheckMinutes", () => { |
| 412 | +it("accepts preauth handshake timeout tuning", () => { |
| 413 | +const res = validateConfigObject({ |
| 414 | +gateway: { |
| 415 | +handshakeTimeoutMs: 30_000, |
| 416 | +}, |
| 417 | +}); |
| 418 | +expect(res.ok).toBe(true); |
| 419 | +}); |
| 420 | + |
| 421 | +it("rejects non-positive preauth handshake timeouts", () => { |
| 422 | +const res = validateConfigObject({ |
| 423 | +gateway: { |
| 424 | +handshakeTimeoutMs: 0, |
| 425 | +}, |
| 426 | +}); |
| 427 | +expect(res.ok).toBe(false); |
| 428 | +if (!res.ok) { |
| 429 | +expect(res.issues[0]?.path).toBe("gateway.handshakeTimeoutMs"); |
| 430 | +} |
| 431 | +}); |
| 432 | + |
412 | 433 | it("accepts zero to disable monitor", () => { |
413 | 434 | const res = validateConfigObject({ |
414 | 435 | gateway: { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -22343,6 +22343,14 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
22343 | 22343 | }, |
22344 | 22344 | additionalProperties: false, |
22345 | 22345 | }, |
| 22346 | + handshakeTimeoutMs: { |
| 22347 | + type: "integer", |
| 22348 | + minimum: 1, |
| 22349 | + maximum: 9007199254740991, |
| 22350 | + title: "Gateway Handshake Timeout", |
| 22351 | + description: |
| 22352 | +"Pre-auth Gateway WebSocket handshake timeout in milliseconds. Use higher values on loaded or low-powered hosts where local clients can connect during startup warmup. OPENCLAW_HANDSHAKE_TIMEOUT_MS still takes precedence.", |
| 22353 | + }, |
22346 | 22354 | channelHealthCheckMinutes: { |
22347 | 22355 | type: "integer", |
22348 | 22356 | minimum: 0, |
@@ -24645,6 +24653,11 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
24645 | 24653 | help: "Explicit gateway-level tool denylist to block risky tools even if lower-level policies allow them. Use deny rules for emergency response and defense-in-depth hardening.", |
24646 | 24654 | tags: ["access", "network"], |
24647 | 24655 | }, |
| 24656 | +"gateway.handshakeTimeoutMs": { |
| 24657 | + label: "Gateway Handshake Timeout", |
| 24658 | + help: "Pre-auth Gateway WebSocket handshake timeout in milliseconds. Use higher values on loaded or low-powered hosts where local clients can connect during startup warmup. OPENCLAW_HANDSHAKE_TIMEOUT_MS still takes precedence.", |
| 24659 | + tags: ["network", "performance"], |
| 24660 | + }, |
24648 | 24661 | "gateway.channelHealthCheckMinutes": { |
24649 | 24662 | label: "Gateway Channel Health Check Interval (min)", |
24650 | 24663 | help: "Interval in minutes for automatic channel health probing and status updates. Use lower intervals for faster detection, or higher intervals to reduce periodic probe noise.", |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -95,6 +95,8 @@ export const FIELD_HELP: Record<string, string> = {
|
95 | 95 | "Explicit gateway-level tool allowlist when you want a narrow set of tools available at runtime. Use this for locked-down environments where tool scope must be tightly controlled.", |
96 | 96 | "gateway.tools.deny": |
97 | 97 | "Explicit gateway-level tool denylist to block risky tools even if lower-level policies allow them. Use deny rules for emergency response and defense-in-depth hardening.", |
| 98 | +"gateway.handshakeTimeoutMs": |
| 99 | +"Pre-auth Gateway WebSocket handshake timeout in milliseconds. Use higher values on loaded or low-powered hosts where local clients can connect during startup warmup. OPENCLAW_HANDSHAKE_TIMEOUT_MS still takes precedence.", |
98 | 100 | "gateway.channelHealthCheckMinutes": |
99 | 101 | "Interval in minutes for automatic channel health probing and status updates. Use lower intervals for faster detection, or higher intervals to reduce periodic probe noise.", |
100 | 102 | "gateway.channelStaleEventThresholdMinutes": |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -119,6 +119,7 @@ export const FIELD_LABELS: Record<string, string> = {
|
119 | 119 | "gateway.tools": "Gateway Tool Exposure Policy", |
120 | 120 | "gateway.tools.allow": "Gateway Tool Allowlist", |
121 | 121 | "gateway.tools.deny": "Gateway Tool Denylist", |
| 122 | +"gateway.handshakeTimeoutMs": "Gateway Handshake Timeout", |
122 | 123 | "gateway.channelHealthCheckMinutes": "Gateway Channel Health Check Interval (min)", |
123 | 124 | "gateway.channelStaleEventThresholdMinutes": "Gateway Channel Stale Event Threshold (min)", |
124 | 125 | "gateway.channelMaxRestartsPerHour": "Gateway Channel Max Restarts Per Hour", |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -453,6 +453,11 @@ export type GatewayConfig = {
|
453 | 453 | tools?: GatewayToolsConfig; |
454 | 454 | /** WebChat display/history settings. */ |
455 | 455 | webchat?: GatewayWebchatConfig; |
| 456 | +/** |
| 457 | + * Pre-auth Gateway WebSocket handshake timeout in milliseconds. |
| 458 | + * Env var OPENCLAW_HANDSHAKE_TIMEOUT_MS takes precedence. Default: 15000. |
| 459 | + */ |
| 460 | +handshakeTimeoutMs?: number; |
456 | 461 | /** |
457 | 462 | * Channel health monitor interval in minutes. |
458 | 463 | * Periodically checks channel health and restarts unhealthy channels. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -797,6 +797,7 @@ export const OpenClawSchema = z
|
797 | 797 | }) |
798 | 798 | .strict() |
799 | 799 | .optional(), |
| 800 | +handshakeTimeoutMs: z.number().int().min(1).optional(), |
800 | 801 | channelHealthCheckMinutes: z.number().int().min(0).optional(), |
801 | 802 | channelStaleEventThresholdMinutes: z.number().int().min(1).optional(), |
802 | 803 | channelMaxRestartsPerHour: z.number().int().min(1).optional(), |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。