diff --git a/roles/vhosts/xworkmate_bridge/defaults/main.yml b/roles/vhosts/xworkmate_bridge/defaults/main.yml index 58e64f7..300577e 100644 --- a/roles/vhosts/xworkmate_bridge/defaults/main.yml +++ b/roles/vhosts/xworkmate_bridge/defaults/main.yml @@ -29,6 +29,13 @@ xworkmate_bridge_service_environment: xworkmate_bridge_openclaw_gateway_max_active: 2 xworkmate_bridge_openclaw_gateway_max_queued: 20 xworkmate_bridge_openclaw_gateway_queue_timeout: 10m +# Caddy reverse_proxy 流式(SSE)超时。必须 >= bridge openClawAgentWaitMaxTimeout(60min) +# 才不会在长任务执行到一半时把 SSE 从入口掐断(表现为 ACP_HTTP_CONNECTION_CLOSED, +# 而 OpenClaw gateway 仍在后台跑)。来源常量见 xworkmate-bridge/internal/acp/orchestrator.go:32。 +# 取 70m = 60min 上限 + 10min 余量(HTTP margin + keepalive 抖动)。改这里即同时驱动 read/write_timeout。 +xworkmate_bridge_acp_stream_timeout: 70m +xworkmate_bridge_acp_dial_timeout: 10s +xworkmate_bridge_acp_upstream_keepalive: 5m xworkmate_bridge_distributed_topology: "" xworkmate_bridge_distributed_local_node_id: "" xworkmate_bridge_distributed_task_forward_peer_id: "" diff --git a/roles/vhosts/xworkmate_bridge/tasks/validate.yml b/roles/vhosts/xworkmate_bridge/tasks/validate.yml index 4884d50..615c2c8 100644 --- a/roles/vhosts/xworkmate_bridge/tasks/validate.yml +++ b/roles/vhosts/xworkmate_bridge/tasks/validate.yml @@ -36,9 +36,10 @@ 'reverse_proxy ' ~ xworkmate_bridge_listen_host ~ ':' ~ xworkmate_bridge_listen_port in xworkmate_bridge_fragment.stdout - "'flush_interval -1' in xworkmate_bridge_fragment.stdout" - - "'read_timeout 30m' in xworkmate_bridge_fragment.stdout" - - "'write_timeout 30m' in xworkmate_bridge_fragment.stdout" - - "'keepalive 5m' in xworkmate_bridge_fragment.stdout" + # 流式超时与 bridge openClawAgentWaitMaxTimeout(60min) 对齐,由 xworkmate_bridge_acp_stream_timeout 驱动(T1/T2)。 + - "'read_timeout ' ~ xworkmate_bridge_acp_stream_timeout in xworkmate_bridge_fragment.stdout" + - "'write_timeout ' ~ xworkmate_bridge_acp_stream_timeout in xworkmate_bridge_fragment.stdout" + - "'keepalive ' ~ xworkmate_bridge_acp_upstream_keepalive in xworkmate_bridge_fragment.stdout" - "'/gateway/openclaw' not in xworkmate_bridge_fragment.stdout" - "'/acp-server' not in xworkmate_bridge_fragment.stdout" - "'127.0.0.1:18789' not in xworkmate_bridge_fragment.stdout" diff --git a/roles/vhosts/xworkmate_bridge/templates/xworkmate-bridge-site.caddy.j2 b/roles/vhosts/xworkmate_bridge/templates/xworkmate-bridge-site.caddy.j2 index c13debe..3a10aa0 100644 --- a/roles/vhosts/xworkmate_bridge/templates/xworkmate-bridge-site.caddy.j2 +++ b/roles/vhosts/xworkmate_bridge/templates/xworkmate-bridge-site.caddy.j2 @@ -11,28 +11,55 @@ respond `{"jsonrpc":"2.0","error":{"code":-32001,"message":"unauthorized"},"type":"res","ok":false}` 401 } + # /api* 承载 tasks.get 轮询与(部分)流式响应:与 /acp* 用同样的流式 + 长超时配置, + # 避免落到 Caddy 默认短超时把轮询/流式打断(T2)。 handle /api* { - reverse_proxy {{ xworkmate_bridge_listen_host }}:{{ xworkmate_bridge_listen_port }} + reverse_proxy {{ xworkmate_bridge_listen_host }}:{{ xworkmate_bridge_listen_port }} { + flush_interval -1 + transport http { + dial_timeout {{ xworkmate_bridge_acp_dial_timeout }} + read_timeout {{ xworkmate_bridge_acp_stream_timeout }} + write_timeout {{ xworkmate_bridge_acp_stream_timeout }} + keepalive {{ xworkmate_bridge_acp_upstream_keepalive }} + } + } } handle /artifacts/* { - reverse_proxy {{ xworkmate_bridge_listen_host }}:{{ xworkmate_bridge_listen_port }} + reverse_proxy {{ xworkmate_bridge_listen_host }}:{{ xworkmate_bridge_listen_port }} { + flush_interval -1 + transport http { + dial_timeout {{ xworkmate_bridge_acp_dial_timeout }} + read_timeout {{ xworkmate_bridge_acp_stream_timeout }} + write_timeout {{ xworkmate_bridge_acp_stream_timeout }} + keepalive {{ xworkmate_bridge_acp_upstream_keepalive }} + } + } } + # /acp* 流式超时必须 >= bridge openClawAgentWaitMaxTimeout(60min),否则长任务在入口被掐断(T1)。 handle /acp* { reverse_proxy {{ xworkmate_bridge_listen_host }}:{{ xworkmate_bridge_listen_port }} { flush_interval -1 transport http { - dial_timeout 10s - read_timeout 30m - write_timeout 30m - keepalive 5m + dial_timeout {{ xworkmate_bridge_acp_dial_timeout }} + read_timeout {{ xworkmate_bridge_acp_stream_timeout }} + write_timeout {{ xworkmate_bridge_acp_stream_timeout }} + keepalive {{ xworkmate_bridge_acp_upstream_keepalive }} } } } handle / { - reverse_proxy {{ xworkmate_bridge_listen_host }}:{{ xworkmate_bridge_listen_port }} + reverse_proxy {{ xworkmate_bridge_listen_host }}:{{ xworkmate_bridge_listen_port }} { + flush_interval -1 + transport http { + dial_timeout {{ xworkmate_bridge_acp_dial_timeout }} + read_timeout {{ xworkmate_bridge_acp_stream_timeout }} + write_timeout {{ xworkmate_bridge_acp_stream_timeout }} + keepalive {{ xworkmate_bridge_acp_upstream_keepalive }} + } + } } log {