77 lines
3.2 KiB
TypeScript
77 lines
3.2 KiB
TypeScript
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
import { createCapabilityRegistry } from "../../src/modules/agent/capability-registry.ts";
|
|
import { registerScheduleCapabilities } from "../../src/modules/schedules/capabilities.ts";
|
|
import { createHarness, type Harness, pgAvailable } from "../sources-identity/harness.ts";
|
|
|
|
// schedule.draft_check:智能体按对话起草巡检 → 建成未启用的 agent_check;只读能力白名单;只放行用户发起的对话
|
|
const pg = await pgAvailable();
|
|
// biome-ignore lint/suspicious/noExplicitAny: 能力输出按 schema 校验过,测试里直接取字段
|
|
type Any = any;
|
|
|
|
describe.skipIf(!pg)("起草巡检能力(真实 PG)", () => {
|
|
let h: Harness;
|
|
beforeAll(async () => {
|
|
h = await createHarness("draftcheck");
|
|
const registry = createCapabilityRegistry({ logger: h.ctx.logger, db: h.db, settings: h.ctx.settings });
|
|
registerScheduleCapabilities(registry, h.ctx);
|
|
(h.ctx as { capabilities: unknown }).capabilities = registry;
|
|
}, 120_000);
|
|
afterAll(async () => {
|
|
await h?.close();
|
|
});
|
|
|
|
const run = async (trigger: "user" | "schedule") =>
|
|
(
|
|
await h.db
|
|
.insertInto("agent_run")
|
|
.values({ trigger, goal: "起草巡检", status: "running", mode: "execute" } as never)
|
|
.returning("id")
|
|
.executeTakeFirstOrThrow()
|
|
).id;
|
|
const invoke = (input: Record<string, unknown>, agentRunId: string) =>
|
|
h.ctx.capabilities.invoke("schedule.draft_check", input, {
|
|
actorId: "agent",
|
|
taskId: crypto.randomUUID(),
|
|
agentRunId,
|
|
scopeIds: [],
|
|
signal: new AbortController().signal,
|
|
source: "agent",
|
|
}) as Promise<Any>;
|
|
const input = {
|
|
name: "失败下载日报",
|
|
goal: "检查下载器里失败或卡住的任务,有就写一段话汇报",
|
|
everyHours: 24,
|
|
capabilities: ["download.list", "downloader.list", "download.submit", "not.exists"],
|
|
triggerCondition: "stalled_downloads",
|
|
reportAsDecision: true,
|
|
};
|
|
|
|
it("对话里起草:建成未启用的巡检;写入 / 不存在的能力去掉", async () => {
|
|
const out = await invoke(input, await run("user"));
|
|
expect(out).toMatchObject({
|
|
enabled: false,
|
|
capabilities: ["download.list", "downloader.list"],
|
|
dropped: ["download.submit", "not.exists"],
|
|
});
|
|
const job = await h.db
|
|
.selectFrom("scheduled_job")
|
|
.selectAll()
|
|
.where("id", "=", out.jobId)
|
|
.executeTakeFirstOrThrow();
|
|
expect(job).toMatchObject({ kind: "agent_check", enabled: false, builtin: false, name: "失败下载日报" });
|
|
expect(job.schedule).toMatchObject({ type: "interval", everyMs: 24 * 3600_000 });
|
|
expect(job.config).toMatchObject({
|
|
goalTemplate: input.goal,
|
|
capabilityAllowlist: ["download.list", "downloader.list"],
|
|
triggerCondition: "stalled_downloads",
|
|
reportAsDecision: true,
|
|
});
|
|
});
|
|
|
|
it("定时巡检的会话里不能再起草巡检", async () => {
|
|
const before = await h.db.selectFrom("scheduled_job").select("id").execute();
|
|
await expect(invoke(input, await run("schedule"))).rejects.toThrow(/用户发起的对话/);
|
|
expect(await h.db.selectFrom("scheduled_job").select("id").execute()).toHaveLength(before.length);
|
|
});
|
|
});
|