feat(web): AI 立项方案生成+预填(种子门控 + 按字段接受)

向导阶段(project 未建)一键推演结构化书级蓝图预填立项向导。

- 新 SPEC project_plan_spec(analyst 档,纯预览 reads/writes=())+ schema
  ProjectPlanResult(书名候选 + 时空背景/叙事结构/故事核心/结局设计/基调,
  全字段默认值守解析韧性)+ 注册 SCHEMA_CATALOG;计数三处 21→22 + regen golden。
- 端点 POST /skills/project-plan/generate(不带 project 前缀,绕开 toolbox 404):
  请求体序列化向导草稿为 project_context,复用 build_brief_context + run_generator;
  种子门控(缺 genre/logline→422);请求 schema 加 max_length 上界。
- run_generator/_build_request 的 project_id 放宽 uuid.UUID|None(向导无 project)。
- 前端 wizard.ts 加 mapPlanResultToWizardForm(错配字段折进 premise 不静默丢)+
  applyPlanPatch(仅回填空字段、保护已编辑)+ useProjectPlan hook + PlanAssistant。
This commit is contained in:
Yaojia Wang
2026-07-06 16:26:08 +02:00
parent 821ace5989
commit 02d19019f6
22 changed files with 1187 additions and 9 deletions

View File

@@ -602,3 +602,31 @@ class BookTeardownResult(BaseModel):
default_factory=list,
description="抓人钩子/爽点套路清单;无则空列表",
)
# ---- 立项方案生成器project-plananalyst纯预览 writes=()----
class ProjectPlanResult(BaseModel):
"""立项方案生成器结构化产出:书级蓝图,供预填立项向导(灵感⑤)。
纯预览产物——不映射任何业务表、不入库(`project_plan_spec.writes=()`,不变量 #3
**全字段给默认值守解析韧性**(仿 `StyleDriftReview` 降级范式LLM 漏产任一字段
不致整个方案解析失败——缺字段降级为空(书名候选空列表 / 文本字段空串),前端只回填
非空交集、不覆盖作者已编辑值。
"""
title_candidates: list[str] = Field(
default_factory=list,
description="书名候选清单35 个差异化候选);无则空列表",
)
setting: str = Field(default="", description="时空背景(时代/地域/世界底层规则概述);缺则空串")
narrative_structure: str = Field(
default="", description="叙事结构(主线推进骨架:立钩/升级/转折节拍);缺则空串"
)
story_core: str = Field(
default="",
description="故事核心(立意 + 核心冲突:主角要什么、挡路的是什么、代价);缺则空串",
)
ending_design: str = Field(default="", description="结局设计(收束方向与情绪落点);缺则空串")
tone: str = Field(default="", description="基调(全书情绪底色与阅读质感);缺则空串")