
















@@ -10,6 +10,7 @@ const loadControlUiBootstrapConfigMock = vi.hoisted(() => vi.fn(async () => unde
1010type GatewayClientMock = {
1111start: ReturnType<typeof vi.fn>;
1212stop: ReturnType<typeof vi.fn>;
13+request: ReturnType<typeof vi.fn>;
1314options: { clientVersion?: string };
1415emitHello: (hello?: GatewayHelloOk) => void;
1516emitClose: (info: {
@@ -40,6 +41,12 @@ vi.mock("./gateway.ts", async (importOriginal) => {
4041class GatewayBrowserClient {
4142readonly start = vi.fn();
4243readonly stop = vi.fn();
44+readonly request = vi.fn(async (method: string) => {
45+if (method === "models.authStatus") {
46+return { ts: 0, providers: [] };
47+}
48+return {};
49+});
43504451constructor(
4552private opts: {
@@ -57,6 +64,7 @@ vi.mock("./gateway.ts", async (importOriginal) => {
5764gatewayClientInstances.push({
5865start: this.start,
5966stop: this.stop,
67+request: this.request,
6068options: { clientVersion: this.opts.clientVersion },
6169emitHello: (hello) => {
6270this.opts.onHello?.(
@@ -524,6 +532,49 @@ describe("connectGateway", () => {
524532expect(loadControlUiBootstrapConfigMock).toHaveBeenCalledWith(host);
525533});
526534535+it("sends queued chat aborts after reconnect before clearing pending state", async () => {
536+const host = createHost();
537+host.chatRunId = "run-main";
538+host.chatStream = "partial";
539+host.pendingAbort = { runId: "run-main", sessionKey: "main" };
540+541+connectGateway(host);
542+const client = gatewayClientInstances[0];
543+expect(client).toBeDefined();
544+545+client.emitHello();
546+await Promise.resolve();
547+548+expect(client.request).toHaveBeenCalledWith("chat.abort", {
549+sessionKey: "main",
550+runId: "run-main",
551+});
552+expect(host.pendingAbort).toBeNull();
553+expect(host.chatRunId).toBeNull();
554+expect(host.chatStream).toBeNull();
555+});
556+557+it("logs and drops stale queued chat abort failures after reconnect", async () => {
558+const host = createHost();
559+host.pendingAbort = { runId: "run-stale", sessionKey: "main" };
560+const warn = vi.spyOn(console, "warn").mockImplementation(() => undefined);
561+562+connectGateway(host);
563+const client = gatewayClientInstances[0];
564+expect(client).toBeDefined();
565+const error = new Error("run already finished");
566+client.request.mockImplementationOnce(async () => {
567+throw error;
568+});
569+570+client.emitHello();
571+await Promise.resolve();
572+573+expect(host.pendingAbort).toBeNull();
574+expect(warn).toHaveBeenCalledWith("[openclaw] pending abort failed:", error);
575+warn.mockRestore();
576+});
577+527578it("keeps shutdown restart reasons on service restart closes", () => {
528579const host = createHost();
529580此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。