feat: add agent_metrics table schema and Drizzle migration
Adds the agentMetrics table to SQLite schema for storing pre-computed per-agent event counts (questions, subagents, compactions), enabling listForRadar to fetch one row per agent instead of scanning log chunks. Also fixes pre-existing Drizzle snapshot chain collision in meta/ (0035/0036 snapshots had wrong prevId due to parallel agent branches) to unblock drizzle-kit generate. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
48
apps/server/db/repositories/drizzle/agent-metrics.test.ts
Normal file
48
apps/server/db/repositories/drizzle/agent-metrics.test.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { createTestDatabase } from './test-helpers.js';
|
||||
import { agentMetrics } from '../../schema.js';
|
||||
|
||||
describe('agentMetrics table', () => {
|
||||
it('select from empty agentMetrics returns []', async () => {
|
||||
const db = createTestDatabase();
|
||||
const rows = await db.select().from(agentMetrics);
|
||||
expect(rows).toEqual([]);
|
||||
});
|
||||
|
||||
it('insert and select a metrics row round-trips correctly', async () => {
|
||||
const db = createTestDatabase();
|
||||
await db.insert(agentMetrics).values({
|
||||
agentId: 'agent-abc',
|
||||
questionsCount: 3,
|
||||
subagentsCount: 1,
|
||||
compactionsCount: 0,
|
||||
updatedAt: new Date('2024-01-01T00:00:00Z'),
|
||||
});
|
||||
const rows = await db.select().from(agentMetrics);
|
||||
expect(rows).toHaveLength(1);
|
||||
expect(rows[0].agentId).toBe('agent-abc');
|
||||
expect(rows[0].questionsCount).toBe(3);
|
||||
expect(rows[0].subagentsCount).toBe(1);
|
||||
expect(rows[0].compactionsCount).toBe(0);
|
||||
});
|
||||
|
||||
it('agentId is primary key — duplicate insert throws', async () => {
|
||||
const db = createTestDatabase();
|
||||
await db.insert(agentMetrics).values({
|
||||
agentId: 'agent-dup',
|
||||
questionsCount: 0,
|
||||
subagentsCount: 0,
|
||||
compactionsCount: 0,
|
||||
updatedAt: new Date(),
|
||||
});
|
||||
await expect(
|
||||
db.insert(agentMetrics).values({
|
||||
agentId: 'agent-dup',
|
||||
questionsCount: 1,
|
||||
subagentsCount: 0,
|
||||
compactionsCount: 0,
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
@@ -513,6 +513,21 @@ export const agentLogChunks = sqliteTable('agent_log_chunks', {
|
||||
export type AgentLogChunk = InferSelectModel<typeof agentLogChunks>;
|
||||
export type NewAgentLogChunk = InferInsertModel<typeof agentLogChunks>;
|
||||
|
||||
// ============================================================================
|
||||
// AGENT METRICS
|
||||
// ============================================================================
|
||||
|
||||
export const agentMetrics = sqliteTable('agent_metrics', {
|
||||
agentId: text('agent_id').primaryKey(),
|
||||
questionsCount: integer('questions_count').notNull().default(0),
|
||||
subagentsCount: integer('subagents_count').notNull().default(0),
|
||||
compactionsCount: integer('compactions_count').notNull().default(0),
|
||||
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
|
||||
});
|
||||
|
||||
export type AgentMetrics = InferSelectModel<typeof agentMetrics>;
|
||||
export type NewAgentMetrics = InferInsertModel<typeof agentMetrics>;
|
||||
|
||||
// ============================================================================
|
||||
// CONVERSATIONS (inter-agent communication)
|
||||
// ============================================================================
|
||||
|
||||
7
apps/server/drizzle/0037_eager_devos.sql
Normal file
7
apps/server/drizzle/0037_eager_devos.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE `agent_metrics` (
|
||||
`agent_id` text PRIMARY KEY NOT NULL,
|
||||
`questions_count` integer DEFAULT 0 NOT NULL,
|
||||
`subagents_count` integer DEFAULT 0 NOT NULL,
|
||||
`compactions_count` integer DEFAULT 0 NOT NULL,
|
||||
`updated_at` integer NOT NULL
|
||||
);
|
||||
@@ -2,7 +2,7 @@
|
||||
"version": "6",
|
||||
"dialect": "sqlite",
|
||||
"id": "c84e499f-7df8-4091-b2a5-6b12847898bd",
|
||||
"prevId": "5fbe1151-1dfb-4b0c-a7fa-2177369543fd",
|
||||
"prevId": "443071fe-31d6-498a-9f4a-4a3ff24a46fc",
|
||||
"tables": {
|
||||
"accounts": {
|
||||
"name": "accounts",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2029
apps/server/drizzle/meta/0037_snapshot.json
Normal file
2029
apps/server/drizzle/meta/0037_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -260,6 +260,13 @@
|
||||
"when": 1772798869413,
|
||||
"tag": "0036_icy_silvermane",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 37,
|
||||
"version": "6",
|
||||
"when": 1772828694292,
|
||||
"tag": "0037_eager_devos",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user