Repository navigation
fix(tui): attach explicitly subscribes to /global/event SSE - #2
Conversation
Without this, externally-triggered session activity (a wake fired via POST /session/<id>/prompt_async from another peer) never renders in attach client TUIs. The wake processes server-side (LLM runs, message written to db), but the attach client has no way to learn about it. ## Root cause attach.ts called tui() without passing `events`. The SDKProvider had a fallback path (startSSE() in context/sdk.tsx onMount) that should have subscribed to /global/event when props.events was undefined. In practice that fallback is silent on failure — its async IIFE catches every error. This patch explicitly creates an EventSource in attach.ts that subscribes to /global/event via the SDK and forwards events to the SDKProvider, mirroring how the local-worker case in thread.ts wires `events: createEventSource(client)`. ## Verification Local typecheck passes (`bun typecheck` from packages/opencode). Manual end-to-end test plan (requires rebuilt binary): 1. Start `opencode serve --port 4096` in one terminal 2. `opencode attach http://127.0.0.1:4096 --dir <project>` in another 3. From a third terminal: `curl -X POST 'http://127.0.0.1:4096/session/<id>/prompt_async' -H 'Content-Type: application/json' -d '{"parts":[{"type":"text","text":"wake test"}]}'` 4. The attach client TUI should render the new user message + assistant response Refs hivemind anomalyco#221 (wake-up display bug verified in production) and anomalyco#222 Phase 2 patch 2c.
✅ Verified end-to-end 2026-05-26T16:14ZBuilt attach client from this branch via Setup confirmed
External wake test
Comparison with un-patched system opencodeThe same external wake fired against an un-patched attach client (verified earlier in hivemind #221) — daemon processed the wake, LLM ran, assistant message written to opencode.db, but nothing rendered in the TUI. Patched build: renders correctly. This unblocks the hivemind autonomous-coordinator vision: peers can now wake each other and Nik sees the activity in real time without manually polling the daemon or opening hivemind-ui. |
Without this, externally-triggered session activity (a wake fired via POST /session/<id>/prompt_async from another peer) never renders in attach client TUIs. The wake processes server-side (LLM runs, message written to db), but the attach client has no way to learn about it. ## Root cause attach.ts called tui() without passing `events`. The SDKProvider had a fallback path (startSSE() in context/sdk.tsx onMount) that should have subscribed to /global/event when props.events was undefined. In practice that fallback is silent on failure — its async IIFE catches every error. This patch explicitly creates an EventSource in attach.ts that subscribes to /global/event via the SDK and forwards events to the SDKProvider, mirroring how the local-worker case in thread.ts wires `events: createEventSource(client)`. ## Verification Local typecheck passes (`bun typecheck` from packages/opencode). Manual end-to-end test plan (requires rebuilt binary): 1. Start `opencode serve --port 4096` in one terminal 2. `opencode attach http://127.0.0.1:4096 --dir <project>` in another 3. From a third terminal: `curl -X POST 'http://127.0.0.1:4096/session/<id>/prompt_async' -H 'Content-Type: application/json' -d '{"parts":[{"type":"text","text":"wake test"}]}'` 4. The attach client TUI should render the new user message + assistant response Refs hivemind anomalyco#221 (wake-up display bug verified in production) and anomalyco#222 Phase 2 patch 2c.
Problem
When opencode runs in attach mode (
opencode attach <url>), externally-triggered session activity never renders in the TUI. Specifically: if peer A POSTs to/session/<id>/prompt_asyncwhile peer B is attached to that same session, the daemon processes the wake (the LLM runs, the assistant message is written to opencode.db) but peer B's screen shows nothing.Verified in production by grunt-it (hivemind anomalyco#221):
service=bus type=message.updated publishingafter the POSTcurl <daemon>/session/<id>/messagereturns the new messagesRoot cause
attach.tscallstui({...})without passingevents. The SDKProvider'sonMounthas a fallback path:startSSE()is an async IIFE that callssdk.global.event({ sseMaxRetryAttempts: 0 })and forwards events to the local emitter. In practice this fallback is silent on failure — the outer.catch(() => {})(line 108 ofcontext/sdk.tsx) swallows every error including the SSE-connect failure I observed in production.Fix
attach.tsnow explicitly creates anEventSourcethat subscribes to/global/eventvia the SDK, mirroring how the local-worker case inthread.tswiresevents: createEventSource(client). Caller (SDKProvider) seesprops.eventsdefined and uses the explicit subscription instead of the silent fallback.The new
createAttachEventSourceis intentionally one-shot (no reconnect loop). Reconnect-on-disconnect can be a follow-up; the silent fallback is the immediate bug.Verification
bun typecheckfrompackages/opencodepasses.Notes for upstream (anomalyco/opencode)
Will open an equivalent PR against
anomalyco/opencode:devonce we've verified the fix end-to-end on a built binary. The bug exists in upstream too.