CoolFace
Apppublic

LaiLarry/Consulting_Assistant_Agent

sourceHugging Faceapache-2.0updated 11mo agoView on Hugging Face
1likes
bob.html2726 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en">3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>Consulting Assistant</title>7    <script src="https://cdn.tailwindcss.com"></script>8    <style>9        /* Import Georgia (Body) and Roboto Slab (Buttons) */10        @import url('https://fonts.googleapis.com/css2?family=Georgia:wght@400;700&family=Roboto+Slab:wght=700&display=swap');11        12        body {13            /* Main body and response content remains Georgia */14            font-family: 'Georgia', sans-serif;15            background-color: #111827; /* Tailwind gray-900 equivalent */16        }17        18        /* * Main Title: Smaller font, centered, bold. 19         * We'll use this for the H1 tag generated by Markdown's '#' 20         */21        .ai-response-content h1 {22            font-size: 1.8rem;23            font-weight: 700;24            text-align: center;25            margin-bottom: 1rem;26        }27        28        /* * Key Sections: Smaller font than the title, bold, no bullet point. 29         * We'll use this for the H2 tag generated by Markdown's '##' 30         */31        .ai-response-content h2 {32            font-size: 1.3rem;33            font-weight: 700;34            margin-top: 1.5rem;35            margin-bottom: 0.5rem;36            color: #bef264 !important;37        }38        39        /* * Sub-sections within a section. 40         * We'll use this for the H3 tag generated by Markdown's '###' 41         */42        .ai-response-content h3 {43            font-size: 1.1rem; /* Slightly smaller for better hierarchy */44            font-weight: 700;45            margin-top: 1rem;46            margin-bottom: 0.5rem;47            color: #facc15 !important;48        }49        50        /* * Points in Sections: Bold, smaller than sections, larger than content. 51         * Markdown wraps these in a `<strong>` tag. 52         */53        .ai-response-content strong {54            font-size: 1rem;55            font-weight: 700;56            display: block; 57            margin-bottom: 0.25rem; 58            color: #facc15 !important;59        }60        61        /* Ensure bulleted lists are styled correctly and have a top margin */62        .ai-response-content ul {63            list-style-type: disc;64            padding-left: 2rem;65            margin-top: 0.5rem; /* Reduced margin since the strong tag now has margin-bottom */66        }67        68        /* Add a bottom margin to each list item for more spacing */69        .ai-response-content li {70            margin-bottom: 1.0rem;71        }72        73        /* Basic table styling for clarity */74        .ai-response-content table {75            width: 100%;76            border-collapse: collapse;77            margin-top: 1rem;78            font-size: 0.9rem;79        }80        81        .ai-response-content th, .ai-response-content td {82            border: 1px solid #d1d5db; /* Lighter border for contrast on dark background */83            padding: 0.75rem;84            text-align: left;85            width: 33%; 86        }87        88        .ai-response-content th {89            /* Darker table header background */90            background-color: #374151; /* Tailwind gray-700 equivalent */91            font-weight: 700;92            color: #f3f4f6;93        }94        95        .ai-response-content td {96            background-color: #1f2937; /* Tailwind gray-800 equivalent */97        }98        .main-title {99            font-size: 1.8rem;100            font-weight: 700;101            color: #f3f4f6; /* Tailwind gray-100 equivalent */102        }103        104        .sub-title {105            font-size: 1.125rem;106            color: #d1d5db; /* Tailwind gray-300 equivalent */107            margin-top: 0.25rem;108        }109        110        /* === Custom Button Style (Main Dropdowns) === */111        .prompt-btn, .dropdown-btn {112            /* --- MODIFIED FONT FAMILY, SIZE, AND WEIGHT --- */113            font-family: 'Roboto Slab', serif; 114            font-size: 0.8125rem; 115            font-weight: 700; 116            /* ----------------------------------------------- */117            118            /* Base styles */119            padding-left: 0.75rem;120            padding-right: 0.75rem;121            padding-top: 0.5rem; 122            padding-bottom: 0.5rem; 123            color: #065f46; /* Text-emerald-800 */124            background-color: #ecfdf5; /* Bg-emerald-50 (light emerald) */125            border-radius: 0.75rem; /* Rounded-xl */126            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.06); /* Shadow-lg */127            128            /* Border */129            border-width: 2px; 130            border-color: #34d399; /* Tailwind emerald-400 for better visibility */131            132            /* Sizing and alignment */133            width: 11rem; /* Fixed width for consistent size (w-44) */134            height: 3rem; /* Fixed height for consistent size (h-12) */135            text-align: center;136            display: flex;137            align-items: center;138            justify-content: center;139            white-space: normal;140                        141            /* Hover and transition effects */142            transition: all 0.2s ease-in-out;143            144            /* Ensure dropdown buttons inherit base style but can be overridden */145            cursor: pointer;146        }147        148        .prompt-btn:hover, .dropdown-btn:hover {149            background-color: #d1fae5; /* Hover:bg-emerald-100 */150            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); /* Hover:shadow-xl */151            transform: translateY(-2px); /* Subtle lift effect */152        }153        154        /* Added active state for a physical "press" effect */155        .prompt-btn:active, .dropdown-btn:active {156            border-color: #10b981; /* Tailwind emerald-600 */157            border-width: 3px; 158            transform: translateY(0); 159            box-shadow: none; 160        }161        /* === Custom Button Style (Sub-Menu Buttons) === */162        .sub-menu-btn {163            /* Define styles for individual, stacked buttons */164            background-color: #303030; /* Charcoal Grey */165            color: #f3f4f6; /* Tailwind gray-100 */166            width: 100%;167            text-align: left;168            padding: 0.5rem 1rem; /* py-2 px-4 */169            font-size: 0.875rem; /* text-sm */170            transition: all 0.15s ease-in-out;171            font-family: 'Georgia', sans-serif;172            cursor: pointer;173            174            /* Key changes for individual button look */175            border: 1px solid #d1d5db; /* Light Grey (Tailwind gray-300) */176            border-radius: 0.5rem; /* rounded-lg */177            margin-bottom: 0.25rem; /* space between buttons */178            box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);179        }180        181        .sub-menu-btn:hover {182            background-color: #4a4a4a; /* Slightly lighter Charcoal hover */183            transform: scale(1.01);184        }185        /* Ensure the last button doesn't have extra margin at the bottom */186        .sub-menu-btn:last-child {187            margin-bottom: 0;188        }189        /* Custom styles for the dynamic textarea */190        #userInput {191            /* Set initial row size and ensure dynamic growth */192            line-height: 1.5; 193            overflow-y: hidden; /* Hide scrollbar unless max height is reached */194            box-sizing: border-box; /* Include padding and border in the element's total width and height */195            resize: none; /* Prevent manual resizing */196        }197    </style>198    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>199</head>200<body class="flex flex-col items-center justify-center min-h-screen p-4 bg-gray-900">201    <div class="bg-gray-800 text-gray-100 rounded-2xl shadow-xl w-full max-w-2xl p-6 md:p-8">202        <div class="flex items-center space-x-4 mb-6">203            <div class="p-3 bg-emerald-100 rounded-full">204                <svg xmlns="http://www.w3.org/2000/svg" fill="#10b981" viewBox="0 0 24 24" stroke-width="1.5" stroke="#10b981" class="w-6 h-6">205                    <path stroke-linecap="round" stroke-linejoin="round" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.225 3.658a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.6l-4.725-2.885a.563.563 0 00-.582 0l-4.725 2.885a.562.562 0 01-.84-.6l1.285-5.385a.562.562 0 00-.182-.557L3.991 10.49a.562.562 0 01.32-.988l5.518-.442a.563.563 0 00.475-.345l2.125-5.111z" />206                </svg>207            </div>208            <div>209                <h1 class="main-title">Bob, Your Consulting Assistant</h1>210                <p class="sub-title">You ask. Bob answers.</p>211            </div>212        </div>213        214        <div class="mb-6">215            <label for="apiKeyInput" class="block text-sm font-medium text-gray-100 mb-1">Enter your Gemini API Key:</label>216            <input type="password" id="apiKeyInput" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-emerald-500 bg-gray-700 text-white" placeholder="Paste your API key here...">217        </div>218        219        <div class="flex justify-between mb-4">220            221            <div class="grid grid-cols-2 gap-4">222                223                <div class="flex flex-col gap-4">224                    <div class="relative">225                        <button id="initialSetupDropdownBtn" class="dropdown-btn flex items-center justify-center">226                            Initial Setup227                            <svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>228                        </button>229                        <div id="initialSetupMenu" class="absolute hidden top-full mt-2 w-56 bg-gray-800 rounded-lg shadow-2xl z-10 border border-emerald-500 p-2">230                            </div>231                    </div>232                    <div class="relative">233                        <button id="solutionDesignDropdownBtn" class="dropdown-btn flex items-center justify-center">234                            Solution Design235                            <svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>236                        </button>237                        <div id="solutionDesignMenu" class="absolute hidden top-full mt-2 w-56 bg-gray-800 rounded-lg shadow-2xl z-10 border border-emerald-500 p-2">238                            </div>239                    </div>240                </div>241                242                <div class="flex flex-col gap-4">243                    <div class="relative">244                        <button id="analysisDropdownBtn" class="dropdown-btn flex items-center justify-center">245                            Analysis246                            <svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>247                        </button>248                        <div id="analysisMenu" class="absolute hidden top-full mt-2 w-56 bg-gray-800 rounded-lg shadow-2xl z-10 border border-emerald-500 p-2">249                            </div>250                    </div>251                    <div class="relative">252                        <button id="executionDropdownBtn" class="dropdown-btn flex items-center justify-center">253                            Execution254                            <svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>255                        </button>256                        <div id="executionMenu" class="absolute hidden top-full mt-2 w-56 bg-gray-800 rounded-lg shadow-2xl z-10 border border-emerald-500 p-2">257                            </div>258                    </div>259                </div>260            </div> 261 262                <!-- Action Buttons Column (Top-Right) -->263            <div class="flex flex-col gap-4 items-end">264                <!-- My Prompts Button with Dropdown -->265                <div class="relative w-48">266                    <button id="myPromptsDropdownBtn" class="w-full px-3 py-1.5 bg-gray-400 text-white rounded-lg hover:bg-gray-500 transition duration-200 inline-flex items-center justify-center font-bold text-xs">267                        My Prompts268                        <svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>269                    </button>270                    <div id="myPromptsMenu" class="absolute hidden top-full mt-2 w-56 bg-gray-800 rounded-lg shadow-2xl z-10 border border-emerald-500 p-2 right-0">271                    </div>272                </div>273 274                <!-- Generate Takeaways Button -->275                <button id="generateTakeawaysBtn" class="w-48 px-3 py-1.5 bg-gray-400 text-white rounded-lg hover:bg-gray-500 transition duration-200 font-bold text-xs">276                    Generate Takeaways277                </button>278 279                <!-- Run Workflow Button with Dropdown -->280                <div class="relative w-48">281                    <button id="workflowBtn" class="w-full px-3 py-1.5 bg-gray-400 text-white rounded-lg hover:bg-gray-500 transition duration-200 font-bold text-xs inline-flex items-center justify-center">282                        Run Workflow283                        <svg class="w-3 h-3 ml-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>284                    </button>285                    <div id="workflowMenu" class="absolute hidden top-full right-0 mt-2 w-64 bg-gray-800 rounded-lg shadow-2xl z-10 border border-green-500 p-2">286                        <button class="workflow-option w-full text-left px-3 py-2 text-sm text-gray-100 hover:bg-gray-700 rounded" data-workflow="market-entry-strategy">287                            Market Entry Strategy288                        </button>289                        <button class="workflow-option w-full text-left px-3 py-2 text-sm text-gray-100 hover:bg-gray-700 rounded" data-workflow="business-health-check">290                            Business Health Check291                        </button>292                        <button class="workflow-option w-full text-left px-3 py-2 text-sm text-gray-100 hover:bg-gray-700 rounded" data-workflow="competitive-analysis">293                            Competitive Analysis294                        </button>295                    </div>296                </div>297 298                <!-- Export Chat Button -->299                <button id="exportBtn" class="w-48 px-3 py-1.5 bg-gray-400 text-white rounded-lg hover:bg-gray-500 transition duration-200 font-bold text-xs">300                    Export Chat301                </button>302            </div>303        </div> 304        305                <!-- Chat Area -->306        <div id="chatArea" class="space-y-4 max-h-96 overflow-y-auto mb-4">307        </div>308 309        310                <!-- Greeting Message and Clear Chat Button -->311        <div class="flex justify-between items-start mb-4">312            <div class="bg-emerald-100 text-emerald-700 rounded-xl p-3 max-w-sm shadow-md">313                Hi there! I'm Bob. How can I assist you today?314            </div>315            <button id="clearChatBtn" class="px-3 py-1.5 bg-gray-400 text-white rounded-lg hover:bg-gray-500 transition duration-200 font-bold text-xs border-2 border-red-500">Clear Chat</button>316        </div>317 318        319        <div class="flex items-center space-x-2">320            <textarea id="userInput" placeholder="Ask a question... (Enter to Send, Shift + Enter for Newline)" rows="1" class="flex-grow px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-emerald-500 bg-gray-700 text-white resize-none overflow-y-hidden"></textarea>321            <button id="sendButton" class="px-6 py-2 bg-emerald-600 text-white font-semibold rounded-lg shadow-md hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-emerald-500 disabled:bg-emerald-300 disabled:cursor-not-allowed" >Send</button>322        </div>323    </div>324    325    <script>326        (function() {327            const apiKeyInput = document.getElementById('apiKeyInput');328            const sendButton = document.getElementById('sendButton');329            const userInput = document.getElementById('userInput');330            const chatArea = document.getElementById('chatArea');331            const clearChatBtn = document.getElementById('clearChatBtn');332            const generateTakeawaysBtn = document.getElementById('generateTakeawaysBtn');333 334            // DROPDOWN ELEMENTS335            const initialSetupDropdownBtn = document.getElementById('initialSetupDropdownBtn');336            const initialSetupMenu = document.getElementById('initialSetupMenu');337            const analysisDropdownBtn = document.getElementById('analysisDropdownBtn');338            const analysisMenu = document.getElementById('analysisMenu');339            const solutionDesignDropdownBtn = document.getElementById('solutionDesignDropdownBtn');340            const solutionDesignMenu = document.getElementById('solutionDesignMenu');341            const executionDropdownBtn = document.getElementById('executionDropdownBtn');342            const executionMenu = document.getElementById('executionMenu');343            // NEW PROMPT ELEMENTS344            const myPromptsDropdownBtn = document.getElementById('myPromptsDropdownBtn'); // NEW345            const myPromptsMenu = document.getElementById('myPromptsMenu'); // NEW346            let MIN_HEIGHT = 0; // Calculated minimum height (1 line)347 348                        // ===== PHASE 1 FEATURE: PERSISTENT MEMORY SYSTEM =====349            350            // User Profile Storage351            const USER_PROFILE_KEY = 'bobUserProfile';352            353            // Initialize or load user profile354            let userProfile = JSON.parse(localStorage.getItem(USER_PROFILE_KEY)) || {355                industry: '',356                consultingAreas: [],357                previousTopics: [],358                conversationSummaries: [],359                preferences: {360                    preferredAnalysisTypes: [],361                    favoritePrompts: []362                },363                lastVisit: null,364                totalInteractions: 0,365                createdAt: new Date().toISOString()366            };367            368            // Save user profile to localStorage369            function saveUserProfile() {370                userProfile.lastVisit = new Date().toISOString();371                localStorage.setItem(USER_PROFILE_KEY, JSON.stringify(userProfile));372            }373            374            // Extract topics from conversation375            function extractTopicsFromConversation() {376                const topics = [];377                chatHistory.forEach(entry => {378                    if (entry.role === 'user') {379                        const text = entry.parts[0].text.toLowerCase();380                        // Simple keyword extraction381                        if (text.includes('market')) topics.push('market analysis');382                        if (text.includes('swot')) topics.push('SWOT analysis');383                        if (text.includes('competitor')) topics.push('competitor analysis');384                        if (text.includes('financial')) topics.push('financial analysis');385                        if (text.includes('strategy')) topics.push('strategy');386                    }387                });388                return [...new Set(topics)]; // Remove duplicates389            }390            391            // Add conversation summary to profile392            function saveConversationSummary() {393                if (chatHistory.length > 1) {394                    const topics = extractTopicsFromConversation();395                    const summary = {396                        date: new Date().toISOString(),397                        topics: topics,398                        messageCount: chatHistory.length - 1,399                        id: Date.now()400                    };401                    402                    userProfile.conversationSummaries.push(summary);403                    userProfile.previousTopics = [404                        ...new Set([...userProfile.previousTopics, ...topics])405                    ].slice(0, 20); // Keep last 20 unique topics406                    407                    userProfile.totalInteractions++;408                    saveUserProfile();409                }410            }411 412                        // ===== PHASE 1 FEATURE: PROACTIVE CHECK-INS =====413            414            // Check if returning user and show personalized welcome415            function checkForProactiveWelcome() {416                const lastVisit = userProfile.lastVisit ? new Date(userProfile.lastVisit) : null;417                const now = new Date();418                419                if (lastVisit) {420                    const hoursSinceLastVisit = (now - lastVisit) / (1000 * 60 * 60);421                    422                    // If more than 24 hours since last visit423                    if (hoursSinceLastVisit > 24 && userProfile.previousTopics.length > 0) {424                        setTimeout(() => {425                            const daysSince = Math.floor(hoursSinceLastVisit / 24);426                            const topicsText = userProfile.previousTopics.slice(0, 3).join(', ');427                            428                            const welcomeBackMessage = `Welcome back! It's been ${daysSince} day${daysSince > 1 ? 's' : ''} since your last visit. 429 430I see we previously discussed: **${topicsText}**. 431 432Would you like to:433• Continue where we left off?434• Get updates on these topics?435• Start a new analysis?436 437How can I assist you today?`;438                            439                            createMessageBubble(welcomeBackMessage, 'model');440                        }, 1500); // Show after 1.5 seconds441                    } else if (hoursSinceLastVisit > 1 && userProfile.totalInteractions > 3) {442                        // Short absence but active user443                        setTimeout(() => {444                            const recentTopics = userProfile.previousTopics.slice(0, 2).join(' and ');445                            const quickWelcome = `Welcome back! Ready to continue with ${recentTopics || 'your consulting questions'}?`;446                            447                            createMessageBubble(quickWelcome, 'model');448                        }, 1000);449                    }450                }451                452                // Update last visit453                userProfile.lastVisit = now.toISOString();454                saveUserProfile();455            }456            457            // Call proactive welcome on page load458            setTimeout(() => {459                checkForProactiveWelcome();460            }, 500); // Wait 500ms after page loads461 462                        463            // ===== PHASE 1 FEATURE: MULTI-STEP TASK TEMPLATES =====464            465            // Define multi-step workflows466            const WORKFLOWS = {467                'market-entry-strategy': {468                    name: 'Complete Market Entry Strategy',469                    steps: [470                        'Industry Trends Snapshot',471                        'Competitor Benchmarking',472                        'SWOT Analysis',473                        'Market Entry Strategy Framework'474                    ],475                    description: 'Full market entry analysis with trends, competitors, SWOT, and strategy'476                },477                'business-health-check': {478                    name: 'Business Health Check',479                    steps: [480                        'SWOT Analysis',481                        'Financial Health Snapshot',482                        'Operational Efficiency Review'483                    ],484                    description: 'Comprehensive business health assessment'485                },486                'competitive-analysis': {487                    name: 'Competitive Analysis Package',488                    steps: [489                        'Competitor Benchmarking',490                        'Market Positioning Map',491                        'Competitive Advantage Analysis'492                    ],493                    description: 'Deep dive into competitive landscape'494                }495            };496                        497            // ===== PHASE 2 FEATURE: TOOL ORCHESTRATION FRAMEWORK =====498            499            // Available tools Bob can use500            const BOB_TOOLS = {501                googleSearch: {502                    enabled: true,503                    name: 'Google Search',504                    description: 'Search the web for current information',505                    icon: '🔍'506                },507                dataAnalysis: {508                    enabled: true,509                    name: 'Data Analysis',510                    description: 'Perform calculations and analyze data',511                    icon: '📊'512                },513                documentExport: {514                    enabled: true,515                    name: 'Document Export',516                    description: 'Export conversation or analysis as text file',517                    icon: '📄'518                },519                chartGeneration: {520                    enabled: true,521                    name: 'Chart Generation',522                    description: 'Create visual charts and graphs',523                    icon: '📈'524                }525            };526            527            // Tool usage tracking528            let toolUsageHistory = [];529            530            // Determine which tools are needed for a query531            function determineRequiredTools(userQuery) {532                const query = userQuery.toLowerCase();533                const tools = [];534                535                // Check for search needs536                if (query.includes('latest') || query.includes('current') || 537                    query.includes('recent') || query.includes('trend')) {538                    tools.push('googleSearch');539                }540                541                // Check for data analysis needs542                if (query.includes('calculate') || query.includes('analyze data') || 543                    query.includes('numbers') || query.includes('statistics')) {544                    tools.push('dataAnalysis');545                }546                547                // Check for export needs548                if (query.includes('export') || query.includes('download') || 549                    query.includes('save as file')) {550                    tools.push('documentExport');551                }552                553                // Check for visualization needs554                if (query.includes('chart') || query.includes('graph') || 555                    query.includes('visualize') || query.includes('plot')) {556                    tools.push('chartGeneration');557                }558                559                return tools;560            }561            562            // Execute document export tool563            function executeDocumentExport() {564                let exportText = 'BOB CONSULTING SESSION EXPORT\n';565                exportText += '='.repeat(50) + '\n';566                exportText += `Date: ${new Date().toLocaleString()}\n`;567                exportText += `Total Messages: ${chatHistory.length - 1}\n`;568                exportText += '='.repeat(50) + '\n\n';569                570                chatHistory.forEach((entry, index) => {571                    if (index > 0) {572                        const role = entry.role === 'user' ? 'YOU' : 'BOB';573                        const text = entry.parts[0].text;574                        exportText += `[${role}]\n${text}\n\n`;575                        exportText += '-'.repeat(50) + '\n\n';576                    }577                });578                579                const blob = new Blob([exportText], { type: 'text/plain' });580                const url = URL.createObjectURL(blob);581                const a = document.createElement('a');582                a.href = url;583                a.download = `bob-session-${Date.now()}.txt`;584                document.body.appendChild(a);585                a.click();586                document.body.removeChild(a);587                URL.revokeObjectURL(url);588                589                // Track tool usage590                toolUsageHistory.push({591                    tool: 'documentExport',592                    timestamp: new Date().toISOString()593                });594                595                return 'Document exported successfully!';596            }597            598            // Execute data analysis tool (simple implementation)599            function executeDataAnalysis(data) {600                // This is a simplified version - can be expanded601                try {602                    const numbers = data.match(/\d+(\.\d+)?/g)?.map(Number) || [];603                    604                    if (numbers.length === 0) {605                        return 'No numerical data found to analyse.';606                    }607                    608                    const sum = numbers.reduce((a, b) => a + b, 0);609                    const avg = sum / numbers.length;610                    const max = Math.max(...numbers);611                    const min = Math.min(...numbers);612                    613                    toolUsageHistory.push({614                        tool: 'dataAnalysis',615                        timestamp: new Date().toISOString()616                    });617                    618                    return `Data Analysis Results:619- Count: ${numbers.length} values620- Sum: ${sum.toFixed(2)}621- Average: ${avg.toFixed(2)}622- Maximum: ${max}623- Minimum: ${min}`;624                } catch (error) {625                    return 'Error analyzing data.';626                }627            }628 629            // Execute multi-step workflow630            async function executeWorkflow(workflowKey, context = '') {631                const workflow = WORKFLOWS[workflowKey];632                if (!workflow) {633                    alert('Workflow not found');634                    return;635                }636                637                // Show workflow initiation message638                const initiationMessage = `Starting **${workflow.name}** workflow...639 640This will execute ${workflow.steps.length} analysis steps:641${workflow.steps.map((step, i) => `${i + 1}. ${step}`).join('\n')}642 643${context ? `\nContext: ${context}` : ''}`;644                645                createMessageBubble(initiationMessage, 'model');646                647                // Execute each step648                for (let i = 0; i < workflow.steps.length; i++) {649                    const step = workflow.steps[i];650                    651                    // Add user message for this step652                    const stepMessage = `[Workflow Step ${i + 1}/${workflow.steps.length}] ${step}${context ? ': ' + context : ''}`;653                    createMessageBubble(stepMessage, 'user');654                    655                    chatHistory.push({656                        role: "user",657                        parts: [{ text: stepMessage }]658                    });659                    660                    // Execute the prompt using sendMessage logic661                    await executePromptStep(PROMPT_MAP[step], context);662                    663                    // Small delay between steps664                    await new Promise(resolve => setTimeout(resolve, 1000));665                }666                667                // Completion message668                const completionMessage = `✅ **${workflow.name}** complete! 669 670I've generated ${workflow.steps.length} comprehensive analyses. Review the insights above and let me know if you'd like to:671• Deep dive into any specific area672• Generate takeaways673• Start another workflow`;674                675                createMessageBubble(completionMessage, 'model');676                677                // Save this workflow execution to user profile678                userProfile.preferences.preferredAnalysisTypes.push(workflowKey);679                saveUserProfile();680            }681            682            // Execute individual prompt step (reuses existing API call logic)683            async function executePromptStep(promptTemplate, userContext) {684                const apiKey = apiKeyInput.value.trim();685                686                // Show "Thinking..." indicator687                const loadingBubble = document.createElement('div');688                loadingBubble.classList.add('flex', 'justify-start');689                loadingBubble.innerHTML = `690                    <div class="bg-gray-700 text-gray-300 rounded-xl rounded-bl-none p-3 max-w-sm shadow-md">691                        <div class="flex items-center">692                            <svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">693                                <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>694                                <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>695                            </svg>696                            Thinking...697                        </div>698                    </div>699                `;700                chatArea.appendChild(loadingBubble);701                chatArea.scrollTop = chatArea.scrollHeight;702                703                try {704                    const finalPrompt = promptTemplate.replace(/\[input[^\]]*\]/gi, userContext || '[No specific context provided]');705                    706                    chatHistory.push({707                        role: "user",708                        parts: [{ text: finalPrompt }]709                    });710                    711                    const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=${apiKey}`;712                    713                    const payload = {714                        systemInstruction: {715                            parts: [{ text: `You are a professional business consultant named Bob. Your role is to provide clear, actionable, and well-structured responses to business-related queries. Use Markdown formatting.` }]716                        },717                        contents: chatHistory,718                        tools: [{ "google_search": {} }],719                    };720                    721                    const response = await fetch(apiUrl, {722                        method: "POST",723                        headers: { "Content-Type": "application/json" },724                        body: JSON.stringify(payload)725                    });726                    727                    const result = await response.json();728                    const aiText = result?.candidates?.[0]?.content?.parts?.[0]?.text || "Sorry, I couldn't process that request.";729                    730                    chatArea.removeChild(loadingBubble);731                    732                    chatHistory.push({733                        role: "model",734                        parts: [{ text: aiText }]735                    });736                    737                    createMessageBubble(aiText, 'model');738                    739                } catch (error) {740                    if (chatArea.contains(loadingBubble)) {741                        chatArea.removeChild(loadingBubble);742                    }743                    console.error('Error in workflow step:', error);744                    createMessageBubble('Error processing this step. Moving to next...', 'model');745                }746            }747 748                        749            // ===== PHASE 2 FEATURE: GOAL-BASED REASONING =====750            751            // Decompose complex goals into sub-goals752            function decomposeGoal(goalStatement) {753                const goal = goalStatement.toLowerCase();754                const subGoals = [];755    756                // Pattern matching for common business goals757                if (goal.includes('launch') || goal.includes('start') || goal.includes('new business') || goal.includes('open')) {758                    subGoals.push(759                        { task: 'Industry Trends Snapshot', priority: 'high' },760                        { task: 'Market Analysis', priority: 'high' },761                        { task: 'Competitor Benchmarking', priority: 'high' },762                        { task: 'Business Plan Outline', priority: 'medium' },763                        { task: 'Go-to-market Strategy', priority: 'medium' }764                    );765                } else if (goal.includes('expand') || goal.includes('growth') || goal.includes('scale') || goal.includes('grow')) {766                    subGoals.push(767                        { task: 'Market Analysis', priority: 'high' },768                        { task: 'SWOT Analysis', priority: 'high' },769                        { task: 'Ansoff Matrix', priority: 'high' },770                        { task: 'Market Entry Strategy', priority: 'medium' },771                        { task: 'Implementation Plan Outline', priority: 'medium' }772                    );773                } else if (goal.includes('improve') || goal.includes('optimize') || goal.includes('enhance')) {774                    subGoals.push(775                        { task: 'SWOT Analysis', priority: 'high' },776                        { task: '5 Forces Analysis', priority: 'high' },777                        { task: 'Risk Analysis', priority: 'medium' },778                        { task: 'KPI Dashboard Mockup', priority: 'medium' },779                        { task: 'Implementation Plan Outline', priority: 'medium' }780                    );781                } else {782                    // Generic goal breakdown783                    subGoals.push(784                        { task: 'SWOT Analysis', priority: 'high' },785                        { task: 'Market Analysis', priority: 'high' },786                        { task: 'Risk Analysis', priority: 'medium' },787                        { task: 'Implementation Plan Outline', priority: 'medium' }788                    );789                }790    791                return subGoals;792            }793 794            795            // Create execution plan from sub-goals796            function createExecutionPlan(subGoals) {797                const plan = {798                    highPriority: subGoals.filter(g => g.priority === 'high'),799                    mediumPriority: subGoals.filter(g => g.priority === 'medium'),800                    steps: subGoals.map((g, i) => ({801                        step: i + 1,802                        task: g.task,803                        priority: g.priority,804                        status: 'pending'805                    }))806                };807                808                return plan;809            }810 811            812// Track if we're waiting for execution plan response813let awaitingPlanResponse = false;814 815// Execute goal plan automatically816async function executeGoalPlanAutomatically(goal, plan) {817    createMessageBubble(`🚀 Starting automatic execution of your goal plan...`, 'model');818    819    for (let i = 0; i < plan.steps.length; i++) {820        const step = plan.steps[i];821        822        // Show which step is being executed823        createMessageBubble(`\n**Step ${i + 1}/${plan.steps.length}: ${step.task}**\n*Priority: ${step.priority}*`, 'model');824        825        // Small delay between steps826        await new Promise(resolve => setTimeout(resolve, 1500));827        828        // Find matching prompt in PROMPT_MAP829        const promptKey = step.task;830        if (PROMPT_MAP[promptKey]) {831            await executePromptStep(PROMPT_MAP[promptKey], goal);832        } else {833            createMessageBubble(`⚠️ Prompt template not found for "${step.task}". Skipping...`, 'model');834        }835        836        // Delay before next step837        await new Promise(resolve => setTimeout(resolve, 2000));838    }839    840    createMessageBubble(`\n✅ **Goal Plan Complete!**\n\nI've executed all ${plan.steps.length} steps for your goal: "${goal}"\n\nReview the analyses above and let me know if you'd like to:\n• Deep dive into any specific area\n• Generate takeaways\n• Start a new goal`, 'model');841    842    // Reset flag843    awaitingPlanResponse = false;844}845            846            // Process and execute a complex goal847            async function processGoal(userGoal) {848                // Show goal analysis message849                const analysisMessage = `🎯 **Goal Analysis**850 851I'm breaking down your goal: "${userGoal}"852 853Let me identify the key steps needed...`;854                855                createMessageBubble(analysisMessage, 'model');856                857                // Small delay for effect858                await new Promise(resolve => setTimeout(resolve, 1000));859                860                // Decompose the goal861                const subGoals = decomposeGoal(userGoal);862                const plan = createExecutionPlan(subGoals);863                864                // Show the execution plan865                const planMessage = `📋 **Execution Plan**866 867I've identified ${plan.steps.length} key steps to achieve your goal:868 869**High Priority:**870${plan.highPriority.map((g, i) => `${i + 1}. ${g.task}`).join('\n')}871 872**Medium Priority:**873${plan.mediumPriority.map((g, i) => `${i + 1}. ${g.task}`).join('\n')}874 875Would you like me to:8761. Execute this plan automatically (runs all steps)8772. Walk through it step-by-step with you8783. Modify the plan first879 880Reply with 1, 2, or 3.`;881                882                createMessageBubble(planMessage, 'model');883                884                // Store the plan for potential execution885                window.currentGoalPlan = plan;886                window.currentGoal = userGoal;887 888                // Set flag to intercept next user message889                awaitingPlanResponse = true;890 891                return plan;892 893            }894 895                        896            // ===== PHASE 2 FEATURE: CONTEXT-AWARE SUGGESTIONS =====897            898            // Analyze conversation patterns899            function identifyConversationPatterns(history) {900                const patterns = [];901                const recentMessages = history.slice(-6); // Last 6 messages902                903                // Pattern: Multiple questions about same topic904                const topics = {};905                recentMessages.forEach(msg => {906                    if (msg.role === 'user') {907                        const text = msg.parts[0].text.toLowerCase();908                        if (text.includes('market')) topics.market = (topics.market || 0) + 1;909                        if (text.includes('financial')) topics.financial = (topics.financial || 0) + 1;910                        if (text.includes('competitor')) topics.competitor = (topics.competitor || 0) + 1;911                        if (text.includes('strategy')) topics.strategy = (topics.strategy || 0) + 1;912                    }913                });914                915                Object.keys(topics).forEach(topic => {916                    if (topics[topic] >= 2) {917                        patterns.push(`deep-dive-${topic}`);918                    }919                });920                921                // Pattern: Incomplete analysis (SWOT without implementation)922                const hasSWOT = history.some(msg => 923                    msg.parts[0].text.toLowerCase().includes('swot')924                );925                const hasImplementation = history.some(msg => 926                    msg.parts[0].text.toLowerCase().includes('implementation') ||927                    msg.parts[0].text.toLowerCase().includes('action plan')928                );929                930                if (hasSWOT && !hasImplementation) {931                    patterns.push('swot-without-implementation');932                }933                934                // Pattern: Analysis without next steps935                const hasAnalysis = history.some(msg =>936                    msg.parts[0].text.toLowerCase().includes('analysis') ||937                    msg.parts[0].text.toLowerCase().includes('trends')938                );939                const hasNextSteps = history.some(msg =>940                    msg.parts[0].text.toLowerCase().includes('next step') ||941                    msg.parts[0].text.toLowerCase().includes('action')942                );943                944                if (hasAnalysis && !hasNextSteps && history.length > 4) {945                    patterns.push('analysis-without-action');946                }947                948                return patterns;949            }950            951            // Generate proactive suggestions based on patterns952            function generateProactiveSuggestions(patterns) {953                const suggestions = [];954                955                patterns.forEach(pattern => {956                    if (pattern === 'swot-without-implementation') {957                        suggestions.push({958                            message: "I notice we completed a SWOT analysis. Would you like me to create an implementation roadmap based on those insights?",959                            action: 'create-implementation-plan'960                        });961                    }962                    963                    if (pattern === 'analysis-without-action') {964                        suggestions.push({965                            message: "We've done some great analysis! Would you like me to convert these insights into concrete action items?",966                            action: 'generate-action-items'967                        });968                    }969                    970                    if (pattern.startsWith('deep-dive-')) {971                        const topic = pattern.replace('deep-dive-', '');972                        suggestions.push({973                            message: `You seem very interested in ${topic} analysis. Would you like me to run a comprehensive ${topic} workflow?`,974                            action: `workflow-${topic}`975                        });976                    }977                });978                979                return suggestions;980            }981            982            // Check and show proactive suggestions periodically983            let suggestionCheckInterval = null;984            985            function startContextAwareSuggestions() {986                // Check every 30 seconds if there are relevant suggestions987                suggestionCheckInterval = setInterval(() => {988                    if (chatHistory.length > 4) {989                        const patterns = identifyConversationPatterns(chatHistory);990                        991                        if (patterns.length > 0) {992                            const suggestions = generateProactiveSuggestions(patterns);993                            994                            if (suggestions.length > 0 && Math.random() > 0.7) { // 30% chance to show995                                const suggestion = suggestions[0]; // Show first suggestion996                                997                                const proactiveMessage = `💡 **Proactive Suggestion**998 999${suggestion.message}`;1000                                1001                                createMessageBubble(proactiveMessage, 'model');1002                                1003                                // Stop checking for a while after showing suggestion1004                                clearInterval(suggestionCheckInterval);1005                                setTimeout(() => {1006                                    startContextAwareSuggestions();1007                                }, 120000); // Resume after 2 minutes1008                            }1009                        }1010                    }1011                }, 30000); // Check every 30 seconds1012            }1013            1014            // Start context-aware suggestions on page load1015            setTimeout(() => {1016                startContextAwareSuggestions();1017                        }, 60000); // Start checking after 1 minute of use1018            1019            // ===== PHASE 3 FEATURE: AUTONOMOUS RESEARCH AGENT =====1020            1021            let activeResearchSession = null;1022            1023            const RESEARCH_FRAMEWORK = {1024                phases: ['Discovery', 'Deep Dive', 'Synthesis', 'Validation'],1025                maxQueries: 5,1026                timeout: 1800001027            };1028            1029            async function startAutonomousResearch(topic, depth = 'standard') {1030                const sessionId = Date.now();1031                activeResearchSession = {1032                    id: sessionId,1033                    topic: topic,1034                    depth: depth,1035                    findings: [],1036                    phase: 0,1037                    startTime: new Date()1038                };1039                1040                createMessageBubble(`🔬 **Autonomous Research Initiated**1041 1042Topic: "${topic}"1043Depth: ${depth}1044 1045I'll conduct comprehensive research across multiple phases:10461. **Discovery** - Identifying key aspects10472. **Deep Dive** - Gathering detailed information10483. **Synthesis** - Connecting insights10494. **Validation** - Cross-referencing findings1050 1051Starting research...`, 'assistant');1052                1053                await executeResearchPhase('Discovery', topic);1054                await new Promise(resolve => setTimeout(resolve, 2000));1055                1056                await executeResearchPhase('Deep Dive', topic);1057                await new Promise(resolve => setTimeout(resolve, 2000));1058                1059                await executeResearchPhase('Synthesis', topic);1060                await new Promise(resolve => setTimeout(resolve, 2000));1061                1062                await executeResearchPhase('Validation', topic);1063                1064                await generateResearchReport(topic);1065                1066                activeResearchSession = null;1067            }1068            1069            async function executeResearchPhase(phase, topic) {1070                createMessageBubble(`📊 **Phase: ${phase}**1071 1072Analyzing ${topic}...`, 'assistant');1073                1074                let phasePrompt = '';1075                1076                switch(phase) {1077                    case 'Discovery':1078                        phasePrompt = `Analyze "${topic}" and provide EXACTLY 5 key aspects in this format:1079 1080                1. [Aspect Name]: [One sentence description]1081                2. [Aspect Name]: [One sentence description]1082                3. [Aspect Name]: [One sentence description]1083                4. [Aspect Name]: [One sentence description]1084                5. [Aspect Name]: [One sentence description]1085 1086                Keep each point to ONE sentence maximum. Be concise and specific.`;1087                        break;1088        1089                    case 'Deep Dive':1090                        phasePrompt = `Analyze "${topic}" in this EXACT format:1091 1092                **Current Trends:**1093                • [Trend 1]1094                • [Trend 2]1095                • [Trend 3]1096 1097                **Key Players:**1098                • [Player 1 and their role]1099                • [Player 2 and their role]1100 1101                **Main Challenges:**1102                • [Challenge 1]1103                • [Challenge 2]1104 1105                **Key Opportunities:**1106                • [Opportunity 1]1107                • [Opportunity 2]1108 1109                Use bullet points. Keep each point to 1-2 sentences maximum.`;1110                        break;1111        1112                    case 'Synthesis':1113                        phasePrompt = `Synthesize insights about "${topic}" in this EXACT format:1114 1115                **Key Patterns Identified:**1116                • [Pattern 1]1117                • [Pattern 2]1118 1119                **Strategic Connections:**1120                 • [Connection 1]1121                 • [Connection 2]1122 1123                **Business Implications:**1124                • [Implication 1]1125                • [Implication 2]1126 1127                Keep each point concise (1-2 sentences).`;1128                        break;1129        1130                    case 'Validation':1131                        phasePrompt = `Validate findings about "${topic}" in this EXACT format:1132 1133                **Validated Key Findings:**1134                • [Finding 1]1135                • [Finding 2]1136                • [Finding 3]1137 1138                **Areas Requiring Further Investigation:**1139                • [Area 1]1140                • [Area 2]1141 1142                **Confidence Level:** [High/Medium/Low]1143 1144                Keep each point to 1-2 sentences.`;1145                        break;1146                }1147 1148                1149                try {1150                    const apiKey = apiKeyInput.value.trim();1151                    const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${apiKey}`;1152                    1153                    const payload = {1154                        systemInstruction: {1155                            parts: [{ text: `You are Bob, an autonomous research consultant conducting independent research. Provide thorough, well-researched insights.` }]1156                        },1157                        contents: [{1158                            role: "user",1159                            parts: [{ text: phasePrompt }]1160                        }],1161                        tools: [{ "google_search": {} }]1162                    };1163                    1164                    const response = await fetch(apiUrl, {1165                        method: "POST",1166                        headers: { "Content-Type": "application/json" },1167                        body: JSON.stringify(payload)1168                    });1169                    1170                    const result = await response.json();1171                    const findings = result?.candidates?.[0]?.content?.parts?.[0]?.text || "Research phase incomplete.";1172                    1173                    activeResearchSession.findings.push({1174                        phase: phase,1175                        content: findings1176                    });1177                    1178                    createMessageBubble(`✅ ${phase} complete`, 'assistant');1179                    1180                } catch (error) {1181                    console.error(`Research phase ${phase} error:`, error);1182                    createMessageBubble(`⚠️ ${phase} encountered issues, continuing...`, 'assistant');1183                }1184            }1185            1186            async function generateResearchReport(topic) {1187                const findings = activeResearchSession.findings1188                    .map(f => `## ${f.phase} Phase\n\n${f.content}`)1189                    .join('\n\n---\n\n');1190    1191                createMessageBubble(`# 📑 Comprehensive Research Report: ${topic}1192 1193            ${findings}1194 1195            ---1196 1197            ## 📊 Research Summary1198 1199            - **Total Phases Completed:** ${activeResearchSession.findings.length}1200            - **Research Duration:** ${Math.round((new Date() - activeResearchSession.startTime) / 1000)} seconds

Showing the first 1,200 of 2726 lines. Download the file for the rest.