feat: agent variants — migration, API, service integration, frontend, tests

- Migration 027: agent_variants table with single-active enforcement,
  variant_id column on agent_performance_log
- API: full CRUD, clone from agent/variant, activate/deactivate,
  per-variant performance metrics and history endpoints
- Services: extractor, event classifier, thesis rewriter all wired
  to AgentConfigResolver with variant override support
- Frontend: variant list, comparison view, create/edit/clone forms,
  activate/delete actions on Agents page
- Tests: API tests + 5 property-based tests (single-active invariant,
  clone preservation, config resolution, slug determinism, update idempotence)
- Spec files for agent-variants feature
This commit is contained in:
Celes Renata
2026-04-17 05:15:42 +00:00
parent 734bf001a7
commit 7c23c044d7
14 changed files with 3118 additions and 120 deletions
+40
View File
@@ -168,3 +168,43 @@ describe('Global Events page', () => {
});
});
});
describe('Agents page', () => {
it('renders agent list in sidebar', async () => {
renderRoute('/agents');
await waitFor(() => {
expect(screen.getByText('Document Extractor')).toBeInTheDocument();
expect(screen.getByText('Event Classifier')).toBeInTheDocument();
});
});
it('renders variant list when an agent is selected', async () => {
renderRoute('/agents');
await waitFor(() => expect(screen.getByText('Document Extractor')).toBeInTheDocument());
await userEvent.click(screen.getByText('Document Extractor'));
await waitFor(() => {
expect(screen.getByText('GPT-4o Variant')).toBeInTheDocument();
expect(screen.getByText('Mistral Variant')).toBeInTheDocument();
});
});
it('shows comparison view when multiple variants are checked', async () => {
renderRoute('/agents');
await waitFor(() => expect(screen.getByText('Document Extractor')).toBeInTheDocument());
await userEvent.click(screen.getByText('Document Extractor'));
await waitFor(() => expect(screen.getByText('GPT-4o Variant')).toBeInTheDocument());
// Select both variant checkboxes
const checkboxes = screen.getAllByRole('checkbox');
await userEvent.click(checkboxes[0]);
await userEvent.click(checkboxes[1]);
await waitFor(() => {
expect(screen.getByText(/Variant Comparison/)).toBeInTheDocument();
});
});
});