mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
175 lines
4.4 KiB
JavaScript
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");
|