fix(extension): address PR review comments and improve implementation
- Fixed InternalError class definition in errorHandler.ts - Updated extension configuration and CI workflows - Improved error handling and type safety - Enhanced build and release automation - Updated documentation and changelogs Addresses review feedback on PR #997
This commit is contained in:
@@ -262,7 +262,7 @@ export const TaskDetailsView: React.FC<TaskDetailsViewProps> = ({
|
||||
}) => {
|
||||
const context = useContext(VSCodeContext);
|
||||
if (!context)
|
||||
throw new Error('TaskDetailsView must be used within VSCodeContext');
|
||||
{throw new Error('TaskDetailsView must be used within VSCodeContext');}
|
||||
|
||||
const { state, sendMessage } = context;
|
||||
const { tasks } = state;
|
||||
@@ -372,7 +372,7 @@ export const TaskDetailsView: React.FC<TaskDetailsViewProps> = ({
|
||||
|
||||
// Handle running complexity analysis for a task
|
||||
const handleRunComplexityAnalysis = useCallback(async () => {
|
||||
if (!currentTask) return;
|
||||
if (!currentTask) {return;}
|
||||
|
||||
setIsLoadingComplexity(true);
|
||||
try {
|
||||
@@ -416,7 +416,7 @@ export const TaskDetailsView: React.FC<TaskDetailsViewProps> = ({
|
||||
|
||||
// Function to fetch task file data (implementation details and test strategy only)
|
||||
const fetchTaskFileData = async () => {
|
||||
if (!currentTask?.id) return;
|
||||
if (!currentTask?.id) {return;}
|
||||
|
||||
setIsLoadingTaskFileData(true);
|
||||
setTaskFileDataError(null);
|
||||
@@ -543,7 +543,7 @@ export const TaskDetailsView: React.FC<TaskDetailsViewProps> = ({
|
||||
|
||||
// Handle AI Actions
|
||||
const handleRegenerate = async () => {
|
||||
if (!currentTask || !prompt.trim()) return;
|
||||
if (!currentTask || !prompt.trim()) {return;}
|
||||
|
||||
setIsRegenerating(true);
|
||||
try {
|
||||
@@ -584,7 +584,7 @@ export const TaskDetailsView: React.FC<TaskDetailsViewProps> = ({
|
||||
};
|
||||
|
||||
const handleAppend = async () => {
|
||||
if (!currentTask || !prompt.trim()) return;
|
||||
if (!currentTask || !prompt.trim()) {return;}
|
||||
|
||||
setIsAppending(true);
|
||||
try {
|
||||
@@ -626,7 +626,7 @@ export const TaskDetailsView: React.FC<TaskDetailsViewProps> = ({
|
||||
|
||||
// Handle adding a new subtask
|
||||
const handleAddSubtask = async () => {
|
||||
if (!currentTask || !newSubtaskTitle.trim() || isSubtask) return;
|
||||
if (!currentTask || !newSubtaskTitle.trim() || isSubtask) {return;}
|
||||
|
||||
setIsSubmittingSubtask(true);
|
||||
try {
|
||||
@@ -672,7 +672,7 @@ export const TaskDetailsView: React.FC<TaskDetailsViewProps> = ({
|
||||
|
||||
// Handle status change
|
||||
const handleStatusChange = async (newStatus: TaskMasterTask['status']) => {
|
||||
if (!currentTask) return;
|
||||
if (!currentTask) {return;}
|
||||
|
||||
try {
|
||||
await sendMessage({
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
} from './utils/errorHandler';
|
||||
import { getToastDuration } from './utils/notificationPreferences';
|
||||
import { parseTaskFileData } from './utils/taskFileReader';
|
||||
import { TaskMasterTask } from './utils/taskMasterApi';
|
||||
|
||||
// Global MCP client manager instance
|
||||
let mcpClient: MCPClientManager | null = null;
|
||||
@@ -39,7 +40,7 @@ interface PollingState {
|
||||
timer?: NodeJS.Timeout;
|
||||
isPolling: boolean;
|
||||
interval: number;
|
||||
lastTaskData?: any[];
|
||||
lastTaskData?: TaskMasterTask[];
|
||||
errorCount: number;
|
||||
maxErrors: number;
|
||||
// Adaptive frequency properties
|
||||
@@ -55,7 +56,7 @@ interface PollingState {
|
||||
reconnectBackoffMultiplier: number;
|
||||
lastSuccessfulConnection?: number;
|
||||
isOfflineMode: boolean;
|
||||
cachedTaskData?: any[];
|
||||
cachedTaskData?: TaskMasterTask[];
|
||||
}
|
||||
|
||||
let pollingState: PollingState = {
|
||||
@@ -351,7 +352,7 @@ function adjustPollingFrequency(): void {
|
||||
// Low activity: reduce polling frequency with exponential backoff
|
||||
const backoffMultiplier = Math.min(
|
||||
4,
|
||||
Math.pow(1.5, pollingState.consecutiveNoChanges - 3)
|
||||
1.5 ** (pollingState.consecutiveNoChanges - 3)
|
||||
);
|
||||
newInterval = Math.min(
|
||||
pollingState.maxInterval,
|
||||
@@ -1031,43 +1032,65 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
case 'readTaskFileData':
|
||||
console.log('📄 Reading task file data:', message.data);
|
||||
const { requestId } = message;
|
||||
try {
|
||||
const { taskId, tag: tagName = 'master' } = message.data;
|
||||
{
|
||||
const { requestId } = message;
|
||||
try {
|
||||
const { taskId, tag: tagName = 'master' } = message.data;
|
||||
|
||||
// Get workspace folder
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
||||
if (!workspaceFolder) {
|
||||
throw new Error('No workspace folder found');
|
||||
}
|
||||
// Get workspace folder
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
||||
if (!workspaceFolder) {
|
||||
throw new Error('No workspace folder found');
|
||||
}
|
||||
|
||||
// Build path to tasks.json
|
||||
const tasksJsonPath = path.join(
|
||||
workspaceFolder.uri.fsPath,
|
||||
'.taskmaster',
|
||||
'tasks',
|
||||
'tasks.json'
|
||||
);
|
||||
console.log('🔍 Looking for tasks.json at:', tasksJsonPath);
|
||||
|
||||
// Check if file exists
|
||||
if (!fs.existsSync(tasksJsonPath)) {
|
||||
// Try legacy location
|
||||
const legacyPath = path.join(
|
||||
// Build path to tasks.json
|
||||
const tasksJsonPath = path.join(
|
||||
workspaceFolder.uri.fsPath,
|
||||
'.taskmaster',
|
||||
'tasks',
|
||||
'tasks.json'
|
||||
);
|
||||
console.log('🔍 Trying legacy path:', legacyPath);
|
||||
if (!fs.existsSync(legacyPath)) {
|
||||
throw new Error(
|
||||
'tasks.json not found in .taskmaster/tasks/ or tasks/ directory'
|
||||
console.log('🔍 Looking for tasks.json at:', tasksJsonPath);
|
||||
|
||||
// Check if file exists
|
||||
if (!fs.existsSync(tasksJsonPath)) {
|
||||
// Try legacy location
|
||||
const legacyPath = path.join(
|
||||
workspaceFolder.uri.fsPath,
|
||||
'tasks',
|
||||
'tasks.json'
|
||||
);
|
||||
console.log('🔍 Trying legacy path:', legacyPath);
|
||||
if (!fs.existsSync(legacyPath)) {
|
||||
throw new Error(
|
||||
'tasks.json not found in .taskmaster/tasks/ or tasks/ directory'
|
||||
);
|
||||
}
|
||||
// Use legacy path
|
||||
const content = fs.readFileSync(legacyPath, 'utf8');
|
||||
console.log(
|
||||
'📖 Read legacy tasks.json, content length:',
|
||||
content.length
|
||||
);
|
||||
const taskData = parseTaskFileData(
|
||||
content,
|
||||
taskId,
|
||||
tagName,
|
||||
workspaceFolder.uri.fsPath
|
||||
);
|
||||
console.log('✅ Parsed task data for legacy path:', taskData);
|
||||
panel.webview.postMessage({
|
||||
type: 'response',
|
||||
requestId,
|
||||
data: taskData
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Use legacy path
|
||||
const content = fs.readFileSync(legacyPath, 'utf8');
|
||||
|
||||
// Read and parse tasks.json
|
||||
const content = fs.readFileSync(tasksJsonPath, 'utf8');
|
||||
console.log(
|
||||
'📖 Read legacy tasks.json, content length:',
|
||||
'📖 Read tasks.json, content length:',
|
||||
content.length
|
||||
);
|
||||
const taskData = parseTaskFileData(
|
||||
@@ -1076,46 +1099,26 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
tagName,
|
||||
workspaceFolder.uri.fsPath
|
||||
);
|
||||
console.log('✅ Parsed task data for legacy path:', taskData);
|
||||
console.log('✅ Parsed task data:', taskData);
|
||||
|
||||
panel.webview.postMessage({
|
||||
type: 'response',
|
||||
requestId,
|
||||
data: taskData
|
||||
});
|
||||
return;
|
||||
|
||||
console.log(`✅ Retrieved task file data for task ${taskId}`);
|
||||
} catch (error) {
|
||||
console.error('❌ Error reading task file data:', error);
|
||||
panel.webview.postMessage({
|
||||
type: 'error',
|
||||
requestId,
|
||||
error:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Failed to read task file data'
|
||||
});
|
||||
}
|
||||
|
||||
// Read and parse tasks.json
|
||||
const content = fs.readFileSync(tasksJsonPath, 'utf8');
|
||||
console.log(
|
||||
'📖 Read tasks.json, content length:',
|
||||
content.length
|
||||
);
|
||||
const taskData = parseTaskFileData(
|
||||
content,
|
||||
taskId,
|
||||
tagName,
|
||||
workspaceFolder.uri.fsPath
|
||||
);
|
||||
console.log('✅ Parsed task data:', taskData);
|
||||
|
||||
panel.webview.postMessage({
|
||||
type: 'response',
|
||||
requestId,
|
||||
data: taskData
|
||||
});
|
||||
|
||||
console.log(`✅ Retrieved task file data for task ${taskId}`);
|
||||
} catch (error) {
|
||||
console.error('❌ Error reading task file data:', error);
|
||||
panel.webview.postMessage({
|
||||
type: 'error',
|
||||
requestId,
|
||||
error:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Failed to read task file data'
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -648,14 +648,14 @@ const TaskEditModal: React.FC<{
|
||||
|
||||
// Only include changed fields
|
||||
const updates: TaskUpdates = {};
|
||||
if (formData.title !== task.title) updates.title = formData.title;
|
||||
if (formData.title !== task.title) {updates.title = formData.title;}
|
||||
if (formData.description !== task.description)
|
||||
updates.description = formData.description;
|
||||
if (formData.details !== task.details) updates.details = formData.details;
|
||||
{updates.description = formData.description;}
|
||||
if (formData.details !== task.details) {updates.details = formData.details;}
|
||||
if (formData.priority !== task.priority)
|
||||
updates.priority = formData.priority;
|
||||
{updates.priority = formData.priority;}
|
||||
if (formData.testStrategy !== task.testStrategy)
|
||||
updates.testStrategy = formData.testStrategy;
|
||||
{updates.testStrategy = formData.testStrategy;}
|
||||
if (
|
||||
JSON.stringify(formData.dependencies) !==
|
||||
JSON.stringify(task.dependencies)
|
||||
@@ -875,7 +875,7 @@ const TaskCard: React.FC<{
|
||||
const TaskMasterKanban: React.FC = () => {
|
||||
const context = useContext(VSCodeContext);
|
||||
if (!context)
|
||||
throw new Error('TaskMasterKanban must be used within VSCodeContext');
|
||||
{throw new Error('TaskMasterKanban must be used within VSCodeContext');}
|
||||
|
||||
const { state, dispatch, sendMessage, availableHeight } = context;
|
||||
const {
|
||||
@@ -984,14 +984,14 @@ const TaskMasterKanban: React.FC = () => {
|
||||
dispatch({ type: 'SET_USER_INTERACTING', payload: false });
|
||||
}, 1000); // 1 second delay to ensure smooth completion
|
||||
|
||||
if (!over) return;
|
||||
if (!over) {return;}
|
||||
|
||||
const taskId = active.id as string;
|
||||
const newStatus = over.id as TaskMasterTask['status'];
|
||||
|
||||
// Find the task that was moved
|
||||
const task = tasks.find((t) => t.id === taskId);
|
||||
if (!task || task.status === newStatus) return;
|
||||
if (!task || task.status === newStatus) {return;}
|
||||
|
||||
console.log(`🔄 Moving task ${taskId} from ${task.status} to ${newStatus}`);
|
||||
|
||||
@@ -1382,7 +1382,7 @@ const App: React.FC = () => {
|
||||
|
||||
// Handle messages from extension
|
||||
useEffect(() => {
|
||||
if (!vscode) return;
|
||||
if (!vscode) {return;}
|
||||
|
||||
const handleMessage = (event: MessageEvent) => {
|
||||
const message: WebviewMessage = event.data;
|
||||
@@ -1526,13 +1526,13 @@ const App: React.FC = () => {
|
||||
|
||||
// Map error severity to toast type
|
||||
let toastType: ToastNotification['type'] = 'error';
|
||||
if (errorData.severity === 'low') toastType = 'info';
|
||||
else if (errorData.severity === 'medium') toastType = 'warning';
|
||||
if (errorData.severity === 'low') {toastType = 'info';}
|
||||
else if (errorData.severity === 'medium') {toastType = 'warning';}
|
||||
else if (
|
||||
errorData.severity === 'high' ||
|
||||
errorData.severity === 'critical'
|
||||
)
|
||||
toastType = 'error';
|
||||
{toastType = 'error';}
|
||||
|
||||
// Create appropriate toast based on error category
|
||||
const title =
|
||||
|
||||
Reference in New Issue
Block a user