mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-06-13 18:31:16 +08:00
Restore extraction visibility for managed hidden messages
This commit is contained in:
@@ -5,8 +5,20 @@
|
||||
import { clampInt } from "./ui-status.js";
|
||||
import { sanitizePlannerMessageText } from "./planner-tag-utils.js";
|
||||
import { rollbackBatch } from "./runtime-state.js";
|
||||
import { isInManagedHideRange } from "./hide-engine.js";
|
||||
|
||||
export function isBmeManagedHiddenMessage(
|
||||
message,
|
||||
{ index = null, chat = null } = {},
|
||||
) {
|
||||
if (
|
||||
Number.isFinite(index) &&
|
||||
index > 0 &&
|
||||
isInManagedHideRange(index, chat)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isBmeManagedHiddenMessage(message) {
|
||||
return Boolean(
|
||||
message?.extra &&
|
||||
typeof message.extra === "object" &&
|
||||
@@ -14,15 +26,24 @@ export function isBmeManagedHiddenMessage(message) {
|
||||
);
|
||||
}
|
||||
|
||||
export function isSystemMessageForExtraction(message) {
|
||||
return Boolean(message?.is_system) && !isBmeManagedHiddenMessage(message);
|
||||
export function isSystemMessageForExtraction(
|
||||
message,
|
||||
{ index = null, chat = null } = {},
|
||||
) {
|
||||
if (!message?.is_system) return false;
|
||||
if (Number.isFinite(index) && index === 0) return true;
|
||||
|
||||
return !isBmeManagedHiddenMessage(message, { index, chat });
|
||||
}
|
||||
|
||||
export function isAssistantChatMessage(message) {
|
||||
export function isAssistantChatMessage(
|
||||
message,
|
||||
{ index = null, chat = null } = {},
|
||||
) {
|
||||
return (
|
||||
Boolean(message) &&
|
||||
!message.is_user &&
|
||||
!isSystemMessageForExtraction(message)
|
||||
!isSystemMessageForExtraction(message, { index, chat })
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,7 +51,7 @@ export function getAssistantTurns(chat) {
|
||||
const assistantTurns = [];
|
||||
// 从 index 1 开始:index 0 是角色卡首条消息(greeting),不参与提取
|
||||
for (let index = 1; index < chat.length; index++) {
|
||||
if (isAssistantChatMessage(chat[index])) {
|
||||
if (isAssistantChatMessage(chat[index], { index, chat })) {
|
||||
assistantTurns.push(index);
|
||||
}
|
||||
}
|
||||
@@ -53,7 +74,7 @@ export function buildExtractionMessages(chat, startIdx, endIdx, settings) {
|
||||
index++
|
||||
) {
|
||||
const msg = chat[index];
|
||||
if (isSystemMessageForExtraction(msg)) continue;
|
||||
if (isSystemMessageForExtraction(msg, { index, chat })) continue;
|
||||
messages.push({
|
||||
seq: index,
|
||||
role: msg.is_user ? "user" : "assistant",
|
||||
@@ -70,7 +91,7 @@ export function getChatIndexForPlayableSeq(chat, playableSeq) {
|
||||
let currentSeq = -1;
|
||||
for (let index = 0; index < chat.length; index++) {
|
||||
const message = chat[index];
|
||||
if (isSystemMessageForExtraction(message)) continue;
|
||||
if (isSystemMessageForExtraction(message, { index, chat })) continue;
|
||||
currentSeq++;
|
||||
if (currentSeq >= playableSeq) {
|
||||
return index;
|
||||
@@ -85,7 +106,7 @@ export function getChatIndexForAssistantSeq(chat, assistantSeq) {
|
||||
|
||||
let currentSeq = -1;
|
||||
for (let index = 0; index < chat.length; index++) {
|
||||
if (!isAssistantChatMessage(chat[index])) continue;
|
||||
if (!isAssistantChatMessage(chat[index], { index, chat })) continue;
|
||||
currentSeq++;
|
||||
if (currentSeq >= assistantSeq) {
|
||||
return index;
|
||||
|
||||
@@ -546,3 +546,11 @@ export function getHideStateSnapshot() {
|
||||
scheduled: Boolean(hideState.scheduledTimer),
|
||||
};
|
||||
}
|
||||
|
||||
export function isInManagedHideRange(index, chat = null) {
|
||||
if (!Number.isFinite(index) || index < 0) return false;
|
||||
if (!hideState.managedChatRef) return false;
|
||||
if (Array.isArray(chat) && chat !== hideState.managedChatRef) return false;
|
||||
|
||||
return hideState.managedSystemIndices.has(index);
|
||||
}
|
||||
|
||||
48
index.js
48
index.js
@@ -4360,22 +4360,6 @@ function notifyExtractionIssue(message, title = "ST-BME 提取提示") {
|
||||
toastr.warning(message, title, { timeOut: 4500 });
|
||||
}
|
||||
|
||||
function settleExtractionStatusAfterHistoryRecovery(
|
||||
text = "提取完成",
|
||||
meta = "",
|
||||
level = "success",
|
||||
) {
|
||||
const currentText = String(lastExtractionStatus?.text || "");
|
||||
const currentLevel = String(lastExtractionStatus?.level || "");
|
||||
if (currentText !== "AI 生成中" && currentLevel !== "running") {
|
||||
return;
|
||||
}
|
||||
setLastExtractionStatus(text, meta, level, {
|
||||
syncRuntime: true,
|
||||
toastKind: "",
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchLocalWithTimeout(
|
||||
url,
|
||||
options = {},
|
||||
@@ -5611,8 +5595,12 @@ const DEFAULT_TRIGGER_KEYWORDS = [
|
||||
export function getSmartTriggerDecision(chat, lastProcessed, settings) {
|
||||
const pendingMessages = chat
|
||||
.slice(Math.max(0, (lastProcessed ?? -1) + 1))
|
||||
.filter((msg) => !isSystemMessageForExtraction(msg))
|
||||
.map((msg) => ({
|
||||
.map((msg, offset) => ({
|
||||
msg,
|
||||
index: Math.max(0, (lastProcessed ?? -1) + 1) + offset,
|
||||
}))
|
||||
.filter(({ msg, index }) => !isSystemMessageForExtraction(msg, { index, chat }))
|
||||
.map(({ msg }) => ({
|
||||
role: msg.is_user ? "user" : "assistant",
|
||||
content: msg.mes || "",
|
||||
}))
|
||||
@@ -7879,6 +7867,30 @@ async function recoverHistoryIfNeeded(trigger = "history-recovery") {
|
||||
}
|
||||
}
|
||||
|
||||
function settleExtractionStatusAfterHistoryRecovery(
|
||||
text = "提取完成",
|
||||
meta = "",
|
||||
level = "success",
|
||||
) {
|
||||
const statusSnapshot =
|
||||
typeof lastExtractionStatus === "object" && lastExtractionStatus
|
||||
? lastExtractionStatus
|
||||
: null;
|
||||
if (!statusSnapshot || typeof setLastExtractionStatus !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentText = String(statusSnapshot.text || "");
|
||||
const currentLevel = String(statusSnapshot.level || "");
|
||||
if (currentText !== "AI 生成中" && currentLevel !== "running") {
|
||||
return;
|
||||
}
|
||||
setLastExtractionStatus(text, meta, level, {
|
||||
syncRuntime: true,
|
||||
toastKind: "",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取管线:处理未提取的对话楼层
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
applyHideSettings,
|
||||
isInManagedHideRange,
|
||||
resetHideState,
|
||||
} from "../hide-engine.js";
|
||||
import {
|
||||
buildExtractionMessages,
|
||||
getAssistantTurns,
|
||||
@@ -32,6 +37,23 @@ const realSystemMessage = {
|
||||
assert.equal(isSystemMessageForExtraction(realSystemMessage), true);
|
||||
assert.equal(isAssistantChatMessage(realSystemMessage), false);
|
||||
|
||||
function createRuntime(chat, chatId = "chat-a") {
|
||||
return {
|
||||
chat,
|
||||
chatId,
|
||||
async executeSlashCommands() {
|
||||
return "";
|
||||
},
|
||||
getContext() {
|
||||
return {
|
||||
chat: this.chat,
|
||||
chatId: this.chatId,
|
||||
executeSlashCommands: this.executeSlashCommands.bind(this),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const chat = [
|
||||
{ is_user: false, is_system: true, mes: "greeting/system" },
|
||||
{ is_user: true, is_system: false, mes: "user-1" },
|
||||
@@ -65,4 +87,41 @@ assert.deepEqual(
|
||||
"extraction should keep BME-managed hidden context but still skip real system messages",
|
||||
);
|
||||
|
||||
resetHideState();
|
||||
const autoHiddenChat = [
|
||||
{ is_user: false, is_system: true, mes: "greeting/system" },
|
||||
{ is_user: true, is_system: false, mes: "user-1" },
|
||||
{ is_user: false, is_system: false, mes: "assistant-1" },
|
||||
{ is_user: true, is_system: false, mes: "user-2" },
|
||||
{ is_user: false, is_system: false, mes: "assistant-2" },
|
||||
{ is_user: true, is_system: false, mes: "user-3" },
|
||||
{ is_user: false, is_system: false, mes: "assistant-3" },
|
||||
];
|
||||
await applyHideSettings(
|
||||
{ enabled: true, hide_last_n: 2 },
|
||||
createRuntime(autoHiddenChat),
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
isInManagedHideRange(2, autoHiddenChat),
|
||||
true,
|
||||
"auto-hidden ordinary floors should be queryable from hide-engine managed range",
|
||||
);
|
||||
assert.equal(
|
||||
isSystemMessageForExtraction(autoHiddenChat[2], {
|
||||
index: 2,
|
||||
chat: autoHiddenChat,
|
||||
}),
|
||||
false,
|
||||
"auto-hidden ordinary floors inside managed range should remain extractable",
|
||||
);
|
||||
assert.equal(
|
||||
isSystemMessageForExtraction(autoHiddenChat[0], {
|
||||
index: 0,
|
||||
chat: autoHiddenChat,
|
||||
}),
|
||||
true,
|
||||
"greeting/system floor should still be treated as system even if hide range starts at 0",
|
||||
);
|
||||
|
||||
console.log("chat-history tests passed");
|
||||
|
||||
Reference in New Issue
Block a user