From 1f1a078450287dbc46f183b1f2b570aa2979a597 Mon Sep 17 00:00:00 2001 From: catlog22 Date: Thu, 22 Jan 2026 11:53:17 +0800 Subject: [PATCH] feat(loop-monitor): implement dynamic tool loading for task modals - Add getEnabledTools() async function to fetch tools from /api/cli/tools-config - Cache enabled tools in window.enabledTools to avoid repeated API calls - Replace hardcoded tool options in add task modal with dynamic generation - Replace hardcoded tool options in edit task modal with dynamic generation - Fallback to ['claude'] if no tools enabled, all tools if API fails - Make showAddTaskModal() and showEditTaskModal() async functions - Update editTask() to use await when calling showEditTaskModal() Fixes issue where task modals only showed hardcoded tools instead of loading enabled tools from CLI configuration. --- .../dashboard-js/views/loop-monitor.js | 70 ++++++++++++++++--- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/ccw/src/templates/dashboard-js/views/loop-monitor.js b/ccw/src/templates/dashboard-js/views/loop-monitor.js index 07c52e72..f9bcdd95 100644 --- a/ccw/src/templates/dashboard-js/views/loop-monitor.js +++ b/ccw/src/templates/dashboard-js/views/loop-monitor.js @@ -8,6 +8,7 @@ window.selectedLoopId = null; window.loopWebSocket = null; window.loopReconnectAttempts = 0; window.loopMaxReconnectAttempts = 10; +window.enabledTools = null; // Cache for enabled tools from config // Status icons and keys (will be updated with i18n labels dynamically) // Colors are now handled by CSS via semantic class names (.loop-status-indicator.{status}) @@ -31,6 +32,45 @@ function updateLoopStatusLabels() { } } +/** + * Get enabled tools from CLI tools config + * Fetches from /api/cli/tools-config and caches result + */ +async function getEnabledTools() { + if (window.enabledTools) { + return window.enabledTools; + } + + try { + const response = await fetch('/api/cli/tools-config'); + const result = await response.json(); + + if (result.tools && typeof result.tools === 'object') { + // Filter enabled tools + window.enabledTools = Object.entries(result.tools) + .filter(([_, config]) => config.enabled === true) + .map(([name]) => name); + + // Fallback to Claude if no tools enabled + if (window.enabledTools.length === 0) { + window.enabledTools = ['claude']; + } + + return window.enabledTools; + } + } catch (err) { + console.error('Load tools config error:', err); + } + + // Fallback to default tools if API fails + window.enabledTools = ['claude', 'gemini', 'qwen', 'codex'].filter(t => { + const defaultTools = { claude: true, gemini: true, qwen: true, codex: true }; + return defaultTools[t]; + }); + + return window.enabledTools; +} + /** * Render Loop Monitor view */ @@ -974,6 +1014,14 @@ async function saveTaskOrder(loopId, newOrder) { * Show add task modal */ async function showAddTaskModal(loopId) { + // Get enabled tools + const enabledTools = await getEnabledTools(); + + // Build tool options HTML + const toolOptions = enabledTools.map(tool => + `` + ).join(''); + const modal = document.createElement('div'); modal.id = 'addTaskModal'; modal.className = 'modal-overlay'; @@ -1001,10 +1049,7 @@ async function showAddTaskModal(loopId) {
@@ -1128,7 +1173,7 @@ async function editTask(taskId) { } const task = result.data; - showEditTaskModal(loopId, task); + await showEditTaskModal(loopId, task); } catch (err) { console.error('Load task error:', err); showNotification(t('loop.loadTaskError') || 'Error loading task', 'error'); @@ -1138,7 +1183,15 @@ async function editTask(taskId) { /** * Show edit task modal */ -function showEditTaskModal(loopId, task) { +async function showEditTaskModal(loopId, task) { + // Get enabled tools + const enabledTools = await getEnabledTools(); + + // Build tool options HTML + const toolOptions = enabledTools.map(tool => + `` + ).join(''); + const modal = document.createElement('div'); modal.id = 'editTaskModal'; modal.className = 'modal-overlay'; @@ -1165,10 +1218,7 @@ function showEditTaskModal(loopId, task) {