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

@@ -42,6 +42,7 @@ __all__ = [
"opening_spec",
"outliner_spec",
"pace_spec",
"project_plan_spec",
"refiner_spec",
"style_drift_spec",
"style_extract_spec",
@@ -298,6 +299,18 @@ teardown_spec = AgentSpec(
scope="builtin",
)
# ---- project-plan立项方案师分析档纯预览 writes=(),灵感⑤)----
project_plan_spec = AgentSpec(
name="project-plan",
tier="analyst", # 不变量 #2只声明档位不写 model立项方案构思用分析档
system_prompt=load_prompt("project-plan"),
input_schema=None, # 向导阶段 project 未建;材料为序列化的向导草稿(端点注入),非结构化入参
output_schema=SCHEMA_CATALOG["project-plan"],
reads=(), # 立项前 project 未建、无库可读;种子经端点序列化注入
writes=(), # 纯预览,不写库(不变量 #3
scope="builtin",
)
# 集中注册表name → spec同一实例兼容期 *_spec 与 SPECS[name] 为同对象,不变量)
# MappingProxyType只读视图运行时 `SPECS[x] = ...` / `del SPECS[x]` 抛 TypeError
@@ -326,9 +339,10 @@ _SPECS_BY_NAME: dict[str, AgentSpec] = {
expand_spec,
de_ai_spec,
teardown_spec,
project_plan_spec,
)
}
assert len(_SPECS_BY_NAME) == 21, "SPECS name 冲突或缺失" # 唯一性 + 数量自检import 期)
assert len(_SPECS_BY_NAME) == 22, "SPECS name 冲突或缺失" # 唯一性 + 数量自检import 期)
SPECS: Final[Mapping[str, AgentSpec]] = MappingProxyType(_SPECS_BY_NAME)
# 四审受信保留名 —— 独立显式白名单(安全边界锚在此,不依附派生集合)