








@@ -5,6 +5,7 @@ import type { CronDeliveryMode } from "../types.js";
55import type { MutableCronSession } from "./run-session-state.js";
66import {
77clearFastTestEnv,
8+cleanupDirectCronSessionMock,
89dispatchCronDeliveryMock,
910getChannelPluginMock,
1011isHeartbeatOnlyResponseMock,
@@ -731,6 +732,76 @@ describe("runCronIsolatedAgentTurn message tool policy", () => {
731732});
732733});
733734735+it("does not dispatch announce delivery for fatal error payloads", async () => {
736+mockRunCronFallbackPassthrough();
737+resolveCronDeliveryPlanMock.mockReturnValue(makeAnnounceDeliveryPlan());
738+runEmbeddedPiAgentMock.mockResolvedValue({
739+payloads: [
740+{
741+text: 'Codex error: {"type":"error","error":{"type":"server_error"}}',
742+isError: true,
743+},
744+],
745+meta: { agentMeta: { usage: { input: 10, output: 20 } } },
746+});
747+748+const result = await runCronIsolatedAgentTurn({
749+ ...makeParams(),
750+job: makeAnnounceMessageToolJob({
751+id: "fatal-error-payload",
752+name: "Fatal Error Payload",
753+}),
754+});
755+756+expect(result.status).toBe("error");
757+expect(result.error).toBe("cron isolated run returned an error payload");
758+expect(result.delivered).toBe(false);
759+expect(result.deliveryAttempted).toBe(false);
760+expect(dispatchCronDeliveryMock).not.toHaveBeenCalled();
761+expect(cleanupDirectCronSessionMock).toHaveBeenCalledWith({
762+job: expect.objectContaining({ id: "fatal-error-payload" }),
763+agentSessionKey: "agent:default:cron:message-tool-policy",
764+sessionId: "test-session-id",
765+retireReason: "cron-delete-after-run-fatal-error",
766+});
767+expectDeliveryFields(result.delivery, {
768+intended: { channel: "messagechat", to: "123", source: "explicit" },
769+resolved: { ok: true, channel: "messagechat", to: "123", source: "explicit" },
770+fallbackUsed: false,
771+delivered: false,
772+});
773+});
774+775+it("cleans up deleteAfterRun sessions when suppressing fatal error announces", async () => {
776+mockRunCronFallbackPassthrough();
777+resolveCronDeliveryPlanMock.mockReturnValue(makeAnnounceDeliveryPlan());
778+runEmbeddedPiAgentMock.mockResolvedValue({
779+payloads: [{ text: "provider failed", isError: true }],
780+meta: { agentMeta: { usage: { input: 10, output: 20 } } },
781+});
782+const deleteAfterRunJob = makeAnnounceMessageToolJob({
783+id: "fatal-delete-after-run",
784+name: "Fatal Delete After Run",
785+}) as unknown as Record<string, unknown>;
786+deleteAfterRunJob.deleteAfterRun = true;
787+788+await runCronIsolatedAgentTurn({
789+ ...makeParams(),
790+job: deleteAfterRunJob as never,
791+});
792+793+expect(dispatchCronDeliveryMock).not.toHaveBeenCalled();
794+expect(cleanupDirectCronSessionMock).toHaveBeenCalledWith({
795+job: expect.objectContaining({
796+id: "fatal-delete-after-run",
797+deleteAfterRun: true,
798+}),
799+agentSessionKey: "agent:default:cron:message-tool-policy",
800+sessionId: "test-session-id",
801+retireReason: "cron-delete-after-run-fatal-error",
802+});
803+});
804+734805it("skips cron fallback delivery when the message tool already sent to the same target", async () => {
735806await expectCronFallbackSkippedForMessageToolDelivery({
736807sentTargets: [{ tool: "message", provider: "messagechat", to: "123" }],
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。