# Paper Draft Streaming Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Stream paper draft markdown into the paper draft page as it is generated, then save the completed draft. **Architecture:** Add a dedicated streaming paper draft endpoint that reuses the existing prompt builder and forwards DeepSeek streaming deltas to the browser. The frontend uses `fetch` with `ReadableStream` so authorization headers and JSON request bodies continue to work. **Tech Stack:** Spring Boot 2.5, `StreamingResponseBody`, DeepSeek chat completions streaming, Vue 3, fetch streams, existing paper persistence API. --- ### Task 1: Backend Streaming Contract **Files:** - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/IDeepSeekClient.java` - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/HttpDeepSeekClient.java` - Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/HttpDeepSeekClientTest.java` - [ ] Add a `StreamHandler` callback contract to `IDeepSeekClient`. - [ ] Write a failing test that feeds SSE lines with `choices[0].delta.content` and verifies chunks are emitted in order. - [ ] Implement DeepSeek `stream: true` parsing for `data:` lines and `[DONE]`. - [ ] Keep the existing non-streaming `chat` behavior unchanged. ### Task 2: Paper Draft Stream Service And Controller **Files:** - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/IAiGenerateService.java` - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java` - Modify: `ruoyi-admin/src/main/java/com/ruoyi/web/controller/front/FrontProjectController.java` - Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerateServiceImplTest.java` - [ ] Add `streamPaperDraft(userId, projectId, request, handler)` to the AI service. - [ ] Write a failing test proving `streamPaperDraft` reuses the paper draft prompt and emits sanitized chunks. - [ ] Add `POST /front/project/{projectId}/paper-draft/stream` returning `text/plain;charset=UTF-8` as a streaming response. - [ ] Ensure exceptions are propagated so the frontend can show failure instead of saving partial text as completed output. ### Task 3: Frontend Stream Consumption **Files:** - Modify: `easycode-web/src/api/project.js` - Modify: `easycode-web/src/views/PaperDraftView.vue` - Test: `easycode-web/src/views/paperDraftView.test.mjs` - [ ] Add `streamPaperDraft(projectId, data, handlers)` using `fetch`, `Authorization`, and `ReadableStream`. - [ ] Update `handleGenerateDraft` to clear old text, stream chunks into `draftMarkdown`, keep the preview tab active, then call `savePaperDraft({ silent: true })`. - [ ] Add an abort controller and show a Stop button while streaming. - [ ] Add source-level tests checking the stream API is imported, the stop action exists, and the old synchronous `generatePaperDraft` path is no longer used by the page. ### Task 4: Verification **Files:** - Test commands only. - [ ] Run `node --test easycode-web/src/views/paperDraftView.test.mjs easycode-web/src/utils/markdown.test.mjs`. - [ ] Run `mvn -pl ruoyi-generator "-Dtest=AiGenerateServiceImplTest#generatePaper*,HttpDeepSeekClientTest" test`. - [ ] Report any unrelated existing red tests separately from the focused streaming checks.