# 交互流程文檔

## 🔄 AI 助手與 MCP 服務完整交互流程

本文檔詳細描述 AI 助手調用 MCP Feedback Enhanced 服務的完整流程，包括首次調用、多次循環調用、錯誤處理和性能優化機制。

### 核心設計理念

- **持久化會話**: 支援 AI 助手多次循環調用，無需重複建立連接
- **智能環境適配**: 自動檢測並適配本地、SSH Remote、WSL 環境
- **無縫狀態切換**: 會話更新時前端局部刷新，保持用戶操作狀態
- **優雅錯誤處理**: 完整的錯誤恢復機制和超時保護
- **資源優化**: 單一活躍會話模式，最小化資源佔用

## 📋 流程概覽

### 整體交互時序圖

```mermaid
sequenceDiagram
    participant AI as AI 助手<br/>(Cursor/Claude/etc)
    participant MCP as MCP 服務<br/>(server.py)
    participant WM as WebUIManager<br/>(單例管理器)
    participant FastAPI as FastAPI 應用<br/>(Web 服務)
    participant WS as WebSocket<br/>(實時通信)
    participant Browser as 瀏覽器<br/>(Web UI)
    participant User as 用戶

    Note over AI,User: 🚀 第一次調用流程
    AI->>+MCP: interactive_feedback(project_dir, summary, timeout)
    MCP->>+WM: launch_web_feedback_ui()

    Note over WM: 環境檢測與會話創建
    WM->>WM: detect_environment()
    WM->>WM: create_session()

    WM->>+FastAPI: 啟動 Web 服務器
    FastAPI->>FastAPI: setup_routes()
    FastAPI->>FastAPI: setup_websocket()
    FastAPI-->>-WM: 服務器就緒

    WM->>Browser: smart_open_browser(url)
    Note over Browser: 智能開啟瀏覽器<br/>檢測活躍標籤頁

    Browser->>+FastAPI: GET /feedback
    FastAPI->>FastAPI: render_template()
    FastAPI-->>-Browser: HTML 頁面

    Browser->>+WS: 建立 WebSocket 連接
    WS->>WM: register_websocket()
    WS-->>-Browser: connection_established

    Note over AI,User: 💬 用戶回饋流程
    User->>Browser: 填寫回饋內容
    Browser->>+WS: submit_feedback
    WS->>WM: process_feedback()
    WM->>WM: validate_and_save()
    WM->>MCP: set_feedback_complete()
    WS-->>-Browser: feedback_received
    MCP-->>-AI: 返回回饋結果

    Note over AI,User: 🔄 第二次調用流程 (持久化會話)
    AI->>+MCP: interactive_feedback(new_summary, timeout)
    MCP->>+WM: 檢查現有會話

    alt 有活躍會話
        WM->>WM: update_session()
        WM->>+WS: session_updated 通知
        WS-->>-Browser: 會話更新訊息
        Browser->>Browser: 局部更新內容
        Note over Browser: 無需重新載入頁面<br/>保持用戶操作狀態
    else 無活躍會話
        WM->>WM: create_new_session()
        WM->>Browser: 重新開啟瀏覽器
    end

    User->>Browser: 提交新回饋
    Browser->>+WS: submit_feedback
    WS->>WM: process_new_feedback()
    WM->>MCP: set_feedback_complete()
    WS-->>-Browser: feedback_received
    MCP-->>-AI: 返回新回饋結果

    Note over AI,User: 🧹 資源清理 (可選)
    alt 會話超時或手動清理
        WM->>WS: cleanup_session()
        WS->>Browser: session_cleanup
        WM->>FastAPI: 停止服務器 (可選)
    end
```

## 🚀 第一次調用詳細流程

### 1. AI 助手發起調用

**MCP 工具調用格式**：
```python
# AI 助手通過 MCP 協議調用
result = await interactive_feedback(
    project_directory="./my-project",
    summary="我已完成了功能 X 的實現，請檢查代碼品質和邏輯正確性。主要變更包括：\n1. 新增錯誤處理機制\n2. 優化性能瓶頸\n3. 增加單元測試覆蓋率",
    timeout=600  # 10 分鐘超時
)
```

