refactor: lazy load cron gateway cleanup

This commit is contained in:
Shakker
2026-04-01 16:40:03 +01:00
committed by Shakker
parent a4efe7c028
commit b721f5e48a
3 changed files with 42 additions and 1 deletions

View File

@@ -11,6 +11,7 @@
*/
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { SILENT_REPLY_TOKEN } from "../../auto-reply/tokens.js";
// --- Module mocks (must be hoisted before imports) ---
@@ -39,6 +40,10 @@ vi.mock("../../cli/outbound-send-deps.js", () => ({
createOutboundSendDeps: vi.fn().mockReturnValue({}),
}));
vi.mock("../../gateway/call.runtime.js", () => ({
callGateway: vi.fn().mockResolvedValue({ status: "ok" }),
}));
vi.mock("../../logger.js", () => ({
logWarn: vi.fn(),
logError: vi.fn(),
@@ -57,6 +62,7 @@ vi.mock("./subagent-followup.js", () => ({
// Import after mocks
import { countActiveDescendantRuns } from "../../agents/subagent-registry.js";
import { callGateway } from "../../gateway/call.runtime.js";
import { deliverOutboundPayloads } from "../../infra/outbound/deliver.js";
import { enqueueSystemEvent } from "../../infra/system-events.js";
import { shouldEnqueueCronMainSummary } from "../heartbeat-policy.js";
@@ -390,6 +396,33 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.deliveryAttempted).toBe(true);
});
it("cleans up the direct cron session after a silent reply when deleteAfterRun is enabled", async () => {
vi.mocked(countActiveDescendantRuns).mockReturnValue(0);
vi.mocked(isLikelyInterimCronMessage).mockReturnValue(false);
const params = makeBaseParams({ synthesizedText: SILENT_REPLY_TOKEN });
params.job.deleteAfterRun = true;
const state = await dispatchCronDelivery(params);
expect(state.result).toEqual(
expect.objectContaining({
status: "ok",
delivered: false,
}),
);
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(callGateway).toHaveBeenCalledWith({
method: "sessions.delete",
params: {
key: "agent:main",
deleteTranscript: true,
emitLifecycleHooks: false,
},
timeoutMs: 10_000,
});
});
it("text delivery fires exactly once (no double-deliver)", async () => {
vi.mocked(countActiveDescendantRuns).mockReturnValue(0);
vi.mocked(isLikelyInterimCronMessage).mockReturnValue(false);

View File

@@ -7,7 +7,6 @@ import {
resolveAgentMainSessionKey,
resolveMainSessionKey,
} from "../../config/sessions/main-session.js";
import { callGateway } from "../../gateway/call.js";
import { sleepWithAbort } from "../../infra/backoff.js";
import {
deliverOutboundPayloads,
@@ -141,8 +140,15 @@ type CompletedDirectCronDelivery = {
results: OutboundDeliveryResult[];
};
let gatewayCallRuntimePromise: Promise<typeof import("../../gateway/call.runtime.js")> | undefined;
const COMPLETED_DIRECT_CRON_DELIVERIES = new Map<string, CompletedDirectCronDelivery>();
async function loadGatewayCallRuntime(): Promise<typeof import("../../gateway/call.runtime.js")> {
gatewayCallRuntimePromise ??= import("../../gateway/call.runtime.js");
return await gatewayCallRuntimePromise;
}
function cloneDeliveryResults(
results: readonly OutboundDeliveryResult[],
): OutboundDeliveryResult[] {
@@ -518,6 +524,7 @@ export async function dispatchCronDelivery(
return;
}
try {
const { callGateway } = await loadGatewayCallRuntime();
await callGateway({
method: "sessions.delete",
params: {

View File

@@ -0,0 +1 @@
export { callGateway } from "./call.js";