fix: 修复召回拦截管线三个致命bug

1. recordRecallSentUserMessage 不再在 MESSAGE_SENT 阶段清空
   pendingRecallSendIntent/pendingHostGenerationInputSnapshot/transactions,
   避免 GENERATION_AFTER_COMMANDS 找不到用户输入而跳过召回

2. resolveGenerationRecallDeliveryMode 将 GENERATION_AFTER_COMMANDS
   从 deferred 改为 immediate,使召回完成后通过 setExtensionPrompt 即时注入

3. onGenerationAfterCommandsController 在 immediate 模式下完成
   runRecall 后直接返回(注入已在 applyRecallInjection 内完成),
   GENERATE_BEFORE_COMBINE_PROMPTS 保留 deferred rewrite 兜底
This commit is contained in:
Youzini-afk
2026-04-01 16:16:31 +08:00
parent 83f8f24f1c
commit ddc654eb1a
2 changed files with 18 additions and 19 deletions

View File

@@ -337,7 +337,11 @@ export async function onGenerationAfterCommandsController(
);
}
if (deliveryMode === "deferred") {
// immediate 模式下runRecall → applyRecallInjection 内部已通过
// setExtensionPrompt 完成了注入,此处直接返回召回结果。
// 后续 GENERATE_BEFORE_COMBINE_PROMPTS 阶段会通过
// applyFinalRecallInjectionForGeneration 做 deferred rewrite 兜底。
if (deliveryMode === "immediate") {
return recallResult;
}

View File

@@ -1152,20 +1152,11 @@ function recordRecallSentUserMessage(messageId, text, source = "message-sent") {
at: Date.now(),
});
if (pendingRecallSendIntent.hash && pendingRecallSendIntent.hash === hash) {
pendingRecallSendIntent = createRecallInputRecord();
}
if (
pendingHostGenerationInputSnapshot.hash &&
pendingHostGenerationInputSnapshot.hash === hash
) {
pendingHostGenerationInputSnapshot = createRecallInputRecord();
}
const activeChatId = getCurrentChatId();
if (activeChatId) {
clearGenerationRecallTransactionsForChat(activeChatId);
}
// 注意:不再在 MESSAGE_SENT 阶段清空 pendingRecallSendIntent /
// pendingHostGenerationInputSnapshot / transactions。
// 这些数据在 GENERATION_AFTER_COMMANDS 中被消费MESSAGE_SENT 先于
// GENERATION_AFTER_COMMANDS 触发,提前清空会导致召回拿不到用户输入。
// 真正的消费发生在 recall 执行后runRecallController 内部)。
return lastRecallSentUserMessage;
}
@@ -5477,10 +5468,14 @@ function resolveGenerationRecallDeliveryMode(
return "immediate";
}
return hookName === "GENERATION_AFTER_COMMANDS" ||
hookName === "GENERATE_BEFORE_COMBINE_PROMPTS"
? "deferred"
: "immediate";
// GENERATION_AFTER_COMMANDS: immediate —— await 完召回后直接通过
// setExtensionPrompt 注入记忆,与 shujuku 参考实现一致。
// GENERATE_BEFORE_COMBINE_PROMPTS: deferred —— 作为兜底,通过 promptData
// rewrite 补救注入。
if (hookName === "GENERATE_BEFORE_COMBINE_PROMPTS") {
return "deferred";
}
return "immediate";
}
function freezeGenerationRecallOptionsForTransaction(