feat(web): Scope B B1 — 多章工作流链前端 UI(发起/轮询/裁决续跑)
链页 app/projects/[id]/chains(RSC fetchProject)+ ChainPage/ChainStarter/
ChainProgress/ChainAdjudication;lib/chain 纯函数(result 收窄/相位映射/resume 组装)。
复用 useJobPoll 轮询、ConflictCard + decisions.ts 裁决、normalizeConflicts/latestReview、
friendlyError;nav 加 chains 入口。awaiting(interrupt)→ 读该章冲突渲 ConflictCard →
POST .../chains/runs/{job_id}/resume 续跑。gen:api 纳入 chains run/resume。
守 #5(链暂停=等裁决,token/正文不入 job result)。
This commit is contained in:
226
apps/web/lib/api/schema.d.ts
vendored
226
apps/web/lib/api/schema.d.ts
vendored
@@ -549,6 +549,55 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/projects/{project_id}/chains/{chain_key}/run": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/**
|
||||
* Run Chain
|
||||
* @description 发起多章链:写一行 job 返 202,链经 BackgroundTask 异步跑。
|
||||
*
|
||||
* 项目不存在 → 404;未知 chain_key → 404;无凭据 → 503(dep 解析阶段拦下);
|
||||
* `count` 越界由 schema Field 在解析阶段 → 422。`gateway` 仅做请求阶段凭据探测——
|
||||
* 链本体在 BackgroundTask 里用独立 session 重建网关跑(请求 session 即将关闭)。
|
||||
*/
|
||||
post: operations["run_chain_projects__project_id__chains__chain_key__run_post"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/projects/{project_id}/chains/runs/{job_id}/resume": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/**
|
||||
* Resume Chain
|
||||
* @description 裁决续跑:仅当 job=awaiting_input,带裁决经 BackgroundTask resume。
|
||||
*
|
||||
* 项目不存在 → 404;job 不存在 / 不属于该项目 → 404(同案,不枚举);非 awaiting 态 →
|
||||
* 409(CONFLICT)。`awaiting→running` 在 HTTP 处理器内**原子抢占**(条件 UPDATE),避免两个
|
||||
* 并发 resume 都过守卫后双 `Command(resume=...)` 损坏图(审评 #3);抢不到(已被并发抢走/非
|
||||
* awaiting)→ 409。resume 经 `Command(resume=decisions)` 从 interrupt 续跑(同 thread_id)。
|
||||
*/
|
||||
post: operations["resume_chain_projects__project_id__chains_runs__job_id__resume_post"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/settings/providers": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -721,6 +770,68 @@ export interface components {
|
||||
*/
|
||||
thinking: boolean;
|
||||
};
|
||||
/**
|
||||
* ChainResumeAccepted
|
||||
* @description resume 受理回执(202):job_id + chain_key(前端走 `GET /jobs/{id}` 轮询续跑进度)。
|
||||
*
|
||||
* 续跑无独立区间(图从检查点续),故不回显 start/count(会是无意义哨兵值)——只回 job 标识。
|
||||
*/
|
||||
ChainResumeAccepted: {
|
||||
/**
|
||||
* Job Id
|
||||
* Format: uuid
|
||||
*/
|
||||
job_id: string;
|
||||
/** Chain Key */
|
||||
chain_key: string;
|
||||
};
|
||||
/**
|
||||
* ChainResumeRequest
|
||||
* @description 裁决续跑:对 awaiting 章最近审稿的每个冲突逐条裁决(复用 `ConflictDecision`)。
|
||||
*/
|
||||
ChainResumeRequest: {
|
||||
/**
|
||||
* Decisions
|
||||
* @description 对 awaiting 章冲突的裁决清单(采纳/忽略/手改)
|
||||
*/
|
||||
decisions?: components["schemas"]["ConflictDecision"][];
|
||||
};
|
||||
/**
|
||||
* ChainRunAccepted
|
||||
* @description 链受理回执(202):job_id + 回显请求参数(前端走 `GET /jobs/{id}` 轮询进度/awaiting)。
|
||||
*/
|
||||
ChainRunAccepted: {
|
||||
/**
|
||||
* Job Id
|
||||
* Format: uuid
|
||||
*/
|
||||
job_id: string;
|
||||
/** Chain Key */
|
||||
chain_key: string;
|
||||
/** Start Chapter No */
|
||||
start_chapter_no: number;
|
||||
/** Count */
|
||||
count: number;
|
||||
};
|
||||
/**
|
||||
* ChainRunRequest
|
||||
* @description 发起多章链:从 `start_chapter_no` 起循环写 `count` 章(区间含两端)。
|
||||
*
|
||||
* `count` 1..50(>50 → 422 VALIDATION,由 Field 约束在边界拦下,不进 BackgroundTask);
|
||||
* `start_chapter_no >= 1`。
|
||||
*/
|
||||
ChainRunRequest: {
|
||||
/**
|
||||
* Start Chapter No
|
||||
* @description 起始章号(含),>=1
|
||||
*/
|
||||
start_chapter_no: number;
|
||||
/**
|
||||
* Count
|
||||
* @description 本 run 连续写的章数(1..50,含起始章)
|
||||
*/
|
||||
count: number;
|
||||
};
|
||||
/**
|
||||
* CharacterCardView
|
||||
* @description 单张角色卡(贴 ww_agents.CharacterCard;预览 + 入库请求共用形)。
|
||||
@@ -1723,9 +1834,14 @@ export interface components {
|
||||
* @default
|
||||
*/
|
||||
brief: string;
|
||||
/**
|
||||
* Text
|
||||
* @description 原文输入(扩写/降AI 的原文、拆书的样本;text_input 策略工具用)
|
||||
*/
|
||||
text?: string | null;
|
||||
/**
|
||||
* Chapter No
|
||||
* @description 按章展开类工具的章号(开篇/细纲)
|
||||
* @description 按章展开/续写类工具的章号(开篇/细纲/续写)
|
||||
*/
|
||||
chapter_no?: number | null;
|
||||
/**
|
||||
@@ -3074,6 +3190,114 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
run_chain_projects__project_id__chains__chain_key__run_post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
project_id: string;
|
||||
chain_key: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ChainRunRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
202: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ChainRunAccepted"];
|
||||
};
|
||||
};
|
||||
/** @description 项目或链 key 不存在 */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
/** @description 请求参数非法(count 越界等) */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
/** @description 无可用 LLM 凭据 */
|
||||
503: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
resume_chain_projects__project_id__chains_runs__job_id__resume_post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
project_id: string;
|
||||
job_id: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ChainResumeRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
202: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ChainResumeAccepted"];
|
||||
};
|
||||
};
|
||||
/** @description 项目或 job 不存在 */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
/** @description job 非 awaiting_input 态,不可续跑 */
|
||||
409: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
list_providers_settings_providers_get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
Reference in New Issue
Block a user