From 8320e3e7f68d90467662cdf745e96e22b82eaae1 Mon Sep 17 00:00:00 2001 From: Youzini-afk <13153778771cx@gmail.com> Date: Mon, 6 Apr 2026 11:26:37 +0800 Subject: [PATCH] Add debug log toggle and silence diagnostic logs --- compressor.js | 3 +- consolidator.js | 13 +++++---- debug-logging.js | 59 ++++++++++++++++++++++++++++++++++++++ ena-planner/ena-planner.js | 11 +++---- event-binding.js | 34 +++++++++++----------- extraction-controller.js | 6 ++-- extractor.js | 19 ++++++------ graph.js | 3 +- host-adapter/context.js | 5 ++-- host-adapter/injection.js | 3 +- host-adapter/regex.js | 3 +- host-adapter/worldbook.js | 3 +- index.js | 41 +++++++++++++++++--------- llm.js | 11 +++---- panel-bridge.js | 4 ++- panel.html | 26 +++++++++++++++++ panel.js | 7 +++++ prompt-builder.js | 15 +++++----- recall-controller.js | 22 +++++++------- retriever.js | 15 +++++----- task-regex.js | 3 +- task-worldinfo.js | 11 +++---- tests/default-settings.mjs | 5 ++-- 23 files changed, 226 insertions(+), 96 deletions(-) create mode 100644 debug-logging.js diff --git a/compressor.js b/compressor.js index 1b5bc89..4e8a94f 100644 --- a/compressor.js +++ b/compressor.js @@ -1,6 +1,7 @@ // ST-BME: 层级压缩引擎 // 超过阈值的节点被 LLM 总结为更高层级的压缩节点 +import { debugLog } from "./debug-logging.js"; import { embedText } from "./embedding.js"; import { addEdge, @@ -517,7 +518,7 @@ export function sleepCycle(graph, settings) { } if (forgotten > 0) { - console.log(`[ST-BME] 主动遗忘: ${forgotten} 个低价值节点已归档`); + debugLog(`[ST-BME] 主动遗忘: ${forgotten} 个低价值节点已归档`); } return { forgotten }; diff --git a/consolidator.js b/consolidator.js index d03a25f..48f58b1 100644 --- a/consolidator.js +++ b/consolidator.js @@ -2,6 +2,7 @@ // 合并 Mem0 精确对照 + A-MEM 记忆进化为单一阶段 // 批量 embed + 批量查近邻 + 单次 LLM 调用 +import { debugLog } from "./debug-logging.js"; import { embedBatch, searchSimilar } from "./embedding.js"; import { addEdge, createEdge, getActiveNodes, getNode } from "./graph.js"; import { callLLMForJSON } from "./llm.js"; @@ -301,7 +302,7 @@ export async function consolidateMemories({ if (!newNodeIds || newNodeIds.length === 0) return stats; if (!validateVectorConfig(embeddingConfig).valid) { - console.log("[ST-BME] 记忆整合跳过:向量配置不可用"); + debugLog("[ST-BME] 记忆整合跳过:向量配置不可用"); return stats; } @@ -331,7 +332,7 @@ export async function consolidateMemories({ } throwIfAborted(signal); - console.log(`[ST-BME] 记忆整合开始: ${newEntries.length} 个新节点`); + debugLog(`[ST-BME] 记忆整合开始: ${newEntries.length} 个新节点`); // ══════════════════════════════════════════════ // Phase 1 + 2: 批量 Embed + 查近邻 @@ -571,7 +572,7 @@ export async function consolidateMemories({ if (stats.updates > 0) actionSummary.push(`回溯更新 ${stats.updates}`); if (actionSummary.length > 0) { - console.log(`[ST-BME] 记忆整合完成: ${actionSummary.join(", ")}`); + debugLog(`[ST-BME] 记忆整合完成: ${actionSummary.join(", ")}`); } return stats; @@ -586,7 +587,7 @@ function processOneResult(graph, entry, result, stats) { // ── 处理 action ── switch (result.action) { case "skip": { - console.log(`[ST-BME] 记忆整合: skip (重复) — ${newId}`); + debugLog(`[ST-BME] 记忆整合: skip (重复) — ${newId}`); newNode.archived = true; stats.skipped++; break; @@ -601,7 +602,7 @@ function processOneResult(graph, entry, result, stats) { !targetNode.archived && canMergeScopedMemories(newNode, targetNode) ) { - console.log(`[ST-BME] 记忆整合: merge ${newId} → ${targetId}`); + debugLog(`[ST-BME] 记忆整合: merge ${newId} → ${targetId}`); if (result.merged_fields && typeof result.merged_fields === "object") { for (const [key, value] of Object.entries(result.merged_fields)) { @@ -658,7 +659,7 @@ function processOneResult(graph, entry, result, stats) { const evolution = result.evolution; if (evolution?.should_evolve && !newNode.archived) { stats.evolved++; - console.log(`[ST-BME] 记忆整合/进化触发: ${result.reason || "(无理由)"}`); + debugLog(`[ST-BME] 记忆整合/进化触发: ${result.reason || "(无理由)"}`); if (Array.isArray(evolution.connections)) { for (const targetId of evolution.connections) { diff --git a/debug-logging.js b/debug-logging.js new file mode 100644 index 0000000..3fc2bb2 --- /dev/null +++ b/debug-logging.js @@ -0,0 +1,59 @@ +const MODULE_NAME = "st_bme"; +const GLOBAL_DEBUG_FLAG_KEY = "__stBmeDebugLoggingEnabled"; + +function resolveModuleSettings(settings = null) { + if (settings && typeof settings === "object") { + return settings; + } + + const moduleSettings = + globalThis?.extension_settings?.[MODULE_NAME] || + globalThis?.__p0ExtensionSettings?.[MODULE_NAME] || + globalThis?.SillyTavern?.getContext?.()?.extensionSettings?.[MODULE_NAME] || + null; + return moduleSettings && typeof moduleSettings === "object" + ? moduleSettings + : null; +} + +export function isDebugLoggingEnabled(settings = null) { + if ( + settings && + typeof settings === "object" && + Object.prototype.hasOwnProperty.call(settings, "debugLoggingEnabled") + ) { + return Boolean(settings.debugLoggingEnabled); + } + + if (typeof globalThis[GLOBAL_DEBUG_FLAG_KEY] === "boolean") { + return globalThis[GLOBAL_DEBUG_FLAG_KEY]; + } + + return Boolean(resolveModuleSettings(settings)?.debugLoggingEnabled); +} + +function emitDebugLog(method, args, settings = null) { + if (!isDebugLoggingEnabled(settings)) { + return; + } + + const target = + typeof console?.[method] === "function" ? console[method] : console.log; + Reflect.apply(target, console, args); +} + +export function debugLog(...args) { + emitDebugLog("log", args); +} + +export function debugInfo(...args) { + emitDebugLog("info", args); +} + +export function debugWarn(...args) { + emitDebugLog("warn", args); +} + +export function debugDebug(...args) { + emitDebugLog("debug", args); +} diff --git a/ena-planner/ena-planner.js b/ena-planner/ena-planner.js index c0c28c7..6a6d7bd 100644 --- a/ena-planner/ena-planner.js +++ b/ena-planner/ena-planner.js @@ -2,6 +2,7 @@ import { extension_settings } from '../../../../extensions.js'; import { getRequestHeaders, saveSettingsDebounced, substituteParamsExtended } from '../../../../../script.js'; import { EnaPlannerStorage, migrateFromLWBIfNeeded } from './ena-planner-storage.js'; import { DEFAULT_PROMPT_BLOCKS, BUILTIN_TEMPLATES } from './ena-planner-presets.js'; +import { debugLog } from '../debug-logging.js'; import jsyaml from '../vendor/js-yaml.mjs'; const EXT_NAME = 'ena-planner'; @@ -199,7 +200,7 @@ async function saveConfigNow() { function toastInfo(msg) { if (window.toastr?.info) return window.toastr.info(msg); - console.log('[EnaPlanner]', msg); + debugLog('[EnaPlanner]', msg); } function toastErr(msg) { if (window.toastr?.error) return window.toastr.error(msg); @@ -505,7 +506,7 @@ async function getCharacterWorldbooks() { } } catch { } - console.log('[EnaPlanner] Character worldbook names found:', worldNames); + debugLog('[EnaPlanner] Character worldbook names found:', worldNames); return worldNames.filter(Boolean); } @@ -618,11 +619,11 @@ async function buildWorldbookBlock(scanText) { const allWorldNames = [...new Set([...charWorldNames, ...globalWorldNames])]; if (!allWorldNames.length) { - console.log('[EnaPlanner] No worldbooks to load'); + debugLog('[EnaPlanner] No worldbooks to load'); return ''; } - console.log('[EnaPlanner] Loading worldbooks:', allWorldNames); + debugLog('[EnaPlanner] Loading worldbooks:', allWorldNames); // Fetch all worldbook data const worldbookResults = await Promise.all(allWorldNames.map(name => getWorldbookData(name))); @@ -1155,7 +1156,7 @@ async function buildPlannerMessages(rawUserInput) { clearTimeout(timeoutId); } } - console.log(`[Ena] Memory source: ${memorySource}`); + debugLog(`[Ena] Memory source: ${memorySource}`); // --- Chat history: last 2 AI messages (floors N-1 & N-3) --- // Two messages instead of one to avoid cross-device cache miss: diff --git a/event-binding.js b/event-binding.js index 4c4602f..e8c3743 100644 --- a/event-binding.js +++ b/event-binding.js @@ -1,3 +1,5 @@ +import { debugWarn } from "./debug-logging.js"; + function getTimerApi(runtime) { const rawSetTimeout = typeof runtime?.setTimeout === "function" @@ -38,14 +40,14 @@ export function registerBeforeCombinePromptsController(runtime, listener) { export function registerGenerationAfterCommandsController(runtime, listener) { const makeFirst = runtime.getEventMakeFirst(); const eventName = runtime.eventTypes.GENERATION_AFTER_COMMANDS; - console.warn("[ST-BME:DIAG] Registering GENERATION_AFTER_COMMANDS:", { + debugWarn("[ST-BME:DIAG] Registering GENERATION_AFTER_COMMANDS:", { eventName, hasMakeFirst: typeof makeFirst === "function", hasListener: typeof listener === "function", }); if (typeof makeFirst === "function") { const cleanup = makeFirst(eventName, listener); - console.warn("[ST-BME:DIAG] Registered via makeFirst, cleanup:", typeof cleanup); + debugWarn("[ST-BME:DIAG] Registered via makeFirst, cleanup:", typeof cleanup); return cleanup; } @@ -406,9 +408,9 @@ export async function onGenerationAfterCommandsController( params = {}, dryRun = false, ) { - console.warn("[ST-BME:DIAG] GENERATION_AFTER_COMMANDS fired", { type, dryRun, paramsKeys: Object.keys(params || {}) }); + debugWarn("[ST-BME:DIAG] GENERATION_AFTER_COMMANDS fired", { type, dryRun, paramsKeys: Object.keys(params || {}) }); if (dryRun) { - console.warn("[ST-BME:DIAG] EXIT: dryRun=true"); + debugWarn("[ST-BME:DIAG] EXIT: dryRun=true"); return; } @@ -418,11 +420,11 @@ export async function onGenerationAfterCommandsController( ? runtime.consumeHostGenerationInputSnapshot?.({ preserve: true }) || runtime.consumeHostGenerationInputSnapshot?.() : null; - console.warn("[ST-BME:DIAG] frozenInputSnapshot:", frozenInputSnapshot?.text ? `"${frozenInputSnapshot.text.slice(0,50)}"` : "(empty)", "fresh:", !!frozenInputSnapshot?.at); + debugWarn("[ST-BME:DIAG] frozenInputSnapshot:", frozenInputSnapshot?.text ? `"${frozenInputSnapshot.text.slice(0,50)}"` : "(empty)", "fresh:", !!frozenInputSnapshot?.at); const context = runtime.getContext(); const chat = context?.chat; - console.warn("[ST-BME:DIAG] chat length:", chat?.length, "last msg:", chat?.length ? { is_user: chat[chat.length-1]?.is_user, mes: (chat[chat.length-1]?.mes||"").slice(0,50) } : "(no chat)"); + debugWarn("[ST-BME:DIAG] chat length:", chat?.length, "last msg:", chat?.length ? { is_user: chat[chat.length-1]?.is_user, mes: (chat[chat.length-1]?.mes||"").slice(0,50) } : "(no chat)"); const recallOptions = runtime.buildGenerationAfterCommandsRecallInput( type, @@ -433,14 +435,14 @@ export async function onGenerationAfterCommandsController( chat, ); if (!recallOptions) { - console.warn("[ST-BME:DIAG] EXIT: buildGenerationAfterCommandsRecallInput returned null"); + debugWarn("[ST-BME:DIAG] EXIT: buildGenerationAfterCommandsRecallInput returned null"); return; } if (recallOptions?.__trivialSkip) { - console.warn("[ST-BME:DIAG] EXIT: trivial-input-skip"); + debugWarn("[ST-BME:DIAG] EXIT: trivial-input-skip"); return; } - console.warn("[ST-BME:DIAG] recallOptions:", { generationType: recallOptions.generationType, overrideUserMessage: recallOptions.overrideUserMessage?.slice(0,50), overrideSource: recallOptions.overrideSource, targetIdx: recallOptions.targetUserMessageIndex }); + debugWarn("[ST-BME:DIAG] recallOptions:", { generationType: recallOptions.generationType, overrideUserMessage: recallOptions.overrideUserMessage?.slice(0,50), overrideSource: recallOptions.overrideSource, targetIdx: recallOptions.targetUserMessageIndex }); const recallContext = runtime.createGenerationRecallContext({ hookName: "GENERATION_AFTER_COMMANDS", @@ -448,10 +450,10 @@ export async function onGenerationAfterCommandsController( recallOptions, }); if (!recallContext.shouldRun && !recallContext.transaction) { - console.warn("[ST-BME:DIAG] EXIT: shouldRun=false, no transaction. guardReason:", recallContext.guardReason); + debugWarn("[ST-BME:DIAG] EXIT: shouldRun=false, no transaction. guardReason:", recallContext.guardReason); return; } - console.warn("[ST-BME:DIAG] recallContext:", { shouldRun: recallContext.shouldRun, guardReason: recallContext.guardReason, transactionId: recallContext.transaction?.id }); + debugWarn("[ST-BME:DIAG] recallContext:", { shouldRun: recallContext.shouldRun, guardReason: recallContext.guardReason, transactionId: recallContext.transaction?.id }); const runtimeRecallOptions = recallContext.recallOptions || recallOptions || {}; @@ -464,7 +466,7 @@ export async function onGenerationAfterCommandsController( let recallResult = runtime.getGenerationRecallTransactionResult?.( recallContext.transaction, ); - console.warn("[ST-BME:DIAG] deliveryMode:", deliveryMode, "shouldRun:", recallContext.shouldRun); + debugWarn("[ST-BME:DIAG] deliveryMode:", deliveryMode, "shouldRun:", recallContext.shouldRun); if (recallContext.shouldRun) { runtime.markGenerationRecallTransactionHookState( @@ -475,7 +477,7 @@ export async function onGenerationAfterCommandsController( if (deliveryMode === "deferred") { runtime.clearLiveRecallInjectionPromptForRewrite?.(); } - console.warn("[ST-BME:DIAG] >>> Starting runRecall..."); + debugWarn("[ST-BME:DIAG] >>> Starting runRecall..."); recallResult = await runtime.runRecall({ ...runtimeRecallOptions, deliveryMode, @@ -483,7 +485,7 @@ export async function onGenerationAfterCommandsController( hookName: recallContext.hookName, signal: params?.signal, }); - console.warn("[ST-BME:DIAG] <<< runRecall finished:", { status: recallResult?.status, ok: recallResult?.ok, reason: recallResult?.reason, injectionText: recallResult?.injectionText?.slice(0,80) }); + debugWarn("[ST-BME:DIAG] <<< runRecall finished:", { status: recallResult?.status, ok: recallResult?.ok, reason: recallResult?.reason, injectionText: recallResult?.injectionText?.slice(0,80) }); runtime.storeGenerationRecallTransactionResult?.( recallContext.transaction, recallResult, @@ -516,7 +518,7 @@ export async function onGenerationAfterCommandsController( // 上面的兜底补写会把 fresh recall 绑定回最终 user 楼层。 // 这里再补一次 UI 刷新,避免需要等到消息编辑/历史恢复后才看到 Recall Card。 runtime.refreshPersistedRecallMessageUi?.(); - console.warn("[ST-BME:DIAG] DONE: immediate mode, injection via setExtensionPrompt in runRecall"); + debugWarn("[ST-BME:DIAG] DONE: immediate mode, injection via setExtensionPrompt in runRecall"); return recallResult; } @@ -550,7 +552,7 @@ export async function onBeforeCombinePromptsController( frozenInputSnapshot, }); if (normalInput?.__trivialSkip) { - console.warn("[ST-BME:DIAG] EXIT: trivial-input-skip"); + debugWarn("[ST-BME:DIAG] EXIT: trivial-input-skip"); return { skipped: true, reason: `trivial:${normalInput.trivialReason || ""}`, diff --git a/extraction-controller.js b/extraction-controller.js index 363836c..3a5181b 100644 --- a/extraction-controller.js +++ b/extraction-controller.js @@ -1,6 +1,8 @@ // ST-BME: 提取编排控制器(纯函数) // 通过 runtime 依赖注入,避免直接访问 index.js 模块级状态。 +import { debugLog } from "./debug-logging.js"; + export async function executeExtractionBatchController( runtime, { @@ -25,7 +27,7 @@ export async function executeExtractionBatchController( extractionCountBefore, }); - runtime.console.log( + debugLog( `[ST-BME] 开始提取: 楼层 ${startIdx}-${endIdx}` + (smartTriggerDecision?.triggered ? ` [智能触发 score=${smartTriggerDecision.score}; ${smartTriggerDecision.reasons.join(" / ")}]` @@ -504,7 +506,7 @@ export async function onRerollController(runtime, { fromFloor } = {}) { }; } - runtime.console.log(`[ST-BME] 重 Roll 开始,目标楼层: ${targetFloor}`); + debugLog(`[ST-BME] 重 Roll 开始,目标楼层: ${targetFloor}`); let rollbackResult; try { rollbackResult = await runtime.rollbackGraphForReroll(targetFloor, context); diff --git a/extractor.js b/extractor.js index 930e5c8..f0d9b35 100644 --- a/extractor.js +++ b/extractor.js @@ -3,6 +3,7 @@ // v2: 融合 Mem0 精确对照 + Graphiti 时序边 + MemoRAG 全局概要 import { embedBatch } from "./embedding.js"; +import { debugLog, debugWarn } from "./debug-logging.js"; import { addEdge, addNode, @@ -345,7 +346,7 @@ export async function extractMemories({ activeUserOwner: stContext?.prompt?.userName || "", }; - console.log( + debugLog( `[ST-BME] 提取开始: chat[${effectiveStartSeq}..${effectiveEndSeq}], ${messages.length} 条消息`, ); @@ -416,7 +417,7 @@ export async function extractMemories({ const pm = Array.isArray(promptPayload.promptMessages) ? promptPayload.promptMessages : []; const pmUser = pm.filter((m) => m?.role === "user"); const am = Array.isArray(promptPayload.additionalMessages) ? promptPayload.additionalMessages : []; - console.log( + debugLog( `[ST-BME][prompt-diag] resolveTaskPromptPayload: ` + `promptMessages=${pm.length} (user=${pmUser.length}), ` + `additionalMessages=${am.length}, ` + @@ -426,13 +427,13 @@ export async function extractMemories({ ); if (pmUser.length > 0) { for (const m of pmUser) { - console.log( + debugLog( `[ST-BME][prompt-diag] user msg: contentLen=${String(m.content || "").length}, ` + `blockName="${m.blockName || ""}", preview="${String(m.content || "").slice(0, 60)}..."`, ); } } else { - console.warn( + debugWarn( `[ST-BME][prompt-diag] NO user messages in promptMessages! Fallback userPrompt will be used.`, ); } @@ -537,7 +538,7 @@ export async function extractMemories({ ); updateRuntimeScopeState(graph, newNodeIds, scopeRuntime); - console.log( + debugLog( `[ST-BME] 提取完成: 新建 ${stats.newNodes}, 更新 ${stats.updatedNodes}, 新边 ${stats.newEdges}, lastProcessedSeq=${graph.lastProcessedSeq}`, ); @@ -863,7 +864,7 @@ async function generateNodeEmbeddings(graph, embeddingConfig, signal) { (node) => buildNodeVectorText(node) || node.type, ); - console.log(`[ST-BME] 为 ${texts.length} 个节点生成 embedding`); + debugLog(`[ST-BME] 为 ${texts.length} 个节点生成 embedding`); const embeddings = await embedBatch(texts, embeddingConfig, { signal }); @@ -1089,7 +1090,7 @@ export async function generateSynopsis({ Math.max(existingSynopsis.seqRange?.[1] ?? currentSeq, currentSeq), ]; existingSynopsis.embedding = null; - console.log("[ST-BME] 全局概要已更新"); + debugLog("[ST-BME] 全局概要已更新"); } else { const node = createNode({ type: "synopsis", @@ -1098,7 +1099,7 @@ export async function generateSynopsis({ importance: 9.0, }); addNode(graph, node); - console.log("[ST-BME] 全局概要已创建"); + debugLog("[ST-BME] 全局概要已创建"); } } @@ -1238,6 +1239,6 @@ export async function generateReflection({ addEdge(graph, edge); } - console.log("[ST-BME] 反思条目已生成"); + debugLog("[ST-BME] 反思条目已生成"); return reflectionNode.id; } diff --git a/graph.js b/graph.js index 4b99159..5e12e55 100644 --- a/graph.js +++ b/graph.js @@ -14,6 +14,7 @@ import { normalizeNodeMemoryScope, isSameLatestScopeBucket, } from "./memory-scope.js"; +import { debugLog } from "./debug-logging.js"; /** * 图状态版本号 @@ -546,7 +547,7 @@ export function deserializeGraph(json) { } if (data.version < GRAPH_VERSION) { - console.log(`[ST-BME] 图版本迁移 v${data.version} → v${GRAPH_VERSION}`); + debugLog(`[ST-BME] 图版本迁移 v${data.version} → v${GRAPH_VERSION}`); if (data.version < 2 && data.edges) { for (const edge of data.edges) { diff --git a/host-adapter/context.js b/host-adapter/context.js index fc42dc2..6acfa23 100644 --- a/host-adapter/context.js +++ b/host-adapter/context.js @@ -1,6 +1,7 @@ import { getContext as extensionGetContext } from "../../../../extensions.js"; import { buildCapabilityStatus, mergeVersionHints } from "./capabilities.js"; +import { debugDebug } from "../debug-logging.js"; function resolveContextGetter(providedGetter = null) { if (typeof providedGetter === "function") { @@ -55,7 +56,7 @@ export function createContextHostFacade(options = {}) { try { return getContext(...args); } catch (error) { - console.debug( + debugDebug( "[ST-BME] host-adapter/context getContext 调用失败", error, ); @@ -71,7 +72,7 @@ export function createContextHostFacade(options = {}) { const context = getContext(...args); return context && typeof context === "object" ? context : null; } catch (error) { - console.debug("[ST-BME] host-adapter/context 读取上下文失败", error); + debugDebug("[ST-BME] host-adapter/context 读取上下文失败", error); return null; } }, diff --git a/host-adapter/injection.js b/host-adapter/injection.js index 11e7dcc..65fd963 100644 --- a/host-adapter/injection.js +++ b/host-adapter/injection.js @@ -1,5 +1,6 @@ import { buildCapabilityStatus, mergeVersionHints } from "./capabilities.js"; import { createContextHostFacade } from "./context.js"; +import { debugDebug } from "../debug-logging.js"; function resolvePromptSetter(providedSetter = null, contextHost = null) { if (typeof providedSetter === "function") { @@ -75,7 +76,7 @@ export function createInjectionHostFacade(options = {}) { liveSetterRecord.setter(...args); return true; } catch (error) { - console.debug( + debugDebug( "[ST-BME] host-adapter/injection setExtensionPrompt 调用失败", error, ); diff --git a/host-adapter/regex.js b/host-adapter/regex.js index 9612ffa..8f17396 100644 --- a/host-adapter/regex.js +++ b/host-adapter/regex.js @@ -1,5 +1,6 @@ import { buildCapabilityStatus, mergeVersionHints } from "./capabilities.js"; import { createContextHostFacade } from "./context.js"; +import { debugDebug } from "../debug-logging.js"; const REGEX_API_NAMES = ["getTavernRegexes", "isCharacterTavernRegexesEnabled"]; @@ -36,7 +37,7 @@ function resolveProviderCandidate(candidate, options = {}) { const resolved = candidate(options); return isObjectLike(resolved) ? resolved : null; } catch (error) { - console.debug("[ST-BME] host-adapter/regex provider 解析失败", error); + debugDebug("[ST-BME] host-adapter/regex provider 解析失败", error); return null; } } diff --git a/host-adapter/worldbook.js b/host-adapter/worldbook.js index c4ed884..39af207 100644 --- a/host-adapter/worldbook.js +++ b/host-adapter/worldbook.js @@ -1,5 +1,6 @@ import { buildCapabilityStatus, mergeVersionHints } from "./capabilities.js"; import { createContextHostFacade } from "./context.js"; +import { debugDebug } from "../debug-logging.js"; const WORLDBOOK_API_NAMES = [ "getWorldbook", @@ -40,7 +41,7 @@ function resolveProviderCandidate(candidate, options = {}) { const resolved = candidate(options); return isObjectLike(resolved) ? resolved : null; } catch (error) { - console.debug("[ST-BME] host-adapter/worldbook provider 解析失败", error); + debugDebug("[ST-BME] host-adapter/worldbook provider 解析失败", error); return null; } } diff --git a/index.js b/index.js index 1168f53..49097e2 100644 --- a/index.js +++ b/index.js @@ -72,6 +72,10 @@ import { onRerollController, runExtractionController, } from "./extraction-controller.js"; +import { + debugDebug, + debugLog, +} from "./debug-logging.js"; import { extractMemories, generateReflection, @@ -371,6 +375,7 @@ function readRuntimeDebugSnapshot() { const defaultSettings = { enabled: true, + debugLoggingEnabled: false, timeoutMs: 300000, hideOldMessagesEnabled: false, hideOldMessagesKeepLastN: 12, @@ -1486,6 +1491,7 @@ function getMessageRecallRecord(messageIndex) { } function debugWithThrottle(cache, key, ...args) { + if (!globalThis.__stBmeDebugLoggingEnabled) return; const now = Date.now(); const lastAt = cache.get(key) || 0; if (now - lastAt < PERSISTED_RECALL_UI_DIAGNOSTIC_THROTTLE_MS) return; @@ -2952,6 +2958,9 @@ function getSettings() { mergedSettings.taskProfilesVersion = migrated.taskProfilesVersion; mergedSettings.taskProfiles = migrated.taskProfiles; extension_settings[MODULE_NAME] = mergedSettings; + globalThis.__stBmeDebugLoggingEnabled = Boolean( + mergedSettings.debugLoggingEnabled, + ); return mergedSettings; } @@ -2989,7 +2998,7 @@ async function applyMessageHideNow(reason = "manual-apply") { getMessageHideSettings(), getHideRuntimeAdapters(), ); - console.log("[ST-BME] 已应用旧楼层隐藏:", reason, result); + debugLog("[ST-BME] 已应用旧楼层隐藏:", reason, result); return result; } catch (error) { console.warn("[ST-BME] 应用旧楼层隐藏失败:", reason, error); @@ -3019,7 +3028,7 @@ async function runIncrementalMessageHide(reason = "incremental") { getHideRuntimeAdapters(), ); if (result?.active) { - console.log("[ST-BME] 已增量更新旧楼层隐藏:", reason, result); + debugLog("[ST-BME] 已增量更新旧楼层隐藏:", reason, result); } return result; } catch (error) { @@ -3034,7 +3043,7 @@ async function runIncrementalMessageHide(reason = "incremental") { function clearMessageHideState(reason = "reset") { try { resetHideState(getHideRuntimeAdapters()); - console.log("[ST-BME] 已重置旧楼层隐藏状态:", reason); + debugLog("[ST-BME] 已重置旧楼层隐藏状态:", reason); } catch (error) { console.warn("[ST-BME] 重置旧楼层隐藏状态失败:", reason, error); } @@ -3043,7 +3052,7 @@ function clearMessageHideState(reason = "reset") { async function clearAllHiddenMessages(reason = "manual-clear") { try { const result = await unhideAll(getHideRuntimeAdapters()); - console.log("[ST-BME] 已取消全部旧楼层隐藏:", reason, result); + debugLog("[ST-BME] 已取消全部旧楼层隐藏:", reason, result); return result; } catch (error) { console.warn("[ST-BME] 取消全部旧楼层隐藏失败:", reason, error); @@ -3485,7 +3494,7 @@ async function syncBmeChatManagerWithCurrentChat( if (!chatId) { await manager.closeCurrent(); - console.debug("[ST-BME] IndexedDB 会话已关闭(无活动聊天)", { + debugDebug("[ST-BME] IndexedDB 会话已关闭(无活动聊天)", { source, }); return { @@ -3496,7 +3505,7 @@ async function syncBmeChatManagerWithCurrentChat( } const db = await manager.switchChat(chatId); - console.debug("[ST-BME] IndexedDB 会话已同步", { + debugDebug("[ST-BME] IndexedDB 会话已同步", { source, chatId, }); @@ -3715,7 +3724,7 @@ async function maybeMigrateLegacyGraphToIndexedDb( const postMigrationSnapshot = await targetDb.exportSnapshot(); cacheIndexedDbSnapshot(normalizedChatId, postMigrationSnapshot); - console.debug("[ST-BME] legacy chat_metadata 图谱迁移完成", { + debugDebug("[ST-BME] legacy chat_metadata 图谱迁移完成", { source, chatId: normalizedChatId, revision: @@ -3990,7 +3999,7 @@ function applyIndexedDbSnapshotToRuntime( removeGraphShadowSnapshot(normalizedChatId); refreshPanelLiveState(); schedulePersistedRecallMessageUiRefresh(30); - console.debug("[ST-BME] 已从 IndexedDB 加载图谱", { + debugDebug("[ST-BME] 已从 IndexedDB 加载图谱", { chatId: normalizedChatId, source, revision, @@ -4766,7 +4775,7 @@ function scheduleGraphLoadRetry( clearPendingGraphLoadRetry({ resetChatId: false }); pendingGraphLoadRetryChatId = normalizedChatId || (allowPendingChat ? GRAPH_LOAD_PENDING_CHAT_ID : ""); - console.debug( + debugDebug( `[ST-BME] 图谱元数据尚未就绪,${delayMs}ms 后重试加载(chat=${normalizedChatId || "pending"},attempt=${attemptIndex + 1},reason=${reason})`, ); @@ -5543,7 +5552,7 @@ async function ensureVectorReadyIfNeeded( currentGraph.vectorIndexState.lastWarning = ""; saveGraphToChat({ reason: "vector-auto-repair-succeeded" }); - console.log("[ST-BME] 向量状态已自动修复:", reason, result.stats); + debugLog("[ST-BME] 向量状态已自动修复:", reason, result.stats); return result; } @@ -5610,6 +5619,9 @@ async function loadServerSettings() { const loaded = await response.json(); if (loaded && typeof loaded === "object" && !Array.isArray(loaded)) { extension_settings[MODULE_NAME] = mergePersistedSettings(loaded); + globalThis.__stBmeDebugLoggingEnabled = Boolean( + extension_settings[MODULE_NAME]?.debugLoggingEnabled, + ); saveSettingsDebounced(); } } catch (error) { @@ -5670,6 +5682,9 @@ function updateModuleSettings(patch = {}) { const settings = getSettings(); Object.assign(settings, patch); extension_settings[MODULE_NAME] = settings; + globalThis.__stBmeDebugLoggingEnabled = Boolean( + settings.debugLoggingEnabled, + ); saveSettingsDebounced(); if ( @@ -9834,11 +9849,11 @@ async function onReembedDirect() { getExtensionPath: () => `scripts/extensions/third-party/${MODULE_NAME}`, isTrivialUserInput, preparePlannerRecallHandoff, - runPlannerRecallForEna, + runPlannerRecallForEna, }); - console.log("[ST-BME] Ena Planner module loaded"); + debugLog("[ST-BME] Ena Planner module loaded"); } catch (error) { console.warn("[ST-BME] Ena Planner module load failed:", error); } - console.log("[ST-BME] 初始化完成"); + debugLog("[ST-BME] 初始化完成"); })(); diff --git a/llm.js b/llm.js index d32054d..c07dae8 100644 --- a/llm.js +++ b/llm.js @@ -4,6 +4,7 @@ import { getRequestHeaders } from "../../../../script.js"; import { extension_settings } from "../../../extensions.js"; import { chat_completion_sources, sendOpenAIRequest } from "../../../openai.js"; +import { debugLog, debugWarn } from "./debug-logging.js"; import { resolveTaskGenerationOptions } from "./generation-options.js"; import { resolveConfiguredTimeoutMs } from "./request-timeout.js"; import { applyTaskRegex } from "./task-regex.js"; @@ -1585,13 +1586,13 @@ export async function callLLMForJSON({ ); { const asmUser = assembledMessages.filter((m) => m?.role === "user"); - console.log( + debugLog( `[ST-BME][prompt-diag] buildJsonAttemptMessages: ` + `total=${assembledMessages.length}, user=${asmUser.length}, ` + `roles=[${assembledMessages.map((m) => m?.role).join(",")}]`, ); for (const m of asmUser) { - console.log( + debugLog( `[ST-BME][prompt-diag] assembled user: len=${String(m.content || "").length}, ` + `preview="${String(m.content || "").slice(0, 80)}..."`, ); @@ -1605,18 +1606,18 @@ export async function callLLMForJSON({ const rcMsgs = Array.isArray(requestCleaning.messages) ? requestCleaning.messages : []; const rcUser = rcMsgs.filter((m) => m?.role === "user"); const dbg = requestCleaning.debug || {}; - console.log( + debugLog( `[ST-BME][prompt-diag] applyTaskFinalInputRegex: ` + `total=${rcMsgs.length}, user=${rcUser.length}, ` + `changed=${dbg.changed}, applied=${dbg.applied}, ` + `roles=[${rcMsgs.map((m) => m?.role).join(",")}]`, ); if (rcUser.length === 0 && assembledMessages.filter((m) => m?.role === "user").length > 0) { - console.warn( + debugWarn( `[ST-BME][prompt-diag] *** USER MESSAGES LOST during applyTaskFinalInputRegex! ***`, ); for (const rule of dbg.appliedRules || []) { - console.warn(`[ST-BME][prompt-diag] applied rule: ${JSON.stringify(rule)}`); + debugWarn(`[ST-BME][prompt-diag] applied rule: ${JSON.stringify(rule)}`); } } } diff --git a/panel-bridge.js b/panel-bridge.js index 4720149..78de4a1 100644 --- a/panel-bridge.js +++ b/panel-bridge.js @@ -1,3 +1,5 @@ +import { debugLog } from "./debug-logging.js"; + function resolvePanelTheme(settings) { return settings?.panelTheme || "crimson"; } @@ -83,7 +85,7 @@ export async function initializePanelBridgeController(runtime) { }); injectOptionsMenuEntry(runtime); - runtime.console.log("[ST-BME] 操控面板初始化完成"); + debugLog("[ST-BME] 操控面板初始化完成"); } catch (panelError) { runtime.console.error( "[ST-BME] 操控面板加载失败(核心功能不受影响):", diff --git a/panel.html b/panel.html index d1f0143..d57bf81 100644 --- a/panel.html +++ b/panel.html @@ -1079,6 +1079,32 @@ +