TalkingBot/chat-engine/tests/stage1.test.js

92 lines
3.7 KiB
JavaScript

const { loadConfig } = require('../src/config');
const { resolveMode } = require('../src/resolveMode');
const { MemorySessionStore, MysqlSessionStore } = require('../src/sessions');
const { BookCache } = require('../src/bookCache');
const { estimateCost } = require('../src/cost');
const { memoryStorage } = require('./fixture');
describe('resolveMode', () => {
const base = { tokenCount: 1000, threshold: 60000, premiumPlans: ['premium'], plan: '', style: 'default' };
it('follows the auto policy', () => {
expect(resolveMode({ ...base, override: 'full' })).toEqual({ mode: 'FULL_CONTEXT', reason: 'override' });
expect(resolveMode({ ...base, override: 'hybrid', tokenCount: 10 })).toEqual({ mode: 'HYBRID_AGENTIC', reason: 'override' });
expect(resolveMode({ ...base, tokenCount: 60001 })).toEqual({ mode: 'HYBRID_AGENTIC', reason: 'over_token_threshold' });
expect(resolveMode({ ...base, tokenCount: 60000, plan: 'premium' })).toEqual({ mode: 'FULL_CONTEXT', reason: 'premium_plan' });
expect(resolveMode({ ...base, style: 'study' })).toEqual({ mode: 'FULL_CONTEXT', reason: 'study_style' });
expect(resolveMode(base)).toEqual({ mode: 'HYBRID_AGENTIC', reason: 'default_hybrid' });
});
});
describe('chat config', () => {
it('defaults cache settings for a local run', () => {
const config = loadConfig({}, { local: true });
expect(config.cacheTtl).toBe('5m');
expect(config.cacheMinTokens).toBe(4096);
expect(config.autoFullContextMaxTokens).toBe(60000);
expect(config.agentMaxIterations).toBe(4);
expect(config.priceTable).toEqual({});
});
});
describe('sessions and book cache', () => {
it('stores a session in memory', async () => {
const store = new MemorySessionStore();
const created = await store.create({ bookId: 3, mode: 'HYBRID_AGENTIC', channel: 'chat' });
created.history = [{ role: 'user', text: 'Hi' }];
await store.save(created);
const loaded = await store.get(created.sessionId);
expect(loaded.history).toHaveLength(1);
expect(loaded.mode).toBe('HYBRID_AGENTIC');
});
it('maps a mysql session row', async () => {
const pool = {
async query(sql) {
if (String(sql).includes('SELECT')) {
return [[{
session_id: 's1',
book_id: '3',
user_id: 4,
mode: 'FULL_CONTEXT',
channel: 'voice',
style: 'study',
plan: 'premium',
history: [{ role: 'user', text: 'Hello' }],
rolling_summary: '',
last_cache_touch_at: null,
cumulative_usage: { inputTokens: 1, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, toolCalls: 0, llmCalls: 0, estimatedCostUsd: 0 },
keepalive_count: 0,
created_at: new Date('2026-01-01T00:00:00Z'),
}]];
}
return [{ affectedRows: 1 }];
},
};
const store = new MysqlSessionStore(pool);
await store.ensure();
const session = await store.get('s1');
expect(session.bookId).toBe('3');
expect(session.history[0].text).toBe('Hello');
});
it('loads each book once', async () => {
const storage = memoryStorage('3');
const cache = new BookCache(storage, 2);
const first = await cache.load('3', 'v1');
const reads = storage.reads();
const second = await cache.load('3', 'v1');
expect(second).toBe(first);
expect(storage.reads()).toBe(reads);
});
});
describe('cost', () => {
it('prices tokens from the table', () => {
const cost = estimateCost('m', { inputTokens: 1000, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 }, {
m: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
});
expect(cost).toBe(3);
});
});