**參數說明**：
- `project_directory`: 專案根目錄，用於命令執行上下文
- `summary`: AI 工作摘要，向用戶說明已完成的工作
- `timeout`: 等待用戶回饋的超時時間（秒）

### 2. MCP 服務處理流程

```mermaid
flowchart TD
    START[AI 調用 interactive_feedback] --> VALIDATE[參數驗證與類型檢查]
    VALIDATE --> ENV[環境檢測<br/>Local/SSH/WSL]
    ENV --> MANAGER[獲取 WebUIManager<br/>單例實例]
    MANAGER --> CHECK[檢查現有會話]
    CHECK --> DECISION{有活躍會話?}

    DECISION -->|否| CREATE[創建新會話]
    DECISION -->|是| UPDATE[更新現有會話]

    CREATE --> SESSION[WebFeedbackSession<br/>初始化]
    UPDATE --> SESSION

    SESSION --> SERVER[啟動 FastAPI 服務器]
    SERVER --> PORT[動態埠分配]
    PORT --> ROUTES[設置路由和 WebSocket]
    ROUTES --> BROWSER[智能開啟瀏覽器]

    BROWSER --> DETECT[檢測活躍標籤頁]
    DETECT --> OPEN_DECISION{需要開啟瀏覽器?}

    OPEN_DECISION -->|是| OPEN[開啟新瀏覽器視窗]
    OPEN_DECISION -->|否| NOTIFY[發送會話更新通知]

    OPEN --> WAIT[等待用戶回饋]
    NOTIFY --> WAIT

    WAIT --> TIMEOUT{檢查超時}
    TIMEOUT -->|未超時| FEEDBACK[接收回饋數據]
    TIMEOUT -->|超時| CLEANUP[清理資源]

    FEEDBACK --> PROCESS[處理回饋數據<br/>圖片壓縮/命令執行]
    PROCESS --> SAVE[保存回饋記錄]
    SAVE --> RETURN[返回結果給 AI]

    CLEANUP --> ERROR[返回超時錯誤]
    ERROR --> RETURN

    style START fill:#e3f2fd
    style RETURN fill:#e8f5e8
    style ERROR fill:#ffebee
    style FEEDBACK fill:#f3e5f5
```

**關鍵步驟詳解**：

#### 2.1 環境檢測與適配
```python
def detect_environment() -> str:
    """智能檢測運行環境"""
    # SSH Remote 環境檢測
    if os.environ.get('SSH_CLIENT') or os.environ.get('SSH_TTY'):
        return "ssh"

    # WSL 環境檢測
    elif 'microsoft' in platform.uname().release.lower():
        return "wsl"

    # 容器環境檢測
    elif os.path.exists('/.dockerenv'):
        return "docker"

    # 本地環境
    else:
        return "local"

def get_environment_config(env_type: str) -> dict:
    """根據環境類型獲取配置"""
    configs = {
        "local": {
            "browser_command": "default",
            "host": "127.0.0.1",
            "auto_open": True
        },
        "ssh": {
            "browser_command": None,
            "host": "127.0.0.1",
            "auto_open": False,
            "tunnel_hint": "ssh -L {port}:127.0.0.1:{port} user@host"
        },
        "wsl": {
            "browser_command": "cmd.exe /c start",
            "host": "127.0.0.1",
            "auto_open": True
        }
    }
    return configs.get(env_type, configs["local"])
```

#### 2.2 智能會話管理
```python
async def create_or_update_session(
    self,
    project_dir: str,
    summary: str,
    timeout: int
) -> str:
    """創建新會話或更新現有會話"""

    # 保存現有 WebSocket 連接
    existing_websockets = []
    if self.current_session:
        existing_websockets = list(self.current_session.websockets)
        debug_log(f"保存 {len(existing_websockets)} 個現有 WebSocket 連接")

    # 創建新會話
    session_id = str(uuid.uuid4())
    self.current_session = WebFeedbackSession(
        session_id=session_id,
        project_directory=os.path.abspath(project_dir),
        summary=summary,
        timeout=timeout,
        status=SessionStatus.WAITING,
        created_at=datetime.now()
    )

    # 繼承 WebSocket 連接，實現無縫切換
    for ws in existing_websockets:
        if ws.client_state == WebSocketState.CONNECTED:
            self.current_session.add_websocket(ws)
            debug_log("WebSocket 連接已繼承到新會話")

    # 標記需要發送會話更新通知
    self._pending_session_update = True

    return session_id
```

