Files
momentry_studio/docs/MARKBASE_SEARCH_SESSION_API.md
Momentry Studio fe91afff98 feat: integrate MarkBase Search Session API into Studio
- Created useSearchSession composable for session management
- Added 7 API endpoints in api/index.ts
- Updated SearchView.vue to use sessions instead of history
- Session sidebar with create, rename, delete functionality
- Auto-save messages to current session after each search
- Auto-create default session on first load
- Updated CSS for session active state and new session button
2026-10-27 05:06:03 +08:00

345 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MarkBase Search Session API 需求
## 背景
Momentry Studio 需要將搜尋歷史(Search History)升級為以 Session 為單位的管理系統,並整合到 MarkBase 的 SQLite 資料庫中。目前 Studio 使用本地 SQLite 儲存搜尋記錄,現在需要改為透過 MarkBase API 存取。
---
## 1. SQLite Schema 需求
### 1.1 新增 search_sessions 表
```sql
CREATE TABLE IF NOT EXISTS search_sessions (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
title TEXT NOT NULL DEFAULT '未命名搜尋',
mode TEXT DEFAULT 'keyword', -- keyword | visual | people | agent
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX idx_sessions_user ON search_sessions(user_id);
CREATE INDEX idx_sessions_updated ON search_sessions(user_id, updated_at DESC);
```
### 1.2 新增 search_messages 表
```sql
CREATE TABLE IF NOT EXISTS search_messages (
id TEXT PRIMARY KEY,
session_id TEXT NOT NULL REFERENCES search_sessions(id) ON DELETE CASCADE,
role TEXT NOT NULL, -- 'user' | 'assistant'
content TEXT, -- 使用者輸入或 AI 回答
results TEXT, -- JSON 格式的搜尋結果
mode TEXT DEFAULT 'keyword', -- 搜尋模式
created_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX idx_messages_session ON search_messages(session_id, created_at);
```
### 1.3 修改現有 search_history 表(選用)
如果要保留向後相容性:
```sql
ALTER TABLE search_history ADD COLUMN session_id TEXT REFERENCES search_sessions(id);
```
---
## 2. API 端點需求
所有端點前綴:`/api/v2/search-sessions`
### 2.1 列出 Session
**端點**: `GET /api/v2/search-sessions`
**認證**: 需要 Bearer Token
**查詢參數**:
| 參數 | 類型 | 必填 | 說明 | 預設 |
|---|---|---|---|---|
| limit | number | ❌ | 返回數量 | 30 |
| offset | number | ❌ | 偏移量 | 0 |
**回應**:
```json
{
"success": true,
"total": 15,
"sessions": [
{
"id": "sess_abc123",
"title": "廚房場景搜尋",
"mode": "visual",
"message_count": 5,
"created_at": "2026-10-27T10:00:00Z",
"updated_at": "2026-10-27T10:30:00Z"
}
]
}
```
---
### 2.2 建立 Session
**端點**: `POST /api/v2/search-sessions`
**認證**: 需要 Bearer Token
**請求**:
```json
{
"title": "廚房場景搜尋",
"mode": "visual"
}
```
**回應**:
```json
{
"success": true,
"session": {
"id": "sess_abc123",
"title": "廚房場景搜尋",
"mode": "visual",
"created_at": "2026-10-27T10:00:00Z",
"updated_at": "2026-10-27T10:00:00Z"
}
}
```
---
### 2.3 更新 Session
**端點**: `PUT /api/v2/search-sessions/:id`
**認證**: 需要 Bearer Token
**請求**:
```json
{
"title": "重新命名的搜尋"
}
```
**回應**:
```json
{
"success": true,
"message": "Session updated"
}
```
---
### 2.4 刪除 Session
**端點**: `DELETE /api/v2/search-sessions/:id`
**認證**: 需要 Bearer Token
**回應**:
```json
{
"success": true,
"message": "Session deleted"
}
```
---
### 2.5 取得 Session 對話
**端點**: `GET /api/v2/search-sessions/:id/messages`
**認證**: 需要 Bearer Token
**回應**:
```json
{
"success": true,
"messages": [
{
"id": "msg_001",
"role": "user",
"content": "Find kitchen scenes",
"results": null,
"created_at": "2026-10-27T10:00:00Z"
},
{
"id": "msg_002",
"role": "assistant",
"content": "Found 3 kitchen scenes...",
"results": "[...]",
"created_at": "2026-10-27T10:00:01Z"
}
]
}
```
---
### 2.6 新增訊息到 Session
**端點**: `POST /api/v2/search-sessions/:id/messages`
**認證**: 需要 Bearer Token
**請求**:
```json
{
"role": "user",
"content": "Find kitchen scenes",
"mode": "visual",
"results": null
}
```
**回應**:
```json
{
"success": true,
"message": {
"id": "msg_001",
"role": "user",
"content": "Find kitchen scenes",
"created_at": "2026-10-27T10:00:00Z"
}
}
```
---
### 2.7 更新訊息結果(AI 回答後)
**端點**: `PATCH /api/v2/search-sessions/:id/messages/:msgId`
**認證**: 需要 Bearer Token
**請求**:
```json
{
"role": "assistant",
"content": "Found 3 kitchen scenes...",
"results": [{...}, {...}]
}
```
**回應**:
```json
{
"success": true,
"message": "Message updated"
}
```
---
## 3. 業務邏輯需求
### 3.1 自動清理
- 未命名的 Session 超過 24 小時自動刪除
- 每個使用者最多保留 50 個 Session
- 超出限制時,刪除最舊的未命名 Session
### 3.2 使用者隔離
- 所有查詢自動過濾 `user_id`
- Token 中必須包含 `user_id` 或從 token 解析
### 3.3 預設 Session
- 使用者首次進入 Search 頁面時,自動建立 "Default" Session
- 後續搜尋都歸入目前活躍的 Session
---
## 4. 錯誤處理
### 統一錯誤格式
```json
{
"success": false,
"error": "Session not found",
"code": "SESSION_NOT_FOUND"
}
```
### 錯誤代碼
| 代碼 | HTTP 狀態 | 說明 |
|---|---|---|
| SESSION_NOT_FOUND | 404 | Session 不存在 |
| UNAUTHORIZED | 401 | 無效 Token |
| VALIDATION_ERROR | 400 | 請求格式錯誤 |
| LIMIT_EXCEEDED | 429 | 超過 Session 數量限制 |
---
## 5. 前端整合計劃
### 5.1 Studio 修改項目
| 檔案 | 修改內容 |
|---|---|
| `src/composables/useSearchSession.ts` | 新增 Session 管理 composable |
| `src/views/SearchView.vue` | 側邊欄改為 Session 列表 |
| `src/api/index.ts` | 新增 search-session 相關 HTTP 呼叫 |
### 5.2 移除項目
| 檔案 | 移除內容 |
|---|---|
| `src-tauri/src/db.rs` | search_history 相關函數 |
| `src-tauri/src/proxy.rs` | search-history handler |
| `src-tauri/src/main.rs` | search_history Tauri commands |
---
## 6. 測試清單
### 6.1 API 測試
- [ ] 建立 Session
- [ ] 列出 Sessions(分頁)
- [ ] 更新 Session 標題
- [ ] 刪除 Session
- [ ] 新增訊息
- [ ] 更新訊息結果
- [ ] 取得 Session 對話
- [ ] 使用者隔離測試
- [ ] 自動清理測試
### 6.2 前端測試
- [ ] 新 Session 建立
- [ ] Session 命名
- [ ] 切換 Session
- [ ] 刪除 Session
- [ ] 對話還原
- [ ] 自動建立 Default Session
---
## 7. 優先順序
| 優先級 | 任務 | 說明 |
|---|---|---|
| **P0** | SQLite Schema | search_sessions + search_messages 表 |
| **P0** | CRUD API | Session 增刪改查 |
| **P0** | Messages API | 訊息增刪改查 |
| **P1** | 自動清理 | 24 小時 + 50 筆限制 |
| **P1** | 使用者隔離 | Token 解析 + user_id 過濾 |
| **P2** | 效能優化 | 索引 + 分頁 |
---
## 8. 時間預估
| 階段 | 預估工時 |
|---|---|
| Schema 設計 + 實作 | 30 min |
| CRUD API 實作 | 60 min |
| Messages API 實作 | 45 min |
| 自動清理邏輯 | 30 min |
| 測試 + 文檔 | 30 min |
| **總計** | **~3 小時** |