feat(assistant): detached chat jobs + subscribe stream + proactive messages#16
Merged
Merged
Conversation
…ssages Replaces the single-request SSE chat (which timed out on long tool-loops and couldn't deliver server-initiated content) with a job + subscribe architecture: - POST /api/assistant/chat now returns immediately with the message IDs. The LLM tool-loop runs as a detached background job that writes to the DB on completion. Long tasks no longer fail when the proxy times out or the phone screen sleeps. - New GET /api/assistant/stream is a long-lived SSE the client opens once per session via EventSource. Replays missed messages since a cursor on reconnect, then live-subscribes to bus events. 25s heartbeats keep proxy NATs warm. - New POST /api/assistant/fire (bearer-auth) lets background processes inject server-initiated assistant messages — they appear in the chat thread the moment they happen, not just as Web Push. - In-process EventEmitter (apps/web/lib/assistant-bus.ts) connects the detached chat job and the fire endpoint to open stream subscribers. - Schema: assistant_messages.status (pending/streaming/done/error) + startup repair to mark orphaned rows from a prior process as error. - SW push handler also postMessage()s open clients as a belt-and- suspenders nudge to refresh. Scanner integration (outside repo, in C:\mcp-servers): - reminders.py and sunnapana.py post into the chat thread via the new endpoint after firing push / sending an email reply. Tests: 12 new (5 bus + 6 fire route + existing). 48/48 pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POST /api/assistant/chatreturns immediately with the message IDs; the LLM tool-loop runs as a detached background job and writes to the DB on completion. Proxy timeouts and phone-screen sleep stop killing in-flight turns.GET /api/assistant/streamis a long-lived SSE the client opens once per session via EventSource. Replays missed messages since a cursor on reconnect, then live-subscribes to bus events. 25s heartbeats keep proxy NATs warm. Auto-reconnect with exponential backoff is free from the browser.POST /api/assistant/fire(bearer-auth) lets background processes (reminders, SuNaPaNa email replies, future scanners) inject server-initiated assistant messages. They appear in the chat thread the moment they happen — chat now feels bidirectional.apps/web/lib/assistant-bus.ts) connects detached jobs and the fire endpoint to open stream subscribers. Single-instance assumption; swap for Redis pub/sub if we ever scale out.assistant_messages.status(pending/streaming/done/error) + startup repair to mark orphaned rows from a prior process as error.pushhandler alsopostMessages open clients as a belt-and-suspenders refresh nudge.Out-of-repo (in
C:\mcp-servers)reminders.pyandsunnapana.pyPOST to/api/assistant/fireafter firing push / sending an email reply, so the activity shows up in the chat thread too.outlook-email/push_config.jsongainedassistant_fire_url.Test plan
pnpm turbo run test --filter=@mysuperapp/web— 48/48 (5 new bus + 6 new fire route)pnpm --filter @mysuperapp/web buildclean, all/api/assistant/*routes registeredPOST /api/assistant/firesmoke: lazily creates inbox conversation, persists message, returns IDsGET /api/assistant/stream?since=<iso>emits past messages🤖 Generated with Claude Code