diff --git a/host/event-binding.js b/host/event-binding.js index 76c8545..c965abe 100644 --- a/host/event-binding.js +++ b/host/event-binding.js @@ -585,12 +585,14 @@ export async function onGenerationAfterCommandsController( const context = runtime.getContext(); const chat = context?.chat; + const generationContext = runtime.getGenerationContext?.() || null; const recallOptions = runtime.buildGenerationAfterCommandsRecallInput( - type, + generationContext?.type || type, { ...params, frozenInputSnapshot, + generationContext, }, chat, ); @@ -601,6 +603,26 @@ export async function onGenerationAfterCommandsController( return; } + if (globalThis.__stBmeDebugLoggingEnabled === true) { + const tail = Array.isArray(chat) + ? chat.slice(-3).map((m, i) => ({ + idx: chat.length - 3 + i, + is_user: Boolean(m?.is_user), + hasRecall: Boolean(m?.extra?.bme_recall), + mes: String(m?.mes || "").slice(0, 40), + })) + : null; + console.warn("[ST-BME][reroll-trace] AFTER_COMMANDS enter", { + type, + generationContextType: generationContext?.type || null, + generationContextKind: generationContext?.kind || null, + recallOptionsSource: recallOptions?.overrideSource || recallOptions?.source || null, + recallOptionsType: recallOptions?.generationType || null, + targetUserMessageIndex: recallOptions?.targetUserMessageIndex ?? null, + chatTail: tail, + }); + } + const recallContext = runtime.createGenerationRecallContext({ hookName: "GENERATION_AFTER_COMMANDS", generationType, diff --git a/retrieval/recall-controller.js b/retrieval/recall-controller.js index 43344b4..6f85716 100644 --- a/retrieval/recall-controller.js +++ b/retrieval/recall-controller.js @@ -1,6 +1,6 @@ // ST-BME: 召回输入解析与注入控制器(纯函数) -import { debugLog } from "../runtime/debug-logging.js"; +import { debugLog, debugWarn } from "../runtime/debug-logging.js"; import { isSystemMessageForExtraction } from "../maintenance/chat-history.js"; export function buildRecallRecentMessagesController( @@ -161,13 +161,29 @@ function resolveReusablePersistedRecallRecord(chat, recallInput, runtime) { } } - if (!Number.isFinite(targetUserMessageIndex)) return null; + if (!Number.isFinite(targetUserMessageIndex)) { + debugWarn("[ST-BME][reroll-trace] no target user floor resolved", { + generationType, + recallSource, + currentRecallInputText: currentRecallInputText.slice(0, 60), + chatLength: Array.isArray(chat) ? chat.length : null, + }); + return null; + } const targetMessage = Array.isArray(chat) ? chat[targetUserMessageIndex] : null; if (!targetMessage?.is_user) return null; const record = readPersistedRecallFromUserMessage(chat, targetUserMessageIndex); - if (!record?.injectionText) return null; + if (!record?.injectionText) { + debugWarn("[ST-BME][reroll-trace] target floor has no persisted recall record", { + generationType, + recallSource, + targetUserMessageIndex, + targetUserFloorText: String(targetMessage?.mes || "").slice(0, 60), + }); + return null; + } const currentUserFloorText = normalizeText(targetMessage?.mes || ""); const recordRecallInput = normalizeText(record?.recallInput || ""); @@ -228,9 +244,34 @@ function resolveReusablePersistedRecallRecord(chat, recallInput, runtime) { !canReuseUnboundTargetRecord && !canTrustUserFloorRecord ) { + debugWarn("[ST-BME][reroll-trace] reuse REJECTED", { + generationType, + recallSource, + targetUserMessageIndex, + isActiveInputSource, + isNoNewUserGeneration, + hasRecord: Boolean(record?.injectionText), + currentUserFloorText: currentUserFloorText.slice(0, 60), + currentRecallInputText: currentRecallInputText.slice(0, 60), + recordRecallInput: recordRecallInput.slice(0, 60), + boundUserFloorText: boundUserFloorText.slice(0, 60), + matchesPersistedRecord, + canReuseUnboundTargetRecord, + canTrustUserFloorRecord, + recordRecallInputMismatch, + }); return null; } + debugWarn("[ST-BME][reroll-trace] reuse ACCEPTED", { + generationType, + recallSource, + targetUserMessageIndex, + matchesPersistedRecord, + canReuseUnboundTargetRecord, + canTrustUserFloorRecord, + }); + return { record, targetUserMessageIndex,