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:
egg
2025-12-10 20:17:44 +08:00
commit 8b6184ecc5
65 changed files with 10510 additions and 0 deletions

143
SDD.md Normal file
View File

@@ -0,0 +1,143 @@
1. 系統架構圖 (System Architecture)
Plaintext
[Client: Electron App]
|
|-- (1. Auth API) --> [Ext: PJ-Auth API (Vercel)]
|
|-- (2. Meeting Data) --> [Middleware Server (Python FastAPI)]
|
|-- (3. SQL Query) --> [DB: MySQL (Shared)]
|
|-- (4. Summarize) --> [Ext: Dify LLM]
注意: 為了安全,資料庫連線資訊與 Dify API Key 嚴禁打包在 Electron Client 端,必須放在 Middleware Server。
2. 資料庫設計 (Database Schema)
Host: mysql.theaken.com (Port 33306)
User/Pass: A060 / WLeSCi0yhtc7
DB Name: db_A060
Prefix: meeting_
SQL
-- 1. 使用者表 (與 Auth API 對應,本地快取用)
CREATE TABLE meeting_users (
user_id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(100) UNIQUE NOT NULL, -- 對應 ymirliu@panjit.com.tw
display_name VARCHAR(50),
role ENUM('admin', 'user') DEFAULT 'user',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 2. 會議主表
CREATE TABLE meeting_records (
meeting_id INT PRIMARY KEY AUTO_INCREMENT,
uuid VARCHAR(64) UNIQUE, -- 系統唯一識別碼
subject VARCHAR(200) NOT NULL, -- 會議主題
meeting_time DATETIME NOT NULL, -- 會議時間
location VARCHAR(100), -- 會議地點
chairperson VARCHAR(50), -- 會議主席
recorder VARCHAR(50), -- 會議記錄人
attendees TEXT, -- 參與人員 (逗號分隔或 JSON)
transcript_blob LONGTEXT, -- AI 原始逐字稿
created_by VARCHAR(100), -- 建立者 Email
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 3. 會議結論表 (Conclusions)
CREATE TABLE meeting_conclusions (
conclusion_id INT PRIMARY KEY AUTO_INCREMENT,
meeting_id INT,
content TEXT,
system_code VARCHAR(20), -- 會議結論編號 (如: C-20251210-01)
FOREIGN KEY (meeting_id) REFERENCES meeting_records(meeting_id)
);
-- 4. 待辦追蹤表 (Action Items)
CREATE TABLE meeting_action_items (
action_id INT PRIMARY KEY AUTO_INCREMENT,
meeting_id INT,
content TEXT, -- 追蹤事項內容
owner VARCHAR(50), -- 負責人
due_date DATE, -- 預計完成日期
status ENUM('Open', 'In Progress', 'Done', 'Delayed') DEFAULT 'Open', -- 執行現況
system_code VARCHAR(20), -- 會議事項編號 (如: A-20251210-01)
FOREIGN KEY (meeting_id) REFERENCES meeting_records(meeting_id)
);
3. Middleware Server 配置 (FastAPI 範例)
Client 端不直接連 MySQL而是呼叫此 Middleware。
3.1 環境變數 (.env)
Ini, TOML
DB_HOST=mysql.theaken.com
DB_PORT=33306
DB_USER=A060
DB_PASS=WLeSCi0yhtc7
DB_NAME=db_A060
AUTH_API_URL=https://pj-auth-api.vercel.app/api/auth/login
DIFY_API_URL=https://dify.theaken.com/v1
DIFY_API_KEY=app-xxxxxxxxxxx # 需至 Dify 後台取得
ADMIN_EMAIL=ymirliu@panjit.com.tw
3.2 API 介面規格
A. 登入代理 (Proxy)
Endpoint: POST /api/login
Logic: Middleware 轉發請求至 pj-auth-api.vercel.app。成功後若該 Email 為 ymirliu@panjit.com.tw則在回傳的 JWT Payload 中標記 { "role": "admin" }。
B. 上傳/同步會議
Endpoint: POST /api/meetings
Payload:
JSON
{
"meta": { "subject": "...", "chairperson": "...", ... },
"transcript": "...",
"conclusions": [ { "content": "..." } ],
"actions": [ { "content": "...", "owner": "...", "due_date": "..." } ]
}
Logic:
Insert into meeting_records.
Loop insert meeting_conclusions (自動生成 ID: C-{YYYYMMDD}-{Seq}).
Loop insert meeting_action_items (自動生成 ID: A-{YYYYMMDD}-{Seq}).
C. Dify 摘要請求
Endpoint: POST /api/ai/summarize
Payload: { "transcript": "..." }
Logic: 呼叫 Dify API。
Dify Prompt 設定 (System):
Plaintext
你是一個會議記錄助手。請根據逐字稿,回傳 JSON 格式。
必要欄位:
1. conclusions (Array): 結論內容
2. action_items (Array): { content, owner, due_date }
若逐字稿未提及日期或負責人,該欄位請留空字串。
D. Excel 匯出
Endpoint: POST /api/meetings/{id}/export
Logic:
SQL Join 查詢 records, conclusions, action_items。
Load template.xlsx.
Replace Placeholders:
{{subject}}, {{time}}, {{chair}}...
Table Filling: 動態插入 Rows 填寫結論與待辦事項。
Return File Stream.