Files
NetMesh/application/state/aiScopeCleanup.test.ts

183 lines
5.6 KiB
TypeScript
Raw Permalink Normal View History

import test from "node:test";
import assert from "node:assert/strict";
import type {
AIPanelView,
AISession,
} from "../../infrastructure/ai/types.ts";
import { createEmptyDraft } from "./aiDraftState.ts";
import {
pruneInactiveScopedSessions,
pruneInactiveScopedTransientState,
} from "./aiScopeCleanup.ts";
function createSession(id: string, scope: AISession["scope"], externalSessionId?: string): AISession {
return {
id,
title: id,
agentId: "catty",
scope,
messages: [],
externalSessionId,
createdAt: 1,
updatedAt: 1,
};
}
test("pruneInactiveScopedTransientState removes closed workspace and terminal scope state", () => {
const activeSessionIdMap = {
"terminal:open-terminal": "session-open",
"terminal:closed-terminal": "session-closed-terminal",
"workspace:open-workspace": "session-open-workspace",
"workspace:closed-workspace": "session-closed-workspace",
};
const draftsByScope = {
"terminal:open-terminal": createEmptyDraft("catty"),
"terminal:closed-terminal": createEmptyDraft("catty"),
"workspace:open-workspace": createEmptyDraft("catty"),
"workspace:closed-workspace": createEmptyDraft("catty"),
};
const panelViewByScope = {
"terminal:open-terminal": { mode: "draft" },
"terminal:closed-terminal": { mode: "session", sessionId: "session-closed-terminal" },
"workspace:open-workspace": { mode: "draft" },
"workspace:closed-workspace": { mode: "session", sessionId: "session-closed-workspace" },
} satisfies Record<string, AIPanelView>;
const next = pruneInactiveScopedTransientState(
activeSessionIdMap,
draftsByScope,
panelViewByScope,
new Set(["open-terminal", "open-workspace"]),
);
assert.deepEqual(next.activeSessionIdMap, {
"terminal:open-terminal": "session-open",
"workspace:open-workspace": "session-open-workspace",
});
assert.deepEqual(next.draftsByScope, {
"terminal:open-terminal": draftsByScope["terminal:open-terminal"],
"workspace:open-workspace": draftsByScope["workspace:open-workspace"],
});
assert.deepEqual(next.panelViewByScope, {
"terminal:open-terminal": panelViewByScope["terminal:open-terminal"],
"workspace:open-workspace": panelViewByScope["workspace:open-workspace"],
});
});
test("pruneInactiveScopedSessions reports inactive targets without deleting persisted history", () => {
const sessions = [
createSession("terminal-restorable", {
type: "terminal",
targetId: "closed-restorable",
hostIds: ["host-1"],
}, "ext-1"),
createSession("terminal-local", {
type: "terminal",
targetId: "closed-local",
hostIds: ["local-shell"],
}, "ext-2"),
createSession("workspace-closed", {
type: "workspace",
targetId: "closed-workspace",
}, "ext-3"),
createSession("terminal-open", {
type: "terminal",
targetId: "open-terminal",
hostIds: ["host-2"],
}, "ext-4"),
];
const next = pruneInactiveScopedSessions(
sessions,
new Set(["open-terminal"]),
);
assert.deepEqual(next.orphanedSessionIds, [
"terminal-restorable",
"terminal-local",
"workspace-closed",
]);
assert.equal(next.sessions, sessions);
});
test("pruneInactiveScopedSessions preserves inactive workspace and local terminal history after restart", () => {
const sessions = [
createSession("terminal-local", {
type: "terminal",
targetId: "closed-local",
hostIds: ["local-shell"],
}, "ext-local"),
createSession("workspace-closed", {
type: "workspace",
targetId: "closed-workspace",
}, "ext-workspace"),
];
const next = pruneInactiveScopedSessions(
sessions,
new Set(),
);
assert.deepEqual(next.orphanedSessionIds, [
"terminal-local",
"workspace-closed",
]);
assert.equal(next.sessions, sessions);
});
test("pruneInactiveScopedSessions preserves original sessions when orphaned restorable chats are already detached", () => {
const sessions = [
createSession("terminal-restorable", {
type: "terminal",
targetId: "closed-restorable",
hostIds: ["host-1"],
}),
createSession("terminal-open", {
type: "terminal",
targetId: "open-terminal",
hostIds: ["host-2"],
}, "ext-4"),
];
const next = pruneInactiveScopedSessions(
sessions,
new Set(["open-terminal"]),
);
assert.deepEqual(next.orphanedSessionIds, ["terminal-restorable"]);
assert.equal(next.sessions, sessions);
});
test("pruneInactiveScopedSessions treats sessions displayed elsewhere as in-use, not orphaned", () => {
// terminal-restorable's original scope (terminal-closed-A) is gone, but
// the user resumed it into terminal-open-B from history. The session's
// externalSessionId must be preserved and it must not appear in the
// orphaned list, otherwise the active chat loses external agent continuity.
const resumedElsewhere = createSession("terminal-restorable", {
type: "terminal",
targetId: "terminal-closed-A",
hostIds: ["host-1"],
}, "ext-resumed");
const trulyOrphaned = createSession("terminal-stale", {
type: "terminal",
targetId: "terminal-closed-C",
hostIds: ["host-2"],
}, "ext-stale");
const sessions = [resumedElsewhere, trulyOrphaned];
const next = pruneInactiveScopedSessions(
sessions,
new Set(["terminal-open-B"]),
new Set(["terminal-restorable"]),
);
// Only the one not being displayed anywhere should show up as orphaned.
assert.deepEqual(next.orphanedSessionIds, ["terminal-stale"]);
// The resumed session must retain its externalSessionId.
const resumedNext = next.sessions.find((s) => s.id === "terminal-restorable");
assert.equal(resumedNext?.externalSessionId, "ext-resumed");
});