#### 2.3 動態埠管理
```python
class PortManager:
    def find_available_port(self, preferred_port: int = 8765) -> int:
        """智能埠分配"""
        # 優先使用環境變數指定的埠
        env_port = os.environ.get('MCP_WEB_PORT')
        if env_port and env_port != "0":
            try:
                port = int(env_port)
                if self.is_port_available(port):
                    return port
            except ValueError:
                pass

        # 嘗試首選埠
        if self.is_port_available(preferred_port):
            return preferred_port

        # 動態分配埠
        for port in range(8765, 8865):
            if self.is_port_available(port):
                return port

        # 系統自動分配
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.bind(('127.0.0.1', 0))
            return sock.getsockname()[1]
```

### 3. Web UI 連接建立與初始化

```mermaid
sequenceDiagram
    participant Browser as 瀏覽器
    participant FastAPI as FastAPI 服務
    participant Template as 模板引擎
    participant WS as WebSocket
    participant Session as 會話管理
    participant I18N as 國際化

    Note over Browser,I18N: 頁面載入流程
    Browser->>+FastAPI: GET /feedback
    FastAPI->>+Template: render_template()
    Template->>I18N: 載入語言包
    I18N-->>Template: 翻譯資源
    Template->>Template: 渲染 HTML
    Template-->>-FastAPI: 完整頁面
    FastAPI-->>-Browser: HTML + CSS + JS

    Note over Browser,Session: WebSocket 連接建立
    Browser->>Browser: 載入 JavaScript 模組
    Browser->>+WS: 建立 WebSocket 連接 (/ws)
    WS->>Session: register_websocket()
    Session->>Session: 檢查會話狀態
    WS-->>-Browser: connection_established

    Note over Browser,Session: 會話狀態同步
    alt 有活躍會話
        Session->>+WS: session_data
        WS-->>-Browser: 當前會話資訊
        Browser->>Browser: 更新 AI 摘要
        Browser->>Browser: 設置會話 ID
    end

    alt 有待處理的會話更新
        Session->>+WS: session_updated
        WS-->>-Browser: 會話更新通知
        Browser->>Browser: 顯示更新提示
        Browser->>Browser: 局部刷新內容
        Browser->>Browser: 自動聚焦輸入框
    end

    Note over Browser,Session: 心跳檢測啟動
    Browser->>Browser: 啟動心跳定時器
    loop 每 30 秒
        Browser->>WS: heartbeat
        WS-->>Browser: heartbeat_ack
    end
```

**連接建立關鍵步驟**：

#### 3.1 頁面渲染
```python
@app.get("/feedback")
async def feedback_page(request: Request):
    """回饋頁面渲染"""
    manager = get_web_ui_manager()
    session = manager.current_session

    # 載入用戶設定
    layout_mode = load_user_layout_settings()

    # 獲取當前語言
    i18n_manager = get_i18n_manager()
    current_language = i18n_manager.get_current_language()

    return templates.TemplateResponse("feedback.html", {
        "request": request,
        "project_directory": session.project_directory if session else ".",
        "layout_mode": layout_mode,
        "current_language": current_language,
        "session_id": session.session_id if session else None,
        "title": i18n_manager.t("app.title")
    })
```

#### 3.2 WebSocket 連接處理
```python
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    """WebSocket 連接端點"""
    await websocket.accept()

    try:
        # 註冊 WebSocket 連接
        manager = get_web_ui_manager()
        if manager.current_session:
            manager.current_session.add_websocket(websocket)

        # 發送連接確認
        await websocket.send_json({
            "type": "connection_established",
            "data": {
                "timestamp": datetime.now().isoformat(),
                "session_id": manager.current_session.session_id if manager.current_session else None
            }
        })

        # 如果有待處理的會話更新，立即發送
        if manager._pending_session_update and manager.current_session:
            await websocket.send_json({
                "type": "session_updated",
                "data": {
                    "session_id": manager.current_session.session_id,
                    "summary": manager.current_session.summary,
                    "project_directory": manager.current_session.project_directory
                }
            })
            manager._pending_session_update = False

        # 處理訊息循環
        while True:
            data = await websocket.receive_json()
            await handle_websocket_message(websocket, data)

    except WebSocketDisconnect:
        # 處理連接斷開
        if manager.current_session:
            manager.current_session.remove_websocket(websocket)
        debug_log("WebSocket 連接已斷開")
```

