# Upload And Extract Episodes Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Add file upload for `.docx`, `.txt`, `.pdf`, and `.md` in conversion mode, stream a Doubao-based episode extraction result into the source textarea, and preserve the existing conversion workflow. **Architecture:** Extend the conversion UI in `src/App.tsx` with upload controls and extraction state, add browser-side file parsing helpers for the four formats, and create a new streaming Doubao extraction method in `src/services/ai.ts`. The extraction result should progressively replace `sourceText`, then hand control back to the user for the existing conversion step. **Tech Stack:** React 19, TypeScript, Vite, OpenAI SDK, browser file APIs, PDF/docx parsing libraries --- ### Task 1: Add dependency and extraction API surface **Files:** - Modify: `package.json` - Modify: `src/services/ai.ts` **Step 1: Write the failing test surrogate** Use TypeScript as the first guard by adding a new extraction function signature and references from `App.tsx` before implementation is complete. **Step 2: Run verification to confirm the break** Run: `npm run lint` Expected: FAIL because the new extraction path is not fully wired. **Step 3: Write minimal implementation** - Add any needed client-side parsing dependencies. - Add `extractEpisodesFromSource` in `src/services/ai.ts`. - Use model `doubao-seed-1-6-flash-250828`. - Stream chunks through a callback similar to the existing conversion flow. - Build a strict prompt requiring 1:1 episode/script extraction with no edits. **Step 4: Re-run verification** Run: `npm run lint` Expected: still failing until UI wiring is complete. ### Task 2: Add browser-side file parsing helpers **Files:** - Create: `src/services/fileParsing.ts` - Modify: `src/App.tsx` **Step 1: Write the failing test surrogate** Reference helper APIs from `App.tsx` before the helper module is complete. **Step 2: Implement minimal parsing** - Support `.txt` and `.md` via plain text reads. - Support `.docx` via browser text extraction. - Support `.pdf` via browser PDF text extraction. - Return normalized raw text for LLM input without attempting episode splitting locally. **Step 3: Handle unsupported files** - Reject anything outside the four allowed extensions. - Return actionable error messages. ### Task 3: Wire upload UX into conversion mode **Files:** - Modify: `src/App.tsx` **Step 1: Add state** - Add extraction progress/loading/error state. - Keep `sourceText` persistence unchanged. **Step 2: Add UI** - Add file upload control near the source textarea. - Show supported formats. - Show extraction-in-progress feedback distinct from the existing conversion action. **Step 3: Add upload flow** - On file select, parse the file. - Start the streaming extraction call immediately. - Replace `sourceText` incrementally with streamed content. - Preserve manual editing after completion. ### Task 4: Verify behavior and guardrails **Files:** - Modify: `src/App.tsx` - Modify: `src/services/ai.ts` - Modify: `package.json` **Step 1: Run type check** Run: `npm run lint` Expected: PASS **Step 2: Run build** Run: `npm run build` Expected: PASS **Step 3: Manual review checklist** - Upload accepts only `.docx`, `.txt`, `.pdf`, `.md`. - Upload starts extraction immediately. - Left source textarea updates in streaming fashion. - Extraction uses the raw-output contract and does not intentionally rewrite content. - Existing `立即转换成剧本` button still works after extraction.