feat: add agent API and operational analytics

This commit is contained in:
jjbrunton committed 2026-08-08 22:08:14 +01:00
1 parent 720ea0652a
commit e8b730b592
65 files changed
+2650 -1214

No files matched your search

+33
View File
@@ -6,6 +6,8 @@ import {
MessagesRepository,
SuccessfulMessagesRepository,
ConversationStateRepository,
ConversationOutcomesRepository,
RecipientHistoryRepository,
} from '../src/database/repositories.js';
import { buildConversationState } from '../src/services/conversation-state.js';
@@ -607,6 +609,37 @@ describe('ConversationStateRepository', () => {
});
});
describe('Mature performance and guardrails', () => {
it('excludes pending sends and reports a confidence interval', () => {
const { postsRepo, messagesRepo } = createTestRepositories();
postsRepo.insert({ id: 'old', subreddit: 'test', author: 'old-user', title: 'old', imageUrl: null, processedAt: 1 });
postsRepo.insert({ id: 'new', subreddit: 'test', author: 'new-user', title: 'new', imageUrl: null, processedAt: 1 });
const oldId = messagesRepo.insert({
postId: 'old', recipient: 'old-user', subject: 's', message: 'm',
sentAt: Date.now() - 72 * 3600000, strategyId: 'direct',
});
messagesRepo.markGotResponse(oldId);
messagesRepo.insert({
postId: 'new', recipient: 'new-user', subject: 's', message: 'm',
sentAt: Date.now(), strategyId: 'direct',
});
expect(messagesRepo.getStrategyStats(Date.now() - 48 * 3600000)).toEqual([
expect.objectContaining({
strategyId: 'direct', totalSent: 1, totalResponses: 1, responseRate: 100,
pendingSent: 1, responseRateLow: expect.any(Number), responseRateHigh: expect.any(Number),
}),
]);
});
it('suppresses boundary recipients across account history checks', () => {
const db = createTestDb();
const outcomes = new ConversationOutcomesRepository(db);
outcomes.suppressRecipient('Alice', 'boundary');
expect(new RecipientHistoryRepository(db).hasSentTo('alice')).toBe(true);
});
});
describe('Repository edge cases', () => {
it('handles special characters in post titles', () => {
const repos = createTestRepositories();