## 🔄 多次循環調用機制

### 持久化會話架構

MCP Feedback Enhanced 的核心創新在於**持久化會話架構**，支援 AI 助手進行多次循環調用而無需重新建立連接。

```mermaid
stateDiagram-v2
    [*] --> FirstCall: AI 首次調用
    FirstCall --> SessionActive: 會話建立
    SessionActive --> UserFeedback: 等待用戶回饋
    UserFeedback --> FeedbackSubmitted: 回饋提交
    FeedbackSubmitted --> AIProcessing: AI 處理回饋
    AIProcessing --> SecondCall: AI 再次調用
    SecondCall --> SessionUpdated: 會話更新
    SessionUpdated --> UserFeedback: 等待新回饋

    note right of SessionActive
        Web 服務器持續運行
        瀏覽器標籤頁保持開啟
        WebSocket 連接維持
    end note

    note right of SessionUpdated
        無需重新開啟瀏覽器
        局部更新頁面內容
        狀態無縫切換
    end note
```

### 第二次調用流程

#### 1. AI 助手再次調用
```python
# AI 根據用戶回饋進行調整後再次調用
result = await interactive_feedback(
    project_directory="./my-project",
    summary="根據您的建議，我已修改了錯誤處理邏輯，請再次確認",
    timeout=600
)
```

#### 2. 智能會話切換
```mermaid
flowchart TD
    CALL[AI 再次調用] --> CHECK[檢查現有會話]
    CHECK --> ACTIVE{有活躍會話?}
    ACTIVE -->|是| UPDATE[更新會話內容]
    ACTIVE -->|否| CREATE[創建新會話]
    UPDATE --> PRESERVE[保存 WebSocket 連接]
    CREATE --> PRESERVE
    PRESERVE --> NOTIFY[發送會話更新通知]
    NOTIFY --> FRONTEND[前端接收更新]
    FRONTEND --> REFRESH[局部刷新內容]
```

#### 3. 前端無縫更新
```javascript
// 處理會話更新訊息
function handleSessionUpdated(data) {
    // 顯示會話更新通知
    showNotification('會話已更新', 'info');

    // 重置回饋狀態
    feedbackState = 'FEEDBACK_WAITING';

    // 局部更新 AI 摘要
    updateAISummary(data.summary);

    // 清空回饋表單
    clearFeedbackForm();

    // 更新會話 ID
    currentSessionId = data.session_id;

    // 保持 WebSocket 連接不變
    // 無需重新建立連接
}
```

## 🚀 新功能交互流程

### 自動提交功能流程

```mermaid
sequenceDiagram
    participant User as 用戶
    participant UI as 前端界面
    participant ASM as AutoSubmitManager
    participant PM as PromptManager
    participant WS as WebSocket

    Note over User,WS: 🔧 設定自動提交
    User->>UI: 開啟設定頁籤
    UI->>PM: 獲取提示詞列表
    PM-->>UI: 返回提示詞（自動提交優先）
    User->>UI: 選擇提示詞並設定倒數時間
    UI->>ASM: updateSettings(enabled, timeout, promptId)
    ASM->>WS: 保存設定到服務器

    Note over User,WS: ⏰ 自動提交執行
    WS->>UI: session_updated（AI 新調用）
    UI->>ASM: checkAutoSubmitConditions()
    ASM->>ASM: 檢查設定和狀態
    alt 條件滿足
        ASM->>ASM: start(timeout, promptId)
        ASM->>UI: 顯示倒數計時器
        loop 每秒更新
            ASM->>UI: updateCountdownDisplay(remaining)
        end
        ASM->>PM: getPromptById(promptId)
        PM-->>ASM: 返回提示詞內容
        ASM->>UI: 填入提示詞到輸入框
        ASM->>WS: submit_feedback（自動提交）
    else 條件不滿足
        ASM->>UI: 隱藏倒數計時器
    end
```

### 提示詞管理流程

