feat(ux): T4-b 后端 — draft 端点接收本章指令 directive 直通 assemble(volatile)

assemble/_build_volatile 加 directive 参数(仅入 volatile,守缓存前缀不变量 #9);stream_draft 加可选 body {directive} 透传;不持久化、无迁移;directive 长度入 log 不记原文。新 DraftStreamRequest schema + 重生成 TS 客户端。后端门禁绿: ruff/mypy/pytest。契约记 memory/contracts.md。
This commit is contained in:
Yaojia Wang
2026-06-20 18:25:00 +02:00
parent 8779530806
commit 2155193cdc
7 changed files with 94 additions and 5 deletions

View File

@@ -162,6 +162,11 @@
- **复用读 seam**:直接调既有 `chapter_repo.get_draft(project_id, chapter_no)->ChapterDraftView|None`(同续审 `_resolve_review_draft` 的读缝);`ChapterDraftView` 已含全部字段,无需新 repo 方法/新 view。多版本时固定返草稿版次`DRAFT_VERSION=1`)那条可编辑工作副本,与 PUT 保存的同一行。
- **@frontend 行动**`pnpm gen:api` 纳入 `GET /projects/:id/chapters/:no/draft`(新 schema `DraftView`);工作台初次加载拉已保存草稿回灌编辑器(去掉「重访看似未保存」局限)。
### C3 扩展T4-b, 2026-06-20· `POST .../draft` 接收可选本章指令 `directive`(挂既有 `routers/projects.py` owner @backend 状态: 稳定
- **仅加可选 body向后兼容**`POST /projects/:id/chapters/:no/draft` 现接收可选 JSON body `DraftStreamRequest{directive: str|None=None}`(无 body 的旧调用方不变,仍按大纲生成)。`directive`=作者本章指令,**临时输入、不持久化、无迁移**。
- 直通 `assemble(..., directive=…)``_build_volatile` 以「本章指令」段领衔 volatile断点后**绝不入 stable_core**(守缓存前缀不变量 #9)。`draft_stream_start` 日志加 `directive_len`(不记原文,脱敏)。
- **@frontend 行动**`pnpm gen:api` 纳入 `DraftStreamRequest``useDraftStream.start(projectId, chapterNo, directive?)` 非空时 POST JSON body 传 directive。
### C3 扩展K1.3, 2026-06-19· Kimi Code OAuth device-flow 端点(独立 `routers/kimi_oauth.py`已注册 owner @backend 状态: 稳定
- snake_case新增 3 端点 + 3 schema → **@frontend 必须 `cd apps/web && pnpm gen:api`**K1.4 前置)。**响应/job 结果/日志绝不含 access/refresh token**(只 user_code/connected/expires_at 等非密信息token 仅以 Fernet 密文存 `provider_credentials.oauth_enc`
- `POST /settings/providers/kimi-code/oauth/start`**202** `OAuthStartResponse{job_id:uuid, user_code:str, verification_uri:str, verification_uri_complete:str|None, expires_in:int, interval:int}`。流程:`start_device_authorization(http)``job_repo.create(None,"kimi_oauth")` + `session.commit()`202 前持久化供轮询)→ `background_tasks.add_task(run_job, session_factory, job.id, _make_poll_work(device))`。后台 `work``run_job` 自建独立 session 上**循环 `poll_token`**`authorization_pending`→续轮询、`slow_down`→增大 interval、`expired`/`denied`→抛 AppError 置 job failed成功 → `upsert_oauth_credential`(加密包)+ job done结果只 `{connected:true, provider}`)。前端展示 user_code + 打开 verification_uri + 轮询 `GET /jobs/{id}`