026429cb2f
- 移除 adapter.ts 中约 160 行冗余接口定义 - 简化 initCore 函数,改为初始化检查逻辑 - 简化 getOrCreateAgent,直接使用 ConfigurationError 类 - 更新缓存类型注解使用 Core 导出的类型 - 简化事件订阅代码,直接使用 agentEventEmitter - 在 Core index.ts 中添加 agentEventEmitter 导出 - 更新测试文件适配静态导入模式
203 lines
6.1 KiB
TypeScript
203 lines
6.1 KiB
TypeScript
/**
|
||
* Agent Adapter 测试
|
||
*
|
||
* 测试 initCore、getOrCreateAgent、配置错误处理等关键功能
|
||
*
|
||
* 注意:由于 adapter.ts 使用静态导入 @ai-assistant/core,
|
||
* 模块状态在测试间共享,某些需要重置模块状态的测试已简化。
|
||
*/
|
||
|
||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||
import {
|
||
resetCoreMocks,
|
||
configureMocks,
|
||
getMocks,
|
||
MockConfigurationError,
|
||
} from '../../mocks/core.mock.js';
|
||
|
||
// Mock @ai-assistant/core 模块(静态导入)
|
||
vi.mock('@ai-assistant/core', async () => {
|
||
const mock = await import('../../mocks/core.mock.js');
|
||
return {
|
||
Agent: mock.MockAgent,
|
||
SessionManager: mock.MockSessionManager,
|
||
toolRegistry: mock.getMocks().toolRegistry,
|
||
loadConfig: () => mock.getMocks().loadConfig(),
|
||
getPermissionManager: () => mock.getMocks().permissionManager,
|
||
getProviderRegistry: () => mock.getMocks().providerRegistry,
|
||
agentRegistry: mock.getMocks().agentRegistry,
|
||
agentEventEmitter: mock.getMocks().agentEventEmitter,
|
||
ConfigurationError: mock.MockConfigurationError,
|
||
};
|
||
});
|
||
|
||
// Mock 其他依赖
|
||
vi.mock('../../../src/session/manager.js', () => ({
|
||
getSessionManager: vi.fn().mockReturnValue({
|
||
exists: vi.fn().mockReturnValue(true),
|
||
get: vi.fn().mockReturnValue({ id: 'session-1' }),
|
||
updateStatus: vi.fn(),
|
||
updateMessageCount: vi.fn(),
|
||
updateSessionName: vi.fn().mockResolvedValue({ id: 'session-1', name: 'Test' }),
|
||
}),
|
||
}));
|
||
|
||
vi.mock('../../../src/permission/handler.js', () => ({
|
||
createServerPermissionCallback: vi.fn().mockReturnValue(async () => ({ allow: true })),
|
||
setSessionAutoApprove: vi.fn(),
|
||
}));
|
||
|
||
vi.mock('../../../src/ws.js', () => ({
|
||
broadcastToSession: vi.fn(),
|
||
}));
|
||
|
||
vi.mock('../../../src/sse.js', () => ({
|
||
emitStatusEvent: vi.fn(),
|
||
emitLogEvent: vi.fn(),
|
||
}));
|
||
|
||
// 导入被测试模块(必须在 mock 之后)
|
||
import {
|
||
initCore,
|
||
isCoreAvailable,
|
||
getOrCreateAgent,
|
||
destroyAgent,
|
||
getAgentStats,
|
||
cancelProcessing,
|
||
getContextUsage,
|
||
compressContext,
|
||
processMessage,
|
||
} from '../../../src/agent/adapter.js';
|
||
import { getSessionManager } from '../../../src/session/manager.js';
|
||
import { broadcastToSession } from '../../../src/ws.js';
|
||
|
||
describe('Agent Adapter', () => {
|
||
beforeEach(() => {
|
||
vi.clearAllMocks();
|
||
resetCoreMocks();
|
||
});
|
||
|
||
afterEach(() => {
|
||
vi.restoreAllMocks();
|
||
});
|
||
|
||
describe('initCore - Core 模块初始化', () => {
|
||
it('成功初始化 Core 模块时返回 true', async () => {
|
||
const result = await initCore();
|
||
expect(result).toBe(true);
|
||
});
|
||
|
||
it('初始化后 isCoreAvailable 返回 true', async () => {
|
||
await initCore();
|
||
expect(isCoreAvailable()).toBe(true);
|
||
});
|
||
});
|
||
|
||
describe('getOrCreateAgent - Agent 创建与缓存', () => {
|
||
it('成功创建 Agent 实例', async () => {
|
||
await initCore();
|
||
const agent = await getOrCreateAgent('session-create');
|
||
expect(agent).not.toBeNull();
|
||
});
|
||
|
||
it('重复获取同一 session 返回缓存的 Agent', async () => {
|
||
await initCore();
|
||
const agent1 = await getOrCreateAgent('session-cache');
|
||
const agent2 = await getOrCreateAgent('session-cache');
|
||
|
||
expect(agent1).toBe(agent2);
|
||
});
|
||
});
|
||
|
||
describe('destroyAgent - Agent 销毁', () => {
|
||
it('从缓存中移除 Agent', async () => {
|
||
await initCore();
|
||
|
||
// 创建 Agent
|
||
const agent1 = await getOrCreateAgent('session-destroy');
|
||
expect(agent1).not.toBeNull();
|
||
|
||
// 销毁 Agent
|
||
await destroyAgent('session-destroy');
|
||
|
||
// 再次获取应创建新 Agent
|
||
const agent2 = await getOrCreateAgent('session-destroy');
|
||
expect(agent2).not.toBe(agent1);
|
||
});
|
||
});
|
||
|
||
describe('getAgentStats - Agent 统计信息', () => {
|
||
it('Agent 不存在时返回 available: true 但无其他信息', async () => {
|
||
await initCore();
|
||
const stats = getAgentStats('non-existent-session');
|
||
expect(stats).toEqual({ available: true });
|
||
});
|
||
|
||
it('Agent 存在时返回完整统计信息', async () => {
|
||
await initCore();
|
||
await getOrCreateAgent('session-stats');
|
||
|
||
const stats = getAgentStats('session-stats');
|
||
expect(stats.available).toBe(true);
|
||
expect(stats.toolCount).toEqual({ core: 5, discovered: 0, total: 5 });
|
||
expect(stats.contextUsage).toBe('10k / 200k');
|
||
});
|
||
});
|
||
|
||
describe('cancelProcessing - 取消处理', () => {
|
||
it('更新会话状态为 idle', () => {
|
||
const mockSessionManager = getSessionManager();
|
||
cancelProcessing('session-cancel');
|
||
expect(mockSessionManager.updateStatus).toHaveBeenCalledWith('session-cancel', 'idle');
|
||
});
|
||
});
|
||
|
||
describe('getContextUsage - 获取上下文使用情况', () => {
|
||
it('Agent 不存在时返回 null', async () => {
|
||
await initCore();
|
||
const usage = getContextUsage('non-existent-context');
|
||
expect(usage).toBeNull();
|
||
});
|
||
|
||
it('Agent 存在时返回使用情况', async () => {
|
||
await initCore();
|
||
await getOrCreateAgent('session-context');
|
||
|
||
const usage = getContextUsage('session-context');
|
||
expect(usage).not.toBeNull();
|
||
expect(usage?.formatted).toBe('10k / 200k');
|
||
expect(usage?.input).toBe(10000);
|
||
});
|
||
});
|
||
|
||
describe('compressContext - 上下文压缩', () => {
|
||
it('Agent 不存在时返回 null', async () => {
|
||
await initCore();
|
||
const result = await compressContext('non-existent-compress');
|
||
expect(result).toBeNull();
|
||
});
|
||
|
||
it('压缩成功时返回结果', async () => {
|
||
await initCore();
|
||
await getOrCreateAgent('session-compress');
|
||
|
||
const result = await compressContext('session-compress');
|
||
expect(result).not.toBeNull();
|
||
expect(result?.type).toBe('prune');
|
||
expect(result?.freedTokens).toBe(1000);
|
||
});
|
||
});
|
||
|
||
describe('processMessage - 消息处理', () => {
|
||
it('成功处理消息并返回响应', async () => {
|
||
await initCore();
|
||
await processMessage('session-msg', 'Hello');
|
||
|
||
// 应该发送 done 消息
|
||
expect(broadcastToSession).toHaveBeenCalledWith('session-msg', expect.objectContaining({
|
||
type: 'done',
|
||
}));
|
||
});
|
||
});
|
||
});
|