modcomms/backend/app/api/knowledge_base_schemas.py
michael 9e2473c3e9 Add Knowledge Base management system for AI agent specs
Full-stack implementation enabling UI-driven management of the 5 AI agent knowledge bases
(Legal, Brand Barclays, Brand Barclaycard, Channel Best Practices, Channel Tech Specs).

Backend:
- 4 new DB models: KnowledgeBase, SourceDocument, SpecVersion, ProcessingJob
- Migration 006: creates tables, seeds 5 KB rows, imports existing prompts/*.md as v1 specs
- KnowledgeBaseRepository with full CRUD for all 4 tables
- LlamaParseService for document parsing, KnowledgeBaseService for pipeline orchestration
- ReferenceDocsService updated with DB-backed spec loading + cache invalidation
- 11 REST endpoints under /api/knowledge-base (list, detail, upload, delete, process, job status, versions, diff, activate)
- StorageService extended with KB document storage

Frontend:
- TypeScript types for all KB entities (KnowledgeBaseListItem, SourceDocument, ProcessingJob, SpecVersion, DiffResult)
- ApiService methods for all KB endpoints including multipart file upload
- KnowledgeBase component with 3-level UI: agent grid, detail view (documents + versions tabs), diff viewer
- Drag-and-drop file upload, processing progress bar with 3s polling, version comparison
- KnowledgeBaseIcon + Sidebar nav item with adminOnly filtering

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-12 15:00:36 -06:00

108 lines
2.5 KiB
Python

"""Pydantic schemas for Knowledge Base API."""
import uuid
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
class SourceDocumentResponse(BaseModel):
id: uuid.UUID
knowledge_base_id: uuid.UUID
filename: str
file_storage_key: str
file_size_bytes: int
mime_type: str
uploaded_by_name: Optional[str]
parse_status: str
parse_error: Optional[str]
created_at: datetime
class Config:
from_attributes = True
class ProcessingJobResponse(BaseModel):
id: uuid.UUID
knowledge_base_id: uuid.UUID
status: str
triggered_by_name: Optional[str]
total_documents: int
parsed_documents: int
spec_version_id: Optional[uuid.UUID]
error_message: Optional[str]
started_at: Optional[datetime]
completed_at: Optional[datetime]
created_at: datetime
class Config:
from_attributes = True
class SpecVersionListItem(BaseModel):
id: uuid.UUID
knowledge_base_id: uuid.UUID
version_number: int
generated_by_name: Optional[str]
source_document_ids: Optional[list]
is_active: bool
char_count: int
created_at: datetime
class Config:
from_attributes = True
class SpecVersionDetail(BaseModel):
id: uuid.UUID
knowledge_base_id: uuid.UUID
version_number: int
content: str
generated_by_name: Optional[str]
source_document_ids: Optional[list]
is_active: bool
char_count: int
created_at: datetime
class Config:
from_attributes = True
class KnowledgeBaseListItem(BaseModel):
id: uuid.UUID
agent_key: str
display_name: str
description: Optional[str]
source_document_count: int
active_spec_version: Optional[int]
active_spec_char_count: Optional[int]
latest_job_status: Optional[str]
latest_job_completed_at: Optional[datetime]
created_at: datetime
class KnowledgeBaseDetail(BaseModel):
id: uuid.UUID
agent_key: str
display_name: str
description: Optional[str]
source_documents: list[SourceDocumentResponse]
active_spec_version: Optional[int]
active_spec_char_count: Optional[int]
latest_job: Optional[ProcessingJobResponse]
created_at: datetime
class DiffLine(BaseModel):
type: str # 'add', 'remove', 'context'
content: str
line_number_old: Optional[int] = None
line_number_new: Optional[int] = None
class DiffResponse(BaseModel):
version_a: int
version_b: int
additions: int
deletions: int
lines: list[DiffLine]