```mermaid
sequenceDiagram
    participant User as 用戶
    participant UI as 設定界面
    participant PM as PromptManager
    participant Modal as PromptModal
    participant Storage as LocalStorage

    Note over User,Storage: 📝 新增提示詞
    User->>UI: 點擊「新增提示詞」
    UI->>Modal: showAddModal()
    Modal->>User: 顯示編輯表單
    User->>Modal: 輸入名稱和內容
    Modal->>PM: addPrompt(name, content)
    PM->>PM: 驗證數據和唯一性
    PM->>Storage: 保存到 localStorage
    PM->>UI: 觸發 onPromptsChange 回調
    UI->>UI: refreshPromptList()

    Note over User,Storage: ✏️ 編輯提示詞
    User->>UI: 點擊編輯按鈕
    UI->>Modal: showEditModal(prompt)
    Modal->>User: 顯示預填表單
    User->>Modal: 修改內容
    Modal->>PM: updatePrompt(id, name, content)
    PM->>Storage: 更新 localStorage
    PM->>UI: 觸發回調更新界面

    Note over User,Storage: 🎯 使用提示詞
    User->>UI: 在輸入區點擊提示詞按鈕
    UI->>PM: getPromptsSortedByUsage()
    PM-->>UI: 返回排序後列表
    UI->>Modal: showSelectModal(prompts)
    User->>Modal: 選擇提示詞
    Modal->>PM: usePrompt(id)
    PM->>Storage: 更新使用記錄
    Modal->>UI: 填入提示詞內容
```

### 會話管理流程

```mermaid
sequenceDiagram
    participant AI as AI 助手
    participant Server as MCP 服務器
    participant SM as SessionManager
    participant SDM as SessionDataManager
    participant UI as 前端界面

    Note over AI,UI: 📊 會話生命週期管理
    AI->>Server: interactive_feedback()
    Server->>SM: createSession()
    SM->>SDM: addCurrentSession()
    SDM->>UI: 更新會話顯示

    Note over AI,UI: 📝 用戶回饋處理
    UI->>Server: submit_feedback
    Server->>SM: processFeedback()
    SM->>SDM: updateSessionStatus()
    SDM->>SDM: 記錄回饋數據
    SM->>AI: 返回回饋結果

    Note over AI,UI: 📚 會話歷史管理
    SM->>SDM: addSessionToHistory()
    SDM->>SDM: 檢查完成狀態
    alt 會話已完成
        SDM->>SDM: 加入歷史記錄
        SDM->>SDM: updateStats()
        SDM->>UI: 觸發 onHistoryChange
    else 會話未完成
        SDM->>SDM: 跳過歷史記錄
    end

    Note over AI,UI: 🔍 歷史查詢
    UI->>SDM: getSessionHistory()
    SDM-->>UI: 返回歷史列表
    UI->>SDM: getSessionStats()
    SDM-->>UI: 返回統計數據
```

## 📊 狀態同步機制

### WebSocket 訊息類型

```mermaid
graph LR
    subgraph "服務器 → 客戶端"
        CE[connection_established<br/>連接建立]
        SU[session_updated<br/>會話更新]
        FR[feedback_received<br/>回饋確認]
        ST[status_update<br/>狀態更新]
        ASS[auto_submit_status<br/>自動提交狀態]
        SH[session_history<br/>會話歷史]
    end

    subgraph "客戶端 → 服務器"
        SF[submit_feedback<br/>提交回饋]
        HB[heartbeat<br/>心跳檢測]
        LS[language_switch<br/>語言切換]
        PM[prompt_management<br/>提示詞管理]
        ASC[auto_submit_control<br/>自動提交控制]
        SM[session_management<br/>會話管理]
    end
```

### 狀態轉換圖

