basant307/AI_Governance_Project
045
1import { describe, expect, it, vi } from 'vitest';2import type { ChannelAgentBridge } from '@qwen-code/channel-base';3import { BridgeChannelMemoryIntentClassifier } from './memory-intent-classifier.js';4 5function bridgeWithResponse(response: string): ChannelAgentBridge {6 return {7 availableCommands: [],8 on: vi.fn(),9 off: vi.fn(),10 newSession: vi.fn().mockResolvedValue('classifier-session'),11 loadSession: vi.fn(),12 prompt: vi.fn().mockResolvedValue(response),13 cancelSession: vi.fn(),14 };15}16 17describe('BridgeChannelMemoryIntentClassifier', () => {18 it('uses an isolated bridge session and parses classifier JSON', async () => {19 const bridge = bridgeWithResponse(20 '{"intent":"remember","memory":"回复前说 1122","confidence":0.93}',21 );22 const classifier = new BridgeChannelMemoryIntentClassifier(bridge, '/tmp');23 24 await expect(25 classifier.classifyChannelMemoryIntent('你记一下以后回复前说 1122'),26 ).resolves.toEqual({27 intent: 'remember',28 memory: '回复前说 1122',29 confidence: 0.93,30 });31 expect(bridge.newSession).toHaveBeenCalledWith('/tmp');32 expect(bridge.prompt).toHaveBeenCalledWith(33 'classifier-session',34 expect.stringContaining('"你记一下以后回复前说 1122"'),35 {},36 );37 expect(bridge.cancelSession).toHaveBeenCalledWith('classifier-session');38 });39 40 it('logs cancelSession cleanup failures without dropping the result', async () => {41 const bridge = bridgeWithResponse(42 '{"intent":"remember","memory":"回复前说 1122","confidence":0.93}',43 );44 vi.mocked(bridge.cancelSession).mockRejectedValue(45 new Error('transport closed'),46 );47 const stderrSpy = vi48 .spyOn(process.stderr, 'write')49 .mockImplementation(() => true);50 const classifier = new BridgeChannelMemoryIntentClassifier(bridge, '/tmp');51 52 await expect(53 classifier.classifyChannelMemoryIntent('你记一下以后回复前说 1122'),54 ).resolves.toEqual({55 intent: 'remember',56 memory: '回复前说 1122',57 confidence: 0.93,58 });59 expect(stderrSpy).toHaveBeenCalledWith(60 '[classifier] cancelSession failed: transport closed\n',61 );62 stderrSpy.mockRestore();63 });64 65 it('extracts a JSON object from wrapped model output', async () => {66 const bridge = bridgeWithResponse(67 '```json\n{"intent":"list","confidence":0.86}\n```',68 );69 const classifier = new BridgeChannelMemoryIntentClassifier(bridge, '/tmp');70 71 await expect(72 classifier.classifyChannelMemoryIntent('你记住了什么'),73 ).resolves.toEqual({74 intent: 'list',75 confidence: 0.86,76 });77 });78 79 it('uses the latest bridge from a lazy provider', async () => {80 const firstBridge = bridgeWithResponse('{"intent":"none","confidence":1}');81 const secondBridge = bridgeWithResponse(82 '{"intent":"list","confidence":0.86}',83 );84 let bridge = firstBridge;85 const classifier = new BridgeChannelMemoryIntentClassifier(86 () => bridge,87 '/tmp',88 );89 90 bridge = secondBridge;91 92 await expect(93 classifier.classifyChannelMemoryIntent('你记住了什么'),94 ).resolves.toEqual({95 intent: 'list',96 confidence: 0.86,97 });98 expect(firstBridge.newSession).not.toHaveBeenCalled();99 expect(secondBridge.newSession).toHaveBeenCalledWith('/tmp');100 });101 102 it('rejects prose-wrapped JSON output with a diagnostic excerpt', async () => {103 const bridge = bridgeWithResponse(104 'Here is the classification: {"intent":"list","confidence":0.86}',105 );106 const classifier = new BridgeChannelMemoryIntentClassifier(bridge, '/tmp');107 108 await expect(109 classifier.classifyChannelMemoryIntent('你记住了什么'),110 ).rejects.toThrow(111 'Classifier response did not contain a JSON object. Got: Here is the classification:',112 );113 });114 115 it('normalizes invalid classifier fields to none', async () => {116 const bridge = bridgeWithResponse(117 '{"intent":"delete_one","confidence":"high"}',118 );119 const classifier = new BridgeChannelMemoryIntentClassifier(bridge, '/tmp');120 121 await expect(122 classifier.classifyChannelMemoryIntent('忘掉其中一条'),123 ).resolves.toEqual({124 intent: 'none',125 confidence: 0,126 });127 });128 129 it('normalizes out-of-range confidence to none', async () => {130 const bridge = bridgeWithResponse(131 '{"intent":"remember","memory":"x","confidence":999}',132 );133 const classifier = new BridgeChannelMemoryIntentClassifier(bridge, '/tmp');134 135 await expect(136 classifier.classifyChannelMemoryIntent('记住 x'),137 ).resolves.toEqual({138 intent: 'none',139 confidence: 0,140 });141 });142});143 