From 3fee7515f3d4455612b8780eaa2548f392eacdd4 Mon Sep 17 00:00:00 2001 From: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com> Date: Sat, 2 Aug 2025 22:59:02 +0300 Subject: [PATCH] fix: fix mcp tool call in extension (#1070) * fix: fix mcp tool call in extension - fix console.log directly being used in scope-adjutment.js breaking mcp * chore: run format and fix tests * chore: format --- .../reports/task-complexity-report.json | 2 +- .taskmaster/state.json | 16 +++---- apps/extension/package.json | 29 ++---------- .../TaskDetails/AIActionsSection.tsx | 46 +++++++++++++------ .../src/webview/hooks/useTaskQueries.ts | 8 ++-- package.json | 5 +- .../modules/task-manager/scope-adjustment.js | 24 ++++++---- .../task-manager/scope-adjustment.test.js | 29 ++++++++++-- 8 files changed, 89 insertions(+), 70 deletions(-) diff --git a/.taskmaster/reports/task-complexity-report.json b/.taskmaster/reports/task-complexity-report.json index b204cb42..3f8f88b2 100644 --- a/.taskmaster/reports/task-complexity-report.json +++ b/.taskmaster/reports/task-complexity-report.json @@ -18,4 +18,4 @@ "reasoning": "This task has high complexity due to several challenging aspects: 1) AI integration requiring sophisticated prompt engineering, 2) Test generation across multiple frameworks, 3) File system operations with proper error handling, 4) MCP tool integration, 5) Complex configuration requirements, and 6) Framework-specific template generation. The task already has 5 subtasks but could benefit from reorganization based on the updated implementation details in the info blocks, particularly around framework support and configuration." } ] -} \ No newline at end of file +} diff --git a/.taskmaster/state.json b/.taskmaster/state.json index 54eba571..a5984cf1 100644 --- a/.taskmaster/state.json +++ b/.taskmaster/state.json @@ -1,9 +1,9 @@ { - "currentTag": "master", - "lastSwitched": "2025-08-01T14:09:25.838Z", - "branchTagMapping": { - "v017-adds": "v017-adds", - "next": "next" - }, - "migrationNoticeShown": true -} \ No newline at end of file + "currentTag": "master", + "lastSwitched": "2025-08-01T14:09:25.838Z", + "branchTagMapping": { + "v017-adds": "v017-adds", + "next": "next" + }, + "migrationNoticeShown": true +} diff --git a/apps/extension/package.json b/apps/extension/package.json index c5f353b6..341b1448 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -9,17 +9,9 @@ "engines": { "vscode": "^1.93.0" }, - "categories": [ - "AI", - "Visualization", - "Education", - "Other" - ], + "categories": ["AI", "Visualization", "Education", "Other"], "main": "./dist/extension.js", - "activationEvents": [ - "onStartupFinished", - "workspaceContains:.taskmaster/**" - ], + "activationEvents": ["onStartupFinished", "workspaceContains:.taskmaster/**"], "contributes": { "viewsContainers": { "activitybar": [ @@ -80,9 +72,7 @@ "items": { "type": "string" }, - "default": [ - "task-master-ai" - ], + "default": ["task-master-ai"], "description": "An array of arguments to pass to the MCP server command." }, "taskmaster.mcp.cwd": { @@ -149,11 +139,7 @@ }, "taskmaster.ui.theme": { "type": "string", - "enum": [ - "auto", - "light", - "dark" - ], + "enum": ["auto", "light", "dark"], "default": "auto", "description": "UI theme preference" }, @@ -214,12 +200,7 @@ }, "taskmaster.debug.logLevel": { "type": "string", - "enum": [ - "error", - "warn", - "info", - "debug" - ], + "enum": ["error", "warn", "info", "debug"], "default": "info", "description": "Logging level" }, diff --git a/apps/extension/src/components/TaskDetails/AIActionsSection.tsx b/apps/extension/src/components/TaskDetails/AIActionsSection.tsx index 9ec2d54b..9855335e 100644 --- a/apps/extension/src/components/TaskDetails/AIActionsSection.tsx +++ b/apps/extension/src/components/TaskDetails/AIActionsSection.tsx @@ -4,7 +4,13 @@ import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { CollapsibleSection } from '@/components/ui/CollapsibleSection'; -import { Wand2, Loader2, PlusCircle, TrendingUp, TrendingDown } from 'lucide-react'; +import { + Wand2, + Loader2, + PlusCircle, + TrendingUp, + TrendingDown +} from 'lucide-react'; import { useUpdateTask, useUpdateSubtask, @@ -34,10 +40,12 @@ export const AIActionsSection: React.FC = ({ }) => { const [prompt, setPrompt] = useState(''); const [scopePrompt, setScopePrompt] = useState(''); - const [scopeStrength, setScopeStrength] = useState<'light' | 'regular' | 'heavy'>('regular'); - const [lastAction, setLastAction] = useState<'regenerate' | 'append' | 'scope-up' | 'scope-down' | null>( - null - ); + const [scopeStrength, setScopeStrength] = useState< + 'light' | 'regular' | 'heavy' + >('regular'); + const [lastAction, setLastAction] = useState< + 'regenerate' | 'append' | 'scope-up' | 'scope-down' | null + >(null); const updateTask = useUpdateTask(); const updateSubtask = useUpdateSubtask(); const scopeUpTask = useScopeUpTask(); @@ -117,8 +125,11 @@ export const AIActionsSection: React.FC = ({ setLastAction('scope-up'); try { - const taskId = isSubtask && parentTask ? `${parentTask.id}.${currentTask.id}` : currentTask.id; - + const taskId = + isSubtask && parentTask + ? `${parentTask.id}.${currentTask.id}` + : currentTask.id; + await scopeUpTask.mutateAsync({ taskId, strength: scopeStrength, @@ -143,8 +154,11 @@ export const AIActionsSection: React.FC = ({ setLastAction('scope-down'); try { - const taskId = isSubtask && parentTask ? `${parentTask.id}.${currentTask.id}` : currentTask.id; - + const taskId = + isSubtask && parentTask + ? `${parentTask.id}.${currentTask.id}` + : currentTask.id; + await scopeDownTask.mutateAsync({ taskId, strength: scopeStrength, @@ -162,7 +176,11 @@ export const AIActionsSection: React.FC = ({ }; // Track loading states based on the last action - const isLoading = updateTask.isPending || updateSubtask.isPending || scopeUpTask.isPending || scopeDownTask.isPending; + const isLoading = + updateTask.isPending || + updateSubtask.isPending || + scopeUpTask.isPending || + scopeDownTask.isPending; const isRegenerating = isLoading && lastAction === 'regenerate'; const isAppending = isLoading && lastAction === 'append'; const isScopingUp = isLoading && lastAction === 'scope-up'; @@ -251,7 +269,7 @@ export const AIActionsSection: React.FC = ({ - + {/* Strength Selection */}
diff --git a/apps/extension/src/webview/hooks/useTaskQueries.ts b/apps/extension/src/webview/hooks/useTaskQueries.ts index acfb8b9b..d18836e6 100644 --- a/apps/extension/src/webview/hooks/useTaskQueries.ts +++ b/apps/extension/src/webview/hooks/useTaskQueries.ts @@ -251,7 +251,7 @@ export function useScopeUpTask() { type: 'mcpRequest', tool: 'scope_up_task', params: { - id: taskId, + id: String(taskId), strength, prompt, research: options.research || false @@ -268,9 +268,7 @@ export function useScopeUpTask() { return response; }, onSuccess: async (data, variables) => { - console.log( - '✅ Task scope up successful, invalidating all task queries' - ); + console.log('✅ Task scope up successful, invalidating all task queries'); console.log('Task ID:', variables.taskId); // Invalidate ALL task-related queries @@ -309,7 +307,7 @@ export function useScopeDownTask() { type: 'mcpRequest', tool: 'scope_down_task', params: { - id: taskId, + id: String(taskId), strength, prompt, research: options.research || false diff --git a/package.json b/package.json index 0d633247..93678b8a 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,7 @@ "task-master-mcp": "mcp-server/server.js", "task-master-ai": "mcp-server/server.js" }, - "workspaces": [ - "apps/*", - "." - ], + "workspaces": ["apps/*", "."], "scripts": { "test": "node --experimental-vm-modules node_modules/.bin/jest", "test:fails": "node --experimental-vm-modules node_modules/.bin/jest --onlyFailures", diff --git a/scripts/modules/task-manager/scope-adjustment.js b/scripts/modules/task-manager/scope-adjustment.js index e78ada35..23792fb3 100644 --- a/scripts/modules/task-manager/scope-adjustment.js +++ b/scripts/modules/task-manager/scope-adjustment.js @@ -279,8 +279,9 @@ async function regenerateSubtasksForComplexity( 'debug', `Complexity-aware subtask calculation${complexityInfo}: ${currentPendingCount} pending -> target ${targetSubtaskCount} total` ); - console.log( - `[DEBUG] Complexity-aware calculation${complexityInfo}: ${currentPendingCount} pending -> ${targetSubtaskCount} total subtasks (${strength} ${direction})` + log( + 'debug', + `Complexity-aware calculation${complexityInfo}: ${currentPendingCount} pending -> ${targetSubtaskCount} total subtasks (${strength} ${direction})` ); const newSubtasksNeeded = Math.max(1, targetSubtaskCount - preservedCount); @@ -386,8 +387,9 @@ Ensure the JSON is valid and properly formatted.`; generated: generatedSubtasks.length }; } catch (error) { - console.log( - `[WARN] Failed to regenerate subtasks for task ${task.id}: ${error.message}` + log( + 'warn', + `Failed to regenerate subtasks for task ${task.id}: ${error.message}` ); // Don't fail the whole operation if subtask regeneration fails return { @@ -583,7 +585,7 @@ export async function scopeUpTask( // Get original complexity score (if available) const originalComplexity = getCurrentComplexityScore(taskId, context); if (originalComplexity && outputFormat === 'text') { - console.log(`[INFO] Original complexity: ${originalComplexity}/10`); + log('info', `Original complexity: ${originalComplexity}/10`); } const adjustResult = await adjustTaskComplexity( @@ -635,8 +637,9 @@ export async function scopeUpTask( const complexityChange = newComplexity - originalComplexity; const arrow = complexityChange > 0 ? '↗️' : complexityChange < 0 ? '↘️' : '➡️'; - console.log( - `[INFO] New complexity: ${originalComplexity}/10 ${arrow} ${newComplexity}/10 (${complexityChange > 0 ? '+' : ''}${complexityChange})` + log( + 'info', + `New complexity: ${originalComplexity}/10 ${arrow} ${newComplexity}/10 (${complexityChange > 0 ? '+' : ''}${complexityChange})` ); } } catch (error) { @@ -733,7 +736,7 @@ export async function scopeDownTask( // Get original complexity score (if available) const originalComplexity = getCurrentComplexityScore(taskId, context); if (originalComplexity && outputFormat === 'text') { - console.log(`[INFO] Original complexity: ${originalComplexity}/10`); + log('info', `Original complexity: ${originalComplexity}/10`); } const adjustResult = await adjustTaskComplexity( @@ -785,8 +788,9 @@ export async function scopeDownTask( const complexityChange = newComplexity - originalComplexity; const arrow = complexityChange > 0 ? '↗️' : complexityChange < 0 ? '↘️' : '➡️'; - console.log( - `[INFO] New complexity: ${originalComplexity}/10 ${arrow} ${newComplexity}/10 (${complexityChange > 0 ? '+' : ''}${complexityChange})` + log( + 'info', + `New complexity: ${originalComplexity}/10 ${arrow} ${newComplexity}/10 (${complexityChange > 0 ? '+' : ''}${complexityChange})` ); } } catch (error) { diff --git a/tests/unit/scripts/modules/task-manager/scope-adjustment.test.js b/tests/unit/scripts/modules/task-manager/scope-adjustment.test.js index a020fd3c..f013ad2f 100644 --- a/tests/unit/scripts/modules/task-manager/scope-adjustment.test.js +++ b/tests/unit/scripts/modules/task-manager/scope-adjustment.test.js @@ -8,13 +8,17 @@ jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({ log: jest.fn(), readJSON: jest.fn(), writeJSON: jest.fn(), - getCurrentTag: jest.fn(() => 'master') + getCurrentTag: jest.fn(() => 'master'), + readComplexityReport: jest.fn(), + findTaskInComplexityReport: jest.fn(), + findProjectRoot: jest.fn() })); jest.unstable_mockModule( '../../../../../scripts/modules/ai-services-unified.js', () => ({ - generateObjectService: jest.fn() + generateObjectService: jest.fn(), + generateTextService: jest.fn() }) ); @@ -26,10 +30,25 @@ jest.unstable_mockModule( }) ); -// Import modules after mocking -const { log, readJSON, writeJSON } = await import( - '../../../../../scripts/modules/utils.js' +jest.unstable_mockModule( + '../../../../../scripts/modules/task-manager/analyze-task-complexity.js', + () => ({ + default: jest.fn() + }) ); + +jest.unstable_mockModule('../../../../../src/utils/path-utils.js', () => ({ + findComplexityReportPath: jest.fn() +})); + +// Import modules after mocking +const { + log, + readJSON, + writeJSON, + readComplexityReport, + findTaskInComplexityReport +} = await import('../../../../../scripts/modules/utils.js'); const { generateObjectService } = await import( '../../../../../scripts/modules/ai-services-unified.js' );