Archived
feat(ops): 运营中心 · 活动模块接口落地 —— L1/L2/L3 十一条(全 ops)+ 设计端活动库两条改名让位
`apps/api/src/app/activity-ops/*`(service / store / instance-state / instance-steps / launch-params / summaries / view-html / view-scope)+ `routes/activities.ts`;契约 `activity-ops.ts` / `api/activity-ops.ts` (与队友按文档补的那版 43 个导出同名,多 INSTANCE_REASON_KINDS / STEP_RESULTS / launchOptionSchema); 迁移 0035_activity_ops;《API文档-活动模块》按契约回写。 设计端活动库 GET/POST `/api/gov/activities` 改名 `/api/gov/activity-packages`,`/api/gov/activities/*` 整个让给运营端(前端 import 路由对象,零改动);activity-registry CONTRACT.md 与路由总表同步。 2026-08-27 另一会话做的,一直留在工作树没入库;与同批另两条提交互相依赖,以合并提交为验证单位。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
This commit is contained in:
@@ -0,0 +1,522 @@
|
||||
/**
|
||||
* 运营中心 · 活动模块的路由契约(`docs/API文档-活动模块.md`)。
|
||||
*
|
||||
* 全部 `access: 'ops'` —— 活动区落在运营中心,与工作流 / 任务看板同端。
|
||||
* `/api/gov/*` 的写路由由 app 中间件自动广播 `{kind:'system', id:'gov'}`。
|
||||
* 设计端的活动库(包版本 / 资产版本 / 装入)在 `/api/gov/activity-packages`(governance.ts),
|
||||
* `/api/gov/activities/*` 整个归运营端(2026-08-27 用户定)。
|
||||
*/
|
||||
import { z } from 'zod';
|
||||
import type { RouteContract } from './http.ts';
|
||||
export declare const listOpsActivitiesRoute: {
|
||||
readonly method: "GET";
|
||||
readonly path: "/api/gov/activities";
|
||||
readonly access: "ops";
|
||||
/** 不带 status = 全量;量小不分页 */
|
||||
readonly query: z.ZodObject<{
|
||||
status: z.ZodOptional<z.ZodEnum<{
|
||||
active: "active";
|
||||
disabled: "disabled";
|
||||
}>>;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
activities: z.ZodArray<z.ZodObject<{
|
||||
id: z.ZodString;
|
||||
name: z.ZodString;
|
||||
biz: z.ZodString;
|
||||
status: z.ZodEnum<{
|
||||
active: "active";
|
||||
disabled: "disabled";
|
||||
}>;
|
||||
version: z.ZodString;
|
||||
owner: z.ZodNullable<z.ZodObject<{
|
||||
id: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
name: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
llm: z.ZodString;
|
||||
instanceCount: z.ZodNumber;
|
||||
createdAt: z.ZodString;
|
||||
ico: z.ZodOptional<z.ZodString>;
|
||||
hue: z.ZodOptional<z.ZodEnum<{
|
||||
blue: "blue";
|
||||
teal: "teal";
|
||||
amber: "amber";
|
||||
violet: "violet";
|
||||
}>>;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
export declare const getOpsActivityRoute: {
|
||||
readonly method: "GET";
|
||||
readonly path: "/api/gov/activities/:activityId";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
id: z.ZodString;
|
||||
version: z.ZodString;
|
||||
status: z.ZodEnum<{
|
||||
active: "active";
|
||||
disabled: "disabled";
|
||||
}>;
|
||||
createdAt: z.ZodString;
|
||||
biz: z.ZodString;
|
||||
owner: z.ZodNullable<z.ZodObject<{
|
||||
id: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
name: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
llm: z.ZodString;
|
||||
ico: z.ZodOptional<z.ZodString>;
|
||||
hue: z.ZodOptional<z.ZodEnum<{
|
||||
blue: "blue";
|
||||
teal: "teal";
|
||||
amber: "amber";
|
||||
violet: "violet";
|
||||
}>>;
|
||||
desc: z.ZodString;
|
||||
view: z.ZodNullable<z.ZodObject<{
|
||||
url: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
/**
|
||||
* 沙箱要渲染的活动视图 —— 处理器回 `text/html`(不是 JSON),`output` 只是形式上的字符串。
|
||||
* iframe 带不了 Authorization 头,走票据 `?ticket=`(GET,中间件已认)。404 = 该活动没配视图。
|
||||
*/
|
||||
export declare const opsActivityViewRoute: {
|
||||
readonly method: "GET";
|
||||
readonly path: "/api/gov/activities/:activityId/view";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodString;
|
||||
};
|
||||
export declare const listOpsInstancesRoute: {
|
||||
readonly method: "GET";
|
||||
readonly path: "/api/gov/activities/:activityId/instances";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly query: z.ZodObject<{
|
||||
id: z.ZodOptional<z.ZodString>;
|
||||
ownerId: z.ZodOptional<z.ZodString>;
|
||||
state: z.ZodOptional<z.ZodEnum<{
|
||||
running: "running";
|
||||
completed: "completed";
|
||||
pending: "pending";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>>;
|
||||
startedFrom: z.ZodOptional<z.ZodString>;
|
||||
startedTo: z.ZodOptional<z.ZodString>;
|
||||
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
||||
size: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
stats: z.ZodObject<{
|
||||
total: z.ZodNumber;
|
||||
byState: z.ZodRecord<z.ZodEnum<{
|
||||
running: "running";
|
||||
completed: "completed";
|
||||
pending: "pending";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>, z.ZodNumber>;
|
||||
}, z.core.$strip>;
|
||||
total: z.ZodNumber;
|
||||
page: z.ZodNumber;
|
||||
size: z.ZodNumber;
|
||||
items: z.ZodArray<z.ZodObject<{
|
||||
id: z.ZodString;
|
||||
no: z.ZodString;
|
||||
state: z.ZodEnum<{
|
||||
running: "running";
|
||||
completed: "completed";
|
||||
pending: "pending";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>;
|
||||
owner: z.ZodObject<{
|
||||
id: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
name: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
input: z.ZodString;
|
||||
output: z.ZodNullable<z.ZodString>;
|
||||
startedAt: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
export declare const opsLaunchParamsRoute: {
|
||||
readonly method: "GET";
|
||||
readonly path: "/api/gov/activities/:activityId/launch-params";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
version: z.ZodString;
|
||||
params: z.ZodArray<z.ZodObject<{
|
||||
key: z.ZodString;
|
||||
label: z.ZodString;
|
||||
type: z.ZodEnum<{
|
||||
text: "text";
|
||||
textarea: "textarea";
|
||||
select: "select";
|
||||
combo: "combo";
|
||||
list: "list";
|
||||
}>;
|
||||
required: z.ZodOptional<z.ZodBoolean>;
|
||||
desc: z.ZodOptional<z.ZodString>;
|
||||
placeholder: z.ZodOptional<z.ZodString>;
|
||||
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
||||
value: z.ZodString;
|
||||
label: z.ZodString;
|
||||
}, z.core.$strip>>>;
|
||||
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
/**
|
||||
* 启动活动 = 创建实例。同一 `idempotencyKey` 重放返回第一次创建的实例;
|
||||
* 412 活动已禁用;400 缺必填 / 类型不符 / select 值不在候选 / 责任人不在职;409 同键正在创建中。
|
||||
*/
|
||||
export declare const launchOpsInstanceRoute: {
|
||||
readonly method: "POST";
|
||||
readonly path: "/api/gov/activities/:activityId/instances";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly body: z.ZodObject<{
|
||||
idempotencyKey: z.ZodString;
|
||||
ownerId: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
params: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
id: z.ZodString;
|
||||
state: z.ZodEnum<{
|
||||
running: "running";
|
||||
completed: "completed";
|
||||
pending: "pending";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>;
|
||||
startedAt: z.ZodString;
|
||||
owner: z.ZodObject<{
|
||||
id: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
name: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
no: z.ZodString;
|
||||
activityId: z.ZodString;
|
||||
llm: z.ZodString;
|
||||
endedAt: z.ZodNullable<z.ZodString>;
|
||||
durationMs: z.ZodNullable<z.ZodNumber>;
|
||||
reason: z.ZodNullable<z.ZodObject<{
|
||||
kind: z.ZodEnum<{
|
||||
terminated: "terminated";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>;
|
||||
text: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
input: z.ZodObject<{
|
||||
content: z.ZodString;
|
||||
source: z.ZodObject<{
|
||||
kind: z.ZodString;
|
||||
label: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
submittedAt: z.ZodString;
|
||||
files: z.ZodArray<z.ZodObject<{
|
||||
index: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
contentType: z.ZodString;
|
||||
size: z.ZodNumber;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
output: z.ZodObject<{
|
||||
files: z.ZodArray<z.ZodObject<{
|
||||
index: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
contentType: z.ZodString;
|
||||
size: z.ZodNumber;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
steps: z.ZodArray<z.ZodObject<{
|
||||
seq: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
by: z.ZodEnum<{
|
||||
human: "human";
|
||||
agent: "agent";
|
||||
}>;
|
||||
byName: z.ZodString;
|
||||
at: z.ZodNullable<z.ZodString>;
|
||||
durationMs: z.ZodNullable<z.ZodNumber>;
|
||||
res: z.ZodEnum<{
|
||||
pending: "pending";
|
||||
done: "done";
|
||||
fail: "fail";
|
||||
current: "current";
|
||||
}>;
|
||||
note: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
export declare const getOpsInstanceRoute: {
|
||||
readonly method: "GET";
|
||||
readonly path: "/api/gov/activities/:activityId/instances/:instanceId";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
instanceId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
id: z.ZodString;
|
||||
state: z.ZodEnum<{
|
||||
running: "running";
|
||||
completed: "completed";
|
||||
pending: "pending";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>;
|
||||
startedAt: z.ZodString;
|
||||
owner: z.ZodObject<{
|
||||
id: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
name: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
no: z.ZodString;
|
||||
activityId: z.ZodString;
|
||||
llm: z.ZodString;
|
||||
endedAt: z.ZodNullable<z.ZodString>;
|
||||
durationMs: z.ZodNullable<z.ZodNumber>;
|
||||
reason: z.ZodNullable<z.ZodObject<{
|
||||
kind: z.ZodEnum<{
|
||||
terminated: "terminated";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>;
|
||||
text: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
input: z.ZodObject<{
|
||||
content: z.ZodString;
|
||||
source: z.ZodObject<{
|
||||
kind: z.ZodString;
|
||||
label: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
submittedAt: z.ZodString;
|
||||
files: z.ZodArray<z.ZodObject<{
|
||||
index: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
contentType: z.ZodString;
|
||||
size: z.ZodNumber;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
output: z.ZodObject<{
|
||||
files: z.ZodArray<z.ZodObject<{
|
||||
index: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
contentType: z.ZodString;
|
||||
size: z.ZodNumber;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
steps: z.ZodArray<z.ZodObject<{
|
||||
seq: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
by: z.ZodEnum<{
|
||||
human: "human";
|
||||
agent: "agent";
|
||||
}>;
|
||||
byName: z.ZodString;
|
||||
at: z.ZodNullable<z.ZodString>;
|
||||
durationMs: z.ZodNullable<z.ZodNumber>;
|
||||
res: z.ZodEnum<{
|
||||
pending: "pending";
|
||||
done: "done";
|
||||
fail: "fail";
|
||||
current: "current";
|
||||
}>;
|
||||
note: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
/**
|
||||
* 实例文件:默认 JSON + base64(与 `GET /api/gov/upload/:id` 同形);`?raw=1` 直出字节
|
||||
* (RFC 5987 文件名),配 `?ticket=` 给 `<a href download>` 用。
|
||||
*/
|
||||
export declare const opsInstanceFileRoute: {
|
||||
readonly method: "GET";
|
||||
readonly path: "/api/gov/activities/:activityId/instances/:instanceId/files/:io/:index";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
instanceId: z.ZodString;
|
||||
io: z.ZodEnum<{
|
||||
output: "output";
|
||||
input: "input";
|
||||
}>;
|
||||
index: z.ZodCoercedNumber<unknown>;
|
||||
}, z.core.$strip>;
|
||||
readonly query: z.ZodObject<{
|
||||
raw: z.ZodOptional<z.ZodString>;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
contentType: z.ZodString;
|
||||
dataBase64: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
/** 任何时刻都可禁用:只拦新启动,在途实例继续跑完;已禁用再禁用 = 幂等 200 */
|
||||
export declare const disableOpsActivityRoute: {
|
||||
readonly method: "POST";
|
||||
readonly path: "/api/gov/activities/:activityId/disable";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
id: z.ZodString;
|
||||
version: z.ZodString;
|
||||
status: z.ZodEnum<{
|
||||
active: "active";
|
||||
disabled: "disabled";
|
||||
}>;
|
||||
createdAt: z.ZodString;
|
||||
biz: z.ZodString;
|
||||
owner: z.ZodNullable<z.ZodObject<{
|
||||
id: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
name: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
llm: z.ZodString;
|
||||
ico: z.ZodOptional<z.ZodString>;
|
||||
hue: z.ZodOptional<z.ZodEnum<{
|
||||
blue: "blue";
|
||||
teal: "teal";
|
||||
amber: "amber";
|
||||
violet: "violet";
|
||||
}>>;
|
||||
desc: z.ZodString;
|
||||
view: z.ZodNullable<z.ZodObject<{
|
||||
url: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
export declare const activateOpsActivityRoute: {
|
||||
readonly method: "POST";
|
||||
readonly path: "/api/gov/activities/:activityId/activate";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
id: z.ZodString;
|
||||
version: z.ZodString;
|
||||
status: z.ZodEnum<{
|
||||
active: "active";
|
||||
disabled: "disabled";
|
||||
}>;
|
||||
createdAt: z.ZodString;
|
||||
biz: z.ZodString;
|
||||
owner: z.ZodNullable<z.ZodObject<{
|
||||
id: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
name: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
llm: z.ZodString;
|
||||
ico: z.ZodOptional<z.ZodString>;
|
||||
hue: z.ZodOptional<z.ZodEnum<{
|
||||
blue: "blue";
|
||||
teal: "teal";
|
||||
amber: "amber";
|
||||
violet: "violet";
|
||||
}>>;
|
||||
desc: z.ZodString;
|
||||
view: z.ZodNullable<z.ZodObject<{
|
||||
url: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
/** body 空;→ `state='failed'` + `reason.kind='terminated'`;412 实例已终态 */
|
||||
export declare const terminateOpsInstanceRoute: {
|
||||
readonly method: "POST";
|
||||
readonly path: "/api/gov/activities/:activityId/instances/:instanceId/terminate";
|
||||
readonly access: "ops";
|
||||
readonly params: z.ZodObject<{
|
||||
activityId: z.ZodString;
|
||||
instanceId: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
readonly output: z.ZodObject<{
|
||||
id: z.ZodString;
|
||||
state: z.ZodEnum<{
|
||||
running: "running";
|
||||
completed: "completed";
|
||||
pending: "pending";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>;
|
||||
startedAt: z.ZodString;
|
||||
owner: z.ZodObject<{
|
||||
id: z.core.$ZodBranded<z.ZodString, "StaffId", "out">;
|
||||
name: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
no: z.ZodString;
|
||||
activityId: z.ZodString;
|
||||
llm: z.ZodString;
|
||||
endedAt: z.ZodNullable<z.ZodString>;
|
||||
durationMs: z.ZodNullable<z.ZodNumber>;
|
||||
reason: z.ZodNullable<z.ZodObject<{
|
||||
kind: z.ZodEnum<{
|
||||
terminated: "terminated";
|
||||
failed: "failed";
|
||||
rejected: "rejected";
|
||||
}>;
|
||||
text: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
input: z.ZodObject<{
|
||||
content: z.ZodString;
|
||||
source: z.ZodObject<{
|
||||
kind: z.ZodString;
|
||||
label: z.ZodString;
|
||||
}, z.core.$strip>;
|
||||
submittedAt: z.ZodString;
|
||||
files: z.ZodArray<z.ZodObject<{
|
||||
index: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
contentType: z.ZodString;
|
||||
size: z.ZodNumber;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
output: z.ZodObject<{
|
||||
files: z.ZodArray<z.ZodObject<{
|
||||
index: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
contentType: z.ZodString;
|
||||
size: z.ZodNumber;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
steps: z.ZodArray<z.ZodObject<{
|
||||
seq: z.ZodNumber;
|
||||
name: z.ZodString;
|
||||
by: z.ZodEnum<{
|
||||
human: "human";
|
||||
agent: "agent";
|
||||
}>;
|
||||
byName: z.ZodString;
|
||||
at: z.ZodNullable<z.ZodString>;
|
||||
durationMs: z.ZodNullable<z.ZodNumber>;
|
||||
res: z.ZodEnum<{
|
||||
pending: "pending";
|
||||
done: "done";
|
||||
fail: "fail";
|
||||
current: "current";
|
||||
}>;
|
||||
note: z.ZodString;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
};
|
||||
/** 全部 11 条 —— 文档总表与覆盖测试按它数 */
|
||||
export declare const ACTIVITY_OPS_ROUTES: readonly RouteContract[];
|
||||
Reference in New Issue
Block a user