Wrap insertChunk in a synchronous better-sqlite3 transaction that upserts agent_metrics counters atomically on every chunk insert. Malformed JSON skips the upsert but always preserves the chunk row. Add findMetricsByAgentIds to the interface and Drizzle adapter for efficient bulk metric reads. Add 8-test suite covering all write/read paths and edge cases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
130 lines
4.1 KiB
TypeScript
130 lines
4.1 KiB
TypeScript
import { describe, it, expect, beforeEach } from 'vitest';
|
|
import { DrizzleLogChunkRepository } from './log-chunk.js';
|
|
import { createTestDatabase } from './test-helpers.js';
|
|
import type { DrizzleDatabase } from '../../index.js';
|
|
|
|
describe('DrizzleLogChunkRepository', () => {
|
|
let db: DrizzleDatabase;
|
|
let repo: DrizzleLogChunkRepository;
|
|
const testAgentId = 'agent-test-001';
|
|
|
|
beforeEach(() => {
|
|
db = createTestDatabase();
|
|
repo = new DrizzleLogChunkRepository(db);
|
|
});
|
|
|
|
it('AskUserQuestion chunk — questionsCount upserted correctly', async () => {
|
|
await repo.insertChunk({
|
|
agentId: testAgentId,
|
|
agentName: 'test-agent',
|
|
sessionNumber: 1,
|
|
content: JSON.stringify({ type: 'tool_use', name: 'AskUserQuestion', input: { questions: [{}, {}] } }),
|
|
});
|
|
const metrics = await repo.findMetricsByAgentIds([testAgentId]);
|
|
expect(metrics).toEqual([{
|
|
agentId: testAgentId,
|
|
questionsCount: 2,
|
|
subagentsCount: 0,
|
|
compactionsCount: 0,
|
|
}]);
|
|
});
|
|
|
|
it('Agent tool chunk — subagentsCount incremented', async () => {
|
|
await repo.insertChunk({
|
|
agentId: testAgentId,
|
|
agentName: 'test-agent',
|
|
sessionNumber: 1,
|
|
content: JSON.stringify({ type: 'tool_use', name: 'Agent' }),
|
|
});
|
|
const metrics = await repo.findMetricsByAgentIds([testAgentId]);
|
|
expect(metrics).toEqual([{
|
|
agentId: testAgentId,
|
|
questionsCount: 0,
|
|
subagentsCount: 1,
|
|
compactionsCount: 0,
|
|
}]);
|
|
});
|
|
|
|
it('Compaction event — compactionsCount incremented', async () => {
|
|
await repo.insertChunk({
|
|
agentId: testAgentId,
|
|
agentName: 'test-agent',
|
|
sessionNumber: 1,
|
|
content: JSON.stringify({ type: 'system', subtype: 'init', source: 'compact' }),
|
|
});
|
|
const metrics = await repo.findMetricsByAgentIds([testAgentId]);
|
|
expect(metrics).toEqual([{
|
|
agentId: testAgentId,
|
|
questionsCount: 0,
|
|
subagentsCount: 0,
|
|
compactionsCount: 1,
|
|
}]);
|
|
});
|
|
|
|
it('Irrelevant chunk type — no metrics row created', async () => {
|
|
await repo.insertChunk({
|
|
agentId: testAgentId,
|
|
agentName: 'test-agent',
|
|
sessionNumber: 1,
|
|
content: JSON.stringify({ type: 'text', text: 'hello' }),
|
|
});
|
|
const metrics = await repo.findMetricsByAgentIds([testAgentId]);
|
|
expect(metrics).toEqual([]);
|
|
});
|
|
|
|
it('Malformed JSON chunk — chunk persisted, metrics row absent', async () => {
|
|
await repo.insertChunk({
|
|
agentId: testAgentId,
|
|
agentName: 'test-agent',
|
|
sessionNumber: 1,
|
|
content: 'not-valid-json',
|
|
});
|
|
const chunks = await repo.findByAgentId(testAgentId);
|
|
expect(chunks).toHaveLength(1);
|
|
const metrics = await repo.findMetricsByAgentIds([testAgentId]);
|
|
expect(metrics).toEqual([]);
|
|
});
|
|
|
|
it('Multiple inserts, same agent — counts accumulate additively', async () => {
|
|
// 3 Agent tool chunks
|
|
for (let i = 0; i < 3; i++) {
|
|
await repo.insertChunk({
|
|
agentId: testAgentId,
|
|
agentName: 'test-agent',
|
|
sessionNumber: 1,
|
|
content: JSON.stringify({ type: 'tool_use', name: 'Agent' }),
|
|
});
|
|
}
|
|
// 1 AskUserQuestion with 2 questions
|
|
await repo.insertChunk({
|
|
agentId: testAgentId,
|
|
agentName: 'test-agent',
|
|
sessionNumber: 1,
|
|
content: JSON.stringify({ type: 'tool_use', name: 'AskUserQuestion', input: { questions: [{}, {}] } }),
|
|
});
|
|
const metrics = await repo.findMetricsByAgentIds([testAgentId]);
|
|
expect(metrics).toEqual([{
|
|
agentId: testAgentId,
|
|
questionsCount: 2,
|
|
subagentsCount: 3,
|
|
compactionsCount: 0,
|
|
}]);
|
|
});
|
|
|
|
it('findMetricsByAgentIds with empty array — returns []', async () => {
|
|
const metrics = await repo.findMetricsByAgentIds([]);
|
|
expect(metrics).toEqual([]);
|
|
});
|
|
|
|
it('findMetricsByAgentIds with agentId that has no metrics row — returns []', async () => {
|
|
await repo.insertChunk({
|
|
agentId: testAgentId,
|
|
agentName: 'test-agent',
|
|
sessionNumber: 1,
|
|
content: JSON.stringify({ type: 'text', text: 'hello' }),
|
|
});
|
|
const metrics = await repo.findMetricsByAgentIds([testAgentId]);
|
|
expect(metrics).toEqual([]);
|
|
});
|
|
});
|