feat(frontend): 整章重写接入 AI 反问澄清——useRewriteClarify + ChapterRewritePanel 门控(WFW-9 M2)

This commit is contained in:
Yaojia Wang
2026-07-08 12:00:17 +02:00
parent 4b1088a179
commit 8e29b33a11
3 changed files with 258 additions and 10 deletions

View File

@@ -0,0 +1,70 @@
"use client";
import { useCallback, useState } from "react";
import { api } from "@/lib/api/client";
import { PROCEED, toVM, type ClarifyDecisionVM } from "./clarify";
export type ClarifyStatus = "idle" | "checking" | "asking" | "proceed" | "error";
export interface UseRewriteClarify {
status: ClarifyStatus;
// status=asking 时的待答问题(含选项);其它时为 null。
decision: ClarifyDecisionVM | null;
// 预检:调 rewrite/clarify 端点,返回 VM 供调用方同步分支。失败=放行needClarification=false不阻塞整章重写。
check: (
projectId: string,
chapterNo: number,
feedback: string,
priorDraft: string,
) => Promise<ClarifyDecisionVM>;
reset: () => void;
}
// 整章重写侧 AI 反问澄清预检WFW-9 M2路线A 两阶段之「问题」阶段——refine/clarify 的章级孪生)。
// 「再沟通/重写」意见含糊/极短时先调独立非流式端点让 AI 反问needClarification=false 或失败=放行去既有 rewrite SSE。
export function useRewriteClarify(): UseRewriteClarify {
const [status, setStatus] = useState<ClarifyStatus>("idle");
const [decision, setDecision] = useState<ClarifyDecisionVM | null>(null);
const check = useCallback<UseRewriteClarify["check"]>(
async (projectId, chapterNo, feedback, priorDraft) => {
setStatus("checking");
try {
const { data, error } = await api.POST(
"/projects/{project_id}/chapters/{chapter_no}/rewrite/clarify",
{
params: { path: { project_id: projectId, chapter_no: chapterNo } },
body: { feedback, prior_draft: priorDraft },
},
);
if (error || !data) {
setStatus("proceed");
setDecision(null);
return PROCEED;
}
const vm = toVM(data);
if (vm.needClarification && vm.questions.length > 0) {
setStatus("asking");
setDecision(vm);
} else {
setStatus("proceed");
setDecision(null);
}
return vm;
} catch {
setStatus("proceed");
setDecision(null);
return PROCEED;
}
},
[],
);
const reset = useCallback((): void => {
setStatus("idle");
setDecision(null);
}, []);
return { status, decision, check, reset };
}