Files
ST-Bionic-Memory-Ecology/tests/dialogue-floor-range-tasks.mjs
2026-04-10 18:38:54 +08:00

175 lines
4.4 KiB
JavaScript

import assert from "node:assert/strict";
import {
buildDialogueFloorMap,
normalizeDialogueFloorRange,
} from "../maintenance/chat-history.js";
import { onExtractionTaskController } from "../maintenance/extraction-controller.js";
import { onRebuildSummaryStateController } from "../ui/ui-actions-controller.js";
const chat = [
{ is_system: true, is_user: false, mes: "greeting" },
{ is_user: true, mes: "user-1" },
{ is_user: false, mes: "assistant-1" },
{ is_system: true, is_user: false, mes: "real-system" },
{
is_system: true,
is_user: false,
mes: "managed-hidden-assistant",
extra: { __st_bme_hide_managed: true },
},
{ is_user: true, mes: "user-2" },
{ is_user: false, mes: "assistant-2" },
];
{
const mapping = buildDialogueFloorMap(chat);
assert.equal(mapping.latestDialogueFloor, 5);
assert.deepEqual(Array.from(mapping.floorToChatIndex), [0, 1, 2, 4, 5, 6]);
assert.equal(mapping.floorToRole[0], "greeting");
assert.deepEqual(Array.from(mapping.assistantDialogueFloors), [2, 3, 5]);
assert.deepEqual(Array.from(mapping.assistantChatIndices), [2, 4, 6]);
}
{
const normalized = normalizeDialogueFloorRange(chat, 2, null);
assert.equal(normalized.valid, true);
assert.equal(normalized.startFloor, 2);
assert.equal(normalized.endFloor, 5);
}
{
const normalized = normalizeDialogueFloorRange(chat, null, 4);
assert.equal(normalized.valid, false);
assert.equal(normalized.reason, "end-without-start");
}
{
const calls = {
rollback: [],
manual: [],
warning: [],
info: [],
};
const runtime = {
getContext() {
return { chat };
},
getIsExtracting() {
return false;
},
ensureGraphMutationReady() {
return true;
},
setRuntimeStatus() {},
rollbackGraphForReroll: async (fromFloor) => {
calls.rollback.push(fromFloor);
return { success: true, effectiveFromFloor: fromFloor };
},
onManualExtract: async (options = {}) => {
calls.manual.push({ ...options });
},
toastr: {
warning(message) {
calls.warning.push(String(message || ""));
},
info(message) {
calls.info.push(String(message || ""));
},
},
};
const result = await onExtractionTaskController(runtime, {
mode: "rerun",
startFloor: 2,
endFloor: 2,
});
assert.equal(result.success, true);
assert.equal(result.fallbackToLatest, true);
assert.deepEqual(calls.rollback, [2]);
assert.equal(calls.manual.length, 1);
assert.equal(calls.manual[0].lockedEndFloor, null);
assert.equal(calls.manual[0].taskLabel, "重新提取");
assert.match(result.reason, /退化为从起始楼层到最新重提/);
}
{
const calls = {
rollback: [],
manual: [],
};
const runtime = {
getContext() {
return { chat };
},
getIsExtracting() {
return false;
},
ensureGraphMutationReady() {
return true;
},
setRuntimeStatus() {},
rollbackGraphForReroll: async (fromFloor) => {
calls.rollback.push(fromFloor);
return { success: true, effectiveFromFloor: fromFloor };
},
onManualExtract: async (options = {}) => {
calls.manual.push({ ...options });
},
toastr: {
warning() {},
info() {},
},
};
const result = await onExtractionTaskController(runtime, {
mode: "rerun",
});
assert.equal(result.success, true);
assert.equal(result.fallbackToLatest, false);
assert.deepEqual(calls.rollback, [6]);
assert.equal(calls.manual[0].lockedEndFloor, 6);
}
{
const captured = [];
const runtime = {
getCurrentGraph() {
return {};
},
ensureGraphMutationReady() {
return true;
},
getContext() {
return { chat };
},
getSettings() {
return {};
},
rebuildHierarchicalSummaryState: async (payload) => {
captured.push(payload);
return { rebuilt: false, reason: "noop" };
},
saveGraphToChat() {},
refreshPanelLiveState() {},
setRuntimeStatus() {},
toastr: {
info() {},
success() {},
},
};
await onRebuildSummaryStateController(runtime, {});
await onRebuildSummaryStateController(runtime, { startFloor: 1, endFloor: 3 });
assert.equal(captured[0].mode, "current");
assert.equal(captured[0].startFloor, null);
assert.equal(captured[1].mode, "range");
assert.equal(captured[1].startFloor, 1);
assert.equal(captured[1].endFloor, 3);
}
console.log("dialogue-floor-range-tasks tests passed");