



















@@ -0,0 +1,104 @@
1+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2+import { onDiagnosticEvent, resetDiagnosticEventsForTest } from "../../infra/diagnostic-events.js";
3+import { resetDiagnosticStateForTest } from "../../logging/diagnostic.js";
4+5+vi.mock("../../agents/auth-profiles/source-check.js", () => ({
6+hasAnyAuthProfileStoreSource: vi.fn(() => false),
7+}));
8+9+import {
10+clearFastTestEnv,
11+loadRunCronIsolatedAgentTurn,
12+resetRunCronIsolatedAgentTurnHarness,
13+restoreFastTestEnv,
14+} from "./run.test-harness.js";
15+16+const runCronIsolatedAgentTurn = await loadRunCronIsolatedAgentTurn();
17+18+function makeParams() {
19+return {
20+cfg: {},
21+deps: {} as never,
22+job: {
23+id: "cron-diag-events",
24+name: "Diag Events",
25+enabled: true,
26+createdAtMs: 0,
27+updatedAtMs: 0,
28+schedule: { kind: "cron" as const, expr: "0 * * * *", tz: "UTC" },
29+sessionTarget: "isolated" as const,
30+state: {},
31+wakeMode: "next-heartbeat" as const,
32+payload: { kind: "agentTurn" as const, message: "run task" },
33+},
34+message: "run task",
35+sessionKey: "cron:diag-events",
36+};
37+}
38+39+type EventRecord = {
40+type: string;
41+sessionKey?: string;
42+sessionId?: string;
43+source?: string;
44+state?: string;
45+outcome?: string;
46+};
47+48+describe("runCronIsolatedAgentTurn diagnostic events", () => {
49+let previousFastTestEnv: string | undefined;
50+51+beforeEach(() => {
52+previousFastTestEnv = clearFastTestEnv();
53+resetRunCronIsolatedAgentTurnHarness();
54+resetDiagnosticStateForTest();
55+resetDiagnosticEventsForTest();
56+});
57+58+afterEach(() => {
59+restoreFastTestEnv(previousFastTestEnv);
60+});
61+62+it("emits a paired queued/processing/idle/processed lifecycle for an isolated cron run", async () => {
63+const events: EventRecord[] = [];
64+const unsubscribe = onDiagnosticEvent((evt) => {
65+const e = evt as EventRecord;
66+if (
67+e.type === "message.queued" ||
68+e.type === "session.state" ||
69+e.type === "message.processed"
70+) {
71+events.push(e);
72+}
73+});
74+75+try {
76+const result = await runCronIsolatedAgentTurn(makeParams());
77+expect(result.status).toBe("ok");
78+} finally {
79+unsubscribe();
80+}
81+82+const ofType = (type: string) => events.filter((e) => e.type === type);
83+expect(ofType("message.queued")).toHaveLength(1);
84+expect(ofType("message.queued")[0]?.source).toBe("cron-isolated");
85+86+const stateEvents = ofType("session.state");
87+expect(stateEvents.map((e) => e.state)).toEqual(["processing", "idle"]);
88+89+const processed = ofType("message.processed");
90+expect(processed).toHaveLength(1);
91+expect(processed[0]?.outcome).toBe("completed");
92+93+const queuedKey = ofType("message.queued")[0]?.sessionKey;
94+expect(queuedKey).toBeTruthy();
95+for (const e of events) {
96+expect(e.sessionKey).toBe(queuedKey);
97+}
98+99+const orderedTypes = events.map((e) => e.type);
100+expect(orderedTypes[0]).toBe("message.queued");
101+expect(orderedTypes[orderedTypes.length - 1]).toBe("message.processed");
102+expect(orderedTypes).toContain("session.state");
103+});
104+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。