Files
openclaw/extensions/active-memory/escalation.ts
Qiong a566ac23a0 fix(active-memory): detect Chinese recall intent in escalate mode (#117338) (#117419)
* fix(active-memory): detect Chinese recall intent in escalate mode (#117338)

* fix(active-memory): recognize formatted multilingual recall intent

---------

Co-authored-by: Peter Steinberger <steipete@macos.shared>
2026-08-01 09:21:45 -07:00

73 lines
4.5 KiB
TypeScript
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.
import type { ActiveMemoryMode } from "./types.js";
const RECALL_INTENT_PATTERNS = [
/\b(?:previously|earlier|last time|used to)\b/iu,
/\b(?:do|can|could|would)\s+you\s+(?:remember|recall)\b/iu,
/\b(?:remember|recall)\s+(?:when|what|which|who|where|why|how)\b/iu,
/\b(?:we|you|i)\s+(?:discussed|decided|agreed|said|talked about|chose)\b/iu,
/\b(?:previous|earlier|past)\s+(?:decision|conversation|chat|discussion)\b/iu,
/\b(?:yesterday|the other day|last (?:week|month|year)|(?:\d+|one|two|three|four|five|six|seven|eight|nine|ten)\s+(?:days?|weeks?|months?|years?)\s+ago)\b/iu,
/\bwhat did (?:we|you|i)\b/iu,
/\bwhat (?:do|did) i usually\b/iu,
/\b(?:what|which|when|where|why|how)\s+(?:did|have|had)\s+(?:we|you|i)\s+(?:decide|choose|discuss|agree|say|mention|talk|use|do)\b/iu,
/\b(?:did|have|had)\s+(?:we|you|i)\s+(?:decide|choose|discuss|agree|say|mention|talk)\b/iu,
/\b(?:conversation|chat|discussion)s?\s+(?:from|in|during)\s+(?:january|february|march|april|may|june|july|august|september|october|november|december|\d{4})\b/iu,
/\b(?:summarize|review|find|search)\s+(?:my|our|the)?\s*(?:past|previous|earlier)?\s*(?:conversation|chat|discussion)s?\b/iu,
/(?:¿?qué\s+(?:decidimos|hablamos)|\b(?:recuerdas|recordar|anteriormente|ayer)\b|(?<![\p{L}\p{N}_])última vez(?![\p{L}\p{N}_]))/iu,
/\bremind\s+(?:me|us)\s+(?:what|which|who|where|why|how)\b/iu,
];
// Future reminders stay quiet unless a completed past discussion or decision
// shows that its future topic is itself the subject of retrospective recall.
const LOCALIZED_RECALL_INTENT_PATTERNS = [
{
intent:
/[][]|[](?=.{0,24}(?:[]|[?]))|(?:[]|(?:|)|[])[\s,:]{0,3}(?:(?:||||)?(?:(?:|[]|[]|[][]|)(?:[](?=[?\s]|$)|[])|[](?:[](?=[?\s]|$)|)|[][](?:[](?=[?\s]|$)|))|(?:)?(?:|[][])[][]|[])/u,
future:
/(?:||||)|(?:|||)|[](?:|)|(?:|||(?:|)?||||)|(?:|)|(?:|)|||||(?:||)|(?:|)|(?:||)/u,
retrospective:
/(?:(?:|||||(?:|)?)|[]|(?:|))[\s,:]{0,3}(?:||||)?[\s,:]{0,3}(?:|[]|[]|[][]||[]|[][])/u,
},
{
intent:
/(?:||(?:|))(?!|||)|(?:|||)(?!\s*).{0,24}(?:(?:|(?!)|)||||)(?![])/u,
future:
/(?:|)|(?:|)||(?:||)|(?:|)|||||||||/u,
retrospective:
/(?:||||||)(?!\s*).{0,24}(?:(?:|(?!)|)||||)(?![])/u,
},
{
intent:
/(?:|(?:)?||+)?(?![\p{L}\p{N}_])|(?:\s*||).{0,24}(?:|(?:||)|||)/u,
future: /(?:|)|\s*(?:||)|||||||||/u,
retrospective:
/(?:\s*(?:||)|||).{0,24}(?:|(?:||)|||)/u,
},
];
export function hasRecallIntent(message: string): boolean {
const normalized = message.replace(/\s+/g, " ").trim();
return (
normalized.length > 0 &&
(RECALL_INTENT_PATTERNS.some((pattern) => pattern.test(normalized)) ||
LOCALIZED_RECALL_INTENT_PATTERNS.some(
({ intent, future, retrospective }) =>
intent.test(normalized) && (!future.test(normalized) || retrospective.test(normalized)),
))
);
}
export function shouldEscalateRecall(params: {
mode: ActiveMemoryMode;
message: string;
hasStrongLaneOneHit: boolean;
}): boolean {
if (params.mode === "off") {
return false;
}
if (params.mode === "always") {
return true;
}
return !params.hasStrongLaneOneHit && hasRecallIntent(params.message);
}