mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 20:43:36 +00:00
feat: standardize logging across UI components
- Replaced console.log and console.error statements with logger methods from @automaker/utils in various UI components, ensuring consistent log formatting and improved readability. - Enhanced error handling by utilizing logger methods to provide clearer context for issues encountered during operations. - Updated multiple views and hooks to integrate the new logging system, improving maintainability and debugging capabilities. This update significantly enhances the observability of UI components, facilitating easier troubleshooting and monitoring.
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import { useState, useRef, useCallback, useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { ImageIcon, Upload, Loader2, Trash2 } from 'lucide-react';
|
||||
|
||||
const logger = createLogger('BoardBackgroundModal');
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
@@ -113,7 +116,7 @@ export function BoardBackgroundModal({ open, onOpenChange }: BoardBackgroundModa
|
||||
setPreviewImage(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to process image:', error);
|
||||
logger.error('Failed to process image:', error);
|
||||
toast.error('Failed to process image');
|
||||
setPreviewImage(null);
|
||||
} finally {
|
||||
@@ -185,7 +188,7 @@ export function BoardBackgroundModal({ open, onOpenChange }: BoardBackgroundModa
|
||||
toast.error(result.error || 'Failed to clear background image');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to clear background:', error);
|
||||
logger.error('Failed to clear background:', error);
|
||||
toast.error('Failed to clear background');
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -29,6 +30,8 @@ import { cn } from '@/lib/utils';
|
||||
import { useFileBrowser } from '@/contexts/file-browser-context';
|
||||
import { getDefaultWorkspaceDirectory, saveLastProjectDirectory } from '@/lib/workspace-config';
|
||||
|
||||
const logger = createLogger('NewProjectModal');
|
||||
|
||||
interface ValidationErrors {
|
||||
projectName?: boolean;
|
||||
workspaceDir?: boolean;
|
||||
@@ -78,7 +81,7 @@ export function NewProjectModal({
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to get default workspace directory:', error);
|
||||
logger.error('Failed to get default workspace directory:', error);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoadingWorkspace(false);
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { ShieldX, RefreshCw, Container, Copy, Check } from 'lucide-react';
|
||||
|
||||
const logger = createLogger('SandboxRejectionScreen');
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
const DOCKER_COMMAND = 'npm run dev:docker';
|
||||
@@ -26,7 +29,7 @@ export function SandboxRejectionScreen() {
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy:', err);
|
||||
logger.error('Failed to copy:', err);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { ShieldAlert, Copy, Check } from 'lucide-react';
|
||||
|
||||
const logger = createLogger('SandboxRiskDialog');
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -43,7 +46,7 @@ export function SandboxRiskDialog({ open, onConfirm, onDeny }: SandboxRiskDialog
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy:', err);
|
||||
logger.error('Failed to copy:', err);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useNavigate, useLocation } from '@tanstack/react-router';
|
||||
|
||||
const logger = createLogger('Sidebar');
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useAppStore, type ThemeMode } from '@/store/app-store';
|
||||
import { useKeyboardShortcuts, useKeyboardShortcutsConfig } from '@/hooks/use-keyboard-shortcuts';
|
||||
@@ -215,7 +218,7 @@ export function Sidebar() {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Sidebar] Failed to open project:', error);
|
||||
logger.error('Failed to open project:', error);
|
||||
toast.error('Failed to open project', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('ProjectCreation');
|
||||
import { initializeProject } from '@/lib/project-init';
|
||||
import { toast } from 'sonner';
|
||||
import type { StarterTemplate } from '@/lib/templates';
|
||||
@@ -82,7 +85,7 @@ export function useProjectCreation({
|
||||
|
||||
toast.success('Project created successfully');
|
||||
} catch (error) {
|
||||
console.error('[ProjectCreation] Failed to finalize project:', error);
|
||||
logger.error('Failed to finalize project:', error);
|
||||
toast.error('Failed to initialize project', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -108,7 +111,7 @@ export function useProjectCreation({
|
||||
// Finalize project setup
|
||||
await finalizeProjectCreation(projectPath, projectName);
|
||||
} catch (error) {
|
||||
console.error('[ProjectCreation] Failed to create blank project:', error);
|
||||
logger.error('Failed to create blank project:', error);
|
||||
toast.error('Failed to create project', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -180,7 +183,7 @@ export function useProjectCreation({
|
||||
description: `Created ${projectName} from ${template.name}`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[ProjectCreation] Failed to create from template:', error);
|
||||
logger.error('Failed to create from template:', error);
|
||||
toast.error('Failed to create project from template', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -252,7 +255,7 @@ export function useProjectCreation({
|
||||
description: `Created ${projectName} from ${repoUrl}`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[ProjectCreation] Failed to create from custom URL:', error);
|
||||
logger.error('Failed to create from custom URL:', error);
|
||||
toast.error('Failed to create project from URL', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('RunningAgents');
|
||||
|
||||
export function useRunningAgents() {
|
||||
const [runningAgentsCount, setRunningAgentsCount] = useState(0);
|
||||
|
||||
@@ -15,7 +18,7 @@ export function useRunningAgents() {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Sidebar] Error fetching running agents count:', error);
|
||||
logger.error('Error fetching running agents count:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('SetupDialog');
|
||||
import { toast } from 'sonner';
|
||||
import type { FeatureCount } from '@/components/views/spec-view/types';
|
||||
|
||||
@@ -53,7 +56,7 @@ export function useSetupDialog({
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
console.error('[SetupDialog] Failed to start spec creation:', result.error);
|
||||
logger.error('Failed to start spec creation:', result.error);
|
||||
setSpecCreatingForProject(null);
|
||||
toast.error('Failed to create specification', {
|
||||
description: result.error,
|
||||
@@ -66,7 +69,7 @@ export function useSetupDialog({
|
||||
}
|
||||
// If successful, we'll wait for the events to update the state
|
||||
} catch (error) {
|
||||
console.error('[SetupDialog] Failed to create spec:', error);
|
||||
logger.error('Failed to create spec:', error);
|
||||
setSpecCreatingForProject(null);
|
||||
toast.error('Failed to create specification', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
const logger = createLogger('SpecRegeneration');
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import type { SpecRegenerationEvent } from '@/types/electron';
|
||||
|
||||
@@ -30,16 +33,11 @@ export function useSpecRegeneration({
|
||||
if (!api.specRegeneration) return;
|
||||
|
||||
const unsubscribe = api.specRegeneration.onEvent((event: SpecRegenerationEvent) => {
|
||||
console.log(
|
||||
'[Sidebar] Spec regeneration event:',
|
||||
event.type,
|
||||
'for project:',
|
||||
event.projectPath
|
||||
);
|
||||
logger.debug('Spec regeneration event:', event.type, 'for project:', event.projectPath);
|
||||
|
||||
// Only handle events for the project we're currently setting up
|
||||
if (event.projectPath !== creatingSpecProjectPath && event.projectPath !== setupProjectPath) {
|
||||
console.log('[Sidebar] Ignoring event - not for project being set up');
|
||||
logger.debug('Ignoring event - not for project being set up');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
const logger = createLogger('TrashOperations');
|
||||
import { getElectronAPI, type TrashedProject } from '@/lib/electron';
|
||||
|
||||
interface UseTrashOperationsProps {
|
||||
@@ -24,7 +27,7 @@ export function useTrashOperations({
|
||||
description: 'Added back to your project list.',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Sidebar] Failed to restore project:', error);
|
||||
logger.error('Failed to restore project:', error);
|
||||
toast.error('Failed to restore project', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -52,7 +55,7 @@ export function useTrashOperations({
|
||||
description: trashedProject.path,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Sidebar] Failed to delete project from disk:', error);
|
||||
logger.error('Failed to delete project from disk:', error);
|
||||
toast.error('Failed to delete project folder', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -69,7 +72,7 @@ export function useTrashOperations({
|
||||
emptyTrash();
|
||||
toast.success('Recycle bin cleared');
|
||||
} catch (error) {
|
||||
console.error('[Sidebar] Failed to empty trash:', error);
|
||||
logger.error('Failed to empty trash:', error);
|
||||
toast.error('Failed to clear recycle bin', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('UnviewedValidations');
|
||||
import type { Project, StoredValidation } from '@/lib/electron';
|
||||
|
||||
/**
|
||||
@@ -38,7 +41,7 @@ export function useUnviewedValidations(currentProject: Project | null) {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[useUnviewedValidations] Failed to load count:', err);
|
||||
logger.error('Failed to load count:', err);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
|
||||
const logger = createLogger('SessionManager');
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { HotkeyButton } from '@/components/ui/hotkey-button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
@@ -126,7 +129,7 @@ export function SessionManager({
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore errors for individual session checks
|
||||
console.warn(`[SessionManager] Failed to check running state for ${session.id}:`, err);
|
||||
logger.warn(`Failed to check running state for ${session.id}:`, err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +230,7 @@ export function SessionManager({
|
||||
const handleArchiveSession = async (sessionId: string) => {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.sessions) {
|
||||
console.error('[SessionManager] Sessions API not available');
|
||||
logger.error('[SessionManager] Sessions API not available');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -240,10 +243,10 @@ export function SessionManager({
|
||||
}
|
||||
await loadSessions();
|
||||
} else {
|
||||
console.error('[SessionManager] Archive failed:', result.error);
|
||||
logger.error('[SessionManager] Archive failed:', result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SessionManager] Archive error:', error);
|
||||
logger.error('[SessionManager] Archive error:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -251,7 +254,7 @@ export function SessionManager({
|
||||
const handleUnarchiveSession = async (sessionId: string) => {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.sessions) {
|
||||
console.error('[SessionManager] Sessions API not available');
|
||||
logger.error('[SessionManager] Sessions API not available');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -260,10 +263,10 @@ export function SessionManager({
|
||||
if (result.success) {
|
||||
await loadSessions();
|
||||
} else {
|
||||
console.error('[SessionManager] Unarchive failed:', result.error);
|
||||
logger.error('[SessionManager] Unarchive failed:', result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SessionManager] Unarchive error:', error);
|
||||
logger.error('[SessionManager] Unarchive error:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import React, { useState, useRef, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('DescriptionImageDropZone');
|
||||
import { ImageIcon, X, Loader2, FileText } from 'lucide-react';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
@@ -108,7 +111,7 @@ export function DescriptionImageDropZone({
|
||||
// Check if saveImageToTemp method exists
|
||||
if (!api.saveImageToTemp) {
|
||||
// Fallback path when saveImageToTemp is not available
|
||||
console.log('[DescriptionImageDropZone] Using fallback path for image');
|
||||
logger.info('Using fallback path for image');
|
||||
return `.automaker/images/${Date.now()}_${filename}`;
|
||||
}
|
||||
|
||||
@@ -118,10 +121,10 @@ export function DescriptionImageDropZone({
|
||||
if (result.success && result.path) {
|
||||
return result.path;
|
||||
}
|
||||
console.error('[DescriptionImageDropZone] Failed to save image:', result.error);
|
||||
logger.error('Failed to save image:', result.error);
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('[DescriptionImageDropZone] Error saving image:', error);
|
||||
logger.error('Error saving image:', error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
@@ -216,7 +219,7 @@ export function DescriptionImageDropZone({
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.warn('File upload errors:', errors);
|
||||
logger.warn('File upload errors:', errors);
|
||||
}
|
||||
|
||||
if (newImages.length > 0) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import React, { useState, useRef, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('FeatureImageUpload');
|
||||
import { ImageIcon, X, Upload } from 'lucide-react';
|
||||
import {
|
||||
fileToBase64,
|
||||
@@ -77,7 +80,7 @@ export function FeatureImageUpload({
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.warn('Image upload errors:', errors);
|
||||
logger.warn('Image upload errors:', errors);
|
||||
}
|
||||
|
||||
if (newImages.length > 0) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import React, { useState, useRef, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('ImageDropZone');
|
||||
import { ImageIcon, X, Upload } from 'lucide-react';
|
||||
import type { ImageAttachment } from '@/store/app-store';
|
||||
import {
|
||||
@@ -88,7 +91,7 @@ export function ImageDropZone({
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.warn('Image upload errors:', errors);
|
||||
logger.warn('Image upload errors:', errors);
|
||||
}
|
||||
|
||||
if (newImages.length > 0) {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('TaskProgressPanel');
|
||||
import { Check, Loader2, Circle, ChevronDown, ChevronRight, FileCode } from 'lucide-react';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import type { AutoModeEvent } from '@/types/electron';
|
||||
@@ -72,7 +75,7 @@ export function TaskProgressPanel({
|
||||
setCurrentTaskId(currentId || null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load initial tasks:', error);
|
||||
logger.error('Failed to load initial tasks:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -19,6 +20,8 @@ import {
|
||||
import { cn } from '@/lib/utils';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('AgentToolsView');
|
||||
|
||||
interface ToolResult {
|
||||
success: boolean;
|
||||
output?: string;
|
||||
@@ -62,7 +65,7 @@ export function AgentToolsView() {
|
||||
|
||||
try {
|
||||
// Simulate agent requesting file read
|
||||
console.log(`[Agent Tool] Requesting to read file: ${readFilePath}`);
|
||||
logger.info(`[Agent Tool] Requesting to read file: ${readFilePath}`);
|
||||
|
||||
const result = await api.readFile(readFilePath);
|
||||
|
||||
@@ -72,14 +75,14 @@ export function AgentToolsView() {
|
||||
output: result.content,
|
||||
timestamp: new Date(),
|
||||
});
|
||||
console.log(`[Agent Tool] File read successful: ${readFilePath}`);
|
||||
logger.info(`[Agent Tool] File read successful: ${readFilePath}`);
|
||||
} else {
|
||||
setReadFileResult({
|
||||
success: false,
|
||||
error: result.error || 'Failed to read file',
|
||||
timestamp: new Date(),
|
||||
});
|
||||
console.log(`[Agent Tool] File read failed: ${result.error}`);
|
||||
logger.info(`[Agent Tool] File read failed: ${result.error}`);
|
||||
}
|
||||
} catch (error) {
|
||||
setReadFileResult({
|
||||
@@ -101,7 +104,7 @@ export function AgentToolsView() {
|
||||
|
||||
try {
|
||||
// Simulate agent requesting file write
|
||||
console.log(`[Agent Tool] Requesting to write file: ${writeFilePath}`);
|
||||
logger.info(`[Agent Tool] Requesting to write file: ${writeFilePath}`);
|
||||
|
||||
const result = await api.writeFile(writeFilePath, writeFileContent);
|
||||
|
||||
@@ -111,14 +114,14 @@ export function AgentToolsView() {
|
||||
output: `File written successfully: ${writeFilePath}`,
|
||||
timestamp: new Date(),
|
||||
});
|
||||
console.log(`[Agent Tool] File write successful: ${writeFilePath}`);
|
||||
logger.info(`[Agent Tool] File write successful: ${writeFilePath}`);
|
||||
} else {
|
||||
setWriteFileResult({
|
||||
success: false,
|
||||
error: result.error || 'Failed to write file',
|
||||
timestamp: new Date(),
|
||||
});
|
||||
console.log(`[Agent Tool] File write failed: ${result.error}`);
|
||||
logger.info(`[Agent Tool] File write failed: ${result.error}`);
|
||||
}
|
||||
} catch (error) {
|
||||
setWriteFileResult({
|
||||
@@ -140,7 +143,7 @@ export function AgentToolsView() {
|
||||
|
||||
try {
|
||||
// Terminal command simulation for demonstration purposes
|
||||
console.log(`[Agent Tool] Simulating command: ${terminalCommand}`);
|
||||
logger.info(`[Agent Tool] Simulating command: ${terminalCommand}`);
|
||||
|
||||
// Simulated outputs for common commands (preview mode)
|
||||
// In production, the agent executes commands via Claude SDK
|
||||
@@ -165,7 +168,7 @@ export function AgentToolsView() {
|
||||
output: output,
|
||||
timestamp: new Date(),
|
||||
});
|
||||
console.log(`[Agent Tool] Command executed successfully: ${terminalCommand}`);
|
||||
logger.info(`[Agent Tool] Command executed successfully: ${terminalCommand}`);
|
||||
} catch (error) {
|
||||
setTerminalResult({
|
||||
success: false,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { useState, useCallback, useEffect, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
const logger = createLogger('AgentSession');
|
||||
|
||||
interface UseAgentSessionOptions {
|
||||
projectPath: string | undefined;
|
||||
}
|
||||
@@ -44,7 +47,7 @@ export function useAgentSession({ projectPath }: UseAgentSessionOptions): UseAge
|
||||
|
||||
const lastSessionId = getLastSelectedSession(projectPath);
|
||||
if (lastSessionId) {
|
||||
console.log('[AgentView] Restoring last selected session:', lastSessionId);
|
||||
logger.info('Restoring last selected session:', lastSessionId);
|
||||
setCurrentSessionId(lastSessionId);
|
||||
}
|
||||
}, [projectPath, getLastSelectedSession]);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import type { ImageAttachment, TextFileAttachment } from '@/store/app-store';
|
||||
|
||||
const logger = createLogger('FileAttachments');
|
||||
import {
|
||||
fileToBase64,
|
||||
generateImageId,
|
||||
@@ -138,7 +141,7 @@ export function useFileAttachments({
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.warn('File upload errors:', errors);
|
||||
logger.warn('File upload errors:', errors);
|
||||
}
|
||||
|
||||
if (newImages.length > 0) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore, FileTreeNode, ProjectAnalysis } from '@/store/app-store';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
@@ -21,6 +22,8 @@ import {
|
||||
} from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('AnalysisView');
|
||||
|
||||
const IGNORE_PATTERNS = [
|
||||
'node_modules',
|
||||
'.git',
|
||||
@@ -109,7 +112,7 @@ export function AnalysisView() {
|
||||
|
||||
return nodes;
|
||||
} catch (error) {
|
||||
console.error('Failed to scan directory:', path, error);
|
||||
logger.error('Failed to scan directory:', path, error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
@@ -165,7 +168,7 @@ export function AnalysisView() {
|
||||
|
||||
setProjectAnalysis(analysis);
|
||||
} catch (error) {
|
||||
console.error('Analysis failed:', error);
|
||||
logger.error('Analysis failed:', error);
|
||||
} finally {
|
||||
setIsAnalyzing(false);
|
||||
}
|
||||
@@ -373,7 +376,7 @@ ${Object.entries(projectAnalysis.filesByExtension)
|
||||
setSpecError(writeResult.error || 'Failed to write spec file');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to generate spec:', error);
|
||||
logger.error('Failed to generate spec:', error);
|
||||
setSpecError(error instanceof Error ? error.message : 'Failed to generate spec');
|
||||
} finally {
|
||||
setIsGeneratingSpec(false);
|
||||
@@ -644,7 +647,7 @@ ${Object.entries(projectAnalysis.filesByExtension)
|
||||
|
||||
setFeatureListGenerated(true);
|
||||
} catch (error) {
|
||||
console.error('Failed to generate feature list:', error);
|
||||
logger.error('Failed to generate feature list:', error);
|
||||
setFeatureListError(
|
||||
error instanceof Error ? error.message : 'Failed to generate feature list'
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState, useCallback, useMemo, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
@@ -62,6 +63,8 @@ import {
|
||||
// Stable empty array to avoid infinite loop in selector
|
||||
const EMPTY_WORKTREES: ReturnType<ReturnType<typeof useAppStore.getState>['getWorktrees']> = [];
|
||||
|
||||
const logger = createLogger('Board');
|
||||
|
||||
export function BoardView() {
|
||||
const {
|
||||
currentProject,
|
||||
@@ -188,7 +191,7 @@ export function BoardView() {
|
||||
|
||||
return result.success && result.exists === true;
|
||||
} catch (error) {
|
||||
console.error('[Board] Error checking context:', error);
|
||||
logger.error('Error checking context:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@@ -222,7 +225,7 @@ export function BoardView() {
|
||||
setPipelineConfig(currentProject.path, result.config);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Failed to load pipeline config:', error);
|
||||
logger.error('Failed to load pipeline config:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -288,7 +291,7 @@ export function BoardView() {
|
||||
setBranchSuggestions(localBranches);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[BoardView] Error fetching branches:', error);
|
||||
logger.error('Error fetching branches:', error);
|
||||
setBranchSuggestions([]);
|
||||
}
|
||||
};
|
||||
@@ -497,7 +500,7 @@ export function BoardView() {
|
||||
if (newFeature) {
|
||||
await handleStartImplementation(newFeature);
|
||||
} else {
|
||||
console.error('Could not find newly created feature to start it automatically.');
|
||||
logger.error('Could not find newly created feature to start it automatically.');
|
||||
toast.error('Failed to auto-start feature', {
|
||||
description: 'The feature was created but could not be started automatically.',
|
||||
});
|
||||
@@ -538,7 +541,7 @@ export function BoardView() {
|
||||
if (newFeature) {
|
||||
await handleStartImplementation(newFeature);
|
||||
} else {
|
||||
console.error('Could not find newly created feature to start it automatically.');
|
||||
logger.error('Could not find newly created feature to start it automatically.');
|
||||
toast.error('Failed to auto-start feature', {
|
||||
description: 'The feature was created but could not be started automatically.',
|
||||
});
|
||||
@@ -561,7 +564,7 @@ export function BoardView() {
|
||||
if (newFeature) {
|
||||
await handleStartImplementation(newFeature);
|
||||
} else {
|
||||
console.error('Could not find newly created feature to start it automatically.');
|
||||
logger.error('Could not find newly created feature to start it automatically.');
|
||||
toast.error('Failed to auto-start feature', {
|
||||
description: 'The feature was created but could not be started automatically.',
|
||||
});
|
||||
@@ -889,10 +892,10 @@ export function BoardView() {
|
||||
// Reload features from server to ensure sync
|
||||
loadFeatures();
|
||||
} else {
|
||||
console.error('[Board] Failed to approve plan:', result.error);
|
||||
logger.error('Failed to approve plan:', result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error approving plan:', error);
|
||||
logger.error('Error approving plan:', error);
|
||||
} finally {
|
||||
setIsPlanApprovalLoading(false);
|
||||
setPendingPlanApproval(null);
|
||||
@@ -945,10 +948,10 @@ export function BoardView() {
|
||||
// Reload features from server to ensure sync
|
||||
loadFeatures();
|
||||
} else {
|
||||
console.error('[Board] Failed to reject plan:', result.error);
|
||||
logger.error('Failed to reject plan:', result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error rejecting plan:', error);
|
||||
logger.error('Error rejecting plan:', error);
|
||||
} finally {
|
||||
setIsPlanApprovalLoading(false);
|
||||
setPendingPlanApproval(null);
|
||||
@@ -1407,7 +1410,7 @@ export function BoardView() {
|
||||
// Persist changes asynchronously and in parallel
|
||||
Promise.all(
|
||||
featuresToUpdate.map((feature) => persistFeatureUpdate(feature.id, { prUrl }))
|
||||
).catch(console.error);
|
||||
).catch((err) => logger.error('Error in handleMove:', err));
|
||||
}
|
||||
setWorktreeRefreshKey((k) => k + 1);
|
||||
setSelectedWorktreeForAction(null);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -64,6 +65,8 @@ import {
|
||||
} from '@automaker/dependency-resolver';
|
||||
import { isCursorModel, PROVIDER_PREFIXES } from '@automaker/types';
|
||||
|
||||
const logger = createLogger('AddFeatureDialog');
|
||||
|
||||
type FeatureData = {
|
||||
title: string;
|
||||
category: string;
|
||||
@@ -331,7 +334,7 @@ export function AddFeatureDialog({
|
||||
toast.error(result?.error || 'Failed to enhance description');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Enhancement failed:', error);
|
||||
logger.error('Enhancement failed:', error);
|
||||
toast.error('Failed to enhance description');
|
||||
} finally {
|
||||
setIsEnhancing(false);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -29,6 +30,8 @@ interface AgentOutputModalProps {
|
||||
|
||||
type ViewMode = 'parsed' | 'raw' | 'changes';
|
||||
|
||||
const logger = createLogger('AgentOutputModal');
|
||||
|
||||
export function AgentOutputModal({
|
||||
open,
|
||||
onClose,
|
||||
@@ -88,7 +91,7 @@ export function AgentOutputModal({
|
||||
setOutput('');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load output:', error);
|
||||
logger.error('Failed to load output:', error);
|
||||
setOutput('');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
@@ -105,11 +108,11 @@ export function AgentOutputModal({
|
||||
const api = getElectronAPI();
|
||||
if (!api?.autoMode) return;
|
||||
|
||||
console.log('[AgentOutputModal] Subscribing to events for featureId:', featureId);
|
||||
logger.info('Subscribing to events for featureId:', featureId);
|
||||
|
||||
const unsubscribe = api.autoMode.onEvent((event) => {
|
||||
console.log(
|
||||
'[AgentOutputModal] Received event:',
|
||||
logger.debug(
|
||||
'Received event:',
|
||||
event.type,
|
||||
'featureId:',
|
||||
'featureId' in event ? event.featureId : 'none',
|
||||
@@ -119,7 +122,7 @@ export function AgentOutputModal({
|
||||
|
||||
// Filter events for this specific feature only (skip events without featureId)
|
||||
if ('featureId' in event && event.featureId !== featureId) {
|
||||
console.log('[AgentOutputModal] Skipping event - featureId mismatch');
|
||||
logger.debug('Skipping event - featureId mismatch');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -22,6 +23,8 @@ interface WorktreeInfo {
|
||||
changedFilesCount?: number;
|
||||
}
|
||||
|
||||
const logger = createLogger('CreateBranchDialog');
|
||||
|
||||
interface CreateBranchDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
@@ -77,7 +80,7 @@ export function CreateBranchDialog({
|
||||
setError(result.error || 'Failed to create branch');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Create branch failed:', err);
|
||||
logger.error('Create branch failed:', err);
|
||||
setError('Failed to create branch');
|
||||
} finally {
|
||||
setIsCreating(false);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -57,6 +58,8 @@ import {
|
||||
import { DependencyTreeDialog } from './dependency-tree-dialog';
|
||||
import { isCursorModel, PROVIDER_PREFIXES } from '@automaker/types';
|
||||
|
||||
const logger = createLogger('EditFeatureDialog');
|
||||
|
||||
interface EditFeatureDialogProps {
|
||||
feature: Feature | null;
|
||||
onClose: () => void;
|
||||
@@ -248,7 +251,7 @@ export function EditFeatureDialog({
|
||||
toast.error(result?.error || 'Failed to enhance description');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Enhancement failed:', error);
|
||||
logger.error('Enhancement failed:', error);
|
||||
toast.error('Failed to enhance description');
|
||||
} finally {
|
||||
setIsEnhancing(false);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -34,6 +35,8 @@ import { useAppStore, Feature } from '@/store/app-store';
|
||||
import { toast } from 'sonner';
|
||||
import { LogViewer } from '@/components/ui/log-viewer';
|
||||
|
||||
const logger = createLogger('FeatureSuggestions');
|
||||
|
||||
interface FeatureSuggestionsDialogProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
@@ -176,7 +179,7 @@ export function FeatureSuggestionsDialog({
|
||||
setIsGenerating(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to generate suggestions:', error);
|
||||
logger.error('Failed to generate suggestions:', error);
|
||||
toast.error('Failed to start generation');
|
||||
setIsGenerating(false);
|
||||
}
|
||||
@@ -194,7 +197,7 @@ export function FeatureSuggestionsDialog({
|
||||
setIsGenerating(false);
|
||||
toast.info('Generation stopped');
|
||||
} catch (error) {
|
||||
console.error('Failed to stop generation:', error);
|
||||
logger.error('Failed to stop generation:', error);
|
||||
}
|
||||
}, [setIsGenerating]);
|
||||
|
||||
@@ -280,7 +283,7 @@ export function FeatureSuggestionsDialog({
|
||||
|
||||
onClose();
|
||||
} catch (error) {
|
||||
console.error('Failed to import features:', error);
|
||||
logger.error('Failed to import features:', error);
|
||||
toast.error('Failed to import features');
|
||||
} finally {
|
||||
setIsImporting(false);
|
||||
|
||||
@@ -13,6 +13,9 @@ import { toast } from 'sonner';
|
||||
import { useAutoMode } from '@/hooks/use-auto-mode';
|
||||
import { truncateDescription } from '@/lib/utils';
|
||||
import { getBlockingDependencies } from '@automaker/dependency-resolver';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
|
||||
const logger = createLogger('BoardActions');
|
||||
|
||||
interface UseBoardActionsProps {
|
||||
currentProject: { path: string; id: string } | null;
|
||||
@@ -112,8 +115,8 @@ export function useBoardActions({
|
||||
if (api?.worktree?.create) {
|
||||
const result = await api.worktree.create(currentProject.path, finalBranchName);
|
||||
if (result.success && result.worktree) {
|
||||
console.log(
|
||||
`[Board] Worktree for branch "${finalBranchName}" ${
|
||||
logger.info(
|
||||
`Worktree for branch "${finalBranchName}" ${
|
||||
result.worktree?.isNew ? 'created' : 'already exists'
|
||||
}`
|
||||
);
|
||||
@@ -125,8 +128,8 @@ export function useBoardActions({
|
||||
// Refresh worktree list in UI
|
||||
onWorktreeCreated?.();
|
||||
} else if (!result.success) {
|
||||
console.error(
|
||||
`[Board] Failed to create worktree for branch "${finalBranchName}":`,
|
||||
logger.error(
|
||||
`Failed to create worktree for branch "${finalBranchName}":`,
|
||||
result.error
|
||||
);
|
||||
toast.error('Failed to create worktree', {
|
||||
@@ -135,7 +138,7 @@ export function useBoardActions({
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error creating worktree:', error);
|
||||
logger.error('Error creating worktree:', error);
|
||||
toast.error('Failed to create worktree', {
|
||||
description: error instanceof Error ? error.message : 'An error occurred',
|
||||
});
|
||||
@@ -180,7 +183,7 @@ export function useBoardActions({
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('[Board] Error generating title:', error);
|
||||
logger.error('Error generating title:', error);
|
||||
// Clear generating flag on error
|
||||
const titleUpdates = { titleGenerating: false };
|
||||
updateFeature(createdFeature.id, titleUpdates);
|
||||
@@ -229,16 +232,16 @@ export function useBoardActions({
|
||||
if (api?.worktree?.create) {
|
||||
const result = await api.worktree.create(currentProject.path, finalBranchName);
|
||||
if (result.success) {
|
||||
console.log(
|
||||
`[Board] Worktree for branch "${finalBranchName}" ${
|
||||
logger.info(
|
||||
`Worktree for branch "${finalBranchName}" ${
|
||||
result.worktree?.isNew ? 'created' : 'already exists'
|
||||
}`
|
||||
);
|
||||
// Refresh worktree list in UI
|
||||
onWorktreeCreated?.();
|
||||
} else {
|
||||
console.error(
|
||||
`[Board] Failed to create worktree for branch "${finalBranchName}":`,
|
||||
logger.error(
|
||||
`Failed to create worktree for branch "${finalBranchName}":`,
|
||||
result.error
|
||||
);
|
||||
toast.error('Failed to create worktree', {
|
||||
@@ -247,7 +250,7 @@ export function useBoardActions({
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error creating worktree:', error);
|
||||
logger.error('Error creating worktree:', error);
|
||||
toast.error('Failed to create worktree', {
|
||||
description: error instanceof Error ? error.message : 'An error occurred',
|
||||
});
|
||||
@@ -292,7 +295,7 @@ export function useBoardActions({
|
||||
description: `Stopped and deleted: ${truncateDescription(feature.description)}`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Board] Error stopping feature before delete:', error);
|
||||
logger.error('Error stopping feature before delete:', error);
|
||||
toast.error('Failed to stop agent', {
|
||||
description: 'The feature will still be deleted.',
|
||||
});
|
||||
@@ -305,13 +308,13 @@ export function useBoardActions({
|
||||
for (const imagePathObj of feature.imagePaths) {
|
||||
try {
|
||||
await api.deleteFile(imagePathObj.path);
|
||||
console.log(`[Board] Deleted image: ${imagePathObj.path}`);
|
||||
logger.info(`Deleted image: ${imagePathObj.path}`);
|
||||
} catch (error) {
|
||||
console.error(`[Board] Failed to delete image ${imagePathObj.path}:`, error);
|
||||
logger.error(`Failed to delete image ${imagePathObj.path}:`, error);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[Board] Error deleting images for feature ${featureId}:`, error);
|
||||
logger.error(`Error deleting images for feature ${featureId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,7 +331,7 @@ export function useBoardActions({
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.autoMode) {
|
||||
console.error('Auto mode API not available');
|
||||
logger.error('Auto mode API not available');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -341,16 +344,13 @@ export function useBoardActions({
|
||||
);
|
||||
|
||||
if (result.success) {
|
||||
console.log(
|
||||
'[Board] Feature run started successfully, branch:',
|
||||
feature.branchName || 'default'
|
||||
);
|
||||
logger.info('Feature run started successfully, branch:', feature.branchName || 'default');
|
||||
} else {
|
||||
console.error('[Board] Failed to run feature:', result.error);
|
||||
logger.error('Failed to run feature:', result.error);
|
||||
await loadFeatures();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error running feature:', error);
|
||||
logger.error('Error running feature:', error);
|
||||
await loadFeatures();
|
||||
}
|
||||
},
|
||||
@@ -392,7 +392,7 @@ export function useBoardActions({
|
||||
updateFeature(feature.id, updates);
|
||||
// Must await to ensure feature status is persisted before starting agent
|
||||
await persistFeatureUpdate(feature.id, updates);
|
||||
console.log('[Board] Feature moved to in_progress, starting agent...');
|
||||
logger.info('Feature moved to in_progress, starting agent...');
|
||||
await handleRunFeature(feature);
|
||||
return true;
|
||||
},
|
||||
@@ -413,20 +413,20 @@ export function useBoardActions({
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.autoMode) {
|
||||
console.error('Auto mode API not available');
|
||||
logger.error('Auto mode API not available');
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await api.autoMode.verifyFeature(currentProject.path, feature.id);
|
||||
|
||||
if (result.success) {
|
||||
console.log('[Board] Feature verification started successfully');
|
||||
logger.info('Feature verification started successfully');
|
||||
} else {
|
||||
console.error('[Board] Failed to verify feature:', result.error);
|
||||
logger.error('Failed to verify feature:', result.error);
|
||||
await loadFeatures();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error verifying feature:', error);
|
||||
logger.error('Error verifying feature:', error);
|
||||
await loadFeatures();
|
||||
}
|
||||
},
|
||||
@@ -435,20 +435,20 @@ export function useBoardActions({
|
||||
|
||||
const handleResumeFeature = useCallback(
|
||||
async (feature: Feature) => {
|
||||
console.log('[Board] handleResumeFeature called for feature:', feature.id);
|
||||
logger.info('handleResumeFeature called for feature:', feature.id);
|
||||
if (!currentProject) {
|
||||
console.error('[Board] No current project');
|
||||
logger.error('No current project');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.autoMode) {
|
||||
console.error('[Board] Auto mode API not available');
|
||||
logger.error('Auto mode API not available');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[Board] Calling resumeFeature API...', {
|
||||
logger.info('Calling resumeFeature API...', {
|
||||
projectPath: currentProject.path,
|
||||
featureId: feature.id,
|
||||
useWorktrees,
|
||||
@@ -460,16 +460,16 @@ export function useBoardActions({
|
||||
useWorktrees
|
||||
);
|
||||
|
||||
console.log('[Board] resumeFeature result:', result);
|
||||
logger.info('resumeFeature result:', result);
|
||||
|
||||
if (result.success) {
|
||||
console.log('[Board] Feature resume started successfully');
|
||||
logger.info('Feature resume started successfully');
|
||||
} else {
|
||||
console.error('[Board] Failed to resume feature:', result.error);
|
||||
logger.error('Failed to resume feature:', result.error);
|
||||
await loadFeatures();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error resuming feature:', error);
|
||||
logger.error('Error resuming feature:', error);
|
||||
await loadFeatures();
|
||||
}
|
||||
},
|
||||
@@ -523,7 +523,7 @@ export function useBoardActions({
|
||||
|
||||
const api = getElectronAPI();
|
||||
if (!api?.autoMode?.followUpFeature) {
|
||||
console.error('Follow-up feature API not available');
|
||||
logger.error('Follow-up feature API not available');
|
||||
toast.error('Follow-up not available', {
|
||||
description: 'This feature is not available in the current version.',
|
||||
});
|
||||
@@ -559,7 +559,7 @@ export function useBoardActions({
|
||||
// No worktreePath - server derives from feature.branchName
|
||||
)
|
||||
.catch((error) => {
|
||||
console.error('[Board] Error sending follow-up:', error);
|
||||
logger.error('Error sending follow-up:', error);
|
||||
toast.error('Failed to send follow-up', {
|
||||
description: error instanceof Error ? error.message : 'An error occurred',
|
||||
});
|
||||
@@ -587,7 +587,7 @@ export function useBoardActions({
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.autoMode?.commitFeature) {
|
||||
console.error('Commit feature API not available');
|
||||
logger.error('Commit feature API not available');
|
||||
toast.error('Commit not available', {
|
||||
description: 'This feature is not available in the current version.',
|
||||
});
|
||||
@@ -610,14 +610,14 @@ export function useBoardActions({
|
||||
// Refresh worktree selector to update commit counts
|
||||
onWorktreeCreated?.();
|
||||
} else {
|
||||
console.error('[Board] Failed to commit feature:', result.error);
|
||||
logger.error('Failed to commit feature:', result.error);
|
||||
toast.error('Failed to commit feature', {
|
||||
description: result.error || 'An error occurred',
|
||||
});
|
||||
await loadFeatures();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error committing feature:', error);
|
||||
logger.error('Error committing feature:', error);
|
||||
toast.error('Failed to commit feature', {
|
||||
description: error instanceof Error ? error.message : 'An error occurred',
|
||||
});
|
||||
@@ -634,7 +634,7 @@ export function useBoardActions({
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.worktree?.mergeFeature) {
|
||||
console.error('Worktree API not available');
|
||||
logger.error('Worktree API not available');
|
||||
toast.error('Merge not available', {
|
||||
description: 'This feature is not available in the current version.',
|
||||
});
|
||||
@@ -651,13 +651,13 @@ export function useBoardActions({
|
||||
)}`,
|
||||
});
|
||||
} else {
|
||||
console.error('[Board] Failed to merge feature:', result.error);
|
||||
logger.error('Failed to merge feature:', result.error);
|
||||
toast.error('Failed to merge feature', {
|
||||
description: result.error || 'An error occurred',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Error merging feature:', error);
|
||||
logger.error('Error merging feature:', error);
|
||||
toast.error('Failed to merge feature', {
|
||||
description: error instanceof Error ? error.message : 'An error occurred',
|
||||
});
|
||||
@@ -747,7 +747,7 @@ export function useBoardActions({
|
||||
: `Stopped working on: ${truncateDescription(feature.description)}`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Board] Error stopping feature:', error);
|
||||
logger.error('Error stopping feature:', error);
|
||||
toast.error('Failed to stop agent', {
|
||||
description: error instanceof Error ? error.message : 'An error occurred',
|
||||
});
|
||||
@@ -857,7 +857,7 @@ export function useBoardActions({
|
||||
try {
|
||||
await autoMode.stopFeature(feature.id);
|
||||
} catch (error) {
|
||||
console.error('[Board] Error stopping feature before archive:', error);
|
||||
logger.error('Error stopping feature before archive:', error);
|
||||
}
|
||||
}
|
||||
// Archive the feature by setting status to completed
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { DragStartEvent, DragEndEvent } from '@dnd-kit/core';
|
||||
import { Feature } from '@/store/app-store';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { toast } from 'sonner';
|
||||
import { COLUMNS, ColumnId } from '../constants';
|
||||
|
||||
const logger = createLogger('BoardDragDrop');
|
||||
|
||||
interface UseBoardDragDropProps {
|
||||
features: Feature[];
|
||||
currentProject: { path: string; id: string } | null;
|
||||
@@ -63,7 +66,7 @@ export function useBoardDragDrop({
|
||||
if (draggedFeature.status === 'in_progress') {
|
||||
// Only allow dragging in_progress if it's not currently running
|
||||
if (isRunningTask) {
|
||||
console.log('[Board] Cannot drag feature - currently running');
|
||||
logger.debug('Cannot drag feature - currently running');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
|
||||
const logger = createLogger('BoardEffects');
|
||||
|
||||
interface UseBoardEffectsProps {
|
||||
currentProject: { path: string; id: string } | null;
|
||||
@@ -70,12 +73,7 @@ export function useBoardEffects({
|
||||
if (!api.specRegeneration) return;
|
||||
|
||||
const unsubscribe = api.specRegeneration.onEvent((event) => {
|
||||
console.log(
|
||||
'[BoardView] Spec regeneration event:',
|
||||
event.type,
|
||||
'for project:',
|
||||
event.projectPath
|
||||
);
|
||||
logger.info('Spec regeneration event:', event.type, 'for project:', event.projectPath);
|
||||
|
||||
if (event.projectPath !== specCreatingForProject) {
|
||||
return;
|
||||
@@ -108,7 +106,7 @@ export function useBoardEffects({
|
||||
const { clearRunningTasks, addRunningTask } = useAppStore.getState();
|
||||
|
||||
if (status.runningFeatures) {
|
||||
console.log('[Board] Syncing running tasks from backend:', status.runningFeatures);
|
||||
logger.info('Syncing running tasks from backend:', status.runningFeatures);
|
||||
|
||||
clearRunningTasks(projectId);
|
||||
|
||||
@@ -118,7 +116,7 @@ export function useBoardEffects({
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Board] Failed to sync running tasks:', error);
|
||||
logger.error('Failed to sync running tasks:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@ import { useState, useCallback, useEffect, useRef } from 'react';
|
||||
import { useAppStore, Feature } from '@/store/app-store';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
|
||||
const logger = createLogger('BoardFeatures');
|
||||
|
||||
interface UseBoardFeaturesProps {
|
||||
currentProject: { path: string; id: string } | null;
|
||||
@@ -32,7 +35,7 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
|
||||
// If project switched, mark it but don't clear features yet
|
||||
// We'll clear after successful API load to prevent data loss
|
||||
if (isProjectSwitch) {
|
||||
console.log(`[BoardView] Project switch detected: ${previousPath} -> ${currentPath}`);
|
||||
logger.info(`Project switch detected: ${previousPath} -> ${currentPath}`);
|
||||
isSwitchingProjectRef.current = true;
|
||||
isInitialLoadRef.current = true;
|
||||
}
|
||||
@@ -48,7 +51,7 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api.features) {
|
||||
console.error('[BoardView] Features API not available');
|
||||
logger.error('Features API not available');
|
||||
// Keep cached features if API is unavailable
|
||||
return;
|
||||
}
|
||||
@@ -73,7 +76,7 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
|
||||
setPersistedCategories([]);
|
||||
}
|
||||
} else if (!result.success && result.error) {
|
||||
console.error('[BoardView] API returned error:', result.error);
|
||||
logger.error('API returned error:', result.error);
|
||||
// If it's a new project or the error indicates no features found,
|
||||
// that's expected - start with empty array
|
||||
if (isProjectSwitch) {
|
||||
@@ -83,7 +86,7 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
|
||||
// Otherwise keep cached features
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load features:', error);
|
||||
logger.error('Failed to load features:', error);
|
||||
// On error, keep existing cached features for the current project
|
||||
// Only clear on project switch if we have no features from server
|
||||
if (isProjectSwitch && cachedFeatures.length === 0) {
|
||||
@@ -115,7 +118,7 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
|
||||
setPersistedCategories([]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load categories:', error);
|
||||
logger.error('Failed to load categories:', error);
|
||||
// If file doesn't exist, ensure categories are cleared
|
||||
setPersistedCategories([]);
|
||||
}
|
||||
@@ -147,7 +150,7 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
|
||||
setPersistedCategories(categories);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to save category:', error);
|
||||
logger.error('Failed to save category:', error);
|
||||
}
|
||||
},
|
||||
[currentProject, persistedCategories]
|
||||
@@ -165,7 +168,7 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
|
||||
currentProject &&
|
||||
event.projectPath === currentProject.path
|
||||
) {
|
||||
console.log('[BoardView] Spec regeneration complete, refreshing features');
|
||||
logger.info('Spec regeneration complete, refreshing features');
|
||||
loadFeatures();
|
||||
}
|
||||
});
|
||||
@@ -190,27 +193,27 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
|
||||
|
||||
if (event.type === 'auto_mode_feature_complete') {
|
||||
// Reload features when a feature is completed
|
||||
console.log('[Board] Feature completed, reloading features...');
|
||||
logger.info('Feature completed, reloading features...');
|
||||
loadFeatures();
|
||||
// Play ding sound when feature is done (unless muted)
|
||||
const { muteDoneSound } = useAppStore.getState();
|
||||
if (!muteDoneSound) {
|
||||
const audio = new Audio('/sounds/ding.mp3');
|
||||
audio.play().catch((err) => console.warn('Could not play ding sound:', err));
|
||||
audio.play().catch((err) => logger.warn('Could not play ding sound:', err));
|
||||
}
|
||||
} else if (event.type === 'plan_approval_required') {
|
||||
// Reload features when plan is generated and requires approval
|
||||
// This ensures the feature card shows the "Approve Plan" button
|
||||
console.log('[Board] Plan approval required, reloading features...');
|
||||
logger.info('Plan approval required, reloading features...');
|
||||
loadFeatures();
|
||||
} else if (event.type === 'pipeline_step_started') {
|
||||
// Pipeline steps update the feature status to `pipeline_*` before the step runs.
|
||||
// Reload so the card moves into the correct pipeline column immediately.
|
||||
console.log('[Board] Pipeline step started, reloading features...');
|
||||
logger.info('Pipeline step started, reloading features...');
|
||||
loadFeatures();
|
||||
} else if (event.type === 'auto_mode_error') {
|
||||
// Reload features when an error occurs (feature moved to waiting_approval)
|
||||
console.log('[Board] Feature error, reloading features...', event.error);
|
||||
logger.info('Feature error, reloading features...', event.error);
|
||||
|
||||
// Remove from running tasks so it moves to the correct column
|
||||
if (event.featureId) {
|
||||
|
||||
@@ -2,6 +2,9 @@ import { useCallback } from 'react';
|
||||
import { Feature } from '@/store/app-store';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
|
||||
const logger = createLogger('BoardPersistence');
|
||||
|
||||
interface UseBoardPersistenceProps {
|
||||
currentProject: { path: string; id: string } | null;
|
||||
@@ -18,7 +21,7 @@ export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api.features) {
|
||||
console.error('[BoardView] Features API not available');
|
||||
logger.error('Features API not available');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -27,7 +30,7 @@ export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps
|
||||
updateFeature(result.feature.id, result.feature);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to persist feature update:', error);
|
||||
logger.error('Failed to persist feature update:', error);
|
||||
}
|
||||
},
|
||||
[currentProject, updateFeature]
|
||||
@@ -41,7 +44,7 @@ export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api.features) {
|
||||
console.error('[BoardView] Features API not available');
|
||||
logger.error('Features API not available');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,7 +53,7 @@ export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps
|
||||
updateFeature(result.feature.id, result.feature);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to persist feature creation:', error);
|
||||
logger.error('Failed to persist feature creation:', error);
|
||||
}
|
||||
},
|
||||
[currentProject, updateFeature]
|
||||
@@ -64,13 +67,13 @@ export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api.features) {
|
||||
console.error('[BoardView] Features API not available');
|
||||
logger.error('Features API not available');
|
||||
return;
|
||||
}
|
||||
|
||||
await api.features.delete(currentProject.path, featureId);
|
||||
} catch (error) {
|
||||
console.error('Failed to persist feature deletion:', error);
|
||||
logger.error('Failed to persist feature deletion:', error);
|
||||
}
|
||||
},
|
||||
[currentProject]
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import type { BranchInfo, GitRepoStatus } from '../types';
|
||||
|
||||
const logger = createLogger('Branches');
|
||||
|
||||
export function useBranches() {
|
||||
const [branches, setBranches] = useState<BranchInfo[]>([]);
|
||||
const [aheadCount, setAheadCount] = useState(0);
|
||||
@@ -26,7 +29,7 @@ export function useBranches() {
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.worktree?.listBranches) {
|
||||
console.warn('List branches API not available');
|
||||
logger.warn('List branches API not available');
|
||||
return;
|
||||
}
|
||||
const result = await api.worktree.listBranches(worktreePath);
|
||||
@@ -45,11 +48,11 @@ export function useBranches() {
|
||||
setGitRepoStatus({ isGitRepo: true, hasCommits: false });
|
||||
} else if (!result.success) {
|
||||
// Other errors - log them
|
||||
console.warn('Failed to fetch branches:', result.error);
|
||||
logger.warn('Failed to fetch branches:', result.error);
|
||||
resetBranchState();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch branches:', error);
|
||||
logger.error('Failed to fetch branches:', error);
|
||||
resetBranchState();
|
||||
// Reset git status to unknown state on network/API errors
|
||||
setGitRepoStatus({ isGitRepo: true, hasCommits: true });
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('DefaultEditor');
|
||||
|
||||
export function useDefaultEditor() {
|
||||
const [defaultEditorName, setDefaultEditorName] = useState<string>('Editor');
|
||||
|
||||
@@ -15,7 +18,7 @@ export function useDefaultEditor() {
|
||||
setDefaultEditorName(result.result.editorName);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch default editor:', error);
|
||||
logger.error('Failed to fetch default editor:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { normalizePath } from '@/lib/utils';
|
||||
import { toast } from 'sonner';
|
||||
import type { DevServerInfo, WorktreeInfo } from '../types';
|
||||
|
||||
const logger = createLogger('DevServers');
|
||||
|
||||
interface UseDevServersOptions {
|
||||
projectPath: string;
|
||||
}
|
||||
@@ -27,7 +30,7 @@ export function useDevServers({ projectPath }: UseDevServersOptions) {
|
||||
setRunningDevServers(serversMap);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch dev servers:', error);
|
||||
logger.error('Failed to fetch dev servers:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -73,7 +76,7 @@ export function useDevServers({ projectPath }: UseDevServersOptions) {
|
||||
toast.error(result.error || 'Failed to start dev server');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Start dev server failed:', error);
|
||||
logger.error('Start dev server failed:', error);
|
||||
toast.error('Failed to start dev server');
|
||||
} finally {
|
||||
setIsStartingDevServer(false);
|
||||
@@ -105,7 +108,7 @@ export function useDevServers({ projectPath }: UseDevServersOptions) {
|
||||
toast.error(result.error || 'Failed to stop dev server');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Stop dev server failed:', error);
|
||||
logger.error('Stop dev server failed:', error);
|
||||
toast.error('Failed to stop dev server');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
import type { WorktreeInfo } from '../types';
|
||||
|
||||
const logger = createLogger('WorktreeActions');
|
||||
|
||||
// Error codes that need special user-friendly handling
|
||||
const GIT_STATUS_ERROR_CODES = ['NOT_GIT_REPO', 'NO_COMMITS'] as const;
|
||||
type GitStatusErrorCode = (typeof GIT_STATUS_ERROR_CODES)[number];
|
||||
@@ -56,7 +59,7 @@ export function useWorktreeActions({ fetchWorktrees, fetchBranches }: UseWorktre
|
||||
toast.error(result.error || 'Failed to switch branch');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Switch branch failed:', error);
|
||||
logger.error('Switch branch failed:', error);
|
||||
toast.error('Failed to switch branch');
|
||||
} finally {
|
||||
setIsSwitching(false);
|
||||
@@ -84,7 +87,7 @@ export function useWorktreeActions({ fetchWorktrees, fetchBranches }: UseWorktre
|
||||
toast.error(result.error || 'Failed to pull latest changes');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Pull failed:', error);
|
||||
logger.error('Pull failed:', error);
|
||||
toast.error('Failed to pull latest changes');
|
||||
} finally {
|
||||
setIsPulling(false);
|
||||
@@ -113,7 +116,7 @@ export function useWorktreeActions({ fetchWorktrees, fetchBranches }: UseWorktre
|
||||
toast.error(result.error || 'Failed to push changes');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Push failed:', error);
|
||||
logger.error('Push failed:', error);
|
||||
toast.error('Failed to push changes');
|
||||
} finally {
|
||||
setIsPushing(false);
|
||||
@@ -126,7 +129,7 @@ export function useWorktreeActions({ fetchWorktrees, fetchBranches }: UseWorktre
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.worktree?.openInEditor) {
|
||||
console.warn('Open in editor API not available');
|
||||
logger.warn('Open in editor API not available');
|
||||
return;
|
||||
}
|
||||
const result = await api.worktree.openInEditor(worktree.path);
|
||||
@@ -136,7 +139,7 @@ export function useWorktreeActions({ fetchWorktrees, fetchBranches }: UseWorktre
|
||||
toast.error(result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Open in editor failed:', error);
|
||||
logger.error('Open in editor failed:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { pathsEqual } from '@/lib/utils';
|
||||
import type { WorktreeInfo } from '../types';
|
||||
|
||||
const logger = createLogger('Worktrees');
|
||||
|
||||
interface UseWorktreesOptions {
|
||||
projectPath: string;
|
||||
refreshTrigger?: number;
|
||||
@@ -33,7 +36,7 @@ export function useWorktrees({
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.worktree?.listAll) {
|
||||
console.warn('Worktree API not available');
|
||||
logger.warn('Worktree API not available');
|
||||
return;
|
||||
}
|
||||
const result = await api.worktree.listAll(projectPath, true);
|
||||
@@ -44,7 +47,7 @@ export function useWorktrees({
|
||||
// Return removed worktrees so they can be handled by the caller
|
||||
return result.removedWorktrees;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch worktrees:', error);
|
||||
logger.error('Failed to fetch worktrees:', error);
|
||||
return undefined;
|
||||
} finally {
|
||||
if (!silent) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
@@ -6,6 +7,8 @@ import { Button } from '@/components/ui/button';
|
||||
import { File, Folder, FolderOpen, ChevronRight, ChevronDown, RefreshCw, Code } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('CodeView');
|
||||
|
||||
interface FileTreeNode {
|
||||
name: string;
|
||||
path: string;
|
||||
@@ -60,7 +63,7 @@ export function CodeView() {
|
||||
setFileTree(entries);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load file tree:', error);
|
||||
logger.error('Failed to load file tree:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -91,7 +94,7 @@ export function CodeView() {
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load subdirectory:', error);
|
||||
logger.error('Failed to load subdirectory:', error);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
@@ -107,7 +110,7 @@ export function CodeView() {
|
||||
setSelectedFile(path);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load file:', error);
|
||||
logger.error('Failed to load file:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState, useCallback, useMemo, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { getHttpApiClient } from '@/lib/http-api-client';
|
||||
@@ -38,6 +39,8 @@ import {
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('ContextView');
|
||||
import { sanitizeFilename } from '@/lib/image-utils';
|
||||
import { Markdown } from '../ui/markdown';
|
||||
import {
|
||||
@@ -160,7 +163,7 @@ export function ContextView() {
|
||||
const metadataPath = `${contextPath}/context-metadata.json`;
|
||||
await api.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
||||
} catch (error) {
|
||||
console.error('Failed to save metadata:', error);
|
||||
logger.error('Failed to save metadata:', error);
|
||||
}
|
||||
},
|
||||
[getContextPath]
|
||||
@@ -202,7 +205,7 @@ export function ContextView() {
|
||||
setContextFiles(files);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load context files:', error);
|
||||
logger.error('Failed to load context files:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -223,7 +226,7 @@ export function ContextView() {
|
||||
setHasChanges(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load file content:', error);
|
||||
logger.error('Failed to load file content:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -247,7 +250,7 @@ export function ContextView() {
|
||||
setSelectedFile({ ...selectedFile, content: editedContent });
|
||||
setHasChanges(false);
|
||||
} catch (error) {
|
||||
console.error('Failed to save file:', error);
|
||||
logger.error('Failed to save file:', error);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
@@ -279,7 +282,7 @@ export function ContextView() {
|
||||
result.error || `Automaker couldn't generate a description for “${fileName}”.`;
|
||||
toast.error('Failed to generate description', { description: message });
|
||||
} catch (error) {
|
||||
console.error('Failed to generate description:', error);
|
||||
logger.error('Failed to generate description:', error);
|
||||
const message =
|
||||
error instanceof Error
|
||||
? error.message
|
||||
@@ -315,7 +318,7 @@ export function ContextView() {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to generate description:', error);
|
||||
logger.error('Failed to generate description:', error);
|
||||
} finally {
|
||||
// Remove from generating set
|
||||
setGeneratingDescriptions((prev) => {
|
||||
@@ -401,7 +404,7 @@ export function ContextView() {
|
||||
// For images, use the path in the images directory
|
||||
generateDescriptionAsync(imagePathForDescription || filePath, fileName, isImage);
|
||||
} catch (error) {
|
||||
console.error('Failed to upload file:', error);
|
||||
logger.error('Failed to upload file:', error);
|
||||
toast.error('Failed to upload file', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -492,7 +495,7 @@ export function ContextView() {
|
||||
setNewMarkdownDescription('');
|
||||
setNewMarkdownContent('');
|
||||
} catch (error) {
|
||||
console.error('Failed to create markdown:', error);
|
||||
logger.error('Failed to create markdown:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -515,7 +518,7 @@ export function ContextView() {
|
||||
setHasChanges(false);
|
||||
await loadContextFiles();
|
||||
} catch (error) {
|
||||
console.error('Failed to delete file:', error);
|
||||
logger.error('Failed to delete file:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -537,14 +540,14 @@ export function ContextView() {
|
||||
// Check if file with new name already exists
|
||||
const exists = await api.exists(newPath);
|
||||
if (exists) {
|
||||
console.error('A file with this name already exists');
|
||||
logger.error('A file with this name already exists');
|
||||
return;
|
||||
}
|
||||
|
||||
// Read current file content
|
||||
const result = await api.readFile(selectedFile.path);
|
||||
if (!result.success || result.content === undefined) {
|
||||
console.error('Failed to read file for rename');
|
||||
logger.error('Failed to read file for rename');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -578,7 +581,7 @@ export function ContextView() {
|
||||
};
|
||||
setSelectedFile(renamedFile);
|
||||
} catch (error) {
|
||||
console.error('Failed to rename file:', error);
|
||||
logger.error('Failed to rename file:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -603,7 +606,7 @@ export function ContextView() {
|
||||
setEditDescriptionValue('');
|
||||
setEditDescriptionFileName('');
|
||||
} catch (error) {
|
||||
console.error('Failed to save description:', error);
|
||||
logger.error('Failed to save description:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -634,7 +637,7 @@ export function ContextView() {
|
||||
|
||||
await loadContextFiles();
|
||||
} catch (error) {
|
||||
console.error('Failed to delete file:', error);
|
||||
logger.error('Failed to delete file:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useCallback, useMemo } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { CircleDot, RefreshCw } from 'lucide-react';
|
||||
import { getElectronAPI, GitHubIssue, IssueValidationResult } from '@/lib/electron';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
@@ -14,6 +15,8 @@ import { formatDate, getFeaturePriority } from './github-issues-view/utils';
|
||||
import { useModelOverride } from '@/components/shared';
|
||||
import type { ValidateIssueOptions } from './github-issues-view/types';
|
||||
|
||||
const logger = createLogger('GitHubIssuesView');
|
||||
|
||||
export function GitHubIssuesView() {
|
||||
const [selectedIssue, setSelectedIssue] = useState<GitHubIssue | null>(null);
|
||||
const [validationResult, setValidationResult] = useState<IssueValidationResult | null>(null);
|
||||
@@ -118,7 +121,7 @@ export function GitHubIssuesView() {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[GitHubIssuesView] Convert to task error:', err);
|
||||
logger.error('Convert to task error:', err);
|
||||
toast.error(err instanceof Error ? err.message : 'Failed to create task');
|
||||
}
|
||||
},
|
||||
@@ -247,7 +250,7 @@ export function GitHubIssuesView() {
|
||||
confirmText="Re-validate"
|
||||
onConfirm={() => {
|
||||
if (selectedIssue && pendingRevalidateOptions) {
|
||||
console.log('[GitHubIssuesView] Revalidating with options:', {
|
||||
logger.info('Revalidating with options:', {
|
||||
commentsCount: pendingRevalidateOptions.comments?.length ?? 0,
|
||||
linkedPRsCount: pendingRevalidateOptions.linkedPRs?.length ?? 0,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI, GitHubIssue } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('GitHubIssues');
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
export function useGithubIssues() {
|
||||
@@ -38,7 +41,7 @@ export function useGithubIssues() {
|
||||
}
|
||||
} catch (err) {
|
||||
if (isMountedRef.current) {
|
||||
console.error('[GitHubIssuesView] Error fetching issues:', err);
|
||||
logger.error('Error fetching issues:', err);
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch issues');
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI, GitHubComment } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('IssueComments');
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
interface UseIssueCommentsResult {
|
||||
@@ -69,7 +72,7 @@ export function useIssueComments(issueNumber: number | null): UseIssueCommentsRe
|
||||
}
|
||||
} catch (err) {
|
||||
if (isMountedRef.current) {
|
||||
console.error('[useIssueComments] Error fetching comments:', err);
|
||||
logger.error('Error fetching comments:', err);
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch comments');
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
getElectronAPI,
|
||||
GitHubIssue,
|
||||
@@ -12,6 +13,8 @@ import { useAppStore } from '@/store/app-store';
|
||||
import { toast } from 'sonner';
|
||||
import { isValidationStale } from '../utils';
|
||||
|
||||
const logger = createLogger('IssueValidation');
|
||||
|
||||
/**
|
||||
* Extract model string from PhaseModelEntry or string (handles both formats)
|
||||
*/
|
||||
@@ -78,7 +81,7 @@ export function useIssueValidation({
|
||||
}
|
||||
} catch (err) {
|
||||
if (isMounted) {
|
||||
console.error('[GitHubIssuesView] Failed to load cached validations:', err);
|
||||
logger.error('Failed to load cached validations:', err);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -107,7 +110,7 @@ export function useIssueValidation({
|
||||
}
|
||||
} catch (err) {
|
||||
if (isMounted) {
|
||||
console.error('[GitHubIssuesView] Failed to load running validations:', err);
|
||||
logger.error('Failed to load running validations:', err);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -283,7 +286,7 @@ export function useIssueValidation({
|
||||
// On success, the result will come through the event stream
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[GitHubIssuesView] Validation error:', err);
|
||||
logger.error('Validation error:', err);
|
||||
toast.error(err instanceof Error ? err.message : 'Failed to validate issue');
|
||||
}
|
||||
},
|
||||
@@ -325,7 +328,7 @@ export function useIssueValidation({
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[GitHubIssuesView] Failed to mark validation as viewed:', err);
|
||||
logger.error('Failed to mark validation as viewed:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { GitPullRequest, Loader2, RefreshCw, ExternalLink, GitMerge, X } from 'lucide-react';
|
||||
import { getElectronAPI, GitHubPR } from '@/lib/electron';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
@@ -6,6 +7,8 @@ import { Button } from '@/components/ui/button';
|
||||
import { Markdown } from '@/components/ui/markdown';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('GitHubPRsView');
|
||||
|
||||
export function GitHubPRsView() {
|
||||
const [openPRs, setOpenPRs] = useState<GitHubPR[]>([]);
|
||||
const [mergedPRs, setMergedPRs] = useState<GitHubPR[]>([]);
|
||||
@@ -35,7 +38,7 @@ export function GitHubPRsView() {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[GitHubPRsView] Error fetching PRs:', err);
|
||||
logger.error('Error fetching PRs:', err);
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch pull requests');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useCallback, useRef, useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore, Feature } from '@/store/app-store';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -12,6 +13,8 @@ import { toast } from 'sonner';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
import { getDefaultWorkspaceDirectory, saveLastProjectDirectory } from '@/lib/workspace-config';
|
||||
|
||||
const logger = createLogger('InterviewView');
|
||||
|
||||
interface InterviewMessage {
|
||||
id: string;
|
||||
role: 'user' | 'assistant';
|
||||
@@ -97,7 +100,7 @@ export function InterviewView() {
|
||||
setProjectPath(defaultDir);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load default workspace directory:', error);
|
||||
logger.error('Failed to load default workspace directory:', error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -367,7 +370,7 @@ export function InterviewView() {
|
||||
addProject(project);
|
||||
setCurrentProject(project);
|
||||
} catch (error) {
|
||||
console.error('Failed to create project:', error);
|
||||
logger.error('Failed to create project:', error);
|
||||
setIsGenerating(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { Bot, Folder, Loader2, RefreshCw, Square, Activity, FileText } from 'lucide-react';
|
||||
import { getElectronAPI, RunningAgent } from '@/lib/electron';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
@@ -7,6 +8,8 @@ import { cn } from '@/lib/utils';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
import { AgentOutputModal } from './board-view/dialogs/agent-output-modal';
|
||||
|
||||
const logger = createLogger('RunningAgentsView');
|
||||
|
||||
export function RunningAgentsView() {
|
||||
const [runningAgents, setRunningAgents] = useState<RunningAgent[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -25,7 +28,7 @@ export function RunningAgentsView() {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[RunningAgentsView] Error fetching running agents:', error);
|
||||
logger.error('Error fetching running agents:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setRefreshing(false);
|
||||
@@ -78,7 +81,7 @@ export function RunningAgentsView() {
|
||||
fetchRunningAgents();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[RunningAgentsView] Error stopping agent:', error);
|
||||
logger.error('Error stopping agent:', error);
|
||||
}
|
||||
},
|
||||
[fetchRunningAgents]
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
const logger = createLogger('ApiKeyManagement');
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import type { ProviderConfigParams } from '@/config/api-providers';
|
||||
|
||||
@@ -60,7 +63,7 @@ export function useApiKeyManagement() {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to check API key status:', error);
|
||||
logger.error('Failed to check API key status:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useSetupStore } from '@/store/setup-store';
|
||||
|
||||
const logger = createLogger('CliStatus');
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
interface CliStatusResult {
|
||||
@@ -40,7 +43,7 @@ export function useCliStatus() {
|
||||
const status = await api.checkClaudeCli();
|
||||
setClaudeCliStatus(status);
|
||||
} catch (error) {
|
||||
console.error('Failed to check Claude CLI status:', error);
|
||||
logger.error('Failed to check Claude CLI status:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +87,7 @@ export function useCliStatus() {
|
||||
setClaudeAuthStatus(authStatus);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to check Claude auth status:', error);
|
||||
logger.error('Failed to check Claude auth status:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -102,7 +105,7 @@ export function useCliStatus() {
|
||||
setClaudeCliStatus(status);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh Claude CLI status:', error);
|
||||
logger.error('Failed to refresh Claude CLI status:', error);
|
||||
} finally {
|
||||
setIsCheckingClaudeCli(false);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
const logger = createLogger('CursorPermissions');
|
||||
import { getHttpApiClient } from '@/lib/http-api-client';
|
||||
import type { CursorPermissionProfile } from '@automaker/types';
|
||||
|
||||
@@ -41,7 +44,7 @@ export function useCursorPermissions(projectPath?: string) {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load Cursor permissions:', error);
|
||||
logger.error('Failed to load Cursor permissions:', error);
|
||||
} finally {
|
||||
setIsLoadingPermissions(false);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
const logger = createLogger('CursorStatus');
|
||||
import { getHttpApiClient } from '@/lib/http-api-client';
|
||||
import { useSetupStore } from '@/store/setup-store';
|
||||
|
||||
@@ -48,7 +51,7 @@ export function useCursorStatus() {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load Cursor settings:', error);
|
||||
logger.error('Failed to load Cursor settings:', error);
|
||||
toast.error('Failed to load Cursor settings');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
const logger = createLogger('MCPServers');
|
||||
import { toast } from 'sonner';
|
||||
import type { MCPServerConfig } from '@automaker/types';
|
||||
import { syncSettingsToServer, loadMCPServersFromServer } from '@/hooks/use-settings-migration';
|
||||
@@ -72,7 +75,7 @@ export function useMCPServers() {
|
||||
// Auto-load MCP servers from settings file on mount
|
||||
useEffect(() => {
|
||||
loadMCPServersFromServer().catch((error) => {
|
||||
console.error('Failed to load MCP servers on mount:', error);
|
||||
logger.error('Failed to load MCP servers on mount:', error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
@@ -431,7 +434,7 @@ export function useMCPServers() {
|
||||
|
||||
if (serverData.type === 'stdio') {
|
||||
if (!serverConfig.command) {
|
||||
console.warn(`Skipping ${name}: no command specified`);
|
||||
logger.warn(`Skipping ${name}: no command specified`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -458,7 +461,7 @@ export function useMCPServers() {
|
||||
}
|
||||
} else {
|
||||
if (!serverConfig.url) {
|
||||
console.warn(`Skipping ${name}: no url specified`);
|
||||
logger.warn(`Skipping ${name}: no url specified`);
|
||||
return null;
|
||||
}
|
||||
serverData.url = serverConfig.url as string;
|
||||
@@ -491,7 +494,7 @@ export function useMCPServers() {
|
||||
const name = config.name as string;
|
||||
|
||||
if (!name) {
|
||||
console.warn('Skipping server: no name specified');
|
||||
logger.warn('Skipping server: no name specified');
|
||||
skippedCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useSetupStore } from '@/store/setup-store';
|
||||
import { StepIndicator } from './setup-view/components';
|
||||
import {
|
||||
@@ -10,6 +11,8 @@ import {
|
||||
} from './setup-view/steps';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
|
||||
const logger = createLogger('SetupView');
|
||||
|
||||
// Main Setup View
|
||||
export function SetupView() {
|
||||
const { currentStep, setCurrentStep, completeSetup, setSkipClaudeSetup } = useSetupStore();
|
||||
@@ -28,33 +31,33 @@ export function SetupView() {
|
||||
const currentIndex = steps.indexOf(getStepName());
|
||||
|
||||
const handleNext = (from: string) => {
|
||||
console.log('[Setup Flow] handleNext called from:', from, 'currentStep:', currentStep);
|
||||
logger.debug('[Setup Flow] handleNext called from:', from, 'currentStep:', currentStep);
|
||||
switch (from) {
|
||||
case 'welcome':
|
||||
console.log('[Setup Flow] Moving to theme step');
|
||||
logger.debug('[Setup Flow] Moving to theme step');
|
||||
setCurrentStep('theme');
|
||||
break;
|
||||
case 'theme':
|
||||
console.log('[Setup Flow] Moving to claude_detect step');
|
||||
logger.debug('[Setup Flow] Moving to claude_detect step');
|
||||
setCurrentStep('claude_detect');
|
||||
break;
|
||||
case 'claude':
|
||||
console.log('[Setup Flow] Moving to cursor step');
|
||||
logger.debug('[Setup Flow] Moving to cursor step');
|
||||
setCurrentStep('cursor');
|
||||
break;
|
||||
case 'cursor':
|
||||
console.log('[Setup Flow] Moving to github step');
|
||||
logger.debug('[Setup Flow] Moving to github step');
|
||||
setCurrentStep('github');
|
||||
break;
|
||||
case 'github':
|
||||
console.log('[Setup Flow] Moving to complete step');
|
||||
logger.debug('[Setup Flow] Moving to complete step');
|
||||
setCurrentStep('complete');
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const handleBack = (from: string) => {
|
||||
console.log('[Setup Flow] handleBack called from:', from);
|
||||
logger.debug('[Setup Flow] handleBack called from:', from);
|
||||
switch (from) {
|
||||
case 'theme':
|
||||
setCurrentStep('welcome');
|
||||
@@ -72,25 +75,25 @@ export function SetupView() {
|
||||
};
|
||||
|
||||
const handleSkipClaude = () => {
|
||||
console.log('[Setup Flow] Skipping Claude setup');
|
||||
logger.debug('[Setup Flow] Skipping Claude setup');
|
||||
setSkipClaudeSetup(true);
|
||||
setCurrentStep('cursor');
|
||||
};
|
||||
|
||||
const handleSkipCursor = () => {
|
||||
console.log('[Setup Flow] Skipping Cursor setup');
|
||||
logger.debug('[Setup Flow] Skipping Cursor setup');
|
||||
setCurrentStep('github');
|
||||
};
|
||||
|
||||
const handleSkipGithub = () => {
|
||||
console.log('[Setup Flow] Skipping GitHub setup');
|
||||
logger.debug('[Setup Flow] Skipping GitHub setup');
|
||||
setCurrentStep('complete');
|
||||
};
|
||||
|
||||
const handleFinish = () => {
|
||||
console.log('[Setup Flow] handleFinish called - completing setup');
|
||||
logger.debug('[Setup Flow] handleFinish called - completing setup');
|
||||
completeSetup();
|
||||
console.log('[Setup Flow] Setup completed, redirecting to welcome view');
|
||||
logger.debug('[Setup Flow] Setup completed, redirecting to welcome view');
|
||||
navigate({ to: '/' });
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
|
||||
const logger = createLogger('CliInstallation');
|
||||
|
||||
interface UseCliInstallationOptions {
|
||||
cliType: 'claude';
|
||||
@@ -82,7 +85,7 @@ export function useCliInstallation({
|
||||
toast.error('Installation failed', { description: result.error });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to install ${cliType}:`, error);
|
||||
logger.error(`Failed to install ${cliType}:`, error);
|
||||
toast.error('Installation failed');
|
||||
} finally {
|
||||
setIsInstalling(false);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
|
||||
interface UseCliStatusOptions {
|
||||
cliType: 'claude';
|
||||
@@ -14,13 +15,14 @@ export function useCliStatus({
|
||||
setAuthStatus,
|
||||
}: UseCliStatusOptions) {
|
||||
const [isChecking, setIsChecking] = useState(false);
|
||||
const logger = createLogger('CliStatus');
|
||||
|
||||
const checkStatus = useCallback(async () => {
|
||||
console.log(`[${cliType} Setup] Starting status check...`);
|
||||
logger.info(`Starting status check for ${cliType}...`);
|
||||
setIsChecking(true);
|
||||
try {
|
||||
const result = await statusApi();
|
||||
console.log(`[${cliType} Setup] Raw status result:`, result);
|
||||
logger.info(`Raw status result for ${cliType}:`, result);
|
||||
|
||||
if (result.success) {
|
||||
const cliStatus = {
|
||||
@@ -29,7 +31,7 @@ export function useCliStatus({
|
||||
version: result.version || null,
|
||||
method: result.method || 'none',
|
||||
};
|
||||
console.log(`[${cliType} Setup] CLI Status:`, cliStatus);
|
||||
logger.info(`CLI Status for ${cliType}:`, cliStatus);
|
||||
setCliStatus(cliStatus);
|
||||
|
||||
if (result.auth) {
|
||||
@@ -60,11 +62,11 @@ export function useCliStatus({
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[${cliType} Setup] Failed to check status:`, error);
|
||||
logger.error(`Failed to check status for ${cliType}:`, error);
|
||||
} finally {
|
||||
setIsChecking(false);
|
||||
}
|
||||
}, [cliType, statusApi, setCliStatus, setAuthStatus]);
|
||||
}, [cliType, statusApi, setCliStatus, setAuthStatus, logger]);
|
||||
|
||||
return { isChecking, checkStatus };
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
|
||||
const logger = createLogger('TokenSave');
|
||||
|
||||
interface UseTokenSaveOptions {
|
||||
provider: string; // e.g., "anthropic_oauth_token", "anthropic", "openai"
|
||||
@@ -24,7 +27,7 @@ export function useTokenSave({ provider, onSuccess }: UseTokenSaveOptions) {
|
||||
|
||||
if (setupApi?.storeApiKey) {
|
||||
const result = await setupApi.storeApiKey(provider, tokenValue);
|
||||
console.log(`[Token Save] Store result for ${provider}:`, result);
|
||||
logger.info(`Store result for ${provider}:`, result);
|
||||
|
||||
if (result.success) {
|
||||
const tokenType = provider.includes('oauth') ? 'subscription token' : 'API key';
|
||||
@@ -42,7 +45,7 @@ export function useTokenSave({ provider, onSuccess }: UseTokenSaveOptions) {
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[Token Save] Failed to save ${provider}:`, error);
|
||||
logger.error(`Failed to save ${provider}:`, error);
|
||||
toast.error('Failed to save token');
|
||||
return false;
|
||||
} finally {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@@ -19,6 +20,8 @@ import {
|
||||
import { toast } from 'sonner';
|
||||
import { StatusBadge } from '../components';
|
||||
|
||||
const logger = createLogger('CursorSetupStep');
|
||||
|
||||
interface CursorSetupStepProps {
|
||||
onNext: () => void;
|
||||
onBack: () => void;
|
||||
@@ -67,7 +70,7 @@ export function CursorSetupStep({ onNext, onBack, onSkip }: CursorSetupStepProps
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to check Cursor status:', error);
|
||||
logger.error('Failed to check Cursor status:', error);
|
||||
} finally {
|
||||
setIsChecking(false);
|
||||
}
|
||||
@@ -140,7 +143,7 @@ export function CursorSetupStep({ onNext, onBack, onSkip }: CursorSetupStepProps
|
||||
}
|
||||
}, 2000);
|
||||
} catch (error) {
|
||||
console.error('Login failed:', error);
|
||||
logger.error('Login failed:', error);
|
||||
toast.error('Failed to start login process');
|
||||
setIsLoggingIn(false);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useSetupStore } from '@/store/setup-store';
|
||||
@@ -18,6 +19,8 @@ import {
|
||||
import { toast } from 'sonner';
|
||||
import { StatusBadge } from '../components';
|
||||
|
||||
const logger = createLogger('GitHubSetupStep');
|
||||
|
||||
interface GitHubSetupStepProps {
|
||||
onNext: () => void;
|
||||
onBack: () => void;
|
||||
@@ -46,7 +49,7 @@ export function GitHubSetupStep({ onNext, onBack, onSkip }: GitHubSetupStepProps
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to check gh status:', error);
|
||||
logger.error('Failed to check gh status:', error);
|
||||
} finally {
|
||||
setIsChecking(false);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useEffect, useState, useCallback, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
const logger = createLogger('SpecGeneration');
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
import { CheckCircle2 } from 'lucide-react';
|
||||
@@ -79,7 +82,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
}
|
||||
|
||||
const status = await api.specRegeneration.status();
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Status check on mount:',
|
||||
status,
|
||||
'for project:',
|
||||
@@ -87,7 +90,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
);
|
||||
|
||||
if (status.success && status.isRunning) {
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Spec generation is running globally. Tentatively showing loader.'
|
||||
);
|
||||
|
||||
@@ -103,7 +106,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
clearTimeout(pendingStatusTimeoutRef.current);
|
||||
}
|
||||
pendingStatusTimeoutRef.current = setTimeout(() => {
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] No events received for current project - clearing tentative state'
|
||||
);
|
||||
setIsCreating(false);
|
||||
@@ -118,7 +121,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
stateRestoredRef.current = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[useSpecGeneration] Failed to check status:', error);
|
||||
logger.error('[useSpecGeneration] Failed to check status:', error);
|
||||
} finally {
|
||||
statusCheckRef.current = false;
|
||||
}
|
||||
@@ -141,10 +144,10 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
if (!api.specRegeneration) return;
|
||||
|
||||
const status = await api.specRegeneration.status();
|
||||
console.log('[useSpecGeneration] Visibility change - status check:', status);
|
||||
logger.debug('[useSpecGeneration] Visibility change - status check:', status);
|
||||
|
||||
if (!status.isRunning) {
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Visibility change: Backend indicates generation complete - clearing state'
|
||||
);
|
||||
setIsCreating(false);
|
||||
@@ -157,7 +160,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
setCurrentPhase(status.currentPhase);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[useSpecGeneration] Failed to check status on visibility change:', error);
|
||||
logger.error('[useSpecGeneration] Failed to check status on visibility change:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -180,7 +183,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
const status = await api.specRegeneration.status();
|
||||
|
||||
if (!status.isRunning) {
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Periodic check: Backend indicates generation complete - clearing state'
|
||||
);
|
||||
setIsCreating(false);
|
||||
@@ -190,14 +193,14 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
stateRestoredRef.current = false;
|
||||
loadSpec();
|
||||
} else if (status.currentPhase && status.currentPhase !== currentPhase) {
|
||||
console.log('[useSpecGeneration] Periodic check: Phase updated from backend', {
|
||||
logger.debug('[useSpecGeneration] Periodic check: Phase updated from backend', {
|
||||
old: currentPhase,
|
||||
new: status.currentPhase,
|
||||
});
|
||||
setCurrentPhase(status.currentPhase);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[useSpecGeneration] Periodic status check error:', error);
|
||||
logger.error('[useSpecGeneration] Periodic status check error:', error);
|
||||
}
|
||||
}, STATUS_CHECK_INTERVAL_MS);
|
||||
|
||||
@@ -214,7 +217,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
if (!api.specRegeneration) return;
|
||||
|
||||
const unsubscribe = api.specRegeneration.onEvent((event: SpecRegenerationEvent) => {
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Regeneration event:',
|
||||
event.type,
|
||||
'for project:',
|
||||
@@ -224,14 +227,14 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
);
|
||||
|
||||
if (event.projectPath !== currentProject?.path) {
|
||||
console.log('[useSpecGeneration] Ignoring event - not for current project');
|
||||
logger.debug('[useSpecGeneration] Ignoring event - not for current project');
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingStatusTimeoutRef.current) {
|
||||
clearTimeout(pendingStatusTimeoutRef.current);
|
||||
pendingStatusTimeoutRef.current = null;
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Event confirmed this is for current project - clearing timeout'
|
||||
);
|
||||
}
|
||||
@@ -244,10 +247,10 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
if (phaseMatch) {
|
||||
const phase = phaseMatch[1];
|
||||
setCurrentPhase(phase);
|
||||
console.log(`[useSpecGeneration] Phase updated: ${phase}`);
|
||||
logger.debug(`[useSpecGeneration] Phase updated: ${phase}`);
|
||||
|
||||
if (phase === 'complete') {
|
||||
console.log('[useSpecGeneration] Phase is complete - clearing state');
|
||||
logger.debug('[useSpecGeneration] Phase is complete - clearing state');
|
||||
setIsCreating(false);
|
||||
setIsRegenerating(false);
|
||||
stateRestoredRef.current = false;
|
||||
@@ -261,7 +264,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
event.content.includes('All tasks completed') ||
|
||||
event.content.includes('✓ All tasks completed')
|
||||
) {
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Detected completion in progress message - clearing state'
|
||||
);
|
||||
setIsCreating(false);
|
||||
@@ -276,7 +279,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
const newLog = logsRef.current + event.content;
|
||||
logsRef.current = newLog;
|
||||
setLogs(newLog);
|
||||
console.log('[useSpecGeneration] Progress:', event.content.substring(0, 100));
|
||||
logger.debug('[useSpecGeneration] Progress:', event.content.substring(0, 100));
|
||||
|
||||
if (errorMessage) {
|
||||
setErrorMessage('');
|
||||
@@ -292,7 +295,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
setCurrentPhase('feature_generation');
|
||||
setIsCreating(true);
|
||||
setIsRegenerating(true);
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Detected feature creation tool - setting phase to feature_generation'
|
||||
);
|
||||
}
|
||||
@@ -305,7 +308,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
const newLog = logsRef.current + toolLog;
|
||||
logsRef.current = newLog;
|
||||
setLogs(newLog);
|
||||
console.log('[useSpecGeneration] Tool:', event.tool, event.input);
|
||||
logger.debug('[useSpecGeneration] Tool:', event.tool, event.input);
|
||||
} else if (event.type === 'spec_regeneration_complete') {
|
||||
const completionLog = logsRef.current + `\n[Complete] ${event.message}\n`;
|
||||
logsRef.current = completionLog;
|
||||
@@ -328,7 +331,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
(isFinalCompletionMessage || hasCompletePhase) && !isIntermediateCompletion;
|
||||
|
||||
if (shouldComplete) {
|
||||
console.log('[useSpecGeneration] Final completion detected - clearing state', {
|
||||
logger.debug('[useSpecGeneration] Final completion detected - clearing state', {
|
||||
isFinalCompletionMessage,
|
||||
hasCompletePhase,
|
||||
message: event.message,
|
||||
@@ -367,12 +370,12 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
setIsCreating(true);
|
||||
setIsRegenerating(true);
|
||||
setCurrentPhase('feature_generation');
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Intermediate completion, continuing with feature generation'
|
||||
);
|
||||
}
|
||||
|
||||
console.log('[useSpecGeneration] Spec generation event:', event.message);
|
||||
logger.debug('[useSpecGeneration] Spec generation event:', event.message);
|
||||
} else if (event.type === 'spec_regeneration_error') {
|
||||
setIsRegenerating(false);
|
||||
setIsCreating(false);
|
||||
@@ -383,7 +386,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
const errorLog = logsRef.current + `\n\n[ERROR] ${event.error}\n`;
|
||||
logsRef.current = errorLog;
|
||||
setLogs(errorLog);
|
||||
console.error('[useSpecGeneration] Regeneration error:', event.error);
|
||||
logger.error('[useSpecGeneration] Regeneration error:', event.error);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -402,11 +405,11 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
setErrorMessage('');
|
||||
logsRef.current = '';
|
||||
setLogs('');
|
||||
console.log('[useSpecGeneration] Starting spec creation, generateFeatures:', generateFeatures);
|
||||
logger.debug('[useSpecGeneration] Starting spec creation, generateFeatures:', generateFeatures);
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api.specRegeneration) {
|
||||
console.error('[useSpecGeneration] Spec regeneration not available');
|
||||
logger.error('[useSpecGeneration] Spec regeneration not available');
|
||||
setIsCreating(false);
|
||||
return;
|
||||
}
|
||||
@@ -420,7 +423,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
|
||||
if (!result.success) {
|
||||
const errorMsg = result.error || 'Unknown error';
|
||||
console.error('[useSpecGeneration] Failed to start spec creation:', errorMsg);
|
||||
logger.error('[useSpecGeneration] Failed to start spec creation:', errorMsg);
|
||||
setIsCreating(false);
|
||||
setCurrentPhase('error');
|
||||
setErrorMessage(errorMsg);
|
||||
@@ -430,7 +433,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
console.error('[useSpecGeneration] Failed to create spec:', errorMsg);
|
||||
logger.error('[useSpecGeneration] Failed to create spec:', errorMsg);
|
||||
setIsCreating(false);
|
||||
setCurrentPhase('error');
|
||||
setErrorMessage(errorMsg);
|
||||
@@ -455,14 +458,14 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
setErrorMessage('');
|
||||
logsRef.current = '';
|
||||
setLogs('');
|
||||
console.log(
|
||||
logger.debug(
|
||||
'[useSpecGeneration] Starting spec regeneration, generateFeatures:',
|
||||
generateFeaturesOnRegenerate
|
||||
);
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api.specRegeneration) {
|
||||
console.error('[useSpecGeneration] Spec regeneration not available');
|
||||
logger.error('[useSpecGeneration] Spec regeneration not available');
|
||||
setIsRegenerating(false);
|
||||
return;
|
||||
}
|
||||
@@ -476,7 +479,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
|
||||
if (!result.success) {
|
||||
const errorMsg = result.error || 'Unknown error';
|
||||
console.error('[useSpecGeneration] Failed to start regeneration:', errorMsg);
|
||||
logger.error('[useSpecGeneration] Failed to start regeneration:', errorMsg);
|
||||
setIsRegenerating(false);
|
||||
setCurrentPhase('error');
|
||||
setErrorMessage(errorMsg);
|
||||
@@ -486,7 +489,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
console.error('[useSpecGeneration] Failed to regenerate spec:', errorMsg);
|
||||
logger.error('[useSpecGeneration] Failed to regenerate spec:', errorMsg);
|
||||
setIsRegenerating(false);
|
||||
setCurrentPhase('error');
|
||||
setErrorMessage(errorMsg);
|
||||
@@ -511,11 +514,11 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
setErrorMessage('');
|
||||
logsRef.current = '';
|
||||
setLogs('');
|
||||
console.log('[useSpecGeneration] Starting feature generation from existing spec');
|
||||
logger.debug('[useSpecGeneration] Starting feature generation from existing spec');
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api.specRegeneration) {
|
||||
console.error('[useSpecGeneration] Spec regeneration not available');
|
||||
logger.error('[useSpecGeneration] Spec regeneration not available');
|
||||
setIsGeneratingFeatures(false);
|
||||
return;
|
||||
}
|
||||
@@ -523,7 +526,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
|
||||
if (!result.success) {
|
||||
const errorMsg = result.error || 'Unknown error';
|
||||
console.error('[useSpecGeneration] Failed to start feature generation:', errorMsg);
|
||||
logger.error('[useSpecGeneration] Failed to start feature generation:', errorMsg);
|
||||
setIsGeneratingFeatures(false);
|
||||
setCurrentPhase('error');
|
||||
setErrorMessage(errorMsg);
|
||||
@@ -533,7 +536,7 @@ export function useSpecGeneration({ loadSpec }: UseSpecGenerationOptions) {
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
console.error('[useSpecGeneration] Failed to generate features:', errorMsg);
|
||||
logger.error('[useSpecGeneration] Failed to generate features:', errorMsg);
|
||||
setIsGeneratingFeatures(false);
|
||||
setCurrentPhase('error');
|
||||
setErrorMessage(errorMsg);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
const logger = createLogger('SpecLoading');
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
export function useSpecLoading() {
|
||||
@@ -24,7 +27,7 @@ export function useSpecLoading() {
|
||||
setSpecExists(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load spec:', error);
|
||||
logger.error('Failed to load spec:', error);
|
||||
setSpecExists(false);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useState } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
const logger = createLogger('SpecSave');
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
export function useSpecSave() {
|
||||
@@ -16,7 +19,7 @@ export function useSpecSave() {
|
||||
await api.writeFile(`${currentProject.path}/.automaker/app_spec.txt`, appSpec);
|
||||
setHasChanges(false);
|
||||
} catch (error) {
|
||||
console.error('Failed to save spec:', error);
|
||||
logger.error('Failed to save spec:', error);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
Terminal as TerminalIcon,
|
||||
Plus,
|
||||
@@ -50,6 +51,8 @@ import { cn } from '@/lib/utils';
|
||||
import { apiFetch, apiGet, apiPost, apiDeleteRaw, getAuthHeaders } from '@/lib/api-fetch';
|
||||
import { getApiKey } from '@/lib/http-api-client';
|
||||
|
||||
const logger = createLogger('Terminal');
|
||||
|
||||
interface TerminalStatus {
|
||||
enabled: boolean;
|
||||
passwordRequired: boolean;
|
||||
@@ -301,7 +304,7 @@ export function TerminalView() {
|
||||
headers['X-Terminal-Token'] = terminalState.authToken;
|
||||
}
|
||||
|
||||
console.log(`[Terminal] Killing ${sessionIds.length} sessions on server`);
|
||||
logger.info(`Killing ${sessionIds.length} sessions on server`);
|
||||
|
||||
// Kill all sessions in parallel
|
||||
await Promise.allSettled(
|
||||
@@ -309,7 +312,7 @@ export function TerminalView() {
|
||||
try {
|
||||
await apiDeleteRaw(`/api/terminal/sessions/${sessionId}`, { headers });
|
||||
} catch (err) {
|
||||
console.error(`[Terminal] Failed to kill session ${sessionId}:`, err);
|
||||
logger.error(`Failed to kill session ${sessionId}:`, err);
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -320,7 +323,7 @@ export function TerminalView() {
|
||||
const canCreateTerminal = (debounceMessage: string): boolean => {
|
||||
const now = Date.now();
|
||||
if (now - lastCreateTimeRef.current < CREATE_COOLDOWN_MS || isCreatingRef.current) {
|
||||
console.log(debounceMessage);
|
||||
logger.debug(debounceMessage);
|
||||
return false;
|
||||
}
|
||||
lastCreateTimeRef.current = now;
|
||||
@@ -447,7 +450,7 @@ export function TerminalView() {
|
||||
}
|
||||
} catch (err) {
|
||||
setError('Failed to connect to server');
|
||||
console.error('[Terminal] Status fetch error:', err);
|
||||
logger.error('Status fetch error:', err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -469,7 +472,7 @@ export function TerminalView() {
|
||||
setServerSessionInfo({ current: data.data.currentSessions, max: data.data.maxSessions });
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Failed to fetch server settings:', err);
|
||||
logger.error('Failed to fetch server settings:', err);
|
||||
}
|
||||
}, [terminalState.isUnlocked, terminalState.authToken]);
|
||||
|
||||
@@ -573,7 +576,7 @@ export function TerminalView() {
|
||||
|
||||
// If no saved layout or no tabs, we're done - terminal starts fresh for this project
|
||||
if (!savedLayout || savedLayout.tabs.length === 0) {
|
||||
console.log('[Terminal] No saved layout for project, starting fresh');
|
||||
logger.info('No saved layout for project, starting fresh');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -585,7 +588,7 @@ export function TerminalView() {
|
||||
const restoreLayout = async () => {
|
||||
// Check if we're still restoring the same project (user may have switched)
|
||||
if (restoringProjectPathRef.current !== currentPath) {
|
||||
console.log('[Terminal] Restore cancelled - project changed');
|
||||
logger.info('Restore cancelled - project changed');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -623,7 +626,7 @@ export function TerminalView() {
|
||||
);
|
||||
return data.success && data.data ? data.data.id : null;
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Failed to create terminal session:', err);
|
||||
logger.error('Failed to create terminal session:', err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -691,7 +694,7 @@ export function TerminalView() {
|
||||
for (let tabIndex = 0; tabIndex < savedLayout.tabs.length; tabIndex++) {
|
||||
// Check if project changed during restore - bail out early
|
||||
if (restoringProjectPathRef.current !== currentPath) {
|
||||
console.log('[Terminal] Restore cancelled mid-loop - project changed');
|
||||
logger.info('Restore cancelled mid-loop - project changed');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -730,7 +733,7 @@ export function TerminalView() {
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Failed to restore terminal layout:', err);
|
||||
logger.error('Failed to restore terminal layout:', err);
|
||||
toast.error('Failed to restore terminals', {
|
||||
description: 'Could not restore terminal layout. Please try creating new terminals.',
|
||||
duration: 5000,
|
||||
@@ -806,7 +809,7 @@ export function TerminalView() {
|
||||
}
|
||||
} catch (err) {
|
||||
setAuthError('Failed to authenticate');
|
||||
console.error('[Terminal] Auth error:', err);
|
||||
logger.error('Auth error:', err);
|
||||
} finally {
|
||||
setAuthLoading(false);
|
||||
}
|
||||
@@ -851,14 +854,14 @@ export function TerminalView() {
|
||||
`Please close unused terminals. Limit: ${data.maxSessions || 'unknown'}`,
|
||||
});
|
||||
} else {
|
||||
console.error('[Terminal] Failed to create session:', data.error);
|
||||
logger.error('Failed to create session:', data.error);
|
||||
toast.error('Failed to create terminal', {
|
||||
description: data.error || 'Unknown error',
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Create session error:', err);
|
||||
logger.error('Create session error:', err);
|
||||
toast.error('Failed to create terminal', {
|
||||
description: 'Could not connect to server',
|
||||
});
|
||||
@@ -915,7 +918,7 @@ export function TerminalView() {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Create session error:', err);
|
||||
logger.error('Create session error:', err);
|
||||
// Remove the empty tab on error
|
||||
const { removeTerminalTab } = useAppStore.getState();
|
||||
removeTerminalTab(tabId);
|
||||
@@ -943,16 +946,13 @@ export function TerminalView() {
|
||||
if (!response.ok && response.status !== 404) {
|
||||
// Log non-404 errors but still proceed with UI cleanup
|
||||
const data = await response.json().catch(() => ({}));
|
||||
console.error(
|
||||
'[Terminal] Server failed to kill session:',
|
||||
data.error || response.statusText
|
||||
);
|
||||
logger.error('Server failed to kill session:', data.error || response.statusText);
|
||||
}
|
||||
|
||||
// Refresh session count
|
||||
fetchServerSettings();
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Kill session error:', err);
|
||||
logger.error('Kill session error:', err);
|
||||
// Still remove from UI on network error - better UX than leaving broken terminal
|
||||
removeTerminalFromLayout(sessionId);
|
||||
}
|
||||
@@ -983,7 +983,7 @@ export function TerminalView() {
|
||||
try {
|
||||
await apiDeleteRaw(`/api/terminal/sessions/${sessionId}`, { headers });
|
||||
} catch (err) {
|
||||
console.error(`[Terminal] Failed to kill session ${sessionId}:`, err);
|
||||
logger.error(`Failed to kill session ${sessionId}:`, err);
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -1210,9 +1210,7 @@ export function TerminalView() {
|
||||
onSessionInvalid={() => {
|
||||
// Auto-remove stale session when server says it doesn't exist
|
||||
// This handles cases like server restart where sessions are lost
|
||||
console.log(
|
||||
`[Terminal] Session ${content.sessionId} is invalid, removing from layout`
|
||||
);
|
||||
logger.info(`Session ${content.sessionId} is invalid, removing from layout`);
|
||||
killTerminal(content.sessionId);
|
||||
}}
|
||||
isDragging={activeDragId === content.sessionId}
|
||||
@@ -1587,9 +1585,7 @@ export function TerminalView() {
|
||||
onNewTab={createTerminalInNewTab}
|
||||
onSessionInvalid={() => {
|
||||
const sessionId = terminalState.maximizedSessionId!;
|
||||
console.log(
|
||||
`[Terminal] Maximized session ${sessionId} is invalid, removing from layout`
|
||||
);
|
||||
logger.info(`Maximized session ${sessionId} is invalid, removing from layout`);
|
||||
killTerminal(sessionId);
|
||||
}}
|
||||
isDragging={false}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import React, { Component, ErrorInfo } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { AlertCircle, RefreshCw } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const logger = createLogger('TerminalErrorBoundary');
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
sessionId: string;
|
||||
@@ -30,7 +33,7 @@ export class TerminalErrorBoundary extends Component<Props, State> {
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error('[TerminalErrorBoundary] Terminal crashed:', {
|
||||
logger.error('Terminal crashed:', {
|
||||
sessionId: this.props.sessionId,
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useRef, useCallback, useState } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import {
|
||||
X,
|
||||
SplitSquareHorizontal,
|
||||
@@ -42,6 +43,8 @@ import { toast } from 'sonner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { getApiKey, getSessionToken, getServerUrlSync } from '@/lib/http-api-client';
|
||||
|
||||
const logger = createLogger('Terminal');
|
||||
|
||||
// Font size constraints
|
||||
const MIN_FONT_SIZE = 8;
|
||||
const MAX_FONT_SIZE = 32;
|
||||
@@ -296,7 +299,7 @@ export function TerminalPanel({
|
||||
toast.success('Copied to clipboard');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Copy failed:', err);
|
||||
logger.error('Copy failed:', err);
|
||||
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
||||
toast.error('Copy failed', {
|
||||
description: errorMessage.includes('permission')
|
||||
@@ -361,7 +364,7 @@ export function TerminalPanel({
|
||||
|
||||
await sendTextInChunks(text);
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Paste failed:', err);
|
||||
logger.error('Paste failed:', err);
|
||||
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
||||
toast.error('Paste failed', {
|
||||
description: errorMessage.includes('permission')
|
||||
@@ -504,7 +507,7 @@ export function TerminalPanel({
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.warn('[Terminal] Failed to fetch wsToken:', response.status);
|
||||
logger.warn('Failed to fetch wsToken:', response.status);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -515,7 +518,7 @@ export function TerminalPanel({
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('[Terminal] Error fetching wsToken:', error);
|
||||
logger.error('Error fetching wsToken:', error);
|
||||
return null;
|
||||
}
|
||||
}, [serverUrl]);
|
||||
@@ -595,7 +598,7 @@ export function TerminalPanel({
|
||||
const api = getElectronAPI();
|
||||
if (api?.openExternalLink) {
|
||||
api.openExternalLink(uri).catch((error) => {
|
||||
console.error('[Terminal] Failed to open URL:', error);
|
||||
logger.error('Failed to open URL:', error);
|
||||
// Fallback to window.open if Electron API fails
|
||||
window.open(uri, '_blank', 'noopener,noreferrer');
|
||||
});
|
||||
@@ -697,7 +700,7 @@ export function TerminalPanel({
|
||||
}
|
||||
} catch {
|
||||
// If we can't get home path, just use the path as-is
|
||||
console.warn('[Terminal] Could not resolve home directory path');
|
||||
logger.warn('Could not resolve home directory path');
|
||||
}
|
||||
} else if (!clickedPath.startsWith('/') && !clickedPath.match(/^[a-zA-Z]:\\/)) {
|
||||
// Relative path - resolve against project path
|
||||
@@ -721,7 +724,7 @@ export function TerminalPanel({
|
||||
toast.error('Failed to open in editor', { description: result.error });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Terminal] Failed to open file:', error);
|
||||
logger.error('Failed to open file:', error);
|
||||
toast.error('Failed to open file', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -744,7 +747,7 @@ export function TerminalPanel({
|
||||
});
|
||||
terminal.loadAddon(webglAddon);
|
||||
} catch {
|
||||
console.warn('[Terminal] WebGL addon not available, falling back to canvas');
|
||||
logger.warn('WebGL addon not available, falling back to canvas');
|
||||
}
|
||||
|
||||
// Fit terminal to container - wait for stable dimensions
|
||||
@@ -770,7 +773,7 @@ export function TerminalPanel({
|
||||
try {
|
||||
fitAddon.fit();
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Initial fit error:', err);
|
||||
logger.error('Initial fit error:', err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1000,7 +1003,7 @@ export function TerminalPanel({
|
||||
wsRef.current = ws;
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log(`[Terminal] WebSocket connected for session ${sessionId}`);
|
||||
logger.info(`WebSocket connected for session ${sessionId}`);
|
||||
|
||||
setConnectionStatus('connected');
|
||||
reconnectAttemptsRef.current = 0;
|
||||
@@ -1037,7 +1040,7 @@ export function TerminalPanel({
|
||||
}
|
||||
break;
|
||||
case 'connected': {
|
||||
console.log(`[Terminal] Session connected: ${msg.shell} in ${msg.cwd}`);
|
||||
logger.info(`Session connected: ${msg.shell} in ${msg.cwd}`);
|
||||
// Detect shell type from path
|
||||
const shellPath = (msg.shell || '').toLowerCase();
|
||||
// Windows shells use backslash paths and include powershell/pwsh/cmd
|
||||
@@ -1088,16 +1091,12 @@ export function TerminalPanel({
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Message parse error:', err);
|
||||
logger.error('Message parse error:', err);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = (event) => {
|
||||
console.log(
|
||||
`[Terminal] WebSocket closed for session ${sessionId}:`,
|
||||
event.code,
|
||||
event.reason
|
||||
);
|
||||
logger.info(`WebSocket closed for session ${sessionId}: ${event.code} ${event.reason}`);
|
||||
wsRef.current = null;
|
||||
|
||||
// Clear heartbeat interval
|
||||
@@ -1167,8 +1166,8 @@ export function TerminalPanel({
|
||||
// Attempt reconnect after exponential delay
|
||||
reconnectTimeoutRef.current = setTimeout(() => {
|
||||
if (xtermRef.current) {
|
||||
console.log(
|
||||
`[Terminal] Attempting reconnect for session ${sessionId} (attempt ${reconnectAttemptsRef.current}/${MAX_RECONNECT_ATTEMPTS})`
|
||||
logger.info(
|
||||
`Attempting reconnect for session ${sessionId} (attempt ${reconnectAttemptsRef.current}/${MAX_RECONNECT_ATTEMPTS})`
|
||||
);
|
||||
connect();
|
||||
}
|
||||
@@ -1176,7 +1175,7 @@ export function TerminalPanel({
|
||||
};
|
||||
|
||||
ws.onerror = (error) => {
|
||||
console.error(`[Terminal] WebSocket error for session ${sessionId}:`, error);
|
||||
logger.error(`WebSocket error for session ${sessionId}:`, error);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1234,7 +1233,7 @@ export function TerminalPanel({
|
||||
wsRef.current.send(JSON.stringify({ type: 'resize', cols, rows }));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Terminal] Resize error:', err);
|
||||
logger.error('Resize error:', err);
|
||||
}
|
||||
}, RESIZE_DEBOUNCE_MS);
|
||||
}, []);
|
||||
@@ -1551,7 +1550,7 @@ export function TerminalPanel({
|
||||
const api = getElectronAPI();
|
||||
if (!api.saveImageToTemp) {
|
||||
// Fallback path when Electron API is not available (browser mode)
|
||||
console.warn('[Terminal] saveImageToTemp not available, returning fallback path');
|
||||
logger.warn('saveImageToTemp not available, returning fallback path');
|
||||
return `.automaker/images/${Date.now()}_${filename}`;
|
||||
}
|
||||
|
||||
@@ -1560,10 +1559,10 @@ export function TerminalPanel({
|
||||
if (result.success && result.path) {
|
||||
return result.path;
|
||||
}
|
||||
console.error('[Terminal] Failed to save image:', result.error);
|
||||
logger.error('Failed to save image:', result.error);
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('[Terminal] Error saving image:', error);
|
||||
logger.error('Error saving image:', error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
@@ -1662,7 +1661,7 @@ export function TerminalPanel({
|
||||
toast.error(`Failed to save: ${file.name}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Terminal] Error processing image:', error);
|
||||
logger.error('Error processing image:', error);
|
||||
toast.error(`Error processing: ${file.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
@@ -34,6 +35,8 @@ import { getHttpApiClient } from '@/lib/http-api-client';
|
||||
import type { StarterTemplate } from '@/lib/templates';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
|
||||
const logger = createLogger('WelcomeView');
|
||||
|
||||
export function WelcomeView() {
|
||||
const {
|
||||
projects,
|
||||
@@ -65,13 +68,13 @@ export function WelcomeView() {
|
||||
const api = getElectronAPI();
|
||||
|
||||
if (!api.autoMode?.analyzeProject) {
|
||||
console.log('[Welcome] Auto mode API not available, skipping analysis');
|
||||
logger.info('[Welcome] Auto mode API not available, skipping analysis');
|
||||
return;
|
||||
}
|
||||
|
||||
setIsAnalyzing(true);
|
||||
try {
|
||||
console.log('[Welcome] Starting project analysis for:', projectPath);
|
||||
logger.info('[Welcome] Starting project analysis for:', projectPath);
|
||||
const result = await api.autoMode.analyzeProject(projectPath);
|
||||
|
||||
if (result.success) {
|
||||
@@ -79,10 +82,10 @@ export function WelcomeView() {
|
||||
description: 'AI agent has analyzed your project structure',
|
||||
});
|
||||
} else {
|
||||
console.error('[Welcome] Project analysis failed:', result.error);
|
||||
logger.error('[Welcome] Project analysis failed:', result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Welcome] Failed to analyze project:', error);
|
||||
logger.error('[Welcome] Failed to analyze project:', error);
|
||||
} finally {
|
||||
setIsAnalyzing(false);
|
||||
}
|
||||
@@ -125,8 +128,8 @@ export function WelcomeView() {
|
||||
setShowInitDialog(true);
|
||||
|
||||
// Kick off agent to analyze the project and update app_spec.txt
|
||||
console.log('[Welcome] Project initialized, created files:', initResult.createdFiles);
|
||||
console.log('[Welcome] Kicking off project analysis agent...');
|
||||
logger.info('[Welcome] Project initialized, created files:', initResult.createdFiles);
|
||||
logger.info('[Welcome] Kicking off project analysis agent...');
|
||||
|
||||
// Start analysis in background (don't await, let it run async)
|
||||
analyzeProject(path);
|
||||
@@ -139,7 +142,7 @@ export function WelcomeView() {
|
||||
// Navigate to the board view
|
||||
navigate({ to: '/board' });
|
||||
} catch (error) {
|
||||
console.error('[Welcome] Failed to open project:', error);
|
||||
logger.error('[Welcome] Failed to open project:', error);
|
||||
toast.error('Failed to open project', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -179,7 +182,7 @@ export function WelcomeView() {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Welcome] Failed to check workspace config:', error);
|
||||
logger.error('[Welcome] Failed to check workspace config:', error);
|
||||
// Fall back to current behavior on error
|
||||
const api = getElectronAPI();
|
||||
const result = await api.openDirectory();
|
||||
@@ -317,7 +320,7 @@ export function WelcomeView() {
|
||||
});
|
||||
setShowInitDialog(true);
|
||||
} catch (error) {
|
||||
console.error('Failed to create project:', error);
|
||||
logger.error('Failed to create project:', error);
|
||||
toast.error('Failed to create project', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -418,7 +421,7 @@ export function WelcomeView() {
|
||||
// Kick off project analysis
|
||||
analyzeProject(projectPath);
|
||||
} catch (error) {
|
||||
console.error('Failed to create project from template:', error);
|
||||
logger.error('Failed to create project from template:', error);
|
||||
toast.error('Failed to create project', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
@@ -515,7 +518,7 @@ export function WelcomeView() {
|
||||
// Kick off project analysis
|
||||
analyzeProject(projectPath);
|
||||
} catch (error) {
|
||||
console.error('Failed to create project from custom URL:', error);
|
||||
logger.error('Failed to create project from custom URL:', error);
|
||||
toast.error('Failed to create project', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user