feat(toolbox): T6 创作工具箱通用生成器框架 — 8 新生成器 + 声明驱动落地页 + P2 收尾
通用执行路径驱动全部生成器("加生成器=加一份声明"):
- @llm: ww_agents +7 输出 schema + 7 spec(book-title/blurb/name/golden-finger/
glossary/opening/fine-outline,只声明 tier)+ build_outline_chapter_context
- @backend: ww_skills GeneratorTool 描述符 + TOOLBOX(11) + get_tool;3 通用端点
GET /skills/toolbox · POST .../skills/{tool_key}/generate(预览不写库,仅记账) ·
POST .../ingest(复用 continuity 409 + partition_writes 白名单);纯 context 派发
- @frontend: 工具箱落地页 RSC + 声明驱动 GeneratorRunner + lib/toolbox 纯函数
+ LeftNav「工具箱」+ ⌘K nav-toolbox/action-gen-*;legacy 3 跳现页
- @qa: tests/test_t6_toolbox_e2e.py 5 用例真 pg + mock 网关零 token,无端点 bug
- P2 收尾: 限流→decisions.md 记延后(单用户原型);noopener/Committable 早已修
守不变量 #2(只声明 tier)/#3(预览不写库,入库经验收 gate)/#9(缓存前缀)。无 DB 迁移。
门禁绿: 后端 ruff/format/mypy 195/alembic 无漂移/pytest 583;前端 lint/tsc/vitest 279/build。
spec 回写 PRODUCT_SPEC §7 + ARCHITECTURE §7.2 端点表。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -177,6 +177,16 @@
|
||||
- **服务缝**(`services/kimi_oauth.py`,注入 `AsyncHttpClient` Protocol = `httpx.AsyncClient.post` 子集,测试零联网):`start_device_authorization(http)->DeviceAuth`、`poll_token(http, device_code)->TokenSet`(一次尝试,`AuthorizationPending`/`SlowDown` 异常供调用方循环)、`refresh(http, refresh_token)->TokenSet`;`encrypt_oauth_bundle`/`decrypt_oauth_bundle`(Fernet 复用 `security/credentials` 的 `encrypt_api_key`/`decrypt_api_key`,工作在 JSON 串上);`needs_refresh(token)`。client_id env `KIMI_CLIENT_ID` 可覆盖默认 `17e5f671-...`;device authorization **带 `scope=kimi-code`**(coding entitlement;实测省略 scope→`api.kimi.com/coding/v1` 回 401,故重新带上。token 交换/刷新不带 scope)。
|
||||
- **@frontend 行动(K1.4)**:`pnpm gen:api` 纳入 OAuth start/disconnect/status + 3 schema;连接流 = start 拿 user_code + 开 verification_uri → 轮询 `GET /jobs/{job_id}` 到 done(已连接)/failed(过期/拒绝);status 端点查连接态;档位路由到 `kimi-code:kimi-for-coding`。
|
||||
|
||||
### C3 扩展(T6.2/T6.3, 2026-06-22)· 创作工具箱通用端点(独立 `routers/toolbox.py`,已注册) owner @backend 状态: 稳定
|
||||
- 通用生成器框架:声明驱动、一条执行路径——「加一个生成器」= 在 `ww_skills.TOOLBOX` 加一份 `GeneratorTool` 声明(descriptor 在代码、**无 DB 迁移**),无需新端点。snake_case;**新增 3 端点 + 新 schema → @frontend 必须 `cd apps/web && pnpm gen:api`**(T6 前端前置)。
|
||||
- `GET /skills/toolbox` → **200** `ToolboxListResponse{tools:[ToolDescriptorView{key,title,subtitle,genre?,is_legacy:bool,ingestable:bool,input_fields:[ToolInputFieldView{name,label,type,required,default?,help?}],legacy_route?:str}]}`(legacy 3 + 新 8,按 key 升序)。legacy 工具(worldbuilding/character/outline,`is_legacy=true`)携 `legacy_route`(`/projects/{id}/codex?gen=world` · `?gen=character` · `/projects/{id}/outline`)供前端跳现有页面,不回归既测。
|
||||
- `POST /projects/{project_id}/skills/{tool_key}/generate` ← `ToolGenerateRequest{brief:str="", chapter_no:int|None(ge1), count:int|None(1..12), kind:str|None}` → **200** `ToolGeneratePreviewResponse{tool_key, output_kind:str(产物 schema 名), preview:dict(各工具 output_schema 的 model_dump)}`。**预览不入库**(按 `spec.tier` 经 `get_tier_gateway_builder` 建网关 → `run_generator`);末尾 `commit()` 仅落 ledger。context 派发(PURE `services/toolbox_context.build_toolbox_context`):brief_only/with_project→`build_brief_context`、with_world→ + world_entities 硬规则卡、with_outline_chapter→ + 指定章 outline beats(**缺章/缺大纲→空节拍不报错**)。未知 tool_key→404;legacy 工具(spec=None)→**404**(前端走 legacy_route);项目不存在→404;无凭据→**503** `LLM_UNAVAILABLE`。
|
||||
- `POST /projects/{project_id}/skills/{tool_key}/ingest` ← `ToolIngestRequest{world_entities:[WorldEntityCardView], chapter_no:int|None, scenes:[OutlineSceneIngestView{idx,beat,purpose,conflict,hook}], acknowledge_conflicts:bool=false}` → **201** `ToolIngestResponse{table:str, created:list[str], rejected_tables:list[str]}`。**仅 `ingest!=None` 的工具**(golden-finger/glossary→world_entities,fine-outline→outline);其余→**422 VALIDATION**。入库 gate(仿 `POST /characters`):world_entities 走 **continuity 预检(analyst 网关)** 比对待入库实体 vs 既有世界观真相源——有冲突且 `acknowledge_conflicts=false`→**409 `CONFLICT_UNRESOLVED`** + `details{conflicts:[{type,where,refs,suggestion}],conflict_count}`;`partition_writes(spec,{table:items})` 白名单过滤(越权→`rejected_tables` 审计);schema→DB JSONB 形变写库(rules→`{"rules":[...]}`;细纲场景按 idx 升序拼成该章 beats,`outline_write_repo.upsert_chapter`)。outline(细纲)不做 continuity 预检(场景是粗节拍展开,非设定/角色比对),无 chapter_no→422。未知/legacy→404。提交边界:ledger + 写侧只 flush → 端点末尾一次 `commit()`(含 409 路径也 commit 落 precheck usage)。
|
||||
- **注册表**(`packages/skills/ww_skills/toolbox_registry.py`,经 `ww_skills` 导出):`TOOLBOX:dict[str,GeneratorTool]`(11 条)+ `get_tool(key)->GeneratorTool|None`。新工具的 `key==spec.name`、`output_schema is spec.output_schema`。
|
||||
- **注入缝**(`services/project_deps.py`):`get_tier_gateway_builder`→`TierGatewayBuilder=Callable[[Tier],Awaitable[Gateway]]`(按工具 tier 动态建网关);测试经 `app.dependency_overrides[get_tier_gateway_builder]` 注返 mock 网关的 builder + `get_world_entity_write_repo`/`get_outline_write_repo`/`get_memory_repos`/`get_project_repo` 注 fake(schema-routing fake 网关按 `req.output_schema` 返 IdeaListResult/ContinuityReview/…)。
|
||||
- **守不变量**:#2(spec 只声明 tier)/#3(预览不写库;入库经 continuity gate + 白名单)/#9(system_prompt 进缓存前块、注入材料进 input)。**无新迁移**(descriptor 在代码,复用 world_entities/outline 表)。
|
||||
- **@frontend 行动**:`pnpm gen:api` 纳入 `GET /skills/toolbox` + `POST .../skills/{tool_key}/generate` + `POST .../skills/{tool_key}/ingest`(新 schema `ToolboxListResponse`/`ToolDescriptorView`/`ToolInputFieldView`/`ToolGenerateRequest`/`ToolGeneratePreviewResponse`/`ToolIngestRequest`/`ToolIngestResponse`/`OutlineSceneIngestView`);工具箱落地页据 `GET /skills/toolbox` 渲染卡片栅格(legacy 走 `legacy_route` 跳页,新工具据 `input_fields` 声明驱动表单 → generate 预览 → 可入库者 ingest + 复用 409 冲突裁决)。
|
||||
|
||||
## C8 · Skill registry + 表权限沙箱 owner @backend 状态: 稳定(T5.5, 2026-06-19;M5 R3 迁入 ww_skills 包, 2026-06-19)
|
||||
- 来源:`ARCHITECTURE.md §5.6` / `PRODUCT_SPEC §5.5`(声明式 Skill = AgentSpec;「声明式权限 + apply 层白名单」,**非进程沙箱**)。消费方:M5 编排/生成入库层、技能库 UI(T5.6,经 C3)。
|
||||
- **实现位置(M5 R3 已迁移)**:实现现落 `packages/skills/ww_skills/{skill_registry,skill_permissions}.py`(`packages/skills` 已是 uv workspace member)。`ww_skills/__init__.py` **直接导出**(不再是再导出 ww_core 的门面)。消费方 `from ww_skills import SkillRegistry/SqlSkillRepo/SkillRecord/SkillRepo/partition_writes/filter_reads/validate_declaration/KNOWN_TABLES`。**`ww_core.domain` 已删除这两个模块 + 其 `__init__` 导出**(不再经 ww_core.domain 暴露 skill 符号)。历史:T5.5 曾因 skills 非 workspace member 暂落 ww_core.domain(见 decisions),现已迁回。
|
||||
|
||||
Reference in New Issue
Block a user