diff --git a/src/mcp_feedback_enhanced/web/locales/en/translation.json b/src/mcp_feedback_enhanced/web/locales/en/translation.json index 863cc04..1c29666 100644 --- a/src/mcp_feedback_enhanced/web/locales/en/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/en/translation.json @@ -91,7 +91,23 @@ "running": "Running...", "completed": "Completed", "error": "Execution Error", - "history": "Command History" + "history": "Command History", + "autoCommand": { + "title": "🤖 Auto Command Settings", + "description": "Configure commands to execute automatically at specific times", + "enabled": "Enable Auto Commands", + "onNewSession": "Execute on New Session", + "onNewSessionPlaceholder": "e.g., pwd or git status", + "onFeedbackSubmit": "Execute on Feedback Submit", + "onFeedbackSubmitPlaceholder": "e.g., echo 'Feedback submitted'", + "testOnNewSession": "Test New Session Command", + "testOnFeedbackSubmit": "Test Feedback Submit Command", + "help": "These commands will execute automatically at the corresponding times. Leave empty to skip execution." + }, + "autoSettings": { + "exampleNewSession": "💡 Example: pwd, git status, ls -la", + "exampleFeedback": "💡 Example: date, echo \"Done\", git log -1" + } }, "combined": { "summaryTitle": "📋 AI Work Summary", diff --git a/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json b/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json index e5abd99..81a7769 100644 --- a/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json @@ -91,7 +91,23 @@ "running": "执行中...", "completed": "执行完成", "error": "执行错误", - "history": "命令历史" + "history": "命令历史", + "autoCommand": { + "title": "🤖 自动执行命令设置", + "description": "设置在特定时机自动执行的命令", + "enabled": "启用自动执行命令", + "onNewSession": "新会话建立时执行", + "onNewSessionPlaceholder": "例如:pwd 或 git status", + "onFeedbackSubmit": "提交反馈后执行", + "onFeedbackSubmitPlaceholder": "例如:echo '反馈已提交'", + "testOnNewSession": "测试新会话命令", + "testOnFeedbackSubmit": "测试反馈提交命令", + "help": "这些命令会在对应的时机自动执行。留空表示不执行任何命令。" + }, + "autoSettings": { + "exampleNewSession": "💡 示例:pwd, git status, ls -la", + "exampleFeedback": "💡 示例:date, echo \"Done\", git log -1" + } }, "combined": { "summaryTitle": "📋 AI 工作摘要", diff --git a/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json b/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json index 9ff9506..bd04817 100644 --- a/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json @@ -96,7 +96,23 @@ "running": "執行中...", "completed": "執行完成", "error": "執行錯誤", - "history": "命令歷史" + "history": "命令歷史", + "autoCommand": { + "title": "🤖 自動執行命令設定", + "description": "設定在特定時機自動執行的命令", + "enabled": "啟用自動執行命令", + "onNewSession": "新會話建立時執行", + "onNewSessionPlaceholder": "例如:pwd 或 git status", + "onFeedbackSubmit": "提交回饋後執行", + "onFeedbackSubmitPlaceholder": "例如:echo '回饋已提交'", + "testOnNewSession": "測試新會話命令", + "testOnFeedbackSubmit": "測試回饋提交命令", + "help": "這些命令會在對應的時機自動執行。留空表示不執行任何命令。" + }, + "autoSettings": { + "exampleNewSession": "💡 範例:pwd, git status, ls -la", + "exampleFeedback": "💡 範例:date, echo \"Done\", git log -1" + } }, "combined": { "summaryTitle": "📋 AI 工作摘要", diff --git a/src/mcp_feedback_enhanced/web/static/css/styles.css b/src/mcp_feedback_enhanced/web/static/css/styles.css index ee08b4d..f96dbe7 100644 --- a/src/mcp_feedback_enhanced/web/static/css/styles.css +++ b/src/mcp_feedback_enhanced/web/static/css/styles.css @@ -2075,3 +2075,129 @@ textarea:-ms-input-placeholder, 100% { opacity: 1; } } +/* 自動執行命令設定樣式 */ +.command-auto-settings { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: 8px; + padding: 16px; + margin: 16px 0; +} + +.command-auto-settings .settings-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; +} + +.command-auto-settings .settings-title { + margin: 0; + font-size: 16px; + font-weight: 600; + color: var(--text-primary); +} + +.command-auto-settings .settings-content { + transition: opacity 0.3s ease; +} + +.command-auto-settings .settings-content.disabled { + opacity: 0.5; + pointer-events: none; +} + +.auto-command-item { + margin-bottom: 20px; + padding: 12px; + background: var(--bg-tertiary); + border-radius: 6px; + border: 1px solid var(--border-color); +} + +.auto-command-item:last-child { + margin-bottom: 0; +} + +.command-label { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 8px; + font-weight: 500; + color: var(--text-primary); +} + +.command-icon { + font-size: 18px; +} + +.command-input-wrapper { + display: flex; + align-items: center; + margin: 8px 0; + background: var(--bg-primary); + border: 1px solid var(--border-color); + border-radius: 4px; + padding: 0 12px; + transition: border-color 0.3s ease; +} + +.command-input-wrapper:focus-within { + border-color: var(--accent-color); +} + +.command-prefix { + color: var(--accent-color); + font-weight: bold; + margin-right: 8px; + font-family: 'Consolas', 'Monaco', 'Courier New', monospace; +} + +.auto-command-input { + flex: 1; + border: none; + background: transparent; + padding: 8px 0; + color: var(--text-primary); + font-family: 'Consolas', 'Monaco', 'Courier New', monospace; + font-size: 14px; + outline: none; +} + +.command-actions { + display: flex; + align-items: center; + gap: 12px; + margin-top: 8px; +} + +.btn-test { + background: var(--info-color); + color: white; + border: none; + padding: 4px 12px; + border-radius: 4px; + font-size: 12px; + cursor: pointer; + transition: background 0.3s ease; +} + +.btn-test:hover { + background: #1976d2; +} + +.command-hint { + color: var(--text-secondary); + font-size: 12px; +} + +.btn-small { + padding: 4px 8px; + font-size: 12px; + border-radius: 4px; + border: none; + cursor: pointer; + transition: all 0.3s ease; +} + diff --git a/src/mcp_feedback_enhanced/web/static/js/app.js b/src/mcp_feedback_enhanced/web/static/js/app.js index 2d2dd3e..6809abd 100644 --- a/src/mcp_feedback_enhanced/web/static/js/app.js +++ b/src/mcp_feedback_enhanced/web/static/js/app.js @@ -367,6 +367,10 @@ }); } + + // 自動命令設定相關事件 + self.setupAutoCommandEvents(); + // 設置設定管理器的事件監聽器 self.settingsManager.setupEventListeners(); @@ -693,6 +697,14 @@ console.log('🖥️ 收到桌面關閉請求'); this.handleDesktopCloseRequest(data); break; + case 'notification': + console.log('📢 收到通知:', data); + // 處理 FEEDBACK_SUBMITTED 通知 + if (data.code === 'session.feedbackSubmitted' || data.code === 'FEEDBACK_SUBMITTED' || data.code === 201) { + console.log('✅ 回饋提交成功通知'); + this.handleFeedbackReceived(data); + } + break; } }; @@ -751,6 +763,9 @@ // 更新 AI 摘要區域顯示「已送出反饋」狀態 const submittedMessage = window.i18nManager ? window.i18nManager.t('feedback.submittedWaiting') : '已送出反饋,等待下次 MCP 調用...'; this.updateSummaryStatus(submittedMessage); + + // 執行提交回饋後的自動命令 + this.executeAutoCommandOnFeedbackSubmit(); // 刷新會話列表以顯示最新狀態 this.refreshSessionList(); @@ -815,6 +830,9 @@ if (this.audioManager) { this.audioManager.playNotification(); } + + // 執行新會話自動命令 + this.executeAutoCommandOnNewSession(); // 發送瀏覽器通知 if (this.notificationManager && data.session_info) { @@ -1451,6 +1469,68 @@ } }; + /** + * 執行新會話自動命令 + */ + FeedbackApp.prototype.executeAutoCommandOnNewSession = function() { + if (!this.settingsManager) return; + + const settings = this.settingsManager.currentSettings; + if (!settings.autoCommandEnabled || !settings.commandOnNewSession) { + console.log('⏩ 新會話自動命令未啟用或未設定'); + return; + } + + const command = settings.commandOnNewSession.trim(); + if (!command) return; + + console.log('🚀 執行新會話自動命令:', command); + this.appendCommandOutput('🆕 [自動執行] $ ' + command + '\n'); + + // 使用 WebSocket 發送命令 + if (this.webSocketManager && this.webSocketManager.isConnected) { + console.log('📡 WebSocket 已連接,發送命令:', command); + this.webSocketManager.send({ + type: 'run_command', + command: command + }); + } else { + console.error('❌ 無法執行自動命令:WebSocket 未連接'); + this.appendCommandOutput('[錯誤] WebSocket 未連接,無法執行命令\n'); + } + }; + + /** + * 執行提交回饋後自動命令 + */ + FeedbackApp.prototype.executeAutoCommandOnFeedbackSubmit = function() { + if (!this.settingsManager) return; + + const settings = this.settingsManager.currentSettings; + if (!settings.autoCommandEnabled || !settings.commandOnFeedbackSubmit) { + console.log('⏩ 提交回饋後自動命令未啟用或未設定'); + return; + } + + const command = settings.commandOnFeedbackSubmit.trim(); + if (!command) return; + + console.log('🚀 執行提交回饋後自動命令:', command); + this.appendCommandOutput('✅ [自動執行] $ ' + command + '\n'); + + // 使用 WebSocket 發送命令 + if (this.webSocketManager && this.webSocketManager.isConnected) { + console.log('📡 WebSocket 已連接,發送命令:', command); + this.webSocketManager.send({ + type: 'run_command', + command: command + }); + } else { + console.error('❌ 無法執行自動命令:WebSocket 未連接'); + this.appendCommandOutput('[錯誤] WebSocket 未連接,無法執行命令\n'); + } + }; + /** * 更新摘要狀態 */ @@ -1461,6 +1541,127 @@ }); }; + /** + * 設置自動命令相關事件 + */ + FeedbackApp.prototype.setupAutoCommandEvents = function() { + const self = this; + + // 自動命令開關 + const autoCommandEnabled = window.MCPFeedback.Utils.safeQuerySelector('#autoCommandEnabled'); + if (autoCommandEnabled) { + // 載入設定 + if (this.settingsManager) { + autoCommandEnabled.checked = this.settingsManager.currentSettings.autoCommandEnabled; + this.updateAutoCommandUI(autoCommandEnabled.checked); + } + + autoCommandEnabled.addEventListener('change', function() { + const enabled = autoCommandEnabled.checked; + self.updateAutoCommandUI(enabled); + + if (self.settingsManager) { + self.settingsManager.saveSettings({ + autoCommandEnabled: enabled + }); + } + }); + } + + // 新會話命令輸入 + const commandOnNewSession = window.MCPFeedback.Utils.safeQuerySelector('#commandOnNewSession'); + if (commandOnNewSession) { + // 載入設定 + if (this.settingsManager) { + commandOnNewSession.value = this.settingsManager.currentSettings.commandOnNewSession || ''; + } + + commandOnNewSession.addEventListener('change', function() { + if (self.settingsManager) { + self.settingsManager.saveSettings({ + commandOnNewSession: commandOnNewSession.value + }); + } + }); + } + + // 提交回饋後命令輸入 + const commandOnFeedbackSubmit = window.MCPFeedback.Utils.safeQuerySelector('#commandOnFeedbackSubmit'); + if (commandOnFeedbackSubmit) { + // 載入設定 + if (this.settingsManager) { + commandOnFeedbackSubmit.value = this.settingsManager.currentSettings.commandOnFeedbackSubmit || ''; + } + + commandOnFeedbackSubmit.addEventListener('change', function() { + if (self.settingsManager) { + self.settingsManager.saveSettings({ + commandOnFeedbackSubmit: commandOnFeedbackSubmit.value + }); + } + }); + } + + // 測試執行按鈕 + const testNewSessionCommand = window.MCPFeedback.Utils.safeQuerySelector('#testNewSessionCommand'); + if (testNewSessionCommand) { + testNewSessionCommand.addEventListener('click', function() { + const command = commandOnNewSession ? commandOnNewSession.value.trim() : ''; + if (command) { + self.testCommand(command, '🆕 [測試] '); + } else { + window.MCPFeedback.Utils.showMessage('請先輸入命令', window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING); + } + }); + } + + const testFeedbackCommand = window.MCPFeedback.Utils.safeQuerySelector('#testFeedbackCommand'); + if (testFeedbackCommand) { + testFeedbackCommand.addEventListener('click', function() { + const command = commandOnFeedbackSubmit ? commandOnFeedbackSubmit.value.trim() : ''; + if (command) { + self.testCommand(command, '✅ [測試] '); + } else { + window.MCPFeedback.Utils.showMessage('請先輸入命令', window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING); + } + }); + } + }; + + /** + * 更新自動命令 UI 狀態 + */ + FeedbackApp.prototype.updateAutoCommandUI = function(enabled) { + const autoCommandContent = window.MCPFeedback.Utils.safeQuerySelector('#autoCommandContent'); + if (autoCommandContent) { + if (enabled) { + autoCommandContent.classList.remove('disabled'); + } else { + autoCommandContent.classList.add('disabled'); + } + } + }; + + /** + * 測試命令執行 + */ + FeedbackApp.prototype.testCommand = function(command, prefix) { + if (!command) return; + + console.log('🧪 測試執行命令:', command); + this.appendCommandOutput(prefix + '$ ' + command + '\n'); + + // 使用 WebSocket 發送命令 + if (this.webSocketManager && this.webSocketManager.isConnected) { + this.webSocketManager.send({ + type: 'run_command', + command: command + }); + } else { + this.appendCommandOutput('❌ WebSocket 未連接\n'); + } + }; + /** * 處理會話更新(來自自動刷新) */ diff --git a/src/mcp_feedback_enhanced/web/static/js/modules/settings-manager.js b/src/mcp_feedback_enhanced/web/static/js/modules/settings-manager.js index 0b76b86..1323406 100644 --- a/src/mcp_feedback_enhanced/web/static/js/modules/settings-manager.js +++ b/src/mcp_feedback_enhanced/web/static/js/modules/settings-manager.js @@ -53,7 +53,11 @@ combinedFeedbackTextHeight: 150, // combinedFeedbackText textarea 的高度(px) // 會話超時設定 sessionTimeoutEnabled: false, // 預設關閉 - sessionTimeoutSeconds: 3600 // 預設 1 小時(秒) + sessionTimeoutSeconds: 3600, // 預設 1 小時(秒) + // 自動執行命令設定 + autoCommandEnabled: true, // 是否啟用自動執行命令 + commandOnNewSession: '', // 新會話建立時執行的命令 + commandOnFeedbackSubmit: '' // 提交回饋後執行的命令 }; // 當前設定 diff --git a/src/mcp_feedback_enhanced/web/templates/feedback.html b/src/mcp_feedback_enhanced/web/templates/feedback.html index de97476..cc7541b 100644 --- a/src/mcp_feedback_enhanced/web/templates/feedback.html +++ b/src/mcp_feedback_enhanced/web/templates/feedback.html @@ -514,8 +514,8 @@
- -設定在特定時機自動執行的命令
+ +這些命令會在對應的時機自動執行。留空表示不執行任何命令。
+