feat: Meeting Assistant MVP - Complete implementation
Enterprise Meeting Knowledge Management System with: Backend (FastAPI): - Authentication proxy with JWT (pj-auth-api integration) - MySQL database with 4 tables (users, meetings, conclusions, actions) - Meeting CRUD with system code generation (C-YYYYMMDD-XX, A-YYYYMMDD-XX) - Dify LLM integration for AI summarization - Excel export with openpyxl - 20 unit tests (all passing) Client (Electron): - Login page with company auth - Meeting list with create/delete - Meeting detail with real-time transcription - Editable transcript textarea (single block, easy editing) - AI summarization with conclusions/action items - 5-second segment recording (efficient for long meetings) Sidecar (Python): - faster-whisper medium model with int8 quantization - ONNX Runtime VAD (lightweight, ~20MB vs PyTorch ~2GB) - Chinese punctuation processing - OpenCC for Traditional Chinese conversion - Anti-hallucination parameters - Auto-cleanup of temp audio files OpenSpec: - add-meeting-assistant-mvp (47 tasks, archived) - add-realtime-transcription (29 tasks, archived) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
37
backend/app/models/__init__.py
Normal file
37
backend/app/models/__init__.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from .schemas import (
|
||||
LoginRequest,
|
||||
LoginResponse,
|
||||
TokenPayload,
|
||||
MeetingCreate,
|
||||
MeetingUpdate,
|
||||
MeetingResponse,
|
||||
MeetingListResponse,
|
||||
ConclusionCreate,
|
||||
ConclusionResponse,
|
||||
ActionItemCreate,
|
||||
ActionItemUpdate,
|
||||
ActionItemResponse,
|
||||
SummarizeRequest,
|
||||
SummarizeResponse,
|
||||
ActionItemStatus,
|
||||
UserRole,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"LoginRequest",
|
||||
"LoginResponse",
|
||||
"TokenPayload",
|
||||
"MeetingCreate",
|
||||
"MeetingUpdate",
|
||||
"MeetingResponse",
|
||||
"MeetingListResponse",
|
||||
"ConclusionCreate",
|
||||
"ConclusionResponse",
|
||||
"ActionItemCreate",
|
||||
"ActionItemUpdate",
|
||||
"ActionItemResponse",
|
||||
"SummarizeRequest",
|
||||
"SummarizeResponse",
|
||||
"ActionItemStatus",
|
||||
"UserRole",
|
||||
]
|
||||
128
backend/app/models/schemas.py
Normal file
128
backend/app/models/schemas.py
Normal file
@@ -0,0 +1,128 @@
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional, List
|
||||
from datetime import datetime, date
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ActionItemStatus(str, Enum):
|
||||
OPEN = "Open"
|
||||
IN_PROGRESS = "In Progress"
|
||||
DONE = "Done"
|
||||
DELAYED = "Delayed"
|
||||
|
||||
|
||||
class UserRole(str, Enum):
|
||||
ADMIN = "admin"
|
||||
USER = "user"
|
||||
|
||||
|
||||
# Auth schemas
|
||||
class LoginRequest(BaseModel):
|
||||
email: str
|
||||
password: str
|
||||
|
||||
|
||||
class LoginResponse(BaseModel):
|
||||
token: str
|
||||
email: str
|
||||
role: str
|
||||
|
||||
|
||||
class TokenPayload(BaseModel):
|
||||
email: str
|
||||
role: str
|
||||
exp: Optional[int] = None
|
||||
|
||||
|
||||
# Meeting schemas
|
||||
class ConclusionCreate(BaseModel):
|
||||
content: str
|
||||
|
||||
|
||||
class ConclusionResponse(BaseModel):
|
||||
conclusion_id: int
|
||||
meeting_id: int
|
||||
content: str
|
||||
system_code: Optional[str] = None
|
||||
|
||||
|
||||
class ActionItemCreate(BaseModel):
|
||||
content: str
|
||||
owner: Optional[str] = ""
|
||||
due_date: Optional[date] = None
|
||||
|
||||
|
||||
class ActionItemUpdate(BaseModel):
|
||||
content: Optional[str] = None
|
||||
owner: Optional[str] = None
|
||||
due_date: Optional[date] = None
|
||||
status: Optional[ActionItemStatus] = None
|
||||
|
||||
|
||||
class ActionItemResponse(BaseModel):
|
||||
action_id: int
|
||||
meeting_id: int
|
||||
content: str
|
||||
owner: Optional[str] = None
|
||||
due_date: Optional[date] = None
|
||||
status: ActionItemStatus
|
||||
system_code: Optional[str] = None
|
||||
|
||||
|
||||
class MeetingCreate(BaseModel):
|
||||
subject: str
|
||||
meeting_time: datetime
|
||||
location: Optional[str] = ""
|
||||
chairperson: Optional[str] = ""
|
||||
recorder: Optional[str] = ""
|
||||
attendees: Optional[str] = ""
|
||||
transcript_blob: Optional[str] = ""
|
||||
conclusions: Optional[List[ConclusionCreate]] = []
|
||||
actions: Optional[List[ActionItemCreate]] = []
|
||||
|
||||
|
||||
class MeetingUpdate(BaseModel):
|
||||
subject: Optional[str] = None
|
||||
meeting_time: Optional[datetime] = None
|
||||
location: Optional[str] = None
|
||||
chairperson: Optional[str] = None
|
||||
recorder: Optional[str] = None
|
||||
attendees: Optional[str] = None
|
||||
transcript_blob: Optional[str] = None
|
||||
conclusions: Optional[List[ConclusionCreate]] = None
|
||||
actions: Optional[List[ActionItemCreate]] = None
|
||||
|
||||
|
||||
class MeetingResponse(BaseModel):
|
||||
meeting_id: int
|
||||
uuid: str
|
||||
subject: str
|
||||
meeting_time: datetime
|
||||
location: Optional[str] = None
|
||||
chairperson: Optional[str] = None
|
||||
recorder: Optional[str] = None
|
||||
attendees: Optional[str] = None
|
||||
transcript_blob: Optional[str] = None
|
||||
created_by: Optional[str] = None
|
||||
created_at: datetime
|
||||
conclusions: List[ConclusionResponse] = []
|
||||
actions: List[ActionItemResponse] = []
|
||||
|
||||
|
||||
class MeetingListResponse(BaseModel):
|
||||
meeting_id: int
|
||||
uuid: str
|
||||
subject: str
|
||||
meeting_time: datetime
|
||||
chairperson: Optional[str] = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
# AI schemas
|
||||
class SummarizeRequest(BaseModel):
|
||||
transcript: str
|
||||
|
||||
|
||||
class SummarizeResponse(BaseModel):
|
||||
conclusions: List[str]
|
||||
action_items: List[ActionItemCreate]
|
||||
Reference in New Issue
Block a user