Skip to content

[Phase A2] Stream LLM responses via SSE for follow-up and draft generation #18

@terisuke

Description

@terisuke

Tracked under ADR 0002 — Phase A. Detail: implementation plan §A2.

Problem

Every LLM call blocks the UI behind a full-screen spinner (static/js/script.js:407). A 3000-character draft on gemma4:31b can take 60–180 seconds; the user has no signal that progress is happening. Comparable products (Claude, ChatGPT, Gemini) stream tokens, which dramatically improves perceived responsiveness.

Scope

  • Add SSE support to internal/infrastructure/llamacpp/client.go (OpenAI-compatible stream: true).
  • Wire streaming into:
    • application/brief.InterviewService.GenerateFollowUp — chunks append to the live deep-dive bubble.
    • application/draft.GenerateDraftService.Generate — chunks append to the right-rail draft preview.
  • application/authorstyle.AnalyzeAuthorStyleService stays non-streaming (single short call, no UX win).
  • Frontend swaps the global spinner for token-by-token append.
  • New endpoints (or Accept: text/event-stream overload of existing endpoints): clearly documented in the implementation plan.

Acceptance criteria

  • A 3000-character draft visibly streams; first token < 3s on warm gemma4:31b.
  • Network tab shows text/event-stream content type with incremental chunks.
  • Cancelling mid-stream stops the LLM call (server-side context cancellation propagates to llama.cpp).
  • Non-streaming path remains for tests; goldenfile tests use concatenated chunks as the canonical comparison.
  • No regression in existing go test ./....

Out of scope

  • Persona/format awareness (Phase B).
  • Retry-on-disconnect resilience (note as follow-up if needed).

Files likely touched

  • internal/infrastructure/llamacpp/client.go
  • internal/application/brief/service.go
  • internal/application/draft/service.go
  • internal/handlers/workflow.go
  • static/js/script.js

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions