fix: hard-stop sessions.delete cleanup
This commit is contained in:
@@ -58,6 +58,7 @@
|
||||
### Fixes
|
||||
- Messages: make `/stop` clear queued followups and pending session lane work for a hard abort.
|
||||
- Messages: make `/stop` abort active sub-agent runs spawned from the requester session and report how many were stopped.
|
||||
- Sessions: ensure `sessions.delete` clears queues, aborts embedded runs, and stops sub-agents before deletion.
|
||||
- WhatsApp: default response prefix only for self-chat, using identity name when set.
|
||||
- Signal/iMessage: bound transport readiness waits to 30s with periodic logging. (#1014) — thanks @Szpadel.
|
||||
- Auth: merge main auth profiles into per-agent stores for sub-agents and document inheritance. (#1013) — thanks @marcmarg.
|
||||
|
||||
@@ -3,17 +3,16 @@ import fs from "node:fs";
|
||||
|
||||
import {
|
||||
abortEmbeddedPiRun,
|
||||
isEmbeddedPiRunActive,
|
||||
resolveEmbeddedSessionLane,
|
||||
waitForEmbeddedPiRunEnd,
|
||||
} from "../../agents/pi-embedded.js";
|
||||
import { stopSubagentsForRequester } from "../../auto-reply/reply/abort.js";
|
||||
import { clearSessionQueues } from "../../auto-reply/reply/queue.js";
|
||||
import { loadConfig } from "../../config/config.js";
|
||||
import {
|
||||
resolveMainSessionKey,
|
||||
type SessionEntry,
|
||||
updateSessionStore,
|
||||
} from "../../config/sessions.js";
|
||||
import { clearCommandLane } from "../../process/command-queue.js";
|
||||
import {
|
||||
ErrorCodes,
|
||||
errorShape,
|
||||
@@ -223,8 +222,12 @@ export const sessionsHandlers: GatewayRequestHandlers = {
|
||||
const { entry } = loadSessionEntry(key);
|
||||
const sessionId = entry?.sessionId;
|
||||
const existed = Boolean(entry);
|
||||
clearCommandLane(resolveEmbeddedSessionLane(target.canonicalKey));
|
||||
if (sessionId && isEmbeddedPiRunActive(sessionId)) {
|
||||
const queueKeys = new Set<string>(target.storeKeys);
|
||||
queueKeys.add(target.canonicalKey);
|
||||
if (sessionId) queueKeys.add(sessionId);
|
||||
clearSessionQueues([...queueKeys]);
|
||||
stopSubagentsForRequester({ cfg, requesterSessionKey: target.canonicalKey });
|
||||
if (sessionId) {
|
||||
abortEmbeddedPiRun(sessionId);
|
||||
const ended = await waitForEmbeddedPiRunEnd(sessionId, 15_000);
|
||||
if (!ended) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import {
|
||||
connectOk,
|
||||
embeddedRunMock,
|
||||
@@ -13,9 +13,39 @@ import {
|
||||
} from "./test-helpers.js";
|
||||
import { DEFAULT_PROVIDER } from "../agents/defaults.js";
|
||||
|
||||
const sessionCleanupMocks = vi.hoisted(() => ({
|
||||
clearSessionQueues: vi.fn(() => ({ followupCleared: 0, laneCleared: 0, keys: [] })),
|
||||
stopSubagentsForRequester: vi.fn(() => ({ stopped: 0 })),
|
||||
}));
|
||||
|
||||
vi.mock("../auto-reply/reply/queue.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("../auto-reply/reply/queue.js")>(
|
||||
"../auto-reply/reply/queue.js",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
clearSessionQueues: sessionCleanupMocks.clearSessionQueues,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../auto-reply/reply/abort.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("../auto-reply/reply/abort.js")>(
|
||||
"../auto-reply/reply/abort.js",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
stopSubagentsForRequester: sessionCleanupMocks.stopSubagentsForRequester,
|
||||
};
|
||||
});
|
||||
|
||||
installGatewayTestHooks();
|
||||
|
||||
describe("gateway server sessions", () => {
|
||||
beforeEach(() => {
|
||||
sessionCleanupMocks.clearSessionQueues.mockClear();
|
||||
sessionCleanupMocks.stopSubagentsForRequester.mockClear();
|
||||
});
|
||||
|
||||
test("lists and patches session store via sessions.* RPC", async () => {
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-"));
|
||||
const storePath = path.join(dir, "sessions.json");
|
||||
@@ -349,6 +379,15 @@ describe("gateway server sessions", () => {
|
||||
});
|
||||
expect(deleted.ok).toBe(true);
|
||||
expect(deleted.payload?.deleted).toBe(true);
|
||||
expect(sessionCleanupMocks.stopSubagentsForRequester).toHaveBeenCalledWith({
|
||||
cfg: expect.any(Object),
|
||||
requesterSessionKey: "agent:main:discord:group:dev",
|
||||
});
|
||||
expect(sessionCleanupMocks.clearSessionQueues).toHaveBeenCalledTimes(1);
|
||||
const clearedKeys = sessionCleanupMocks.clearSessionQueues.mock.calls[0]?.[0] as string[];
|
||||
expect(clearedKeys).toEqual(
|
||||
expect.arrayContaining(["discord:group:dev", "agent:main:discord:group:dev", "sess-active"]),
|
||||
);
|
||||
expect(embeddedRunMock.abortCalls).toEqual(["sess-active"]);
|
||||
expect(embeddedRunMock.waitCalls).toEqual(["sess-active"]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user