feat(contracts,db): scheduled_job registry tables and schedules API contracts

- 0028_scheduled_jobs: scheduled_job (stable key, group, kind task|agent_check,
  enabled/schedule with defaults + customized flag, config, last_* / next_run_at /
  run_requested_at / running_since, counters) and scheduled_job_run history
- contracts/schedules.ts: ScheduleSpec (interval | 5-field cron), AgentCheckConfig
  (goal template, capability allowlist, budget, trigger condition, allowRecover,
  reportAsDecision), board / run views
- Api.schedules: list, create (agent_check only), update, remove, run-now, skip,
  runs; all admin + console session only

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 02:32:22 +08:00
1 parent f0386af319
commit f8f70d8e09
5 files changed
+373

No files matched your search

+70
View File
@@ -14,6 +14,7 @@ import * as ops from "./ops.ts";
import * as organization from "./organization.ts";
import * as pi from "./pi.ts";
import * as policy from "./policy.ts";
import * as schedules from "./schedules.ts";
import { GlobalSettings, GlobalSettingsUpdate } from "./settings.ts";
import * as sources from "./sources.ts";
@@ -1561,6 +1562,74 @@ export const Api = {
response: z.object({ report: z.record(z.string(), z.unknown()) }),
}),
},
// ── 定时任务看板(W7-C):统一注册表 + Agent 巡检;全部只接受控制台会话 ──
schedules: {
list: ep({
method: "get",
path: "/schedules",
scope: "admin",
auth: "session",
summary: "定时任务看板:全部登记的周期任务与 Agent 巡检、统计、调度器是否在线",
response: schedules.ScheduleBoard,
}),
create: ep({
method: "post",
path: "/schedules",
scope: "admin",
auth: "session",
summary: "新建自定义 Agent 巡检(目标模板 + 能力白名单 + 预算 + 间隔)",
body: schedules.AgentCheckCreate,
response: schedules.ScheduledJob,
}),
update: ep({
method: "patch",
path: "/schedules/{id}",
scope: "admin",
auth: "session",
summary: "修改开关 / 间隔或 cron / 参数;reset 恢复默认开关与调度",
params: schedules.ScheduleIdParam,
body: schedules.ScheduleUpdate,
response: schedules.ScheduledJob,
}),
remove: ep({
method: "delete",
path: "/schedules/{id}",
scope: "admin",
auth: "session",
summary: "删除自定义 Agent 巡检(内置任务不可删)",
params: schedules.ScheduleIdParam,
response: OkResult,
}),
runNow: ep({
method: "post",
path: "/schedules/{id}/run-now",
scope: "admin",
auth: "session",
summary: "立即执行一次(不改下次运行时间;已在排队或运行中则合并)",
params: schedules.ScheduleIdParam,
response: schedules.ScheduleRunNowResult,
}),
skip: ep({
method: "post",
path: "/schedules/{id}/skip",
scope: "admin",
auth: "session",
summary: "跳过下一次运行(下次运行时间顺延一个周期)",
params: schedules.ScheduleIdParam,
response: schedules.ScheduledJob,
}),
runs: ep({
method: "get",
path: "/schedules/{id}/runs",
scope: "admin",
auth: "session",
summary: "最近运行历史(新→旧)",
params: schedules.ScheduleIdParam,
query: schedules.ScheduleRunsQuery,
response: z.object({ items: z.array(schedules.ScheduledJobRun) }),
}),
},
} as const;
/** 用参数填充 `{name}` 路径占位,返回带 API_PREFIX 的完整路径 */
@@ -1582,3 +1651,4 @@ export type EndpointBody<E extends EndpointDef> = E["body"] extends z.ZodType ?
export type EndpointResponse<E extends EndpointDef> = z.infer<E["response"]>;
export * from "./files.ts";
export * from "./schedules.ts";