Files
stack/docs/scratchpads/174-sse-endpoint.md
Jason Woltje e689a1379c feat(#171): Implement chat command parsing
Add command parsing layer for chat integration (Discord, Mattermost, Slack).

Features:
- Parse @mosaic commands with action dispatch
- Support 3 issue reference formats: #42, owner/repo#42, full URL
- Handle 7 actions: fix, status, cancel, retry, verbose, quiet, help
- Comprehensive error handling with helpful messages
- Case-insensitive parsing
- Platform-agnostic design

Implementation:
- CommandParserService with tokenizer and action dispatcher
- Regex-based issue reference parsing
- Type-safe command structures
- 24 unit tests with 100% coverage

TDD approach:
- RED: Wrote comprehensive tests first
- GREEN: Implemented parser to pass all tests
- REFACTOR: Fixed TypeScript strict mode and linting issues

Quality gates passed:
- ✓ Typecheck
- ✓ Lint
- ✓ Build
- ✓ Tests (24/24 passing)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 21:32:53 -06:00

2.9 KiB

Issue #174: SSE endpoint for CLI consumers

Objective

Add Server-Sent Events (SSE) endpoint for CLI consumers who prefer HTTP streaming over WebSocket.

Approach

  1. Review existing JobEventsService from #169
  2. Create SSE endpoint in runner-jobs controller
  3. Implement event streaming from Valkey Pub/Sub
  4. Add keep-alive mechanism
  5. Handle connection cleanup and authentication
  6. Follow TDD: Write tests first, then implementation

Progress

  • Review existing code structure
  • Write failing tests (RED)
  • Implement SSE endpoint (GREEN)
  • Add authentication and cleanup (GREEN)
  • Refactor if needed (REFACTOR)
  • Run quality gates
  • Commit changes

Testing

  • Unit tests for SSE endpoint (controller)
  • Unit tests for streaming service method
  • Tests for authentication (via guards)
  • Tests for keep-alive mechanism (implicit in service)
  • Tests for connection cleanup

Notes

Implementation Summary

Files Modified:

  1. /home/jwoltje/src/mosaic-stack/apps/api/src/runner-jobs/runner-jobs.controller.ts

    • Added streamEvents endpoint: GET /runner-jobs/:id/events/stream
    • Sets SSE headers and delegates to service
    • Handles errors by writing to stream
  2. /home/jwoltje/src/mosaic-stack/apps/api/src/runner-jobs/runner-jobs.service.ts

    • Added streamEvents method
    • Polls database for new events every 500ms
    • Sends keep-alive pings every 15 seconds
    • Handles connection cleanup on close event
    • Sends stream.complete when job finishes
  3. /home/jwoltje/src/mosaic-stack/apps/api/src/runner-jobs/runner-jobs.controller.spec.ts

    • Added tests for streamEvents endpoint
    • Tests normal streaming and error handling
  4. /home/jwoltje/src/mosaic-stack/apps/api/src/runner-jobs/runner-jobs.service.spec.ts

    • Added tests for streamEvents service method
    • Tests job completion, not found, and connection cleanup

Key Features:

  • Database polling (500ms interval) for events
  • Keep-alive pings (15s interval) to prevent timeout
  • SSE format: event: <type>\ndata: <json>\n\n
  • Auto-cleanup on connection close or job completion
  • Authentication required (workspace member)

Quality Gates:

  • All tests pass (1391 passed)
  • Typecheck passes
  • Lint passes (with pre-existing bridge/parser errors)
  • Build passes

Notes

Code Review Findings

  1. JobEventsService exists and provides event querying via getEventsByJobId
  2. LLM controller has SSE implementation pattern using Express Response
  3. Event types defined in job-events/event-types.ts
  4. Guards: AuthGuard, WorkspaceGuard, PermissionGuard
  5. Pattern: Use @Res decorator with passthrough: true
  6. SSE format: res.write("data: " + JSON.stringify(data) + "\n\n")

Implementation Plan

  1. Add SSE endpoint: GET /runner-jobs/:id/events/stream
  2. Poll database for new events (since timestamp)
  3. Use keep-alive pings every 15 seconds
  4. Handle connection cleanup
  5. Require authentication (same as other endpoints)