```mermaid
stateDiagram-v2
    [*] --> WAITING: 會話創建/更新
    WAITING --> AUTO_SUBMIT_READY: 自動提交條件滿足
    AUTO_SUBMIT_READY --> AUTO_SUBMIT_COUNTDOWN: 啟動倒數計時
    AUTO_SUBMIT_COUNTDOWN --> FEEDBACK_PROCESSING: 自動提交執行
    WAITING --> FEEDBACK_PROCESSING: 用戶手動提交回饋
    FEEDBACK_PROCESSING --> FEEDBACK_SUBMITTED: 處理完成
    FEEDBACK_SUBMITTED --> WAITING: 新會話更新
    FEEDBACK_SUBMITTED --> [*]: 會話結束

    AUTO_SUBMIT_COUNTDOWN --> WAITING: 用戶取消自動提交
    WAITING --> ERROR: 連接錯誤
    FEEDBACK_PROCESSING --> ERROR: 處理錯誤
    AUTO_SUBMIT_COUNTDOWN --> ERROR: 自動提交錯誤
    ERROR --> WAITING: 錯誤恢復
    ERROR --> [*]: 致命錯誤

    note right of AUTO_SUBMIT_READY
        檢查自動提交設定：
        - 功能已啟用
        - 已選擇提示詞
        - 當前狀態為等待回饋
    end note

    note right of AUTO_SUBMIT_COUNTDOWN
        倒數計時狀態：
        - 顯示剩餘時間
        - 允許用戶取消
        - 時間到自動提交
    end note
```

## 🛡️ 錯誤處理和恢復

### 連接斷線處理
```javascript
// WebSocket 重連機制
function handleWebSocketClose() {
    console.log('WebSocket 連接已關閉，嘗試重連...');

    setTimeout(() => {
        initWebSocket();
    }, 3000); // 3秒後重連
}

// 心跳檢測
setInterval(() => {
    if (websocket && websocket.readyState === WebSocket.OPEN) {
        websocket.send(JSON.stringify({
            type: 'heartbeat',
            timestamp: Date.now()
        }));
    }
}, 30000); // 每30秒發送心跳
```

### 超時處理
```python
async def wait_for_feedback(self, timeout: int = 600):
    try:
        await asyncio.wait_for(
            self.feedback_completed.wait(),
            timeout=timeout
        )
        return self.get_feedback_result()
    except asyncio.TimeoutError:
        raise TimeoutError(f"等待用戶回饋超時 ({timeout}秒)")
```

## 🎯 性能優化

### 連接復用
- **WebSocket 連接保持**: 避免重複建立連接
- **會話狀態繼承**: 新會話繼承舊會話的連接
- **智能瀏覽器開啟**: 檢測活躍標籤頁，避免重複開啟

### 資源管理
- **自動清理機制**: 超時會話自動清理
- **內存優化**: 單一活躍會話模式
- **進程管理**: 優雅的進程啟動和關閉

## 🔒 安全性考量

### 數據安全
- **本地綁定**: 服務器只綁定 127.0.0.1，減少攻擊面
- **輸入驗證**: 嚴格的參數類型檢查和數據清理
- **文件上傳安全**: 圖片格式驗證和大小限制
- **命令執行限制**: 在專案目錄內執行，防止路徑遍歷

### 網路安全
- **WebSocket 驗證**: 連接來源驗證
- **CORS 控制**: 限制跨域請求來源
- **超時保護**: 防止長時間佔用資源
- **錯誤信息過濾**: 避免敏感信息洩露

## 🚀 性能優化總結

### 連接復用優勢
- **減少 60% 啟動時間**: 避免重複建立服務器和瀏覽器
- **降低 40% 記憶體使用**: 單一活躍會話模式
- **提升用戶體驗**: 無縫會話切換，保持操作狀態
- **減少網路開銷**: WebSocket 連接保持和復用

### 資源管理效率
- **智能清理**: 自動檢測和清理過期資源
- **動態埠分配**: 避免埠衝突，支援並行開發
- **錯誤恢復**: 優雅的錯誤處理和自動重連
- **跨平台適配**: 統一的環境檢測和適配機制

---

## 📚 相關文檔

- **[系統架構總覽](./system-overview.md)** - 了解整體架構設計理念和技術棧
- **[組件詳細說明](./component-details.md)** - 深入了解各層組件的具體實現
- **[API 參考文檔](./api-reference.md)** - 完整的 API 端點和參數說明
- **[部署指南](./deployment-guide.md)** - 環境配置和部署最佳實踐

---

**版本**: 2.3.0
**最後更新**: 2024年12月
**維護者**: Minidoracat
**架構類型**: Web-Only 四層架構
**核心特性**: 持久化會話、智能環境適配、無縫狀態切換
