|
|
@@ -154,15 +154,28 @@ describe('loop-guard', () => {
|
|
|
});
|
|
|
|
|
|
describe('③ 内容重复检测', () => {
|
|
|
- it('🔴 连续「收到」「收到。」「收到!」→ 判为复读', () => {
|
|
|
+ /*
|
|
|
+ * 🔴 2026-11-13 行为变更:**重复检测不再独立触发**。
|
|
|
+ *
|
|
|
+ * 原规则「尾部连续 N 条内容相似就算回环」,不看连续数、也不看人类是否介入。
|
|
|
+ * 结果容器连续输出几条结构相近的工具行就误报,用户反馈
|
|
|
+ * 「我正常输出也会这样」。现在重复只在「连续数也达标」时才计入。
|
|
|
+ */
|
|
|
+ it('🔴 只有 3 条重复、未达连续数阈值 → 不触发(旧行为会误报)', () => {
|
|
|
const msgs = [
|
|
|
msg(A, '收到', 1),
|
|
|
msg(B, '收到。', 2),
|
|
|
msg(A, '收到!', 3),
|
|
|
];
|
|
|
const v = detectLoop(msgs, isHuman, { maxStreak: 99, maxPerMinute: 99, repeatWindow: 3 });
|
|
|
+ expect(v.loop).withContext('未达连续数阈值,不应判回环').toBeFalse();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('🔴 达到连续数阈值 + 内容重复 → 才判回环', () => {
|
|
|
+ const msgs = Array.from({ length: 6 }, (_, i) => msg(A, `收到${'。'.repeat(i)}`, i));
|
|
|
+ const v = detectLoop(msgs, isHuman, LOOP_GUARD_PRESETS.standard);
|
|
|
expect(v.loop).toBeTrue();
|
|
|
- expect(v.reason).toBe('repeat');
|
|
|
+ expect(v.reason).toBe('streak');
|
|
|
});
|
|
|
|
|
|
it('内容各不相同的三条 → 不触发', () => {
|
|
|
@@ -305,7 +318,7 @@ describe('loop-guard', () => {
|
|
|
expect(v.loop).withContext(v.detail ?? '').toBeFalse();
|
|
|
});
|
|
|
|
|
|
- it('agent 连续 3 条「收到」仍然触发(收紧口径没有放过真回环)', () => {
|
|
|
+ it('agent 连续 3 条「收到」未达阈值 → 不触发(2026-11-13 收紧口径)', () => {
|
|
|
const t0 = 7_400_000;
|
|
|
const msgs: LoopMessage[] = [
|
|
|
{ sender: HUMAN, body: '你好', ts: t0, fromMe: true },
|
|
|
@@ -314,8 +327,27 @@ describe('loop-guard', () => {
|
|
|
{ sender: A, body: '收到!', ts: t0 + 3000, fromMe: false },
|
|
|
];
|
|
|
const v = detectLoop(msgs, isHuman, LOOP_GUARD_PRESETS.standard, t0 + 3000);
|
|
|
+ /*
|
|
|
+ * standard 的 maxStreak=5,这里只有 3 条连续 → 不达阈值。
|
|
|
+ * 旧逻辑会因「内容重复」独立触发而误报。
|
|
|
+ */
|
|
|
+ expect(v.loop).toBeFalse();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('agent 连续 6 条相同内容 → 仍能识别(真回环不放过)', () => {
|
|
|
+ const t0 = 7_400_000;
|
|
|
+ const msgs: LoopMessage[] = [
|
|
|
+ { sender: HUMAN, body: '帮我改配置', ts: t0, fromMe: true },
|
|
|
+ ...Array.from({ length: 6 }, (_, i) => ({
|
|
|
+ sender: A,
|
|
|
+ body: '收到',
|
|
|
+ ts: t0 + 1000 * (i + 1),
|
|
|
+ fromMe: false as const,
|
|
|
+ })),
|
|
|
+ ];
|
|
|
+ const v = detectLoop(msgs, isHuman, LOOP_GUARD_PRESETS.standard, t0 + 7000);
|
|
|
expect(v.loop).toBeTrue();
|
|
|
- expect(v.reason).toBe('repeat');
|
|
|
+ expect(v.reason).toBe('streak');
|
|
|
});
|
|
|
|
|
|
it('保护期内(quiet=true)不触发,但诊断值照常返回', () => {
|