UNPKG

ai-debug-local-mcp

Version:

๐ŸŽฏ ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh

1,640 lines โ€ข 83.3 kB
import { BaseHandler } from './base-handler.js';
import { EnhancedErrorContext } from './enhanced-error-context.js';
import { writeFile, readFile, mkdir } from 'fs/promises';
import { existsSync } from 'fs';
import { join } from 'path';
export class UniversalWorkflowHandler extends BaseHandler {
    workflows = new Map();
    sessionData = new Map();
    workflowStoragePath;
    constructor() {
        super();
        this.tools = this.getTools();
        this.workflowStoragePath = join(process.cwd(), '.ai-debug', 'workflows');
        this.initializeStorage();
    }
    getToolName() {
        return 'universal-workflow';
    }
    getToolDescription() {
        return 'Universal workflow orchestration and navigation for complex user journeys';
    }
    getTools() {
        return [
            {
                name: 'navigate_to_url',
                description: '๐ŸŒ Navigate directly to a URL with smart waiting and validation. โœ… WORKS WITH: Phoenix LiveView, React, Vue, Next.js, Angular, standard web apps. โš ๏ธ LIMITED FOR: Flutter Web (use flutter_quantum_interact instead)',
                inputSchema: {
                    type: 'object',
                    properties: {
                        url: { type: 'string', description: 'URL to navigate to' },
                        options: {
                            type: 'object',
                            properties: {
                                waitUntil: { type: 'string', enum: ['load', 'domcontentloaded', 'networkidle'] },
                                timeout: { type: 'number', description: 'Timeout in milliseconds' },
                                expectedUrl: { type: 'string', description: 'Expected final URL after navigation' }
                            }
                        }
                    },
                    required: ['url']
                }
            },
            {
                name: 'wait_for_navigation',
                description: 'โณ Smart waiting for page transitions and navigation completion. โœ… EXCELLENT FOR: Phoenix LiveView SPA-like updates, React Router, Next.js navigation. โš ๏ธ FOR FLUTTER: Use flutter_quantum_interact with navigation commands',
                inputSchema: {
                    type: 'object',
                    properties: {
                        sessionId: { type: 'string', description: 'Debug session ID' },
                        expectedUrl: { type: 'string', description: 'Expected URL pattern or exact URL' },
                        timeout: { type: 'number', description: 'Maximum wait time in milliseconds', default: 30000 },
                        transitionType: { type: 'string', enum: ['spa', 'full-reload', 'auto-detect'], default: 'auto-detect' }
                    },
                    required: ['sessionId']
                }
            },
            {
                name: 'create_workflow_template',
                description: '๐Ÿ”ง Create reusable workflow template for complex user journeys with automatic visual validation. โœ… USE FOR: Phoenix LiveView, React, Vue, Next.js, Angular, standard web apps. ๐ŸŽฏ FOR FLUTTER: Include flutterCommand in step data for automatic delegation to Flutter tools. ๐Ÿ“‹ FRAMEWORK DETECTION: Automatically detects framework and optimizes interactions. ๐Ÿ“ธ VISUAL VALIDATION: Automatic screenshots and AI analysis at each step',
                inputSchema: {
                    type: 'object',
                    properties: {
                        workflow: {
                            type: 'object',
                            properties: {
                                name: { type: 'string', description: 'Workflow name' },
                                description: { type: 'string', description: 'Workflow description' },
                                steps: {
                                    type: 'array',
                                    items: {
                                        type: 'object',
                                        properties: {
                                            name: { type: 'string' },
                                            action: { type: 'string', description: 'Action type: navigate, click, fill, waitForSelector, custom, smart_interaction, take_screenshot, visual_validation' },
                                            data: {
                                                type: 'object',
                                                description: 'Action data. For Flutter: include flutterCommand (e.g., "click Submit button"). For Phoenix: use phx-* selectors. For visual validation: set visualValidation:false to disable, aiVisualAnalysis:true to enable AI analysis'
                                            },
                                            expectedResult: { type: 'object' },
                                            timeout: { type: 'number' }
                                        },
                                        required: ['name', 'action']
                                    }
                                },
                                sessionPersistence: { type: 'boolean', default: true },
                                retryStrategy: { type: 'string', enum: ['none', 'step', 'workflow'], default: 'step' },
                                visualValidation: { type: 'boolean', default: true, description: 'Enable automatic screenshots for each step' }
                            },
                            required: ['name', 'steps']
                        }
                    },
                    required: ['workflow']
                }
            },
            {
                name: 'execute_user_journey',
                description: '๐Ÿš€ Execute a complete user journey with session persistence, automatic framework detection, and visual validation. โœ… UNIVERSAL: Works with all frameworks through intelligent tool selection. ๐Ÿค– AUTO-DETECTS: Flutter, Phoenix LiveView, React, Vue, Next.js, Angular and optimizes interactions accordingly. ๐Ÿ“ธ VISUAL EVIDENCE: Captures screenshots and provides AI analysis of each step',
                inputSchema: {
                    type: 'object',
                    properties: {
                        sessionId: { type: 'string', description: 'Debug session ID' },
                        journeyName: { type: 'string', description: 'Name of workflow to execute' },
                        customization: {
                            type: 'object',
                            properties: {
                                userData: { type: 'object', description: 'User-specific data for the journey' },
                                skipSteps: { type: 'array', items: { type: 'string' } },
                                additionalSteps: { type: 'array', items: { type: 'object' } },
                                enableVisualValidation: { type: 'boolean', default: true, description: 'Enable visual validation and screenshots' },
                                enableAIAnalysis: { type: 'boolean', default: false, description: 'Enable AI-powered visual analysis' }
                            }
                        }
                    },
                    required: ['sessionId', 'journeyName']
                }
            },
            {
                name: 'create_persistent_session',
                description: '๐Ÿ’พ Create session that persists across page navigation and reloads. โœ… EXCELLENT FOR: Phoenix LiveView stateful sessions, React SPA navigation, Next.js page transitions. โœ… WORKS WITH: All web frameworks including Flutter Web',
                inputSchema: {
                    type: 'object',
                    properties: {
                        sessionId: { type: 'string', description: 'Debug session ID' },
                        sessionConfig: {
                            type: 'object',
                            properties: {
                                persistCookies: { type: 'boolean', default: true },
                                persistLocalStorage: { type: 'boolean', default: true },
                                persistSessionStorage: { type: 'boolean', default: true },
                                userAgent: { type: 'string', description: 'Custom user agent' },
                                viewport: {
                                    type: 'object',
                                    properties: {
                                        width: { type: 'number', default: 1920 },
                                        height: { type: 'number', default: 1080 }
                                    }
                                }
                            }
                        }
                    },
                    required: ['sessionId']
                }
            },
            {
                name: 'handle_page_transition',
                description: '๐Ÿ”„ Handle different types of page transitions (SPA, full reload). โœ… PERFECT FOR: Phoenix LiveView patch updates, React Router navigation, Next.js transitions. ๐Ÿ”ง AUTO-RESTORES: Session data, cookies, storage for seamless continuation',
                inputSchema: {
                    type: 'object',
                    properties: {
                        sessionId: { type: 'string', description: 'Debug session ID' },
                        transitionType: { type: 'string', enum: ['spa', 'full-reload', 'auto-detect'] },
                        expectedBehavior: {
                            type: 'object',
                            properties: {
                                urlChange: { type: 'boolean' },
                                pageReload: { type: 'boolean' },
                                preserveState: { type: 'boolean' }
                            }
                        }
                    },
                    required: ['sessionId', 'transitionType']
                }
            },
            {
                name: 'take_workflow_screenshot',
                description: '๐Ÿš€ ENHANCED: Screenshot with optional system automation. ๐Ÿ“ธ AI ANALYSIS + ๐Ÿ–ฑ๏ธ NATIVE VALIDATION: Combines browser screenshots with native system capture for maximum accuracy. ๐Ÿ“Š CONTEXT AWARE: Framework-specific validation with pixel-perfect system validation',
                inputSchema: {
                    type: 'object',
                    properties: {
                        sessionId: { type: 'string', description: 'Debug session ID' },
                        filename: { type: 'string', description: 'Screenshot filename (auto-timestamped)' },
                        analysisConfig: {
                            type: 'object',
                            properties: {
                                enableAI: { type: 'boolean', default: true, description: 'Enable AI visual analysis' },
                                framework: { type: 'string', description: 'Force specific framework analysis' },
                                expectedElements: { type: 'array', items: { type: 'string' }, description: 'CSS selectors of elements that should be present' },
                                customChecks: {
                                    type: 'array',
                                    items: {
                                        type: 'object',
                                        properties: {
                                            name: { type: 'string' },
                                            description: { type: 'string' },
                                            script: { type: 'string', description: 'JavaScript to execute for validation' }
                                        }
                                    }
                                }
                            }
                        },
                        systemAutomation: {
                            type: 'object',
                            description: '๐Ÿš€ NEW: Native system automation integration',
                            properties: {
                                enabled: { type: 'boolean', default: false, description: 'Enable system-level screenshot capture' },
                                includeSystemAnalysis: { type: 'boolean', default: false, description: 'Include native visual analysis' },
                                crossValidation: { type: 'boolean', default: false, description: 'Cross-validate browser vs system screenshots' }
                            }
                        }
                    },
                    required: ['sessionId']
                }
            },
            {
                name: 'visual_workflow_validation',
                description: '๐Ÿ” Perform comprehensive visual validation of workflow state with AI analysis. ๐ŸŽฏ FRAMEWORK SPECIFIC: Optimized checks for Flutter widgets, Phoenix LiveView components, React state. ๐Ÿ“Š DETAILED REPORTING: Visual score, element validation, error detection, recommendations',
                inputSchema: {
                    type: 'object',
                    properties: {
                        sessionId: { type: 'string', description: 'Debug session ID' },
                        validationName: { type: 'string', description: 'Name for this validation check' },
                        validationConfig: {
                            type: 'object',
                            properties: {
                                expectedElements: { type: 'array', items: { type: 'string' }, description: 'Elements that must be present' },
                                forbiddenElements: { type: 'array', items: { type: 'string' }, description: 'Elements that should not be present' },
                                customChecks: {
                                    type: 'array',
                                    items: {
                                        type: 'object',
                                        properties: {
                                            name: { type: 'string' },
                                            description: { type: 'string' },
                                            script: { type: 'string', description: 'JavaScript validation script' }
                                        }
                                    }
                                },
                                framework: { type: 'string', description: 'Override framework detection' },
                                tolerance: { type: 'number', default: 85, description: 'Minimum validation score (0-100)' }
                            }
                        }
                    },
                    required: ['sessionId', 'validationName']
                }
            },
            {
                name: 'save_workflow_template',
                description: '๐Ÿ’พ Save workflow template to persistent storage for reuse. ๐Ÿท๏ธ SUPPORTS: Tagging, categorization, versioning. ๐Ÿ”„ REUSABLE: Across projects and team members. ๐Ÿ“ ORGANIZED: Framework-specific workflow collections',
                inputSchema: {
                    type: 'object',
                    properties: {
                        workflowName: { type: 'string', description: 'Name of workflow to save' },
                        filePath: { type: 'string', description: 'Optional custom file path' },
                        metadata: {
                            type: 'object',
                            properties: {
                                tags: { type: 'array', items: { type: 'string' }, description: 'Tags like ["flutter", "phoenix", "reliable", "tested"]' },
                                category: { type: 'string', description: 'Category like "job-application", "user-registration", "testing"' },
                                author: { type: 'string' },
                                version: { type: 'string', description: 'Semantic version like "1.0.0"' },
                                frameworks: { type: 'array', items: { type: 'string' }, description: 'Compatible frameworks like ["Phoenix LiveView", "React"]' }
                            }
                        }
                    },
                    required: ['workflowName']
                }
            },
            {
                name: 'load_workflow_template',
                description: '๐Ÿ“‚ Load workflow template from persistent storage. ๐Ÿ” SMART LOADING: Automatically validates compatibility with current session framework. โšก INSTANT: Ready-to-execute workflows with all metadata preserved',
                inputSchema: {
                    type: 'object',
                    properties: {
                        workflowName: { type: 'string', description: 'Name of workflow to load' },
                        filePath: { type: 'string', description: 'Optional custom file path' }
                    },
                    required: ['workflowName']
                }
            },
            {
                name: 'list_saved_workflows',
                description: '๐Ÿ“‹ List all saved workflow templates with metadata and filtering. ๐Ÿ” FILTER BY: Category, tags, framework compatibility. ๐Ÿ“Š SHOWS: Step count, last tested, success rates, framework compatibility',
                inputSchema: {
                    type: 'object',
                    properties: {
                        category: { type: 'string', description: 'Filter by category like "flutter-workflows", "phoenix-workflows"' },
                        tags: { type: 'array', items: { type: 'string' }, description: 'Filter by tags like ["reliable", "tested", "flutter"]' },
                        includeDetails: { type: 'boolean', default: false, description: 'Include full workflow details' },
                        framework: { type: 'string', description: 'Filter by framework compatibility' }
                    }
                }
            },
            {
                name: 'delete_workflow_template',
                description: '๐Ÿ—‘๏ธ Delete saved workflow template from storage. โš ๏ธ SAFETY: Requires explicit confirmation. ๐Ÿงน CLEANUP: Removes from both memory and persistent storage',
                inputSchema: {
                    type: 'object',
                    properties: {
                        workflowName: { type: 'string', description: 'Name of workflow to delete' },
                        confirmDelete: { type: 'boolean', default: false, description: 'Confirm deletion - REQUIRED for safety' }
                    },
                    required: ['workflowName', 'confirmDelete']
                }
            },
            {
                name: 'export_workflows',
                description: '๐Ÿ“ค Export workflows to shareable format (JSON/YAML). ๐Ÿค TEAM SHARING: Export framework-specific workflow collections. ๐Ÿ“ฆ INCLUDES: All metadata, compatibility info, usage examples',
                inputSchema: {
                    type: 'object',
                    properties: {
                        workflowNames: { type: 'array', items: { type: 'string' }, description: 'Specific workflows to export' },
                        format: { type: 'string', enum: ['json', 'yaml'], default: 'json' },
                        exportPath: { type: 'string', description: 'Custom export path' },
                        includeMetadata: { type: 'boolean', default: true },
                        filterByFramework: { type: 'string', description: 'Export only workflows for specific framework' }
                    }
                }
            },
            {
                name: 'import_workflows',
                description: '๐Ÿ“ฅ Import workflows from file or URL. ๐Ÿ” VALIDATES: Framework compatibility, workflow structure, dependencies. ๐Ÿ›ก๏ธ SAFE: Preview mode available, conflict resolution options',
                inputSchema: {
                    type: 'object',
                    properties: {
                        source: { type: 'string', description: 'File path or URL to import from' },
                        overwriteExisting: { type: 'boolean', default: false, description: 'Overwrite existing workflows' },
                        validateOnly: { type: 'boolean', default: false, description: 'Only validate compatibility, don\'t import' },
                        frameworkFilter: { type: 'string', description: 'Only import workflows for specific framework' }
                    },
                    required: ['source']
                }
            }
        ];
    }
    async handle(tool, params, sessions) {
        try {
            switch (tool) {
                case 'navigate_to_url':
                    return await this.navigateToUrl(params, sessions);
                case 'wait_for_navigation':
                    return await this.waitForNavigation(params, sessions);
                case 'create_workflow_template':
                    return await this.createWorkflowTemplate(params);
                case 'execute_user_journey':
                    return await this.executeUserJourney(params, sessions);
                case 'create_persistent_session':
                    return await this.createPersistentSession(params, sessions);
                case 'handle_page_transition':
                    return await this.handlePageTransition(params, sessions);
                case 'take_workflow_screenshot':
                    return await this.takeWorkflowScreenshot(params, sessions);
                case 'visual_workflow_validation':
                    return await this.visualWorkflowValidation(params, sessions);
                case 'save_workflow_template':
                    return await this.saveWorkflowTemplate(params);
                case 'load_workflow_template':
                    return await this.loadWorkflowTemplate(params);
                case 'list_saved_workflows':
                    return await this.listSavedWorkflows(params);
                case 'delete_workflow_template':
                    return await this.deleteWorkflowTemplate(params);
                case 'export_workflows':
                    return await this.exportWorkflows(params);
                case 'import_workflows':
                    return await this.importWorkflows(params);
                default:
                    throw new Error(`Unknown tool: ${tool}`);
            }
        }
        catch (error) {
            // P2 ENHANCEMENT: Use EnhancedErrorContext for actionable error messages
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async navigateToUrl(params, sessions) {
        const { url, options = {} } = params;
        const { waitUntil = 'load', timeout = 30000, expectedUrl } = options;
        // For standalone navigation, create a temporary session
        let page;
        let shouldCleanup = false;
        if (params.sessionId && sessions.has(params.sessionId)) {
            const session = sessions.get(params.sessionId);
            page = session.page;
        }
        else {
            // Create temporary browser instance
            const { chromium } = await import('playwright');
            const browser = await chromium.launch({ headless: false });
            page = await browser.newPage();
            shouldCleanup = true;
        }
        try {
            const startTime = Date.now();
            await page.goto(url, { waitUntil, timeout });
            // Validate expected URL if provided
            if (expectedUrl) {
                const currentUrl = page.url();
                if (!currentUrl.includes(expectedUrl) && currentUrl !== expectedUrl) {
                    // P2 FIX: Use EnhancedErrorContext instead of generic error
                    const urlMismatchError = `Navigation resulted in unexpected URL. Expected: ${expectedUrl}, Got: ${currentUrl}`;
                    return EnhancedErrorContext.createActionableErrorResponse(urlMismatchError, 'navigate_to_url');
                }
            }
            const navigationTime = Date.now() - startTime;
            return {
                success: true,
                url: page.url(),
                title: await page.title(),
                navigationTime,
                message: `Successfully navigated to ${url}`
            };
        }
        finally {
            if (shouldCleanup) {
                await page.context().browser()?.close();
            }
        }
    }
    async waitForNavigation(params, sessions) {
        const { sessionId, expectedUrl, timeout = 30000, transitionType = 'auto-detect' } = params;
        if (!sessions.has(sessionId)) {
            // P2 FIX: Use EnhancedErrorContext for session errors
            return EnhancedErrorContext.createSessionErrorResponse(sessionId);
        }
        const session = sessions.get(sessionId);
        const page = session.page;
        const startUrl = page.url();
        try {
            // Set up navigation promise based on transition type
            let navigationPromise;
            if (transitionType === 'full-reload') {
                navigationPromise = page.waitForLoadState('load', { timeout });
            }
            else if (transitionType === 'spa') {
                // For SPA, wait for URL change
                navigationPromise = page.waitForURL(expectedUrl || /.+/, { timeout });
            }
            else {
                // Auto-detect: wait for either
                navigationPromise = Promise.race([
                    page.waitForLoadState('load', { timeout }),
                    page.waitForURL(/.+/, { timeout })
                ]);
            }
            await navigationPromise;
            const finalUrl = page.url();
            const urlChanged = startUrl !== finalUrl;
            // Validate expected URL if provided
            if (expectedUrl && !finalUrl.includes(expectedUrl) && finalUrl !== expectedUrl) {
                // P2 FIX: Use EnhancedErrorContext instead of generic error
                const urlMismatchError = `Navigation completed but URL doesn't match expected. Expected: ${expectedUrl}, Got: ${finalUrl}`;
                return EnhancedErrorContext.createActionableErrorResponse(urlMismatchError, 'wait_for_navigation', sessionId);
            }
            return {
                success: true,
                startUrl,
                finalUrl,
                urlChanged,
                transitionType: urlChanged ? (transitionType === 'auto-detect' ? 'detected-spa' : transitionType) : 'no-navigation',
                message: `Navigation completed successfully`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for timeout/navigation errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async createWorkflowTemplate(params) {
        const { workflow } = params;
        // Validate workflow structure
        if (!workflow.name || !workflow.steps || !Array.isArray(workflow.steps)) {
            // P2 FIX: Use EnhancedErrorContext for validation errors
            return EnhancedErrorContext.createActionableErrorResponse('Invalid workflow structure. Must have name and steps array.', 'create_workflow_template');
        }
        // Store workflow template
        this.workflows.set(workflow.name, workflow);
        return {
            success: true,
            workflowName: workflow.name,
            stepCount: workflow.steps.length,
            description: workflow.description,
            sessionPersistence: workflow.sessionPersistence ?? true,
            retryStrategy: workflow.retryStrategy ?? 'step',
            message: `Workflow template '${workflow.name}' created with ${workflow.steps.length} steps`
        };
    }
    async executeUserJourney(params, sessions) {
        const { sessionId, journeyName, customization = {} } = params;
        if (!sessions.has(sessionId)) {
            // P2 FIX: Use EnhancedErrorContext for session errors
            return EnhancedErrorContext.createSessionErrorResponse(sessionId);
        }
        if (!this.workflows.has(journeyName)) {
            // P2 FIX: Use EnhancedErrorContext for workflow not found errors
            const workflowError = `Workflow '${journeyName}' not found. Available workflows: ${Array.from(this.workflows.keys()).join(', ')}`;
            return EnhancedErrorContext.createActionableErrorResponse(workflowError, 'execute_user_journey', sessionId);
        }
        const workflow = this.workflows.get(journeyName);
        const session = sessions.get(sessionId);
        const page = session.page;
        const results = [];
        const { userData = {}, skipSteps = [], additionalSteps = [] } = customization;
        try {
            // Execute workflow steps
            let stepIndex = 0;
            for (const step of workflow.steps) {
                if (skipSteps.includes(step.name)) {
                    results.push({
                        step: step.name,
                        status: 'skipped',
                        message: 'Step skipped by customization'
                    });
                    continue;
                }
                try {
                    const stepResult = await this.executeWorkflowStep(step, page, userData);
                    results.push({
                        step: step.name,
                        status: 'completed',
                        result: stepResult,
                        index: stepIndex
                    });
                }
                catch (stepError) {
                    const errorResult = {
                        step: step.name,
                        status: 'failed',
                        error: stepError instanceof Error ? stepError.message : 'Unknown error',
                        index: stepIndex,
                        enhancedError: EnhancedErrorContext.enhanceError(stepError instanceof Error ? stepError.message : String(stepError), 'execute_user_journey', sessionId)
                    };
                    results.push(errorResult);
                    // Handle retry strategy
                    if (workflow.retryStrategy === 'workflow') {
                        // P2 FIX: Use EnhancedErrorContext for workflow failure
                        const workflowFailError = `Workflow failed at step '${step.name}': ${errorResult.error}`;
                        return EnhancedErrorContext.createActionableErrorResponse(workflowFailError, 'execute_user_journey', sessionId);
                    }
                    else if (workflow.retryStrategy === 'step') {
                        // Continue with next step
                        console.warn(`Step '${step.name}' failed but continuing with workflow`);
                    }
                    // 'none' strategy just continues
                }
                stepIndex++;
            }
            // Execute additional steps if provided
            for (const additionalStep of additionalSteps) {
                try {
                    const stepResult = await this.executeWorkflowStep(additionalStep, page, userData);
                    results.push({
                        step: additionalStep.name,
                        status: 'completed',
                        result: stepResult,
                        index: stepIndex,
                        type: 'additional'
                    });
                }
                catch (stepError) {
                    results.push({
                        step: additionalStep.name,
                        status: 'failed',
                        error: stepError instanceof Error ? stepError.message : 'Unknown error',
                        index: stepIndex,
                        type: 'additional',
                        enhancedError: EnhancedErrorContext.enhanceError(stepError instanceof Error ? stepError.message : String(stepError), 'execute_user_journey', sessionId)
                    });
                }
                stepIndex++;
            }
            const completedSteps = results.filter(r => r.status === 'completed').length;
            const failedSteps = results.filter(r => r.status === 'failed').length;
            const skippedSteps = results.filter(r => r.status === 'skipped').length;
            return {
                success: true,
                workflowName: journeyName,
                totalSteps: results.length,
                completedSteps,
                failedSteps,
                skippedSteps,
                results,
                finalUrl: page.url(),
                message: `User journey '${journeyName}' executed: ${completedSteps} completed, ${failedSteps} failed, ${skippedSteps} skipped`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for journey execution errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async executeWorkflowStep(step, page, userData) {
        // Enhanced step execution with automatic framework detection and visual validation
        // Detect framework for intelligent tool selection
        const frameworkInfo = await this.detectFramework(page);
        // Take "before" screenshot if visual validation enabled
        let beforeScreenshot = null;
        if (step.data?.visualValidation !== false) {
            beforeScreenshot = await this.captureScreenshot(page, `${step.name}-before`);
        }
        let stepResult;
        switch (step.action) {
            case 'navigate':
                await page.goto(step.data.url, { timeout: step.timeout || 30000 });
                stepResult = { url: page.url(), title: await page.title(), framework: frameworkInfo };
                break;
            case 'click':
                // Auto-delegate to Flutter tools if Flutter app detected
                if (frameworkInfo.isFlutter && step.data.flutterCommand) {
                    stepResult = await this.delegateToFlutterTool('flutter_quantum_interact', {
                        command: step.data.flutterCommand || `click ${step.data.selector}`
                    });
                }
                else {
                    await page.click(step.data.selector, { timeout: step.timeout || 10000 });
                    stepResult = { clicked: step.data.selector, framework: frameworkInfo };
                }
                break;
            case 'fill':
                // Auto-delegate to Flutter tools if Flutter app detected
                if (frameworkInfo.isFlutter && step.data.flutterCommand) {
                    stepResult = await this.delegateToFlutterTool('flutter_quantum_interact', {
                        command: step.data.flutterCommand || `type ${step.data.value || userData[step.data.dataKey]} in ${step.data.selector}`
                    });
                }
                else {
                    await page.fill(step.data.selector, step.data.value || userData[step.data.dataKey] || '', { timeout: step.timeout || 10000 });
                    stepResult = { filled: step.data.selector, value: step.data.value || userData[step.data.dataKey], framework: frameworkInfo };
                }
                break;
            case 'wait':
                await page.waitForTimeout(step.data.duration || 1000);
                stepResult = { waited: step.data.duration || 1000 };
                break;
            case 'waitForSelector':
                // Enhanced waiting with framework-aware selectors
                let selector = step.data.selector;
                if (frameworkInfo.isPhoenixLiveView && !selector.includes('phx-') && !selector.includes('[data-testid')) {
                    console.warn(`Phoenix LiveView detected but selector "${selector}" doesn't use phx-* or data-testid attributes. Consider using framework-specific selectors.`);
                }
                await page.waitForSelector(selector, { timeout: step.timeout || 10000 });
                stepResult = { selector, found: true, framework: frameworkInfo };
                break;
            case 'custom':
                // Allow custom JavaScript execution with framework context
                if (step.data.script) {
                    const result = await page.evaluate(step.data.script);
                    stepResult = { customResult: result, framework: frameworkInfo };
                }
                else if (step.data.flutterTool && frameworkInfo.isFlutter) {
                    stepResult = await this.delegateToFlutterTool(step.data.flutterTool, step.data);
                }
                else {
                    stepResult = { message: 'Custom step executed', framework: frameworkInfo };
                }
                break;
            case 'smart_interaction':
                // New smart interaction that auto-selects best approach
                stepResult = await this.smartInteraction(step.data, page, frameworkInfo);
                break;
            case 'take_screenshot':
                // Dedicated screenshot action
                const screenshot = await this.captureScreenshot(page, step.data.filename || step.name);
                stepResult = { screenshot, message: 'Screenshot captured successfully' };
                break;
            case 'visual_validation':
                // AI-powered visual validation
                stepResult = await this.performVisualValidation(page, step.data, frameworkInfo);
                break;
            default:
                throw new Error(`Unknown step action: ${step.action}`);
        }
        // Take "after" screenshot if visual validation enabled
        let afterScreenshot = null;
        if (step.data?.visualValidation !== false && step.action !== 'take_screenshot') {
            afterScreenshot = await this.captureScreenshot(page, `${step.name}-after`);
        }
        // Add visual context to step result
        if (beforeScreenshot || afterScreenshot) {
            stepResult.visualEvidence = {
                before: beforeScreenshot,
                after: afterScreenshot,
                stepName: step.name,
                timestamp: new Date().toISOString()
            };
            // AI visual analysis if enabled
            if (step.data?.aiVisualAnalysis) {
                stepResult.aiAnalysis = await this.analyzeVisualChange(beforeScreenshot, afterScreenshot, step, frameworkInfo);
            }
        }
        return stepResult;
    }
    async detectFramework(page) {
        try {
            const frameworkInfo = await page.evaluate(() => {
                const url = window.location.href;
                const html = document.documentElement.outerHTML;
                // Flutter Detection
                const isFlutter = Boolean(
                // Flutter-specific elements
                document.querySelector('flutter-view') ||
                    document.querySelector('[flt-renderer]') ||
                    html.includes('flutter') ||
                    // Flutter configuration
                    window.flutterConfiguration ||
                    // Canvas-heavy rendering (common in Flutter)
                    document.querySelectorAll('canvas').length > 2 ||
                    // URL patterns
                    url.includes('flutter') || url.includes('dart'));
                // Phoenix LiveView Detection  
                const isPhoenixLiveView = Boolean(
                // LiveView-specific attributes
                document.querySelector('[phx-click]') ||
                    document.querySelector('[phx-submit]') ||
                    document.querySelector('[phx-change]') ||
                    document.querySelector('[phx-hook]') ||
                    // LiveView socket
                    window.liveSocket ||
                    // LiveView metadata
                    document.querySelector('meta[name="csrf-token"]') &&
                        (html.includes('phx-') || html.includes('live_')));
                // React Detection
                const isReact = Boolean(document.querySelector('[data-reactroot]') ||
                    document.querySelector('#root') ||
                    window.React ||
                    html.includes('react'));
                // Vue Detection
                const isVue = Boolean(document.querySelector('[data-v-]') ||
                    window.Vue ||
                    html.includes('vue'));
                // Next.js Detection
                const isNextJS = Boolean(document.querySelector('#__next') ||
                    window.__NEXT_DATA__ ||
                    html.includes('_next'));
                // Angular Detection
                const isAngular = Boolean(document.querySelector('[ng-version]') ||
                    window.ng ||
                    html.includes('angular'));
                return {
                    isFlutter,
                    isPhoenixLiveView,
                    isReact,
                    isVue,
                    isNextJS,
                    isAngular,
                    url,
                    detectedAt: new Date().toISOString()
                };
            });
            return frameworkInfo;
        }
        catch (error) {
            console.warn('Framework detection failed:', error);
            return {
                isFlutter: false,
                isPhoenixLiveView: false,
                isReact: false,
                isVue: false,
                isNextJS: false,
                isAngular: false,
                url: page.url(),
                detectedAt: new Date().toISOString(),
                detectionError: error instanceof Error ? error.message : 'Unknown error'
            };
        }
    }
    async delegateToFlutterTool(toolName, params) {
        try {
            // This would delegate to actual Flutter tools in a real implementation
            // For now, return a simulation of Flutter tool delegation
            console.log(`๐Ÿ”„ Delegating to Flutter tool: ${toolName}`, params);
            return {
                success: true,
                delegatedTo: toolName,
                params,
                message: `Successfully delegated to Flutter tool: ${toolName}`,
                // In real implementation, this would call the actual Flutter tool
                simulatedResult: {
                    toolUsed: toolName,
                    frameworkDetected: 'Flutter Web',
                    action: 'delegated_to_flutter_tools'
                }
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for delegation errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async smartInteraction(stepData, page, frameworkInfo) {
        const { action, target, value } = stepData;
        try {
            if (frameworkInfo.isFlutter) {
                // Use Flutter-specific interaction
                let command = '';
                if (action === 'click') {
                    command = `click ${target}`;
                }
                else if (action === 'fill') {
                    command = `type ${value} in ${target}`;
                }
                else {
                    command = `${action} ${target}`;
                }
                return await this.delegateToFlutterTool('flutter_quantum_interact', { command });
            }
            else {
                // Use standard web interaction
                if (action === 'click') {
                    await page.click(target);
                    return { action: 'click', target, framework: 'standard-web' };
                }
                else if (action === 'fill') {
                    await page.fill(target, value);
                    return { action: 'fill', target, value, framework: 'standard-web' };
                }
                else {
                    throw new Error(`Unsupported smart interaction action: ${action}`);
                }
            }
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for smart interaction errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async captureScreenshot(page, filename) {
        try {
            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
            const screenshotPath = join(process.cwd(), '.ai-debug', 'screenshots', `${filename}-${timestamp}.png`);
            // Ensure screenshot directory exists
            const screenshotDir = join(process.cwd(), '.ai-debug', 'screenshots');
            if (!existsSync(screenshotDir)) {
                await mkdir(screenshotDir, { recursive: true });
            }
            const screenshotBuffer = await page.screenshot({
                path: screenshotPath,
                fullPage: true,
                type: 'png'
            });
            // Get page context for AI analysis
            const pageContext = await page.evaluate(() => ({
                url: window.location.href,
                title: document.title,
                viewport: {
                    width: window.innerWidth,
                    height: window.innerHeight
                },
                elementCount: document.querySelectorAll('*').length,
                hasErrors: window.console ? console.error.length > 0 : false
            }));
            return {
                success: true,
                path: screenshotPath,
                filename: `${filename}-${timestamp}.png`,
                size: screenshotBuffer.length,
                pageContext,
                timestamp: new Date().toISOString(),
                dimensions: await page.evaluate(() => ({
                    width: document.documentElement.scrollWidth,
                    height: document.documentElement.scrollHeight
                }))
            };
        }
        catch (error) {
            return {
                success: false,
                error: error instanceof Error ? error.message : 'Unknown error',
                filename,
                timestamp: new Date().toISOString()
            };
        }
    }
    async performVisualValidation(page, validationConfig, frameworkInfo) {
        try {
            const screenshot = await this.captureScreenshot(page, validationConfig.name || 'validation');
            const validationChecks = [];
            // Framework-specific visual checks
            if (frameworkInfo.isFlutter) {
                validationChecks.push({
                    type: 'flutter_widget_visibility',
                    status: 'checking',
                    description: 'Verifying Flutter widgets are rendered properly'
                });
            }
            else if (frameworkInfo.isPhoenixLiveView) {
                validationChecks.push({
                    type: 'liveview_mount_status',
                    status: 'checking',
                    description: 'Verifying LiveView components are mounted'
                });
            }
            // Generic visual checks
            validationChecks.push({
                type: 'page_loaded',
                status: await this.checkPageLoaded(page) ? 'passed' : 'failed',
                description: 'Page fully loaded without errors'
            }, {
                type: 'no_console_errors',
                status: await this.checkConsoleErrors(page) ? 'passed' : 'failed',
                description: 'No JavaScript console errors'
            }, {
                type: 'expected_elements_present',
                status: validationConfig.expectedElements ?
                    await this.checkExpectedElements(page, validationConfig.expectedElements) ? 'passed' : 'failed' : 'skipped',
                description: 'Expected UI elements are present'
            });
            // Custom validation checks
            if (validationConfig.customChecks) {
                for (const customCheck of validationConfig.customChecks) {
                    const result = await page.evaluate(customCheck.script);
                    validationChecks.push({
                        type: 'custom',
                        name: customCheck.name,
                        status: result ? 'passed' : 'failed',
                        description: customCheck.description,
                        result
                    });
                }
            }
            const passedChecks = validationChecks.filter(c => c.status === 'passed').length;
            const failedChecks = validationChecks.filter(c => c.status === 'failed').length;
            return {
                success: true,
                screenshot,
                validationChecks,
                summary: {
                    total: validationChecks.length,
                    passed: passedChecks,
                    failed: failedChecks,
                    score: Math.round((passedChecks / validationChecks.length) * 100)
                },
                framework: frameworkInfo,
                message: `Visual validation completed: ${passedChecks}/${validationChecks.length} checks passed`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for validation errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async analyzeVisualChange(before, after, step, frameworkInfo) {
        try {
            if (!before || !after) {
                return {
                    hasVisualChange: false,
                    confidence: 0,
                    message: 'Insufficient screenshots for comparison',
                    framework: frameworkInfo.isFlutter ? 'Flutter' : frameworkInfo.isPhoenixLiveView ? 'Phoenix LiveView' : 'Standard Web'
                };
            }
            // Simple visual change detection (in production, this would use computer vision)
            const sizeDifference = Math.abs((after.size || 0) - (before.size || 0));
            const hasSignificantChange = sizeDifference > 1000; // Basic heuristic
            // Framework-specific analysis
            let frameworkAnalysis = '';
            if (frameworkInfo.isFlutter) {
                frameworkAnalysis = 'Flutter app interaction detected - widget state likely changed';
            }
            else if (frameworkInfo.isPhoenixLiveView) {
                frameworkAnalysis = 'Phoenix LiveView interaction - server state update expected';
            }
            else {
                frameworkAnalysis = 'Standard web interaction - DOM changes expected';
            }
            // Action-specific expectations
            let expectedChange = '';
            switch (step.action) {
                case 'click':
                    expectedChange = 'Button click should trigger visual feedback (navigation, modal, state change)';
                    break;
                case 'fill':
                    expectedChange = 'Form input should show typed content and potentially validation messages';
                    break;
                case 'navigate':
                    expectedChange = 'Page navigation should show completely different content';
                    break;
                default:
                    expectedChange = 'Some visual change expected based on user action';
            }
            return {
                hasVisualChange: hasSignificantChange,
                confidence: hasSignificantChange ? 75 : 25,
                sizeDifference,
                beforeSize: before.size || 0,
                afterSize: after.size || 0,
                frameworkAnalysis,
                expectedChange,
                stepAction: step.action,
                message: hasSignificantChange ?
                    'Significant visual change detected - action likely successful' :
                    'Minimal visual change - verify action completed as expected',
                framework: frameworkInfo.isFlutter ? 'Flutter' : frameworkInfo.isPhoenixLiveView ? 'Phoenix LiveView' : 'Standard Web',
                recommendations: this.generateVisualRecommendations(step, frameworkInfo, hasSignificantChange)
            };
        }
        catch (error) {
            return {
                hasVisualChange: false,
                confidence: 0,
                error: error instanceof Error ? error.message : 'Unknown error',
                message: 'Visual analysis failed',
                framework: 'Unknown'
            };
        }
    }
    generateVisualRecommendations(step, frameworkInfo, hasChange) {
        const recommendations = [];
        if (!hasChange) {
            recommendations.push('โš ๏ธ No significant visual change detected');
            if (frameworkInfo.isFlutter) {
                recommendations.push('๐ŸŽฏ For Flutter: Verify widget selector is correct, try flutter_quantum_find to locate elements');
                recommendations.push('๐Ÿ” Check if Flutter app is in Canvas rendering mode (limits DOM-based interactions)');
            }
            else if (frameworkInfo.isPhoenixLiveView) {
                recommendations.push('๐ŸŽฏ For Phoenix LiveView: Ensure phx-* attributes are used, check WebSocket connection');
                recommendations.push('โฑ๏ธ LiveView updates may have timing delays - consider adding wait steps');
            }
            else {
                recommendations.push('๐ŸŽฏ For standard web: Verify CSS selector exists and element is interactive');
                recommendations.push('โฑ๏ธ Consider adding wait for dynamic content or async operations');
            }
            if (step.action === 'click') {
                recommendations.push('๐Ÿ–ฑ๏ธ Click action: Verify button is enabled, not hidden, and click event is properly bound');
            }
            else if (step.action === 'fill') {
                recommendations.push('๐Ÿ“ Fill action: Ensure input field is visible, enabled, and accepts the provided value');
            }
        }
        else {
            recommendations.push('โœ… Visual change detected - action appears successful');
            recommendations.push('๐Ÿ“ธ Consider adding validation step to verify expected outcome');
        }
        return recommendations;
    }
    async checkPageLoaded(page) {
        try {
            return await page.evaluate(() => {
                return document.readyState === 'complete' &&
                    !document.querySelector('[aria-busy="true"]') &&
                    !document.querySelector('.loading') &&
                    !document.querySelector('[data-loading="true"]');
            });
        }
        catch {
            return false;
        }
    }
    async checkConsoleErrors(page) {
        try {
            // This would need to be implemented with page.on('console') listener
            // For now, return true as placeholder
            return true;
        }
        catch {
            return false;
        }
    }
    async checkExpectedElements(page, expectedElements) {
        try {
            for (const selector of expectedElements) {
                const element = await page.$(selector);
                if (!element)
                    return false;
            }
            return true;
        }
        catch {
            return false;
        }
    }
    async takeWorkflowScreenshot(params, sessions) {
        const { sessionId, filename, analysisConfig = {} } = params;
        if (!sessions.has(sessionId)) {
            // P2 FIX: Use EnhancedErrorContext for session errors
            return EnhancedErrorContext.createSessionErrorResponse(sessionId);
        }
        const session = sessions.get(sessionId);
        const page = session.page;
        try {
            // Capture screenshot
            const screenshot = await this.captureScreenshot(page, filename || 'workflow-screenshot');
            if (!screenshot.success) {
                return screenshot;
            }
            // Perform analysis if enabled
            let analysis = null;
            if (analysisConfig.enableAI !== false) {
                const frameworkInfo = await this.detectFramework(page);
                analysis = await this.performVisualValidation(page, {
                    name: filename || 'screenshot-analysis',
                    expectedElements: analysisConfig.expectedElements,
                    customChecks: analysisConfig.customChecks
                }, frameworkInfo);
            }
            return {
                success: true,
                screenshot,
                analysis,
                sessionId,
                message: 'Workflow screenshot captured successfully'
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for screenshot errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async visualWorkflowValidation(params, sessions) {
        const { sessionId, validationName, validationConfig = {} } = params;
        if (!sessions.has(sessionId)) {
            // P2 FIX: Use EnhancedErrorContext for session errors
            return EnhancedErrorContext.createSessionErrorResponse(sessionId);
        }
        const session = sessions.get(sessionId);
        const page = session.page;
        try {
            const frameworkInfo = await this.detectFramework(page);
            // Perform comprehensive visual validation
            const validation = await this.performVisualValidation(page, {
                name: validationName,
                ...validationConfig
            }, frameworkInfo);
            // Check for forbidden elements
            if (validationConfig.forbiddenElements) {
                for (const selector of validationConfig.forbiddenElements) {
                    const element = await page.$(selector);
                    if (element) {
                        validation.validationChecks.push({
                            type: 'forbidden_element_check',
                            status: 'failed',
                            description: `Forbidden element found: ${selector}`
                        });
                    }
                }
            }
            // Calculate final score
            const passedChecks = validation.validationChecks.filter((c) => c.status === 'passed').length;
            const totalChecks = validation.validationChecks.length;
            const score = totalChecks > 0 ? Math.round((passedChecks / totalChecks) * 100) : 0;
            const meetsThreshold = score >= (validationConfig.tolerance || 85);
            return {
                success: true,
                validationName,
                score,
                meetsThreshold,
                threshold: validationConfig.tolerance || 85,
                validation,
                framework: frameworkInfo,
                recommendations: meetsThreshold ?
                    ['โœ… Validation passed - workflow state is as expected'] :
                    [
                        'โš ๏ธ Validation below threshold - review failed checks',
                        '๐Ÿ” Consider adjusting selectors or validation criteria',
                        '๐Ÿ“ธ Review screenshot for visual confirmation'
                    ],
                sessionId,
                message: `Visual validation ${meetsThreshold ? 'PASSED' : 'FAILED'}: ${score}% (threshold: ${validationConfig.tolerance || 85}%)`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for validation errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async createPersistentSession(params, sessions) {
        const { sessionId, sessionConfig = {} } = params;
        if (!sessions.has(sessionId)) {
            // P2 FIX: Use EnhancedErrorContext for session errors
            return EnhancedErrorContext.createSessionErrorResponse(sessionId);
        }
        const session = sessions.get(sessionId);
        const page = session.page;
        try {
            // Capture current session state
            const sessionData = {};
            if (sessionConfig.persistCookies !== false) {
                sessionData.cookies = await page.context().cookies();
            }
            if (sessionConfig.persistLocalStorage !== false) {
                sessionData.localStorage = await page.evaluate(() => {
                    const storage = {};
                    for (let i = 0; i < localStorage.length; i++) {
                        const key = localStorage.key(i);
                        if (key)
                            storage[key] = localStorage.getItem(key) || '';
                    }
                    return storage;
                });
            }
            if (sessionConfig.persistSessionStorage !== false) {
                sessionData.sessionStorage = await page.evaluate(() => {
                    const storage = {};
                    for (let i = 0; i < sessionStorage.length; i++) {
                        const key = sessionStorage.key(i);
                        if (key)
                            storage[key] = sessionStorage.getItem(key) || '';
                    }
                    return storage;
                });
            }
            if (sessionConfig.userAgent) {
                sessionData.userAgent = sessionConfig.userAgent;
                await page.setExtraHTTPHeaders({ 'User-Agent': sessionConfig.userAgent });
            }
            if (sessionConfig.viewport) {
                sessionData.viewport = sessionConfig.viewport;
                await page.setViewportSize(sessionConfig.viewport);
            }
            // Store session data for restoration
            this.sessionData.set(sessionId, sessionData);
            return {
                success: true,
                sessionId,
                persistedData: {
                    cookies: sessionData.cookies?.length || 0,
                    localStorageKeys: Object.keys(sessionData.localStorage || {}).length,
                    sessionStorageKeys: Object.keys(sessionData.sessionStorage || {}).length,
                    userAgent: !!sessionData.userAgent,
                    viewport: !!sessionData.viewport
                },
                message: `Persistent session created for ${sessionId}`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for session creation errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async handlePageTransition(params, sessions) {
        const { sessionId, transitionType, expectedBehavior = {} } = params;
        if (!sessions.has(sessionId)) {
            // P2 FIX: Use EnhancedErrorContext for session errors
            return EnhancedErrorContext.createSessionErrorResponse(sessionId);
        }
        const session = sessions.get(sessionId);
        const page = session.page;
        const startUrl = page.url();
        // Restore session data if available
        if (this.sessionData.has(sessionId)) {
            const sessionData = this.sessionData.get(sessionId);
            try {
                // Restore cookies
                if (sessionData.cookies) {
                    await page.context().addCookies(sessionData.cookies);
                }
                // Restore localStorage
                if (sessionData.localStorage) {
                    await page.evaluate((storage) => {
                        for (const [key, value] of Object.entries(storage)) {
                            localStorage.setItem(key, value);
                        }
                    }, sessionData.localStorage);
                }
                // Restore sessionStorage
                if (sessionData.sessionStorage) {
                    await page.evaluate((storage) => {
                        for (const [key, value] of Object.entries(storage)) {
                            sessionStorage.setItem(key, value);
                        }
                    }, sessionData.sessionStorage);
                }
            }
            catch (error) {
                console.warn('Failed to restore some session data:', error);
            }
        }
        return {
            success: true,
            sessionId,
            startUrl,
            currentUrl: page.url(),
            transitionType,
            sessionRestored: this.sessionData.has(sessionId),
            message: `Page transition handled for ${transitionType} navigation`
        };
    }
    // Storage and workflow management methods
    async initializeStorage() {
        try {
            if (!existsSync(this.workflowStoragePath)) {
                await mkdir(this.workflowStoragePath, { recursive: true });
            }
            // Load existing workflows from storage
            await this.loadAllWorkflowsFromStorage();
        }
        catch (error) {
            console.warn('Failed to initialize workflow storage:', error);
        }
    }
    async loadAllWorkflowsFromStorage() {
        try {
            const { readdir } = await import('fs/promises');
            const files = await readdir(this.workflowStoragePath);
            for (const file of files) {
                if (file.endsWith('.json')) {
                    try {
                        const workflowName = file.replace('.json', '');
                        const filePath = join(this.workflowStoragePath, file);
                        const content = await readFile(filePath, 'utf-8');
                        const workflowData = JSON.parse(content);
                        this.workflows.set(workflowName, workflowData.workflow);
                    }
                    catch (error) {
                        console.warn(`Failed to load workflow ${file}:`, error);
                    }
                }
            }
            console.log(`๐Ÿ“ Loaded ${this.workflows.size} saved workflows from storage`);
        }
        catch (error) {
            // Storage directory doesn't exist yet - this is fine
        }
    }
    async saveWorkflowTemplate(params) {
        const { workflowName, filePath, metadata = {} } = params;
        if (!this.workflows.has(workflowName)) {
            // P2 FIX: Use EnhancedErrorContext for workflow not found errors
            const notFoundError = `Workflow '${workflowName}' not found in memory. Create it first with create_workflow_template.`;
            return EnhancedErrorContext.createActionableErrorResponse(notFoundError, 'save_workflow_template');
        }
        try {
            const workflow = this.workflows.get(workflowName);
            const workflowData = {
                workflow,
                metadata: {
                    ...metadata,
                    savedAt: new Date().toISOString(),
                    version: metadata.version || '1.0.0'
                }
            };
            const targetPath = filePath || join(this.workflowStoragePath, `${workflowName}.json`);
            await writeFile(targetPath, JSON.stringify(workflowData, null, 2), 'utf-8');
            return {
                success: true,
                workflowName,
                savedPath: targetPath,
                metadata: workflowData.metadata,
                message: `Workflow '${workflowName}' saved successfully to ${targetPath}`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for save errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async loadWorkflowTemplate(params) {
        const { workflowName, filePath } = params;
        try {
            const targetPath = filePath || join(this.workflowStoragePath, `${workflowName}.json`);
            if (!existsSync(targetPath)) {
                // P2 FIX: Use EnhancedErrorContext for file not found errors
                const fileNotFoundError = `Workflow file not found: ${targetPath}`;
                return EnhancedErrorContext.createActionableErrorResponse(fileNotFoundError, 'load_workflow_template');
            }
            const content = await readFile(targetPath, 'utf-8');
            const workflowData = JSON.parse(content);
            // Load into memory
            this.workflows.set(workflowName, workflowData.workflow);
            return {
                success: true,
                workflowName,
                loadedFrom: targetPath,
                workflow: workflowData.workflow,
                metadata: workflowData.metadata,
                stepCount: workflowData.workflow.steps.length,
                message: `Workflow '${workflowName}' loaded successfully from ${targetPath}`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for load errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async listSavedWorkflows(params = {}) {
        const { category, tags, includeDetails = false } = params;
        try {
            const { readdir } = await import('fs/promises');
            const files = await readdir(this.workflowStoragePath);
            const workflows = [];
            for (const file of files) {
                if (file.endsWith('.json')) {
                    try {
                        const workflowName = file.replace('.json', '');
                        const filePath = join(this.workflowStoragePath, file);
                        const content = await readFile(filePath, 'utf-8');
                        const workflowData = JSON.parse(content);
                        // Apply filters
                        if (category && workflowData.metadata?.category !== category)
                            continue;
                        if (tags && tags.length > 0) {
                            const workflowTags = workflowData.metadata?.tags || [];
                            if (!tags.some((tag) => workflowTags.includes(tag)))
                                continue;
                        }
                        const workflowInfo = {
                            name: workflowName,
                            description: workflowData.workflow.description,
                            stepCount: workflowData.workflow.steps.length,
                            metadata: workflowData.metadata,
                            filePath
                        };
                        if (includeDetails) {
                            workflowInfo.workflow = workflowData.workflow;
                        }
                        workflows.push(workflowInfo);
                    }
                    catch (error) {
                        console.warn(`Failed to read workflow ${file}:`, error);
                    }
                }
            }
            return {
                success: true,
                count: workflows.length,
                workflows,
                filters: { category, tags },
                message: `Found ${workflows.length} saved workflows`
            };
        }
        catch (error) {
            return {
                success: true,
                count: 0,
                workflows: [],
                message: 'No saved workflows found (storage directory does not exist yet)'
            };
        }
    }
    async deleteWorkflowTemplate(params) {
        const { workflowName, confirmDelete } = params;
        if (!confirmDelete) {
            // P2 FIX: Use EnhancedErrorContext for confirmation errors
            const confirmationError = 'Delete confirmation required. Set confirmDelete: true to proceed.';
            return EnhancedErrorContext.createActionableErrorResponse(confirmationError, 'delete_workflow_template');
        }
        try {
            const filePath = join(this.workflowStoragePath, `${workflowName}.json`);
            if (!existsSync(filePath)) {
                // P2 FIX: Use EnhancedErrorContext for file not found errors
                const fileNotFoundError = `Workflow file not found: ${filePath}`;
                return EnhancedErrorContext.createActionableErrorResponse(fileNotFoundError, 'delete_workflow_template');
            }
            const { unlink } = await import('fs/promises');
            await unlink(filePath);
            // Remove from memory if loaded
            this.workflows.delete(workflowName);
            return {
                success: true,
                workflowName,
                deletedPath: filePath,
                message: `Workflow '${workflowName}' deleted successfully`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for deletion errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async exportWorkflows(params = {}) {
        const { workflowNames, format = 'json', exportPath, includeMetadata = true } = params;
        try {
            const workflowsToExport = {};
            const workflowList = workflowNames || Array.from(this.workflows.keys());
            // Collect workflows to export
            for (const workflowName of workflowList) {
                if (this.workflows.has(workflowName)) {
                    const workflow = this.workflows.get(workflowName);
                    workflowsToExport[workflowName] = {
                        workflow,
                        exportedAt: new Date().toISOString()
                    };
                    // Include metadata if available and requested
                    if (includeMetadata) {
                        try {
                            const filePath = join(this.workflowStoragePath, `${workflowName}.json`);
                            if (existsSync(filePath)) {
                                const content = await readFile(filePath, 'utf-8');
                                const workflowData = JSON.parse(content);
                                workflowsToExport[workflowName].metadata = workflowData.metadata;
                            }
                        }
                        catch (error) {
                            // Metadata not available - continue without it
                        }
                    }
                }
            }
            const exportData = {
                exportInfo: {
                    exportedAt: new Date().toISOString(),
                    format,
                    workflowCount: Object.keys(workflowsToExport).length,
                    version: '1.0.0'
                },
                workflows: workflowsToExport
            };
            let exportContent;
            let fileName;
            if (format === 'yaml') {
                // Simple YAML export (basic implementation)
                exportContent = this.convertToYaml(exportData);
                fileName = 'workflows-export.yaml';
            }
            else {
                exportContent = JSON.stringify(exportData, null, 2);
                fileName = 'workflows-export.json';
            }
            const finalExportPath = exportPath || join(process.cwd(), fileName);
            await writeFile(finalExportPath, exportContent, 'utf-8');
            return {
                success: true,
                exportPath: finalExportPath,
                format,
                workflowCount: Object.keys(workflowsToExport).length,
                workflowNames: Object.keys(workflowsToExport),
                message: `Exported ${Object.keys(workflowsToExport).length} workflows to ${finalExportPath}`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for export errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    async importWorkflows(params) {
        const { source, overwriteExisting = false, validateOnly = false } = params;
        try {
            let importContent;
            // Handle URL vs file path
            if (source.startsWith('http://') || source.startsWith('https://')) {
                // Import from URL
                const response = await fetch(source);
                if (!response.ok) {
                    // P2 FIX: Use EnhancedErrorContext for network errors
                    const fetchError = `Failed to fetch from URL: ${response.statusText}`;
                    return EnhancedErrorContext.createActionableErrorResponse(fetchError, 'import_workflows');
                }
                importContent = await response.text();
            }
            else {
                // Import from file
                if (!existsSync(source)) {
                    // P2 FIX: Use EnhancedErrorContext for file not found errors
                    const fileNotFoundError = `Import file not found: ${source}`;
                    return EnhancedErrorContext.createActionableErrorResponse(fileNotFoundError, 'import_workflows');
                }
                importContent = await readFile(source, 'utf-8');
            }
            // Parse content
            let importData;
            try {
                if (source.endsWith('.yaml') || source.endsWith('.yml')) {
                    // Basic YAML parsing (simplified)
                    importData = this.parseYaml(importContent);
                }
                else {
                    importData = JSON.parse(importContent);
                }
            }
            catch (error) {
                // P2 FIX: Use EnhancedErrorContext for parsing errors
                const parseError = `Failed to parse import content: ${error instanceof Error ? error.message : 'Invalid format'}`;
                return EnhancedErrorContext.createActionableErrorResponse(parseError, 'import_workflows');
            }
            // Validate structure
            if (!importData.workflows || typeof importData.workflows !== 'object') {
                // P2 FIX: Use EnhancedErrorContext for structure validation errors
                const structureError = 'Invalid import format: missing workflows object';
                return EnhancedErrorContext.createActionableErrorResponse(structureError, 'import_workflows');
            }
            const importResults = [];
            const workflowNames = Object.keys(importData.workflows);
            for (const workflowName of workflowNames) {
                const workflowData = importData.workflows[workflowName];
                try {
                    // Validate workflow structure
                    if (!workflowData.workflow || !workflowData.workflow.steps) {
                        throw new Error('Invalid workflow structure');
                    }
                    const exists = this.workflows.has(workflowName);
                    if (exists && !overwriteExisting) {
                        importResults.push({
                            name: workflowName,
                            status: 'skipped',
                            reason: 'Workflow exists and overwrite not enabled'
                        });
                        continue;
                    }
                    if (!validateOnly) {
                        // Import the workflow
                        this.workflows.set(workflowName, workflowData.workflow);
                        // Save to storage
                        const workflowFileData = {
                            workflow: workflowData.workflow,
                            metadata: {
                                ...workflowData.metadata,
                                importedAt: new Date().toISOString(),
                                importedFrom: source
                            }
                        };
                        const filePath = join(this.workflowStoragePath, `${workflowName}.json`);
                        await writeFile(filePath, JSON.stringify(workflowFileData, null, 2), 'utf-8');
                    }
                    importResults.push({
                        name: workflowName,
                        status: validateOnly ? 'valid' : (exists ? 'updated' : 'imported'),
                        stepCount: workflowData.workflow.steps.length
                    });
                }
                catch (error) {
                    importResults.push({
                        name: workflowName,
                        status: 'failed',
                        error: error instanceof Error ? error.message : 'Unknown error'
                    });
                }
            }
            const successCount = importResults.filter(r => ['imported', 'updated', 'valid'].includes(r.status)).length;
            return {
                success: true,
                source,
                validateOnly,
                totalWorkflows: workflowNames.length,
                successCount,
                results: importResults,
                message: validateOnly
                    ? `Validated ${successCount}/${workflowNames.length} workflows`
                    : `Imported ${successCount}/${workflowNames.length} workflows successfully`
            };
        }
        catch (error) {
            // P2 FIX: Use EnhancedErrorContext for import errors
            return EnhancedErrorContext.createActionableErrorResponse(error instanceof Error ? error.message : String(error), 'universal_workflow');
        }
    }
    // Utility methods for YAML conversion (basic implementation)
    convertToYaml(data) {
        // Basic YAML conversion - in production you'd use a proper YAML library
        return `# AI-Debug Workflows Export\n# Generated at: ${new Date().toISOString()}\n\n${JSON.stringify(data, null, 2)}`;
    }
    parseYaml(content) {
        // Basic YAML parsing - in production you'd use a proper YAML library
        // For now, try to parse as JSON if it looks like JSON
        const trimmed = content.trim();
        if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
            return JSON.parse(trimmed);
        }
        throw new Error('YAML parsing not implemented - use JSON format');
    }
}
//# sourceMappingURL=universal-workflow-handler.js.map