deskpaw-memory/src/policy.js
2026-09-22 23:33:47 +08:00

34 lines
1.2 KiB
JavaScript

const SECRET_PATTERNS = [
/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/i,
/\b(?:password|passwd|api[_ -]?key|access[_ -]?token|refresh[_ -]?token|bearer|client[_ -]?secret)\b/i,
/(?:密码|口令|令牌|密钥|私钥|验证码)/,
];
export function boundedText(value, maxLength) {
if (typeof value !== "string") return "";
return value.trim().slice(0, maxLength);
}
export function safeMemoryText(value, maxLength = 8_000) {
const text = boundedText(value, maxLength);
if (SECRET_PATTERNS.some((pattern) => pattern.test(text))) return "[敏感内容未写入记忆]";
return text;
}
export function words(value) {
const lowered = boundedText(value, 16_000).toLowerCase();
const terms = new Set(lowered.match(/[a-z0-9_-]{2,}|[\u3400-\u9fff]{2}/g) ?? []);
const cjk = [...lowered.matchAll(/[\u3400-\u9fff]/g)].map((match) => match[0]).join("");
for (let index = 0; index + 1 < cjk.length; index++) terms.add(cjk.slice(index, index + 2));
return terms;
}
export function similarity(left, right) {
const a = words(left);
const b = words(right);
if (!a.size || !b.size) return 0;
let overlap = 0;
for (const term of a) if (b.has(term)) overlap++;
return overlap / Math.sqrt(a.size * b.size);
}