Conversation
Replace all child_process.exec("openclaw agents ...") calls with
callGatewayRpc() WebSocket calls. Add persistent event streaming via
GatewayEventManager singleton, SSE endpoint (/api/events), status
endpoint (/api/status), and useGatewayEvents React hook for live
dashboard updates. Server component now calls Gateway directly
instead of self-fetching localhost.
https://claude.ai/code/session_01XLFgYizVSscsWXY3FF724r
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
This PR is being reviewed by Cursor Bugbot
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| cancel() { | ||
| // Client disconnected — cleanup happens via the Proxy above | ||
| // or we can do additional cleanup here if needed | ||
| }, |
There was a problem hiding this comment.
SSE event listener cleanup never executes on disconnect
High Severity
The cleanup function (which removes event listeners from the singleton gatewayEvents and clears the heartbeat interval) is only reachable via a Proxy on controller.close. However, when a client disconnects from an SSE stream, the runtime invokes the cancel() callback on the underlying source — not controller.close(). The cancel() body is empty, so cleanup never runs. Every client connection permanently adds four event listeners to gatewayEvents and leaks a setInterval, causing unbounded resource growth.
| return updatedAgent; | ||
| }), | ||
| ); | ||
| }, [getAgentUpdate]); |
There was a problem hiding this comment.
Log entries duplicated on every agent update event
Medium Severity
The useEffect depends on getAgentUpdate, which gets a new identity every time the agentUpdates map changes (any agent update). Updates are never cleared from the map after being applied. So when agent B receives an event, the effect re-runs for all agents — and agent A's previously-applied update.log is appended again to its logs array. This causes the same log entry to be duplicated with every subsequent gateway event from any agent.
|
|
||
| await callGatewayRpc<unknown>("agents.update", { | ||
| id, | ||
| ...body, |
There was a problem hiding this comment.
Request body can override URL-derived agent ID
Medium Severity
In the PATCH handler, the RPC params are built as { id, ...body }. Since AgentUpdateParams includes an id field, and body is spread after the URL-derived id, a client can send { "id": "other-agent" } in the request body to update a different agent than the one in the URL path. The response still returns agentId: id from the URL, masking the mismatch.


Note
Medium Risk
Moderate risk: replaces CLI/config-file based backend paths with Gateway RPC + a persistent WebSocket→SSE bridge, which could impact core dashboard data loading and realtime updates if the Gateway protocol/availability differs.
Overview
Migrates agent and model backend endpoints off local
openclawCLI / filesystem reads and ontocallGatewayRpc(agents.list/add/delete/update,models.listwithstatusfallback), including a newPATCH /api/agents/[id]for updates.Adds realtime plumbing by introducing a persistent Gateway WebSocket event singleton (
gatewayEvents), exposing it via a new SSE endpointGET /api/events, and wiring the dashboard to display Gateway connection status plus apply live agent status/task/log updates with periodic list refresh.Updates SSR (
app/page.tsx) to call the Gateway directly (no self-fetch), extends agent typing/mapping (GatewayAgentEntry+gatewayEntryToAgent), addsGET /api/statushealth/presence probe, and pinstypescriptto5.9.3.Written by Cursor Bugbot for commit 366340e. This will update automatically on new commits. Configure here.