scriptflow/docs/plans/2026-03-11-upload-extract-episodes.md
Song367 b49d703e3c
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 1m22s
一键转换模式优化
2026-03-11 21:53:41 +08:00

110 lines
3.5 KiB
Markdown

# 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.