mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
239 lines
6.3 KiB
JavaScript
239 lines
6.3 KiB
JavaScript
import assert from "node:assert/strict";
|
|
|
|
import { createEmptyGraph, createNode, addNode } from "../graph/graph.js";
|
|
import {
|
|
applyCognitionUpdates,
|
|
applyManualKnowledgeOverride,
|
|
clearManualKnowledgeOverride,
|
|
applyRegionUpdates,
|
|
computeKnowledgeGateForNode,
|
|
listKnowledgeOwners,
|
|
resolveActiveRegionContext,
|
|
resolveAdjacentRegions,
|
|
resolveKnowledgeOwner,
|
|
setManualActiveRegion,
|
|
} from "../graph/knowledge-state.js";
|
|
|
|
globalThis.SillyTavern = {
|
|
getContext() {
|
|
return {
|
|
name1: "露西亚",
|
|
};
|
|
},
|
|
};
|
|
|
|
const graph = createEmptyGraph();
|
|
const erinA = createNode({
|
|
type: "character",
|
|
fields: { name: "艾琳", state: "守塔人" },
|
|
seq: 1,
|
|
});
|
|
const erinB = createNode({
|
|
type: "character",
|
|
fields: { name: "艾琳", state: "伪装者" },
|
|
seq: 2,
|
|
});
|
|
const lucia = createNode({
|
|
type: "character",
|
|
fields: { name: "露西亚", state: "旁观者" },
|
|
seq: 2,
|
|
});
|
|
const bellEvent = createNode({
|
|
type: "event",
|
|
fields: { title: "钟楼异响", summary: "钟楼深夜传出异响" },
|
|
seq: 3,
|
|
scope: { layer: "objective", regionPrimary: "钟楼" },
|
|
});
|
|
addNode(graph, erinA);
|
|
addNode(graph, erinB);
|
|
addNode(graph, lucia);
|
|
addNode(graph, bellEvent);
|
|
|
|
const ownerA = resolveKnowledgeOwner(graph, {
|
|
ownerType: "character",
|
|
ownerName: "艾琳",
|
|
nodeId: erinA.id,
|
|
});
|
|
const ownerB = resolveKnowledgeOwner(graph, {
|
|
ownerType: "character",
|
|
ownerName: "艾琳",
|
|
nodeId: erinB.id,
|
|
});
|
|
assert.notEqual(ownerA.ownerKey, ownerB.ownerKey);
|
|
|
|
applyCognitionUpdates(
|
|
graph,
|
|
[
|
|
{
|
|
ownerType: "character",
|
|
ownerName: "艾琳",
|
|
ownerNodeId: erinA.id,
|
|
knownRefs: [bellEvent.id],
|
|
visibility: [{ ref: bellEvent.id, score: 1 }],
|
|
},
|
|
],
|
|
{
|
|
changedNodeIds: [bellEvent.id],
|
|
scopeRuntime: {
|
|
activeCharacterOwner: "艾琳",
|
|
activeUserOwner: "玩家",
|
|
},
|
|
},
|
|
);
|
|
|
|
const gateVisible = computeKnowledgeGateForNode(graph, bellEvent, ownerA.ownerKey, {
|
|
scopeBucket: "objectiveCurrentRegion",
|
|
});
|
|
assert.equal(gateVisible.visible, true);
|
|
assert.equal(gateVisible.anchored, true);
|
|
|
|
applyManualKnowledgeOverride(graph, {
|
|
ownerKey: ownerA.ownerKey,
|
|
nodeId: bellEvent.id,
|
|
mode: "mistaken",
|
|
});
|
|
const gateSuppressed = computeKnowledgeGateForNode(graph, bellEvent, ownerA.ownerKey, {
|
|
scopeBucket: "objectiveCurrentRegion",
|
|
});
|
|
assert.equal(gateSuppressed.visible, false);
|
|
assert.equal(gateSuppressed.suppressedReason, "mistaken-objective");
|
|
|
|
const clearedOverride = clearManualKnowledgeOverride(graph, {
|
|
ownerKey: ownerA.ownerKey,
|
|
nodeId: bellEvent.id,
|
|
});
|
|
assert.equal(clearedOverride.ok, true);
|
|
const gateRestored = computeKnowledgeGateForNode(graph, bellEvent, ownerA.ownerKey, {
|
|
scopeBucket: "objectiveCurrentRegion",
|
|
});
|
|
assert.equal(gateRestored.visible, true);
|
|
assert.notEqual(gateRestored.suppressedReason, "mistaken-objective");
|
|
|
|
applyCognitionUpdates(
|
|
graph,
|
|
[
|
|
{
|
|
ownerType: "character",
|
|
ownerName: "露西亚",
|
|
ownerNodeId: lucia.id,
|
|
knownRefs: [bellEvent.id],
|
|
visibility: [{ ref: bellEvent.id, score: 1 }],
|
|
},
|
|
],
|
|
{ changedNodeIds: [bellEvent.id] },
|
|
);
|
|
applyCognitionUpdates(
|
|
graph,
|
|
[
|
|
{
|
|
ownerType: "user",
|
|
ownerName: "露西亚",
|
|
knownRefs: [bellEvent.id],
|
|
visibility: [{ ref: bellEvent.id, score: 0.8 }],
|
|
},
|
|
],
|
|
{ changedNodeIds: [bellEvent.id] },
|
|
);
|
|
applyManualKnowledgeOverride(graph, {
|
|
ownerKey: ownerA.ownerKey,
|
|
nodeId: bellEvent.id,
|
|
mode: "mistaken",
|
|
});
|
|
const gateUnion = computeKnowledgeGateForNode(
|
|
graph,
|
|
bellEvent,
|
|
[ownerA.ownerKey, `character:露西亚`],
|
|
{
|
|
scopeBucket: "objectiveCurrentRegion",
|
|
},
|
|
);
|
|
assert.equal(gateUnion.visible, true);
|
|
assert.deepEqual(gateUnion.visibleOwnerKeys, ["character:露西亚"]);
|
|
assert.deepEqual(gateUnion.suppressedOwnerKeys, [ownerA.ownerKey]);
|
|
|
|
applyRegionUpdates(graph, {
|
|
activeRegionHint: "钟楼",
|
|
adjacency: [{ region: "钟楼", adjacent: ["旧城区", "内廷"] }],
|
|
});
|
|
assert.equal(resolveActiveRegionContext(graph).activeRegion, "钟楼");
|
|
assert.deepEqual(resolveAdjacentRegions(graph, "钟楼").adjacentRegions, ["旧城区", "内廷"]);
|
|
|
|
setManualActiveRegion(graph, "旧城区");
|
|
assert.equal(resolveActiveRegionContext(graph).source, "manual");
|
|
assert.equal(resolveActiveRegionContext(graph).activeRegion, "旧城区");
|
|
|
|
const ownerList = listKnowledgeOwners(graph);
|
|
assert.ok(ownerList.some((entry) => entry.ownerKey === ownerA.ownerKey));
|
|
assert.ok(
|
|
ownerList.some(
|
|
(entry) => entry.ownerName === "露西亚" && entry.knownCount >= 1,
|
|
),
|
|
);
|
|
const sameNameOwners = ownerList.filter((entry) => entry.ownerName === "露西亚");
|
|
assert.equal(sameNameOwners.length, 2);
|
|
assert.deepEqual(
|
|
sameNameOwners.map((entry) => entry.ownerType).sort(),
|
|
["character", "user"],
|
|
);
|
|
|
|
const aliasMatchedUserOwner = resolveKnowledgeOwner(graph, {
|
|
ownerType: "character",
|
|
ownerName: "露 西 亚",
|
|
});
|
|
assert.equal(aliasMatchedUserOwner.ownerType, "user");
|
|
assert.equal(aliasMatchedUserOwner.ownerName, "露西亚");
|
|
|
|
const syntheticGraph = createEmptyGraph();
|
|
syntheticGraph.historyState.activeUserPovOwner = "玩家";
|
|
addNode(
|
|
syntheticGraph,
|
|
createNode({
|
|
type: "character",
|
|
fields: { name: "玩 家" },
|
|
seq: 1,
|
|
}),
|
|
);
|
|
const syntheticOwners = listKnowledgeOwners(syntheticGraph);
|
|
assert.equal(syntheticOwners.some((entry) => entry.ownerType === "character"), false);
|
|
|
|
const duplicateCharacterGraph = createEmptyGraph();
|
|
const roleCardNameNode = createNode({
|
|
type: "character",
|
|
fields: { name: "艾 琳" },
|
|
seq: 1,
|
|
});
|
|
const watchedEvent = createNode({
|
|
type: "event",
|
|
fields: { title: "看见钟楼", summary: "艾琳看见钟楼方向出现火光" },
|
|
seq: 2,
|
|
});
|
|
addNode(duplicateCharacterGraph, roleCardNameNode);
|
|
addNode(duplicateCharacterGraph, watchedEvent);
|
|
applyCognitionUpdates(
|
|
duplicateCharacterGraph,
|
|
[
|
|
{
|
|
ownerType: "character",
|
|
ownerName: "艾琳",
|
|
knownRefs: [watchedEvent.id],
|
|
visibility: [{ ref: watchedEvent.id, score: 0.9 }],
|
|
},
|
|
],
|
|
{ changedNodeIds: [watchedEvent.id] },
|
|
);
|
|
const dedupedCharacterOwners = listKnowledgeOwners(duplicateCharacterGraph).filter(
|
|
(entry) => entry.ownerType === "character",
|
|
);
|
|
assert.equal(dedupedCharacterOwners.length, 1);
|
|
assert.equal(dedupedCharacterOwners[0].knownCount >= 1, true);
|
|
assert.equal(
|
|
dedupedCharacterOwners[0].aliases.includes("艾 琳"),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
dedupedCharacterOwners[0].aliases.includes("艾琳"),
|
|
true,
|
|
);
|
|
|
|
console.log("knowledge-state tests passed");
|