Replace artifact polling with SSE push for sub-second new-artifact toasts #34
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lz/agent-nexus#34
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
When the agent calls
notify-artifactfrom a session pane, the operator (sitting on the Session Terminal tab) sees nothing happen for up to 7 seconds. That's the upper bound of the current architecture:ArtifactsStorepolls/api/workers/:id/sessions/:sid/artifactsevery 5 seconds (POLL_MSinnexus/src/lib/artifacts-store.svelte.ts).toastQueue.enqueuethen waits 2 seconds for a burst window (burstMsinnexus/src/lib/artifacts-toast.svelte.ts) before flushing the toast.So in the median case it takes ~3.5s, worst case ~7s. Operators tested it under 10s and concluded "nothing happens" — silence is bad UX even when the system is technically working.
Proposed fix
Replace polling with server-sent events (SSE) for the foreground per-session artifact stream:
/api/workers/:id/sessions/:sid/artifacts/streamthat yields a JSON-line event whenever an artifact for that session is created/updated/deleted./api/agent/artifacts(and the operator endpoints under/api/workers/:id/sessions/:sid/artifacts*) to emit on a per-session in-process EventEmitter (or a singletonMap<sessionId, Set<sseClient>>).ArtifactsStore.start()'ssetIntervalwith anEventSourcesubscription. Fall back to polling if the SSE connection fails (keeps the contract simple —onNewcallback unchanged).toastQueue.enqueuecan stay at 2s, OR drop to ~200ms now that the inbound stream is real-time. The window exists to collapse rapid bursts ofnotify-artifactcalls into one toast; with SSE the actual time-to-toast becomes burst-window + 1 network hop (~250ms).End result: notify-artifact → toast appears in ~250ms.
Scope notes
Map<sessionId, Set<Response>>innexus/src/lib/server/singletons.tsis plenty for the single-operator model. No Redis pubsub or external broker needed.:\n\n) every ~30s to keep proxies from idling the connection. SvelteKit's adapter-node should pass through SSE cleanly; the customnexus/src/server.tswe already maintain (for the WebSocket upgrade listener) gives us flexibility here./api/*is gated globally inhooks.server.ts— the SSE endpoint inherits the same operator-session check.Last-Event-IDheader for replay? Probably YAGNI for v1: the next reconnect's poll-fallback or initial list refetch closes any window we miss.Why open this instead of fix-now
The two-system change (server emitter + client EventSource + fallback) is wider than the polish in PR #31. The companion survey issue (linked once filed) explores whether the same SSE infrastructure should also cover previews, worker/session health, file-explorer changes, etc. — better to design the channel once than to bolt on a one-off endpoint just for artifacts.
Acceptance criteria
notify-artifact→ toast visible within 1s on the in-app Artifacts tab AND on Files/Terminal tabs (whichever has the bgStore equivalent).tested with 60s idle).vitesttest suite.ArtifactsStore.onNewcallback contract unchanged —MainSplitandArtifactsPanelshould not need to change beyond replacingstore.start().