diff --git a/src/mcp_feedback_enhanced/__main__.py b/src/mcp_feedback_enhanced/__main__.py index 482b3ef..f8d53f4 100644 --- a/src/mcp_feedback_enhanced/__main__.py +++ b/src/mcp_feedback_enhanced/__main__.py @@ -13,6 +13,7 @@ MCP Interactive Feedback Enhanced - 主程式入口 import sys import argparse +import os def main(): """主程式入口點""" @@ -56,6 +57,9 @@ def run_server(): def run_tests(args): """執行測試""" + # 啟用調試模式以顯示測試過程 + os.environ["MCP_DEBUG"] = "true" + if args.web: print("🧪 執行 Web UI 測試...") from .test_web_ui import test_web_ui, interactive_demo diff --git a/src/mcp_feedback_enhanced/feedback_ui.py b/src/mcp_feedback_enhanced/feedback_ui.py index c0d885f..a638d7a 100644 --- a/src/mcp_feedback_enhanced/feedback_ui.py +++ b/src/mcp_feedback_enhanced/feedback_ui.py @@ -745,6 +745,24 @@ class FeedbackWindow(QMainWindow): if hasattr(self, 'summary_title'): self.summary_title.setText(t('ai_summary')) + # 更新摘要內容(如果是測試摘要) + if hasattr(self, 'summary_text'): + # 檢查是否為測試摘要,需要動態翻譯 + if self._is_test_summary(): + # 判斷是哪種測試類型並重新獲取翻譯 + if '圖片預覽' in self.summary or 'Image Preview' in self.summary or '图片预览' in self.summary: + # Qt GUI 測試 + translated_summary = t('test.qtGuiSummary') + elif 'Web UI' in self.summary: + # Web UI 測試 + translated_summary = t('test.webUiSummary') + else: + translated_summary = self.summary + + self.summary_text.setPlainText(translated_summary) + # 更新儲存的摘要以保持一致 + self.summary = translated_summary + # 更新專案目錄標籤 if hasattr(self, 'project_label'): self.project_label.setText(f"{t('project_directory')}: {self.project_dir}") @@ -780,6 +798,38 @@ class FeedbackWindow(QMainWindow): if hasattr(self, 'output_title'): self.output_title.setText(t('command_output')) + def _is_test_summary(self) -> bool: + """檢查是否為測試摘要,使用更嚴格的檢測邏輯""" + # 更嚴格的測試摘要特徵組合檢測 + test_patterns = [ + # Qt GUI 測試特徵 + ('測試 Qt GUI 功能', '🎯 **功能測試項目'), + ('Test Qt GUI Functionality', '🎯 **Test Items'), + ('测试 Qt GUI 功能', '🎯 **功能测试项目'), + + # Web UI 測試特徵 + ('測試 Web UI 功能', '🎯 **功能測試項目'), + ('Test Web UI Functionality', '🎯 **Test Items'), + ('测试 Web UI 功能', '🎯 **功能测试项目'), + + # 具體的測試項目描述 + ('圖片上傳和預覽', '智能 Ctrl+V 圖片貼上'), + ('Image upload and preview', 'Smart Ctrl+V image paste'), + ('图片上传和预览', '智能 Ctrl+V 图片粘贴'), + + # WebSocket 和服務器啟動描述 + ('WebSocket 即時通訊', 'Web UI 服務器啟動'), + ('WebSocket real-time communication', 'Web UI server startup'), + ('WebSocket 即时通讯', 'Web UI 服务器启动') + ] + + # 必須同時包含模式中的兩個特徵才認為是測試摘要 + for pattern1, pattern2 in test_patterns: + if pattern1 in self.summary and pattern2 in self.summary: + return True + + return False + def _update_image_upload_texts(self) -> None: """更新圖片上傳元件的文字""" if hasattr(self, 'image_upload'): @@ -812,12 +862,12 @@ class FeedbackWindow(QMainWindow): summary_layout.addLayout(header_layout) - # 摘要內容(可滾動的文本區域) - summary_text = QTextEdit() - summary_text.setPlainText(self.summary) - summary_text.setReadOnly(True) - summary_text.setMaximumHeight(120) - summary_layout.addWidget(summary_text) + # 摘要內容(可滾動的文本區域)- 儲存為實例變數以支援動態更新 + self.summary_text = QTextEdit() + self.summary_text.setPlainText(self.summary) + self.summary_text.setReadOnly(True) + self.summary_text.setMaximumHeight(120) + summary_layout.addWidget(self.summary_text) layout.addWidget(summary_group) diff --git a/src/mcp_feedback_enhanced/i18n.py b/src/mcp_feedback_enhanced/i18n.py index 1febbc3..9755ee7 100644 --- a/src/mcp_feedback_enhanced/i18n.py +++ b/src/mcp_feedback_enhanced/i18n.py @@ -268,6 +268,10 @@ class I18nManager: 'language_zh_tw': 'languageNames.zhTw', 'language_en': 'languageNames.en', 'language_zh_cn': 'languageNames.zhCn', + + # 測試 + 'test_qt_gui_summary': 'test.qtGuiSummary', + 'test_web_ui_summary': 'test.webUiSummary', } # 檢查是否有對應的新鍵 diff --git a/src/mcp_feedback_enhanced/locales/en/translations.json b/src/mcp_feedback_enhanced/locales/en/translations.json index 357bf3b..8f414da 100644 --- a/src/mcp_feedback_enhanced/locales/en/translations.json +++ b/src/mcp_feedback_enhanced/locales/en/translations.json @@ -82,5 +82,9 @@ "zhTw": "繁體中文", "en": "English", "zhCn": "简体中文" + }, + "test": { + "qtGuiSummary": "🎯 Image Preview and Window Adjustment Test\n\nThis is a test session to verify the following features:\n\n✅ Test Items:\n1. Image upload and preview functionality\n2. Image X delete button in top-right corner\n3. Free window resizing\n4. Flexible splitter adjustment\n5. Dynamic layout of all areas\n6. Smart Ctrl+V image paste functionality\n\n📋 Test Steps:\n1. Try uploading some images (drag & drop, file selection, clipboard)\n2. Check if image preview displays correctly\n3. Click the X button in the top-right corner of images to delete them\n4. Try resizing the window, check if it can be freely adjusted\n5. Drag the splitter to adjust area sizes\n6. Press Ctrl+V in the text box to test smart paste functionality\n7. Provide any feedback or issues found\n\nPlease test these features and provide feedback!", + "webUiSummary": "Test Web UI Functionality\n\n🎯 **Test Items:**\n- Web UI server startup and operation\n- WebSocket real-time communication\n- Feedback submission functionality\n- Image upload and preview\n- Command execution functionality\n- Smart Ctrl+V image paste\n- Multi-language interface switching\n\n📋 **Test Steps:**\n1. Test image upload (drag & drop, file selection, clipboard)\n2. Press Ctrl+V in text box to test smart paste\n3. Try switching languages (Traditional Chinese/Simplified Chinese/English)\n4. Test command execution functionality\n5. Submit feedback and images\n\nPlease test these features and provide feedback!" } } \ No newline at end of file diff --git a/src/mcp_feedback_enhanced/locales/zh-CN/translations.json b/src/mcp_feedback_enhanced/locales/zh-CN/translations.json index 41d4934..b8159dc 100644 --- a/src/mcp_feedback_enhanced/locales/zh-CN/translations.json +++ b/src/mcp_feedback_enhanced/locales/zh-CN/translations.json @@ -82,5 +82,9 @@ "zhTw": "繁體中文", "en": "English", "zhCn": "简体中文" + }, + "test": { + "qtGuiSummary": "🎯 图片预览和窗口调整测试\n\n这是一个测试会话,用于验证以下功能:\n\n✅ 功能测试项目:\n1. 图片上传和预览功能\n2. 图片右上角X删除按钮\n3. 窗口自由调整大小\n4. 分割器的灵活调整\n5. 各区域的动态布局\n6. 智能 Ctrl+V 图片粘贴功能\n\n📋 测试步骤:\n1. 尝试上传一些图片(拖拽、文件选择、剪贴板)\n2. 检查图片预览是否正常显示\n3. 点击图片右上角的X按钮删除图片\n4. 尝试调整窗口大小,检查是否可以自由调整\n5. 拖动分割器调整各区域大小\n6. 在文本框内按 Ctrl+V 测试智能粘贴功能\n7. 提供任何回馈或发现的问题\n\n请测试这些功能并提供回馈!", + "webUiSummary": "测试 Web UI 功能\n\n🎯 **功能测试项目:**\n- Web UI 服务器启动和运行\n- WebSocket 即时通讯\n- 回馈提交功能\n- 图片上传和预览\n- 命令执行功能\n- 智能 Ctrl+V 图片粘贴\n- 多语言界面切换\n\n📋 **测试步骤:**\n1. 测试图片上传(拖拽、选择文件、剪贴板)\n2. 在文本框内按 Ctrl+V 测试智能粘贴\n3. 尝试切换语言(繁中/简中/英文)\n4. 测试命令执行功能\n5. 提交回馈和图片\n\n请测试这些功能并提供回馈!" } } \ No newline at end of file diff --git a/src/mcp_feedback_enhanced/locales/zh-TW/translations.json b/src/mcp_feedback_enhanced/locales/zh-TW/translations.json index ba69ad0..9ddd8dc 100644 --- a/src/mcp_feedback_enhanced/locales/zh-TW/translations.json +++ b/src/mcp_feedback_enhanced/locales/zh-TW/translations.json @@ -77,10 +77,14 @@ "fileTooLarge": "文件過大(最大 1MB)" }, "aiSummary": "AI 工作摘要", - "languageSelector": "🌐 語言", + "languageSelector": "🌐 語言選擇", "languageNames": { "zhTw": "繁體中文", "en": "English", "zhCn": "简体中文" + }, + "test": { + "qtGuiSummary": "🎯 圖片預覽和視窗調整測試\n\n這是一個測試會話,用於驗證以下功能:\n\n✅ 功能測試項目:\n1. 圖片上傳和預覽功能\n2. 圖片右上角X刪除按鈕\n3. 視窗自由調整大小\n4. 分割器的靈活調整\n5. 各區域的動態佈局\n6. 智能 Ctrl+V 圖片貼上功能\n\n📋 測試步驟:\n1. 嘗試上傳一些圖片(拖拽、文件選擇、剪貼板)\n2. 檢查圖片預覽是否正常顯示\n3. 點擊圖片右上角的X按鈕刪除圖片\n4. 嘗試調整視窗大小,檢查是否可以自由調整\n5. 拖動分割器調整各區域大小\n6. 在文字框內按 Ctrl+V 測試智能貼上功能\n7. 提供任何回饋或發現的問題\n\n請測試這些功能並提供回饋!", + "webUiSummary": "測試 Web UI 功能\n\n🎯 **功能測試項目:**\n- Web UI 服務器啟動和運行\n- WebSocket 即時通訊\n- 回饋提交功能\n- 圖片上傳和預覽\n- 命令執行功能\n- 智能 Ctrl+V 圖片貼上\n- 多語言介面切換\n\n📋 **測試步驟:**\n1. 測試圖片上傳(拖拽、選擇檔案、剪貼簿)\n2. 在文字框內按 Ctrl+V 測試智能貼上\n3. 嘗試切換語言(繁中/簡中/英文)\n4. 測試命令執行功能\n5. 提交回饋和圖片\n\n請測試這些功能並提供回饋!" } } \ No newline at end of file diff --git a/src/mcp_feedback_enhanced/server.py b/src/mcp_feedback_enhanced/server.py index 0df2673..b3d83c8 100644 --- a/src/mcp_feedback_enhanced/server.py +++ b/src/mcp_feedback_enhanced/server.py @@ -373,8 +373,7 @@ def launch_gui(project_dir: str, summary: str) -> dict: async def interactive_feedback( project_directory: Annotated[str, Field(description="專案目錄路徑")] = ".", summary: Annotated[str, Field(description="AI 工作完成的摘要說明")] = "我已完成了您請求的任務。", - timeout: Annotated[int, Field(description="等待用戶回饋的超時時間(秒)")] = 600, - force_web_ui: Annotated[bool, Field(description="強制使用 Web UI(用於測試或特殊需求)")] = False + timeout: Annotated[int, Field(description="等待用戶回饋的超時時間(秒)")] = 600 ) -> List: """ 收集用戶的互動回饋,支援文字和圖片 @@ -382,7 +381,7 @@ async def interactive_feedback( 此工具會自動偵測運行環境: - 遠端環境:使用 Web UI - 本地環境:使用 Qt GUI - - 可透過 force_web_ui 參數或 FORCE_WEB 環境變數強制使用 Web UI + - 可透過 FORCE_WEB 環境變數強制使用 Web UI 用戶可以: 1. 執行命令來驗證結果 @@ -390,6 +389,10 @@ async def interactive_feedback( 3. 上傳圖片作為回饋 4. 查看 AI 的工作摘要 + 介面控制(按優先級排序): + 1. **FORCE_WEB 環境變數**:在 mcp.json 中設置 "FORCE_WEB": "true" + 2. 自動檢測:根據運行環境自動選擇 + 調試模式: - 設置環境變數 MCP_DEBUG=true 可啟用詳細調試輸出 - 生產環境建議關閉調試模式以避免輸出干擾 @@ -398,26 +401,26 @@ async def interactive_feedback( project_directory: 專案目錄路徑 summary: AI 工作完成的摘要說明 timeout: 等待用戶回饋的超時時間(秒),預設為 600 秒(10 分鐘) - force_web_ui: 強制使用 Web UI,即使在本地環境也使用 Web UI(用於測試) Returns: List: 包含 TextContent 和 MCPImage 對象的列表 """ - # 檢查環境變數,如果設定了 FORCE_WEB 就覆蓋 force_web_ui 參數 + # 檢查環境變數 FORCE_WEB + force_web = False env_force_web = os.getenv("FORCE_WEB", "").lower() if env_force_web in ("true", "1", "yes", "on"): - force_web_ui = True + force_web = True debug_log("環境變數 FORCE_WEB 已啟用,強制使用 Web UI") elif env_force_web in ("false", "0", "no", "off"): - force_web_ui = False + force_web = False debug_log("環境變數 FORCE_WEB 已停用,使用預設邏輯") # 環境偵測 is_remote = is_remote_environment() can_gui = can_use_gui() - use_web_ui = is_remote or not can_gui or force_web_ui + use_web_ui = is_remote or not can_gui or force_web - debug_log(f"環境偵測結果 - 遠端: {is_remote}, GUI 可用: {can_gui}, 強制 Web UI: {force_web_ui}") + debug_log(f"環境偵測結果 - 遠端: {is_remote}, GUI 可用: {can_gui}, 強制 Web UI: {force_web}") debug_log(f"決定使用介面: {'Web UI' if use_web_ui else 'Qt GUI'}") try: diff --git a/src/mcp_feedback_enhanced/static/i18n.js b/src/mcp_feedback_enhanced/static/i18n.js index a913792..7c37f62 100644 --- a/src/mcp_feedback_enhanced/static/i18n.js +++ b/src/mcp_feedback_enhanced/static/i18n.js @@ -26,185 +26,27 @@ class I18nManager { } /** - * 獲取內嵌的備用翻譯 + * 獲取內嵌的備用翻譯(僅保留基本錯誤訊息) */ _getEmbeddedTranslations() { return { 'zh-TW': { - app: { - title: 'Interactive Feedback MCP', - projectDirectory: '專案目錄', - language: '語言' - }, - tabs: { - feedback: '💬 回饋', - command: '⚡ 命令' - }, - feedback: { - title: '💬 您的回饋', - description: '請在這裡輸入您的回饋、建議或問題。您的意見將幫助 AI 更好地理解您的需求。', - placeholder: '請在這裡輸入您的回饋、建議或問題...\n\n💡 小提示:\n• 按 Ctrl+Enter 可快速提交回饋\n• 按 Ctrl+V 可直接貼上剪貼簿圖片' - }, - command: { - title: '⚡ 命令執行', - description: '您可以在此執行系統命令來驗證結果或獲取更多資訊。', - placeholder: '輸入要執行的命令...', - output: '命令輸出' - }, - images: { - title: '🖼️ 圖片附件(可選)', - status: '已選擇 {count} 張圖片', - statusWithSize: '已選擇 {count} 張圖片 (總計 {size})', - dragHint: '🎯 拖拽圖片到這裡 或 按 Ctrl+V 貼上剪貼簿圖片 (PNG、JPG、JPEG、GIF、BMP、WebP)', - deleteConfirm: '確定要移除圖片 "{filename}" 嗎?', - deleteTitle: '確認刪除' - }, - buttons: { - selectFiles: '📁 選擇文件', - pasteClipboard: '📋 剪貼板', - clearAll: '✕ 清除', - runCommand: '▶️ 執行', - submitFeedback: '✅ 提交回饋', - cancel: '❌ 取消' - }, - status: { - uploading: '上傳中...', - uploadSuccess: '上傳成功', - uploadFailed: '上傳失敗', - commandRunning: '命令執行中...', - commandFinished: '命令執行完成', - pasteSuccess: '已從剪貼板貼上圖片', - pasteFailed: '無法從剪貼板獲取圖片', - paste_no_image: '剪貼簿中沒有圖片可貼上', - paste_image_from_textarea: '已將圖片從文字框智能貼到圖片區域', - invalidFileType: '不支援的文件類型', - fileTooLarge: '文件過大(最大 1MB)' - }, - aiSummary: '📋 AI 工作摘要', - languageSelector: '🌐 語言選擇', - languageNames: { - zhTw: '繁體中文', - en: 'English', - zhCn: '简体中文' - } + app: { title: 'Interactive Feedback MCP' }, + loading: '載入中...', + error: '載入失敗', + retry: '重試' }, - 'en': { - app: { - title: 'Interactive Feedback MCP', - projectDirectory: 'Project Directory', - language: 'Language' - }, - tabs: { - feedback: '💬 Feedback', - command: '⚡ Commands' - }, - feedback: { - title: '💬 Your Feedback', - description: 'Please enter your feedback, suggestions, or questions here. Your input helps AI better understand your needs.', - placeholder: 'Please enter your feedback, suggestions, or questions here...\n\n💡 Tips:\n• Press Ctrl+Enter to submit quickly\n• Press Ctrl+V to paste images from clipboard' - }, - command: { - title: '⚡ Command Execution', - description: 'You can execute system commands here to verify results or get additional information.', - placeholder: 'Enter command to execute...', - output: 'Command Output' - }, - images: { - title: '🖼️ Image Attachments (Optional)', - status: '{count} images selected', - statusWithSize: '{count} images selected (Total {size})', - dragHint: '🎯 Drag images here or press Ctrl+V to paste from clipboard (PNG, JPG, JPEG, GIF, BMP, WebP)', - deleteConfirm: 'Are you sure you want to remove image "{filename}"?', - deleteTitle: 'Confirm Delete' - }, - buttons: { - selectFiles: '📁 Select Files', - pasteClipboard: '📋 Clipboard', - clearAll: '✕ Clear', - runCommand: '▶️ Run', - submitFeedback: '✅ Submit Feedback', - cancel: '❌ Cancel' - }, - status: { - uploading: 'Uploading...', - uploadSuccess: 'Upload successful', - uploadFailed: 'Upload failed', - commandRunning: 'Command running...', - commandFinished: 'Command finished', - pasteSuccess: 'Image pasted from clipboard', - pasteFailed: 'Failed to get image from clipboard', - paste_no_image: 'No image to paste from clipboard', - paste_image_from_textarea: 'Image pasted from text area to image area', - invalidFileType: 'Unsupported file type', - fileTooLarge: 'File too large (max 1MB)' - }, - aiSummary: '📋 AI Work Summary', - languageSelector: '🌐 Language', - languageNames: { - zhTw: '繁體中文', - en: 'English', - zhCn: '简体中文' - } + app: { title: 'Interactive Feedback MCP' }, + loading: 'Loading...', + error: 'Loading failed', + retry: 'Retry' }, - 'zh-CN': { - app: { - title: 'Interactive Feedback MCP', - projectDirectory: '项目目录', - language: '语言' - }, - tabs: { - feedback: '💬 反馈', - command: '⚡ 命令' - }, - feedback: { - title: '💬 您的反馈', - description: '请在这里输入您的反馈、建议或问题。您的意见将帮助 AI 更好地理解您的需求。', - placeholder: '请在这里输入您的反馈、建议或问题...\n\n💡 小提示:\n• 按 Ctrl+Enter 可快速提交反馈\n• 按 Ctrl+V 可直接贴上剪贴板图片' - }, - command: { - title: '⚡ 命令执行', - description: '您可以在此执行系统命令来验证结果或获取更多信息。', - placeholder: '输入要执行的命令...', - output: '命令输出' - }, - images: { - title: '🖼️ 图片附件(可选)', - status: '已选择 {count} 张图片', - statusWithSize: '已选择 {count} 张图片 (总计 {size})', - dragHint: '🎯 拖拽图片到这里 或 按 Ctrl+V 贴上剪贴板图片 (PNG、JPG、JPEG、GIF、BMP、WebP)', - deleteConfirm: '确定要移除图片 "{filename}" 吗?', - deleteTitle: '确认删除' - }, - buttons: { - selectFiles: '📁 选择文件', - pasteClipboard: '📋 剪贴板', - clearAll: '✕ 清除', - runCommand: '▶️ 执行', - submitFeedback: '✅ 提交反馈', - cancel: '❌ 取消' - }, - status: { - uploading: '上传中...', - uploadSuccess: '上传成功', - uploadFailed: '上传失败', - commandRunning: '命令执行中...', - commandFinished: '命令执行完成', - pasteSuccess: '已从剪贴板粘贴图片', - pasteFailed: '无法从剪贴板获取图片', - paste_no_image: '剪贴板中没有图片可粘贴', - paste_image_from_textarea: '已将图片从文字框智能贴到图片区域', - invalidFileType: '不支持的文件类型', - fileTooLarge: '文件过大(最大 1MB)' - }, - aiSummary: '📋 AI 工作摘要', - languageSelector: '🌐 语言选择', - languageNames: { - zhTw: '繁體中文', - en: 'English', - zhCn: '简体中文' - } + app: { title: 'Interactive Feedback MCP' }, + loading: '加载中...', + error: '加载失败', + retry: '重试' } }; } diff --git a/src/mcp_feedback_enhanced/templates/feedback.html b/src/mcp_feedback_enhanced/templates/feedback.html index 0434dc9..4479969 100644 --- a/src/mcp_feedback_enhanced/templates/feedback.html +++ b/src/mcp_feedback_enhanced/templates/feedback.html @@ -1,5 +1,6 @@ +
@@ -103,7 +104,8 @@ } } - .feedback-section, .summary-section { + .feedback-section, + .summary-section { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; @@ -180,7 +182,8 @@ color: var(--text-primary); } - .text-input, .command-input { + .text-input, + .command-input { width: 100%; background: var(--bg-tertiary); border: 1px solid var(--border-color); @@ -199,13 +202,15 @@ font-family: 'Consolas', 'Monaco', 'Courier New', monospace; } - .text-input:focus, .command-input:focus { + .text-input:focus, + .command-input:focus { outline: none; border-color: var(--accent-color); box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2); } - .text-input::placeholder, .command-input::placeholder { + .text-input::placeholder, + .command-input::placeholder { color: var(--text-secondary); } @@ -333,7 +338,7 @@ border-radius: 6px; padding: 15px; background: var(--bg-tertiary); - background-image: + background-image: linear-gradient(90deg, rgba(70, 70, 71, 0.1) 1px, transparent 1px), linear-gradient(rgba(70, 70, 71, 0.1) 1px, transparent 1px); background-size: 120px 120px; @@ -509,11 +514,11 @@ .container { padding: 15px; } - + .header-content { padding: 0 15px; } - + .image-preview-area { grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: 10px; @@ -553,14 +558,14 @@ flex-direction: column; gap: 15px; } - + .image-preview-area { grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); gap: 8px; padding: 10px; max-height: 300px; } - + .image-preview { height: 80px; } @@ -572,7 +577,7 @@ gap: 15px; padding: 20px; } - + .image-preview { height: 120px; } @@ -602,6 +607,7 @@ } +