





























@@ -1,5 +1,8 @@
11import { beforeEach, describe, expect, it, vi } from "vitest";
22import type { RestartSentinelPayload } from "../../infra/restart-sentinel.js";
3+import type { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
4+5+type ScheduleGatewayRestartArgs = Parameters<typeof scheduleGatewaySigusr1Restart>[0];
3647const isRestartEnabledMock = vi.fn(() => true);
58const extractDeliveryInfoMock = vi.fn(() => ({
@@ -12,7 +15,11 @@ const extractDeliveryInfoMock = vi.fn(() => ({
1215}));
1316const formatDoctorNonInteractiveHintMock = vi.fn(() => "Run: openclaw doctor --non-interactive");
1417const writeRestartSentinelMock = vi.fn(async (_payload: RestartSentinelPayload) => "/tmp/restart");
15-const scheduleGatewaySigusr1RestartMock = vi.fn(() => ({ scheduled: true, delayMs: 250 }));
18+const removeRestartSentinelFileMock = vi.fn(async (_path: string | null | undefined) => undefined);
19+const scheduleGatewaySigusr1RestartMock = vi.fn((_opts?: ScheduleGatewayRestartArgs) => ({
20+scheduled: true,
21+delayMs: 250,
22+}));
16231724vi.mock("../../config/commands.js", () => ({
1825isRestartEnabled: isRestartEnabledMock,
@@ -29,6 +36,7 @@ vi.mock("../../infra/restart-sentinel.js", async () => {
2936return {
3037 ...actual,
3138formatDoctorNonInteractiveHint: formatDoctorNonInteractiveHintMock,
39+removeRestartSentinelFile: removeRestartSentinelFileMock,
3240writeRestartSentinel: writeRestartSentinelMock,
3341};
3442});
@@ -65,6 +73,7 @@ describe("gateway tool restart continuation", () => {
6573formatDoctorNonInteractiveHintMock.mockReturnValue("Run: openclaw doctor --non-interactive");
6674writeRestartSentinelMock.mockReset();
6775writeRestartSentinelMock.mockResolvedValue("/tmp/restart");
76+removeRestartSentinelFileMock.mockClear();
6877scheduleGatewaySigusr1RestartMock.mockReset();
6978scheduleGatewaySigusr1RestartMock.mockReturnValue({ scheduled: true, delayMs: 250 });
7079});
@@ -105,6 +114,10 @@ describe("gateway tool restart continuation", () => {
105114continuationMessage: "Reply with exactly: Yay! I did it!",
106115});
107116117+expect(writeRestartSentinelMock).not.toHaveBeenCalled();
118+const scheduledArgs = scheduleGatewaySigusr1RestartMock.mock.calls.at(-1)?.[0];
119+await scheduledArgs?.emitHooks?.beforeEmit?.();
120+108121expect(writeRestartSentinelMock).toHaveBeenCalledWith(
109122expect.objectContaining({
110123kind: "restart",
@@ -126,6 +139,10 @@ describe("gateway tool restart continuation", () => {
126139expect(scheduleGatewaySigusr1RestartMock).toHaveBeenCalledWith({
127140delayMs: 250,
128141reason: "continue after reboot",
142+emitHooks: expect.objectContaining({
143+beforeEmit: expect.any(Function),
144+afterEmitRejected: expect.any(Function),
145+}),
129146});
130147expect(result?.details).toEqual({ scheduled: true, delayMs: 250 });
131148});
@@ -143,6 +160,9 @@ describe("gateway tool restart continuation", () => {
143160continuationMessage: "Reply after restart",
144161});
145162163+const scheduledArgs = scheduleGatewaySigusr1RestartMock.mock.calls.at(-1)?.[0];
164+await scheduledArgs?.emitHooks?.beforeEmit?.();
165+146166expect(writeRestartSentinelMock).toHaveBeenCalledWith(
147167expect.objectContaining({
148168continuation: {
@@ -168,6 +188,9 @@ describe("gateway tool restart continuation", () => {
168188reason: "restart requested",
169189});
170190191+const scheduledArgs = scheduleGatewaySigusr1RestartMock.mock.calls.at(-1)?.[0];
192+await scheduledArgs?.emitHooks?.beforeEmit?.();
193+171194expect(writeRestartSentinelMock).toHaveBeenCalledWith(
172195expect.objectContaining({
173196sessionKey: "agent:main:main",
@@ -178,4 +201,22 @@ describe("gateway tool restart continuation", () => {
178201}),
179202);
180203});
204+205+it("removes the prepared sentinel when restart emission is rejected", async () => {
206+const { createGatewayTool } = await import("./gateway-tool.js");
207+const tool = createGatewayTool({
208+agentSessionKey: "agent:main:main",
209+config: {},
210+});
211+212+await tool.execute?.("tool-call-1", {
213+action: "restart",
214+});
215+216+const scheduledArgs = scheduleGatewaySigusr1RestartMock.mock.calls.at(-1)?.[0];
217+await scheduledArgs?.emitHooks?.beforeEmit?.();
218+await scheduledArgs?.emitHooks?.afterEmitRejected?.();
219+220+expect(removeRestartSentinelFileMock).toHaveBeenCalledWith("/tmp/restart");
221+});
181222});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。