docs: add final report for SSE migration
This commit is contained in:
@@ -0,0 +1,645 @@
|
||||
# SSE Migration Implementation Plan
|
||||
|
||||
> [!NOTE]
|
||||
> This document may not reflect the current implementation.
|
||||
> See the final report for up-to-date state:
|
||||
> [Final Report](../reports/sse-migration.md)
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use compose:subagent (recommended) or compose:execute to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Replace polling-based message reception with SSE (Server-Sent Events) for real-time message delivery from signal-cli.
|
||||
|
||||
**Architecture:** Create a new `noise-sse.el` module that implements an SSE client using Emacs process filters. The client connects to signal-cli's `/api/v1/events` endpoint, parses incoming SSE events, and feeds them to the existing envelope processing pipeline. Includes automatic reconnection with exponential backoff.
|
||||
|
||||
**Tech Stack:** Emacs Lisp, `make-network-process`, `url.el` for URL parsing, existing `noise-receive.el` envelope processing.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
| File | Action | Purpose |
|
||||
|------|--------|---------|
|
||||
| `noise-sse.el` | Create | SSE client with process filter, reconnection logic |
|
||||
| `noise-receive.el` | Modify | Remove polling, add SSE start/stop functions |
|
||||
| `noise.el` | Modify | Update `noise-mode` to use SSE |
|
||||
| `test/noise-sse-test.el` | Create | Unit tests for SSE parsing and reconnection |
|
||||
| `test/noise-receive-test.el` | Modify | Update tests for SSE integration |
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Create SSE Client Core
|
||||
|
||||
**Covers:** S1 (SSE connection management)
|
||||
|
||||
**Files:**
|
||||
- Create: `noise-sse.el`
|
||||
- Test: `test/noise-sse-test.el`
|
||||
|
||||
- [ ] **Step 1: Write failing test for SSE event parsing**
|
||||
|
||||
```elisp
|
||||
;; test/noise-sse-test.el
|
||||
(require 'ert)
|
||||
(require 'noise-sse)
|
||||
|
||||
(ert-deftest noise-sse--parse-event-basic ()
|
||||
"Parse a basic SSE event with data field."
|
||||
(let ((event "data: {\"type\":\"message\",\"content\":\"hello\"}\n\n"))
|
||||
(let ((result (noise-sse--parse-event event)))
|
||||
(should (hash-table-p result))
|
||||
(should (equal (gethash "type" result) "message"))
|
||||
(should (equal (gethash "content" result) "hello")))))
|
||||
|
||||
(ert-deftest noise-sse--parse-event-multiline ()
|
||||
"Parse SSE event with multiline data."
|
||||
(let ((event "data: {\"type\":\"message\"\ndata: \"content\":\"hello\"}\n\n"))
|
||||
(let ((result (noise-sse--parse-event event)))
|
||||
(should (hash-table-p result))
|
||||
(should (equal (gethash "type" result) "message")))))
|
||||
|
||||
(ert-deftest noise-sse--parse-event-empty ()
|
||||
"Parse empty SSE event returns nil."
|
||||
(let ((event "\n\n"))
|
||||
(should (null (noise-sse--parse-event event)))))
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: FAIL with "void-function noise-sse--parse-event"
|
||||
|
||||
- [ ] **Step 3: Write minimal SSE parsing implementation**
|
||||
|
||||
```elisp
|
||||
;; noise-sse.el --- SSE client for signal-cli -*- lexical-binding: t; -*-
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Implements Server-Sent Events client for receiving real-time messages
|
||||
;; from signal-cli daemon's /api/v1/events endpoint.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'url)
|
||||
(require 'json)
|
||||
(require 'cl-lib)
|
||||
|
||||
(defun noise-sse--parse-event (event-string)
|
||||
"Parse an SSE EVENT-STRING into a hash table.
|
||||
Returns nil for empty or invalid events."
|
||||
(when (and event-string (not (string-empty-p event-string)))
|
||||
(let ((lines (split-string event-string "\n"))
|
||||
(data-lines '()))
|
||||
(dolist (line lines)
|
||||
(when (string-prefix-p "data: " line)
|
||||
(push (substring line 6) data-lines)))
|
||||
(when data-lines
|
||||
(let ((json-str (mapconcat #'identity (nreverse data-lines) "")))
|
||||
(condition-case nil
|
||||
(json-parse-string json-str)
|
||||
(error nil)))))))
|
||||
|
||||
(provide 'noise-sse)
|
||||
;;; noise-sse.el ends here
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add noise-sse.el test/noise-sse-test.el
|
||||
git commit -m "feat: add SSE event parsing for signal-cli"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Add SSE Connection Management
|
||||
|
||||
**Covers:** S1, S2 (connection lifecycle, reconnection)
|
||||
|
||||
**Files:**
|
||||
- Modify: `noise-sse.el`
|
||||
- Modify: `test/noise-sse-test.el`
|
||||
|
||||
- [ ] **Step 1: Write failing tests for connection state**
|
||||
|
||||
```elisp
|
||||
;; Add to test/noise-sse-test.el
|
||||
|
||||
(ert-deftest noise-sse--initial-state ()
|
||||
"SSE client starts in disconnected state."
|
||||
(let ((noise-sse--process nil)
|
||||
(noise-sse--reconnect-timer nil)
|
||||
(noise-sse--reconnect-delay 1))
|
||||
(should (null noise-sse--process))
|
||||
(should (null noise-sse--reconnect-timer))
|
||||
(should (= 1 noise-sse--reconnect-delay))))
|
||||
|
||||
(ert-deftest noise-sse--reconnect-delay-backoff ()
|
||||
"Reconnect delay doubles on each attempt."
|
||||
(let ((noise-sse--reconnect-delay 1))
|
||||
(noise-sse--increase-reconnect-delay)
|
||||
(should (= 2 noise-sse--reconnect-delay))
|
||||
(noise-sse--increase-reconnect-delay)
|
||||
(should (= 4 noise-sse--reconnect-delay))
|
||||
(noise-sse--increase-reconnect-delay)
|
||||
(should (= 8 noise-sse--reconnect-delay))))
|
||||
|
||||
(ert-deftest noise-sse--reconnect-delay-max ()
|
||||
"Reconnect delay caps at max value."
|
||||
(let ((noise-sse--reconnect-delay 32)
|
||||
(noise-sse--max-reconnect-delay 60))
|
||||
(noise-sse--increase-reconnect-delay)
|
||||
(should (= 60 noise-sse--reconnect-delay))))
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: FAIL with "void-function noise-sse--increase-reconnect-delay"
|
||||
|
||||
- [ ] **Step 3: Implement connection state and reconnection logic**
|
||||
|
||||
```elisp
|
||||
;; Add to noise-sse.el after requires
|
||||
|
||||
(defvar noise-sse--process nil
|
||||
"Active SSE network process, or nil.")
|
||||
|
||||
(defvar noise-sse--reconnect-timer nil
|
||||
"Timer for reconnection attempts, or nil.")
|
||||
|
||||
(defvar noise-sse--reconnect-delay 1
|
||||
"Current delay in seconds before next reconnection attempt.")
|
||||
|
||||
(defvar noise-sdefcustom noise-sse-max-reconnect-delay 60
|
||||
"Maximum delay in seconds between reconnection attempts."
|
||||
:type 'integer
|
||||
:group 'noise)
|
||||
|
||||
(defun noise-sse--increase-reconnect-delay ()
|
||||
"Increase reconnect delay with exponential backoff, capped at max."
|
||||
(setq noise-sse--reconnect-delay
|
||||
(min (* noise-sse--reconnect-delay 2)
|
||||
noise-sse-max-reconnect-delay)))
|
||||
|
||||
(defun noise-sse--reset-reconnect-delay ()
|
||||
"Reset reconnect delay to initial value after successful connection."
|
||||
(setq noise-sse--reconnect-delay 1))
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add noise-sse.el test/noise-sse-test.el
|
||||
git commit -m "feat: add SSE connection state and reconnection logic"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Implement Process Filter for SSE Stream
|
||||
|
||||
**Covers:** S1, S3 (real-time event processing)
|
||||
|
||||
**Files:**
|
||||
- Modify: `noise-sse.el`
|
||||
- Modify: `test/noise-sse-test.el`
|
||||
|
||||
- [ ] **Step 1: Write failing test for process filter**
|
||||
|
||||
```elisp
|
||||
;; Add to test/noise-sse-test.el
|
||||
|
||||
(ert-deftest noise-sse--filter-processes-complete-event ()
|
||||
"Process filter parses and calls handler for complete events."
|
||||
(let ((processed-events '()))
|
||||
(cl-letf (((symbol-function 'noise-sse--handle-event)
|
||||
(lambda (event) (push event processed-events))))
|
||||
(let ((noise-sse--buffer ""))
|
||||
(noise-sse--filter nil "data: {\"type\":\"message\"}\n\n")
|
||||
(should (= 1 (length processed-events)))
|
||||
(should (hash-table-p (car processed-events)))))))
|
||||
|
||||
(ert-deftest noise-sse--filter-buffers-incomplete-event ()
|
||||
"Process filter buffers incomplete events until newline."
|
||||
(let ((processed-events '()))
|
||||
(cl-letf (((symbol-function 'noise-sse--handle-event)
|
||||
(lambda (event) (push event processed-events))))
|
||||
(let ((noise-sse--buffer ""))
|
||||
(noise-sse--filter nil "data: {\"type\":\"message\"")
|
||||
(should (= 0 (length processed-events)))
|
||||
(noise-sse--filter nil "}\n\n")
|
||||
(should (= 1 (length processed-events)))))))
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: FAIL with "void-function noise-sse--filter"
|
||||
|
||||
- [ ] **Step 3: Implement process filter**
|
||||
|
||||
```elisp
|
||||
;; Add to noise-sse.el
|
||||
|
||||
(defvar noise-sse--buffer ""
|
||||
"Buffer for partial SSE event data.")
|
||||
|
||||
(defun noise-sse--filter (proc string)
|
||||
"Process filter for SSE connection.
|
||||
Buffers incoming STRING and processes complete events."
|
||||
(setq noise-sse--buffer (concat noise-sse--buffer string))
|
||||
(while (string-match "\n\n" noise-sse--buffer)
|
||||
(let ((event-end (match-beginning 0))
|
||||
(event-start 0))
|
||||
(let ((event-str (substring noise-sse--buffer event-start event-end)))
|
||||
(setq noise-sse--buffer
|
||||
(substring noise-sse--buffer (+ event-end 2)))
|
||||
(when-let ((event (noise-sse--parse-event event-str)))
|
||||
(noise-sse--handle-event event))))))
|
||||
|
||||
(defun noise-sse--handle-event (event)
|
||||
"Handle a parsed SSE EVENT.
|
||||
This function will be overridden in noise-receive to process envelopes."
|
||||
(message "SSE event received: %s" event))
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add noise-sse.el test/noise-sse-test.el
|
||||
git commit -m "feat: add SSE process filter for stream parsing"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Implement SSE Connection Functions
|
||||
|
||||
**Covers:** S1, S2 (connection establishment, URL construction)
|
||||
|
||||
**Files:**
|
||||
- Modify: `noise-sse.el`
|
||||
- Modify: `test/noise-sse-test.el`
|
||||
|
||||
- [ ] **Step 1: Write failing test for URL construction**
|
||||
|
||||
```elisp
|
||||
;; Add to test/noise-sse-test.el
|
||||
|
||||
(ert-deftest noise-sse--build-url ()
|
||||
"Build SSE endpoint URL from base address."
|
||||
(let ((noise-signal-cli-address "http://localhost:8080")
|
||||
(noise-account "+15551234567"))
|
||||
(let ((url (noise-sse--build-url)))
|
||||
(should (string-match-p "/api/v1/events" url))
|
||||
(should (string-match-p "account=%2B15551234567" url)))))
|
||||
|
||||
(ert-deftest noise-sse--build-url-no-account ()
|
||||
"Build SSE endpoint URL without account parameter."
|
||||
(let ((noise-signal-cli-address "http://localhost:8080")
|
||||
(noise-account nil))
|
||||
(let ((url (noise-sse--build-url)))
|
||||
(should (string-match-p "/api/v1/events" url))
|
||||
(should-not (string-match-p "account=" url)))))
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: FAIL with "void-function noise-sse--build-url"
|
||||
|
||||
- [ ] **Step 3: Implement URL construction and connection**
|
||||
|
||||
```elisp
|
||||
;; Add to noise-sse.el
|
||||
|
||||
(declare-variable noise-signal-cli-address)
|
||||
(declare-variable noise-account)
|
||||
|
||||
(defun noise-sse--build-url ()
|
||||
"Build the SSE endpoint URL for signal-cli."
|
||||
(let ((base (concat noise-signal-cli-address "/api/v1/events")))
|
||||
(if (and (boundp 'noise-account) noise-account)
|
||||
(concat base "?account=" (url-hexify-string noise-account))
|
||||
base)))
|
||||
|
||||
(defun noise-sse--sentinel (proc status)
|
||||
"Process sentinel for SSE connection.
|
||||
Handles connection close and triggers reconnection."
|
||||
(when (or (equal status "finished\n")
|
||||
(string-match-p "failed" status)
|
||||
(string-match-p "deleted" status))
|
||||
(message "Noise: SSE connection lost, reconnecting in %ds..."
|
||||
noise-sse--reconnect-delay)
|
||||
(setq noise-sse--process nil)
|
||||
(noise-sse--schedule-reconnect)))
|
||||
|
||||
(defun noise-sse--schedule-reconnect ()
|
||||
"Schedule a reconnection attempt after the current delay."
|
||||
(when noise-sse--reconnect-timer
|
||||
(cancel-timer noise-sse--reconnect-timer))
|
||||
(setq noise-sse--reconnect-timer
|
||||
(run-with-timer noise-sse--reconnect-delay nil
|
||||
#'noise-sse-connect)))
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add noise-sse.el test/noise-sse-test.el
|
||||
git commit -m "feat: add SSE URL construction and connection management"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Implement Connect/Disconnect Functions
|
||||
|
||||
**Covers:** S1, S2 (public API, connection lifecycle)
|
||||
|
||||
**Files:**
|
||||
- Modify: `noise-sse.el`
|
||||
- Modify: `test/noise-sse-test.el`
|
||||
|
||||
- [ ] **Step 1: Write failing test for connect/disconnect**
|
||||
|
||||
```elisp
|
||||
;; Add to test/noise-sse-test.el
|
||||
|
||||
(ert-deftest noise-sse-connect-creates-process ()
|
||||
"noise-sse-connect creates a network process."
|
||||
(let ((noise-signal-cli-address "http://localhost:8080")
|
||||
(noise-account nil)
|
||||
(noise-sse--process nil)
|
||||
(created-process nil))
|
||||
(cl-letf (((symbol-function 'make-network-process)
|
||||
(lambda (&rest args) (setq created-process t) (make-identity-process "test"))))
|
||||
(noise-sse-connect)
|
||||
(should created-process)
|
||||
(when noise-sse--process
|
||||
(delete-process noise-sse--process)))))
|
||||
|
||||
(ert-deftest noise-sse-disconnect-cleans-up ()
|
||||
"noise-sse-disconnect cleans up process and timer."
|
||||
(let ((noise-sse--process (make-identity-process "test"))
|
||||
(noise-sse--reconnect-timer (run-with-timer 1000 nil #'ignore)))
|
||||
(noise-sse-disconnect)
|
||||
(should (null noise-sse--process))
|
||||
(should (null noise-sse--reconnect-timer))))
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: FAIL with "void-function noise-sse-connect"
|
||||
|
||||
- [ ] **Step 3: Implement connect/disconnect functions**
|
||||
|
||||
```elisp
|
||||
;; Add to noise-sse.el
|
||||
|
||||
;;;###autoload
|
||||
(defun noise-sse-connect ()
|
||||
"Connect to signal-cli SSE endpoint."
|
||||
(interactive)
|
||||
(noise-sse-disconnect)
|
||||
(let* ((url (noise-sse--build-url))
|
||||
(parsed (url-generic-parse-url url))
|
||||
(host (url-host parsed))
|
||||
(port (or (url-port parsed) 80))
|
||||
(proc (make-network-process
|
||||
:name "noise-sse"
|
||||
:host host
|
||||
:port port
|
||||
:filter #'noise-sse--filter
|
||||
:sentinel #'noise-sse--sentinel)))
|
||||
(setq noise-sse--process proc)
|
||||
(noise-sse--reset-reconnect-delay)
|
||||
(process-send-string proc
|
||||
(format "GET %s HTTP/1.1\r\nHost: %s\r\nAccept: text/event-stream\r\n\r\n"
|
||||
(url-filename parsed)
|
||||
host))
|
||||
(message "Noise: SSE connected to %s" url)))
|
||||
|
||||
;;;###autoload
|
||||
(defun noise-sse-disconnect ()
|
||||
"Disconnect from signal-cli SSE endpoint."
|
||||
(interactive)
|
||||
(when noise-sse--process
|
||||
(delete-process noise-sse--process)
|
||||
(setq noise-sse--process nil))
|
||||
(when noise-sse--reconnect-timer
|
||||
(cancel-timer noise-sse--reconnect-timer)
|
||||
(setq noise-sse--reconnect-timer nil))
|
||||
(setq noise-sse--buffer "")
|
||||
(message "Noise: SSE disconnected"))
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `emacs -batch -l ert -l test/noise-sse-test.el -f ert-run-tests-batch-and-exit`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add noise-sse.el test/noise-sse-test.el
|
||||
git commit -m "feat: add SSE connect/disconnect public API"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Integrate SSE with Message Reception
|
||||
|
||||
**Covers:** S1, S3, S4 (integration with existing envelope processing)
|
||||
|
||||
**Files:**
|
||||
- Modify: `noise-receive.el`
|
||||
- Modify: `noise-sse.el`
|
||||
|
||||
- [ ] **Step 1: Add SSE event handler to noise-receive.el**
|
||||
|
||||
```elisp
|
||||
;; Add to noise-receive.el after requires
|
||||
|
||||
(require 'noise-sse)
|
||||
|
||||
(defun noise-receive--handle-sse-event (event)
|
||||
"Handle an SSE EVENT from signal-cli.
|
||||
Processes the envelope and updates UI."
|
||||
(noise-db-init)
|
||||
(when-let ((envelope (noise-receive--field event "envelope")))
|
||||
(when-let ((conv-id (noise-receive--process-envelope envelope)))
|
||||
(noise-conversation-refresh-for conv-id)
|
||||
(when-let ((buf (get-buffer "*signal*")))
|
||||
(with-current-buffer buf
|
||||
(noise-chat-list--render))))))
|
||||
|
||||
;; Override the default handler in noise-sse
|
||||
(setq noise-sse--handle-event #'noise-receive--handle-sse-event)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add SSE start/stop functions**
|
||||
|
||||
```elisp
|
||||
;; Add to noise-receive.el
|
||||
|
||||
;;;###autoload
|
||||
(defun noise-receive-start-sse ()
|
||||
"Start receiving messages via SSE."
|
||||
(interactive)
|
||||
(noise-sse-connect))
|
||||
|
||||
;;;###autoload
|
||||
(defun noise-receive-stop-sse ()
|
||||
"Stop receiving messages via SSE."
|
||||
(interactive)
|
||||
(noise-sse-disconnect))
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Remove polling functions**
|
||||
|
||||
```elisp
|
||||
;; Remove from noise-receive.el:
|
||||
;; - noise-receive-interval defcustom
|
||||
;; - noise-receive--timer defvar
|
||||
;; - noise-receive--last-poll-error defvar
|
||||
;; - noise-receive-start-polling function
|
||||
;; - noise-receive-stop-polling function
|
||||
;; - noise-receive--poll function
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Update tests**
|
||||
|
||||
```elisp
|
||||
;; Update test/noise-receive-poll-test.el to test SSE integration
|
||||
;; or rename to test/noise-receive-test.el
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add noise-receive.el noise-sse.el
|
||||
git commit -m "feat: integrate SSE with message reception pipeline"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Update Noise Mode
|
||||
|
||||
**Covers:** S4 (user-facing mode toggle)
|
||||
|
||||
**Files:**
|
||||
- Modify: `noise.el`
|
||||
|
||||
- [ ] **Step 1: Update noise-mode to use SSE**
|
||||
|
||||
```elisp
|
||||
;; In noise.el, update noise-mode definition:
|
||||
|
||||
(define-minor-mode noise-mode
|
||||
"Toggle Noise Signal client mode."
|
||||
:global t
|
||||
:lighter " Noise"
|
||||
:group 'noise
|
||||
(if noise-mode
|
||||
(progn
|
||||
(noise-chat-list)
|
||||
(noise-receive-start-sse))
|
||||
(noise-receive-stop-sse)
|
||||
(message "Noise mode disabled")))
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add SSE configuration options**
|
||||
|
||||
```elisp
|
||||
;; Add to noise.el defcustom section:
|
||||
|
||||
(defcustom noise-sse-max-reconnect-delay 60
|
||||
"Maximum delay in seconds between SSE reconnection attempts."
|
||||
:type 'integer
|
||||
:group 'noise)
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add noise.el
|
||||
git commit -m "feat: update noise-mode to use SSE instead of polling"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 8: Documentation and Cleanup
|
||||
|
||||
**Covers:** S5 (documentation updates)
|
||||
|
||||
**Files:**
|
||||
- Modify: `README.md`
|
||||
- Modify: `AGENTS.md`
|
||||
|
||||
- [ ] **Step 1: Update README.md**
|
||||
|
||||
```markdown
|
||||
## How it works
|
||||
|
||||
Noise uses Server-Sent Events (SSE) to receive messages in real-time from
|
||||
signal-cli. When a message arrives, it's instantly processed and displayed.
|
||||
|
||||
### SSE Connection
|
||||
|
||||
- Connects to `signal-cli` at `/api/v1/events`
|
||||
- Automatic reconnection with exponential backoff on disconnect
|
||||
- Configurable via `noise-sse-max-reconnect-delay`
|
||||
|
||||
### Manual Refresh
|
||||
|
||||
You can manually refresh messages with `M-x noise-receive` even while
|
||||
SSE is running.
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Update AGENTS.md**
|
||||
|
||||
```markdown
|
||||
## Architecture
|
||||
|
||||
- Uses SSE (Server-Sent Events) for real-time message reception
|
||||
- `noise-sse.el` handles connection and event parsing
|
||||
- `noise-receive.el` processes envelopes and updates UI
|
||||
- Automatic reconnection with exponential backoff
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add README.md AGENTS.md
|
||||
git commit -m "docs: update documentation for SSE migration"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Self-Review Checklist
|
||||
|
||||
- [ ] **Spec coverage:** All design requirements covered by tasks
|
||||
- [ ] **Placeholder scan:** No TBD/TODO/placeholders in steps
|
||||
- [ ] **Type consistency:** Function names and signatures consistent across tasks
|
||||
- [ ] **Test coverage:** Each component has corresponding tests
|
||||
- [ ] **Commit frequency:** Each task has meaningful commit points
|
||||
Reference in New Issue
Block a user