Files
ST-Bionic-Memory-Ecology/runtime/final-recall-injection.js
youzini f986bcc293 fix(recall): deterministic persisted reapply on reroll (Phase 1 inject-decoupling)
Reroll (swipe/regenerate/continue = no-new-user) now deterministically
reapplies the parent user floor's stored bme_recall block in
GENERATE_BEFORE_COMBINE_PROMPTS, bypassing the transaction gate and
runRecall entirely. AFTER_COMMANDS defers no-new-user work to
before-combine. Staleness guard recomputes when the user edited the
floor; settings gate honors plugin/recall disable. Fresh normal sends
are unaffected. Compute machinery retained as fallback.
2026-06-01 05:52:45 +00:00

985 lines
32 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export function createFinalRecallInjection(deps = {}) {
const normalizeRecallInputText = (value = "") =>
deps.normalizeRecallInputText?.(value) ?? String(value || "").trim();
const getContext = (...args) => deps.getContext?.(...args);
const getSettings = (...args) => deps.getSettings?.(...args);
const getLastRecallSentUserMessage = () =>
deps.getLastRecallSentUserMessage?.() || {};
const getLastInjectionContent = () =>
String(deps.getLastInjectionContent?.() || "");
const setLastInjectionContent = (value = "") => {
deps.setLastInjectionContent?.(String(value || ""));
};
const setRuntimeStatus = (value) => {
deps.setRuntimeStatus?.(value);
};
function persistRecallInjectionRecord({
recallInput = {},
result = {},
injectionText = "",
tokenEstimate = 0,
} = {}) {
const chat = getContext()?.chat;
if (!Array.isArray(chat)) return null;
const generationType =
String(recallInput?.generationType || "normal").trim() || "normal";
const lastRecallSentUserMessage = getLastRecallSentUserMessage();
let resolvedTargetIndex = deps.resolveRecallPersistenceTargetUserMessageIndex(
chat,
{
generationType,
explicitTargetUserMessageIndex: recallInput?.targetUserMessageIndex,
candidateTexts: [
recallInput?.userMessage,
recallInput?.overrideUserMessage,
lastRecallSentUserMessage?.text,
],
preferredRecord: lastRecallSentUserMessage,
},
);
if (!Number.isFinite(resolvedTargetIndex)) {
deps.debugPersistedRecallPersistence?.("目标 user 楼层解析失败", {
generationType,
explicitTargetUserMessageIndex: recallInput?.targetUserMessageIndex,
lastSentUserMessageId: lastRecallSentUserMessage?.messageId,
recallInputSource: String(recallInput?.source || ""),
});
return null;
}
if (!chat[resolvedTargetIndex]?.is_user) {
deps.debugPersistedRecallPersistence?.("目标楼层不是 user 消息,跳过持久化", {
targetUserMessageIndex: resolvedTargetIndex,
messageKeys: Object.keys(chat[resolvedTargetIndex] || {}),
});
return null;
}
const targetUserFloorText = normalizeRecallInputText(
chat[resolvedTargetIndex]?.mes || "",
);
const boundUserFloorText = normalizeRecallInputText(
recallInput?.boundUserFloorText || targetUserFloorText,
);
const record = deps.buildPersistedRecallRecord(
{
injectionText,
selectedNodeIds: result?.selectedNodeIds || [],
recallInput: String(recallInput?.userMessage || ""),
recallSource: String(recallInput?.source || ""),
hookName: String(recallInput?.hookName || ""),
tokenEstimate,
manuallyEdited: false,
authoritativeInputUsed: Boolean(recallInput?.authoritativeInputUsed),
boundUserFloorText,
},
deps.readPersistedRecallFromUserMessage(chat, resolvedTargetIndex),
);
if (!String(record?.injectionText || "").trim()) {
deps.debugPersistedRecallPersistence?.("无有效 injectionText跳过持久化", {
targetUserMessageIndex: resolvedTargetIndex,
selectedNodeCount: Array.isArray(result?.selectedNodeIds)
? result.selectedNodeIds.length
: 0,
});
return null;
}
if (!deps.writePersistedRecallToUserMessage(chat, resolvedTargetIndex, record)) {
deps.debugPersistedRecallPersistence?.("写入 user 楼层失败", {
targetUserMessageIndex: resolvedTargetIndex,
});
return null;
}
deps.triggerChatMetadataSave(getContext(), { immediate: false });
deps.schedulePersistedRecallMessageUiRefresh();
deps.debugPersistedRecallPersistence?.(
"召回记录已写入 user 楼层",
{
targetUserMessageIndex: resolvedTargetIndex,
injectionTextLength: String(record?.injectionText || "").length,
selectedNodeCount: Array.isArray(record?.selectedNodeIds)
? record.selectedNodeIds.length
: 0,
},
`persist-success:${resolvedTargetIndex}`,
);
return {
index: resolvedTargetIndex,
record,
};
}
function ensurePersistedRecallRecordForGeneration({
generationType = "normal",
recallResult = null,
transaction = null,
recallOptions = null,
hookName = "",
} = {}) {
const injectionText = String(recallResult?.injectionText || "").trim();
if (
recallResult?.status !== "completed" ||
!recallResult?.didRecall ||
!injectionText
) {
return {
persisted: false,
reason: "no-fresh-recall",
targetUserMessageIndex: null,
record: null,
};
}
const chat = getContext()?.chat;
if (!Array.isArray(chat) || chat.length === 0) {
return {
persisted: false,
reason: "missing-chat",
targetUserMessageIndex: null,
record: null,
};
}
const frozenRecallOptions =
transaction?.frozenRecallOptions &&
typeof transaction.frozenRecallOptions === "object"
? transaction.frozenRecallOptions
: null;
const lastRecallSentUserMessage = getLastRecallSentUserMessage();
const targetUserMessageIndex = deps.resolveRecallPersistenceTargetUserMessageIndex(
chat,
{
generationType,
explicitTargetUserMessageIndex:
frozenRecallOptions?.targetUserMessageIndex ??
recallOptions?.targetUserMessageIndex ??
recallOptions?.explicitTargetUserMessageIndex ??
null,
candidateTexts: [
frozenRecallOptions?.overrideUserMessage,
frozenRecallOptions?.userMessage,
recallOptions?.overrideUserMessage,
recallOptions?.userMessage,
recallResult?.recallInput,
recallResult?.userMessage,
...(Array.isArray(recallResult?.sourceCandidates)
? recallResult.sourceCandidates.map((candidate) => candidate?.text)
: []),
lastRecallSentUserMessage?.text,
],
preferredRecord: lastRecallSentUserMessage,
},
);
if (
!Number.isFinite(targetUserMessageIndex) ||
!chat[targetUserMessageIndex]?.is_user
) {
return {
persisted: false,
reason: "target-unresolved",
targetUserMessageIndex: Number.isFinite(targetUserMessageIndex)
? targetUserMessageIndex
: null,
record: null,
};
}
const selectedNodeIds = deps.normalizeRecallNodeIdList(
recallResult?.selectedNodeIds || [],
);
const existingRecord = deps.readPersistedRecallFromUserMessage(
chat,
targetUserMessageIndex,
);
const nextAuthoritativeInputUsed = Boolean(
recallResult?.authoritativeInputUsed ??
frozenRecallOptions?.authoritativeInputUsed ??
recallOptions?.authoritativeInputUsed,
);
const targetUserFloorText = normalizeRecallInputText(
chat[targetUserMessageIndex]?.mes || "",
);
const nextBoundUserFloorText = normalizeRecallInputText(
recallResult?.boundUserFloorText ||
frozenRecallOptions?.boundUserFloorText ||
recallOptions?.boundUserFloorText ||
targetUserFloorText ||
"",
);
const existingBoundUserFloorText = normalizeRecallInputText(
existingRecord?.boundUserFloorText || "",
);
const existingMetadataUpToDate =
Boolean(existingRecord?.authoritativeInputUsed) === nextAuthoritativeInputUsed &&
(!nextBoundUserFloorText ||
existingBoundUserFloorText === nextBoundUserFloorText);
if (
existingRecord &&
String(existingRecord.injectionText || "").trim() === injectionText &&
deps.areRecallNodeIdListsEqual(existingRecord.selectedNodeIds, selectedNodeIds) &&
String(existingRecord.recallInput || "").trim() &&
existingMetadataUpToDate
) {
return {
persisted: false,
reason: "already-up-to-date",
targetUserMessageIndex,
record: existingRecord,
};
}
const nextRecord = deps.buildPersistedRecallRecord(
{
injectionText,
selectedNodeIds,
recallInput: String(
recallResult?.recallInput ||
recallResult?.userMessage ||
frozenRecallOptions?.overrideUserMessage ||
recallOptions?.overrideUserMessage ||
recallOptions?.userMessage ||
"",
),
recallSource: String(
recallResult?.source ||
frozenRecallOptions?.lockedSource ||
frozenRecallOptions?.overrideSource ||
recallOptions?.overrideSource ||
"",
),
hookName: String(
hookName ||
recallResult?.hookName ||
frozenRecallOptions?.hookName ||
recallOptions?.hookName ||
"",
),
tokenEstimate: deps.estimateTokens(injectionText),
manuallyEdited: false,
authoritativeInputUsed: nextAuthoritativeInputUsed,
boundUserFloorText: nextBoundUserFloorText,
},
existingRecord,
);
if (!deps.writePersistedRecallToUserMessage(chat, targetUserMessageIndex, nextRecord)) {
return {
persisted: false,
reason: "write-failed",
targetUserMessageIndex,
record: null,
};
}
deps.triggerChatMetadataSave(getContext(), { immediate: false });
deps.schedulePersistedRecallMessageUiRefresh();
deps.debugPersistedRecallPersistence?.(
"最终阶段已补写召回记录",
{
targetUserMessageIndex,
hookName:
String(
hookName ||
recallResult?.hookName ||
frozenRecallOptions?.hookName ||
recallOptions?.hookName ||
"",
) || "",
injectionTextLength: injectionText.length,
selectedNodeCount: selectedNodeIds.length,
},
`finalize-persist:${targetUserMessageIndex}`,
);
return {
persisted: true,
reason: "backfilled",
targetUserMessageIndex,
record: nextRecord,
};
}
function rewriteRecallPayloadWithInjection(
promptData = null,
injectionText = "",
) {
const normalizedInjectionText = normalizeRecallInputText(injectionText);
if (!normalizedInjectionText) {
return {
applied: false,
path: "",
field: "",
reason: "empty-injection-text",
};
}
const finalMesSend = Array.isArray(promptData?.finalMesSend)
? promptData.finalMesSend
: null;
if (Array.isArray(finalMesSend) && finalMesSend.length > 0) {
for (let index = finalMesSend.length - 1; index >= 0; index--) {
const entry = finalMesSend[index];
if (!entry || typeof entry !== "object") continue;
if (entry.injected === true) continue;
const messageText = normalizeRecallInputText(
entry.message || entry.mes || entry.content || "",
);
if (!messageText) continue;
entry.extensionPrompts = Array.isArray(entry.extensionPrompts)
? entry.extensionPrompts
: [];
const alreadyPresent = entry.extensionPrompts.some((chunk) =>
String(chunk || "").includes(normalizedInjectionText),
);
if (!alreadyPresent) {
entry.extensionPrompts.push(`${normalizedInjectionText}\n`);
}
return {
applied: true,
path: "finalMesSend",
field: `finalMesSend[${index}].extensionPrompts`,
reason: alreadyPresent
? "rewrite-already-present"
: "finalMesSend-extensionPrompt-appended",
targetIndex: index,
};
}
return {
applied: false,
path: "finalMesSend",
field: "",
reason: "no-rewritable-finalMesSend-entry",
};
}
if (
typeof promptData?.combinedPrompt === "string" &&
promptData.combinedPrompt.trim()
) {
if (!promptData.combinedPrompt.includes(normalizedInjectionText)) {
promptData.combinedPrompt = `${normalizedInjectionText}\n\n${promptData.combinedPrompt}`;
}
return {
applied: true,
path: "combinedPrompt",
field: "combinedPrompt",
reason: "combinedPrompt-prefixed",
};
}
if (typeof promptData?.prompt === "string" && promptData.prompt.trim()) {
if (!promptData.prompt.includes(normalizedInjectionText)) {
promptData.prompt = `${normalizedInjectionText}\n\n${promptData.prompt}`;
}
return {
applied: true,
path: "prompt",
field: "prompt",
reason: "prompt-prefixed",
};
}
return {
applied: false,
path: "",
field: "",
reason: "prompt-payload-unavailable",
};
}
function rewriteRecallPayloadWithAuthoritativeUserInput(
promptData = null,
authoritativeText = "",
boundUserFloorText = "",
) {
const normalizedAuthoritativeText = normalizeRecallInputText(authoritativeText);
const normalizedBoundUserFloorText = normalizeRecallInputText(boundUserFloorText);
if (!normalizedAuthoritativeText) {
return {
applied: false,
changed: false,
path: "",
field: "",
reason: "empty-authoritative-text",
};
}
const finalMesSend = Array.isArray(promptData?.finalMesSend)
? promptData.finalMesSend
: null;
if (!Array.isArray(finalMesSend) || finalMesSend.length <= 0) {
return {
applied: false,
changed: false,
path: "",
field: "",
reason: "finalMesSend-unavailable",
};
}
let fallbackIndex = -1;
let matchedIndex = -1;
for (let index = finalMesSend.length - 1; index >= 0; index--) {
const entry = finalMesSend[index];
if (!entry || typeof entry !== "object") continue;
if (entry.injected === true) continue;
const messageText = normalizeRecallInputText(
entry.message || entry.mes || entry.content || "",
);
if (!messageText) continue;
if (fallbackIndex < 0) {
fallbackIndex = index;
}
if (
messageText === normalizedAuthoritativeText ||
(normalizedBoundUserFloorText &&
messageText === normalizedBoundUserFloorText)
) {
matchedIndex = index;
break;
}
}
const targetIndex =
matchedIndex >= 0
? matchedIndex
: normalizedBoundUserFloorText
? -1
: fallbackIndex;
if (targetIndex < 0) {
return {
applied: false,
changed: false,
path: "finalMesSend",
field: "",
reason: normalizedBoundUserFloorText
? "bound-user-floor-text-not-found"
: "no-rewritable-finalMesSend-entry",
};
}
const entry = finalMesSend[targetIndex];
const fieldName = Object.prototype.hasOwnProperty.call(entry, "message")
? "message"
: Object.prototype.hasOwnProperty.call(entry, "mes")
? "mes"
: Object.prototype.hasOwnProperty.call(entry, "content")
? "content"
: "message";
const previousText = normalizeRecallInputText(
entry?.[fieldName] || entry?.message || entry?.mes || entry?.content || "",
);
const changed = previousText !== normalizedAuthoritativeText;
if (changed) {
entry[fieldName] = normalizedAuthoritativeText;
}
return {
applied: true,
changed,
path: "finalMesSend",
field: `finalMesSend[${targetIndex}].${fieldName}`,
reason: changed
? "finalMesSend-authoritative-user-rewritten"
: "authoritative-user-already-matched",
targetIndex,
};
}
function reapplyPersistedRecallBlock({
generationType = "normal",
generationContext = null,
promptData = null,
hookName = "",
} = {}) {
const settings = getSettings() || {};
if (!settings.enabled || !settings.recallEnabled) {
return { applied: false, reason: "disabled" };
}
const chat = getContext()?.chat;
if (!Array.isArray(chat)) {
return { applied: false, reason: "no-chat" };
}
const targetUserMessageIndex = deps.resolveGenerationTargetUserMessageIndex(
chat,
{
generationType,
generationContext,
},
);
if (!Number.isFinite(targetUserMessageIndex)) {
return { applied: false, reason: "no-parent-floor" };
}
const targetMessage = chat[targetUserMessageIndex];
if (!targetMessage?.is_user) {
return { applied: false, reason: "parent-not-user" };
}
const record = deps.readPersistedRecallFromUserMessage(
chat,
targetUserMessageIndex,
);
if (!record?.injectionText) {
return { applied: false, reason: "no-record" };
}
const currentFloorText = normalizeRecallInputText(targetMessage.mes || "");
const bound = normalizeRecallInputText(record.boundUserFloorText || "");
const recInput = normalizeRecallInputText(record.recallInput || "");
if (bound) {
if (bound !== currentFloorText) {
return { applied: false, reason: "bound-mismatch" };
}
} else if (recInput && recInput !== currentFloorText) {
return { applied: false, reason: "legacy-recall-input-mismatch" };
}
const injectionText = String(record.injectionText || "").trim();
let transport = {
applied: false,
source: "none",
mode: "none",
};
if (promptData) {
const rewrite = rewriteRecallPayloadWithInjection(promptData, injectionText);
if (rewrite.applied) {
deps.clearLiveRecallInjectionPromptForRewrite?.();
transport = rewrite;
} else {
transport =
deps.applyModuleInjectionPrompt(injectionText, getSettings()) || transport;
}
} else {
transport =
deps.applyModuleInjectionPrompt(injectionText, getSettings()) || transport;
}
setLastInjectionContent(injectionText);
deps.bumpPersistedRecallGenerationCount(chat, targetUserMessageIndex);
deps.triggerChatMetadataSave(getContext(), { immediate: false });
deps.recordInjectionSnapshot("recall", {
taskType: "recall",
source: "persisted-user-floor",
sourceLabel: "复用用户楼层召回",
reason: "deterministic-reapply",
hookName: String(hookName || "").trim(),
selectedNodeIds: record.selectedNodeIds || [],
injectionText,
applicationMode: promptData ? "rewrite" : "persisted-injection",
transport,
sourceKind: "persisted",
targetUserMessageIndex,
boundUserFloorText: bound,
});
setRuntimeStatus(deps.createUiStatus(
"召回已复用",
"本轮 reroll 复用了用户楼层已存召回",
"success",
));
deps.refreshPanelLiveState();
deps.schedulePersistedRecallMessageUiRefresh();
return {
applied: true,
source: "persisted",
injectionText,
targetUserMessageIndex,
transport,
reason: "deterministic-reapply",
};
}
function applyFinalRecallInjectionForGeneration({
generationType = "normal",
freshRecallResult = null,
transaction = null,
promptData = null,
hookName = "",
} = {}) {
const existingFinalResolution =
deps.readGenerationRecallTransactionFinalResolution(transaction);
if (existingFinalResolution) {
if (
promptData &&
transaction?.frozenRecallOptions?.authoritativeInputUsed === true
) {
const recallResult =
freshRecallResult ||
deps.getGenerationRecallTransactionResult(transaction) ||
null;
const inputRewrite = rewriteRecallPayloadWithAuthoritativeUserInput(
promptData,
transaction?.frozenRecallOptions?.overrideUserMessage || "",
transaction?.frozenRecallOptions?.boundUserFloorText || "",
);
const rewrite = rewriteRecallPayloadWithInjection(
promptData,
existingFinalResolution.usedText || recallResult?.injectionText || "",
);
const nextFinalResolution = {
...existingFinalResolution,
deliveryMode: "deferred",
applicationMode:
rewrite.applied || inputRewrite.applied
? "rewrite"
: existingFinalResolution.applicationMode,
rewrite,
inputRewrite,
};
deps.recordInjectionSnapshot("recall", {
taskType: "recall",
source:
String(
recallResult?.source ||
transaction?.frozenRecallOptions?.lockedSource ||
transaction?.frozenRecallOptions?.overrideSource ||
"",
).trim() || "unknown",
sourceLabel:
String(
recallResult?.sourceLabel ||
transaction?.frozenRecallOptions?.lockedSourceLabel ||
transaction?.frozenRecallOptions?.overrideSourceLabel ||
"",
).trim() || "未知",
reason:
String(
recallResult?.reason ||
transaction?.frozenRecallOptions?.lockedReason ||
transaction?.frozenRecallOptions?.overrideReason ||
"",
).trim() || "final-application-reused",
sourceCandidates: Array.isArray(recallResult?.sourceCandidates)
? recallResult.sourceCandidates.map((candidate) => ({ ...candidate }))
: Array.isArray(transaction?.frozenRecallOptions?.sourceCandidates)
? transaction.frozenRecallOptions.sourceCandidates.map((candidate) => ({
...candidate,
}))
: [],
hookName: String(hookName || recallResult?.hookName || "").trim(),
selectedNodeIds: recallResult?.selectedNodeIds || [],
retrievalMeta: recallResult?.retrievalMeta || {},
llmMeta: recallResult?.llmMeta || {},
stats: recallResult?.stats || {},
injectionText: nextFinalResolution.usedText || "",
deliveryMode: nextFinalResolution.deliveryMode || "",
applicationMode: nextFinalResolution.applicationMode || "none",
transport: nextFinalResolution.transport || {
applied: false,
source: "none",
mode: "none",
},
rewrite: nextFinalResolution.rewrite || {
applied: false,
path: "",
field: "",
reason: "final-resolution-reused",
},
inputRewrite,
targetUserMessageIndex: nextFinalResolution.targetUserMessageIndex,
sourceKind: nextFinalResolution.source || "none",
authoritativeInputUsed: true,
boundUserFloorText: String(
transaction?.frozenRecallOptions?.boundUserFloorText || "",
),
});
deps.storeGenerationRecallTransactionFinalResolution(
transaction,
nextFinalResolution,
);
deps.refreshPanelLiveState();
deps.schedulePersistedRecallMessageUiRefresh();
return nextFinalResolution;
}
return existingFinalResolution;
}
const recallResult =
freshRecallResult ||
deps.getGenerationRecallTransactionResult(transaction) ||
null;
const hookResolvedDeliveryMode =
String(
deps.resolveGenerationRecallDeliveryMode(
hookName,
generationType,
transaction?.frozenRecallOptions || {},
),
).trim() || "immediate";
const deliveryMode =
String(
promptData && hookName === "GENERATE_BEFORE_COMBINE_PROMPTS"
? hookResolvedDeliveryMode
: recallResult?.deliveryMode ||
transaction?.lastDeliveryMode ||
hookResolvedDeliveryMode,
).trim() || "immediate";
const chat = getContext()?.chat;
let transport = {
applied: false,
source: "none",
mode: "none",
};
let targetUserMessageIndex = null;
let resolved = {
source: "none",
injectionText: "",
record: null,
};
const authoritativeInputRewrite =
deliveryMode === "deferred" &&
transaction?.frozenRecallOptions?.authoritativeInputUsed === true
? rewriteRecallPayloadWithAuthoritativeUserInput(
promptData,
transaction?.frozenRecallOptions?.overrideUserMessage || "",
transaction?.frozenRecallOptions?.boundUserFloorText || "",
)
: {
applied: false,
changed: false,
path: "",
field: "",
reason:
deliveryMode === "deferred"
? "authoritative-input-unused"
: "non-deferred-delivery",
};
const rewrite = {
applied: false,
path: "",
field: "",
reason: "no-recall-source",
};
let applicationMode = "none";
if (!Array.isArray(chat)) {
transport = deps.applyModuleInjectionPrompt("", getSettings()) || transport;
const emptyResolution = {
source: "none",
isFallback: false,
targetUserMessageIndex: null,
usedText: "",
deliveryMode,
applicationMode: "none",
rewrite,
transport,
};
deps.storeGenerationRecallTransactionFinalResolution(
transaction,
emptyResolution,
);
return emptyResolution;
}
const ensuredPersistence = ensurePersistedRecallRecordForGeneration({
generationType,
recallResult,
transaction,
recallOptions: transaction?.frozenRecallOptions || null,
hookName,
});
const lastRecallSentUserMessage = getLastRecallSentUserMessage();
targetUserMessageIndex = deps.resolveRecallPersistenceTargetUserMessageIndex(chat, {
generationType,
explicitTargetUserMessageIndex:
transaction?.frozenRecallOptions?.targetUserMessageIndex,
candidateTexts: [
transaction?.frozenRecallOptions?.overrideUserMessage,
recallResult?.recallInput,
recallResult?.userMessage,
recallResult?.sourceCandidates?.[0]?.text,
lastRecallSentUserMessage?.text,
],
preferredRecord: lastRecallSentUserMessage,
});
if (Number.isFinite(ensuredPersistence?.targetUserMessageIndex)) {
targetUserMessageIndex = ensuredPersistence.targetUserMessageIndex;
}
const persistedRecord = Number.isFinite(targetUserMessageIndex)
? deps.readPersistedRecallFromUserMessage(chat, targetUserMessageIndex)
: null;
resolved = deps.resolveFinalRecallInjectionSource({
freshRecallResult: recallResult,
persistedRecord,
});
if (resolved.source === "fresh" && deliveryMode === "deferred") {
const rewriteResult = rewriteRecallPayloadWithInjection(
promptData,
resolved.injectionText || "",
);
Object.assign(rewrite, rewriteResult);
setLastInjectionContent(resolved.injectionText || "");
if (rewriteResult.applied) {
applicationMode = "rewrite";
transport = deps.clearLiveRecallInjectionPromptForRewrite() || {
applied: false,
source: "rewrite-cleared",
mode: "rewrite-cleared",
};
setRuntimeStatus(deps.createUiStatus(
"召回已改写",
`本轮发送载荷已 rewrite · ${rewriteResult.path || rewriteResult.field || "payload"}`,
"success",
));
} else {
applicationMode = "fallback-injection";
transport =
deps.applyModuleInjectionPrompt(
resolved.injectionText || "",
getSettings(),
) || transport;
setRuntimeStatus(deps.createUiStatus(
"召回回退",
`rewrite 未命中,已回退注入 · ${rewriteResult.reason}`,
"warning",
));
}
} else if (resolved.source === "fresh") {
applicationMode = "injection";
transport =
deps.applyModuleInjectionPrompt(resolved.injectionText || "", getSettings()) ||
transport;
setLastInjectionContent(resolved.injectionText || "");
rewrite.reason = "immediate-injection";
setRuntimeStatus(deps.createUiStatus(
"召回已注入",
"本轮已使用最新召回结果",
"success",
));
} else if (resolved.source === "persisted") {
applicationMode = "persisted-injection";
transport =
deps.applyModuleInjectionPrompt(resolved.injectionText || "", getSettings()) ||
transport;
setLastInjectionContent(resolved.injectionText || "");
rewrite.reason = "persisted-record-fallback";
setRuntimeStatus(deps.createUiStatus(
"召回回退",
"已使用消息楼层持久化注入",
"info",
));
} else {
transport = deps.applyModuleInjectionPrompt("", getSettings()) || transport;
setLastInjectionContent("");
setRuntimeStatus(deps.createUiStatus("待命", "当前无有效注入内容", "idle"));
}
if (
resolved.source === "persisted" &&
Number.isFinite(targetUserMessageIndex)
) {
deps.bumpPersistedRecallGenerationCount(chat, targetUserMessageIndex);
deps.triggerChatMetadataSave(getContext(), { immediate: false });
}
deps.recordInjectionSnapshot("recall", {
taskType: "recall",
source:
String(
recallResult?.source ||
transaction?.frozenRecallOptions?.lockedSource ||
transaction?.frozenRecallOptions?.overrideSource ||
"",
).trim() || "unknown",
sourceLabel:
String(
recallResult?.sourceLabel ||
transaction?.frozenRecallOptions?.lockedSourceLabel ||
transaction?.frozenRecallOptions?.overrideSourceLabel ||
"",
).trim() || "未知",
reason:
String(
recallResult?.reason ||
transaction?.frozenRecallOptions?.lockedReason ||
transaction?.frozenRecallOptions?.overrideReason ||
"",
).trim() || "final-application",
sourceCandidates: Array.isArray(recallResult?.sourceCandidates)
? recallResult.sourceCandidates.map((candidate) => ({ ...candidate }))
: Array.isArray(transaction?.frozenRecallOptions?.sourceCandidates)
? transaction.frozenRecallOptions.sourceCandidates.map((candidate) => ({
...candidate,
}))
: [],
hookName: String(hookName || recallResult?.hookName || "").trim(),
selectedNodeIds: recallResult?.selectedNodeIds || [],
retrievalMeta: recallResult?.retrievalMeta || {},
llmMeta: recallResult?.llmMeta || {},
stats: recallResult?.stats || {},
injectionText: resolved.injectionText || "",
deliveryMode,
applicationMode,
transport,
rewrite,
inputRewrite: authoritativeInputRewrite,
targetUserMessageIndex,
sourceKind: resolved.source,
authoritativeInputUsed: Boolean(
recallResult?.authoritativeInputUsed ??
transaction?.frozenRecallOptions?.authoritativeInputUsed,
),
boundUserFloorText: String(
recallResult?.boundUserFloorText ||
transaction?.frozenRecallOptions?.boundUserFloorText ||
"",
),
});
deps.refreshPanelLiveState();
deps.schedulePersistedRecallMessageUiRefresh();
const finalResolution = {
source: resolved.source,
isFallback:
resolved.source === "persisted" ||
applicationMode === "fallback-injection",
targetUserMessageIndex,
usedText: resolved.injectionText || "",
deliveryMode,
applicationMode,
rewrite,
transport,
inputRewrite: authoritativeInputRewrite,
authoritativeInputUsed: Boolean(
recallResult?.authoritativeInputUsed ??
transaction?.frozenRecallOptions?.authoritativeInputUsed,
),
boundUserFloorText: String(
recallResult?.boundUserFloorText ||
transaction?.frozenRecallOptions?.boundUserFloorText ||
"",
),
};
deps.storeGenerationRecallTransactionFinalResolution(transaction, finalResolution);
return finalResolution;
}
return {
persistRecallInjectionRecord,
ensurePersistedRecallRecordForGeneration,
rewriteRecallPayloadWithInjection,
rewriteRecallPayloadWithAuthoritativeUserInput,
reapplyPersistedRecallBlock,
applyFinalRecallInjectionForGeneration,
getLastInjectionContent,
};
}