mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
Normalize mistaken user owners across extraction and cognition
This commit is contained in:
@@ -3,6 +3,11 @@ import {
|
||||
getScopeRegionKey,
|
||||
normalizeMemoryScope,
|
||||
} from "./memory-scope.js";
|
||||
import {
|
||||
aliasSetMatchesValue,
|
||||
buildUserPovAliasNormalizedSet,
|
||||
getHostUserAliasHints,
|
||||
} from "../runtime/user-alias-utils.js";
|
||||
|
||||
export const KNOWLEDGE_STATE_VERSION = 1;
|
||||
export const REGION_STATE_VERSION = 1;
|
||||
@@ -65,6 +70,61 @@ function normalizeOwnerType(ownerType = "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
function appendAliasHintStrings(target, value) {
|
||||
if (value == null) return;
|
||||
if (typeof value === "string") {
|
||||
const normalized = normalizeString(value);
|
||||
if (normalized) target.push(normalized);
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
for (const item of value) appendAliasHintStrings(target, item);
|
||||
return;
|
||||
}
|
||||
if (typeof value === "object") {
|
||||
appendAliasHintStrings(target, value.name1);
|
||||
appendAliasHintStrings(target, value.userName);
|
||||
appendAliasHintStrings(target, value.personaName);
|
||||
appendAliasHintStrings(target, value.name);
|
||||
appendAliasHintStrings(target, value.aliases);
|
||||
}
|
||||
}
|
||||
|
||||
function buildUserAliasContext(graph = null, extraHints = []) {
|
||||
const aliasHints = [];
|
||||
appendAliasHintStrings(aliasHints, graph?.historyState?.activeUserPovOwner);
|
||||
appendAliasHintStrings(aliasHints, getHostUserAliasHints());
|
||||
appendAliasHintStrings(aliasHints, extraHints);
|
||||
const uniqueAliasHints = uniqueStrings(aliasHints);
|
||||
return {
|
||||
aliasHints: uniqueAliasHints,
|
||||
aliasSet: buildUserPovAliasNormalizedSet(uniqueAliasHints),
|
||||
preferredName: uniqueAliasHints[0] || "",
|
||||
};
|
||||
}
|
||||
|
||||
function shouldResolveCharacterOwnerAsUser(
|
||||
graph,
|
||||
ownerName = "",
|
||||
nodeId = "",
|
||||
userAliasContext = null,
|
||||
) {
|
||||
const normalizedOwnerName = normalizeString(ownerName);
|
||||
if (!normalizedOwnerName) return false;
|
||||
const aliasContext = userAliasContext || buildUserAliasContext(graph);
|
||||
if (!aliasSetMatchesValue(aliasContext.aliasSet, normalizedOwnerName)) {
|
||||
return false;
|
||||
}
|
||||
const normalizedNodeId = normalizeString(nodeId);
|
||||
if (normalizedNodeId) {
|
||||
const explicitNode = findCharacterNodeById(graph, normalizedNodeId);
|
||||
if (explicitNode) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getCharacterNodes(graph) {
|
||||
return Array.isArray(graph?.nodes)
|
||||
? graph.nodes.filter(
|
||||
@@ -241,7 +301,12 @@ function mergeKnowledgeOwnerEntries(baseEntry, incomingEntry) {
|
||||
return merged;
|
||||
}
|
||||
|
||||
function resolveCanonicalKnowledgeEntry(graph, ownerKey, entry) {
|
||||
function resolveCanonicalKnowledgeEntry(
|
||||
graph,
|
||||
ownerKey,
|
||||
entry,
|
||||
userAliasContext = null,
|
||||
) {
|
||||
const normalizedEntry = createDefaultKnowledgeOwnerState({
|
||||
...entry,
|
||||
ownerKey,
|
||||
@@ -252,6 +317,7 @@ function resolveCanonicalKnowledgeEntry(graph, ownerKey, entry) {
|
||||
ownerId: normalizedEntry.ownerName,
|
||||
nodeId: normalizedEntry.nodeId,
|
||||
aliases: normalizedEntry.aliases,
|
||||
userAliasContext,
|
||||
});
|
||||
return createDefaultKnowledgeOwnerState({
|
||||
...normalizedEntry,
|
||||
@@ -270,8 +336,14 @@ function resolveCanonicalKnowledgeEntry(graph, ownerKey, entry) {
|
||||
export function normalizeKnowledgeState(state = {}, graph = null) {
|
||||
const normalized = createDefaultKnowledgeState(state);
|
||||
const owners = {};
|
||||
const userAliasContext = buildUserAliasContext(graph);
|
||||
for (const [ownerKey, rawEntry] of Object.entries(normalized.owners || {})) {
|
||||
const canonicalEntry = resolveCanonicalKnowledgeEntry(graph, ownerKey, rawEntry);
|
||||
const canonicalEntry = resolveCanonicalKnowledgeEntry(
|
||||
graph,
|
||||
ownerKey,
|
||||
rawEntry,
|
||||
userAliasContext,
|
||||
);
|
||||
if (!canonicalEntry.ownerKey) continue;
|
||||
owners[canonicalEntry.ownerKey] = owners[canonicalEntry.ownerKey]
|
||||
? mergeKnowledgeOwnerEntries(owners[canonicalEntry.ownerKey], canonicalEntry)
|
||||
@@ -321,16 +393,27 @@ export function resolveKnowledgeOwner(graph, input = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
const userAliasContext =
|
||||
input?.userAliasContext &&
|
||||
input.userAliasContext.aliasSet instanceof Set
|
||||
? input.userAliasContext
|
||||
: buildUserAliasContext(graph);
|
||||
|
||||
if (ownerType === OWNER_TYPE_USER) {
|
||||
const ownerName = normalizeString(
|
||||
const fallbackOwnerName = normalizeString(
|
||||
input.ownerName || input.ownerId || input.ownerKey,
|
||||
);
|
||||
const ownerName = userAliasContext.preferredName || fallbackOwnerName;
|
||||
return {
|
||||
ownerType,
|
||||
ownerKey: buildOwnerKey(ownerType, ownerName),
|
||||
ownerName,
|
||||
nodeId: "",
|
||||
aliases: uniqueStrings(input.aliases || [ownerName]),
|
||||
aliases: uniqueStrings([
|
||||
...(Array.isArray(input.aliases) ? input.aliases : [input.aliases]),
|
||||
...userAliasContext.aliasHints,
|
||||
ownerName,
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -342,6 +425,31 @@ export function resolveKnowledgeOwner(graph, input = {}) {
|
||||
ownerName = ownerName || normalizeString(explicitNode?.fields?.name);
|
||||
}
|
||||
|
||||
if (
|
||||
shouldResolveCharacterOwnerAsUser(
|
||||
graph,
|
||||
ownerName || input.ownerId,
|
||||
nodeId,
|
||||
userAliasContext,
|
||||
)
|
||||
) {
|
||||
const userOwnerName =
|
||||
userAliasContext.preferredName ||
|
||||
normalizeString(ownerName || input.ownerId || input.ownerKey);
|
||||
return {
|
||||
ownerType: OWNER_TYPE_USER,
|
||||
ownerKey: buildOwnerKey(OWNER_TYPE_USER, userOwnerName),
|
||||
ownerName: userOwnerName,
|
||||
nodeId: "",
|
||||
aliases: uniqueStrings([
|
||||
...(Array.isArray(input.aliases) ? input.aliases : [input.aliases]),
|
||||
...userAliasContext.aliasHints,
|
||||
ownerName,
|
||||
userOwnerName,
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
||||
if (!nodeId && ownerName) {
|
||||
const matches = findCharacterNodeByName(graph, ownerName);
|
||||
if (matches.length === 1) {
|
||||
@@ -1224,6 +1332,7 @@ export function getKnowledgeOwnerEntry(graph, ownerKey = "") {
|
||||
export function listKnowledgeOwners(graph) {
|
||||
normalizeGraphCognitiveState(graph);
|
||||
const owners = new Map();
|
||||
const userAliasContext = buildUserAliasContext(graph);
|
||||
|
||||
for (const entry of Object.values(graph.knowledgeState.owners || {})) {
|
||||
const normalizedEntry = createDefaultKnowledgeOwnerState(entry);
|
||||
@@ -1244,10 +1353,21 @@ export function listKnowledgeOwners(graph) {
|
||||
}
|
||||
|
||||
for (const characterNode of getCharacterNodes(graph)) {
|
||||
if (
|
||||
shouldResolveCharacterOwnerAsUser(
|
||||
graph,
|
||||
characterNode?.fields?.name,
|
||||
"",
|
||||
userAliasContext,
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const resolvedOwner = resolveKnowledgeOwner(graph, {
|
||||
ownerType: OWNER_TYPE_CHARACTER,
|
||||
ownerName: characterNode?.fields?.name,
|
||||
nodeId: characterNode?.id,
|
||||
userAliasContext,
|
||||
});
|
||||
if (!resolvedOwner.ownerKey || owners.has(resolvedOwner.ownerKey)) continue;
|
||||
owners.set(resolvedOwner.ownerKey, {
|
||||
|
||||
Reference in New Issue
Block a user