"use client"; import { useState } from "react"; import { Check, MessagesSquare, RotateCcw, Square, X } from "lucide-react"; import { ThinkingIndicator } from "@/components/ThinkingIndicator"; import { Button } from "@/components/ui/Button"; import { SectionHeader } from "@/components/ui/SectionHeader"; import { StatusNote } from "@/components/ui/StatusNote"; import { TextArea } from "@/components/ui/TextArea"; import { friendlyError } from "@/lib/errors/messages"; import { foldClarifications, needsClarifyGate } from "@/lib/workbench/clarify"; import { useChapterRewrite } from "@/lib/workbench/useChapterRewrite"; import { useRewriteClarify } from "@/lib/workbench/useRewriteClarify"; import { ChoiceChips } from "./ChoiceChips"; // 门控阈值:整章意见 trim 后短于此字数才自动预检反问(清晰意见不交往返税)。 const CLARIFY_MIN_CHARS = 10; interface ChapterRewritePanelProps { projectId: string; chapterNo: number; // 当前整章正文(首轮重写的 prior_draft)。 currentDraft: string; // 接受某一版 → 替换整章正文(HITL,作者显式点选才落草稿)。 onAccept: (text: string) => void; onClose: () => void; } // 整章「再沟通 / 重写」结果卡(内联,非模态):作者给意见 → 意见含糊/极短时 AI 先反问给方向选项(预检、只读、 // HITL)→ 就着当前整章 + 完整记忆注入流式重写一版 → 版本栈可多轮迭代 → 接受某版才替换整章正文(不变量 #3)。 export function ChapterRewritePanel({ projectId, chapterNo, currentDraft, onAccept, onClose, }: ChapterRewritePanelProps) { const rewrite = useChapterRewrite(); const clarify = useRewriteClarify(); const [feedback, setFeedback] = useState(""); const [pendingFeedback, setPendingFeedback] = useState(null); const hasVersions = rewrite.versions.length > 0; const clarifying = clarify.status === "checking"; const canSend = feedback.trim().length > 0 && !rewrite.isStreaming && !clarifying; const firstQuestion = clarify.decision?.questions[0] ?? null; const asking = clarify.status === "asking" && firstQuestion !== null; // 下一轮以最新版正文为基础(无版本则用当前整章正文)迭代。 const priorDraft = rewrite.latest?.text ?? currentDraft; const err = rewrite.state.phase === "error" ? rewrite.state.error : null; // 折入澄清答案(或原意见)后流式重写,并清理澄清态。 const runSend = (fb: string): void => { clarify.reset(); setPendingFeedback(null); setFeedback(""); void rewrite.send(projectId, chapterNo, fb, priorDraft); }; // 「重写整章 / 再改一版」:意见含糊/极短(或 force)先预检反问;否则直接流式重写。 const onSend = async (force: boolean): Promise => { const fb = feedback.trim(); if (!fb || rewrite.isStreaming || clarifying) return; if (force || needsClarifyGate(fb, CLARIFY_MIN_CHARS)) { const vm = await clarify.check(projectId, chapterNo, fb, priorDraft); if (vm.needClarification && vm.questions.length > 0) { setPendingFeedback(fb); // 记住原意见,等作者答完折进去 return; } } runSend(fb); }; // 作者答复澄清(点选 value 或自由输入)→ 折进意见 → 流式重写。 const onClarifyAnswer = (answer: string): void => { const question = clarify.decision?.questions[0]?.question ?? ""; const base = pendingFeedback ?? feedback.trim(); runSend(foldClarifications(base, [{ question, answer }])); }; return (