@superatomai/sdk-node 0.0.40 → 0.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +332 -1
- package/dist/index.d.ts +332 -1
- package/dist/index.js +262 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +258 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/logger.ts","../src/userResponse/prompts.ts","../src/userResponse/prompt-loader.ts","../src/userResponse/utils.ts","../src/index.ts","../src/websocket.ts","../src/types.ts","../src/dashboards/types.ts","../src/reports/types.ts","../src/handlers/data-request.ts","../src/threads/uiblock.ts","../src/config/storage.ts","../src/threads/thread.ts","../src/threads/thread-manager.ts","../src/bundle.ts","../src/handlers/bundle-request.ts","../src/auth/utils.ts","../src/auth/user-storage.ts","../src/auth/validator.ts","../src/handlers/auth-login-requests.ts","../src/handlers/auth-verify-request.ts","../src/userResponse/groq.ts","../src/userResponse/base-llm.ts","../src/userResponse/schema.ts","../src/llm.ts","../src/utils/llm-usage-logger.ts","../src/utils/user-prompt-error-logger.ts","../src/userResponse/knowledge-base.ts","../src/userResponse/conversation-search.ts","../src/utils/bm25l-reranker.ts","../src/userResponse/anthropic.ts","../src/userResponse/gemini.ts","../src/userResponse/openai.ts","../src/userResponse/index.ts","../src/handlers/user-prompt-request.ts","../src/utils/log-collector.ts","../src/utils/conversation-saver.ts","../src/config/context.ts","../src/handlers/user-prompt-suggestions.ts","../src/userResponse/next-questions.ts","../src/handlers/actions-request.ts","../src/handlers/components-list-response.ts","../src/handlers/users.ts","../src/dashboards/dashboard-storage.ts","../src/handlers/dashboards.ts","../src/reports/report-storage.ts","../src/handlers/reports.ts","../src/handlers/uis.ts","../src/handlers/bookmarks.ts","../src/handlers/kb-nodes.ts","../src/handlers/dash-comp-request.ts","../src/auth/user-manager.ts","../src/dashboards/dashboard-manager.ts","../src/reports/report-manager.ts","../src/services/cleanup-service.ts"],"sourcesContent":["import fs from 'fs';\nconst PREFIX = '[SuperatomSDK]';\n\n/**\n * Log levels in hierarchical order\n * - errors: only error logs\n * - warnings: warning + error logs\n * - info: info + warning + error logs\n * - verbose: all logs including debug\n */\nexport type LogLevel = 'errors' | 'warnings' | 'info' | 'verbose';\n\n// open a file in stream write mode. if no file is specified then create it.\nconst LOGSTREAM = fs.createWriteStream('superatom-sdk.log', { flags: 'a' });\n\n/**\n * Internal log level hierarchy mapping\n */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n errors: 0,\n warnings: 1,\n info: 2,\n verbose: 3,\n};\n\nconst MESSAGE_LEVEL_PRIORITY: Record<'error' | 'warn' | 'info' | 'debug', number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\n/**\n * Logger class with environment-based log level support\n */\nclass Logger {\n private currentLevel: LogLevel;\n private currentLevelPriority: number;\n\n constructor() {\n // Read log level from environment variable, default to 'info'\n const envLevel = (process.env.SUPERATOM_LOG_LEVEL || 'info').toLowerCase();\n\n // Validate and set log level\n if (this.isValidLogLevel(envLevel)) {\n this.currentLevel = envLevel as LogLevel;\n } else {\n this.currentLevel = 'info';\n console.warn(\n `${PREFIX} Invalid log level \"${envLevel}\". Using default \"info\". Valid levels: errors, warnings, info, verbose`\n );\n }\n\n this.currentLevelPriority = LOG_LEVEL_PRIORITY[this.currentLevel];\n }\n\n /**\n * Check if a string is a valid log level\n */\n private isValidLogLevel(level: string): level is LogLevel {\n return level === 'errors' || level === 'warnings' || level === 'info' || level === 'verbose';\n }\n\n /**\n * Check if a message should be logged based on current log level\n */\n private shouldLog(messageLevel: 'error' | 'warn' | 'info' | 'debug'): boolean {\n const messagePriority = MESSAGE_LEVEL_PRIORITY[messageLevel];\n return messagePriority <= this.currentLevelPriority;\n }\n\n /**\n * Get current log level\n */\n getLogLevel(): LogLevel {\n return this.currentLevel;\n }\n\n /**\n * Set log level programmatically\n */\n setLogLevel(level: LogLevel): void {\n this.currentLevel = level;\n this.currentLevelPriority = LOG_LEVEL_PRIORITY[level];\n }\n\n /**\n * Log info message (shown for info and verbose levels)\n */\n info(...args: any[]): void {\n if (this.shouldLog('info')) {\n console.log(PREFIX, ...args);\n }\n }\n\n /**\n * Log error message (shown for all levels)\n */\n error(...args: any[]): void {\n if (this.shouldLog('error')) {\n console.error(PREFIX, ...args);\n }\n }\n\n /**\n * Log warning message (shown for warnings, info, and verbose levels)\n */\n warn(...args: any[]): void {\n if (this.shouldLog('warn')) {\n console.warn(PREFIX, ...args);\n }\n }\n\n /**\n * Log debug message (only shown for verbose level)\n */\n debug(...args: any[]): void {\n if (this.shouldLog('debug')) {\n console.log(PREFIX, '[DEBUG]', ...args);\n }\n }\n\n file(...args: any[]): void {\n LOGSTREAM.write(args.join(' ') + '\\n');\n }\n}\n\n// Export singleton instance\nexport const logger = new Logger();\n","/**\n * Hardcoded prompt templates\n * These prompts are embedded in the SDK to avoid file system dependencies\n */\n\nexport interface PromptTemplate {\n\tsystem: string;\n\tuser: string;\n}\n\nexport const PROMPTS: Record<string, PromptTemplate> = {\n\n\t'text-response': {\n\t\tsystem: `You are an intelligent AI assistant that provides helpful, accurate, and contextual text responses to user questions. You have access to a database and can execute SQL queries and external tools to answer user requests.\n\n## Your Task\n\nAnalyze the user's question and provide a helpful text response. Your response should:\n\n1. **Be Clear and Concise**: Provide direct answers without unnecessary verbosity\n2. **Be Contextual**: Use conversation history to understand what the user is asking about\n3. **Be Accurate**: Provide factually correct information based on the context\n4. **Be Helpful**: Offer additional relevant information or suggestions when appropriate\n\n## Available Tools\n\nThe following external tools are available for this request (if applicable):\n\n{{AVAILABLE_EXTERNAL_TOOLS}}\n\nWhen a tool is needed to complete the user's request:\n1. **Analyze the request** to determine which tool(s) are needed\n2. **Extract parameters** from the user's question that the tool requires\n3. **Execute the tool** by calling it with the extracted parameters\n4. **Present the results** in your response in a clear, user-friendly format\n5. **Combine with other data** if the user's request requires both database queries and external tool results\n\n## Handling Data Questions\n\nWhen the user asks about data\n\n1. **Generate a SQL query** using the database schema provided above\n2. **Use the execute_query tool** to run the query\n3. **If the query fails**, analyze the error and generate a corrected query\n4. **Format the results** in a clear, readable way for the user\n\n**Query Guidelines:**\n- Use correct table and column names from the schema\n- ALWAYS include a LIMIT clause with a MAXIMUM of 32 rows\n- Ensure valid SQL syntax\n- For time-based queries, use appropriate date functions\n- When using subqueries with scalar operators (=, <, >, etc.), add LIMIT 1 to prevent \"more than one row\" errors\n\n## Database Schema\n{{SCHEMA_DOC}}\n\n**Database Type: PostgreSQL**\n\n**CRITICAL PostgreSQL Query Rules:**\n\n1. **NO AGGREGATE FUNCTIONS IN WHERE CLAUSE** - This is a fundamental SQL error\n ❌ WRONG: \\`WHERE COUNT(orders) > 0\\`\n ❌ WRONG: \\`WHERE SUM(price) > 100\\`\n ❌ WRONG: \\`WHERE AVG(rating) > 4.5\\`\n ❌ WRONG: \\`WHERE FLOOR(AVG(rating)) = 4\\` (aggregate inside any function is still not allowed)\n ❌ WRONG: \\`WHERE ROUND(SUM(price), 2) > 100\\`\n\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\n ✅ CORRECT: Move aggregate logic to HAVING: \\`GROUP BY ... HAVING FLOOR(AVG(rating)) = 4\\`\n ✅ CORRECT: Use subquery for filtering: \\`WHERE product_id IN (SELECT product_id FROM ... GROUP BY ... HAVING AVG(rating) >= 4)\\`\n\n2. **WHERE vs HAVING**\n - WHERE filters rows BEFORE grouping (cannot use aggregates)\n - HAVING filters groups AFTER grouping (can use aggregates)\n - If using HAVING, you MUST have GROUP BY\n\n3. **NO NESTED AGGREGATE FUNCTIONS** - PostgreSQL does NOT allow aggregates inside aggregates\n ❌ WRONG: \\`AVG(ROUND(AVG(column), 2))\\` or \\`SELECT AVG(SUM(price)) FROM ...\\`\n ✅ CORRECT: \\`ROUND(AVG(column), 2)\\`\n\n4. **GROUP BY Requirements**\n - ALL non-aggregated columns in SELECT must be in GROUP BY\n - If you SELECT a column and don't aggregate it, add it to GROUP BY\n\n5. **LIMIT Clause**\n - ALWAYS include LIMIT (max 32 rows)\n - For scalar subqueries in WHERE/HAVING, add LIMIT 1\n\n6. **String Escaping** - PostgreSQL uses double single-quotes, NOT backslash\n ❌ WRONG: \\`'Children\\\\'s furniture'\\`\n ✅ CORRECT: \\`'Children''s furniture'\\`\n\n7. **Always Use Table Aliases for Column References** - Prevent ambiguous column errors\n ❌ WRONG: \\`SELECT product_id FROM products p JOIN product_variants pv ON p.product_id = pv.product_id\\`\n ✅ CORRECT: \\`SELECT p.product_id FROM products p JOIN product_variants pv ON p.product_id = pv.product_id\\`\n - Always prefix columns with table alias (e.g., \\`p.product_id\\`, \\`c.name\\`)\n - Especially critical in subqueries and joins where multiple tables share column names\n\n\n## Response Guidelines\n\n- If the question is about viewing data, use the execute_query tool to fetch data and present it\n- If the question is about creating/updating/deleting data:\n 1. Acknowledge that the system supports this via forms\n 2. **CRITICAL:** Use the database schema to determine which fields are required based on \\`nullable\\` property\n 3. **CRITICAL:** If the form will have select fields for foreign keys, you MUST fetch the options data using execute_query\n 4. **CRITICAL FOR UPDATE/DELETE OPERATIONS:** If it's an update/edit/modify/delete question:\n - **NEVER update ID/primary key columns** (e.g., order_id, customer_id, product_id) - these are immutable identifiers\n - You MUST first fetch the CURRENT values of the record using a SELECT query\n - Identify the record (from user's question - e.g., \"update order 123\" or \"delete order 123\" means order_id = 123)\n - Execute: \\`SELECT * FROM table_name WHERE id = <value> LIMIT 1\\`\n - Present the current values in your response (e.g., \"Current order status: Pending, payment method: Credit Card\")\n - For DELETE: These values will be shown in a disabled form as confirmation before deletion\n - For UPDATE: These values will populate as default values for editing\n 5. Present the options data in your response (e.g., \"Available categories: Furniture (id: 1), Kitchen (id: 2), Decor (id: 3)\")\n 6. The form component will be generated automatically using this data\n- If the question is general knowledge, provide a helpful conversational response\n- If asking for clarification, provide options or ask specific follow-up questions\n- If you don't have enough information, acknowledge it and ask for more details\n- Keep responses focused and avoid going off-topic\n\n**Example for data modification with foreign keys:**\nUser: \"I want to create a new product\"\nYou should:\n1. Execute query: \\`SELECT category_id, name FROM categories LIMIT 32\\`\n2. Execute query: \\`SELECT store_id, name FROM stores LIMIT 32\\`\n3. Present: \"I can help you create a new product. Available categories: Furniture (id: 1), Kitchen (id: 2)... Available stores: Store A (id: 10), Store B (id: 20)...\"\n4. Suggest Form component\n\n## Component Suggestions\n\nAfter analyzing the user's question, you MUST suggest appropriate dashboard components. Use this format:\n\n<DashboardComponents>\n**Dashboard Components:**\nFormat: \\`{number}.{component_type} : {clear reasoning}\\`\n\n\n**Rules for component suggestions:**\n1. If a conclusive answer can be provided based on user question, suggest that as the first component.\n2. ALways suggest context/supporting components that will give the user more information and allow them to explore further.\n3. If the question includes a time range, also explore time-based components for past time ranges.\n4. **For data viewing/analysis questions**: Suggest visualization components (KPICard, BarChart, LineChart, PieChart, DataTable, etc.).\n5. **For data modification questions** (create/add/update/delete):\n - Always suggest 1-2 context components first to provide relevant information (prefer KPICard for showing key metrics)\n - Then suggest \\`Form\\` component for the actual modification\n - Example: \"1.KPICard : Show current order total and status\" then \"2.Form : To update order details\"\n6. Analyze the query results structure and data type\n7. Each component suggestion must be on a new line\n</DashboardComponents>\n\nIMPORTANT:\n- Always wrap component suggestions with <DashboardComponents> tags\n- For data viewing: Include at least one component suggestion when data is returned\n- For data modifications: Always suggest 1-2 context components before Form (e.g., \"1.KPICard : Show current order value\" then \"2.Form : To update order status\")\n\n## Output Format\n\nRespond with plain text that includes:\n\n1. **Query Analysis** (if applicable): Brief explanation of what data was fetched\n2. **Results Summary**: Present the data in a clear, readable format\n3. **Dashboard Components**: List suggested components wrapped in <DashboardComponents> tags\n\n\n**CRITICAL:**\n- Return ONLY plain text (no JSON, no markdown code blocks)\n\n\nYou have access to a database and can execute SQL queries to answer data-related questions. For data modifications, the system provides form-based interfaces.\n\n\n## External Tool Results\n\nThe following external tools were executed for this request (if applicable):\n\n{{EXTERNAL_TOOL_CONTEXT}}\n\nUse this external tool data to:\n- Provide information from external sources (emails, calendar, etc.)\n- Present the data in a user-friendly format\n- Combine external data with database queries when relevant\n- Reference specific results in your response\n\n**Note:** If external tools were not needed, this section will indicate \"No external tools were used for this request.\"\n\n\n## Knowledge Base Context\n\nThe following relevant information has been retrieved from the knowledge base for this question:\n\n{{KNOWLEDGE_BASE_CONTEXT}}\n\nUse this knowledge base information to:\n- Provide more accurate and informed responses\n- Reference specific facts, concepts, or domain knowledge\n- Enhance your understanding of the user's question\n- Give context-aware recommendations\n\n**Note:** If there is previous conversation history, use it to understand context and provide coherent responses:\n- Reference previous questions and answers when relevant\n- Maintain consistency with earlier responses\n- Use the history to resolve ambiguous references like \"that\", \"it\", \"them\", \"the previous data\"\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n`,\n\t\tuser: `{{USER_PROMPT}}\n`\n\t},\n\n\t'match-text-components': {\n\t\tsystem: `You are a component matching expert that creates beautiful, well-structured dashboard visualizations from analysis results.\n\n## Your Task\n\nYou will receive a text response containing:\n1. Query execution results (with \"✅ Query executed successfully!\" markers)\n2. Data analysis and insights\n3. **Dashboard Components:** suggestions (1:component_type : reasoning format)\n\nYour job is to:\n1. **FIRST: Generate a direct answer component** (if the user question can be answered with a single visualization)\n - Determine the BEST visualization type (KPICard, BarChart, DataTable, PieChart, LineChart, etc.) to directly answer the user's question\n - Select the matching component from the available components list\n - Generate complete props for this component (query, title, description, config)\n - This component will be placed in the \\`answerComponent\\` field\n - This component will be streamed to the frontend IMMEDIATELY for instant user feedback\n - **CRITICAL**: Generate this FIRST in your JSON response\n\n2. **THEN: Parse ALL dashboard component suggestions** from the text response (format: 1:component_type : reasoning)\n3. **Match EACH suggestion with an actual component** from the available list\n4. **CRITICAL**: \\`matchedComponents\\` must include **ALL** dashboard components suggested in the text, INCLUDING the component you used as \\`answerComponent\\`\n - The answerComponent is shown first for quick feedback, but the full dashboard shows everything\n5. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched\n6. **Generate title and description** for the dashboard container\n7. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis\n\n**CRITICAL GOAL**: Create dashboard components that display the **same data that was already analyzed** - NOT new data. The queries already ran and got results. You're just creating different visualizations of those results.\n\n## Available Components\n\n{{AVAILABLE_COMPONENTS}}\n\n## Component Matching Rules\nFor each component suggestion (c1, c2, c3, etc.) from the text response:\n\n1. **Match by type**: Find components whose \\`type\\` matches the suggested component type\n2. **Refine by relevance**: If multiple components match, choose based on:\n - Description and keywords matching the use case\n - Best fit for the data being visualized\n3. **Fallback**: If no exact type match, find the closest alternative\n\n## Dashboard Container\nAll matched components will be placed in the default **MultiComponentContainer** layout. Your job is to:\n1. **Generate a clear title** for the dashboard that summarizes what it shows\n2. **Generate a brief description** explaining the dashboard's purpose and scope\n\n## Props Generation Rules\n\nFor each matched component, generate complete props:\n\n### 1. Query - When to Reuse vs Generate\n\n**Option A: REUSE the successful query** (preferred when possible)\n- Look for \"✅ Query executed successfully!\" in the text response\n- Extract the exact SQL query that worked\n- Use this SAME query for components that visualize the same data differently\n\n**Option B: GENERATE a new query** (when necessary)\n- Only generate new queries when you need DIFFERENT data\n- For SELECT queries: Use the database schema below to write valid SQL\n- For mutations (INSERT/UPDATE/DELETE): Only if matching a Form component, generate mutation query with $fieldName placeholders\n\n\n**Decision Logic:**\n- Different aggregation needed → Generate new query ✅\n- Same data, different view → Reuse query ✅\n\n**Database Schema:**\n{{SCHEMA_DOC}}\n\n**Database Type: PostgreSQL**\n\n**CRITICAL PostgreSQL Query Rules**\n\n1. **NO AGGREGATE FUNCTIONS IN WHERE CLAUSE** - This is a fundamental SQL error\n ❌ WRONG: \\`WHERE COUNT(orders) > 0\\`\n ❌ WRONG: \\`WHERE SUM(price) > 100\\`\n ❌ WRONG: \\`WHERE AVG(rating) > 4.5\\`\n ❌ WRONG: \\`WHERE FLOOR(AVG(rating)) = 4\\` (aggregate inside any function is still not allowed)\n ❌ WRONG: \\`WHERE ROUND(SUM(price), 2) > 100\\`\n\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\n ✅ CORRECT: Move aggregate logic to HAVING: \\`GROUP BY ... HAVING FLOOR(AVG(rating)) = 4\\`\n ✅ CORRECT: Use subquery for filtering: \\`WHERE product_id IN (SELECT product_id FROM ... GROUP BY ... HAVING AVG(rating) >= 4)\\`\n\n2. **NO NESTED AGGREGATE FUNCTIONS** - PostgreSQL does NOT allow aggregates inside aggregates\n ❌ WRONG: \\`AVG(ROUND(AVG(column), 2))\\`\n ✅ CORRECT: \\`ROUND(AVG(column), 2)\\`\n\n3. **Aggregate Functions Can Only Appear Once Per Level**\n ❌ WRONG: \\`SELECT AVG(SUM(price)) FROM ...\\` (nested)\n ✅ CORRECT: Use subquery: \\`SELECT AVG(total) FROM (SELECT SUM(price) as total FROM ... GROUP BY ...) subq\\`\n\n4. **WHERE vs HAVING**\n - WHERE filters rows BEFORE grouping (cannot use aggregates)\n - HAVING filters groups AFTER grouping (can use aggregates)\n - Use WHERE for column comparisons: \\`WHERE price > 100\\`\n - Use HAVING for aggregate comparisons: \\`HAVING COUNT(*) > 5\\`\n\n5. **GROUP BY Requirements**\n - ALL non-aggregated columns in SELECT must be in GROUP BY\n - Use proper column references (table.column or aliases)\n - If using HAVING, you MUST have GROUP BY\n\n6. **LIMIT Clause**\n - ALWAYS include LIMIT clause (max 32 rows for dashboard queries)\n - For scalar subqueries in WHERE/HAVING, add LIMIT 1\n\n7. **Scalar Subqueries**\n - Subqueries used with =, <, >, etc. must return single value\n - Always add LIMIT 1 to scalar subqueries\n\n8. **String Escaping** - PostgreSQL uses double single-quotes, NOT backslash\n ❌ WRONG: \\`'Children\\\\'s furniture'\\`\n ✅ CORRECT: \\`'Children''s furniture'\\`\n\n9. **Always Use Table Aliases for Column References** - Prevent ambiguous column errors\n ❌ WRONG: \\`SELECT product_id FROM products p JOIN product_variants pv ON p.product_id = pv.product_id\\`\n ✅ CORRECT: \\`SELECT p.product_id FROM products p JOIN product_variants pv ON p.product_id = pv.product_id\\`\n - Always prefix columns with table alias (e.g., \\`p.product_id\\`, \\`c.name\\`)\n - Especially critical in subqueries and joins where multiple tables share column names\n\n**Query Generation Guidelines** (when creating new queries):\n- Use correct table and column names from the schema above\n- ALWAYS include LIMIT clause (max 32 rows)\n\n### 2. Title\n- Create a clear, descriptive title\n- Should explain what the component shows\n- Use context from the original question\n\n### 3. Description\n- Brief explanation of what this component displays\n- Why it's useful for this data\n\n### 4. Config (for visualization components)\n- **CRITICAL**: Look at the component's \"Props Structure\" to see what config fields it expects\n- Map query result columns to the appropriate config fields\n- Keep other existing config properties that don't need to change\n- Ensure config field values match actual column names from the query\n\n**Special Rules for Bar Charts**\n- \\`xAxisKey\\` = ALWAYS the category/label column (text field )\n- \\`yAxisKey\\` = ALWAYS the numeric value column (number field )\n- \\`orientation\\` = \"vertical\" or \"horizontal\" (controls visual direction only)\n- **DO NOT swap xAxisKey/yAxisKey based on orientation** - they always represent category and value respectively\n\n### 5. Additional Props (match according to component type)\n- **CRITICAL**: Look at the matched component's \"Props Structure\" in the available components list\n- Generate props that match EXACTLY what the component expects\n\n**For Form components (type: \"Form\"):**\n\nProps structure:\n- **query**: \\`{ sql: \"INSERT/UPDATE/DELETE query with $fieldName placeholders\", params: [] }\\`\n - **For UPDATE queries**: Check the database schema - if the table has an \\`updated_at\\` or \\`last_updated\\` column, always include it in the SET clause with \\`CURRENT_TIMESTAMP\\` (e.g., \\`UPDATE table_name SET field = $field, updated_at = CURRENT_TIMESTAMP WHERE id = value\\`)\n- **title**: \"Update Order 5000\", \"Create New Product\", or \"Delete Order 5000\"\n- **description**: What the form does\n- **submitButtonText**: Button text (default: \"Submit\"). For delete: \"Delete\", \"Confirm Delete\"\n- **submitButtonColor**: \"primary\" (blue) or \"danger\" (red). Use \"danger\" for DELETE operations\n- **successMessage**: Success message (default: \"Form submitted successfully!\"). For delete: \"Record deleted successfully!\"\n- **disableFields**: Set \\`true\\` for DELETE operations to show current values but prevent editing\n- **fields**: Array of field objects (structure below)\n\n**Field object:**\n\\`\\`\\`json\n{\n \"name\": \"field_name\", // Matches $field_name in SQL query\n \"description\": \"Field Label\",\n \"type\": \"text|number|email|date|select|multiselect|checkbox|textarea\",\n \"required\": true, // Set based on schema: nullable=false → required=true, nullable=true → required=false\n \"defaultValue\": \"current_value\", // For UPDATE: extract from text response\n \"placeholder\": \"hint text\",\n \"options\": [...], // For select/multiselect\n \"validation\": {\n \"minLength\": { \"value\": 5, \"message\": \"...\" },\n \"maxLength\": { \"value\": 100, \"message\": \"...\" },\n \"min\": { \"value\": 18, \"message\": \"...\" },\n \"max\": { \"value\": 120, \"message\": \"...\" },\n \"pattern\": { \"value\": \"regex\", \"message\": \"...\" }\n }\n}\n\\`\\`\\`\n\n**CRITICAL - Set required based on database schema:**\n- Check the column's \\`nullable\\` property in the database schema\n- If \\`nullable: false\\` → set \\`required: true\\` (field is mandatory)\n- If \\`nullable: true\\` → set \\`required: false\\` (field is optional)\n- Never set fields as required if the schema allows NULL\n\n**Default Values for UPDATE:**\n- **NEVER include ID/primary key fields in UPDATE forms** (e.g., order_id, customer_id, product_id) - these cannot be changed\n- Detect UPDATE by checking if SQL contains \"UPDATE\" keyword\n- Extract current values from text response (look for \"Current values:\" or SELECT results)\n- Set \\`defaultValue\\` for each field with the extracted current value\n\n**CRITICAL - Single field with current value pre-selected:**\nFor UPDATE operations, use ONE field with defaultValue set to current value (not two separate fields).\n\n✅ CORRECT - Single field, current value pre-selected:\n\\`\\`\\`json\n{\n \"name\": \"category_id\",\n \"type\": \"select\",\n \"defaultValue\": 5,\n \"options\": [{\"id\": 1, \"name\": \"Kitchen\"}, {\"id\": 5, \"name\": \"Furniture\"}, {\"id\": 7, \"name\": \"Decor\"}]\n}\n\\`\\`\\`\nUser sees dropdown with \"Furniture\" selected, can change to any other category.\n\n❌ WRONG - Two separate fields:\n\\`\\`\\`json\n[\n {\"name\": \"current_category\", \"type\": \"text\", \"defaultValue\": \"Furniture\", \"disabled\": true},\n {\"name\": \"new_category\", \"type\": \"select\", \"options\": [...]}\n]\n\\`\\`\\`\n\n**Options Format:**\n- **Enum/status fields** (non-foreign keys): String array \\`[\"Pending\", \"Shipped\", \"Delivered\"]\\`\n- **Foreign keys** (reference tables): Object array \\`[{\"id\": 1, \"name\": \"Furniture\"}, {\"id\": 2, \"name\": \"Kitchen\"}]\\`\n- Extract from text response queries and match format to field type\n\n**Example UPDATE form field:**\n\\`\\`\\`json\n{\n \"name\": \"status\",\n \"description\": \"Order Status\",\n \"type\": \"select\",\n \"required\": true,\n \"defaultValue\": \"Pending\", // Current value from database\n \"options\": [\"Pending\", \"Processing\", \"Shipped\", \"Delivered\"]\n}\n\\`\\`\\`\n\n**Example DELETE form props:**\n\\`\\`\\`json\n{\n \"query\": { \"sql\": \"DELETE FROM orders WHERE order_id = 123\", \"params\": [] },\n \"title\": \"Delete Order 123\",\n \"description\": \"Are you sure you want to delete this order?\",\n \"submitButtonText\": \"Confirm Delete\",\n \"submitButtonColor\": \"danger\",\n \"successMessage\": \"Order deleted successfully!\",\n \"disableFields\": true,\n \"fields\": [\n { \"name\": \"order_id\", \"description\": \"Order ID\", \"type\": \"text\", \"defaultValue\": \"123\" },\n { \"name\": \"status\", \"description\": \"Status\", \"type\": \"text\", \"defaultValue\": \"Pending\" }\n ]\n}\n\\`\\`\\`\n\n**For visualization components (Charts, Tables, KPIs):**\n- **query**: String (SQL SELECT query)\n- **title**, **description**, **config**: As per component's props structure\n- Do NOT include fields array\n\n## Follow-Up Questions (Actions) Generation\n\nAfter analyzing the text response and matched components, generate 4-5 intelligent follow-up questions that the user might naturally ask next. These questions should:\n\n1. **Build upon the data analysis** shown in the text response and components\n2. **Explore natural next steps** in the data exploration journey\n3. **Be progressively more detailed or specific** - go deeper into the analysis\n4. **Consider the insights revealed** - suggest questions that help users understand implications\n5. **Be phrased naturally** as if a real user would ask them\n6. **Vary in scope** - include both broad trends and specific details\n7. **Avoid redundancy** - don't ask questions already answered in the text response\n\n\n## Output Format\n\nYou MUST respond with ONLY a valid JSON object (no markdown, no code blocks):\n\n**IMPORTANT JSON FORMATTING RULES:**\n- Put SQL queries on a SINGLE LINE (no newlines in the query string)\n- Escape all quotes in SQL properly (use \\\\\" for quotes inside strings)\n- Remove any newlines, tabs, or special characters from SQL\n- Do NOT use markdown code blocks (no \\`\\`\\`)\n- Return ONLY the JSON object, nothing else\n\n**Example 1: With answer component** (when user question can be answered with single visualization)\n\\`\\`\\`json\n{\n \"hasAnswerComponent\": true,\n \"answerComponent\": {\n \"componentId\": \"id_from_available_list\",\n \"componentName\": \"name_of_component\",\n \"componentType\": \"type_of_component (can be KPICard, BarChart, LineChart, PieChart, DataTable, etc.)\",\n \"reasoning\": \"Why this visualization type best answers the user's question\",\n \"props\": {\n \"query\": \"SQL query for this component\",\n \"title\": \"Component title that directly answers the user's question\",\n \"description\": \"Component description\",\n \"config\": {\n \"field1\": \"value1\",\n \"field2\": \"value2\"\n }\n }\n },\n \"layoutTitle\": \"Clear, concise title for the overall dashboard/layout (5-10 words)\",\n \"layoutDescription\": \"Brief description of what the dashboard shows and its purpose (1-2 sentences)\",\n \"matchedComponents\": [\n {\n \"componentId\": \"id_from_available_list\",\n \"componentName\": \"name_of_component\",\n \"componentType\": \"type_of_component\",\n \"reasoning\": \"Why this component was selected for the dashboard\",\n \"originalSuggestion\": \"c1:table : original reasoning from text\",\n \"props\": {\n \"query\": \"SQL query for this component\",\n \"title\": \"Component title\",\n \"description\": \"Component description\",\n \"config\": {\n \"field1\": \"value1\",\n \"field2\": \"value2\"\n }\n }\n }\n ],\n \"actions\": [\n \"Follow-up question 1?\",\n \"Follow-up question 2?\",\n \"Follow-up question 3?\",\n \"Follow-up question 4?\",\n \"Follow-up question 5?\"\n ]\n}\n\\`\\`\\`\n\n**Example 2: Without answer component** (when user question needs multiple visualizations or dashboard)\n\\`\\`\\`json\n{\n \"hasAnswerComponent\": false,\n \"answerComponent\": null,\n \"layoutTitle\": \"Clear, concise title for the overall dashboard/layout (5-10 words)\",\n \"layoutDescription\": \"Brief description of what the dashboard shows and its purpose (1-2 sentences)\",\n \"matchedComponents\": [\n {\n \"componentId\": \"id_from_available_list\",\n \"componentName\": \"name_of_component\",\n \"componentType\": \"type_of_component\",\n \"reasoning\": \"Why this component was selected for the dashboard\",\n \"originalSuggestion\": \"c1:chart : original reasoning from text\",\n \"props\": {\n \"query\": \"SQL query for this component\",\n \"title\": \"Component title\",\n \"description\": \"Component description\",\n \"config\": {\n \"field1\": \"value1\",\n \"field2\": \"value2\"\n }\n }\n }\n ],\n \"actions\": [\n \"Follow-up question 1?\",\n \"Follow-up question 2?\",\n \"Follow-up question 3?\",\n \"Follow-up question 4?\",\n \"Follow-up question 5?\"\n ]\n}\n\\`\\`\\`\n\n**CRITICAL:**\n- **\\`hasAnswerComponent\\` determines if an answer component exists**\n - Set to \\`true\\` if the user question can be answered with a single visualization\n - Set to \\`false\\` if the user question can not be answered with single visualisation and needs multiple visualizations or a dashboard overview\n- **If \\`hasAnswerComponent\\` is \\`true\\`:**\n - \\`answerComponent\\` MUST be generated FIRST in the JSON before \\`layoutTitle\\`\n - Generate complete props (query, title, description, config)\n- **If \\`hasAnswerComponent\\` is \\`false\\`:**\n - Set \\`answerComponent\\` to \\`null\\`\n- **\\`matchedComponents\\` MUST include ALL dashboard components from the text analysis**\n - **CRITICAL**: Even if you used a component as \\`answerComponent\\`, you MUST STILL include it in \\`matchedComponents\\`\n - The count of matchedComponents should EQUAL the count of dashboard suggestions in the text (e.g., if text has 4 suggestions, matchedComponents should have 4 items)\n - Do NOT skip the answerComponent from matchedComponents\n- \\`matchedComponents\\` come from the dashboard component suggestions in the text response\n- \\`layoutTitle\\` MUST be a clear, concise title (5-10 words) that summarizes what the entire dashboard shows\n- \\`layoutDescription\\` MUST be a brief description (1-2 sentences) explaining the purpose and scope of the dashboard\n - Should describe what insights the dashboard provides and what data it shows\n- \\`actions\\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis\n- Return ONLY valid JSON (no markdown code blocks, no text before/after)\n- Generate complete props for each component\n`,\n\t\tuser: `## Analysis Content\n\n{{ANALYSIS_CONTENT}}\n\n---\n\nMatch the component suggestions from the text response above with available components, and generate proper props for each matched component.\n`\n\t},\n\n\t'actions': {\n\t\tsystem: `You are an expert data analyst. Your task is to suggest intelligent follow-up questions based on the conversation history and the current data visualization. The questions should help users explore the data more deeply and make better insights.\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n**Context Instructions:**\n- Review the entire conversation history to understand the user's journey and interests\n- Suggest questions that naturally progress from previous explorations\n- Avoid suggesting questions about topics already covered in the conversation\n- Build upon insights from previous components to suggest deeper analysis\n- Consider what the user might want to explore next based on their question pattern`,\n\t\tuser: `Given the following context:\n\nLatest User Question: {{ORIGINAL_USER_PROMPT}}\n\nCurrent Component:\n{{COMPONENT_INFO}}\n\n{{COMPONENT_DATA}}\n\nGenerate a JSON array of 4-5 intelligent follow-up questions that the user might naturally ask next. These questions should:\n1. Build upon the conversation history and insights shown in the current component\n2. NOT repeat questions or topics already covered in the conversation history\n3. Explore natural next steps in the data exploration journey\n4. Be progressively more detailed or specific\n5. Consider the user's apparent interests based on their question pattern\n6. Be phrased naturally as if a real user would ask them\n\nFormat your response as a JSON object with this structure:\n{\n \"nextQuestions\": [\n \"Question 1?\",\n \"Question 2?\",\n ...\n ]\n}\n\nReturn ONLY valid JSON.`\n\t},\n\n\t'category-classification': {\n\t\tsystem: `You are an expert AI that categorizes user questions into specific action categories and identifies required tools/resources.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\n## Available External Tools\n\n{{AVAILABLE_TOOLS}}\n\n---\n\nYour task is to analyze the user's question and determine:\n\n1. **Question Category:**\n - \"data_analysis\": Questions about analyzing, querying, reading, or visualizing data from the database (SELECT operations)\n - \"data_modification\": Questions about creating, updating, deleting, or modifying data in the database (INSERT, UPDATE, DELETE operations)\n\n2. **External Tools Required** (for both categories):\n From the available tools listed above, identify which ones are needed to support the user's request:\n - Match the tool names/descriptions to what the user is asking for\n - Extract specific parameters mentioned in the user's question\n\n3. **Tool Parameters** (if tools are identified):\n Extract specific parameters the user mentioned:\n - For each identified tool, extract relevant parameters (email, recipient, content, etc.)\n - Only include parameters the user explicitly or implicitly mentioned\n\n**Important Guidelines:**\n- If user mentions any of the available external tools → identify those tools and extract their parameters\n- If user asks to \"send\", \"schedule\", \"create event\", \"message\" → check if available tools match\n- If user asks to \"show\", \"analyze\", \"compare\", \"calculate\" data → \"data_analysis\"\n- If user asks to modify/create/update/delete data → \"data_modification\"\n- Always identify tools from the available tools list (not from generic descriptions)\n- Be precise in identifying tool types and required parameters\n- Only include tools that are explicitly mentioned or clearly needed\n\n**Output Format:**\n\\`\\`\\`json\n{\n \"category\": \"data_analysis\" | \"data_modification\",\n \"reasoning\": \"Brief explanation of why this category was chosen\",\n \"externalTools\": [\n {\n \"type\": \"tool_id_from_available_tools\",\n \"name\": \"Tool Display Name\",\n \"description\": \"What this tool will do\",\n \"parameters\": {\n \"param1\": \"extracted value\",\n \"param2\": \"extracted value\"\n }\n }\n ],\n \"dataAnalysisType\": \"visualization\" | \"calculation\" | \"comparison\" | \"trend\" | null,\n \"confidence\": 0-100\n}\n\\`\\`\\`\n\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}`,\n\t\tuser: `{{USER_PROMPT}}`\n\t},\n\n\t'adapt-ui-block-params': {\n\t\tsystem: `You are an expert AI that adapts and modifies UI block component parameters based on the user's current question.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\n## Database Schema Reference\n\n{{SCHEMA_DOC}}\n\nUse this schema to understand available tables, columns, and relationships when modifying SQL queries. Ensure all table and column names you use in adapted queries are valid according to this schema.\n\n## Context\nYou are given:\n1. A previous UI Block response (with component and its props) that matched the user's current question with >90% semantic similarity\n2. The user's current question\n3. The component that needs parameter adaptation\n\nYour task is to:\n1. **Analyze the difference** between the original question (from the matched UIBlock) and the current user question\n2. **Identify what parameters need to change** in the component props to answer the current question\n3. **Modify the props** to match the current request while keeping the same component type(s)\n4. **Preserve component structure** - only change props, not the components themselves\n\n## Component Structure Handling\n\n### For Single Components:\n- Modify props directly (config, actions, query, filters, etc.)\n\n### For MultiComponentContainer:\nThe component will have structure:\n\\`\\`\\`json\n{\n \"type\": \"Container\",\n \"name\": \"MultiComponentContainer\",\n \"props\": {\n \"config\": {\n \"components\": [...], // Array of nested components - ADAPT EACH ONE\n \"title\": \"...\", // Container title - UPDATE based on new question\n \"description\": \"...\" // Container description - UPDATE based on new question\n },\n \"actions\": [...] // ADAPT actions if needed\n }\n}\n\\`\\`\\`\n\nWhen adapting MultiComponentContainer:\n- Update the container-level \\`title\\` and \\`description\\` to reflect the new user question\n- For each component in \\`config.components\\`:\n - Identify what data it shows and how the new question changes what's needed\n - Adapt its query parameters (WHERE clauses, LIMIT, ORDER BY, filters, date ranges)\n - Update its title/description to match the new context\n - Update its config settings (colors, sorting, grouping, metrics)\n- Update \\`actions\\` if the new question requires different actions\n\n## Important Guidelines:\n- Keep the same component type (don't change KPICard to LineChart)\n- Keep the same number of components in the container\n- For each nested component, update:\n - Query WHERE clauses, LIMIT, ORDER BY, filters, date ranges, metrics\n - Title and description to reflect the new question\n - Config settings like colors, sorting, grouping if needed\n- Maintain each component's core purpose while answering the new question\n- If query modification is needed, ensure all table/column names remain valid\n- CRITICAL: Ensure JSON is valid and complete for all nested structures\n\n\n## Output Format:\n\n### For Single Component:\n\\`\\`\\`json\n{\n \"success\": true,\n \"adaptedComponent\": {\n \"id\": \"original_component_id\",\n \"name\": \"component_name\",\n \"type\": \"component_type\",\n \"description\": \"updated_description\",\n \"props\": {\n \"config\": { },\n \"actions\": [],\n }\n },\n \"parametersChanged\": [\n {\n \"field\": \"query\",\n \"reason\": \"Added Q4 date filter\"\n },\n {\n \"field\": \"title\",\n \"reason\": \"Updated to reflect Q4 focus\"\n }\n ],\n \"explanation\": \"How the component was adapted to answer the new question\"\n}\n\\`\\`\\`\n\n### For MultiComponentContainer:\n\\`\\`\\`json\n{\n \"success\": true,\n \"adaptedComponent\": {\n \"id\": \"original_container_id\",\n \"name\": \"MultiComponentContainer\",\n \"type\": \"Container\",\n \"description\": \"updated_container_description\",\n \"props\": {\n \"config\": {\n \"title\": \"Updated dashboard title based on new question\",\n \"description\": \"Updated description reflecting new question context\",\n \"components\": [\n {\n \"id\": \"component_1_id\",\n \"name\": \"component_1_name\",\n \"type\": \"component_1_type\",\n \"description\": \"updated description for this specific component\",\n \"props\": {\n \"query\": \"Modified SQL query with updated WHERE/LIMIT/ORDER BY\",\n \"config\": { \"metric\": \"updated_metric\", \"filters\": {...} }\n }\n },\n {\n \"id\": \"component_2_id\",\n \"name\": \"component_2_name\",\n \"type\": \"component_2_type\",\n \"description\": \"updated description for this component\",\n \"props\": {\n \"query\": \"Modified SQL query for this component\",\n \"config\": { \"metric\": \"updated_metric\", \"filters\": {...} }\n }\n }\n ]\n },\n \"actions\": []\n }\n },\n \"parametersChanged\": [\n {\n \"field\": \"container.title\",\n \"reason\": \"Updated to reflect new dashboard focus\"\n },\n {\n \"field\": \"components[0].query\",\n \"reason\": \"Modified WHERE clause for new metrics\"\n },\n {\n \"field\": \"components[1].config.metric\",\n \"reason\": \"Changed metric from X to Y based on new question\"\n }\n ],\n \"explanation\": \"Detailed explanation of how each component was adapted\"\n}\n\\`\\`\\`\n\nIf adaptation is not possible or would fundamentally change the component:\n\\`\\`\\`json\n{\n \"success\": false,\n \"reason\": \"Cannot adapt component - the new question requires a different visualization type\",\n \"explanation\": \"The original component shows KPI cards but the new question needs a trend chart\"\n}\n\\`\\`\\``,\n\t\tuser: `## Previous Matched UIBlock\n\n**Original Question:** {{ORIGINAL_USER_PROMPT}}\n\n**Matched UIBlock Component:**\n\\`\\`\\`json\n{{MATCHED_UI_BLOCK_COMPONENT}}\n\\`\\`\\`\n\n**Component Properties:**\n\\`\\`\\`json\n{{COMPONENT_PROPS}}\n\\`\\`\\`\n\n## Current User Question\n{{CURRENT_USER_PROMPT}}\n\n---\n\n## Adaptation Instructions\n\n1. **Analyze the difference** between the original question and the current question\n2. **Identify what data needs to change**:\n - For single components: adapt the query/config/actions\n - For MultiComponentContainer: adapt the container title/description AND each nested component's parameters\n\n3. **Modify the parameters**:\n - **Container level** (if MultiComponentContainer):\n - Update \\`title\\` and \\`description\\` to reflect the new user question\n - Update \\`actions\\` if needed\n\n - **For each component** (single or nested in container):\n - Identify what it shows (sales, revenue, inventory, etc.)\n - Adapt SQL queries: modify WHERE clauses, LIMIT, ORDER BY, filters, date ranges\n - Update component title and description\n - Update config settings (metrics, colors, sorting, grouping)\n\n4. **Preserve structure**: Keep the same number and type of components\n\n5. **Return complete JSON** with all adapted properties for all components`\n\t},\n\n\t'dash-comp-picker': {\n\t\tsystem: `You are a component selection expert that picks the best dashboard component and generates complete props based on user requests.\n\n## Your Task\n\nAnalyze the user's request and:\n1. **Select the most appropriate component** from the available components list\n2. **Determine the data source**: Database query OR External tool (ERP)\n3. **Generate complete props** for the selected component including the data retrieval/modification method\n\n## Component Selection Rules\n\n1. **Match by Intent**: Understand what the user wants to display/achieve\n2. **Match by Type**: Choose the component type that best fits the data visualization or action need\n3. **Match by Description**: Use component descriptions and keywords to find the best fit\n\n## Data Source Decision\n\n### Use DATABASE when:\n- User asks about data that exists in the database schema (customers, orders, products, etc.)\n- Questions about internal business data (sales, inventory, users, transactions)\n- CRUD operations on database tables\n\n### Use EXTERNAL TOOL when:\n- User mentions specific external systems (ERP, CRM, email, calendar, etc.)\n- Data not available in database schema\n- Actions that require external integrations (send email, create calendar event, sync with ERP)\n- Tool description matches the user's request\n\n## Props Generation Rules\n\n**CRITICAL**: Look at each component's \"Props Structure\" in the available components list. Generate ALL props that the component expects.\n\n### For Data Viewing Components (charts, tables, KPIs):\n\n**Option A: Database Query** (when data is in database)\n\\`\\`\\`json\n{\n \"query\": {\n \"sql\": \"SELECT column1, column2 FROM table WHERE condition = $param LIMIT 32\",\n \"params\": { \"param\": \"value\" }\n }\n}\n\\`\\`\\`\n\n**Option B: External Tool** (when data is from ERP/external system)\n\\`\\`\\`json\n{\n \"externalTool\": {\n \"toolId\": \"tool_id_from_list\",\n \"toolName\": \"Tool Display Name\",\n \"action\": \"get\",\n \"params\": {\n \"param1\": \"value1\",\n \"param2\": \"value2\"\n }\n }\n}\n\\`\\`\\`\n\n### For Data Modification Components (forms):\n\n**Option A: Database Mutation**\n\\`\\`\\`json\n{\n \"query\": {\n \"sql\": \"INSERT INTO table (col1, col2) VALUES ($col1, $col2)\",\n \"params\": {}\n },\n \"fields\": [\n { \"name\": \"col1\", \"type\": \"text\", \"required\": true },\n { \"name\": \"col2\", \"type\": \"number\", \"required\": false }\n ]\n}\n\\`\\`\\`\n\n**Option B: External Tool Mutation**\n\\`\\`\\`json\n{\n \"externalTool\": {\n \"toolId\": \"tool_id_from_list\",\n \"toolName\": \"Tool Display Name\",\n \"action\": \"create|update|delete\",\n \"params\": {\n \"param1\": \"value_or_placeholder\"\n }\n },\n \"fields\": [\n { \"name\": \"param1\", \"type\": \"text\", \"required\": true }\n ]\n}\n\\`\\`\\`\n\n### Database Query Rules\n{{DATABASE_RULES}}\n\n## Output Format\n\nYou MUST respond with ONLY a valid JSON object (no markdown, no code blocks):\n\n{\n \"componentId\": \"id_from_available_list\",\n \"componentName\": \"name_of_component\",\n \"componentType\": \"type_of_component\",\n \"dataSourceType\": \"database\" | \"external_tool\",\n \"operationType\": \"view\" | \"create\" | \"update\" | \"delete\",\n \"reasoning\": \"Why this component was selected and why this data source\",\n \"props\": {\n // Generate ALL props based on the component's Props Structure\n // Include either \"query\" OR \"externalTool\" based on data source\n // Include all other required props (title, description, config, fields, etc.)\n }\n}\n\n**CRITICAL:**\n- Return ONLY valid JSON (no markdown code blocks, no text before/after)\n- \\`componentId\\` MUST match an ID from the available components list\n- \\`dataSourceType\\` indicates whether data comes from database or external tool\n- \\`operationType\\` indicates the type of operation (view/create/update/delete)\n- Generate COMPLETE props based on the component's \"Props Structure\"\n- For queries, ALWAYS use \\`$paramName\\` placeholders and include \\`params\\` object\n- For external tools, \\`toolId\\` MUST match an ID from the available tools list\n\n---\n\n## CONTEXT (for this specific request)\n\n### Database Schema\n{{SCHEMA_DOC}}\n\n### Available External Tools\n{{AVAILABLE_TOOLS}}\n\n### Available Components\n{{AVAILABLE_COMPONENTS}}`,\n\t\tuser: `{{USER_PROMPT}}`\n\t}\n};\n","import fs from 'fs';\nimport path from 'path';\nimport { logger } from '../utils/logger';\nimport { PROMPTS } from './prompts';\n\nexport interface PromptLoaderConfig {\n\tpromptsDir?: string;\n}\n\ninterface CachedPromptTemplate {\n\tsystem: string;\n\tuser: string;\n}\n\n/**\n * PromptLoader class for loading and processing prompt templates\n * Tries to load from file system first, then falls back to hardcoded prompts\n */\nexport class PromptLoader {\n\tprivate promptsDir: string;\n\tprivate promptCache: Map<string, CachedPromptTemplate> = new Map();\n\tprivate databaseRulesCache: Map<string, string> = new Map();\n\tprivate isInitialized: boolean = false;\n\tprivate databaseType: string = 'postgresql';\n\n\tconstructor(config?: PromptLoaderConfig) {\n\t\tlogger.debug('Initializing PromptLoader...');\n\t\t// Default to backend's .prompts directory (where the SDK is being used)\n\t\tthis.promptsDir = config?.promptsDir || path.join(process.cwd(), '.prompts');\n\t\tlogger.debug(`Prompts directory set to: ${this.promptsDir}`);\n\t}\n\n\t/**\n\t * Load a prompt template from file system OR fallback to hardcoded prompts\n\t * @param promptName - Name of the prompt folder\n\t * @returns Template with system and user prompts\n\t */\n\tprivate loadPromptTemplate(promptName: string): CachedPromptTemplate {\n\t\t// First, try to load from file system (backend's .prompts directory)\n\t\ttry {\n\t\t\tconst systemPath = path.join(this.promptsDir, promptName, 'system.md');\n\t\t\tconst userPath = path.join(this.promptsDir, promptName, 'user.md');\n\n\t\t\tif (fs.existsSync(systemPath) && fs.existsSync(userPath)) {\n\t\t\t\tconst system = fs.readFileSync(systemPath, 'utf-8');\n\t\t\t\tconst user = fs.readFileSync(userPath, 'utf-8');\n\t\t\t\tlogger.info(`✓ Loaded prompt '${promptName}' from file system: ${this.promptsDir}`);\n\t\t\t\treturn { system, user };\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Ignore file system errors and try fallback\n\t\t\tlogger.error(`Could not load '${promptName}' from file system, trying fallback...`);\n\t\t}\n\n\t\t// Fallback to hardcoded prompts\n\t\tconst hardcodedPrompt = PROMPTS[promptName];\n\t\tif (hardcodedPrompt) {\n\t\t\tlogger.info(`✓ Loaded prompt '${promptName}' from hardcoded fallback`);\n\t\t\treturn hardcodedPrompt;\n\t\t}\n\n\t\tthrow new Error(`Prompt template '${promptName}' not found in either ${this.promptsDir} or hardcoded prompts. Available prompts: ${Object.keys(PROMPTS).join(', ')}`);\n\t}\n\n\t/**\n\t * Initialize and cache all prompts into memory\n\t * Tries file system first, then falls back to hardcoded prompts\n\t */\n\tasync initialize(): Promise<void> {\n\t\tif (this.isInitialized) {\n\t\t\tlogger.debug('PromptLoader already initialized, skipping...');\n\t\t\treturn;\n\t\t}\n\n\t\tlogger.info('Loading prompts into memory...');\n\n\t\tconst promptTypes = Object.keys(PROMPTS);\n\n\t\tfor (const promptName of promptTypes) {\n\t\t\ttry {\n\t\t\t\tconst template = this.loadPromptTemplate(promptName);\n\t\t\t\tthis.promptCache.set(promptName, template);\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(`Failed to load prompt '${promptName}':`, error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tthis.isInitialized = true;\n\t\tlogger.info(`Successfully loaded ${this.promptCache.size} prompt templates into memory`);\n\t}\n\n\t/**\n\t * Replace variables in a template string using {{VARIABLE_NAME}} pattern\n\t * @param template - Template string with placeholders\n\t * @param variables - Variables to replace in the template\n\t * @returns Processed string\n\t */\n\tprivate replaceVariables(\n\t\ttemplate: string,\n\t\tvariables: Record<string, string | number | boolean | any[]>\n\t): string {\n\t\tlet content = template;\n\n\t\t// Replace all variables matching {{VARIABLE_NAME}} pattern\n\t\tfor (const [key, value] of Object.entries(variables)) {\n\t\t\tconst pattern = new RegExp(`{{${key}}}`, 'g');\n\t\t\tconst replacementValue = typeof value === 'string' ? value : JSON.stringify(value);\n\t\t\tcontent = content.replace(pattern, replacementValue);\n\t\t}\n\n\t\treturn content;\n\t}\n\n\t/**\n\t * Load both system and user prompts from cache and replace variables\n\t * Supports prompt caching by splitting static and dynamic content\n\t * @param promptName - Name of the prompt\n\t * @param variables - Variables to replace in the templates\n\t * @returns Object containing both system and user prompts (system can be string or array for caching)\n\t */\n\tasync loadPrompts(\n\t\tpromptName: string,\n\t\tvariables: Record<string, string | number | boolean | any[]>\n\t): Promise<{ system: string | any[]; user: string }> {\n\t\tif (!this.isInitialized) {\n\t\t\tlogger.warn('PromptLoader not initialized, initializing now...');\n\t\t\tawait this.initialize();\n\t\t}\n\n\t\tconst template = this.promptCache.get(promptName);\n\n\t\tif (!template) {\n\t\t\tthrow new Error(`Prompt template '${promptName}' not found in cache. Available prompts: ${Array.from(this.promptCache.keys()).join(', ')}`);\n\t\t}\n\n\t\t// Check if the prompt has a context section marker (for caching)\n\t\tconst contextMarker = '---\\n\\n## CONTEXT';\n\n\t\tif (template.system.includes(contextMarker)) {\n\t\t\t// Split into static (cacheable) and dynamic (context) sections\n\t\t\tconst [staticPart, contextPart] = template.system.split(contextMarker);\n\n\t\t\t// Replace variables in BOTH parts\n\t\t\t// Static part may contain schema/rules which are per-project but stable\n\t\t\tconst processedStatic = this.replaceVariables(staticPart, variables);\n\t\t\tconst processedContext = this.replaceVariables(contextMarker + contextPart, variables);\n\n\t\t\tconst staticLength = processedStatic.length;\n\t\t\tconst contextLength = processedContext.length;\n\n\t\t\tlogger.debug(`✓ Prompt caching enabled for '${promptName}' (cached: ${staticLength} chars, dynamic: ${contextLength} chars)`);\n\n\t\t\t// Return as array of blocks for Anthropic caching\n\t\t\t// The static part (with schema) will be cached after first request\n\t\t\treturn {\n\t\t\t\tsystem: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: processedStatic.trim(),\n\t\t\t\t\t\tcache_control: { type: 'ephemeral' }\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: processedContext.trim()\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tuser: this.replaceVariables(template.user, variables)\n\t\t\t};\n\t\t}\n\n\t\t// Fallback: No caching, return as simple string\n\t\treturn {\n\t\t\tsystem: this.replaceVariables(template.system, variables),\n\t\t\tuser: this.replaceVariables(template.user, variables)\n\t\t};\n\t}\n\n\t/**\n\t * DEPRECATED: Use loadPrompts instead\n\t * Load a single prompt file and replace variables using {{VARIABLE_NAME}} pattern\n\t */\n\tasync loadPrompt(\n\t\tpromptName: string,\n\t\tpromptType: 'system' | 'user',\n\t\tvariables: Record<string, string | number | boolean | any[]>\n\t): Promise<string | any[]> {\n\t\tconst prompts = await this.loadPrompts(promptName, variables);\n\t\treturn promptType === 'system' ? prompts.system : prompts.user;\n\t}\n\n\t/**\n\t * Set custom prompts directory (requires re-initialization)\n\t * @param dir - Path to the prompts directory\n\t */\n\tsetPromptsDir(dir: string): void {\n\t\tthis.promptsDir = dir;\n\t\tthis.isInitialized = false;\n\t\tthis.promptCache.clear();\n\t\tlogger.debug(`Prompts directory changed to: ${dir}`);\n\t}\n\n\t/**\n\t * Get current prompts directory\n\t * @returns Path to the prompts directory\n\t */\n\tgetPromptsDir(): string {\n\t\treturn this.promptsDir;\n\t}\n\n\t/**\n\t * Check if prompts are loaded in memory\n\t */\n\tisReady(): boolean {\n\t\treturn this.isInitialized;\n\t}\n\n\t/**\n\t * Get the number of cached prompts\n\t */\n\tgetCacheSize(): number {\n\t\treturn this.promptCache.size;\n\t}\n\n\t/**\n\t * Set the database type for SQL rules loading\n\t * @param type - Database type ('postgresql' | 'mssql')\n\t */\n\tsetDatabaseType(type: string): void {\n\t\tthis.databaseType = type;\n\t\tthis.databaseRulesCache.clear();\n\t\tlogger.debug(`Database type set to: ${type}`);\n\t}\n\n\t/**\n\t * Get current database type\n\t * @returns Database type string\n\t */\n\tgetDatabaseType(): string {\n\t\treturn this.databaseType;\n\t}\n\n\t/**\n\t * Load database-specific SQL rules from file system\n\t * Falls back to minimal default rules if file not found\n\t * @returns Database rules as a string\n\t */\n\tasync loadDatabaseRules(): Promise<string> {\n\t\t// Check cache first\n\t\tif (this.databaseRulesCache.has(this.databaseType)) {\n\t\t\tlogger.debug(`✓ Database rules for '${this.databaseType}' loaded from cache`);\n\t\t\treturn this.databaseRulesCache.get(this.databaseType)!;\n\t\t}\n\n\t\t// Try loading from file system\n\t\tconst rulesPath = path.join(this.promptsDir, 'database-rules', `${this.databaseType}.md`);\n\n\t\ttry {\n\t\t\tif (fs.existsSync(rulesPath)) {\n\t\t\t\tconst rules = fs.readFileSync(rulesPath, 'utf-8');\n\t\t\t\tthis.databaseRulesCache.set(this.databaseType, rules);\n\t\t\t\tlogger.info(`✓ Loaded database rules for '${this.databaseType}' from ${rulesPath}`);\n\t\t\t\treturn rules;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tlogger.warn(`Could not load database rules for '${this.databaseType}' from file system: ${error}`);\n\t\t}\n\n\t\t// Fallback to default rules\n\t\tconst defaultRules = this.getDefaultDatabaseRules();\n\t\tthis.databaseRulesCache.set(this.databaseType, defaultRules);\n\t\tlogger.warn(`Using default database rules for '${this.databaseType}' (file not found at ${rulesPath})`);\n\t\treturn defaultRules;\n\t}\n\n\t/**\n\t * Get default database rules as fallback\n\t * @returns Minimal database rules\n\t */\n\tprivate getDefaultDatabaseRules(): string {\n\t\tif (this.databaseType === 'mssql') {\n\t\t\treturn `**Database Type: Microsoft SQL Server**\n\n**SQL Query Rules:**\n- Use \\`TOP N\\` for row limiting (e.g., \\`SELECT TOP 32 * FROM table\\`)\n- Use \\`1\\` for true, \\`0\\` for false (no native boolean)\n- Use \\`+\\` or \\`CONCAT()\\` for string concatenation\n- Use \\`GETDATE()\\` for current timestamp\n- Use \\`CAST()\\` or \\`CONVERT()\\` for type casting\n- Use \\`OUTPUT INSERTED.*\\` instead of \\`RETURNING\\`\n- NULL values: Use \\`NULL\\` keyword without quotes`;\n\t\t}\n\n\t\t// Default to PostgreSQL\n\t\treturn `**Database Type: PostgreSQL**\n\n**SQL Query Rules:**\n- Use \\`LIMIT N\\` for row limiting (e.g., \\`SELECT * FROM table LIMIT 32\\`)\n- Use \\`true\\` / \\`false\\` for boolean values\n- Use \\`||\\` for string concatenation\n- Use \\`NOW()\\` for current timestamp\n- Use \\`::TYPE\\` or \\`CAST()\\` for type casting\n- Use \\`RETURNING\\` clause for mutations\n- NULL values: Use \\`NULL\\` keyword without quotes`;\n\t}\n}\n\n// Export a singleton instance\n// Default to backend's .prompts directory (where the SDK is being used)\n// If prompts are not found there, the loader will fallback to hardcoded prompts\nconst defaultPromptsPath = process.env.PROMPTS_DIR || path.join(process.cwd(), '.prompts');\n\nexport const promptLoader = new PromptLoader({\n\tpromptsDir: defaultPromptsPath\n});\n","import type { Action } from '../threads/action';\nimport type { DatabaseType } from '../types';\nimport { promptLoader } from './prompt-loader';\n\nexport type { DatabaseType };\n\n/**\n * Gets the current database type from the prompt loader\n * @returns The database type string\n */\nexport function getDatabaseType(): DatabaseType {\n\treturn promptLoader.getDatabaseType() as DatabaseType;\n}\n\n/**\n * Converts LIMIT syntax to TOP syntax for MSSQL\n * MSSQL doesn't support LIMIT keyword - it must use TOP\n * @param query - The SQL query to check\n * @param limit - The limit value to use\n * @returns The query with LIMIT converted to TOP\n */\nexport function convertLimitToTop(query: string, limit: number): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Remove LIMIT clause and add TOP after SELECT\n\tlet modifiedQuery = query.replace(/\\s*\\bLIMIT\\s+\\d+\\b/gi, '').trim();\n\n\t// Add TOP N after SELECT (handles SELECT DISTINCT as well)\n\tmodifiedQuery = modifiedQuery.replace(/^\\s*(SELECT)\\s+(DISTINCT\\s+)?/i, `$1 TOP ${limit} $2`);\n\n\treturn modifiedQuery;\n}\n\n/**\n * Converts TOP syntax to LIMIT syntax for PostgreSQL/Snowflake\n * These databases don't support TOP keyword - they must use LIMIT\n * @param query - The SQL query to check\n * @returns The query with TOP removed (LIMIT will be added separately)\n */\nexport function convertTopToLimit(query: string): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Remove \"TOP N\" from query - LIMIT will be added at the end\n\t// Pattern: SELECT TOP number or SELECT TOP (number)\n\tlet modifiedQuery = query.replace(/\\bSELECT\\s+TOP\\s+\\(?\\d+\\)?\\s*/gi, 'SELECT ');\n\n\treturn modifiedQuery;\n}\n\n/**\n * Ensures a SQL query has a row limiting clause to prevent large result sets\n * Only applies to SELECT queries - leaves INSERT, UPDATE, DELETE, etc. unchanged\n * Database-aware: Uses TOP for MSSQL, LIMIT for PostgreSQL/Snowflake/MySQL\n * Enforces a maximum limit to prevent excessive data retrieval\n * @param query - The SQL query to check\n * @param defaultLimit - Default limit to apply if none exists (default: 32)\n * @param maxLimit - Maximum allowed limit (default: 32)\n * @param dbType - Database type (optional, defaults to promptLoader's database type)\n * @returns The query with appropriate row limiting clause (if it's a SELECT query)\n */\nexport function ensureQueryLimit(\n\tquery: string,\n\tdefaultLimit: number = 32,\n\tmaxLimit: number = 32,\n\tdbType?: DatabaseType\n): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Get database type from parameter or prompt loader\n\tconst databaseType = dbType || getDatabaseType();\n\tconst isMssql = databaseType === 'mssql';\n\n\tlet trimmedQuery = query.trim();\n\n\t// Only apply limits to SELECT queries\n\t// Check if the query is a SELECT statement (not INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, etc.)\n\tconst isSelectQuery = /^\\s*SELECT\\b/i.test(trimmedQuery) ||\n\t\t/^\\s*WITH\\b.*\\bSELECT\\b/is.test(trimmedQuery); // Also handle CTEs (WITH clause)\n\n\tif (!isSelectQuery) {\n\t\t// Not a SELECT query, return as-is\n\t\treturn query;\n\t}\n\n\t// Remove any trailing semicolon for processing\n\tconst hadSemicolon = trimmedQuery.endsWith(';');\n\tif (hadSemicolon) {\n\t\ttrimmedQuery = trimmedQuery.slice(0, -1).trim();\n\t}\n\n\tif (isMssql) {\n\t\t// MSSQL: Use TOP syntax\n\t\treturn ensureMssqlTop(trimmedQuery, defaultLimit, maxLimit, hadSemicolon);\n\t} else {\n\t\t// PostgreSQL/Snowflake/MySQL: Use LIMIT syntax\n\t\treturn ensurePostgresLimit(trimmedQuery, defaultLimit, maxLimit, hadSemicolon);\n\t}\n}\n\n/**\n * Ensures MSSQL query has TOP clause for row limiting\n */\nfunction ensureMssqlTop(query: string, defaultLimit: number, maxLimit: number, hadSemicolon: boolean): string {\n\tlet trimmedQuery = query;\n\n\t// First, remove any LIMIT clauses (might be added by LLM incorrectly)\n\ttrimmedQuery = trimmedQuery.replace(/\\s*\\bLIMIT\\s+\\d+\\b/gi, '').trim();\n\n\t// Check if TOP already exists\n\tconst topMatch = trimmedQuery.match(/\\bSELECT\\s+TOP\\s+\\(?\\s*(\\d+)\\s*\\)?/i);\n\n\tif (topMatch) {\n\t\tconst existingTop = parseInt(topMatch[1], 10);\n\n\t\t// If existing TOP is within limits, keep it\n\t\tif (existingTop <= maxLimit) {\n\t\t\tif (hadSemicolon) {\n\t\t\t\ttrimmedQuery += ';';\n\t\t\t}\n\t\t\treturn trimmedQuery;\n\t\t}\n\n\t\t// If existing TOP exceeds maxLimit, replace it\n\t\tconsole.warn(`⚠️ Query TOP ${existingTop} exceeds maximum of ${maxLimit}. Reducing to ${maxLimit}...`);\n\t\ttrimmedQuery = trimmedQuery.replace(/\\bSELECT\\s+TOP\\s+\\(?\\s*\\d+\\s*\\)?/i, `SELECT TOP ${maxLimit}`);\n\n\t\tif (hadSemicolon) {\n\t\t\ttrimmedQuery += ';';\n\t\t}\n\t\treturn trimmedQuery;\n\t}\n\n\t// No TOP exists, add it after SELECT (handle SELECT DISTINCT)\n\ttrimmedQuery = trimmedQuery.replace(\n\t\t/^\\s*(SELECT)\\s+(DISTINCT\\s+)?/i,\n\t\t`$1 TOP ${defaultLimit} $2`\n\t);\n\n\tif (hadSemicolon) {\n\t\ttrimmedQuery += ';';\n\t}\n\treturn trimmedQuery;\n}\n\n/**\n * Ensures PostgreSQL/Snowflake/MySQL query has LIMIT clause for row limiting\n */\nfunction ensurePostgresLimit(query: string, defaultLimit: number, maxLimit: number, hadSemicolon: boolean): string {\n\tlet trimmedQuery = query;\n\n\t// First, convert any TOP syntax to standard format (remove TOP, will add LIMIT)\n\ttrimmedQuery = convertTopToLimit(trimmedQuery);\n\n\t// Remove any duplicate LIMIT clauses\n\tconst limitMatches = trimmedQuery.match(/\\bLIMIT\\s+(\\d+)\\b/gi);\n\n\tif (limitMatches && limitMatches.length > 0) {\n\t\tif (limitMatches.length > 1) {\n\t\t\t// Multiple LIMIT clauses, remove all and add fresh one\n\t\t\tconsole.warn(`⚠️ Query had ${limitMatches.length} LIMIT clauses. Removing duplicates...`);\n\t\t\ttrimmedQuery = trimmedQuery.replace(/\\s*\\bLIMIT\\s+\\d+\\b/gi, '').trim();\n\t\t} else {\n\t\t\t// Single LIMIT exists - check if it exceeds maxLimit\n\t\t\tconst existingLimitMatch = trimmedQuery.match(/\\bLIMIT\\s+(\\d+)\\b/i);\n\t\t\tif (existingLimitMatch) {\n\t\t\t\tconst existingLimit = parseInt(existingLimitMatch[1], 10);\n\n\t\t\t\tif (existingLimit <= maxLimit) {\n\t\t\t\t\tif (hadSemicolon) {\n\t\t\t\t\t\ttrimmedQuery += ';';\n\t\t\t\t\t}\n\t\t\t\t\treturn trimmedQuery;\n\t\t\t\t}\n\n\t\t\t\tconsole.warn(`⚠️ Query LIMIT ${existingLimit} exceeds maximum of ${maxLimit}. Reducing to ${maxLimit}...`);\n\t\t\t\ttrimmedQuery = trimmedQuery.replace(/\\bLIMIT\\s+\\d+\\b/i, `LIMIT ${maxLimit}`);\n\n\t\t\t\tif (hadSemicolon) {\n\t\t\t\t\ttrimmedQuery += ';';\n\t\t\t\t}\n\t\t\t\treturn trimmedQuery;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add LIMIT clause at the end\n\ttrimmedQuery = `${trimmedQuery} LIMIT ${defaultLimit}`;\n\n\tif (hadSemicolon) {\n\t\ttrimmedQuery += ';';\n\t}\n\treturn trimmedQuery;\n}\n\n/**\n * Validates and fixes scalar subqueries to ensure they return exactly one row\n * Database-aware: Adds TOP 1 for MSSQL, LIMIT 1 for PostgreSQL/Snowflake/MySQL\n * Fixes subqueries used with scalar comparison operators (=, <, >, <=, >=, <>)\n *\n * @param query - The SQL query to validate\n * @param dbType - Database type (optional, defaults to promptLoader's database type)\n * @returns The query with fixed scalar subqueries\n */\nexport function fixScalarSubqueries(query: string, dbType?: DatabaseType): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Get database type from parameter or prompt loader\n\tconst databaseType = dbType || getDatabaseType();\n\tconst isMssql = databaseType === 'mssql';\n\n\tlet modifiedQuery = query;\n\tlet hasChanges = false;\n\n\t// Find all subqueries preceded by scalar comparison operators\n\t// Pattern: operator followed by (SELECT ...)\n\tconst scalarOperatorPattern = /([=<>!]=?|<>)\\s*\\(\\s*SELECT\\s/gi;\n\n\tconst matches = [...modifiedQuery.matchAll(scalarOperatorPattern)];\n\n\t// Process matches in reverse order to maintain string positions\n\tfor (let i = matches.length - 1; i >= 0; i--) {\n\t\tconst match = matches[i];\n\t\tconst startPos = match.index! + match[0].length - 'SELECT '.length;\n\n\t\t// Find the matching closing parenthesis\n\t\tlet parenDepth = 1;\n\t\tlet endPos = startPos;\n\t\tlet foundEnd = false;\n\n\t\tfor (let j = startPos; j < modifiedQuery.length; j++) {\n\t\t\tconst char = modifiedQuery[j];\n\t\t\tif (char === '(') parenDepth++;\n\t\t\tif (char === ')') {\n\t\t\t\tparenDepth--;\n\t\t\t\tif (parenDepth === 0) {\n\t\t\t\t\tendPos = j;\n\t\t\t\t\tfoundEnd = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!foundEnd) continue;\n\n\t\t// Extract the subquery content\n\t\tconst subquery = modifiedQuery.substring(startPos, endPos);\n\n\t\tif (isMssql) {\n\t\t\t// Check if it already has TOP\n\t\t\tif (/\\bSELECT\\s+TOP\\s+\\d+/i.test(subquery)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Add TOP 1 after SELECT for MSSQL\n\t\t\tconst fixedSubquery = subquery.replace(/^\\s*SELECT\\s+/i, 'SELECT TOP 1 ');\n\t\t\tmodifiedQuery =\n\t\t\t\tmodifiedQuery.substring(0, startPos) +\n\t\t\t\tfixedSubquery +\n\t\t\t\tmodifiedQuery.substring(endPos);\n\t\t} else {\n\t\t\t// Check if it already has LIMIT\n\t\t\tif (/\\bLIMIT\\s+\\d+/i.test(subquery)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Add LIMIT 1 at the end for PostgreSQL/Snowflake/MySQL\n\t\t\tconst fixedSubquery = subquery.trim() + ' LIMIT 1';\n\t\t\tmodifiedQuery =\n\t\t\t\tmodifiedQuery.substring(0, startPos) +\n\t\t\t\tfixedSubquery +\n\t\t\t\tmodifiedQuery.substring(endPos);\n\t\t}\n\n\t\thasChanges = true;\n\t\tconst limitType = isMssql ? 'TOP 1' : 'LIMIT 1';\n\t\tconsole.warn(`⚠️ Fixed scalar subquery: added ${limitType} to prevent multiple row error`);\n\t}\n\n\tif (hasChanges) {\n\t\tconst dbName = isMssql ? 'MSSQL' : 'PostgreSQL';\n\t\tconsole.log(`✓ Query validated and fixed for ${dbName} scalar subquery compatibility`);\n\t}\n\n\treturn modifiedQuery;\n}\n\n/**\n * Converts question strings to Action objects format\n * Used for follow-up questions generated by LLM\n * @param questions - Array of question strings\n * @returns Array of Action objects\n */\nexport function convertQuestionsToActions(questions: string[]): Action[] {\n\treturn questions.map((question: string, index: number) => ({\n\t\tid: `action_${index}_${Date.now()}`,\n\t\tname: question,\n\t\ttype: 'next_question',\n\t\tquestion\n\t}));\n}\n\n/**\n * Calculates the size of a JSON object in bytes\n * @param obj - The object to measure\n * @returns Size in bytes\n */\nexport function getJsonSizeInBytes(obj: any): number {\n\tconst jsonString = JSON.stringify(obj);\n\treturn Buffer.byteLength(jsonString, 'utf8');\n}\n\n/**\n * Checks if a message exceeds the WebSocket size limit\n * @param message - The message object to check\n * @param maxSize - Maximum size in bytes (default: 1MB)\n * @returns Object with isValid flag and size information\n */\nexport function validateMessageSize(message: any, maxSize: number = 1048576): { isValid: boolean; size: number; maxSize: number } {\n\tconst size = getJsonSizeInBytes(message);\n\treturn {\n\t\tisValid: size <= maxSize,\n\t\tsize,\n\t\tmaxSize\n\t};\n}","import { createWebSocket } from './websocket';\nimport {\n IncomingMessageSchema,\n type Message,\n type IncomingMessage,\n type SuperatomSDKConfig,\n type CollectionRegistry,\n type CollectionHandler,\n type CollectionOperation,\n type DatabaseType,\n Component,\n LLMProvider,\n Tool,\n} from './types';\nimport { logger } from './utils/logger';\nimport { handleDataRequest } from './handlers/data-request';\nimport { handleBundleRequest } from './handlers/bundle-request';\nimport { handleAuthLoginRequest } from './handlers/auth-login-requests';\nimport { handleAuthVerifyRequest } from './handlers/auth-verify-request';\nimport { handleUserPromptRequest } from './handlers/user-prompt-request';\nimport { handleUserPromptSuggestions } from './handlers/user-prompt-suggestions';\nimport { handleActionsRequest } from './handlers/actions-request';\nimport { handleComponentListResponse } from './handlers/components-list-response';\nimport { handleUsersRequest } from './handlers/users';\nimport { handleDashboardsRequest } from './handlers/dashboards';\nimport { handleReportsRequest } from './handlers/reports';\nimport { handleUIsRequest } from './handlers/uis';\nimport { handleBookmarksRequest } from './handlers/bookmarks';\nimport { handleKbNodesRequest } from './handlers/kb-nodes';\nimport { handleDashCompRequest } from './handlers/dash-comp-request';\nimport { getLLMProviders } from './userResponse';\nimport { setUserManager, cleanupUserStorage } from './auth/user-storage';\nimport { UserManager } from './auth/user-manager';\nimport { setDashboardManager } from './dashboards/dashboard-storage';\nimport { DashboardManager } from './dashboards/dashboard-manager';\nimport { setReportManager } from './reports/report-storage';\nimport { ReportManager } from './reports/report-manager';\nimport { promptLoader } from './userResponse/prompt-loader';\n\nexport const SDK_VERSION = '0.0.8';\n\nconst DEFAULT_WS_URL = 'wss://ws.superatom.ai/websocket';\n\ntype MessageTypeHandler = (message: IncomingMessage) => void | Promise<void>;\n\nexport class SuperatomSDK {\n private ws: ReturnType<typeof createWebSocket> | null = null;\n private url: string;\n private apiKey?: string;\n private projectId: string;\n private userId: string;\n private type: string;\n private bundleDir: string | undefined;\n private messageHandlers: Map<string, (message: IncomingMessage) => void> = new Map();\n private messageTypeHandlers: Map<string, MessageTypeHandler> = new Map();\n private connected: boolean = false;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = 5;\n private collections: CollectionRegistry = {};\n\tprivate components: Component[] = [];\n private tools: Tool[] = [];\n private anthropicApiKey: string;\n private groqApiKey: string;\n private geminiApiKey: string;\n private openaiApiKey: string;\n private llmProviders: LLMProvider[];\n private databaseType: DatabaseType;\n private userManager: UserManager;\n private dashboardManager: DashboardManager;\n private reportManager: ReportManager;\n\n // Heartbeat properties for keeping WebSocket connection alive\n private pingInterval: NodeJS.Timeout | null = null;\n private lastPong: number = Date.now();\n private readonly PING_INTERVAL_MS = 180000; // 3 minutes\n private readonly PONG_TIMEOUT_MS = 210000; // 3.5 minutes (PING_INTERVAL + 30s grace)\n\n constructor(config: SuperatomSDKConfig) {\n // Set log level if provided in config (overrides environment variable)\n if (config.logLevel) {\n logger.setLogLevel(config.logLevel);\n }\n\n this.apiKey = config.apiKey;\n this.projectId = config.projectId;\n this.userId = config.userId || 'anonymous';\n this.type = config.type || 'data-agent';\n this.bundleDir = config.bundleDir;\n this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;\n this.anthropicApiKey = config.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY || '';\n this.groqApiKey = config.GROQ_API_KEY || process.env.GROQ_API_KEY || '';\n this.geminiApiKey = config.GEMINI_API_KEY || process.env.GEMINI_API_KEY || '';\n this.openaiApiKey = config.OPENAI_API_KEY || process.env.OPENAI_API_KEY || '';\n this.llmProviders = config.LLM_PROVIDERS || getLLMProviders();\n this.databaseType = config.databaseType || 'postgresql';\n logger.info(`Initializing Superatom SDK v${SDK_VERSION} for project ${this.projectId}, llm providers: ${this.llmProviders.join(', ')}, database type: ${this.databaseType}`);\n\n // Initialize UserManager for this SDK instance\n this.userManager = new UserManager(this.projectId, 5000);\n\n // Initialize DashboardManager for this SDK instance\n this.dashboardManager = new DashboardManager(this.projectId);\n\n // Initialize ReportManager for this SDK instance\n this.reportManager = new ReportManager(this.projectId);\n\n // Initialize PromptLoader (load prompts into memory)\n this.initializePromptLoader(config.promptsDir).catch((error) => {\n logger.error('Failed to initialize PromptLoader:', error);\n });\n\n // Initialize UserManager with projectId (startup)\n this.initializeUserManager().catch((error) => {\n logger.error('Failed to initialize UserManager:', error);\n });\n\n // Initialize DashboardManager\n this.initializeDashboardManager();\n\n // Initialize ReportManager\n this.initializeReportManager();\n\n // Note: Connection is not automatic - call connect() explicitly when ready\n }\n\n /**\n * Initialize PromptLoader and load prompts into memory\n * Tries to load from file system first, then falls back to hardcoded prompts\n */\n private async initializePromptLoader(promptsDir?: string): Promise<void> {\n try {\n // Set custom prompts directory if provided\n if (promptsDir) {\n promptLoader.setPromptsDir(promptsDir);\n }\n\n // Set database type for SQL rules loading\n promptLoader.setDatabaseType(this.databaseType);\n\n await promptLoader.initialize();\n logger.info(`PromptLoader initialized with ${promptLoader.getCacheSize()} prompts from ${promptLoader.getPromptsDir()}, database type: ${this.databaseType}`);\n } catch (error) {\n logger.error('Failed to initialize PromptLoader:', error);\n throw error;\n }\n }\n\n /**\n * Initialize UserManager for the project\n */\n private async initializeUserManager(): Promise<void> {\n try {\n await this.userManager.init();\n // Set the global reference for backward compatibility with existing auth code\n setUserManager(this.userManager);\n logger.info(`UserManager initialized for project: ${this.projectId}`);\n } catch (error) {\n logger.error('Failed to initialize UserManager:', error);\n throw error;\n }\n }\n\n /**\n * Get the UserManager instance for this SDK\n */\n public getUserManager(): UserManager {\n return this.userManager;\n }\n\n /**\n * Initialize DashboardManager for the project\n */\n private initializeDashboardManager(): void {\n // Set the global reference for dashboard operations\n setDashboardManager(this.dashboardManager);\n logger.info(`DashboardManager initialized for project: ${this.projectId}`);\n }\n\n /**\n * Get the DashboardManager instance for this SDK\n */\n public getDashboardManager(): DashboardManager {\n return this.dashboardManager;\n }\n\n /**\n * Initialize ReportManager for the project\n */\n private initializeReportManager(): void {\n // Set the global reference for report operations\n setReportManager(this.reportManager);\n logger.info(`ReportManager initialized for project: ${this.projectId}`);\n }\n\n /**\n * Get the ReportManager instance for this SDK\n */\n public getReportManager(): ReportManager {\n return this.reportManager;\n }\n\n /**\n * Connect to the Superatom WebSocket service\n */\n async connect(): Promise<void> {\n // If already connected, return immediately\n if (this.connected && this.ws && this.ws.readyState === this.ws.OPEN) {\n logger.info('Already connected to WebSocket');\n return Promise.resolve();\n }\n\n return new Promise((resolve, reject) => {\n try {\n // Add all required query parameters\n const url = new URL(this.url);\n if (this.apiKey) {\n url.searchParams.set('apiKey', this.apiKey);\n }\n url.searchParams.set('projectId', this.projectId);\n url.searchParams.set('userId', this.userId);\n url.searchParams.set('type', this.type);\n\n logger.info(`Connecting to WebSocket: ${url.toString()}`);\n\n this.ws = createWebSocket(url.toString());\n\n this.ws.addEventListener('open', () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n logger.info('WebSocket connected successfully');\n this.startHeartbeat(); // Start heartbeat to keep connection alive\n resolve();\n });\n\n this.ws.addEventListener('message', (event: any) => {\n this.handleMessage(event.data);\n });\n\n this.ws.addEventListener('error', (error: any) => {\n logger.error('WebSocket error:', error);\n reject(error);\n });\n\n this.ws.addEventListener('close', () => {\n this.connected = false;\n logger.warn('WebSocket closed');\n this.handleReconnect();\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Handle incoming WebSocket messages\n */\n private handleMessage(data: string): void {\n try {\n const parsed = JSON.parse(data);\n const message = IncomingMessageSchema.parse(parsed);\n\n logger.debug('Received message:', message.type);\n\n // Route message by type\n switch (message.type) {\n case 'PONG':\n // Handle heartbeat PONG response\n this.handlePong();\n break;\n\n case 'DATA_REQ':\n handleDataRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle data request:', error);\n });\n break;\n\n case 'BUNDLE_REQ':\n handleBundleRequest(parsed, this.bundleDir, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle bundle request:', error);\n });\n break;\n\n case 'AUTH_LOGIN_REQ':\n handleAuthLoginRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle auth login request:', error);\n });\n break;\n\n case 'AUTH_VERIFY_REQ':\n handleAuthVerifyRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle auth verify request:', error);\n });\n break;\n\n case 'USER_PROMPT_REQ':\n handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools, this.userId).catch((error) => {\n logger.error('Failed to handle user prompt request:', error);\n });\n break;\n\n case 'ACTIONS':\n handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders).catch((error) => {\n logger.error('Failed to handle actions request:', error);\n });\n break;\n\n case 'USER_PROMPT_SUGGESTIONS_REQ':\n handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections, this.userId).catch((error) => {\n logger.error('Failed to handle user prompt suggestions request:', error);\n });\n break;\n\n case 'COMPONENT_LIST_RES':\n handleComponentListResponse(parsed, (com) => this.storeComponents(com), this.collections).catch((error) => {\n logger.error('Failed to handle component list request:', error);\n });\n break;\n\n case 'USERS':\n handleUsersRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle users request:', error);\n });\n break;\n\n case 'DASHBOARDS':\n handleDashboardsRequest(parsed, this.collections, (msg: Message) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle dashboards request:', error);\n });\n break;\n\n case 'REPORTS':\n handleReportsRequest(parsed, this.collections, (msg: Message) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle reports request:', error);\n });\n break;\n\n case 'UIS':\n handleUIsRequest(parsed, this.collections, (msg: Message) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle UIs request:', error);\n });\n break;\n\n case 'BOOKMARKS':\n handleBookmarksRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle bookmarks request:', error);\n });\n break;\n\n case 'KB_NODES':\n handleKbNodesRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle KB nodes request:', error);\n });\n break;\n\n case 'DASH_COMP_REQ':\n handleDashCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {\n logger.error('Failed to handle dash comp request:', error);\n });\n break;\n\n default:\n // Check for custom message type handlers\n const handler = this.messageTypeHandlers.get(message.type);\n if (handler) {\n Promise.resolve(handler(message)).catch((error) => {\n logger.error(`Failed to handle ${message.type}:`, error);\n });\n }\n break;\n }\n\n // Call registered message handlers\n this.messageHandlers.forEach((handler) => {\n handler(message);\n });\n } catch (error) {\n logger.error('Failed to parse incoming message:', error);\n }\n }\n\n /**\n * Send a message to the Superatom service\n */\n send(message: Message): void {\n if (!this.ws || !this.connected) {\n throw new Error('WebSocket is not connected. Call connect() first.');\n }\n\n if (this.ws.readyState !== this.ws.OPEN) {\n throw new Error('WebSocket is not ready to send messages.');\n }\n\n const payload = JSON.stringify(message);\n this.ws.send(payload);\n }\n\n /**\n * Register a message handler to receive all messages\n */\n onMessage(handler: (message: IncomingMessage) => void): () => void {\n const id = Math.random().toString(36).substring(7);\n this.messageHandlers.set(id, handler);\n\n // Return unsubscribe function\n return () => {\n this.messageHandlers.delete(id);\n };\n }\n\n /**\n * Register a handler for a specific message type\n */\n onMessageType(type: string, handler: MessageTypeHandler): () => void {\n this.messageTypeHandlers.set(type, handler);\n\n // Return unsubscribe function\n return () => {\n this.messageTypeHandlers.delete(type);\n };\n }\n\n /**\n * Disconnect from the WebSocket service\n */\n disconnect(): void {\n this.stopHeartbeat(); // Stop heartbeat before disconnecting\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n this.connected = false;\n }\n }\n\n /**\n * Cleanup and disconnect - stops reconnection attempts and closes the connection\n */\n async destroy(): Promise<void> {\n // Stop heartbeat first\n this.stopHeartbeat();\n\n // Prevent further reconnection attempts\n this.maxReconnectAttempts = 0;\n this.reconnectAttempts = 0;\n\n // Clear all message handlers\n this.messageHandlers.clear();\n\n // Clear all collections\n this.collections = {};\n\n // Cleanup UserManager\n try {\n await cleanupUserStorage();\n logger.info('UserManager cleanup completed');\n } catch (error) {\n logger.error('Error during UserManager cleanup:', error);\n }\n\n // Disconnect\n this.disconnect();\n }\n\n /**\n * Check if the SDK is currently connected\n */\n isConnected(): boolean {\n return this.connected && this.ws !== null && this.ws.readyState === this.ws.OPEN;\n }\n\n /**\n * Register a collection handler for data operations\n */\n addCollection<TParams = any, TResult = any>(\n collectionName: string,\n operation: CollectionOperation | string,\n handler: CollectionHandler<TParams, TResult>\n ): void {\n if (!this.collections[collectionName]) {\n this.collections[collectionName] = {};\n }\n this.collections[collectionName][operation] = handler;\n }\n\n private handleReconnect(): void {\n if (this.reconnectAttempts < this.maxReconnectAttempts) {\n this.reconnectAttempts++;\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 10000);\n\n setTimeout(() => {\n logger.info(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);\n this.connect().catch((error) => {\n logger.error('Reconnection failed:', error);\n });\n }, delay);\n } else {\n logger.error('Max reconnection attempts reached');\n }\n }\n\n /**\n * Start heartbeat to keep WebSocket connection alive\n * Sends PING every 3 minutes to prevent idle timeout from cloud infrastructure\n */\n private startHeartbeat(): void {\n this.stopHeartbeat(); // Clear any existing interval\n this.lastPong = Date.now();\n\n this.pingInterval = setInterval(() => {\n if (!this.ws || this.ws.readyState !== this.ws.OPEN) {\n logger.warn('WebSocket not open during heartbeat check, stopping heartbeat');\n this.stopHeartbeat();\n return;\n }\n\n // Check if we received a PONG within the timeout period\n const timeSinceLastPong = Date.now() - this.lastPong;\n if (timeSinceLastPong > this.PONG_TIMEOUT_MS) {\n logger.warn(`No PONG received for ${timeSinceLastPong}ms, connection may be dead. Reconnecting...`);\n this.stopHeartbeat();\n this.ws.close(); // This will trigger handleReconnect via the close event\n return;\n }\n\n // Send PING message\n try {\n const pingMessage: Message = {\n type: 'PING',\n from: { type: this.type },\n payload: { timestamp: Date.now() }\n };\n this.ws.send(JSON.stringify(pingMessage));\n logger.debug('Heartbeat PING sent');\n } catch (error) {\n logger.error('Failed to send PING:', error);\n this.stopHeartbeat();\n this.ws.close();\n }\n }, this.PING_INTERVAL_MS);\n\n logger.info(`Heartbeat started (PING every ${this.PING_INTERVAL_MS / 1000}s)`);\n }\n\n /**\n * Stop the heartbeat interval\n */\n private stopHeartbeat(): void {\n if (this.pingInterval) {\n clearInterval(this.pingInterval);\n this.pingInterval = null;\n logger.debug('Heartbeat stopped');\n }\n }\n\n /**\n * Handle PONG response from server\n */\n private handlePong(): void {\n this.lastPong = Date.now();\n logger.debug('Heartbeat PONG received');\n }\n\n private storeComponents(components: Component[]){\n this.components = components;\n }\n\n /**\n * Set tools for the SDK instance\n */\n public setTools(tools: Tool[]): void {\n this.tools = tools;\n logger.info(`Tools stored in SDK: ${tools.length} tools`);\n }\n\n /**\n * Get the stored tools\n */\n public getTools(): Tool[] {\n return this.tools;\n }\n\n}\n\n// Export types\nexport type { Message, IncomingMessage, SuperatomSDKConfig, CollectionHandler, CollectionOperation, User, UsersData, Tool, DBUIBlock, KbNodesRequestPayload, KbNodesQueryFilters, DatabaseType } from './types';\nexport {LLM} from './llm';\nexport { UserManager } from './auth/user-manager';\nexport { UILogCollector, type CapturedLog } from './utils/log-collector';\nexport { Thread, UIBlock, ThreadManager, type Action } from './threads';\nexport { CleanupService } from './services/cleanup-service';\nexport { STORAGE_CONFIG } from './config/storage';\nexport { CONTEXT_CONFIG } from './config/context';\nexport { logger, type LogLevel } from './utils/logger';\n// LLM Usage Logger for tracking API costs and performance\nexport { llmUsageLogger, type LLMUsageEntry } from './utils/llm-usage-logger';\n// User Prompt Error Logger for capturing detailed error information\nexport { userPromptErrorLogger } from './utils/user-prompt-error-logger';\n// BM25L Reranker for hybrid semantic search\nexport {\n BM25L,\n hybridRerank,\n rerankChromaResults,\n rerankConversationResults,\n type BM25LOptions,\n type HybridSearchOptions,\n type RerankedResult\n} from './utils/bm25l-reranker';","import WebSocket from 'ws';\nimport type { WebSocketLike } from './types';\n\n/**\n * Creates a WebSocket instance for Node.js using the ws package\n */\nexport function createWebSocket(url: string): WebSocketLike {\n return new WebSocket(url) as WebSocketLike;\n}\n","import { z } from 'zod';\n\n// Re-export DBUIBlock for external use\nexport type { DBUIBlock } from './utils/conversation-saver';\n\n// User schema for authentication and management\nexport const UserSchema = z.object({\n username: z.string().min(1, 'Username is required'),\n email: z.string().email('Invalid email format').optional(),\n password: z.string().min(1, 'Password is required'),\n fullname: z.string().optional(),\n role: z.string().optional(),\n userInfo: z.record(z.unknown()).optional(),\n wsIds: z.array(z.string()).optional(), // Only in memory, not persisted to file\n});\n\nexport type User = z.infer<typeof UserSchema>;\n\nexport const UsersDataSchema = z.object({\n users: z.array(UserSchema),\n});\n\nexport type UsersData = z.infer<typeof UsersDataSchema>;\n\n// From/To object schema for WebSocket messages\nexport const MessageParticipantSchema = z.object({\n id: z.string().optional(),\n type: z.string().optional(),\n});\n\nexport type MessageParticipant = z.infer<typeof MessageParticipantSchema>;\n\n// Message schemas for WebSocket communication\nexport const MessageSchema = z.object({\n id: z.string().optional(),\n type: z.string(),\n from: MessageParticipantSchema,\n to: MessageParticipantSchema.optional(),\n payload: z.unknown(),\n});\n\nexport type Message = z.infer<typeof MessageSchema>;\n\nexport const IncomingMessageSchema = z.object({\n id: z.string().optional(),\n type: z.string(),\n from: MessageParticipantSchema,\n to: MessageParticipantSchema.optional(),\n payload: z.unknown(),\n});\n\nexport type IncomingMessage = z.infer<typeof IncomingMessageSchema>;\n\n// Data request/response schemas\nexport const DataRequestPayloadSchema = z.object({\n collection: z.string(),\n op: z.string(),\n params: z.record(z.unknown()).optional(),\n SA_RUNTIME: z.record(z.unknown()).optional(),\n});\n\nexport type DataRequestPayload = z.infer<typeof DataRequestPayloadSchema>;\n\nexport const DataRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('DATA_REQ'),\n payload: DataRequestPayloadSchema,\n});\n\nexport type DataRequestMessage = z.infer<typeof DataRequestMessageSchema>;\n\nexport const AuthLoginRequestPayloadSchema = z.object({\n login_data: z.string(),\n});\n\nexport type AuthLoginRequestPayload = z.infer<typeof AuthLoginRequestPayloadSchema>;\n\nexport const AuthLoginRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('AUTH_LOGIN_REQ'),\n payload: AuthLoginRequestPayloadSchema,\n});\n\nexport type AuthLoginRequestMessage = z.infer<typeof AuthLoginRequestMessageSchema>;\n\nexport const AuthVerifyRequestPayloadSchema = z.object({\n token: z.string(),\n});\n\nexport type AuthVerifyRequestPayload = z.infer<typeof AuthVerifyRequestPayloadSchema>;\n\nexport const AuthVerifyRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('AUTH_VERIFY_REQ'),\n payload: AuthVerifyRequestPayloadSchema,\n});\n\nexport type AuthVerifyRequestMessage = z.infer<typeof AuthVerifyRequestMessageSchema>;\n\nexport const UserPromptRequestPayloadSchema = z.object({\n prompt: z.string(),\n SA_RUNTIME: z.object({\n threadId: z.string(),\n uiBlockId: z.string(),\n }).optional(),\n responseMode: z.enum(['component', 'text']).optional(),\n});\n\nexport type UserPromptRequestPayload = z.infer<typeof UserPromptRequestPayloadSchema>;\n\nexport const UserPromptRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('USER_PROMPT_REQ'),\n payload: UserPromptRequestPayloadSchema,\n});\n\nexport type UserPromptRequestMessage = z.infer<typeof UserPromptRequestMessageSchema>;\n\nexport const UserPromptSuggestionsPayloadSchema = z.object({\n prompt: z.string(),\n limit: z.number().int().positive().default(5),\n similarityThreshold: z.number().min(0).max(1).default(0.4),\n});\n\nexport type UserPromptSuggestionsPayload = z.infer<typeof UserPromptSuggestionsPayloadSchema>;\n\nexport const UserPromptSuggestionsMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('USER_PROMPT_SUGGESTIONS_REQ'),\n payload: UserPromptSuggestionsPayloadSchema,\n});\n\nexport type UserPromptSuggestionsMessage = z.infer<typeof UserPromptSuggestionsMessageSchema>;\n\n\nexport const ComponentPropsSchema = z.object({\n query: z.string().or(z.object({})).optional(),\n title: z.string().optional(),\n description: z.string().optional(),\n config: z.record(z.unknown()).optional(),\n actions: z.array(z.any()).optional(),\n});\n\nexport const ComponentSchema = z.object({\n id: z.string(),\n name: z.string(),\n displayName: z.string().optional(),\n isDisplayComp: z.boolean().optional(),\n type: z.string(),\n description: z.string(),\n props: ComponentPropsSchema,\n category: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n});\n\nexport const ComponentsSchema = z.array(ComponentSchema);\n\nexport type Component = z.infer<typeof ComponentSchema>;\n\nexport const ComponentListResponsePayloadSchema = z.object({\n components: z.array(ComponentSchema),\n});\n\nexport type ComponentListResponsePayload = z.infer<typeof ComponentListResponsePayloadSchema>; \n\nexport const ComponentListResponseMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('COMPONENT_LIST_RES'),\n payload: ComponentListResponsePayloadSchema,\n});\n\nexport type ComponentListResponseMessage = z.infer<typeof ComponentListResponseMessageSchema>;\n\n// Tool schemas\nexport const ToolSchema = z.object({\n id: z.string(),\n name: z.string(),\n description: z.string(),\n params: z.record(z.string()),\n fn: z.function().args(z.any()).returns(z.any())\n});\n\nexport type Tool = z.infer<typeof ToolSchema>;\n\n// Admin User Management Request/Response schemas (Unified)\n\n// Query filters schema for users\nexport const UserQueryFiltersSchema = z.object({\n username: z.string().optional(),\n email: z.string().optional(),\n role: z.string().optional(),\n fullname: z.string().optional(),\n});\n\nexport type UserQueryFilters = z.infer<typeof UserQueryFiltersSchema>;\n\nexport const UsersRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n username: z.string().optional(),\n email: z.string().email('Invalid email format').optional(),\n password: z.string().optional(),\n fullname: z.string().optional(),\n role: z.string().optional(),\n userInfo: z.record(z.unknown()).optional(),\n // Query operation fields\n filters: UserQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type UsersRequestPayload = z.infer<typeof UsersRequestPayloadSchema>;\n\nexport const UsersRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('USERS'),\n payload: UsersRequestPayloadSchema,\n});\n\nexport type UsersRequestMessage = z.infer<typeof UsersRequestMessageSchema>;\n\n// UI Logs schema for tracking user request execution\nexport const UILogsPayloadSchema = z.object({\n logs: z.array(z.object({\n timestamp: z.number(),\n level: z.enum(['info', 'error', 'warn', 'debug']),\n message: z.string(),\n type: z.enum(['explanation', 'query', 'general']).optional(),\n data: z.record(z.unknown()).optional(),\n })),\n});\n\nexport type UILogsPayload = z.infer<typeof UILogsPayloadSchema>;\n\nexport const UILogsMessageSchema = z.object({\n id: z.string(), // uiBlockId\n from: MessageParticipantSchema,\n type: z.literal('UI_LOGS'),\n payload: UILogsPayloadSchema,\n});\n\nexport type UILogsMessage = z.infer<typeof UILogsMessageSchema>;\n\n// Actions request schema - for runtime to send component actions and request next questions\nexport const ActionsRequestPayloadSchema = z.object({\n SA_RUNTIME: z.object({\n threadId: z.string(),\n uiBlockId: z.string(),\n }).optional(),\n});\n\nexport type ActionsRequestPayload = z.infer<typeof ActionsRequestPayloadSchema>;\n\nexport const ActionsRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('ACTIONS'),\n payload: ActionsRequestPayloadSchema,\n});\n\nexport type ActionsRequestMessage = z.infer<typeof ActionsRequestMessageSchema>;\n\n// Collection operation types\nexport type CollectionOperation =\n | 'getMany'\n | 'getOne'\n | 'query'\n | 'mutation'\n | 'updateOne'\n | 'deleteOne'\n | 'createOne';\n\nexport type CollectionHandler<TParams = any, TResult = any> = (\n params: TParams\n) => Promise<TResult> | TResult;\n\nexport interface CollectionRegistry {\n [collectionName: string]: {\n [operation: string]: CollectionHandler;\n };\n}\n\nexport type LLMProvider = 'anthropic' | 'groq' | 'gemini' | 'openai';\n\nimport type { LogLevel } from './utils/logger';\n\nexport type DatabaseType = 'postgresql' | 'mssql' | 'snowflake' | 'mysql';\n\nexport interface SuperatomSDKConfig {\n url?: string;\n apiKey?: string;\n projectId: string;\n userId?: string;\n type?: string;\n bundleDir?: string;\n promptsDir?: string; // Path to custom prompts directory (defaults to .prompts in SDK)\n databaseType?: DatabaseType; // Database type for SQL generation rules (defaults to 'postgresql')\n ANTHROPIC_API_KEY?: string;\n GROQ_API_KEY?: string;\n GEMINI_API_KEY?: string;\n OPENAI_API_KEY?: string;\n LLM_PROVIDERS?: LLMProvider[];\n logLevel?: LogLevel; // Log level for SDK logging (errors, warnings, info, verbose)\n}\n\n// ==================== Dashboard CRUD Message Schemas ====================\n\n// Import DSL types from dashboards module\nimport { DSLRendererPropsSchema } from './dashboards/types';\nexport type { DSLRendererProps } from './dashboards/types';\n\n// Query filters schema for dashboards\nexport const DashboardQueryFiltersSchema = z.object({\n dashboardId: z.string().optional(),\n projectId: z.string().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n name: z.string().optional(),\n published: z.boolean().optional(),\n});\n\nexport type DashboardQueryFilters = z.infer<typeof DashboardQueryFiltersSchema>;\n\n// Dashboard CRUD request payload\nexport const DashboardsRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n dashboardId: z.string().optional(),\n projectId: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n published: z.boolean().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n allowedUsers: z.array(z.number()).optional(),\n dashboard: DSLRendererPropsSchema.optional(),\n // Query operation fields\n filters: DashboardQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type DashboardsRequestPayload = z.infer<typeof DashboardsRequestPayloadSchema>;\n\nexport const DashboardsRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('DASHBOARDS'),\n payload: DashboardsRequestPayloadSchema,\n});\n\nexport type DashboardsRequestMessage = z.infer<typeof DashboardsRequestMessageSchema>;\n\n// ==================== Report CRUD Message Schemas ====================\n\n// Import DSL types from reports module\nimport { DSLRendererPropsSchema as ReportDSLRendererPropsSchema } from './reports/types';\nexport type { DSLRendererProps as ReportDSLRendererProps } from './reports/types';\n\n// Query filters schema for reports\nexport const ReportQueryFiltersSchema = z.object({\n reportId: z.string().optional(),\n projectId: z.string().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n name: z.string().optional(),\n published: z.boolean().optional(),\n});\n\nexport type ReportQueryFilters = z.infer<typeof ReportQueryFiltersSchema>;\n\n// Report CRUD request payload\nexport const ReportsRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n reportId: z.string().optional(),\n projectId: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n published: z.boolean().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n report: ReportDSLRendererPropsSchema.optional(),\n // Query operation fields\n filters: ReportQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type ReportsRequestPayload = z.infer<typeof ReportsRequestPayloadSchema>;\n\nexport const ReportsRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('REPORTS'),\n payload: ReportsRequestPayloadSchema,\n});\n\nexport type ReportsRequestMessage = z.infer<typeof ReportsRequestMessageSchema>;\n\n// ==================== UIs CRUD Message Schemas ====================\n\n// Import DSL types from uis module (same as dashboards)\nimport { DSLRendererPropsSchema as UIDSLRendererPropsSchema } from './dashboards/types';\nexport type { DSLRendererProps as UIDSLRendererProps } from './dashboards/types';\n\n// Query filters schema for UIs\nexport const UIQueryFiltersSchema = z.object({\n uiId: z.string().optional(),\n projectId: z.string().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n name: z.string().optional(),\n});\n\nexport type UIQueryFilters = z.infer<typeof UIQueryFiltersSchema>;\n\n// UI CRUD request payload\nexport const UIsRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n uiId: z.string().optional(),\n projectId: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n ui: UIDSLRendererPropsSchema.optional(),\n // Query operation fields\n filters: UIQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type UIsRequestPayload = z.infer<typeof UIsRequestPayloadSchema>;\n\nexport const UIsRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('UIS'),\n payload: UIsRequestPayloadSchema,\n});\n\nexport type UIsRequestMessage = z.infer<typeof UIsRequestMessageSchema>;\n\n// ==================== UI Block (Conversation History) ====================\n\n/**\n * UIBlock represents a stored conversation response with component and actions\n * Used for semantic search matching in conversation history\n */\nexport const UIBlockSchema = z.object({\n id: z.string().optional(),\n userQuestion: z.string().optional(),\n user_prompt: z.string().optional(), // DB field name\n text: z.string().optional(),\n textResponse: z.string().optional(),\n analysis: z.string().optional(), // DB field name for textResponse\n component: ComponentSchema.optional(), // DB field name / Legacy field\n generatedComponentMetadata: ComponentSchema.optional(), // Actual field used by UIBlock class\n componentData: z.record(z.any()).optional(),\n actions: z.array(z.any()).optional(),\n isFetchingActions: z.boolean().optional(),\n createdAt: z.string().optional(),\n metadata: z.object({\n timestamp: z.number().optional(),\n userPrompt: z.string().optional(),\n similarity: z.number().optional(),\n }).optional(),\n});\n\nexport type UIBlock = z.infer<typeof UIBlockSchema>;\n\n// ==================== Bookmarks CRUD Message Schemas ====================\n\n// DBUIBlock schema for database storage (matches DBUIBlock interface from conversation-saver.ts)\nexport const DBUIBlockSchema = z.object({\n id: z.string(),\n component: z.record(z.string(), z.any()).nullable(),\n analysis: z.string().nullable(),\n user_prompt: z.string(),\n});\n\n// Bookmark data schema\nexport const BookmarkDataSchema = z.object({\n id: z.number().optional(),\n uiblock: DBUIBlockSchema, // Typed JSON object\n created_at: z.string().optional(),\n updated_at: z.string().optional(),\n});\n\nexport type BookmarkData = z.infer<typeof BookmarkDataSchema>;\n\n// Query filters schema for bookmarks\nexport const BookmarkQueryFiltersSchema = z.object({\n userId: z.number().optional(),\n threadId: z.string().optional(),\n name: z.string().optional(),\n});\n\nexport type BookmarkQueryFilters = z.infer<typeof BookmarkQueryFiltersSchema>;\n\n// Bookmarks CRUD request payload\nexport const BookmarksRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n userId: z.number().optional(),\n threadId: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n uiblock: DBUIBlockSchema.optional(),\n // Query operation fields\n filters: BookmarkQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type BookmarksRequestPayload = z.infer<typeof BookmarksRequestPayloadSchema>;\n\nexport const BookmarksRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('BOOKMARKS'),\n payload: BookmarksRequestPayloadSchema,\n});\n\nexport type BookmarksRequestMessage = z.infer<typeof BookmarksRequestMessageSchema>;\n\n// KB Nodes (Knowledge Base) request schema\nexport const KbNodesQueryFiltersSchema = z.object({\n query: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n createdBy: z.number().optional(),\n});\n\nexport type KbNodesQueryFilters = z.infer<typeof KbNodesQueryFiltersSchema>;\n\nexport const KbNodesRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'search', 'getByCategory', 'getByUser', 'getCategories', 'getTags']),\n data: z.object({\n id: z.number().optional(),\n title: z.string().optional(),\n content: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n userId: z.number().optional(),\n // Query/search operation fields\n query: z.string().optional(),\n filters: KbNodesQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n offset: z.number().optional(),\n }).optional(),\n});\n\nexport type KbNodesRequestPayload = z.infer<typeof KbNodesRequestPayloadSchema>;\n\nexport const KbNodesRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('KB_NODES'),\n payload: KbNodesRequestPayloadSchema,\n});\n\nexport type KbNodesRequestMessage = z.infer<typeof KbNodesRequestMessageSchema>;\n\n// ==================== Dashboard Component Request Schema ====================\n\nexport const DashCompRequestPayloadSchema = z.object({\n prompt: z.string(),\n SA_RUNTIME: z.object({\n threadId: z.string().optional(),\n uiBlockId: z.string().optional(),\n }).optional(),\n});\n\nexport type DashCompRequestPayload = z.infer<typeof DashCompRequestPayloadSchema>;\n\nexport const DashCompRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('DASH_COMP_REQ'),\n payload: DashCompRequestPayloadSchema,\n});\n\nexport type DashCompRequestMessage = z.infer<typeof DashCompRequestMessageSchema>;\n\n// ==================== Response Types ====================\n\n// Standard response format for LLM operations\nexport interface T_RESPONSE {\n success: boolean;\n data?: any;\n errors: string[];\n}\n\nexport interface WebSocketLike {\n send(data: string): void;\n close(): void;\n addEventListener(event: string, listener: (event: any) => void): void;\n removeEventListener(event: string, listener: (event: any) => void): void;\n readyState: number;\n CONNECTING: number;\n OPEN: number;\n CLOSING: number;\n CLOSED: number;\n}\n\n","import { z } from 'zod';\n\n// ==================== Dashboard DSL Schemas ====================\n\n// Expression schema for dynamic values\nexport const ExpressionSchema = z.object({\n $exp: z.string(),\n $deps: z.array(z.string()).optional(),\n});\n\nexport type Expression = z.infer<typeof ExpressionSchema>;\n\n// Binding schema for data binding\nexport const BindingSchema = z.object({\n $bind: z.string(),\n $transform: z\n .array(\n z.object({\n name: z.string(),\n args: z.array(z.any()).optional(),\n }),\n )\n .optional(),\n});\n\nexport type Binding = z.infer<typeof BindingSchema>;\n\n// For directive schema\nexport const ForDirectiveSchema = z.object({\n in: z.union([ExpressionSchema, BindingSchema, z.string()]),\n as: z.string(),\n key: z.string().optional(),\n index: z.string().optional(),\n});\n\nexport type ForDirective = z.infer<typeof ForDirectiveSchema>;\n\n// Query specification schema\nexport const QuerySpecSchema = z.object({\n graphql: z.string().optional(),\n sql: z.string().optional(),\n variables: z.record(z.string(), z.any()).optional(),\n params: z.record(z.string(), z.any()).optional(),\n key: z.string().optional(),\n refetchPolicy: z\n .enum(['cache-first', 'network-only', 'cache-and-network'])\n .optional(),\n dependencies: z.array(z.string()).optional(),\n});\n\nexport type QuerySpec = z.infer<typeof QuerySpecSchema>;\n\n// UI Element schema\nexport const UIElementSchema: z.ZodType<any> = z.lazy(() =>\n z.object({\n id: z.string(),\n type: z.string(),\n key: z.union([z.string(), ExpressionSchema]).optional(),\n props: z.record(z.string(), z.any()).optional(),\n query: QuerySpecSchema.optional(),\n if: ExpressionSchema.optional(),\n elseIf: ExpressionSchema.optional(),\n for: ForDirectiveSchema.optional(),\n 'link-to': z\n .union([\n z.string(),\n ExpressionSchema,\n BindingSchema,\n z.object({\n ui: z.union([z.string(), ExpressionSchema, BindingSchema]),\n params: z.record(z.string(), z.any()).optional(),\n }),\n ])\n .optional(),\n _meta: z\n .object({\n id: z.string().optional(),\n version: z.string().optional(),\n created: z.string().optional(),\n lastModified: z.string().optional(),\n })\n .optional(),\n children: z.any().optional(),\n else: UIElementSchema.optional(),\n slots: z\n .record(z.string(), z.union([UIElementSchema, z.array(UIElementSchema)]))\n .optional(),\n platform: z\n .object({\n web: z.any().optional(),\n ios: z.any().optional(),\n android: z.any().optional(),\n })\n .optional(),\n })\n);\n\nexport type UIElement = z.infer<typeof UIElementSchema>;\n\n// Page schema for multi-page dashboards\nexport const PageSchema = z.object({\n id: z.string(),\n name: z.string(),\n order: z.number(),\n icon: z.string().optional(),\n render: UIElementSchema,\n});\n\nexport type Page = z.infer<typeof PageSchema>;\n\n// UI Component schema\nexport const UIComponentSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n props: z.record(z.string(), z.any()).optional(),\n states: z.record(z.string(), z.any()).optional(),\n methods: z\n .record(\n z.string(),\n z.object({\n fn: z.string(),\n params: z.record(z.string(), z.any()).optional(),\n }),\n )\n .optional(),\n effects: z\n .array(\n z.object({\n fn: z.string(),\n deps: z.array(z.string()).optional(),\n }),\n )\n .optional(),\n data: z.record(z.string(), z.any()).optional(),\n render: UIElementSchema.optional(),\n pages: z.array(PageSchema).optional(),\n defaultPageId: z.string().optional(),\n query: QuerySpecSchema.optional(),\n});\n\nexport type UIComponent = z.infer<typeof UIComponentSchema>;\n\n// DSL Renderer Props schema\nexport const DSLRendererPropsSchema = z.object({\n dsl: UIComponentSchema,\n data: z.record(z.string(), z.any()).optional(),\n context: z.record(z.string(), z.any()).optional(),\n});\n\nexport type DSLRendererProps = z.infer<typeof DSLRendererPropsSchema>;\n","import { z } from 'zod';\n\n// ==================== Report DSL Schemas ====================\n\n// Expression schema for dynamic values\nexport const ExpressionSchema = z.object({\n $exp: z.string(),\n $deps: z.array(z.string()).optional(),\n});\n\nexport type Expression = z.infer<typeof ExpressionSchema>;\n\n// Binding schema for data binding\nexport const BindingSchema = z.object({\n $bind: z.string(),\n $transform: z\n .array(\n z.object({\n name: z.string(),\n args: z.array(z.any()).optional(),\n }),\n )\n .optional(),\n});\n\nexport type Binding = z.infer<typeof BindingSchema>;\n\n// For directive schema\nexport const ForDirectiveSchema = z.object({\n in: z.union([ExpressionSchema, BindingSchema, z.string()]),\n as: z.string(),\n key: z.string().optional(),\n index: z.string().optional(),\n});\n\nexport type ForDirective = z.infer<typeof ForDirectiveSchema>;\n\n// Query specification schema\nexport const QuerySpecSchema = z.object({\n graphql: z.string().optional(),\n sql: z.string().optional(),\n variables: z.record(z.string(), z.any()).optional(),\n params: z.record(z.string(), z.any()).optional(),\n key: z.string().optional(),\n refetchPolicy: z\n .enum(['cache-first', 'network-only', 'cache-and-network'])\n .optional(),\n dependencies: z.array(z.string()).optional(),\n});\n\nexport type QuerySpec = z.infer<typeof QuerySpecSchema>;\n\n// UI Element schema\nexport const UIElementSchema: z.ZodType<any> = z.lazy(() =>\n z.object({\n id: z.string(),\n type: z.string(),\n key: z.union([z.string(), ExpressionSchema]).optional(),\n props: z.record(z.string(), z.any()).optional(),\n query: QuerySpecSchema.optional(),\n if: ExpressionSchema.optional(),\n elseIf: ExpressionSchema.optional(),\n for: ForDirectiveSchema.optional(),\n 'link-to': z\n .union([\n z.string(),\n ExpressionSchema,\n BindingSchema,\n z.object({\n ui: z.union([z.string(), ExpressionSchema, BindingSchema]),\n params: z.record(z.string(), z.any()).optional(),\n }),\n ])\n .optional(),\n _meta: z\n .object({\n id: z.string().optional(),\n version: z.string().optional(),\n created: z.string().optional(),\n lastModified: z.string().optional(),\n })\n .optional(),\n children: z.any().optional(),\n else: UIElementSchema.optional(),\n slots: z\n .record(z.string(), z.union([UIElementSchema, z.array(UIElementSchema)]))\n .optional(),\n platform: z\n .object({\n web: z.any().optional(),\n ios: z.any().optional(),\n android: z.any().optional(),\n })\n .optional(),\n })\n);\n\nexport type UIElement = z.infer<typeof UIElementSchema>;\n\n// UI Component schema\nexport const UIComponentSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n props: z.record(z.string(), z.any()).optional(),\n states: z.record(z.string(), z.any()).optional(),\n methods: z\n .record(\n z.string(),\n z.object({\n fn: z.string(),\n params: z.record(z.string(), z.any()).optional(),\n }),\n )\n .optional(),\n effects: z\n .array(\n z.object({\n fn: z.string(),\n deps: z.array(z.string()).optional(),\n }),\n )\n .optional(),\n data: z.record(z.string(), z.any()).optional(),\n render: UIElementSchema,\n query: QuerySpecSchema.optional(),\n});\n\nexport type UIComponent = z.infer<typeof UIComponentSchema>;\n\n// DSL Renderer Props schema\nexport const DSLRendererPropsSchema = z.object({\n dsl: UIComponentSchema,\n data: z.record(z.string(), z.any()).optional(),\n context: z.record(z.string(), z.any()).optional(),\n});\n\nexport type DSLRendererProps = z.infer<typeof DSLRendererPropsSchema>;\n","import { DataRequestMessageSchema, type CollectionRegistry, type Message } from '../types';\nimport { logger } from '../utils/logger';\nimport { ThreadManager } from '../threads';\n\n/**\n * Handle incoming data_req messages and execute collection handlers\n */\nexport async function handleDataRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n const dataRequest = DataRequestMessageSchema.parse(data);\n const { id, payload } = dataRequest;\n const { collection, op, params, SA_RUNTIME } = payload;\n\n // Check if collection and operation exist\n if (!collections[collection]) {\n sendDataResponse(id, collection, op, null, {\n error: `Collection '${collection}' not found`,\n }, sendMessage);\n return;\n }\n\n if (!collections[collection][op]) {\n sendDataResponse(id, collection, op, null, {\n error: `Operation '${op}' not found for collection '${collection}'`,\n }, sendMessage);\n return;\n }\n\n // Execute the handler and measure execution time\n const startTime = performance.now();\n const handler = collections[collection][op];\n const result = await handler(params || {});\n const executionMs = Math.round(performance.now() - startTime);\n\n logger.info(`Executed ${collection}.${op} in ${executionMs}ms`);\n\n // Update UIBlock with component data if SA_RUNTIME has uiBlockId\n if (SA_RUNTIME && typeof SA_RUNTIME === 'object' && 'uiBlockId' in SA_RUNTIME) {\n const uiBlockId = (SA_RUNTIME as any).uiBlockId;\n const threadId = (SA_RUNTIME as any).threadId;\n\n const threadManager = ThreadManager.getInstance();\n let uiBlock = null;\n let thread = null;\n\n // If threadId is provided, get the specific thread\n if (threadId) {\n thread = threadManager.getThread(threadId);\n if (thread) {\n uiBlock = thread.getUIBlock(uiBlockId);\n }\n } else {\n // Otherwise search across all threads\n const result = threadManager.findUIBlockById(uiBlockId);\n if (result) {\n thread = result.thread;\n uiBlock = result.uiBlock;\n }\n }\n\n // Update UIBlock's componentData with a summary (not full result) to save memory\n // The full result is sent to the frontend via WebSocket, no need to store it\n if (uiBlock) {\n // Store only metadata, not the full data to reduce memory usage\n const dataSummary = {\n _dataReceived: true,\n _timestamp: new Date().toISOString(),\n _collection: collection,\n _operation: op,\n _recordCount: Array.isArray(result) ? result.length :\n (result?.data?.length || result?.contacts?.length || result?.salesorders?.length || 'unknown')\n };\n uiBlock.setComponentData(dataSummary);\n logger.info(`Updated UIBlock ${uiBlockId} with data summary from ${collection}.${op} (full data not stored to save memory)`);\n } else {\n logger.warn(`UIBlock ${uiBlockId} not found in threads`);\n }\n }\n\n // Send response\n sendDataResponse(id, collection, op, result, { executionMs }, sendMessage);\n } catch (error) {\n logger.error('Failed to handle data request:', error);\n // Not a data_req message or invalid format\n }\n}\n\n/**\n * Send a data_res response message\n */\nfunction sendDataResponse(\n id: string,\n collection: string,\n op: string,\n data: any,\n meta: { executionMs?: number; error?: string },\n sendMessage: (message: Message) => void\n): void {\n const response: Message = {\n id,\n from: { type: 'data-agent' },\n type: 'DATA_RES',\n payload: {\n collection,\n op,\n data,\n ...meta,\n },\n };\n\n sendMessage(response);\n}\n","import { randomUUID } from 'crypto';\nimport { logger } from '../utils/logger';\nimport { STORAGE_CONFIG } from '../config/storage';\nimport { Action } from './action';\n\n/**\n * UIBlock represents a single user and assistant message block in a thread\n * Contains user question, component metadata, component data, text response, and available actions\n */\nexport class UIBlock {\n private id: string;\n private userQuestion: string;\n private generatedComponentMetadata: Record<string, any>;\n private componentData: Record<string, any>;\n private textResponse: string | null;\n private actions: Action[] | null | Promise<Action[]>;\n private createdAt: Date;\n\n /**\n * Creates a new UIBlock instance\n * @param userQuestion - The user's question or input\n * @param componentData - The component data object\n * @param generatedComponentMetadata - Optional metadata about the generated component\n * @param actions - Optional array of available actions\n * @param id - Optional custom ID, generates UUID if not provided\n * @param textResponse - Optional text response from LLM\n */\n constructor(\n userQuestion: string,\n componentData: Record<string, any> = {},\n generatedComponentMetadata: Record<string, any> = {},\n actions: Action[] = [],\n id?: string,\n textResponse: string | null = null\n ) {\n this.id = id || randomUUID();\n this.userQuestion = userQuestion;\n this.componentData = componentData;\n this.generatedComponentMetadata = generatedComponentMetadata;\n this.actions = actions;\n this.textResponse = textResponse;\n this.createdAt = new Date();\n }\n\n /**\n * Get the UIBlock ID\n */\n getId(): string {\n return this.id;\n }\n\n /**\n * Get the user question\n */\n getUserQuestion(): string {\n return this.userQuestion;\n }\n\n /**\n * Set or update the user question\n */\n setUserQuestion(question: string): void {\n this.userQuestion = question;\n }\n\n /**\n * Get component metadata\n */\n getComponentMetadata(): Record<string, any> {\n return this.generatedComponentMetadata;\n }\n\n getTextResponse(): string {\n return this.textResponse || '';\n }\n\n /**\n * Set or update component metadata\n */\n setComponentMetadata(metadata: Record<string, any>): void {\n this.generatedComponentMetadata = { ...this.generatedComponentMetadata, ...metadata };\n }\n\n /**\n * Get component data\n */\n getComponentData(): Record<string, any> {\n return this.componentData;\n }\n\n /**\n * Calculate size of data in bytes\n */\n private getDataSizeInBytes(data: any): number {\n try {\n const jsonString = JSON.stringify(data);\n return Buffer.byteLength(jsonString, 'utf8');\n } catch (error) {\n logger.error('Error calculating data size:', error);\n return 0;\n }\n }\n\n /**\n * Limit array data to maximum rows\n */\n private limitArrayData(data: any[]): { data: any[]; metadata: any } {\n const totalRows = data.length;\n const limitedData = data.slice(0, STORAGE_CONFIG.MAX_ROWS_PER_BLOCK);\n\n return {\n data: limitedData,\n metadata: {\n totalRows,\n storedRows: limitedData.length,\n isTruncated: totalRows > STORAGE_CONFIG.MAX_ROWS_PER_BLOCK,\n },\n };\n }\n\n /**\n * Check if data exceeds size limit\n */\n private exceedsSizeLimit(data: any): boolean {\n const size = this.getDataSizeInBytes(data);\n return size > STORAGE_CONFIG.MAX_SIZE_PER_BLOCK_BYTES;\n }\n\n /**\n * Process and limit data before storing\n */\n private processDataForStorage(data: any): any {\n // If data is an array, limit rows\n if (Array.isArray(data)) {\n const { data: limitedData, metadata } = this.limitArrayData(data);\n\n // Check size after limiting rows\n const size = this.getDataSizeInBytes(limitedData);\n\n logger.info(\n `UIBlock ${this.id}: Storing ${metadata.storedRows}/${metadata.totalRows} rows (${(size / 1024).toFixed(2)} KB)`\n );\n\n // If still too large, store only metadata\n if (this.exceedsSizeLimit(limitedData)) {\n logger.warn(\n `UIBlock ${this.id}: Data too large (${(size / 1024 / 1024).toFixed(2)} MB), storing metadata only`\n );\n return {\n ...metadata,\n preview: limitedData.slice(0, 3), // Store only first 3 rows as preview\n dataTooLarge: true,\n };\n }\n\n return {\n data: limitedData,\n ...metadata,\n };\n }\n\n // For non-array data, check size\n const size = this.getDataSizeInBytes(data);\n\n if (this.exceedsSizeLimit(data)) {\n logger.warn(\n `UIBlock ${this.id}: Data too large (${(size / 1024 / 1024).toFixed(2)} MB), storing summary only`\n );\n return {\n dataTooLarge: true,\n dataType: typeof data,\n keys: typeof data === 'object' ? Object.keys(data) : undefined,\n };\n }\n\n return data;\n }\n\n /**\n * Set or update component data with size and row limits\n */\n setComponentData(data: Record<string, any>): void {\n const processedData = this.processDataForStorage(data);\n this.componentData = { ...this.componentData, ...processedData };\n }\n\n\n\n /**\n * Set or update text response\n */\n setTextResponse(textResponse: string | null): void {\n this.textResponse = textResponse;\n }\n\n /**\n * Get all actions (only if they are resolved, not if fetching)\n */\n getActions(): Action[] | null | Promise<Action[]> {\n return this.actions;\n }\n\n /**\n * Get or fetch actions\n * If actions don't exist or are a Promise, calls the generateFn and stores the promise\n * If actions already exist, returns them\n * @param generateFn - Async function to generate actions\n * @returns Promise resolving to Action[]\n */\n async getOrFetchActions(generateFn: () => Promise<Action[]>): Promise<Action[]> {\n // If actions already exist and are not a Promise, return them\n\n if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions) && this.actions.length > 0) {\n return this.actions;\n }\n\n // If already fetching, cancel and start new fetch\n // Set new promise for fetching\n const fetchPromise = generateFn();\n this.actions = fetchPromise;\n\n try {\n // Wait for the promise to resolve\n const resolvedActions = await fetchPromise;\n // Store the resolved actions\n logger.info(`Fetched ${resolvedActions.length} actions for UIBlock: ${this.id}`);\n this.actions = resolvedActions;\n return resolvedActions;\n } catch (error) {\n // If generation fails, reset to null\n this.actions = null;\n throw error;\n }\n }\n\n /**\n * Set or replace all actions\n */\n setActions(actions: Action[]): void {\n this.actions = actions;\n }\n\n /**\n * Add a single action (only if actions are resolved)\n */\n addAction(action: Action): void {\n if (this.actions && Array.isArray(this.actions)) {\n this.actions.push(action);\n }\n }\n\n /**\n * Add multiple actions (only if actions are resolved)\n */\n addActions(actions: Action[]): void {\n if (this.actions && Array.isArray(this.actions)) {\n this.actions.push(...actions);\n }\n }\n\n /**\n * Remove an action by ID (only if actions are resolved)\n */\n removeAction(actionId: string): boolean {\n if (this.actions && Array.isArray(this.actions)) {\n const index = this.actions.findIndex(a => a.id === actionId);\n if (index > -1) {\n this.actions.splice(index, 1);\n return true;\n }\n }\n return false;\n }\n\n /**\n * Clear all actions\n */\n clearActions(): void {\n this.actions = null;\n }\n\n /**\n * Get creation timestamp\n */\n getCreatedAt(): Date {\n return this.createdAt;\n }\n\n /**\n * Convert UIBlock to JSON-serializable object\n */\n toJSON(): Record<string, any> {\n // Handle Promise case for serialization\n let actionsValue: Action[] | null = null;\n if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions)) {\n actionsValue = this.actions;\n }\n\n return {\n id: this.id,\n userQuestion: this.userQuestion,\n generatedComponentMetadata: this.generatedComponentMetadata,\n componentData: this.componentData,\n textResponse: this.textResponse,\n actions: actionsValue,\n isFetchingActions: this.actions instanceof Promise,\n createdAt: this.createdAt.toISOString(),\n };\n }\n}\n","/**\n * Configuration for data storage limits in UIBlocks\n */\nexport const STORAGE_CONFIG = {\n /**\n * Maximum number of rows to store in UIBlock data\n */\n MAX_ROWS_PER_BLOCK: 10,\n\n /**\n * Maximum size in bytes per UIBlock (500KB - reduced to save memory)\n */\n MAX_SIZE_PER_BLOCK_BYTES: 500 * 1024, // 500KB\n\n /**\n * Number of days to keep threads before cleanup\n * Note: This is for in-memory storage. Conversations are also persisted to database.\n */\n THREAD_RETENTION_DAYS: 2, // Reduced from 7 to 1 day for memory efficiency\n\n /**\n * Number of days to keep UIBlocks before cleanup\n * Note: This is for in-memory storage. Data is also persisted to database.\n */\n UIBLOCK_RETENTION_DAYS: 2, // Reduced from 7 to 1 day for memory efficiency\n};\n","import { randomUUID } from 'crypto';\nimport { UIBlock } from './uiblock';\n\n/**\n * Thread represents a conversation thread containing multiple UIBlocks\n * Each UIBlock in a thread represents a user question and assistant response pair\n */\nexport class Thread {\n private id: string;\n private uiblocks: Map<string, UIBlock>;\n private createdAt: Date;\n\n /**\n * Creates a new Thread instance\n * @param id - Optional custom ID, generates UUID if not provided\n */\n constructor(id?: string) {\n this.id = id || randomUUID();\n this.uiblocks = new Map();\n this.createdAt = new Date();\n }\n\n /**\n * Get the thread ID\n */\n getId(): string {\n return this.id;\n }\n\n /**\n * Add a UIBlock to the thread\n */\n addUIBlock(uiblock: UIBlock): void {\n this.uiblocks.set(uiblock.getId(), uiblock);\n }\n\n /**\n * Get a UIBlock by ID\n */\n getUIBlock(id: string): UIBlock | undefined {\n return this.uiblocks.get(id);\n }\n\n /**\n * Get all UIBlocks in the thread\n */\n getUIBlocks(): UIBlock[] {\n return Array.from(this.uiblocks.values());\n }\n\n /**\n * Get UIBlocks as a Map\n */\n getUIBlocksMap(): Map<string, UIBlock> {\n return new Map(this.uiblocks);\n }\n\n /**\n * Remove a UIBlock by ID\n */\n removeUIBlock(id: string): boolean {\n return this.uiblocks.delete(id);\n }\n\n /**\n * Check if UIBlock exists\n */\n hasUIBlock(id: string): boolean {\n return this.uiblocks.has(id);\n }\n\n /**\n * Get number of UIBlocks in the thread\n */\n getUIBlockCount(): number {\n return this.uiblocks.size;\n }\n\n /**\n * Clear all UIBlocks from the thread\n */\n clear(): void {\n this.uiblocks.clear();\n }\n\n /**\n * Get creation timestamp\n */\n getCreatedAt(): Date {\n return this.createdAt;\n }\n\n /**\n * Get conversation context from recent UIBlocks (excluding current one)\n * Returns formatted string with previous questions and component summaries\n * @param limit - Maximum number of previous UIBlocks to include (default: 5)\n * @param currentUIBlockId - ID of current UIBlock to exclude from context (optional)\n * @returns Formatted conversation history string\n */\n getConversationContext(limit: number = 5, currentUIBlockId?: string): string {\n if (limit === 0) {\n return '';\n }\n\n // Get all UIBlocks sorted by creation time (oldest first)\n const allBlocks = Array.from(this.uiblocks.values())\n .filter(block => !currentUIBlockId || block.getId() !== currentUIBlockId)\n .sort((a, b) => a.getCreatedAt().getTime() - b.getCreatedAt().getTime());\n\n if (allBlocks.length === 0) {\n return '';\n }\n\n // Take the last N blocks (most recent)\n const recentBlocks = allBlocks.slice(-limit);\n\n // Format as conversation history\n const contextLines: string[] = [];\n\n recentBlocks.forEach((block, index) => {\n const questionNum = index + 1;\n const question = block.getUserQuestion();\n const metadata = block.getComponentMetadata();\n const textResponse = block.getTextResponse();\n\n // Determine what was generated and build appropriate response\n let assistantResponse = '';\n\n // Check if component was generated (metadata exists and has meaningful content)\n const hasComponent = metadata && Object.keys(metadata).length > 0 && metadata.type;\n\n // Check if text response was generated\n const hasTextResponse = textResponse && textResponse.trim().length > 0;\n\n const responseParts: string[] = [];\n\n if (hasComponent) {\n // Component was generated - show component summary\n const parts: string[] = [];\n\n if (metadata.type) {\n parts.push(`Component Type: ${metadata.type}`);\n }\n if (metadata.name) {\n parts.push(`Name: ${metadata.name}`);\n }\n if (metadata.description) {\n parts.push(`Description: ${metadata.description}`);\n }\n if (metadata.props) {\n parts.push(`Props: ${JSON.stringify(metadata.props)}`);\n }\n\n responseParts.push(parts.join('\\n'));\n }\n\n if (hasTextResponse) {\n // Text response was generated - add it to response parts\n responseParts.push(textResponse);\n }\n\n if (responseParts.length > 0) {\n // Join both component and text response if both exist\n assistantResponse = responseParts.join('\\n');\n } else {\n // Nothing was generated\n assistantResponse = 'No response generated';\n }\n\n contextLines.push(`User:\\n ${question}`);\n contextLines.push(`Assistant:\\n ${assistantResponse}`);\n contextLines.push('---'); // Empty line for readability\n });\n\n return contextLines.join('\\n').trim();\n }\n\n /**\n * Convert Thread to JSON-serializable object\n */\n toJSON(): Record<string, any> {\n return {\n id: this.id,\n uiblocks: Array.from(this.uiblocks.values()).map(block => block.toJSON()),\n createdAt: this.createdAt.toISOString(),\n };\n }\n}\n","import { Thread } from './thread';\nimport { UIBlock } from './uiblock';\n\n/**\n * ThreadManager manages all threads globally\n * Provides methods to create, retrieve, and delete threads\n */\nexport class ThreadManager {\n private static instance: ThreadManager;\n private threads: Map<string, Thread>;\n\n private constructor() {\n this.threads = new Map();\n\n // Initialize cleanup service\n // new CleanupService(this.threads);\n }\n\n /**\n * Get singleton instance of ThreadManager\n */\n static getInstance(): ThreadManager {\n if (!ThreadManager.instance) {\n ThreadManager.instance = new ThreadManager();\n }\n return ThreadManager.instance;\n }\n\n /**\n * Create a new thread\n * @param id - Optional custom ID, generates UUID if not provided\n * @returns The created Thread instance\n */\n createThread(id?: string): Thread {\n const thread = new Thread(id);\n this.threads.set(thread.getId(), thread);\n return thread;\n }\n\n /**\n * Get a thread by ID\n */\n getThread(id: string): Thread | undefined {\n return this.threads.get(id);\n }\n\n /**\n * Get all threads\n */\n getAllThreads(): Thread[] {\n return Array.from(this.threads.values());\n }\n\n /**\n * Get threads as a Map\n */\n getThreadsMap(): Map<string, Thread> {\n return new Map(this.threads);\n }\n\n /**\n * Delete a thread by ID\n */\n deleteThread(id: string): boolean {\n return this.threads.delete(id);\n }\n\n /**\n * Check if thread exists\n */\n hasThread(id: string): boolean {\n return this.threads.has(id);\n }\n\n /**\n * Get number of threads\n */\n getThreadCount(): number {\n return this.threads.size;\n }\n\n /**\n * Clear all threads\n */\n clearAll(): void {\n this.threads.clear();\n }\n\n /**\n * Find a UIBlock by ID across all threads\n * @param uiBlockId - The UIBlock ID to search for\n * @returns Object with thread and uiBlock if found, undefined otherwise\n */\n findUIBlockById(uiBlockId: string): { thread: Thread; uiBlock: UIBlock } | undefined {\n for (const thread of this.threads.values()) {\n const uiBlock = thread.getUIBlock(uiBlockId);\n if (uiBlock) {\n return { thread, uiBlock };\n }\n }\n return undefined;\n }\n\n /**\n * Convert all threads to JSON-serializable object\n */\n toJSON(): Record<string, any> {\n return {\n threads: Array.from(this.threads.values()).map(thread => thread.toJSON()),\n count: this.threads.size,\n };\n }\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { logger } from './utils/logger';\n\n/**\n * Get the bundle directory from config or environment variable\n */\nexport function getBundleDir(configDir?: string): string {\n const bundleDir = configDir || process.env.SA_BUNDLE_DIR;\n\n if (!bundleDir) {\n throw new Error(\n 'Bundle directory not configured. Please provide bundleDir in config or set SA_BUNDLE_DIR environment variable.'\n );\n }\n\n return bundleDir;\n}\n\n/**\n * Load the JavaScript bundle from the configured directory\n */\nexport function getJS(bundleDir: string): string {\n try {\n // Check if directory exists\n if (!fs.existsSync(bundleDir)) {\n throw new Error(`Bundle directory does not exist: ${bundleDir}`);\n }\n\n // Check if it's actually a directory\n const stats = fs.statSync(bundleDir);\n if (!stats.isDirectory()) {\n throw new Error(`Bundle path is not a directory: ${bundleDir}`);\n }\n\n // Read directory contents\n let files: string[];\n try {\n files = fs.readdirSync(bundleDir);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read bundle directory: ${errorMessage}`);\n }\n\n // Find the bundle file\n const indexFile = files.find((file) => file.startsWith('index-') && file.endsWith('.js'));\n\n if (!indexFile) {\n logger.warn(`Available files in ${bundleDir}:`, files);\n throw new Error(\n `Could not find index-*.js file in ${bundleDir}. ` +\n `Expected a file matching pattern: index-*.js`\n );\n }\n\n // Read the bundle file\n const filePath = path.join(bundleDir, indexFile);\n logger.info(`Loading bundle from ${filePath}`);\n\n try {\n return fs.readFileSync(filePath, 'utf8');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read bundle file: ${errorMessage}`);\n }\n } catch (error) {\n if (error instanceof Error) {\n logger.error('Failed to load bundle:', error.message);\n } else {\n logger.error('Failed to load bundle:', error);\n }\n throw error;\n }\n}\n","import { getJS, getBundleDir } from '../bundle';\nimport { logger } from '../utils/logger';\nimport type { Message } from '../types';\n\nconst CHUNK_SIZE = 900 * 1024; // 900 KB chunks (leaving room for metadata, max 1MB per message)\n\n/**\n * Handle incoming bundle_req messages and send chunked bundle response\n */\nexport async function handleBundleRequest(\n data: any,\n bundleDir: string | undefined,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n const id = data.id || 'unknown';\n const fromId = data.from?.id;\n\n // Get bundle directory and load bundle\n const dir = getBundleDir(bundleDir);\n const js = getJS(dir);\n const bundleSize = Buffer.byteLength(js, 'utf8');\n\n logger.info(`Bundle size: ${(bundleSize / 1024).toFixed(2)} KB`);\n\n // Split bundle into chunks\n const totalChunks = Math.ceil(bundleSize / CHUNK_SIZE);\n logger.info(`Splitting bundle into ${totalChunks} chunks`);\n\n for (let i = 0; i < totalChunks; i++) {\n const start = i * CHUNK_SIZE;\n const end = Math.min(start + CHUNK_SIZE, js.length);\n const chunk = js.substring(start, end);\n const isComplete = i === totalChunks - 1;\n const progress = ((i + 1) / totalChunks) * 100;\n\n const chunkMessage: Message = {\n id: `${id}-chunk-${i}`,\n type: 'BUNDLE_CHUNK',\n from: { type: 'data-agent' },\n to: fromId ? { id: fromId } : undefined,\n payload: {\n chunk: chunk,\n chunkIndex: i,\n totalChunks: totalChunks,\n isComplete: isComplete,\n progress: parseFloat(progress.toFixed(2)),\n },\n };\n\n sendMessage(chunkMessage);\n logger.debug(`Sent chunk ${i + 1}/${totalChunks} (${progress.toFixed(2)}%)`);\n }\n\n logger.info('Bundle sending complete');\n } catch (error) {\n logger.error('Failed to handle bundle request:', error);\n\n // Send error response\n const errorMessage: Message = {\n id: data.id || 'unknown',\n type: 'BUNDLE_RES',\n from: { type: 'data-agent' },\n to: data.from?.id ? { id: data.from.id } : undefined,\n payload: {\n error: error instanceof Error ? error.message : 'Unknown error',\n },\n };\n\n sendMessage(errorMessage);\n }\n}\n","import crypto from 'crypto';\n\n/**\n * Decode base64 encoded string and parse JSON\n * @param base64Data - Base64 encoded string\n * @returns Parsed JSON object\n */\nexport function decodeBase64ToJson(base64Data: string): any {\n try {\n const decodedString = Buffer.from(base64Data, 'base64').toString('utf-8');\n return JSON.parse(decodedString);\n } catch (error) {\n throw new Error(`Failed to decode base64 data: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\n/**\n * Hash password using SHA1\n * @param password - Plain text password\n * @returns SHA1 hashed password\n */\nexport function hashPassword(password: string): string {\n return crypto.createHash('sha1').update(password).digest('hex');\n}\n","import { UserManager } from './user-manager';\nimport { type User, type UsersData } from '../types';\nimport { logger } from '../utils/logger';\n\n// Global reference to the current SDK's UserManager instance\nlet currentUserManager: UserManager | null = null;\n\n/**\n * Set the UserManager instance (called by SuperatomSDK during initialization)\n * This should be called with the SDK's UserManager instance\n * @param userManager - UserManager instance from SuperatomSDK\n */\nexport function setUserManager(userManager: UserManager): void {\n if (!userManager) {\n throw new Error('userManager cannot be null');\n }\n currentUserManager = userManager;\n logger.debug('UserManager instance set');\n}\n\n/**\n * Get the current UserManager instance\n */\nexport function getUserManager(): UserManager {\n if (!currentUserManager) {\n throw new Error(\n 'UserManager not initialized. Make sure SuperatomSDK is initialized before using user storage.'\n );\n }\n return currentUserManager;\n}\n\n/**\n * Load users from memory (UserManager maintains the cache)\n * @returns UsersData object containing all users\n */\nexport function loadUsers(): UsersData {\n const manager = getUserManager();\n return {\n users: manager.getAllUsers()\n };\n}\n\n/**\n * Save users to file immediately (forces sync)\n * @param usersData - UsersData object to save\n */\nexport async function saveUsers(usersData: UsersData): Promise<void> {\n const manager = getUserManager();\n\n // Clear existing users and repopulate\n manager.deleteAllUsers();\n\n // Add all users from the provided data\n for (const user of usersData.users) {\n try {\n manager.createUser(user);\n } catch (error) {\n // User might already exist, update instead\n if (manager.userExists(user.username)) {\n manager.updateUser(user.username, user);\n }\n }\n }\n\n // Force immediate sync to file\n await manager.forceSync();\n}\n\n/**\n * Find a user by username\n * @param username - Username to search for\n * @returns User object if found, null otherwise\n */\nexport function findUserByUsername(username: string): User | null {\n const manager = getUserManager();\n const user = manager.getUser(username);\n return user || null;\n}\n\n/**\n * Find a user by email\n * @param email - Email to search for\n * @returns User object if found, null otherwise\n */\nexport function findUserByEmail(email: string): User | null {\n const manager = getUserManager();\n const user = manager.getUserByEmail(email);\n return user || null;\n}\n\n/**\n * Find a user by username or email\n * @param identifier - Username or email to search for\n * @returns User object if found, null otherwise\n */\nexport function findUserByUsernameOrEmail(identifier: string): User | null {\n const manager = getUserManager();\n const user = manager.getUserByUsernameOrEmail(identifier);\n return user || null;\n}\n\n/**\n * Add WebSocket ID to a user's wsIds array\n * @param username - Username to update\n * @param wsId - WebSocket ID to add\n * @returns true if successful, false otherwise\n */\nexport function addWsIdToUser(username: string, wsId: string): boolean {\n try {\n const manager = getUserManager();\n return manager.addWsId(username, wsId);\n } catch (error) {\n logger.error('Error adding WebSocket ID:', error);\n return false;\n }\n}\n\n/**\n * Remove WebSocket ID from a user's wsIds array\n * @param username - Username to update\n * @param wsId - WebSocket ID to remove\n * @returns true if successful, false otherwise\n */\nexport function removeWsIdFromUser(username: string, wsId: string): boolean {\n try {\n const manager = getUserManager();\n return manager.removeWsId(username, wsId);\n } catch (error) {\n logger.error('Error removing WebSocket ID:', error);\n return false;\n }\n}\n\n/**\n * Cleanup and destroy the UserManager\n */\nexport async function cleanupUserStorage(): Promise<void> {\n if (currentUserManager) {\n await currentUserManager.destroy();\n currentUserManager = null;\n logger.info('UserManager cleaned up');\n }\n}\n\n// Export types\nexport type { User, UsersData } from '../types';\n","import { findUserByUsernameOrEmail, addWsIdToUser } from \"./user-storage\";\nimport { hashPassword } from \"./utils\";\nimport { logger } from \"../utils/logger\";\nimport type { CollectionRegistry } from \"../types\";\n\nexport interface LoginCredentials {\n username?: string;\n email?: string;\n password: string;\n}\n\nexport interface ValidationResult {\n success: boolean;\n error?: string;\n data?: any;\n username?: string;\n userId?: number;\n}\n\n/**\n * Validate user credentials against database first, then file storage as fallback\n * @param credentials - Login credentials with username/email and password\n * @param collections - Optional collection registry for database lookup\n * @returns ValidationResult indicating success or failure\n */\nexport async function validateUser(\n credentials: LoginCredentials,\n collections?: CollectionRegistry\n): Promise<ValidationResult> {\n const { username, email, password } = credentials;\n const identifier = username || email;\n\n logger.debug('[validateUser] Starting user validation');\n logger.debug(`[validateUser] Username provided: ${username ? '✓' : '✗'}, Email provided: ${email ? '✓' : '✗'}, Password provided: ${password ? '✓' : '✗'}`);\n\n // Check if identifier (username or email) and password are provided\n if (!identifier || !password) {\n logger.warn('[validateUser] Validation failed: Username/email and password are required');\n return {\n success: false,\n error: 'Username or email and password are required'\n };\n }\n\n // Try database lookup first if collections are available\n if (collections && collections['users'] && collections['users']['authenticate']) {\n logger.debug(`[validateUser] Attempting database authentication for: ${identifier}`);\n try {\n const dbResult = await collections['users']['authenticate']({\n identifier,\n password\n });\n\n logger.info('[validateUser] Database authentication attempt completed', dbResult);\n\n if (dbResult && dbResult.success && dbResult.data) {\n logger.info(`[validateUser] ✓ User authenticated via database: ${dbResult.data.username}`);\n return {\n success: true,\n data: dbResult.data.username,\n username: dbResult.data.username,\n userId: dbResult.data.id\n };\n } else {\n logger.debug(`[validateUser] Database auth failed for ${identifier}: ${dbResult?.error || 'Invalid credentials'}`);\n // Don't fall back to file if DB explicitly says invalid credentials\n if (dbResult && dbResult.error === 'Invalid credentials') {\n return {\n success: false,\n error: 'Invalid credentials'\n };\n }\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.debug(`[validateUser] Database lookup error: ${errorMsg}, falling back to file storage`);\n }\n } else {\n logger.debug('[validateUser] No users collection available, using file storage only');\n }\n\n // Fall back to file-based validation\n logger.info(`[validateUser] Attempting file-based validation for: ${identifier}`);\n\n // Find user by username or email from in-memory cache\n const user = findUserByUsernameOrEmail(identifier);\n\n if (!user) {\n logger.warn(`[validateUser] Validation failed: User not found - ${identifier}`);\n return {\n success: false,\n error: 'Invalid username or email'\n };\n }\n\n logger.debug(`[validateUser] User found in file storage: ${user.username}, verifying password`);\n\n // Hash the stored password and compare with provided password\n const hashedPassword = hashPassword(user.password);\n\n if (hashedPassword !== password) {\n logger.warn(`[validateUser] Validation failed: Invalid password for user - ${user.username}`);\n logger.debug(`[validateUser] Password hash mismatch for user: ${user.username}`);\n return {\n success: false,\n error: 'Invalid password'\n };\n }\n\n logger.info(`[validateUser] ✓ User validated via file storage: ${user.username}`);\n return {\n success: true,\n data: user.username,\n username: user.username\n };\n}\n\n/**\n * Authenticate user and store WebSocket ID\n * Uses database first via collections, then falls back to file storage\n * @param credentials - Login credentials\n * @param wsId - WebSocket ID to store\n * @param collections - Optional collection registry for database lookup\n * @returns ValidationResult with authentication status\n */\nexport async function authenticateAndStoreWsId(\n credentials: LoginCredentials,\n wsId: string,\n collections?: CollectionRegistry\n): Promise<ValidationResult> {\n const identifier = credentials.username || credentials.email;\n logger.debug('[authenticateAndStoreWsId] Starting authentication and WebSocket ID storage');\n\n // Validate user credentials first\n logger.debug('[authenticateAndStoreWsId] Validating user credentials');\n const validationResult = await validateUser(credentials, collections);\n\n if (!validationResult.success) {\n logger.warn(`[authenticateAndStoreWsId] User validation failed for: ${identifier}`);\n return validationResult;\n }\n\n // Use the username from validation result (guaranteed to exist if validation succeeded)\n const username = validationResult.username!;\n logger.info(`[authenticateAndStoreWsId] User ${username} validated, storing WebSocket ID`);\n\n // Store wsId in user's wsIds array using UserManager\n // Changes are automatically synced to file via setInterval\n logger.debug(`[authenticateAndStoreWsId] Calling addWsIdToUser for ${username}`);\n addWsIdToUser(username, wsId);\n\n logger.debug(`[authenticateAndStoreWsId] WebSocket ID ${wsId} associated with user ${username}`);\n return validationResult;\n}\n\n/**\n * Verify authentication token\n * @param authToken - Base64 encoded auth token containing username and password\n * @param collections - Optional collection registry for database lookup\n * @returns ValidationResult indicating if token is valid\n */\nexport async function verifyAuthToken(\n authToken: string,\n collections?: CollectionRegistry\n): Promise<ValidationResult> {\n try {\n logger.debug('[verifyAuthToken] Starting token verification');\n\n // Decode base64 token\n logger.debug('[verifyAuthToken] Decoding base64 token');\n const decodedString = Buffer.from(authToken, 'base64').toString('utf-8');\n\n logger.debug('[verifyAuthToken] Parsing decoded token as JSON');\n const credentials = JSON.parse(decodedString);\n\n logger.debug('[verifyAuthToken] Token decoded and parsed successfully');\n logger.debug(`[verifyAuthToken] Token contains username: ${credentials.username ? '✓' : '✗'}`);\n\n // Validate credentials\n logger.debug('[verifyAuthToken] Validating credentials from token');\n const result = await validateUser(credentials, collections);\n\n if (result.success) {\n logger.info(`[verifyAuthToken] ✓ Token verified successfully for user: ${credentials.username || 'unknown'}`);\n } else {\n logger.warn(`[verifyAuthToken] Token verification failed: ${result.error}`);\n }\n\n return result;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(`[verifyAuthToken] Failed to verify auth token: ${errorMsg}`);\n logger.debug('[verifyAuthToken] Token verification error details:', error);\n\n return {\n success: false,\n error: 'Invalid token format'\n };\n }\n}\n","import { decodeBase64ToJson } from \"../auth/utils\";\nimport { authenticateAndStoreWsId } from \"../auth/validator\";\nimport { AuthLoginRequestMessageSchema, Message, CollectionRegistry } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\n\nexport async function handleAuthLoginRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n logger.debug('[AUTH_LOGIN_REQ] Parsing incoming auth login request');\n const authRequest = AuthLoginRequestMessageSchema.parse(data);\n const { id, payload } = authRequest;\n\n const login_data = payload.login_data;\n\n const wsId = authRequest.from.id ;\n\n logger.info(`[AUTH_LOGIN_REQ ${id}] Processing auth login request from client: ${wsId}`);\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Login data present: ${!!login_data}`);\n\n if(!login_data){\n logger.error(`[AUTH_LOGIN_REQ ${id}] Login data not found in request`);\n sendDataResponse(id, {\n success: false,\n error: 'Login data not found'\n }, sendMessage, wsId);\n return;\n }\n\n\n // Decode base64 data and parse JSON\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Decoding base64 login data`);\n let loginData: any;\n try {\n loginData = decodeBase64ToJson(login_data);\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Login data decoded successfully`);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(`[AUTH_LOGIN_REQ ${id}] Failed to decode login data: ${errorMsg}`);\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Decode error details:`, error);\n sendDataResponse(id, {\n success: false,\n error: 'Invalid login data format'\n }, sendMessage, wsId);\n return;\n }\n\n // Extract username/email and password from decoded data\n const { username, email, password } = loginData;\n const identifier = username || email;\n\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Validating credentials - username: ${username ? '✓' : '✗'}, email: ${email ? '✓' : '✗'}, password: ${password ? '✓' : '✗'}`);\n\n if (!identifier) {\n logger.error(`[AUTH_LOGIN_REQ ${id}] Username or email not found in login data`);\n sendDataResponse(id, {\n success: false,\n error: 'Username or email is required'\n }, sendMessage, wsId);\n return;\n }\n\n if (!password) {\n logger.error(`[AUTH_LOGIN_REQ ${id}] Password not found in login data`);\n sendDataResponse(id, {\n success: false,\n error: 'Password not found in login data'\n }, sendMessage, wsId);\n return;\n }\n\n\n if(!wsId){\n logger.error(`[AUTH_LOGIN_REQ ${id}] WebSocket ID not found in request`);\n sendDataResponse(id, {\n success: false,\n error: 'WebSocket ID not found'\n }, sendMessage, wsId);\n return;\n }\n\n logger.info(`[AUTH_LOGIN_REQ ${id}] Credentials validated, authenticating user: ${identifier} username: ${username} email: ${email} password: ${password}`);\n\n // Authenticate user and store wsId\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Calling authenticateAndStoreWsId for user: ${identifier}`);\n const authResult = await authenticateAndStoreWsId(\n { username, email, password },\n wsId,\n collections\n );\n\n logger.info(`[AUTH_LOGIN_REQ ${id}] Authentication result for ${identifier}: ${authResult.success ? 'success' : 'failed'}`);\n if (!authResult.success) {\n logger.warn(`[AUTH_LOGIN_REQ ${id}] Authentication failed for ${identifier}: ${authResult.error}`);\n } else {\n logger.info(`[AUTH_LOGIN_REQ ${id}] User ${authResult.username || identifier} authenticated successfully`);\n }\n\n // Send response\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Sending auth response to client`);\n sendDataResponse(id, authResult, sendMessage, wsId);\n\n logger.info(`[AUTH_LOGIN_REQ ${id}] ${authResult.success ? '✓' : '✗'} Auth login request completed`);\n return ;\n }\n catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n logger.error(`[AUTH_LOGIN_REQ] Failed to handle auth login request: ${errorMessage}`);\n logger.debug(`[AUTH_LOGIN_REQ] Error stack trace:`, errorStack);\n\n // Try to send error response\n try {\n const parsedData = data as any;\n if (parsedData?.id) {\n sendDataResponse(parsedData.id, {\n success: false,\n error: `Internal error: ${errorMessage}`\n }, sendMessage, parsedData.from?.id);\n }\n } catch (sendError) {\n logger.error('[AUTH_LOGIN_REQ] Failed to send error response:', sendError);\n }\n }\n}\n\n\n/**\n * Send a data_res response message\n */\nfunction sendDataResponse(\n id: string,\n res: {success: boolean; error?: string; data?: any},\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id,\n type: 'AUTH_LOGIN_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: clientId\n },\n payload:{\n ...res,\n }\n };\n\n logger.debug(`[AUTH_LOGIN_RES ${id}] Sending ${res.success ? 'successful' : 'failed'} auth response to client: ${clientId}`);\n logger.debug(`[AUTH_LOGIN_RES ${id}] Response payload size: ${JSON.stringify(response).length} bytes`);\n\n if (res.error) {\n logger.debug(`[AUTH_LOGIN_RES ${id}] Error message: ${res.error}`);\n }\n\n sendMessage(response);\n}\n\n","import { verifyAuthToken } from \"../auth/validator\";\nimport { AuthVerifyRequestMessageSchema, Message, CollectionRegistry } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\nexport async function handleAuthVerifyRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n logger.debug('[AUTH_VERIFY_REQ] Parsing incoming auth verify request');\n const authRequest = AuthVerifyRequestMessageSchema.parse(data);\n const { id, payload } = authRequest;\n\n const token = payload.token;\n\n const wsId = authRequest.from.id ;\n\n logger.info(`[AUTH_VERIFY_REQ ${id}] Processing auth verify request from client: ${wsId}`);\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Token present: ${!!token}`);\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Token length: ${token ? token.length : 0} characters`);\n\n if(!token){\n logger.error(`[AUTH_VERIFY_REQ ${id}] Token not found in request`);\n sendDataResponse(id, {\n success: false,\n error: 'Token not found'\n }, sendMessage, wsId);\n return;\n }\n\n\n if(!wsId){\n logger.error(`[AUTH_VERIFY_REQ ${id}] WebSocket ID not found in request`);\n sendDataResponse(id, {\n success: false,\n error: 'WebSocket ID not found'\n }, sendMessage, wsId);\n return;\n }\n\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token validation starting`);\n logger.debug(`[AUTH_VERIFY_REQ ${id}] WebSocket ID: ${wsId}`);\n\n // Verify token\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Calling verifyAuthToken`);\n const startTime = Date.now();\n\n const authResult = await verifyAuthToken(token, collections);\n\n const verificationTime = Date.now() - startTime;\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token verification completed in ${verificationTime}ms - ${authResult.success ? 'valid' : 'invalid'}`);\n\n if (!authResult.success) {\n logger.warn(`[AUTH_VERIFY_REQ ${id}] Token verification failed: ${authResult.error}`);\n } else {\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token verified successfully for user: ${authResult.data || 'unknown'}`);\n }\n\n // Send response\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Sending verification response to client`);\n sendDataResponse(id, authResult, sendMessage, wsId);\n\n logger.info(`[AUTH_VERIFY_REQ ${id}] ${authResult.success ? '✓' : '✗'} Auth verify request completed`);\n return ;\n }\n catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n logger.error(`[AUTH_VERIFY_REQ] Failed to handle auth verify request: ${errorMessage}`);\n logger.debug(`[AUTH_VERIFY_REQ] Error stack trace:`, errorStack);\n\n // Try to send error response\n try {\n const parsedData = data as any;\n if (parsedData?.id) {\n sendDataResponse(parsedData.id, {\n success: false,\n error: `Internal error: ${errorMessage}`\n }, sendMessage, parsedData.from?.id);\n }\n } catch (sendError) {\n logger.error('[AUTH_VERIFY_REQ] Failed to send error response:', sendError);\n }\n }\n}\n\n/**\n * Send a data_res response message\n */\nfunction sendDataResponse(\n id: string,\n res: {success: boolean; error?: string; data?: any},\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id,\n type: 'AUTH_VERIFY_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: clientId\n },\n payload:{\n ...res,\n }\n };\n\n logger.debug(`[AUTH_VERIFY_RES ${id}] Sending ${res.success ? 'successful' : 'failed'} verification response to client: ${clientId}`);\n logger.debug(`[AUTH_VERIFY_RES ${id}] Response payload size: ${JSON.stringify(response).length} bytes`);\n\n if (res.error) {\n logger.debug(`[AUTH_VERIFY_RES ${id}] Error message: ${res.error}`);\n }\n\n if (res.data) {\n logger.debug(`[AUTH_VERIFY_RES ${id}] User verified: ${res.data}`);\n }\n\n sendMessage(response);\n} ","import dotenv from 'dotenv';\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\n\ndotenv.config();\n\nexport interface GroqLLMConfig extends BaseLLMConfig {}\n\n/**\n * GroqLLM class for handling AI-powered component generation and matching using Groq\n */\nexport class GroqLLM extends BaseLLM {\n\tconstructor(config?: GroqLLMConfig) {\n\t\tsuper(config);\n\t}\n\n\tprotected getDefaultModel(): string {\n\t\treturn 'groq/openai/gpt-oss-120b';\n\t}\n\n\tprotected getDefaultFastModel(): string {\n\t\t// Llama 3.1 8B is extremely fast and cheap on Groq\n\t\treturn 'groq/llama-3.1-8b-instant';\n\t}\n\n\tprotected getDefaultApiKey(): string | undefined {\n\t\treturn process.env.GROQ_API_KEY;\n\t}\n\n\tprotected getProviderName(): string {\n\t\treturn 'Groq';\n\t}\n}\n\n// Export a singleton instance\nexport const groqLLM = new GroqLLM();\n","import { Component, T_RESPONSE } from '../types';\nimport { ensureQueryLimit, fixScalarSubqueries, convertQuestionsToActions } from './utils';\nimport { schema } from './schema';\nimport { promptLoader } from './prompt-loader';\nimport { LLM } from '../llm';\nimport { logger } from '../utils/logger';\nimport { userPromptErrorLogger } from '../utils/user-prompt-error-logger';\nimport type { Action } from '../threads/action';\nimport KB from './knowledge-base';\nimport ConversationSearch from './conversation-search';\n\nexport interface BaseLLMConfig {\n\tmodel?: string;\n\tfastModel?: string; // Cheaper/faster model for simple tasks (classification, matching, actions)\n\tdefaultLimit?: number;\n\tapiKey?: string;\n}\n\n/**\n * BaseLLM abstract class for AI-powered component generation and matching\n * Provides common functionality for all LLM providers\n */\nexport abstract class BaseLLM {\n\tprotected model: string;\n\tprotected fastModel: string; // Used for classification, matching, actions (cheaper)\n\tprotected defaultLimit: number;\n\tprotected apiKey?: string;\n\n\tconstructor(config?: BaseLLMConfig) {\n\t\tthis.model = config?.model || this.getDefaultModel();\n\t\tthis.fastModel = config?.fastModel || this.getDefaultFastModel();\n\t\tthis.defaultLimit = config?.defaultLimit || 50;\n\t\tthis.apiKey = config?.apiKey;\n\t}\n\n\t/**\n\t * Get the default model for this provider (used for complex tasks like text generation)\n\t */\n\tprotected abstract getDefaultModel(): string;\n\n\t/**\n\t * Get the default fast model for this provider (used for simple tasks: classification, matching, actions)\n\t * Should return a cheaper/faster model like Haiku for Anthropic\n\t */\n\tprotected abstract getDefaultFastModel(): string;\n\n\t/**\n\t * Get the default API key from environment\n\t */\n\tprotected abstract getDefaultApiKey(): string | undefined;\n\n\t/**\n\t * Get the provider name (for logging)\n\t */\n\tprotected abstract getProviderName(): string;\n\n\t/**\n\t * Get the API key (from instance, parameter, or environment)\n\t */\n\tprotected getApiKey(apiKey?: string): string | undefined {\n\t\treturn apiKey || this.apiKey || this.getDefaultApiKey();\n\t}\n\n\t/**\n\t * Check if a component contains a Form (data_modification component)\n\t * Forms have hardcoded defaultValues that become stale when cached\n\t * This checks both single Form components and Forms inside MultiComponentContainer\n\t */\n\tprotected containsFormComponent(component: any): boolean {\n\t\tif (!component) return false;\n\n\t\t// Check if this component itself is a Form\n\t\tif (component.type === 'Form' || component.name === 'DynamicForm') {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check if this is a Container with nested components\n\t\tif (component.type === 'Container' || component.name === 'MultiComponentContainer') {\n\t\t\tconst nestedComponents = component.props?.config?.components || [];\n\t\t\tfor (const nested of nestedComponents) {\n\t\t\t\tif (nested.type === 'Form' || nested.name === 'DynamicForm') {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\n\t/**\n\t * Match components from text response suggestions and generate follow-up questions\n\t * Takes a text response with component suggestions (c1:type format) and matches with available components\n\t * Also generates title, description, and intelligent follow-up questions (actions) based on the analysis\n\t * All components are placed in a default MultiComponentContainer layout\n\t * @param analysisContent - The text response containing component suggestions\n\t * @param components - List of available components\n\t * @param apiKey - Optional API key\n\t * @param logCollector - Optional log collector\n\t * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified\n\t * @returns Object containing matched components, layout title/description, and follow-up actions\n\t */\n\tasync matchComponentsFromAnalysis(\n\t\tanalysisContent: string,\n\t\tcomponents: Component[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tcomponentStreamCallback?: (component: Component) => void,\n\t\tdeferredTools?: any[],\n\t\texecutedTools?: any[]\n\t): Promise<{\n\t\tcomponents: Component[];\n\t\tlayoutTitle: string;\n\t\tlayoutDescription: string;\n\t\tactions: Action[];\n\t}> {\n\t\ttry {\n\t\t\tlogger.debug(`[${this.getProviderName()}] Starting component matching from text response`);\n\n\t\t\t// Format available components for the prompt\n\t\t\tlet availableComponentsText = 'No components available';\n\t\t\tif (components && components.length > 0) {\n\t\t\t\tavailableComponentsText = components\n\t\t\t\t\t.map((comp, idx) => {\n\t\t\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\n\t\t\t\t\t\tconst propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : 'No props';\n\t\t\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\n Name: ${comp.name}\n Type: ${comp.type}\n Description: ${comp.description || 'No description'}\n Keywords: ${keywords}\n Props Structure: ${propsPreview}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join('\\n\\n');\n\t\t\t}\n\n\t\t\t// Format deferred tools for Form generation\n\t\t\tlet deferredToolsText = 'No deferred external tools for this request.';\n\t\t\tif (deferredTools && deferredTools.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools to component matching`);\n\t\t\t\tdeferredToolsText = 'The following external tools need user input via a Form component.\\n' +\n\t\t\t\t\t'**IMPORTANT: Use these EXACT values when generating Form externalTool prop.**\\n\\n' +\n\t\t\t\t\tdeferredTools.map((tool, idx) => {\n\t\t\t\t\t\treturn `${idx + 1}. **${tool.name}**\n toolId: \"${tool.id}\" (USE THIS EXACT VALUE - do not modify!)\n toolName: \"${tool.name}\"\n parameters: ${JSON.stringify(tool.params || {})}\n requiredFields:\n${JSON.stringify(tool.requiredFields || [], null, 2)}`;\n\t\t\t\t\t}).join('\\n\\n');\n\t\t\t}\n\n\t\t\t// Format executed tools for data visualization components\n\t\t\tlet executedToolsText = 'No external tools were executed for data fetching.';\n\t\t\tif (executedTools && executedTools.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Passing ${executedTools.length} executed tools to component matching`);\n\t\t\t\texecutedToolsText = 'The following external tools were executed to fetch data.\\n' +\n\t\t\t\t\t'**IMPORTANT: For components displaying this data, use externalTool prop instead of query.**\\n' +\n\t\t\t\t\t'**IMPORTANT: Use the result data to populate deferred tool parameters when applicable.**\\n\\n' +\n\t\t\t\t\texecutedTools.map((tool, idx) => {\n\t\t\t\t\t\t// Format result - limit size to avoid token overflow\n\t\t\t\t\t\tlet resultPreview = 'No result data';\n\t\t\t\t\t\tif (tool.result) {\n\t\t\t\t\t\t\tconst resultStr = typeof tool.result === 'string' ? tool.result : JSON.stringify(tool.result, null, 2);\n\t\t\t\t\t\t\t// Limit result preview to first 2000 chars to avoid token overflow\n\t\t\t\t\t\t\tresultPreview = resultStr.length > 2000 ? resultStr.substring(0, 2000) + '\\n... (truncated)' : resultStr;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn `${idx + 1}. **${tool.name}**\n toolId: \"${tool.id}\" (USE THIS EXACT VALUE for externalTool.toolId)\n toolName: \"${tool.name}\" (USE THIS EXACT VALUE for externalTool.toolName)\n parameters: ${JSON.stringify(tool.params || {})} (USE THESE for externalTool.parameters)\n result: ${resultPreview}`;\n\t\t\t\t\t}).join('\\n\\n');\n\t\t\t}\n\n\t\t\t// Get schema documentation for query generation\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t\t// Get database-specific SQL rules\n\t\t\tconst databaseRules = await promptLoader.loadDatabaseRules();\n\n\t\t\tlogger.file('\\n=============================\\nText analysis response:', analysisContent);\n\t\t\tlogger.file('\\n=============================\\nDeferred tools:', deferredToolsText);\n\t\t\tlogger.file('\\n=============================\\nExecuted tools:', executedToolsText);\n\t\t\tconst prompts = await promptLoader.loadPrompts('match-text-components', {\n\t\t\t\tANALYSIS_CONTENT: analysisContent,\n\t\t\t\tAVAILABLE_COMPONENTS: availableComponentsText,\n\t\t\t\tSCHEMA_DOC: schemaDoc,\n\t\t\t\tDATABASE_RULES: databaseRules,\n\t\t\t\tDEFERRED_TOOLS: deferredToolsText,\n\t\t\t\tEXECUTED_TOOLS: executedToolsText\n\t\t\t});\n\n\t\t\tlogger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);\n\t\t\tlogger.file('\\n=============================\\nmatch text components system prompt:', prompts.system);\n\n\t\t\tlogCollector?.info('Matching components from text response...');\n\n\t\t\t// Partial JSON streaming to extract answerComponent as soon as it's available\n\t\t\tlet fullResponseText = '';\n\t\t\tlet answerComponentExtracted = false;\n\n\t\t\t// Streaming callback to detect and extract answerComponent early\n\t\t\t// Capture componentStreamCallback in closure\n\t\t\tconst answerCallback = componentStreamCallback;\n\t\t\tconst partialCallback = answerCallback ? (chunk: string) => {\n\t\t\t\tfullResponseText += chunk;\n\n\t\t\t\t// Only try to extract answerComponent if we haven't already and if we have a callback\n\t\t\t\tif (!answerComponentExtracted && answerCallback) {\n\t\t\t\t\t// Check if hasAnswerComponent is true first\n\t\t\t\t\tconst hasAnswerComponentMatch = fullResponseText.match(/\"hasAnswerComponent\"\\s*:\\s*(true|false)/);\n\t\t\t\t\tif (!hasAnswerComponentMatch || hasAnswerComponentMatch[1] !== 'true') {\n\t\t\t\t\t\treturn; // No answer component or not true yet\n\t\t\t\t\t}\n\n\t\t\t\t\t// Look for \"answerComponent\": { and extract the complete object\n\t\t\t\t\tconst answerComponentStartMatch = fullResponseText.match(/\"answerComponent\"\\s*:\\s*\\{/);\n\t\t\t\t\tif (!answerComponentStartMatch) {\n\t\t\t\t\t\treturn; // answerComponent field not found yet\n\t\t\t\t\t}\n\n\t\t\t\t\t// Find the start position of the object\n\t\t\t\t\tconst startPos = answerComponentStartMatch.index! + answerComponentStartMatch[0].length - 1; // Position of opening {\n\n\t\t\t\t\t// Track brace depth to find the matching closing brace\n\t\t\t\t\tlet braceDepth = 0;\n\t\t\t\t\tlet inString = false;\n\t\t\t\t\tlet escapeNext = false;\n\t\t\t\t\tlet endPos = -1;\n\n\t\t\t\t\tfor (let i = startPos; i < fullResponseText.length; i++) {\n\t\t\t\t\t\tconst char = fullResponseText[i];\n\n\t\t\t\t\t\tif (escapeNext) {\n\t\t\t\t\t\t\tescapeNext = false;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (char === '\\\\') {\n\t\t\t\t\t\t\tescapeNext = true;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (char === '\"') {\n\t\t\t\t\t\t\tinString = !inString;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!inString) {\n\t\t\t\t\t\t\tif (char === '{') {\n\t\t\t\t\t\t\t\tbraceDepth++;\n\t\t\t\t\t\t\t} else if (char === '}') {\n\t\t\t\t\t\t\t\tbraceDepth--;\n\t\t\t\t\t\t\t\tif (braceDepth === 0) {\n\t\t\t\t\t\t\t\t\tendPos = i + 1;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (endPos > startPos) {\n\t\t\t\t\t\t// We found the complete answerComponent object\n\t\t\t\t\t\tconst answerComponentString = fullResponseText.substring(startPos, endPos);\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst answerComponentData = JSON.parse(answerComponentString);\n\n\t\t\t\t\t\t\tif (answerComponentData && answerComponentData.componentId) {\n\t\t\t\t\t\t\t\t// Find the component and build it\n\t\t\t\t\t\t\t\tconst originalComponent = components.find(c => c.id === answerComponentData.componentId);\n\n\t\t\t\t\t\t\t\tif (originalComponent) {\n\t\t\t\t\t\t\t\t\tconst answerComponent: Component = {\n\t\t\t\t\t\t\t\t\t\t...originalComponent,\n\t\t\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\t\t\t...originalComponent.props,\n\t\t\t\t\t\t\t\t\t\t\t...answerComponentData.props\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\tconst streamTime = new Date().toISOString();\n\t\t\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type}) - STREAMING TO FRONTEND NOW`);\n\t\t\t\t\t\t\t\t\tlogCollector?.info(`✓ Answer component: ${answerComponent.name} (${answerComponent.type}) - streaming to frontend at ${streamTime}`);\n\n\t\t\t\t\t\t\t\t\tif (answerComponentData.props?.query) {\n\t\t\t\t\t\t\t\t\t\tlogCollector?.logQuery(\n\t\t\t\t\t\t\t\t\t\t\t'Answer component query',\n\t\t\t\t\t\t\t\t\t\t\tanswerComponentData.props.query,\n\t\t\t\t\t\t\t\t\t\t\t{ componentName: answerComponent.name, componentType: answerComponent.type, reasoning: answerComponentData.reasoning }\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// STREAM ANSWER COMPONENT IMMEDIATELY\n\t\t\t\t\t\t\t\t\tanswerCallback(answerComponent);\n\t\t\t\t\t\t\t\t\tanswerComponentExtracted = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t// JSON not complete or malformed, will try again with more data\n\t\t\t\t\t\t\tlogger.debug(`[${this.getProviderName()}] Partial answerComponent parse failed, waiting for more data...`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} : undefined;\n\n\t\t\t// Let LLM.stream handle JSON parsing automatically, but also use partial callback\n\t\t// Use full model for component matching (requires complex SQL generation and prop mapping)\n\t\t\tconst result = await LLM.stream<any>(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t\tmaxTokens: 8192,\n\t\t\t\t\ttemperature: 0.2,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey),\n\t\t\t\t\tpartial: partialCallback\n\t\t\t\t},\n\t\t\t\ttrue // Parse as JSON\n\t\t\t) as any;\n\n\t\t\tlogger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);\n\n\t\t\t// Extract component suggestions from text analysis (format: c1:type : reasoning)\n\t\t\tconst componentSuggestionPattern = /c\\d+:(\\w+)\\s*:\\s*(.+)/g;\n\t\t\tconst suggestedComponents = [];\n\t\t\tlet match;\n\t\t\twhile ((match = componentSuggestionPattern.exec(analysisContent)) !== null) {\n\t\t\t\tsuggestedComponents.push({\n\t\t\t\t\ttype: match[1],\n\t\t\t\t\treasoning: match[2].trim()\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst matchedComponents = result.matchedComponents || [];\n\t\t\tconst layoutTitle = result.layoutTitle || 'Dashboard';\n\t\t\tconst layoutDescription = result.layoutDescription || 'Multi-component dashboard';\n\n\t\t\tlogger.info(`[${this.getProviderName()}] 📊 Component Suggestions from Text Analysis: ${suggestedComponents.length}`);\n\t\t\tsuggestedComponents.forEach((comp, idx) => {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] c${idx + 1}: ${comp.type} - ${comp.reasoning}`);\n\t\t\t});\n\n\t\t\tlogger.info(`[${this.getProviderName()}] 📦 Matched Components from LLM: ${matchedComponents.length}`);\n\t\t\tmatchedComponents.forEach((comp: any, idx: number) => {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || 'N/A'}`);\n\t\t\t});\n\n\t\t\tlogger.file('\\n=============================\\nFull LLM response:', JSON.stringify(result, null, 2));\n\t\t\t// Convert question strings to Action objects]\n\t\t\tconst rawActions = result.actions || [];\n\t\t\tconst actions = convertQuestionsToActions(rawActions);\n\n\t\t\tlogger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);\n\t\t\tlogger.info(`[${this.getProviderName()}] Layout title: \"${layoutTitle}\"`);\n\t\t\tlogger.info(`[${this.getProviderName()}] Layout description: \"${layoutDescription}\"`);\n\t\t\tlogger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);\n\n\t\t\t// Log component suggestions vs matched components\n\t\t\tif (suggestedComponents.length > 0) {\n\t\t\t\tlogCollector?.info(`📝 Text Analysis suggested ${suggestedComponents.length} dashboard components:`);\n\t\t\t\tsuggestedComponents.forEach((comp, idx) => {\n\t\t\t\t\tlogCollector?.info(` c${idx + 1}: ${comp.type} - ${comp.reasoning}`);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Log matched components\n\t\t\tif (matchedComponents.length > 0) {\n\t\t\t\tlogCollector?.info(`📦 Matched ${matchedComponents.length} components for dashboard`);\n\t\t\t\tif (suggestedComponents.length !== matchedComponents.length) {\n\t\t\t\t\tlogCollector?.warn(`⚠️ Component count mismatch: Suggested ${suggestedComponents.length}, but matched ${matchedComponents.length}`);\n\t\t\t\t}\n\t\t\t\tlogCollector?.info(`Dashboard: \"${layoutTitle}\"`);\n\t\t\t\tmatchedComponents.forEach((comp: any, idx: number) => {\n\t\t\t\t\tlogCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);\n\t\t\t\t\tif (comp.props?.query) {\n\t\t\t\t\t\tlogCollector?.logQuery(\n\t\t\t\t\t\t\t`Component ${idx + 1} query`,\n\t\t\t\t\t\t\tcomp.props.query,\n\t\t\t\t\t\t\t{ componentName: comp.componentName, title: comp.props.title }\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Log generated actions\n\t\t\tif (actions.length > 0) {\n\t\t\t\tlogCollector?.info(`Generated ${actions.length} follow-up questions`);\n\t\t\t\tactions.forEach((action: Action, idx: number) => {\n\t\t\t\t\tlogCollector?.info(` ${idx + 1}. ${action.name}`);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Build final component objects with full metadata\n\t\t\tconst finalComponents: Component[] = matchedComponents.map((mc: any) => {\n\t\t\t\t// Find the original component from the list to preserve all metadata\n\t\t\t\tconst originalComponent = components.find(c => c.id === mc.componentId);\n\n\t\t\t\tif (!originalComponent) {\n\t\t\t\t\tlogger.warn(`[${this.getProviderName()}] Component ${mc.componentId} not found in available components`);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Merge generated props with original component\n\t\t\t\treturn {\n\t\t\t\t\t...originalComponent,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...originalComponent.props,\n\t\t\t\t\t\t...mc.props\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}).filter(Boolean) as Component[];\n\n\t\t\treturn {\n\t\t\t\tcomponents: finalComponents,\n\t\t\t\tlayoutTitle,\n\t\t\t\tlayoutDescription,\n\t\t\t\tactions\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error matching components: ${errorMsg}`);\n\t\t\tlogCollector?.error(`Failed to match components: ${errorMsg}`);\n\n\t\t\t// Return empty results on error\n\t\t\treturn {\n\t\t\t\tcomponents: [],\n\t\t\t\tlayoutTitle: 'Dashboard',\n\t\t\t\tlayoutDescription: 'Failed to generate dashboard',\n\t\t\t\tactions: []\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Classify user question into category and detect external tools needed\n\t * Determines if question is for data analysis, requires external tools, or needs text response\n\t */\n\tasync classifyQuestionCategory(\n\t\tuserPrompt: string,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string,\n\t\texternalTools?: any[]\n\t): Promise<{\n\t\tcategory: 'data_analysis' | 'data_modification' | 'general';\n\t\texternalTools: Array<{\n\t\t\ttype: string;\n\t\t\tname: string;\n\t\t\tdescription: string;\n\t\t\tparameters: Record<string, any>;\n\t\t}>;\n\t\tdataAnalysisType?: 'visualization' | 'calculation' | 'comparison' | 'trend';\n\t\treasoning: string;\n\t\tconfidence: number;\n\t}> {\n\t\ttry {\n\t\t\t// Get database schema documentation - CRITICAL for proper category classification\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t\t// Format available external tools for the system prompt\n\t\t\tconst availableToolsDoc = externalTools && externalTools.length > 0\n\t\t\t\t? externalTools.map(tool => {\n\t\t\t\t\tconst paramsStr = Object.entries(tool.params || {})\n\t\t\t\t\t\t.map(([key, type]) => `${key}: ${type}`)\n\t\t\t\t\t\t.join(', ');\n\t\t\t\t\treturn `- **${tool.name}** (id: ${tool.id})\\n Description: ${tool.description}\\n Parameters: ${paramsStr}`;\n\t\t\t\t}).join('\\n\\n')\n\t\t\t\t: 'No external tools available';\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('category-classification', {\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation',\n\t\t\t\tAVAILABLE_TOOLS: availableToolsDoc,\n\t\t\t\tSCHEMA_DOC: schemaDoc || 'No database schema available'\n\t\t\t});\n\n\t\t\t// Use fast model for classification (simple task, cheaper)\n\t\t\tconst result = await LLM.stream<any>(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmodel: this.fastModel,\n\t\t\t\t\tmaxTokens: 1500,\n\t\t\t\t\ttemperature: 0.2,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\n\t\t\t\t},\n\t\t\t\ttrue // Parse as JSON\n\t\t\t) as any;\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'Question category classified',\n\t\t\t\tresult.reasoning || 'No reasoning provided',\n\t\t\t\t{\n\t\t\t\t\tcategory: result.category,\n\t\t\t\t\texternalTools: result.externalTools || [],\n\t\t\t\t\tdataAnalysisType: result.dataAnalysisType,\n\t\t\t\t\tconfidence: result.confidence\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tcategory: result.category || 'data_analysis',\n\t\t\t\texternalTools: result.externalTools || [],\n\t\t\t\tdataAnalysisType: result.dataAnalysisType,\n\t\t\t\treasoning: result.reasoning || 'No reasoning provided',\n\t\t\t\tconfidence: result.confidence || 0\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error classifying question category: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Category classification error details:`, error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Adapt UI block parameters based on current user question\n\t * Takes a matched UI block from semantic search and modifies its props to answer the new question\n\t */\n\tasync adaptUIBlockParameters(\n\t\tcurrentUserPrompt: string,\n\t\toriginalUserPrompt: string,\n\t\tmatchedUIBlock: any,\n\t\tapiKey?: string,\n\t\tlogCollector?: any\n\t): Promise<{\n\t\tsuccess: boolean;\n\t\tadaptedComponent?: Component;\n\t\tparametersChanged?: Array<{ field: string; reason: string }>;\n\t\texplanation: string;\n\t}> {\n\t\ttry {\n\t\t\t// Support both old format (generatedComponentMetadata) and new format (component)\n\t\t\tconst component = matchedUIBlock?.generatedComponentMetadata || matchedUIBlock?.component;\n\n\t\t\tif (!matchedUIBlock || !component) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\texplanation: 'No component found in matched UI block'\n\t\t\t\t};\n\t\t\t}\n\n\t\t// Get schema documentation for query adaptation\n\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t// Get database-specific SQL rules\n\t\tconst databaseRules = await promptLoader.loadDatabaseRules();\n\n\t\tconst prompts = await promptLoader.loadPrompts('adapt-ui-block-params', {\n\t\t\tORIGINAL_USER_PROMPT: originalUserPrompt,\n\t\t\tCURRENT_USER_PROMPT: currentUserPrompt,\n\t\t\tMATCHED_UI_BLOCK_COMPONENT: JSON.stringify(component, null, 2),\n\t\t\tCOMPONENT_PROPS: JSON.stringify(component.props, null, 2),\n\t\t\tSCHEMA_DOC: schemaDoc || 'No schema available',\n\t\t\tDATABASE_RULES: databaseRules\n\t\t});\n\n\t\t\tconst result = await LLM.stream<any>(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t\tmaxTokens: 3000,\n\t\t\t\t\ttemperature: 0.2,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\n\t\t\t\t},\n\t\t\t\ttrue // Parse as JSON\n\t\t\t) as any;\n\n\t\t\tif (!result.success) {\n\t\t\t\tlogger.info(\n\t\t\t\t\t`[${this.getProviderName()}] Could not adapt UI block: ${result.reason}`\n\t\t\t\t);\n\t\t\t\tlogCollector?.warn(\n\t\t\t\t\t'Could not adapt matched UI block',\n\t\t\t\t\t'explanation',\n\t\t\t\t\t{ reason: result.reason }\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\texplanation: result.explanation || 'Adaptation not possible'\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Ensure query has proper LIMIT clause if modified\n\t\t\tif (result.adaptedComponent?.props?.query) {\n\t\t\t\tresult.adaptedComponent.props.query = ensureQueryLimit(\n\t\t\t\t\tresult.adaptedComponent.props.query,\n\t\t\t\t\tthis.defaultLimit\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'UI block parameters adapted',\n\t\t\t\tresult.explanation || 'Parameters adapted successfully',\n\t\t\t\t{\n\t\t\t\t\tparametersChanged: result.parametersChanged || [],\n\t\t\t\t\tcomponentType: result.adaptedComponent?.type\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tadaptedComponent: result.adaptedComponent,\n\t\t\t\tparametersChanged: result.parametersChanged,\n\t\t\t\texplanation: result.explanation || 'Parameters adapted successfully'\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error adapting UI block parameters: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Adaptation error details:`, error);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\texplanation: `Error adapting parameters: ${errorMsg}`\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Generate text-based response for user question\n\t * This provides conversational text responses instead of component generation\n\t * Supports tool calling for query execution with automatic retry on errors (max 3 attempts)\n\t * After generating text response, if components are provided, matches suggested components\n\t * @param streamCallback - Optional callback function to receive text chunks as they stream\n\t * @param collections - Collection registry for executing database queries via database.execute\n\t * @param components - Optional list of available components for matching suggestions\n\t * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called\n\t * @param category - Question category ('data_analysis' | 'data_modification' | 'general'). For data_modification, answer component streaming is skipped. For general, component generation is skipped entirely.\n\t */\n\tasync generateTextResponse(\n\t\tuserPrompt: string,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string,\n\t\tstreamCallback?: (chunk: string) => void,\n\t\tcollections?: any,\n\t\tcomponents?: Component[],\n\t\texternalTools?: any[],\n\t\tcategory?: 'data_analysis' | 'data_modification' | 'general'\n\t): Promise<T_RESPONSE> {\n\t\tconst errors: string[] = [];\n\n\t\tlogger.debug(`[${this.getProviderName()}] Starting text response generation`);\n\t\tlogger.debug(`[${this.getProviderName()}] User prompt: \"${userPrompt.substring(0, 50)}...\"`);\n\n\t\ttry {\n\t\t\t// Step 1: Format available external tools for the system prompt\n\t\t\t// Separate tools by execution type\n\t\t\tlet availableToolsDoc = 'No external tools are available for this request.';\n\t\t\tif (externalTools && externalTools.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] External tools available: ${externalTools.map(t => t.name).join(', ')}`);\n\n\t\t\t\t// Separate immediate and deferred tools\n\t\t\t\tconst immediateTools = externalTools.filter(t => t.executionType === 'immediate' || (t.executionType === 'deferred' && t.userProvidedData));\n\t\t\t\tconst deferredTools = externalTools.filter(t => t.executionType === 'deferred' && !t.userProvidedData);\n\n\t\t\t\tlet toolsDocParts: string[] = [];\n\n\t\t\t\t// Document IMMEDIATE tools (to be executed)\n\t\t\t\tif (immediateTools.length > 0) {\n\t\t\t\t\tconst immediateDoc = '## IMMEDIATE EXECUTION TOOLS\\n' +\n\t\t\t\t\t\t'Execute these tools right away:\\n\\n' +\n\t\t\t\t\t\timmediateTools.map((tool, idx) => {\n\t\t\t\t\t\t\tconst paramsText = Object.entries(tool.params || {})\n\t\t\t\t\t\t\t\t.map(([key, value]) => {\n\t\t\t\t\t\t\t\t\tconst valueType = typeof value;\n\t\t\t\t\t\t\t\t\tif (valueType === 'string' && ['string', 'number', 'integer', 'boolean', 'array', 'object'].includes(String(value).toLowerCase())) {\n\t\t\t\t\t\t\t\t\t\treturn `- ${key}: ${value}`;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn `- ${key}: ${JSON.stringify(value)} (default value - use this)`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.join('\\n ');\n\n\t\t\t\t\t\t\t// If deferred tool with user data, include the data\n\t\t\t\t\t\t\tlet userDataText = '';\n\t\t\t\t\t\t\tif (tool.userProvidedData) {\n\t\t\t\t\t\t\t\tuserDataText = '\\n **User Provided Data** (use these values):\\n ' +\n\t\t\t\t\t\t\t\t\tObject.entries(tool.userProvidedData)\n\t\t\t\t\t\t\t\t\t\t.map(([key, value]) => `- ${key}: ${JSON.stringify(value)}`)\n\t\t\t\t\t\t\t\t\t\t.join('\\n ');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn `${idx + 1}. **${tool.name}** (ID: ${tool.id})\\n Execution Type: IMMEDIATE\\n Description: ${tool.description}\\n Parameters:\\n ${paramsText}${userDataText}`;\n\t\t\t\t\t\t}).join('\\n\\n');\n\t\t\t\t\ttoolsDocParts.push(immediateDoc);\n\t\t\t\t}\n\n\t\t\t\t// Document DEFERRED tools (need user input - will generate Form)\n\t\t\t\tif (deferredTools.length > 0) {\n\t\t\t\t\tconst deferredDoc = '## DEFERRED TOOLS (DO NOT EXECUTE)\\n' +\n\t\t\t\t\t\t'These tools need user input. A Form component will be generated to collect the data.\\n' +\n\t\t\t\t\t\t'**DO NOT call these tools.** Instead, acknowledge the request and inform user that a form will be shown.\\n\\n' +\n\t\t\t\t\t\tdeferredTools.map((tool, idx) => {\n\t\t\t\t\t\t\tconst requiredFieldsText = (tool.requiredFields || [])\n\t\t\t\t\t\t\t\t.map((f: any) => `- ${f.label || f.name} (${f.type})${f.required ? ' *required*' : ''}`)\n\t\t\t\t\t\t\t\t.join('\\n ');\n\n\t\t\t\t\t\t\treturn `${idx + 1}. **${tool.name}** (ID: ${tool.id})\\n Execution Type: DEFERRED (needs form input)\\n Description: ${tool.description}\\n Reason: ${tool.executionReason || 'Write operation requires user confirmation'}\\n Required Fields:\\n ${requiredFieldsText || '(fields will be determined by form)'}`;\n\t\t\t\t\t\t}).join('\\n\\n');\n\t\t\t\t\ttoolsDocParts.push(deferredDoc);\n\t\t\t\t}\n\n\t\t\t\tavailableToolsDoc = toolsDocParts.join('\\n\\n---\\n\\n');\n\t\t\t}\n\n\t\t\t// Get schema documentation\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t\t// Get database-specific SQL rules\n\t\t\tconst databaseRules = await promptLoader.loadDatabaseRules();\n\n\t\t\t// Get relevant knowledge base context (best match only)\n\t\t\tconst knowledgeBaseContext = await KB.getKnowledgeBase({\n\t\t\t\tprompt: userPrompt,\n\t\t\t\tcollections,\n\t\t\t\ttopK: 1\n\t\t\t});\n\n\t\t\tlogger.file('\\n=============================\\nknowledge base context:', knowledgeBaseContext);\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('text-response', {\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation',\n\t\t\t\tSCHEMA_DOC: schemaDoc,\n\t\t\t\tDATABASE_RULES: databaseRules,\n\t\t\t\tKNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || 'No additional knowledge base context available.',\n\t\t\t\tAVAILABLE_EXTERNAL_TOOLS: availableToolsDoc\n\t\t\t});\n\n\t\t\tlogger.file('\\n=============================\\nsystem prompt:', prompts.system);\n\t\t\tlogger.file('\\n=============================\\nuser prompt:', prompts.user);\n\n\t\t\tlogger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);\n\n\t\t\tlogCollector?.info('Generating text response with query execution capability...');\n\n\t\t\t// Define tools: execute_query + external tools identified by category classification\n\t\t\tconst tools = [{\n\t\t\t\tname: 'execute_query',\n\t\t\t\tdescription: 'Executes a parameterized SQL query against the database. CRITICAL: NEVER hardcode literal values in WHERE/HAVING conditions - ALWAYS use $paramName placeholders and pass actual values in params object.',\n\t\t\t\tinput_schema: {\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tsql: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: 'SQL query with $paramName placeholders for ALL literal values in WHERE/HAVING conditions. NEVER hardcode values like WHERE status = \\'Delivered\\' - instead use WHERE status = $status. Table names, column names, and SQL keywords stay as-is.'\n\t\t\t\t\t\t},\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tdescription: 'REQUIRED when SQL has WHERE/HAVING conditions. Maps each $paramName placeholder (without $) to its actual value. Pattern: WHERE col = $name → params: { \"name\": \"value\" }. Every placeholder in SQL MUST have a corresponding entry here.',\n\t\t\t\t\t\t\tadditionalProperties: true\n\t\t\t\t\t\t},\n\t\t\t\t\t\treasoning: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: 'Brief explanation of what this query does and why it answers the user\\'s question.'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\trequired: ['sql'],\n\t\t\t\t\tadditionalProperties: false\n\t\t\t\t}\n\t\t\t}];\n\n\t\t\t// Add external tools to the tools array (if any were identified by category classification)\n\t\t\t// IMPORTANT: Only add tools that should be executed (immediate OR deferred with user data)\n\t\t\tif (externalTools && externalTools.length > 0) {\n\t\t\t\t// Filter to only executable tools\n\t\t\t\tconst executableTools = externalTools.filter(t =>\n\t\t\t\t\tt.executionType === 'immediate' || (t.executionType === 'deferred' && t.userProvidedData)\n\t\t\t\t);\n\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Executable tools: ${executableTools.length} of ${externalTools.length} total`);\n\n\t\t\t\texecutableTools.forEach(tool => {\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Processing executable tool:`, JSON.stringify(tool, null, 2));\n\t\t\t\t\tconst properties: any = {};\n\t\t\t\t\tconst required: string[] = [];\n\n\t\t\t\t\tObject.entries(tool.params || {}).forEach(([key, typeOrValue]) => {\n\t\t\t\t\t\t// Normalize type to valid JSON Schema types\n\t\t\t\t\t\t// Handle both type strings and actual values from LLM classification\n\t\t\t\t\t\tlet schemaType: string;\n\t\t\t\t\t\tlet hasDefaultValue = false;\n\t\t\t\t\t\tlet defaultValue: any;\n\n\t\t\t\t\t\t// Check if this is an actual value (not a type string)\n\t\t\t\t\t\tconst valueType = typeof typeOrValue;\n\t\t\t\t\t\tif (valueType === 'number') {\n\t\t\t\t\t\t\t// If it's a number value, infer the type and mark as having default\n\t\t\t\t\t\t\tschemaType = Number.isInteger(typeOrValue) ? 'integer' : 'number';\n\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t} else if (valueType === 'boolean') {\n\t\t\t\t\t\t\tschemaType = 'boolean';\n\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t} else if (Array.isArray(typeOrValue)) {\n\t\t\t\t\t\t\tschemaType = 'array';\n\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t} else if (valueType === 'object' && typeOrValue !== null) {\n\t\t\t\t\t\t\tschemaType = 'object';\n\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// It's a string - could be a type name or a string value\n\t\t\t\t\t\t\tconst typeStr = String(typeOrValue).toLowerCase().trim();\n\n\t\t\t\t\t\t\t// Check if it's a known type name\n\t\t\t\t\t\t\tif (typeStr === 'string' || typeStr === 'str') {\n\t\t\t\t\t\t\t\tschemaType = 'string';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'number' || typeStr === 'num' || typeStr === 'float' || typeStr === 'double') {\n\t\t\t\t\t\t\t\tschemaType = 'number';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'integer' || typeStr === 'int') {\n\t\t\t\t\t\t\t\tschemaType = 'integer';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'boolean' || typeStr === 'bool') {\n\t\t\t\t\t\t\t\tschemaType = 'boolean';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'array' || typeStr === 'list') {\n\t\t\t\t\t\t\t\tschemaType = 'array';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'object' || typeStr === 'dict') {\n\t\t\t\t\t\t\t\tschemaType = 'object';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Not a recognized type name, assume it's a string value - infer type as string\n\t\t\t\t\t\t\t\tschemaType = 'string';\n\t\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst propertySchema: any = {\n\t\t\t\t\t\t\ttype: schemaType,\n\t\t\t\t\t\t\tdescription: `${key} parameter for ${tool.name}`\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// Add default value to schema if present\n\t\t\t\t\t\tif (hasDefaultValue) {\n\t\t\t\t\t\t\tpropertySchema.default = defaultValue;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Only mark as required if no default value\n\t\t\t\t\t\t\trequired.push(key);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tproperties[key] = propertySchema;\n\t\t\t\t\t});\n\n\t\t\t\t\tconst inputSchema: any = {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\tadditionalProperties: false\n\t\t\t\t\t};\n\n\t\t\t\t\t// Only include required array if there are required fields\n\t\t\t\t\tif (required.length > 0) {\n\t\t\t\t\t\tinputSchema.required = required;\n\t\t\t\t\t}\n\n\t\t\t\t\ttools.push({\n\t\t\t\t\t\tname: tool.id,\n\t\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\t\tinput_schema: inputSchema\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Added ${executableTools.length} executable tools to tool calling capability (${externalTools.length - executableTools.length} deferred tools await form input)`);\n\t\t\t\t// Debug: Log the complete tools array to verify schema\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Complete tools array:`, JSON.stringify(tools, null, 2));\n\t\t\t}\n\n\t\t\t// Track query attempts for retry logic (max 6 attempts per unique query pattern)\n\t\t\tconst queryAttempts = new Map<string, number>();\n\t\t\tconst MAX_QUERY_ATTEMPTS = 6;\n\n\t\t\t// Track external tool attempts for retry logic (max 3 attempts per tool)\n\t\t\tconst toolAttempts = new Map<string, number>();\n\t\t\tconst MAX_TOOL_ATTEMPTS = 3;\n\n\t\t\t// Track successfully executed external tools (for passing to component matching)\n\t\t\tconst executedToolsList: any[] = [];\n\n\t\t\tlet maxAttemptsReached = false;\n\n\t\t\t// Capture all streamed text to pass to component matching\n\t\t\tlet fullStreamedText = '';\n\n\t\t\t// Wrap the streamCallback to capture all text\n\t\t\tconst wrappedStreamCallback = streamCallback ? (chunk: string) => {\n\t\t\t\tfullStreamedText += chunk;\n\t\t\t\tstreamCallback(chunk);\n\t\t\t} : undefined;\n\n\t\t\t// Tool handler with retry logic and streaming updates\n\t\t\tconst toolHandler = async (toolName: string, toolInput: any) => {\n\t\t\t\tif (toolName === 'execute_query') {\n\t\t\t\t\tlet sql = toolInput.sql;\n\t\t\t\t\tconst params = toolInput.params || {};\n\t\t\t\t\tconst reasoning = toolInput.reasoning;\n\n\t\t\t\t\t// Ensure query has proper LIMIT clause (max 32 rows)\n\t\t\t\t\tconst { ensureQueryLimit } = await import('./utils');\n\t\t\t\t\tsql = ensureQueryLimit(sql, 32, 32);\n\n\t\t\t\t\t// Track attempts for this query pattern (normalized)\n\t\t\t\t\tconst queryKey = sql.toLowerCase().replace(/\\s+/g, ' ').trim();\n\t\t\t\t\tconst attempts = (queryAttempts.get(queryKey) || 0) + 1;\n\t\t\t\t\tqueryAttempts.set(queryKey, attempts);\n\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Executing query (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${sql.substring(0, 100)}...`);\n\t\t\t\t\tif (Object.keys(params).length > 0) {\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Query params: ${JSON.stringify(params)}`);\n\t\t\t\t\t}\n\t\t\t\t\tif (reasoning) {\n\t\t\t\t\t\tlogCollector?.info(`Query reasoning: ${reasoning}`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check if max attempts reached\n\t\t\t\t\tif (attempts > MAX_QUERY_ATTEMPTS) {\n\t\t\t\t\t\tconst errorMsg = `Maximum query attempts (${MAX_QUERY_ATTEMPTS}) reached. Unable to generate a valid query for your question.`;\n\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] ${errorMsg}`);\n\t\t\t\t\t\tlogCollector?.error(errorMsg);\n\n\t\t\t\t\t\t// Set flag instead of throwing\n\t\t\t\t\t\tmaxAttemptsReached = true;\n\n\t\t\t\t\t\t// Stream error to frontend\n\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n❌ ${errorMsg}\\n\\nPlease try rephrasing your question or simplifying your request.\\n\\n`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Return error message to stop the tool calling loop\n\t\t\t\t\t\tthrow new Error(errorMsg);\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Stream query generation message to frontend\n\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\tconst paramsDisplay = Object.keys(params).length > 0 ? `\\n**Parameters:** ${JSON.stringify(params)}` : '';\n\t\t\t\t\t\t\tif (attempts === 1) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔍 **Analyzing your question...**\\n\\n`);\n\t\t\t\t\t\t\t\tif (reasoning) {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`💭 ${reasoning}\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twrappedStreamCallback(`📝 **Generated SQL Query:**\\n\\`\\`\\`sql\\n${sql}\\n\\`\\`\\`${paramsDisplay}\\n\\n`);\n\t\t\t\t\t\t\t\twrappedStreamCallback(`⚡ **Executing query...**\\n\\n`);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔄 **Retrying with corrected query (attempt ${attempts}/${MAX_QUERY_ATTEMPTS})...**\\n\\n`);\n\t\t\t\t\t\t\t\tif (reasoning) {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`💭 ${reasoning}\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twrappedStreamCallback(`📝 **Corrected SQL Query:**\\n\\`\\`\\`sql\\n${sql}\\n\\`\\`\\`${paramsDisplay}\\n\\n`);\n\t\t\t\t\t\t\t\twrappedStreamCallback(`⚡ **Executing query...**\\n\\n`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Log the query with params\n\t\t\t\t\t\tlogCollector?.logQuery(\n\t\t\t\t\t\t\t`Executing SQL query (attempt ${attempts})`,\n\t\t\t\t\t\t\t{ sql, params },\n\t\t\t\t\t\t\t{ reasoning, attempt: attempts }\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Execute query using collections system (database.execute)\n\t\t\t\t\t\t// Pass { sql, params } format for parameterized queries\n\t\t\t\t\t\tif (!collections || !collections['database'] || !collections['database']['execute']) {\n\t\t\t\t\t\t\tthrow new Error('Database collection not registered. Please register database.execute collection to execute queries.');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Build the query payload - if params exist, send as JSON structure for parameterized query\n\t\t\t\t\t\tconst queryPayload = Object.keys(params).length > 0\n\t\t\t\t\t\t\t? { sql: JSON.stringify({ sql, values: params }) }\n\t\t\t\t\t\t\t: { sql };\n\n\t\t\t\t\t\tconst result = await collections['database']['execute'](queryPayload);\n\n\t\t\t\t\t\t// Extract data from result\n\t\t\t\t\t\tconst data = result?.data || result;\n\t\t\t\t\t\tconst rowCount = result?.count ?? (Array.isArray(data) ? data.length : 'N/A');\n\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Query executed successfully, rows returned: ${rowCount}`);\n\t\t\t\t\t\tlogCollector?.info(`Query successful, returned ${rowCount} rows`);\n\n\t\t\t\t\t\t// Stream success message and data preview to frontend\n\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\twrappedStreamCallback(`✅ **Query executed successfully!**\\n\\n`);\n\n\t\t\t\t\t\t\t// Check if it's a count query or aggregate\n\t\t\t\t\t\t\tif (Array.isArray(data) && data.length > 0) {\n\t\t\t\t\t\t\t\tconst firstRow = data[0];\n\t\t\t\t\t\t\t\tconst columns = Object.keys(firstRow);\n\n\t\t\t\t\t\t\t\t// If single row with single column (likely a count/aggregate)\n\t\t\t\t\t\t\t\tif (data.length === 1 && columns.length === 1) {\n\t\t\t\t\t\t\t\t\tconst value = firstRow[columns[0]];\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`**Result:** ${value}\\n\\n`);\n\t\t\t\t\t\t\t\t} else if (data.length > 0) {\n\t\t\t\t\t\t\t\t\t// Multiple rows or columns - embed DataTable component\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`**Retrieved ${rowCount} rows**\\n\\n`);\n\n\t\t\t\t\t\t\t\t\t// Stream the data as a DataTable component\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`<DataTable>${JSON.stringify(data)}</DataTable>\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (Array.isArray(data) && data.length === 0) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`**No rows returned.**\\n\\n`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\twrappedStreamCallback(`📊 **Analyzing results...**\\n\\n`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Return full result as JSON string for the LLM to analyze\n\t\t\t\t\t\treturn JSON.stringify(data, null, 2);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] Query execution failed (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${errorMsg}`);\n\t\t\t\t\t\tlogCollector?.error(`Query failed (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${errorMsg}`);\n\n\t\t\t\t\t\t// Log full SQL error details to error log file\n\t\t\t\t\t\tuserPromptErrorLogger.logSqlError(sql, error instanceof Error ? error : new Error(errorMsg), Object.keys(params).length > 0 ? Object.values(params) : undefined);\n\n\t\t\t\t\t\t// Stream error message to frontend\n\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\twrappedStreamCallback(`❌ **Query execution failed:**\\n\\`\\`\\`\\n${errorMsg}\\n\\`\\`\\`\\n\\n`);\n\n\t\t\t\t\t\t\tif (attempts < MAX_QUERY_ATTEMPTS) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`🔧 **Generating corrected query...**\\n\\n`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Return error to LLM so it can retry with corrected query\n\t\t\t\t\t\tthrow new Error(`Query execution failed: ${errorMsg}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Handle external tools identified by category classification\n\t\t\t\t\tconst externalTool = externalTools?.find(t => t.id === toolName);\n\t\t\t\t\tif (externalTool) {\n\t\t\t\t\t\t// Track attempts for this tool\n\t\t\t\t\t\tconst attempts = (toolAttempts.get(toolName) || 0) + 1;\n\t\t\t\t\t\ttoolAttempts.set(toolName, attempts);\n\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Executing external tool: ${externalTool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})`);\n\t\t\t\t\t\tlogCollector?.info(`Executing external tool: ${externalTool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})...`);\n\n\t\t\t\t\t\t// Check if max attempts reached\n\t\t\t\t\t\tif (attempts > MAX_TOOL_ATTEMPTS) {\n\t\t\t\t\t\t\tconst errorMsg = `Maximum attempts (${MAX_TOOL_ATTEMPTS}) reached for tool: ${externalTool.name}`;\n\t\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] ${errorMsg}`);\n\t\t\t\t\t\t\tlogCollector?.error(errorMsg);\n\n\t\t\t\t\t\t\t// Stream error to frontend\n\t\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n❌ ${errorMsg}\\n\\nPlease try rephrasing your request or contact support.\\n\\n`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Return error message to stop the tool calling loop\n\t\t\t\t\t\t\tthrow new Error(errorMsg);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Stream tool execution message\n\t\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\t\tif (attempts === 1) {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔗 **Executing ${externalTool.name}...**\\n\\n`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔄 **Retrying ${externalTool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})...**\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Execute the external tool function with parameters from LLM\n\t\t\t\t\t\t\tconst result = await externalTool.fn(toolInput);\n\n\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] External tool ${externalTool.name} executed successfully`);\n\t\t\t\t\t\t\tlogCollector?.info(`✓ ${externalTool.name} executed successfully`);\n\n\t\t\t\t\t\t\t// Track successfully executed tool (for passing to component matching)\n\t\t\t\t\t\t\t// Only add if not already tracked (avoid duplicates on retry)\n\t\t\t\t\t\t\tif (!executedToolsList.find(t => t.id === externalTool.id)) {\n\t\t\t\t\t\t\t\t// Create a lightweight summary instead of storing full result to reduce memory\n\t\t\t\t\t\t\t\t// The component matching prompt only needs: toolId, toolName, parameters\n\t\t\t\t\t\t\t\t// and a brief preview of results for context\n\t\t\t\t\t\t\t\tlet resultSummary: any = null;\n\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\tconst resultStr = typeof result === 'string' ? result : JSON.stringify(result);\n\t\t\t\t\t\t\t\t\t// Store only first 1000 chars as preview (enough for LLM context)\n\t\t\t\t\t\t\t\t\tif (resultStr.length > 1000) {\n\t\t\t\t\t\t\t\t\t\tresultSummary = {\n\t\t\t\t\t\t\t\t\t\t\t_preview: resultStr.substring(0, 1000) + '... (truncated)',\n\t\t\t\t\t\t\t\t\t\t\t_totalLength: resultStr.length,\n\t\t\t\t\t\t\t\t\t\t\t_recordCount: Array.isArray(result) ? result.length :\n\t\t\t\t\t\t\t\t\t\t\t\t(result?.data?.length || result?.contacts?.length || result?.salesorders?.length || 'unknown')\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tresultSummary = result;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\texecutedToolsList.push({\n\t\t\t\t\t\t\t\t\tid: externalTool.id,\n\t\t\t\t\t\t\t\t\tname: externalTool.name,\n\t\t\t\t\t\t\t\t\tparams: toolInput, // The actual parameters used in this execution\n\t\t\t\t\t\t\t\t\tresult: resultSummary // Store summary instead of full result to save memory\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Tracked executed tool: ${externalTool.name} with params: ${JSON.stringify(toolInput)}`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Stream success message\n\t\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`✅ **${externalTool.name} completed successfully**\\n\\n`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Return result as JSON string for the LLM\n\t\t\t\t\t\t\treturn JSON.stringify(result, null, 2);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] External tool ${externalTool.name} failed (attempt ${attempts}/${MAX_TOOL_ATTEMPTS}): ${errorMsg}`);\n\t\t\t\t\t\t\tlogCollector?.error(`✗ ${externalTool.name} failed: ${errorMsg}`);\n\n\t\t\t\t\t\t\t// Log full tool error details to error log file\n\t\t\t\t\t\t\tuserPromptErrorLogger.logToolError(externalTool.name, toolInput, error instanceof Error ? error : new Error(errorMsg));\n\n\t\t\t\t\t\t\t// Stream error message\n\t\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`❌ **${externalTool.name} failed:**\\n\\`\\`\\`\\n${errorMsg}\\n\\`\\`\\`\\n\\n`);\n\n\t\t\t\t\t\t\t\tif (attempts < MAX_TOOL_ATTEMPTS) {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`🔧 **Retrying with adjusted parameters...**\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Throw error so LLM can handle it and retry with adjusted parameters\n\t\t\t\t\t\t\tthrow new Error(`Tool execution failed: ${errorMsg}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow new Error(`Unknown tool: ${toolName}`);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Use tool calling with streaming\n\t\t\t// Max iterations needs to account for:\n\t\t\t// - Up to 6 query retry attempts (MAX_QUERY_ATTEMPTS)\n\t\t\t// - Up to 3 external tool retry attempts per tool (MAX_TOOL_ATTEMPTS)\n\t\t\t// - 1 additional iteration for final text response\n\t\t\t// - Buffer for multiple tool calls in one iteration\n\t\t\tconst result = await LLM.streamWithTools(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\ttools,\n\t\t\t\ttoolHandler,\n\t\t\t\t{\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t\tmaxTokens: 4000,\n\t\t\t\t\ttemperature: 0.7,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey),\n\t\t\t\t\tpartial: wrappedStreamCallback // Pass the wrapped streaming callback to LLM\n\t\t\t\t},\n\t\t\t\t20 // max iterations: allows for 6 query retries + 3 tool retries + final response + buffer\n\t\t\t);\n\n\t\t\tlogger.info(`[${this.getProviderName()}] Text response stream completed`);\n\n\t\t\t// Use fullStreamedText if available (contains all streamed content), otherwise fallback to result\n\t\t\tconst textResponse = fullStreamedText || result || 'I apologize, but I was unable to generate a response.';\n\n\t\t\t// Check if max query attempts were reached\n\t\t\tif (maxAttemptsReached) {\n\t\t\t\tlogger.warn(`[${this.getProviderName()}] Max query attempts reached, returning failure response`);\n\t\t\t\tlogCollector?.error('Failed to generate valid query after maximum attempts');\n\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terrors: [`Maximum query attempts (${MAX_QUERY_ATTEMPTS}) reached. Unable to generate a valid query for your question.`],\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttext: textResponse, // Include the streamed text showing all attempts\n\t\t\t\t\t\tmatchedComponents: [],\n\t\t\t\t\t\tactions: [],\n\t\t\t\t\t\tmethod: `${this.getProviderName()}-text-response-max-attempts`\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Log the text response\n\t\t\tlogCollector?.info(`Text response: ${textResponse.substring(0, 100)}${textResponse.length > 100 ? '...' : ''}`);\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'Text response generated',\n\t\t\t\t'Generated plain text response with component suggestions',\n\t\t\t\t{\n\t\t\t\t\ttextLength: textResponse.length\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t// Send marker message to frontend indicating text generation is complete\n\t\t\t// and component matching is starting (skip for general category)\n\t\t\tif (wrappedStreamCallback && components && components.length > 0 && category !== 'general') {\n\t\t\t\twrappedStreamCallback('__TEXT_COMPLETE__COMPONENT_GENERATION_START__');\n\t\t\t}\n\n\t\t\t// If components are provided, match them from the text response\n\t\t\t// Skip component generation for 'general' category (greetings, small talk, etc.)\n\t\t\tlet matchedComponents: Component[] = [];\n\t\t\tlet layoutTitle = 'Dashboard';\n\t\t\tlet layoutDescription = 'Multi-component dashboard';\n\t\t\tlet actions: Action[] = [];\n\n\t\t\tif (category === 'general') {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Skipping component generation for general/conversational question`);\n\t\t\t\tlogCollector?.info('Skipping component generation for general question');\n\t\t\t} else if (components && components.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Matching components from text response...`);\n\n\t\t\t\t// Component streaming callback to send answer component immediately to frontend\n\t\t\t\t// For data_modification, skip answer component streaming - show full dashboard directly\n\t\t\t\tconst componentStreamCallback = (wrappedStreamCallback && category !== 'data_modification') ? (component: Component) => {\n\t\t\t\t\t// Send special marker to indicate answer component is ready\n\t\t\t\t\tconst answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;\n\t\t\t\t\twrappedStreamCallback(answerMarker);\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);\n\t\t\t\t} : undefined;\n\n\t\t\t\t// Extract deferred tools (tools that need user input via Form)\n\t\t\t\t// For data_modification category, tools with Create/Update/Delete in name are deferred\n\t\t\t\tconst deferredTools = externalTools?.filter(t => {\n\t\t\t\t\t// Explicit deferred type\n\t\t\t\t\tif (t.executionType === 'deferred' && !t.userProvidedData) return true;\n\t\t\t\t\t// Infer deferred for data_modification category based on tool name patterns\n\t\t\t\t\tif (category === 'data_modification' && !t.userProvidedData) {\n\t\t\t\t\t\tconst name = (t.name || t.id || '').toLowerCase();\n\t\t\t\t\t\tconst isWriteOperation = /create|add|insert|new|update|edit|modify|delete|remove|send/.test(name);\n\t\t\t\t\t\tif (isWriteOperation) {\n\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Inferred deferred execution for tool: ${t.name}`);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}) || [];\n\n\t\t\t\tif (deferredTools.length > 0) {\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools for Form generation`);\n\t\t\t\t}\n\n\t\t\t\t// logger.info(`[${this.getProviderName()}] passing deferred tools to the matching function: ${JSON.stringify(deferredTools,null,2)}`);\n\t\t\t\t// logger.info(`[${this.getProviderName()}] passing executed tools to the matching function: ${JSON.stringify(executedToolsList,null,2)}`);\n\n\t\t\t\tconst matchResult = await this.matchComponentsFromAnalysis(\n\t\t\t\t\ttextResponse,\n\t\t\t\t\tcomponents,\n\t\t\t\t\tapiKey,\n\t\t\t\t\tlogCollector,\n\t\t\t\t\tcomponentStreamCallback,\n\t\t\t\t\tdeferredTools,\n\t\t\t\t\texecutedToolsList\n\t\t\t\t);\n\t\t\t\tmatchedComponents = matchResult.components;\n\t\t\t\tlayoutTitle = matchResult.layoutTitle;\n\t\t\t\tlayoutDescription = matchResult.layoutDescription;\n\t\t\t\tactions = matchResult.actions;\n\t\t\t}\n\n\t\t\tlet container_componet:Component | null = null;\n\n\t\t\tif(matchedComponents.length > 0){\n\t\t\t\t// Create MultiComponentContainer with matched components\n\t\t\t\t\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Created MultiComponentContainer: \"${layoutTitle}\" with ${matchedComponents.length} components and ${actions.length} actions`);\n\t\t\t\tlogCollector?.info(`Created dashboard: \"${layoutTitle}\" with ${matchedComponents.length} components and ${actions.length} actions`);\n\n\t\t\t\tcontainer_componet = {\n\t\t\t\t\tid: `container_${Date.now()}`,\n\t\t\t\t\tname: 'MultiComponentContainer',\n\t\t\t\t\ttype: 'Container',\n\t\t\t\t\tdescription: layoutDescription,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tconfig: {\n\t\t\t\t\t\t\ttitle: layoutTitle,\n\t\t\t\t\t\t\tdescription: layoutDescription,\n\t\t\t\t\t\t\tcomponents: matchedComponents\n\t\t\t\t\t\t},\n\t\t\t\t\t\tactions: actions\n\t\t\t\t\t}\n\t\t\t\t};\t\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\ttext: textResponse,\n\t\t\t\t\tmatchedComponents: matchedComponents,\n\t\t\t\t\tcomponent: container_componet,\n\t\t\t\t\tactions: actions,\n\t\t\t\t\tmethod: `${this.getProviderName()}-text-response`\n\t\t\t\t},\n\t\t\t\terrors: []\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating text response: ${errorMsg}`);\n\t\t\tlogCollector?.error(`Error generating text response: ${errorMsg}`);\n\n\t\t\t// Log LLM error with full details\n\t\t\tuserPromptErrorLogger.logLlmError(\n\t\t\t\tthis.getProviderName(),\n\t\t\t\tthis.model,\n\t\t\t\t'generateTextResponse',\n\t\t\t\terror instanceof Error ? error : new Error(errorMsg),\n\t\t\t\t{ userPrompt }\n\t\t\t);\n\n\t\t\terrors.push(errorMsg);\n\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terrors,\n\t\t\t\tdata: {\n\t\t\t\t\ttext: 'I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.',\n\t\t\t\t\tmatchedComponents: [],\n\t\t\t\t\tactions: [],\n\t\t\t\t\tmethod: `${this.getProviderName()}-text-response-error`\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t}\n\n\n\t/**\n\t * Main orchestration function with semantic search and multi-step classification\n\t * NEW FLOW (Recommended):\n\t * 1. Semantic search: Check previous conversations (>60% match)\n\t * - If match found → Adapt UI block parameters and return\n\t * 2. Category classification: Determine if data_analysis, requires_external_tools, or text_response\n\t * 3. Route appropriately based on category and response mode\n\t *\n\t * @param responseMode - 'component' for component generation (default), 'text' for text responses\n\t * @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)\n\t * @param collections - Collection registry for executing database queries (required for text mode)\n\t * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called (only for text mode)\n\t */\n\tasync handleUserRequest(\n\t\tuserPrompt: string,\n\t\tcomponents: Component[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string,\n\t\tresponseMode: 'component' | 'text' = 'text',\n\t\tstreamCallback?: (chunk: string) => void,\n\t\tcollections?: any,\n\t\texternalTools?: any[],\n\t\tuserId?: string\n\t): Promise<T_RESPONSE> {\n\t\tconst startTime = Date.now();\n\t\tlogger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);\n\t\tlogCollector?.info(`Starting request processing with mode: ${responseMode}`);\n\n\t\ttry {\n\t\t\t// STEP 1: Semantic search - Check if this question matches previous conversations (>60% similarity)\n\t\t\tlogger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);\n\t\t\tlogCollector?.info('Step 1: Searching for similar previous conversations...');\n\n\t\t\t// const conversationMatch = await ConversationSearch.searchConversations({\n\t\t\t// \tuserPrompt,\n\t\t\t// \tcollections,\n\t\t\t// \tuserId,\n\t\t\t// \tsimilarityThreshold: 0.6 // 60% threshold\n\t\t\t// });\n\n\t\t\tconst conversationMatch = await ConversationSearch.searchConversationsWithReranking({\n\t\t\t\tuserPrompt,\n\t\t\t\tcollections,\n\t\t\t\tuserId,\n\t\t\t\tsimilarityThreshold: 0.6 // 60% threshold\n\t\t\t});\n\n\t\t\t// logger.info('conversationMatch:', conversationMatch);\n\n\t\t\tif (conversationMatch) {\n\t\t\t\t// Found a match! Check if it's a 100% match (exact same question)\n\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);\n\t\t\t\tlogCollector?.info(\n\t\t\t\t\t`✓ Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`\n\t\t\t\t);\n\n\t\t\t\t// Extract the component from the UI block\n\t\t\t\tconst rawComponent = conversationMatch.uiBlock?.component || conversationMatch.uiBlock?.generatedComponentMetadata;\n\n\t\t\t\t// Check if component is valid (not null, not empty object)\n\t\t\t\tconst isValidComponent = rawComponent && typeof rawComponent === 'object' && Object.keys(rawComponent).length > 0;\n\t\t\t\tconst component = isValidComponent ? rawComponent : null;\n\n\t\t\t\t// Extract text response - DB stores as 'analysis'\n\t\t\t\tconst cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || '';\n\n\n\t\t\t\t// Check if cached component contains a Form (data_modification)\n\t\t\t\t// Forms have hardcoded defaultValues that become stale - always fetch fresh data\n\t\t\t\tif (this.containsFormComponent(component)) {\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Skipping cached result - Form components contain stale defaultValues, fetching fresh data`);\n\t\t\t\t\tlogCollector?.info('Skipping cache for form - fetching current values from database...');\n\t\t\t\t\t// Fall through to category classification to generate fresh form with current values\n\t\t\t\t}\n\t\t\t\t// Check if this was a general conversation (no component)\n\t\t\t\t// If so, return text response for exact match or skip adaptation for similar match\n\t\t\t\telse if (!component) {\n\t\t\t\t\tif (conversationMatch.similarity >= 0.99) {\n\t\t\t\t\t\t// Exact match for general question - return cached text response\n\t\t\t\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ Exact match for general question - returning cached text response`);\n\t\t\t\t\t\tlogCollector?.info(`✓ Exact match for general question - returning cached response`);\n\t\t\t\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\ttext: cachedTextResponse,\n\t\t\t\t\t\t\t\tcomponent: null,\n\t\t\t\t\t\t\t\tmatchedComponents: [],\n\t\t\t\t\t\t\t\tactions: conversationMatch.uiBlock?.actions || [],\n\t\t\t\t\t\t\t\treasoning: `Exact match from previous general conversation`,\n\t\t\t\t\t\t\t\tmethod: `${this.getProviderName()}-semantic-match-general`,\n\t\t\t\t\t\t\t\tsemanticSimilarity: conversationMatch.similarity\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terrors: []\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Similar match but no component (general question) - skip adaptation and process fresh\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Similar match but no component (general question) - processing fresh`);\n\t\t\t\t\t\tlogCollector?.info('Similar match found but was a general conversation - processing as new question');\n\t\t\t\t\t\t// Fall through to category classification\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Has component - proceed with normal flow\n\t\t\t\t\t// If similarity >= 99%, it's essentially the same question - return UI block directly\n\t\t\t\t\tif (conversationMatch.similarity >= 0.99) {\n\t\t\t\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ 100% match - returning UI block directly without adaptation`);\n\t\t\t\t\t\tlogCollector?.info(`✓ Exact match (${(conversationMatch.similarity * 100).toFixed(2)}%) - returning cached result`);\n\t\t\t\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tcomponent: component,\n\t\t\t\t\t\t\t\treasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,\n\t\t\t\t\t\t\t\tmethod: `${this.getProviderName()}-semantic-match-exact`,\n\t\t\t\t\t\t\t\tsemanticSimilarity: conversationMatch.similarity\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terrors: []\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Similarity between 60-99%, adapt the UI block parameters\n\t\t\t\t\tlogCollector?.info(`Adapting parameters for similar question...`);\n\n\t\t\t\t\t// Get the original prompt from the matched UIBlock\n\t\t\t\t\tconst originalPrompt = conversationMatch.metadata?.userPrompt || 'Previous question';\n\n\t\t\t\t\t// Adapt the UI block parameters to the current question\n\t\t\t\t\tconst adaptResult = await this.adaptUIBlockParameters(\n\t\t\t\t\t\tuserPrompt,\n\t\t\t\t\t\toriginalPrompt,\n\t\t\t\t\t\tconversationMatch.uiBlock,\n\t\t\t\t\t\tapiKey,\n\t\t\t\t\t\tlogCollector\n\t\t\t\t\t);\n\n\t\t\t\t\tif (adaptResult.success && adaptResult.adaptedComponent) {\n\t\t\t\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ Successfully adapted UI block parameters`);\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\t\t\t\tlogCollector?.info(`✓ UI block adapted successfully`);\n\t\t\t\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tcomponent: adaptResult.adaptedComponent,\n\t\t\t\t\t\t\t\treasoning: `Adapted from previous conversation: ${originalPrompt}`,\n\t\t\t\t\t\t\t\tmethod: `${this.getProviderName()}-semantic-match`,\n\t\t\t\t\t\t\t\tsemanticSimilarity: conversationMatch.similarity,\n\t\t\t\t\t\t\t\tparametersChanged: adaptResult.parametersChanged\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terrors: []\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Could not adapt matched conversation, continuing to category classification`);\n\t\t\t\t\t\tlogCollector?.warn(`Could not adapt matched conversation: ${adaptResult.explanation}`);\n\t\t\t\t\t\t// Fall through to category classification\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] No matching previous conversations found, proceeding to category classification`);\n\t\t\t\tlogCollector?.info('No similar previous conversations found. Proceeding to category classification...');\n\t\t\t}\n\n\t\t\t// STEP 2: Category classification - Determine the type of request\n\t\t\tlogger.info(`[${this.getProviderName()}] Step 2: Classifying question category...`);\n\t\t\tlogCollector?.info('Step 2: Classifying question category...');\n\n\t\t\tconst categoryClassification = await this.classifyQuestionCategory(\n\t\t\t\tuserPrompt,\n\t\t\t\tapiKey,\n\t\t\t\tlogCollector,\n\t\t\t\tconversationHistory,\n\t\t\t\texternalTools\n\t\t\t);\n\n\t\t\tlogger.info(\n\t\t\t\t`[${this.getProviderName()}] Question classified as: ${categoryClassification.category} (confidence: ${categoryClassification.confidence}%)`\n\t\t\t);\n\t\t\tlogCollector?.info(\n\t\t\t\t`Category: ${categoryClassification.category} | Confidence: ${categoryClassification.confidence}%`\n\t\t\t);\n\n\t\t\t// STEP 3: Prepare tools based on category classification\n\t\t\t// Only use tools identified by the LLM classification\n\t\t\tlet toolsToUse: any[] = [];\n\t\t\tif (categoryClassification.externalTools && categoryClassification.externalTools.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Identified ${categoryClassification.externalTools.length} external tools needed`);\n\t\t\t\tlogCollector?.info(`Identified external tools: ${categoryClassification.externalTools.map((t: any) => t.name || t.type).join(', ')}`);\n\n\t\t\t\t// Log the raw external tools from category classification for debugging\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Raw external tools from classification: ${JSON.stringify(categoryClassification.externalTools, null, 2)}`);\n\n\t\t\t\ttoolsToUse = categoryClassification.externalTools?.map((t: any) => {\n\t\t\t\t\t// Look up the real tool implementation\n\t\t\t\t\tconst realTool = externalTools?.find(tool => tool.id === t.type);\n\n\t\t\t\t\t// Log execution type for debugging\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Tool ${t.name}: executionType=${t.executionType}, userProvidedData=${t.userProvidedData ? 'present' : 'null'}`);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: t.type,\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparams: t.parameters || {},\n\t\t\t\t\t\t// NEW: Include execution type info from category classification\n\t\t\t\t\t\texecutionType: t.executionType || 'immediate',\n\t\t\t\t\t\texecutionReason: t.executionReason || '',\n\t\t\t\t\t\trequiredFields: t.requiredFields || [],\n\t\t\t\t\t\tuserProvidedData: t.userProvidedData || null,\n\t\t\t\t\t\tfn: (() => {\n\t\t\t\t\t\t\tif (realTool) {\n\t\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);\n\t\t\t\t\t\t\t\treturn realTool.fn; // Use the real function!\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlogger.warn(`[${this.getProviderName()}] Tool ${t.type} not found in registered tools`);\n\t\t\t\t\t\t\t\treturn async () => ({ success: false, message: `Tool ${t.name || t.type} not registered` });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})()\n\t\t\t\t\t};\n\t\t\t\t}) || [];\n\n\t\t\t}\n\n\t\t\t// STEP 4: Route based on category\n\t\t\tif (categoryClassification.category === 'general') {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);\n\t\t\t\tlogCollector?.info('Routing to general conversation...');\n\t\t\t} else if (categoryClassification.category === 'data_analysis') {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Routing to data analysis (SELECT operations)`);\n\t\t\t\tlogCollector?.info('Routing to data analysis...');\n\t\t\t} else if (categoryClassification.category === 'data_modification') {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Routing to data modification (INSERT/UPDATE/DELETE operations)`);\n\t\t\t\tlogCollector?.info('Routing to data modification...');\n\t\t\t}\n\n\t\t\t// Generate text response with identified tools\n\t\t\tconst textResponse = await this.generateTextResponse(\n\t\t\t\tuserPrompt,\n\t\t\t\tapiKey,\n\t\t\t\tlogCollector,\n\t\t\t\tconversationHistory,\n\t\t\t\tstreamCallback,\n\t\t\t\tcollections,\n\t\t\t\tcomponents,\n\t\t\t\ttoolsToUse,\n\t\t\t\tcategoryClassification.category\n\t\t\t);\n\n\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\treturn textResponse;\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error in handleUserRequest: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Error details:`, error);\n\t\t\tlogCollector?.error(`Error processing request: ${errorMsg}`);\n\n\t\t\t// Log error with full details\n\t\t\tuserPromptErrorLogger.logError(\n\t\t\t\t'handleUserRequest',\n\t\t\t\terror instanceof Error ? error : new Error(errorMsg),\n\t\t\t\t{ userPrompt }\n\t\t\t);\n\n\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terrors: [errorMsg],\n\t\t\t\tdata: {\n\t\t\t\t\ttext: 'I apologize, but I encountered an error processing your request. Please try again.',\n\t\t\t\t\tmethod: `${this.getProviderName()}-orchestration-error`\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Generate next questions that the user might ask based on the original prompt and generated component\n\t * This helps provide intelligent suggestions for follow-up queries\n\t */\n\tasync generateNextQuestions(\n\t\toriginalUserPrompt: string,\n\t\tcomponent: Component,\n\t\tcomponentData?: Record<string, unknown>,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<string[]> {\n\t\ttry {\n\t\t\tconst component_info = `\n\t\t\t\tComponent Name: ${component.name}\n\t\t\t\tComponent Type: ${component.type}\n\t\t\t\tComponent Description: ${component.description || 'No description'}\n\t\t\t\tComponent Props: ${component.props ? JSON.stringify(component.props, null, 2) : 'No props'}\n\t\t\t`;\n\n\t\t\tconst component_data = componentData ? `Component Data: ${JSON.stringify(componentData, null, 2)}` : '';\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('actions', {\n\t\t\t\tORIGINAL_USER_PROMPT: originalUserPrompt,\n\t\t\t\tCOMPONENT_INFO: component_info,\n\t\t\t\tCOMPONENT_DATA: component_data,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\n\t\t\t});\n\n\t\t\t// Use fast model for actions generation (simple task, cheaper)\n\t\t\tconst result = await LLM.stream<any>(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmodel: this.fastModel,\n\t\t\t\t\tmaxTokens: 1200,\n\t\t\t\t\ttemperature: 0.7,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\n\t\t\t\t},\n\t\t\t\ttrue // Parse as JSON\n\t\t\t) as any;\n\n\t\t\tconst nextQuestions = result.nextQuestions || [];\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'Next questions generated',\n\t\t\t\t'Generated intelligent follow-up questions based on component',\n\t\t\t\t{\n\t\t\t\t\tcount: nextQuestions.length,\n\t\t\t\t\tquestions: nextQuestions\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn nextQuestions;\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating next questions: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Next questions generation error details:`, error);\n\t\t\tlogCollector?.error(`Error generating next questions: ${errorMsg}`);\n\t\t\t// Return empty array on error instead of throwing\n\t\t\treturn [];\n\t\t}\n\t}\n\n}\n","import path from 'path';\nimport fs from 'fs';\nimport { logger } from '../utils/logger';\n\n/**\n * Schema class for managing database schema operations\n */\nexport class Schema {\n private schemaFilePath: string;\n private cachedSchema: any = null;\n\n constructor(schemaFilePath?: string) {\n this.schemaFilePath = schemaFilePath || path.join(process.cwd(), '../analysis/data/schema.json');\n }\n\n /**\n * Gets the database schema from the schema file\n * @returns Parsed schema object or null if error occurs\n */\n getDatabaseSchema(): any | null {\n logger.info(`SCHEMA_FILE_PATH: ${this.schemaFilePath}`);\n\n try {\n // Create directory structure if it doesn't exist\n const dir = path.dirname(this.schemaFilePath);\n if (!fs.existsSync(dir)) {\n logger.info(`Creating directory structure: ${dir}`);\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Create file with empty schema if it doesn't exist\n if (!fs.existsSync(this.schemaFilePath)) {\n logger.info(`Schema file does not exist at ${this.schemaFilePath}, creating with empty schema`);\n const initialSchema = {\n database: '',\n schema: '',\n description: '',\n tables: [],\n relationships: []\n };\n fs.writeFileSync(this.schemaFilePath, JSON.stringify(initialSchema, null, 4));\n this.cachedSchema = initialSchema;\n return initialSchema;\n }\n\n const fileContent = fs.readFileSync(this.schemaFilePath, 'utf-8');\n const schema = JSON.parse(fileContent);\n this.cachedSchema = schema;\n return schema;\n } catch (error) {\n logger.error('Error parsing schema file:', error);\n return null;\n }\n }\n\n /**\n * Gets the cached schema or loads it if not cached\n * @returns Cached schema or freshly loaded schema\n */\n getSchema(): any | null {\n if (this.cachedSchema) {\n return this.cachedSchema;\n }\n return this.getDatabaseSchema();\n }\n\n /**\n * Generates database schema documentation for LLM from Snowflake JSON schema\n * @returns Formatted schema documentation string\n */\n generateSchemaDocumentation(): string {\n const schema = this.getSchema();\n\n if (!schema) {\n logger.warn('No database schema found.');\n return 'No database schema available.';\n }\n\n const tables: string[] = [];\n\n // Header information\n tables.push(`Database: ${schema.database}`);\n tables.push(`Schema: ${schema.schema}`);\n tables.push(`Description: ${schema.description}`);\n tables.push('');\n tables.push('='.repeat(80));\n tables.push('');\n\n // Process each table\n for (const table of schema.tables) {\n const tableInfo: string[] = [];\n\n tableInfo.push(`TABLE: ${table.fullName}`);\n tableInfo.push(`Description: ${table.description}`);\n tableInfo.push(`Row Count: ~${table.rowCount.toLocaleString()}`);\n tableInfo.push('');\n tableInfo.push('Columns:');\n\n // Process columns\n for (const column of table.columns) {\n let columnLine = ` - ${column.name}: ${column.type}`;\n\n if ((column as any).isPrimaryKey) {\n columnLine += ' (PRIMARY KEY)';\n }\n\n if ((column as any).isForeignKey && (column as any).references) {\n columnLine += ` (FK -> ${(column as any).references.table}.${(column as any).references.column})`;\n }\n\n if (!column.nullable) {\n columnLine += ' NOT NULL';\n }\n\n if (column.description) {\n columnLine += ` - ${column.description}`;\n }\n\n tableInfo.push(columnLine);\n\n // Add value examples for categorical columns\n if ((column as any).sampleValues && (column as any).sampleValues.length > 0) {\n tableInfo.push(` Sample values: [${(column as any).sampleValues.join(', ')}]`);\n }\n\n // Add statistics if available\n if ((column as any).statistics) {\n const stats = (column as any).statistics;\n if (stats.min !== undefined && stats.max !== undefined) {\n tableInfo.push(` Range: ${stats.min} to ${stats.max}`);\n }\n if (stats.distinct !== undefined) {\n tableInfo.push(` Distinct values: ${stats.distinct.toLocaleString()}`);\n }\n }\n }\n\n tableInfo.push('');\n tables.push(tableInfo.join('\\n'));\n }\n\n // Add relationships section\n tables.push('='.repeat(80));\n tables.push('');\n tables.push('TABLE RELATIONSHIPS:');\n tables.push('');\n\n for (const rel of schema.relationships) {\n tables.push(`${rel.from} -> ${rel.to} (${rel.type}): ${rel.keys.join(' = ')}`);\n }\n\n return tables.join('\\n');\n }\n\n /**\n * Clears the cached schema, forcing a reload on next access\n */\n clearCache(): void {\n this.cachedSchema = null;\n }\n\n /**\n * Sets a custom schema file path\n * @param filePath - Path to the schema file\n */\n setSchemaPath(filePath: string): void {\n this.schemaFilePath = filePath;\n this.clearCache();\n }\n}\n\n// Export a singleton instance for use across the application\nexport const schema = new Schema();\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport Groq from \"groq-sdk\";\nimport { GoogleGenerativeAI, SchemaType, FunctionDeclarationSchemaProperty } from \"@google/generative-ai\";\nimport OpenAI from \"openai\";\nimport { jsonrepair } from 'jsonrepair';\nimport { llmUsageLogger, LLMUsageEntry } from './utils/llm-usage-logger';\nimport { userPromptErrorLogger } from './utils/user-prompt-error-logger';\n\n// System prompt can be either a simple string or an array of content blocks for caching\ntype SystemPrompt = string | Anthropic.Messages.TextBlockParam[];\n\ninterface LLMMessages {\n sys: SystemPrompt;\n user: string;\n prefill?: string; // Optional assistant prefill to force specific output format (e.g., \"{\" for JSON)\n}\n\ninterface LLMOptions {\n model?: string;\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n apiKey?: string;\n partial?: (chunk: string) => void; // Callback for each chunk\n}\n\ninterface Tool {\n name: string;\n description: string;\n input_schema: {\n type: string;\n properties: Record<string, any>;\n required?: string[];\n };\n}\n\ninterface ToolResult {\n tool_use_id: string;\n content: string;\n is_error?: boolean;\n}\n\nexport class LLM {\n /* Get a complete text response from an LLM (Anthropic or Groq) */\n static async text(messages: LLMMessages, options: LLMOptions = {}): Promise<string> {\n const [provider, modelName] = this._parseModel(options.model);\n\n if (provider === 'anthropic') {\n return this._anthropicText(messages, modelName, options);\n } else if (provider === 'groq') {\n return this._groqText(messages, modelName, options);\n } else if (provider === 'gemini') {\n return this._geminiText(messages, modelName, options);\n } else if (provider === 'openai') {\n return this._openaiText(messages, modelName, options);\n } else {\n throw new Error(`Unsupported provider: ${provider}. Use \"anthropic\", \"groq\", \"gemini\", or \"openai\"`);\n }\n }\n\n /* Stream response from an LLM (Anthropic or Groq) */\n static async stream<T = string>(\n messages: LLMMessages,\n options: LLMOptions = {},\n json?: boolean\n ): Promise<T extends string ? string : any> {\n const [provider, modelName] = this._parseModel(options.model);\n\n if (provider === 'anthropic') {\n return this._anthropicStream(messages, modelName, options, json);\n } else if (provider === 'groq') {\n return this._groqStream(messages, modelName, options, json);\n } else if (provider === 'gemini') {\n return this._geminiStream(messages, modelName, options, json);\n } else if (provider === 'openai') {\n return this._openaiStream(messages, modelName, options, json);\n } else {\n throw new Error(`Unsupported provider: ${provider}. Use \"anthropic\", \"groq\", \"gemini\", or \"openai\"`);\n }\n }\n\n /* Stream response with tool calling support (Anthropic and Gemini) */\n static async streamWithTools(\n messages: LLMMessages,\n tools: Tool[],\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\n options: LLMOptions = {},\n maxIterations: number = 3\n ): Promise<string> {\n const [provider, modelName] = this._parseModel(options.model);\n\n if (provider === 'anthropic') {\n return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);\n } else if (provider === 'gemini') {\n return this._geminiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);\n } else if (provider === 'openai') {\n return this._openaiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);\n } else {\n throw new Error(`Tool calling is only supported for Anthropic, Gemini, and OpenAI models`);\n }\n }\n\n // ============================================================\n // PRIVATE HELPER METHODS\n // ============================================================\n\n /**\n * Normalize system prompt to Anthropic format\n * Converts string to array format if needed\n * @param sys - System prompt (string or array of blocks)\n * @returns Normalized system prompt for Anthropic API\n */\n private static _normalizeSystemPrompt(sys: SystemPrompt): string | Anthropic.Messages.TextBlockParam[] {\n // If it's already a string, return as-is for backward compatibility\n if (typeof sys === 'string') {\n return sys;\n }\n\n // If it's an array, return it for caching support\n return sys;\n }\n\n /**\n * Log cache usage metrics from Anthropic API response\n * Shows cache hits, costs, and savings\n */\n private static _logCacheUsage(usage: any): void {\n if (!usage) return;\n\n const inputTokens = usage.input_tokens || 0;\n const cacheCreationTokens = usage.cache_creation_input_tokens || 0;\n const cacheReadTokens = usage.cache_read_input_tokens || 0;\n const outputTokens = usage.output_tokens || 0;\n\n // Pricing (per 1M tokens) for Claude Haiku 4.5\n const INPUT_PRICE = 0.80; // $0.80 per 1M tokens\n const OUTPUT_PRICE = 4.00; // $4.00 per 1M tokens\n const CACHE_WRITE_PRICE = 1.00; // $1.00 per 1M tokens (25% markup)\n const CACHE_READ_PRICE = 0.08; // $0.08 per 1M tokens (90% discount)\n\n // Calculate costs\n const regularInputCost = (inputTokens / 1_000_000) * INPUT_PRICE;\n const cacheWriteCost = (cacheCreationTokens / 1_000_000) * CACHE_WRITE_PRICE;\n const cacheReadCost = (cacheReadTokens / 1_000_000) * CACHE_READ_PRICE;\n const outputCost = (outputTokens / 1_000_000) * OUTPUT_PRICE;\n const totalCost = regularInputCost + cacheWriteCost + cacheReadCost + outputCost;\n\n // Calculate what it would have cost without caching\n const totalInputTokens = inputTokens + cacheCreationTokens + cacheReadTokens;\n const costWithoutCache = (totalInputTokens / 1_000_000) * INPUT_PRICE + outputCost;\n const savings = costWithoutCache - totalCost;\n const savingsPercent = costWithoutCache > 0 ? (savings / costWithoutCache * 100) : 0;\n\n // Log metrics\n console.log('\\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.log('💰 PROMPT CACHING METRICS');\n console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n\n console.log('\\n📊 Token Usage:');\n console.log(` Input (regular): ${inputTokens.toLocaleString()} tokens`);\n if (cacheCreationTokens > 0) {\n console.log(` Cache write: ${cacheCreationTokens.toLocaleString()} tokens (first request)`);\n }\n if (cacheReadTokens > 0) {\n console.log(` Cache read: ${cacheReadTokens.toLocaleString()} tokens ⚡ HIT!`);\n }\n console.log(` Output: ${outputTokens.toLocaleString()} tokens`);\n console.log(` Total input: ${totalInputTokens.toLocaleString()} tokens`);\n\n console.log('\\n💵 Cost Breakdown:');\n console.log(` Input (regular): $${regularInputCost.toFixed(6)}`);\n if (cacheCreationTokens > 0) {\n console.log(` Cache write: $${cacheWriteCost.toFixed(6)}`);\n }\n if (cacheReadTokens > 0) {\n console.log(` Cache read: $${cacheReadCost.toFixed(6)} (90% off!)`);\n }\n console.log(` Output: $${outputCost.toFixed(6)}`);\n console.log(` ─────────────────────────────────────`);\n console.log(` Total cost: $${totalCost.toFixed(6)}`);\n\n if (cacheReadTokens > 0) {\n console.log(`\\n💎 Savings: $${savings.toFixed(6)} (${savingsPercent.toFixed(1)}% off)`);\n console.log(` Without cache: $${costWithoutCache.toFixed(6)}`);\n } else if (cacheCreationTokens > 0) {\n console.log(`\\n⏱️ Cache created - next request will be ~90% cheaper!`);\n }\n\n console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n');\n }\n\n /**\n * Parse model string to extract provider and model name\n * @param modelString - Format: \"provider/model-name\" or just \"model-name\"\n * @returns [provider, modelName]\n *\n * @example\n * \"anthropic/claude-sonnet-4-5\" → [\"anthropic\", \"claude-sonnet-4-5\"]\n * \"groq/openai/gpt-oss-120b\" → [\"groq\", \"openai/gpt-oss-120b\"]\n * \"claude-sonnet-4-5\" → [\"anthropic\", \"claude-sonnet-4-5\"] (default)\n */\n private static _parseModel(modelString?: string): [string, string] {\n if (!modelString) {\n // Default to Anthropic Claude\n return ['anthropic', 'claude-sonnet-4-5'];\n }\n\n // Check if model string has provider prefix\n if (modelString.includes('/')) {\n // Split only on the FIRST slash to handle models like \"groq/openai/gpt-oss-120b\"\n const firstSlashIndex = modelString.indexOf('/');\n const provider = modelString.substring(0, firstSlashIndex).toLowerCase().trim();\n const model = modelString.substring(firstSlashIndex + 1).trim();\n return [provider, model];\n }\n\n // No prefix, assume Anthropic\n return ['anthropic', modelString];\n }\n\n // ============================================================\n // ANTHROPIC IMPLEMENTATION\n // ============================================================\n\n private static async _anthropicText(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions\n ): Promise<string> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\n const client = new Anthropic({\n apiKey: apiKey,\n });\n\n try {\n const response = await client.messages.create({\n model: modelName,\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n system: this._normalizeSystemPrompt(messages.sys) as any,\n messages: [{\n role: \"user\",\n content: messages.user\n }]\n });\n\n const durationMs = Date.now() - startTime;\n const usage = response.usage as any;\n\n // Log usage\n const inputTokens = usage?.input_tokens || 0;\n const outputTokens = usage?.output_tokens || 0;\n const cacheReadTokens = usage?.cache_read_input_tokens || 0;\n const cacheWriteTokens = usage?.cache_creation_input_tokens || 0;\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: 'text',\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n totalTokens: inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens),\n durationMs,\n success: true,\n });\n\n const textBlock = response.content.find(block => block.type === 'text');\n return textBlock?.type === 'text' ? textBlock.text : '';\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: 'text',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _anthropicStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\n const client = new Anthropic({\n apiKey: apiKey,\n });\n\n try {\n // Build messages array\n const apiMessages: Anthropic.Messages.MessageParam[] = [{\n role: \"user\",\n content: messages.user\n }];\n\n // Add prefill to force specific output format (e.g., \"{\" for JSON)\n // For JSON mode, automatically prefill with \"{\" if no explicit prefill provided\n const prefill = messages.prefill || (json ? \"{\" : undefined);\n if (prefill) {\n apiMessages.push({\n role: \"assistant\",\n content: prefill\n });\n }\n\n const stream = await client.messages.create({\n model: modelName,\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n system: this._normalizeSystemPrompt(messages.sys) as any,\n messages: apiMessages,\n stream: true,\n });\n\n // Start with prefill if provided (since model continues from there)\n let fullText = prefill || '';\n let usage: any = null;\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheReadTokens = 0;\n let cacheWriteTokens = 0;\n\n // Process stream\n for await (const chunk of stream) {\n if (chunk.type === 'content_block_delta' && chunk.delta.type === 'text_delta') {\n const text = chunk.delta.text;\n fullText += text;\n\n // Call partial callback if provided\n if (options.partial) {\n options.partial(text);\n }\n } else if (chunk.type === 'message_start' && (chunk as any).message?.usage) {\n // Capture input tokens from message_start\n const msgUsage = (chunk as any).message.usage;\n inputTokens = msgUsage.input_tokens || 0;\n cacheReadTokens = msgUsage.cache_read_input_tokens || 0;\n cacheWriteTokens = msgUsage.cache_creation_input_tokens || 0;\n } else if (chunk.type === 'message_delta' && (chunk as any).usage) {\n // Capture output tokens from message_delta event\n usage = (chunk as any).usage;\n outputTokens = usage.output_tokens || 0;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Log usage\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: 'stream',\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n totalTokens: inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens),\n durationMs,\n success: true,\n });\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: 'stream',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _anthropicStreamWithTools(\n messages: LLMMessages,\n tools: Tool[],\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\n modelName: string,\n options: LLMOptions,\n maxIterations: number\n ): Promise<string> {\n const methodStartTime = Date.now();\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\n const client = new Anthropic({\n apiKey: apiKey,\n });\n\n // Conversation history for tool calling loop\n const conversationMessages: Anthropic.MessageParam[] = [{\n role: \"user\",\n content: messages.user\n }];\n\n let iterations = 0;\n let finalText = '';\n let totalToolCalls = 0;\n\n // Track cumulative usage across all iterations\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCacheReadTokens = 0;\n let totalCacheWriteTokens = 0;\n\n while (iterations < maxIterations) {\n iterations++;\n const iterationStartTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n\n // Use streaming API\n const stream = await client.messages.create({\n model: modelName,\n max_tokens: options.maxTokens || 4000,\n temperature: options.temperature,\n system: this._normalizeSystemPrompt(messages.sys) as any,\n messages: conversationMessages,\n tools: tools as any,\n stream: true, // Enable streaming\n });\n\n // Collect the response content and stop reason\n let stopReason: string | null = null;\n const contentBlocks: any[] = [];\n let currentTextBlock = '';\n let currentToolUse: any = null;\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheReadTokens = 0;\n let cacheWriteTokens = 0;\n\n // Process the stream\n for await (const chunk of stream) {\n if (chunk.type === 'message_start') {\n // Reset for new message\n contentBlocks.length = 0;\n currentTextBlock = '';\n currentToolUse = null;\n // Capture input tokens from message_start\n const msgUsage = (chunk as any).message?.usage;\n if (msgUsage) {\n inputTokens = msgUsage.input_tokens || 0;\n cacheReadTokens = msgUsage.cache_read_input_tokens || 0;\n cacheWriteTokens = msgUsage.cache_creation_input_tokens || 0;\n }\n }\n\n if (chunk.type === 'content_block_start') {\n if (chunk.content_block.type === 'text') {\n currentTextBlock = '';\n } else if (chunk.content_block.type === 'tool_use') {\n currentToolUse = {\n type: 'tool_use',\n id: chunk.content_block.id,\n name: chunk.content_block.name,\n input: {}\n };\n }\n }\n\n if (chunk.type === 'content_block_delta') {\n if (chunk.delta.type === 'text_delta') {\n // Stream text chunks to callback\n const text = chunk.delta.text;\n currentTextBlock += text;\n if (options.partial) {\n options.partial(text);\n }\n } else if (chunk.delta.type === 'input_json_delta' && currentToolUse) {\n // Accumulate tool input JSON\n currentToolUse.inputJson = (currentToolUse.inputJson || '') + chunk.delta.partial_json;\n }\n }\n\n if (chunk.type === 'content_block_stop') {\n if (currentTextBlock) {\n contentBlocks.push({\n type: 'text',\n text: currentTextBlock\n });\n finalText = currentTextBlock; // Keep track of final text\n currentTextBlock = '';\n } else if (currentToolUse) {\n // Parse the accumulated JSON input\n try {\n currentToolUse.input = currentToolUse.inputJson ? JSON.parse(currentToolUse.inputJson) : {};\n } catch (error) {\n currentToolUse.input = {};\n }\n delete currentToolUse.inputJson;\n contentBlocks.push(currentToolUse);\n currentToolUse = null;\n }\n }\n\n if (chunk.type === 'message_delta') {\n stopReason = chunk.delta.stop_reason || stopReason;\n // Capture output tokens from message_delta\n if ((chunk as any).usage) {\n outputTokens = (chunk as any).usage.output_tokens || 0;\n }\n }\n\n if (chunk.type === 'message_stop') {\n // Message complete\n break;\n }\n }\n\n const iterationDuration = Date.now() - iterationStartTime;\n const toolUsesInIteration = contentBlocks.filter(block => block.type === 'tool_use').length;\n totalToolCalls += toolUsesInIteration;\n\n // Update cumulative totals\n totalInputTokens += inputTokens;\n totalOutputTokens += outputTokens;\n totalCacheReadTokens += cacheReadTokens;\n totalCacheWriteTokens += cacheWriteTokens;\n\n // Log this iteration\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: `streamWithTools[iter=${iterations}]`,\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n totalTokens: inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens),\n durationMs: iterationDuration,\n toolCalls: toolUsesInIteration,\n success: true,\n });\n\n // Check stop reason\n if (stopReason === 'end_turn') {\n // Final text response already streamed\n break;\n }\n\n if (stopReason === 'tool_use') {\n // Find all tool use blocks\n const toolUses = contentBlocks.filter(block => block.type === 'tool_use');\n\n if (toolUses.length === 0) {\n break;\n }\n\n // Add assistant's response to conversation\n conversationMessages.push({\n role: \"assistant\",\n content: contentBlocks\n });\n\n // Execute all tools and collect results\n const toolResults: Anthropic.MessageParam = {\n role: \"user\",\n content: []\n };\n\n for (const toolUse of toolUses) {\n try {\n const result = await toolHandler(toolUse.name, toolUse.input);\n // Truncate very large results to reduce memory and token usage\n let resultContent = typeof result === 'string' ? result : JSON.stringify(result);\n const MAX_RESULT_LENGTH = 50000; // ~12k tokens max per tool result\n if (resultContent.length > MAX_RESULT_LENGTH) {\n resultContent = resultContent.substring(0, MAX_RESULT_LENGTH) +\n '\\n\\n... [Result truncated - showing first 50000 characters of ' + resultContent.length + ' total]';\n }\n (toolResults.content as any[]).push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: resultContent\n });\n } catch (error) {\n (toolResults.content as any[]).push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: error instanceof Error ? error.message : String(error),\n is_error: true\n });\n }\n }\n\n // Add tool results to conversation\n conversationMessages.push(toolResults);\n } else {\n // Unexpected stop reason, final text already streamed\n break;\n }\n }\n\n // Log total summary for all iterations\n const totalDuration = Date.now() - methodStartTime;\n if (iterations > 1) {\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId: llmUsageLogger.generateRequestId(),\n provider: 'anthropic',\n model: modelName,\n method: `streamWithTools[TOTAL:${iterations}iters]`,\n inputTokens: totalInputTokens,\n outputTokens: totalOutputTokens,\n cacheReadTokens: totalCacheReadTokens,\n cacheWriteTokens: totalCacheWriteTokens,\n totalTokens: totalInputTokens + totalOutputTokens + totalCacheReadTokens + totalCacheWriteTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, totalInputTokens, totalOutputTokens, totalCacheReadTokens, totalCacheWriteTokens),\n durationMs: totalDuration,\n toolCalls: totalToolCalls,\n success: true,\n });\n }\n\n if (iterations >= maxIterations) {\n throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);\n }\n\n return finalText;\n }\n\n // ============================================================\n // GROQ IMPLEMENTATION\n // ============================================================\n\n private static async _groqText(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions\n ): Promise<string> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const client = new Groq({\n apiKey: options.apiKey || process.env.GROQ_API_KEY || \"\",\n });\n\n try {\n const response = await client.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: messages.sys as string },\n { role: 'user', content: messages.user }\n ],\n temperature: options.temperature,\n max_tokens: options.maxTokens || 1000,\n });\n\n const durationMs = Date.now() - startTime;\n const usage = response.usage;\n const inputTokens = usage?.prompt_tokens || 0;\n const outputTokens = usage?.completion_tokens || 0;\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'groq',\n model: modelName,\n method: 'text',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n return response.choices[0]?.message?.content || '';\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'groq',\n model: modelName,\n method: 'text',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _groqStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.GROQ_API_KEY || \"\";\n const client = new Groq({\n apiKey: apiKey,\n });\n\n try {\n const stream = await client.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: messages.sys as string },\n { role: 'user', content: messages.user }\n ],\n temperature: options.temperature,\n max_tokens: options.maxTokens || 1000,\n stream: true,\n response_format: json ? { type: 'json_object' } : undefined\n });\n\n let fullText = '';\n let inputTokens = 0;\n let outputTokens = 0;\n\n // Process stream\n for await (const chunk of stream) {\n const text = chunk.choices[0]?.delta?.content || '';\n if (text) {\n fullText += text;\n\n // Call partial callback if provided\n if (options.partial) {\n options.partial(text);\n }\n }\n // Groq provides usage in the last chunk\n if ((chunk as any).x_groq?.usage) {\n inputTokens = (chunk as any).x_groq.usage.prompt_tokens || 0;\n outputTokens = (chunk as any).x_groq.usage.completion_tokens || 0;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Estimate tokens if not provided (Groq streaming may not always provide usage)\n if (inputTokens === 0) {\n // Rough estimate: 1 token ≈ 4 characters\n const sysPrompt = typeof messages.sys === 'string' ? messages.sys : messages.sys.map(b => b.text).join('');\n inputTokens = Math.ceil((sysPrompt.length + messages.user.length) / 4);\n }\n if (outputTokens === 0) {\n outputTokens = Math.ceil(fullText.length / 4);\n }\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'groq',\n model: modelName,\n method: 'stream',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'groq',\n model: modelName,\n method: 'stream',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n // ============================================================\n // GEMINI IMPLEMENTATION\n // ============================================================\n\n private static async _geminiText(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions\n ): Promise<string> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.GEMINI_API_KEY || \"\";\n const genAI = new GoogleGenerativeAI(apiKey);\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n try {\n const model = genAI.getGenerativeModel({\n model: modelName,\n systemInstruction: systemPrompt,\n generationConfig: {\n maxOutputTokens: options.maxTokens || 1000,\n temperature: options.temperature,\n topP: options.topP,\n }\n });\n\n const result = await model.generateContent(messages.user);\n const response = await result.response;\n const text = response.text();\n const durationMs = Date.now() - startTime;\n\n // Gemini provides usage metadata\n const usage = response.usageMetadata;\n const inputTokens = usage?.promptTokenCount || Math.ceil((systemPrompt.length + messages.user.length) / 4);\n const outputTokens = usage?.candidatesTokenCount || Math.ceil(text.length / 4);\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: 'text',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n return text;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: 'text',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _geminiStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.GEMINI_API_KEY || \"\";\n const genAI = new GoogleGenerativeAI(apiKey);\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n try {\n const model = genAI.getGenerativeModel({\n model: modelName,\n systemInstruction: systemPrompt,\n generationConfig: {\n maxOutputTokens: options.maxTokens || 1000,\n temperature: options.temperature,\n topP: options.topP,\n responseMimeType: json ? 'application/json' : undefined,\n }\n });\n\n const result = await model.generateContentStream(messages.user);\n\n let fullText = '';\n let inputTokens = 0;\n let outputTokens = 0;\n\n // Process stream\n for await (const chunk of result.stream) {\n const text = chunk.text();\n if (text) {\n fullText += text;\n\n // Call partial callback if provided\n if (options.partial) {\n options.partial(text);\n }\n }\n // Capture usage from final chunk\n if (chunk.usageMetadata) {\n inputTokens = chunk.usageMetadata.promptTokenCount || 0;\n outputTokens = chunk.usageMetadata.candidatesTokenCount || 0;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Estimate tokens if not provided\n if (inputTokens === 0) {\n inputTokens = Math.ceil((systemPrompt.length + messages.user.length) / 4);\n }\n if (outputTokens === 0) {\n outputTokens = Math.ceil(fullText.length / 4);\n }\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: 'stream',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: 'stream',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _geminiStreamWithTools(\n messages: LLMMessages,\n tools: Tool[],\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\n modelName: string,\n options: LLMOptions,\n maxIterations: number\n ): Promise<string> {\n const apiKey = options.apiKey || process.env.GEMINI_API_KEY || \"\";\n const genAI = new GoogleGenerativeAI(apiKey);\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n // Convert tools to Gemini function declarations format\n const functionDeclarations = tools.map(tool => ({\n name: tool.name,\n description: tool.description,\n parameters: {\n type: SchemaType.OBJECT,\n properties: tool.input_schema.properties as { [key: string]: FunctionDeclarationSchemaProperty },\n required: tool.input_schema.required || []\n }\n }));\n\n const model = genAI.getGenerativeModel({\n model: modelName,\n systemInstruction: systemPrompt,\n tools: [{ functionDeclarations }],\n generationConfig: {\n maxOutputTokens: options.maxTokens || 4000,\n temperature: options.temperature,\n topP: options.topP,\n }\n });\n\n // Start a chat session to maintain conversation history for tool calling loop\n const chat = model.startChat({\n history: []\n });\n\n let iterations = 0;\n let finalText = '';\n let currentUserMessage = messages.user;\n\n while (iterations < maxIterations) {\n iterations++;\n\n // Send message and stream the response\n const result = await chat.sendMessageStream(currentUserMessage);\n\n let responseText = '';\n const functionCalls: Array<{ name: string; args: any }> = [];\n\n // Process the stream\n for await (const chunk of result.stream) {\n const candidate = chunk.candidates?.[0];\n if (!candidate) continue;\n\n for (const part of candidate.content?.parts || []) {\n if (part.text) {\n responseText += part.text;\n // Stream text chunks to callback\n if (options.partial) {\n options.partial(part.text);\n }\n } else if (part.functionCall) {\n functionCalls.push({\n name: part.functionCall.name,\n args: part.functionCall.args\n });\n }\n }\n }\n\n // If no function calls, we're done\n if (functionCalls.length === 0) {\n finalText = responseText;\n break;\n }\n\n // Execute all function calls and collect results\n const functionResponses: Array<{ name: string; response: any }> = [];\n\n for (const fc of functionCalls) {\n try {\n const result = await toolHandler(fc.name, fc.args);\n // Truncate very large results to reduce memory and token usage\n let resultContent = typeof result === 'string' ? result : JSON.stringify(result);\n const MAX_RESULT_LENGTH = 50000; // ~12k tokens max per tool result\n if (resultContent.length > MAX_RESULT_LENGTH) {\n resultContent = resultContent.substring(0, MAX_RESULT_LENGTH) +\n '\\n\\n... [Result truncated - showing first 50000 characters of ' + resultContent.length + ' total]';\n }\n functionResponses.push({\n name: fc.name,\n response: { result: resultContent }\n });\n } catch (error) {\n functionResponses.push({\n name: fc.name,\n response: { error: error instanceof Error ? error.message : String(error) }\n });\n }\n }\n\n // Send function responses back to the model\n // Build the function response parts for the next message\n const functionResponseParts = functionResponses.map(fr => ({\n functionResponse: {\n name: fr.name,\n response: fr.response\n }\n }));\n\n // Send function responses as the next user message\n currentUserMessage = functionResponseParts as any;\n }\n\n if (iterations >= maxIterations) {\n throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);\n }\n\n return finalText;\n }\n\n // ============================================================\n // OPENAI IMPLEMENTATION\n // ============================================================\n\n private static async _openaiText(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions\n ): Promise<string> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.OPENAI_API_KEY || \"\";\n const openai = new OpenAI({ apiKey });\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n try {\n const response = await openai.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: messages.user }\n ],\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n top_p: options.topP,\n });\n\n const durationMs = Date.now() - startTime;\n const usage = response.usage;\n const inputTokens = usage?.prompt_tokens || 0;\n const outputTokens = usage?.completion_tokens || 0;\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'openai',\n model: modelName,\n method: 'text',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n return response.choices[0]?.message?.content || '';\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'openai',\n model: modelName,\n method: 'text',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _openaiStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.OPENAI_API_KEY || \"\";\n const openai = new OpenAI({ apiKey });\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n try {\n const stream = await openai.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: messages.user }\n ],\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n top_p: options.topP,\n response_format: json ? { type: 'json_object' } : undefined,\n stream: true,\n stream_options: { include_usage: true }, // Request usage info in stream\n });\n\n let fullText = '';\n let inputTokens = 0;\n let outputTokens = 0;\n\n for await (const chunk of stream) {\n const content = chunk.choices[0]?.delta?.content || '';\n if (content) {\n fullText += content;\n\n // Call partial callback if provided\n if (options.partial) {\n options.partial(content);\n }\n }\n // OpenAI provides usage in the final chunk when stream_options.include_usage is true\n if (chunk.usage) {\n inputTokens = chunk.usage.prompt_tokens || 0;\n outputTokens = chunk.usage.completion_tokens || 0;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Estimate tokens if not provided\n if (inputTokens === 0) {\n inputTokens = Math.ceil((systemPrompt.length + messages.user.length) / 4);\n }\n if (outputTokens === 0) {\n outputTokens = Math.ceil(fullText.length / 4);\n }\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'openai',\n model: modelName,\n method: 'stream',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'openai',\n model: modelName,\n method: 'stream',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _openaiStreamWithTools(\n messages: LLMMessages,\n tools: Tool[],\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\n modelName: string,\n options: LLMOptions,\n maxIterations: number\n ): Promise<string> {\n const apiKey = options.apiKey || process.env.OPENAI_API_KEY || \"\";\n const openai = new OpenAI({ apiKey });\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n // Convert tools to OpenAI function format\n const openaiTools: OpenAI.Chat.Completions.ChatCompletionTool[] = tools.map(tool => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: tool.input_schema.type,\n properties: tool.input_schema.properties,\n required: tool.input_schema.required || []\n }\n }\n }));\n\n // Build conversation messages\n const conversationMessages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: messages.user }\n ];\n\n let iterations = 0;\n let finalText = '';\n\n while (iterations < maxIterations) {\n iterations++;\n\n const stream = await openai.chat.completions.create({\n model: modelName,\n messages: conversationMessages,\n max_tokens: options.maxTokens || 4000,\n temperature: options.temperature,\n top_p: options.topP,\n tools: openaiTools,\n stream: true,\n });\n\n let responseText = '';\n const toolCalls: Array<{\n id: string;\n name: string;\n arguments: string;\n }> = [];\n\n // Track tool call assembly (OpenAI streams tool calls in chunks)\n const toolCallsInProgress: Map<number, { id: string; name: string; arguments: string }> = new Map();\n\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n // Handle text content\n if (delta?.content) {\n responseText += delta.content;\n if (options.partial) {\n options.partial(delta.content);\n }\n }\n\n // Handle tool calls\n if (delta?.tool_calls) {\n for (const toolCallDelta of delta.tool_calls) {\n const index = toolCallDelta.index;\n\n if (!toolCallsInProgress.has(index)) {\n toolCallsInProgress.set(index, {\n id: toolCallDelta.id || '',\n name: toolCallDelta.function?.name || '',\n arguments: ''\n });\n }\n\n const tc = toolCallsInProgress.get(index)!;\n\n if (toolCallDelta.id) {\n tc.id = toolCallDelta.id;\n }\n if (toolCallDelta.function?.name) {\n tc.name = toolCallDelta.function.name;\n }\n if (toolCallDelta.function?.arguments) {\n tc.arguments += toolCallDelta.function.arguments;\n }\n }\n }\n }\n\n // Collect completed tool calls\n for (const tc of toolCallsInProgress.values()) {\n if (tc.id && tc.name) {\n toolCalls.push(tc);\n }\n }\n\n // If no tool calls, we're done\n if (toolCalls.length === 0) {\n finalText = responseText;\n break;\n }\n\n // Add assistant message with tool calls to conversation\n conversationMessages.push({\n role: 'assistant',\n content: responseText || null,\n tool_calls: toolCalls.map(tc => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.name,\n arguments: tc.arguments\n }\n }))\n });\n\n // Execute tool calls and add results\n for (const tc of toolCalls) {\n let result: string;\n try {\n const args = JSON.parse(tc.arguments);\n const toolResult = await toolHandler(tc.name, args);\n result = typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult);\n // Truncate very large results to reduce memory and token usage\n const MAX_RESULT_LENGTH = 50000; // ~12k tokens max per tool result\n if (result.length > MAX_RESULT_LENGTH) {\n result = result.substring(0, MAX_RESULT_LENGTH) +\n '\\n\\n... [Result truncated - showing first 50000 characters of ' + result.length + ' total]';\n }\n } catch (error) {\n result = JSON.stringify({ error: error instanceof Error ? error.message : String(error) });\n }\n\n conversationMessages.push({\n role: 'tool',\n tool_call_id: tc.id,\n content: result\n });\n }\n }\n\n if (iterations >= maxIterations) {\n throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);\n }\n\n return finalText;\n }\n\n // ============================================================\n // JSON PARSING HELPER\n // ============================================================\n\n /**\n * Parse JSON string, handling markdown code blocks and surrounding text\n * Enhanced version with jsonrepair to handle malformed JSON from LLMs\n * @param text - Text that may contain JSON wrapped in ```json...``` or with surrounding text\n * @returns Parsed JSON object or array\n */\n private static _parseJSON(text: string): any {\n let jsonText = text.trim();\n\n // Step 1: Remove markdown code blocks (jsonrepair doesn't handle markdown)\n if (jsonText.startsWith('```json')) {\n jsonText = jsonText.replace(/^```json\\s*\\n?/, '').replace(/\\n?```\\s*$/, '');\n } else if (jsonText.startsWith('```')) {\n jsonText = jsonText.replace(/^```\\s*\\n?/, '').replace(/\\n?```\\s*$/, '');\n }\n\n // Step 2: Extract JSON from surrounding text using proper brace matching\n // Find the first JSON object or array and extract only that\n const firstBrace = jsonText.indexOf('{');\n const firstBracket = jsonText.indexOf('[');\n\n // Determine if it's an object or array\n let startIdx = -1;\n let openChar = '';\n let closeChar = '';\n\n if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {\n // Object starts first\n startIdx = firstBrace;\n openChar = '{';\n closeChar = '}';\n } else if (firstBracket !== -1) {\n // Array starts first\n startIdx = firstBracket;\n openChar = '[';\n closeChar = ']';\n }\n\n // If no JSON structure found at all, throw a clear error\n if (startIdx === -1) {\n const error = new Error(`No JSON found in response. LLM returned plain text instead of JSON.`);\n userPromptErrorLogger.logJsonParseError('LLM._parseJSON - No JSON structure found', text, error);\n throw error;\n }\n\n // Find the MATCHING closing brace/bracket (not the last one in the document)\n let depth = 0;\n let inString = false;\n let endIdx = -1;\n\n for (let i = startIdx; i < jsonText.length; i++) {\n const char = jsonText[i];\n const prevChar = i > 0 ? jsonText[i - 1] : '';\n\n // Handle string literals (skip content inside quotes)\n if (char === '\"' && prevChar !== '\\\\') {\n inString = !inString;\n continue;\n }\n\n if (!inString) {\n if (char === openChar) {\n depth++;\n } else if (char === closeChar) {\n depth--;\n if (depth === 0) {\n endIdx = i;\n break;\n }\n }\n }\n }\n\n if (endIdx !== -1) {\n jsonText = jsonText.substring(startIdx, endIdx + 1);\n } else {\n // No matching closing brace found\n const error = new Error(`Incomplete JSON - no matching closing ${closeChar} found.`);\n userPromptErrorLogger.logJsonParseError('LLM._parseJSON - Incomplete JSON', text, error);\n throw error;\n }\n\n // Step 3: Use jsonrepair to fix malformed JSON before parsing\n // This handles: missing commas, trailing commas, incomplete JSON, improper escaping, etc.\n try {\n const repairedJson = jsonrepair(jsonText);\n return JSON.parse(repairedJson);\n } catch (error) {\n // If jsonrepair fails, log the full raw string and throw\n const parseError = error instanceof Error ? error : new Error(String(error));\n userPromptErrorLogger.logJsonParseError('LLM._parseJSON - JSON parse/repair failed', text, parseError);\n throw new Error(`Failed to parse JSON: ${parseError.message}`);\n }\n }\n}","import fs from 'fs';\nimport path from 'path';\n\n/**\n * LLM Usage Logger - Tracks token usage, costs, and timing for all LLM API calls\n */\n\nexport interface LLMUsageEntry {\n timestamp: string;\n requestId: string;\n provider: string;\n model: string;\n method: string; // 'text' | 'stream' | 'streamWithTools'\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n totalTokens: number;\n costUSD: number;\n durationMs: number;\n toolCalls?: number;\n success: boolean;\n error?: string;\n}\n\n// Pricing per 1M tokens (as of Dec 2024)\nconst PRICING: Record<string, { input: number; output: number; cacheRead?: number; cacheWrite?: number }> = {\n // Anthropic\n 'claude-3-5-sonnet-20241022': { input: 3.00, output: 15.00, cacheRead: 0.30, cacheWrite: 3.75 },\n 'claude-sonnet-4-5': { input: 3.00, output: 15.00, cacheRead: 0.30, cacheWrite: 3.75 },\n 'claude-sonnet-4-5-20250929': { input: 3.00, output: 15.00, cacheRead: 0.30, cacheWrite: 3.75 },\n 'claude-3-5-haiku-20241022': { input: 0.80, output: 4.00, cacheRead: 0.08, cacheWrite: 1.00 },\n 'claude-haiku-4-5-20251001': { input: 0.80, output: 4.00, cacheRead: 0.08, cacheWrite: 1.00 },\n 'claude-3-opus-20240229': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },\n 'claude-3-sonnet-20240229': { input: 3.00, output: 15.00, cacheRead: 0.30, cacheWrite: 3.75 },\n 'claude-3-haiku-20240307': { input: 0.25, output: 1.25, cacheRead: 0.03, cacheWrite: 0.30 },\n\n // OpenAI\n 'gpt-4o': { input: 2.50, output: 10.00 },\n 'gpt-4o-mini': { input: 0.15, output: 0.60 },\n 'gpt-4-turbo': { input: 10.00, output: 30.00 },\n 'gpt-4': { input: 30.00, output: 60.00 },\n 'gpt-3.5-turbo': { input: 0.50, output: 1.50 },\n\n // Gemini\n 'gemini-1.5-pro': { input: 1.25, output: 5.00 },\n 'gemini-1.5-flash': { input: 0.075, output: 0.30 },\n 'gemini-2.0-flash-exp': { input: 0.10, output: 0.40 },\n\n // Groq (very cheap)\n 'llama-3.3-70b-versatile': { input: 0.59, output: 0.79 },\n 'llama-3.1-70b-versatile': { input: 0.59, output: 0.79 },\n 'llama-3.1-8b-instant': { input: 0.05, output: 0.08 },\n 'mixtral-8x7b-32768': { input: 0.24, output: 0.24 },\n};\n\n// Default pricing for unknown models\nconst DEFAULT_PRICING = { input: 3.00, output: 15.00 };\n\nclass LLMUsageLogger {\n private logStream: fs.WriteStream | null = null;\n private logPath: string;\n private enabled: boolean;\n private sessionStats = {\n totalCalls: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheWriteTokens: 0,\n totalCostUSD: 0,\n totalDurationMs: 0,\n };\n\n constructor() {\n // Get log path from environment or use default\n this.logPath = process.env.LLM_USAGE_LOG_PATH || path.join(process.cwd(), 'llm-usage-logs');\n this.enabled = process.env.LLM_USAGE_LOGGING !== 'false';\n\n if (this.enabled) {\n this.initLogStream();\n }\n }\n\n private initLogStream(): void {\n try {\n // Ensure directory exists\n const dir = path.dirname(this.logPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n this.logStream = fs.createWriteStream(this.logPath, { flags: 'a' });\n\n // Write header if file is new/empty\n if (!fs.existsSync(this.logPath) || fs.statSync(this.logPath).size === 0) {\n this.writeHeader();\n }\n } catch (error) {\n console.error('[LLM-Usage-Logger] Failed to initialize log stream:', error);\n this.enabled = false;\n }\n }\n\n private writeHeader(): void {\n const header = `\n================================================================================\nLLM USAGE LOG - Session Started: ${new Date().toISOString()}\n================================================================================\nFormat: [TIMESTAMP] [REQUEST_ID] [PROVIDER/MODEL] [METHOD]\n Tokens: IN=input OUT=output CACHE_R=cache_read CACHE_W=cache_write TOTAL=total\n Cost: $X.XXXXXX | Time: Xms\n================================================================================\n\n`;\n this.logStream?.write(header);\n }\n\n /**\n * Calculate cost based on token usage and model\n */\n calculateCost(\n model: string,\n inputTokens: number,\n outputTokens: number,\n cacheReadTokens = 0,\n cacheWriteTokens = 0\n ): number {\n // Find pricing for model (try exact match, then partial match)\n let pricing = PRICING[model];\n if (!pricing) {\n // Try to find a partial match\n const modelLower = model.toLowerCase();\n for (const [key, value] of Object.entries(PRICING)) {\n if (modelLower.includes(key.toLowerCase()) || key.toLowerCase().includes(modelLower)) {\n pricing = value;\n break;\n }\n }\n }\n pricing = pricing || DEFAULT_PRICING;\n\n const inputCost = (inputTokens / 1_000_000) * pricing.input;\n const outputCost = (outputTokens / 1_000_000) * pricing.output;\n const cacheReadCost = (cacheReadTokens / 1_000_000) * (pricing.cacheRead || pricing.input * 0.1);\n const cacheWriteCost = (cacheWriteTokens / 1_000_000) * (pricing.cacheWrite || pricing.input * 1.25);\n\n return inputCost + outputCost + cacheReadCost + cacheWriteCost;\n }\n\n /**\n * Log an LLM API call\n */\n log(entry: LLMUsageEntry): void {\n if (!this.enabled) return;\n\n // Update session stats\n this.sessionStats.totalCalls++;\n this.sessionStats.totalInputTokens += entry.inputTokens;\n this.sessionStats.totalOutputTokens += entry.outputTokens;\n this.sessionStats.totalCacheReadTokens += entry.cacheReadTokens || 0;\n this.sessionStats.totalCacheWriteTokens += entry.cacheWriteTokens || 0;\n this.sessionStats.totalCostUSD += entry.costUSD;\n this.sessionStats.totalDurationMs += entry.durationMs;\n\n // Format log entry\n const cacheInfo = entry.cacheReadTokens || entry.cacheWriteTokens\n ? ` CACHE_R=${entry.cacheReadTokens || 0} CACHE_W=${entry.cacheWriteTokens || 0}`\n : '';\n\n const toolInfo = entry.toolCalls ? ` | Tools: ${entry.toolCalls}` : '';\n const errorInfo = entry.error ? ` | ERROR: ${entry.error}` : '';\n const status = entry.success ? '✓' : '✗';\n\n // Calculate cache savings\n let cacheStatus = '';\n if (entry.cacheReadTokens && entry.cacheReadTokens > 0) {\n const savedCost = (entry.cacheReadTokens / 1_000_000) * 2.70; // Difference between regular and cache price\n cacheStatus = ` ⚡ CACHE HIT! Saved ~$${savedCost.toFixed(4)}`;\n } else if (entry.cacheWriteTokens && entry.cacheWriteTokens > 0) {\n cacheStatus = ' 📝 Cache created (next request will be cheaper)';\n }\n\n const logLine = `[${entry.timestamp}] [${entry.requestId}] ${status} ${entry.provider}/${entry.model} [${entry.method}]\n Tokens: IN=${entry.inputTokens} OUT=${entry.outputTokens}${cacheInfo} TOTAL=${entry.totalTokens}\n Cost: $${entry.costUSD.toFixed(6)} | Time: ${entry.durationMs}ms${toolInfo}${errorInfo}${cacheStatus}\n`;\n\n this.logStream?.write(logLine);\n\n // Log cache status to console (always show cache hits/writes)\n if (entry.cacheReadTokens && entry.cacheReadTokens > 0) {\n console.log(`[LLM] ⚡ CACHE HIT: ${entry.cacheReadTokens.toLocaleString()} tokens read from cache (${entry.method})`);\n } else if (entry.cacheWriteTokens && entry.cacheWriteTokens > 0) {\n console.log(`[LLM] 📝 CACHE WRITE: ${entry.cacheWriteTokens.toLocaleString()} tokens cached for future requests (${entry.method})`);\n }\n\n // Also log to console in verbose mode\n if (process.env.SUPERATOM_LOG_LEVEL === 'verbose') {\n console.log('\\n[LLM-Usage]', logLine);\n }\n }\n\n /**\n * Log session summary (call at end of request)\n */\n logSessionSummary(requestContext?: string): void {\n if (!this.enabled || this.sessionStats.totalCalls === 0) return;\n\n // Calculate cache savings\n const cacheReadSavings = (this.sessionStats.totalCacheReadTokens / 1_000_000) * 2.70; // Saved per 1M tokens\n const hasCaching = this.sessionStats.totalCacheReadTokens > 0 || this.sessionStats.totalCacheWriteTokens > 0;\n\n let cacheSection = '';\n if (hasCaching) {\n cacheSection = `\nCache Statistics:\n Cache Read Tokens: ${this.sessionStats.totalCacheReadTokens.toLocaleString()}${this.sessionStats.totalCacheReadTokens > 0 ? ' ⚡' : ''}\n Cache Write Tokens: ${this.sessionStats.totalCacheWriteTokens.toLocaleString()}${this.sessionStats.totalCacheWriteTokens > 0 ? ' 📝' : ''}\n Estimated Savings: $${cacheReadSavings.toFixed(4)}`;\n }\n\n const summary = `\n--------------------------------------------------------------------------------\nSESSION SUMMARY${requestContext ? ` (${requestContext})` : ''}\n--------------------------------------------------------------------------------\nTotal LLM Calls: ${this.sessionStats.totalCalls}\nTotal Input Tokens: ${this.sessionStats.totalInputTokens.toLocaleString()}\nTotal Output Tokens: ${this.sessionStats.totalOutputTokens.toLocaleString()}\nTotal Tokens: ${(this.sessionStats.totalInputTokens + this.sessionStats.totalOutputTokens).toLocaleString()}\nTotal Cost: $${this.sessionStats.totalCostUSD.toFixed(6)}\nTotal Time: ${this.sessionStats.totalDurationMs}ms (${(this.sessionStats.totalDurationMs / 1000).toFixed(2)}s)\nAvg Cost/Call: $${(this.sessionStats.totalCostUSD / this.sessionStats.totalCalls).toFixed(6)}\nAvg Time/Call: ${Math.round(this.sessionStats.totalDurationMs / this.sessionStats.totalCalls)}ms${cacheSection}\n--------------------------------------------------------------------------------\n\n`;\n this.logStream?.write(summary);\n\n // Always log summary to console\n console.log('\\n[LLM-Usage] Session Summary:');\n console.log(` Calls: ${this.sessionStats.totalCalls} | Tokens: ${(this.sessionStats.totalInputTokens + this.sessionStats.totalOutputTokens).toLocaleString()} | Cost: $${this.sessionStats.totalCostUSD.toFixed(4)} | Time: ${(this.sessionStats.totalDurationMs / 1000).toFixed(2)}s`);\n if (hasCaching) {\n console.log(` Cache: ${this.sessionStats.totalCacheReadTokens.toLocaleString()} read, ${this.sessionStats.totalCacheWriteTokens.toLocaleString()} written | Savings: ~$${cacheReadSavings.toFixed(4)}`);\n }\n }\n\n /**\n * Reset session stats (call at start of new user request)\n */\n resetSession(): void {\n this.sessionStats = {\n totalCalls: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheWriteTokens: 0,\n totalCostUSD: 0,\n totalDurationMs: 0,\n };\n }\n\n /**\n * Reset the log file for a new request (clears previous logs)\n * Call this at the start of each USER_PROMPT_REQ\n */\n resetLogFile(requestContext?: string): void {\n if (!this.enabled) return;\n\n try {\n // Close existing stream\n if (this.logStream) {\n this.logStream.end();\n this.logStream = null;\n }\n\n // Truncate the file by opening in write mode (not append)\n this.logStream = fs.createWriteStream(this.logPath, { flags: 'w' });\n\n // Write new header\n const header = `\n================================================================================\nLLM USAGE LOG - Request Started: ${new Date().toISOString()}\n${requestContext ? `Context: ${requestContext}` : ''}\n================================================================================\nFormat: [TIMESTAMP] [REQUEST_ID] [PROVIDER/MODEL] [METHOD]\n Tokens: IN=input OUT=output CACHE_R=cache_read CACHE_W=cache_write TOTAL=total\n Cost: $X.XXXXXX | Time: Xms\n================================================================================\n\n`;\n this.logStream.write(header);\n\n // Reset session stats\n this.resetSession();\n\n console.log(`[LLM-Usage] Log file reset for new request: ${this.logPath}`);\n } catch (error) {\n console.error('[LLM-Usage-Logger] Failed to reset log file:', error);\n }\n }\n\n /**\n * Get current session stats\n */\n getSessionStats() {\n return { ...this.sessionStats };\n }\n\n /**\n * Generate a unique request ID\n */\n generateRequestId(): string {\n return `req-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;\n }\n}\n\n// Export singleton instance\nexport const llmUsageLogger = new LLMUsageLogger();\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * User Prompt Error Logger - Captures detailed errors for USER_PROMPT_REQ\n * Logs full error details including raw strings for parse failures\n */\n\nclass UserPromptErrorLogger {\n private logStream: fs.WriteStream | null = null;\n private logPath: string;\n private enabled: boolean;\n private hasErrors: boolean = false;\n\n constructor() {\n // Get log path from environment or use default\n this.logPath = process.env.USER_PROMPT_ERROR_LOG_PATH || path.join(process.cwd(), 'user-prompt-req-errors');\n this.enabled = process.env.USER_PROMPT_ERROR_LOGGING !== 'false';\n }\n\n /**\n * Reset the error log file for a new request\n */\n resetLogFile(requestContext?: string): void {\n if (!this.enabled) return;\n\n try {\n // Close existing stream\n if (this.logStream) {\n this.logStream.end();\n this.logStream = null;\n }\n\n // Ensure directory exists\n const dir = path.dirname(this.logPath);\n if (dir !== '.' && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Truncate the file by opening in write mode (not append)\n this.logStream = fs.createWriteStream(this.logPath, { flags: 'w' });\n this.hasErrors = false;\n\n // Write header\n const header = `================================================================================\nUSER PROMPT REQUEST ERROR LOG\nRequest Started: ${new Date().toISOString()}\n${requestContext ? `Context: ${requestContext}` : ''}\n================================================================================\n\n`;\n this.logStream.write(header);\n\n } catch (error) {\n console.error('[UserPromptErrorLogger] Failed to reset log file:', error);\n }\n }\n\n /**\n * Log a JSON parse error with the raw string that failed\n */\n logJsonParseError(context: string, rawString: string, error: Error): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] JSON PARSE ERROR\n--------------------------------------------------------------------------------\nContext: ${context}\nError: ${error.message}\n\nRaw String (${rawString.length} chars):\n--------------------------------------------------------------------------------\n${rawString}\n--------------------------------------------------------------------------------\n\nStack Trace:\n${error.stack || 'No stack trace available'}\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] JSON Parse Error in ${context}: ${error.message}`);\n }\n\n /**\n * Log a general error with full details\n */\n logError(context: string, error: Error | string, additionalData?: Record<string, any>): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const errorMessage = error instanceof Error ? error.message : error;\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n let entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] ERROR\n--------------------------------------------------------------------------------\nContext: ${context}\nError: ${errorMessage}\n`;\n\n if (additionalData) {\n entry += `\nAdditional Data:\n${JSON.stringify(additionalData, null, 2)}\n`;\n }\n\n if (errorStack) {\n entry += `\nStack Trace:\n${errorStack}\n`;\n }\n\n entry += `--------------------------------------------------------------------------------\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] ${context}: ${errorMessage}`);\n }\n\n /**\n * Log a SQL query error with the full query\n */\n logSqlError(query: string, error: Error | string, params?: any[]): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const errorMessage = error instanceof Error ? error.message : error;\n\n const entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] SQL QUERY ERROR\n--------------------------------------------------------------------------------\nError: ${errorMessage}\n\nQuery (${query.length} chars):\n--------------------------------------------------------------------------------\n${query}\n--------------------------------------------------------------------------------\n${params ? `\\nParameters: ${JSON.stringify(params)}` : ''}\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] SQL Error: ${errorMessage}`);\n }\n\n /**\n * Log an LLM API error\n */\n logLlmError(provider: string, model: string, method: string, error: Error | string, requestData?: any): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const errorMessage = error instanceof Error ? error.message : error;\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n let entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] LLM API ERROR\n--------------------------------------------------------------------------------\nProvider: ${provider}\nModel: ${model}\nMethod: ${method}\nError: ${errorMessage}\n`;\n\n if (requestData) {\n // Truncate large request data\n const dataStr = JSON.stringify(requestData, null, 2);\n const truncated = dataStr.length > 5000 ? dataStr.substring(0, 5000) + '\\n... [truncated]' : dataStr;\n entry += `\nRequest Data:\n${truncated}\n`;\n }\n\n if (errorStack) {\n entry += `\nStack Trace:\n${errorStack}\n`;\n }\n\n entry += `--------------------------------------------------------------------------------\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] LLM Error (${provider}/${model}): ${errorMessage}`);\n }\n\n /**\n * Log tool execution error\n */\n logToolError(toolName: string, toolInput: any, error: Error | string): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const errorMessage = error instanceof Error ? error.message : error;\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n const entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] TOOL EXECUTION ERROR\n--------------------------------------------------------------------------------\nTool: ${toolName}\nError: ${errorMessage}\n\nTool Input:\n${JSON.stringify(toolInput, null, 2)}\n${errorStack ? `\\nStack Trace:\\n${errorStack}` : ''}\n--------------------------------------------------------------------------------\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] Tool Error (${toolName}): ${errorMessage}`);\n }\n\n /**\n * Write final summary if there were errors\n */\n writeSummary(): void {\n if (!this.enabled || !this.hasErrors) return;\n\n const summary = `\n================================================================================\nREQUEST COMPLETED WITH ERRORS\nTime: ${new Date().toISOString()}\n================================================================================\n`;\n this.write(summary);\n }\n\n /**\n * Check if any errors were logged\n */\n hadErrors(): boolean {\n return this.hasErrors;\n }\n\n private write(content: string): void {\n if (this.logStream) {\n this.logStream.write(content);\n }\n }\n}\n\n// Export singleton instance\nexport const userPromptErrorLogger = new UserPromptErrorLogger();\n","import { logger } from '../utils/logger';\n\n/**\n * Knowledge Base result interface\n */\nexport interface KnowledgeBaseResult {\n content: string;\n metadata?: {\n sources?: Array<{\n title: string;\n similarity?: number;\n kb_id?: string | number;\n }>;\n };\n}\n\n/**\n * Get relevant knowledge base context for a user prompt\n * Calls the registered 'knowledge-base.query' collection\n *\n * @param prompt - The user's question/prompt\n * @param collections - The collection registry containing knowledge-base.query\n * @param topK - Number of top results to retrieve (default: 1)\n * @returns Formatted knowledge base context string, or empty string if collection not registered\n */\nconst getKnowledgeBase = async ({\n prompt,\n collections,\n topK = 1\n}: {\n prompt: string;\n collections?: any;\n topK?: number;\n}): Promise<string> => {\n try {\n // Check if knowledge-base collection is registered\n if (!collections || !collections['knowledge-base'] || !collections['knowledge-base']['query']) {\n logger.info('[KnowledgeBase] knowledge-base.query collection not registered, skipping');\n return '';\n }\n\n logger.info(`[KnowledgeBase] Querying knowledge base for: \"${prompt.substring(0, 50)}...\"`);\n\n // Call the registered knowledge-base.query collection\n const result: KnowledgeBaseResult = await collections['knowledge-base']['query']({\n prompt,\n topK\n });\n\n if (!result || !result.content) {\n logger.error('[KnowledgeBase] No knowledge base results returned');\n return '';\n }\n\n logger.info(`[KnowledgeBase] Retrieved knowledge base context (${result.content.length} chars)`);\n\n // Log sources if available\n if (result.metadata?.sources && result.metadata.sources.length > 0) {\n logger.debug(`[KnowledgeBase] Sources: ${result.metadata.sources.map(s => s.title).join(', ')}`);\n }\n\n return result.content;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.warn(`[KnowledgeBase] Error querying knowledge base: ${errorMsg}`);\n // Return empty string on error - don't fail the entire request\n return '';\n }\n};\n\nconst KB = {\n getKnowledgeBase\n};\n\nexport default KB;","import { logger } from '../utils/logger';\nimport { rerankConversationResults, type HybridSearchOptions } from '../utils/bm25l-reranker';\nimport type { UIBlock } from '../types';\n\n/**\n * Conversation Search result interface\n */\nexport interface ConversationSearchResult {\n\tuiBlock: UIBlock;\n\tsimilarity: number;\n\tmetadata?: {\n\t\tuserPrompt?: string;\n\t\ttimestamp?: number;\n\t};\n\t/** Hybrid score combining semantic and BM25L lexical matching */\n\thybridScore?: number;\n\t/** BM25L lexical score */\n\tbm25Score?: number;\n}\n\n/**\n * Options for conversation search with reranking\n */\nexport interface ConversationSearchOptions {\n\tuserPrompt: string;\n\tcollections?: any;\n\tuserId?: string;\n\tsimilarityThreshold?: number;\n\t/** Enable hybrid reranking with BM25L (default: true) */\n\tenableReranking?: boolean;\n\t/** Number of candidates to fetch for reranking (default: 5) */\n\trerankCandidates?: number;\n\t/** Hybrid search options for BM25L reranking */\n\thybridOptions?: HybridSearchOptions;\n}\n\n/**\n * Search for semantically similar previous conversations for a user\n * Calls the registered 'conversation-history.search' collection\n * Returns the best match if similarity > threshold (default: 0.6)\n *\n * @param userPrompt - The current user's question/prompt\n * @param collections - The collection registry containing conversation-history.search\n * @param similarityThreshold - Minimum similarity threshold (0-1, default: 0.6)\n * @returns Matching UIBlock if found with similarity > threshold, null otherwise\n */\nconst searchConversations = async ({\n\tuserPrompt,\n\tcollections,\n\tuserId,\n\tsimilarityThreshold = 0.6\n}: {\n\tuserPrompt: string;\n\tcollections?: any;\n\tuserId?: string;\n\tsimilarityThreshold?: number;\n}): Promise<ConversationSearchResult | null> => {\n\ttry {\n\t\t// Check if conversation-history collection is registered\n\t\tif (\n\t\t\t!collections ||\n\t\t\t!collections['conversation-history'] ||\n\t\t\t!collections['conversation-history']['search']\n\t\t) {\n\t\t\tlogger.info('[ConversationSearch] conversation-history.search collection not registered, skipping');\n\t\t\treturn null;\n\t\t}\n\n\t\tlogger.info(`[ConversationSearch] Searching conversations for: \"${userPrompt.substring(0, 50)}...\"`);\n\t\tlogger.info(`[ConversationSearch] Using similarity threshold: ${(similarityThreshold! * 100).toFixed(0)}%`);\n\n\t\t// Call the registered conversation-history.search collection\n\t\tconst result: ConversationSearchResult = await collections['conversation-history']['search']({\n\t\t\tuserPrompt,\n\t\t\tuserId,\n\t\t\tthreshold: similarityThreshold\n\t\t});\n\n\t\tif (!result) {\n\t\t\tlogger.info('[ConversationSearch] No matching conversations found');\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!result.uiBlock) {\n\t\t\tlogger.error('[ConversationSearch] No UI block in conversation search result');\n\t\t\treturn null;\n\t\t}\n\n\t\tconst similarity = result.similarity || 0;\n\t\tlogger.info(`[ConversationSearch] Best match similarity: ${(similarity * 100).toFixed(2)}%`);\n\t\t// Check if similarity meets threshold\n\t\tif (similarity < similarityThreshold) {\n\t\t\tlogger.info(\n\t\t\t\t`[ConversationSearch] Best match has similarity ${(similarity * 100).toFixed(2)}% but below threshold ${(similarityThreshold * 100).toFixed(2)}%`\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\n\t\tlogger.info(\n\t\t\t`[ConversationSearch] Found matching conversation with similarity ${(similarity * 100).toFixed(2)}%`\n\t\t);\n\t\tlogger.debug(`[ConversationSearch] Matched prompt: \"${result.metadata?.userPrompt?.substring(0, 50)}...\"`);\n\n\t\treturn result;\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\tlogger.warn(`[ConversationSearch] Error searching conversations: ${errorMsg}`);\n\t\t// Return null on error - don't fail the entire request\n\t\treturn null;\n\t}\n};\n\n/**\n * Search for semantically similar previous conversations with hybrid reranking\n *\n * This is an enhanced version of searchConversations that uses BM25L reranking\n * to improve search accuracy by combining semantic similarity with lexical matching.\n *\n * Flow:\n * 1. Fetch a large pool of candidates from ChromaDB (default: 50) with no threshold\n * 2. Apply BM25L reranking on all candidates to find the best lexical + semantic match\n * 3. Return the top result only if it meets the similarity threshold\n *\n * This approach ensures we don't miss good lexical matches that might have\n * lower semantic similarity but are actually more relevant to the query.\n *\n * @param options - Search options including userPrompt, collections, userId, and reranking settings\n * @returns Matching UIBlock if found with hybrid score > threshold, null otherwise\n */\nconst searchConversationsWithReranking = async (options: ConversationSearchOptions): Promise<ConversationSearchResult | null> => {\n\tconst {\n\t\tuserPrompt,\n\t\tcollections,\n\t\tuserId,\n\t\tsimilarityThreshold = 0.6,\n\t\trerankCandidates = 50, // Fetch more candidates for better reranking\n\t\thybridOptions = {\n\t\t\tsemanticWeight: 0.7,\n\t\t\tbm25Weight: 0.3\n\t\t}\n\t} = options;\n\n\ttry {\n\t\t// Check if conversation-history collection is registered\n\t\tif (\n\t\t\t!collections ||\n\t\t\t!collections['conversation-history']\n\t\t) {\n\t\t\tlogger.info('[ConversationSearch] conversation-history collection not registered, skipping');\n\t\t\treturn null;\n\t\t}\n\n\t\t// Check if searchMultiple is available for reranking\n\t\tif (!collections['conversation-history']['searchMultiple']) {\n\t\t\tlogger.info('[ConversationSearch] searchMultiple not available, falling back to standard search');\n\t\t\treturn searchConversations({\n\t\t\t\tuserPrompt,\n\t\t\t\tcollections,\n\t\t\t\tuserId,\n\t\t\t\tsimilarityThreshold\n\t\t\t});\n\t\t}\n\n\t\tlogger.info(`[ConversationSearch] Hybrid search for: \"${userPrompt.substring(0, 50)}...\"`);\n\t\tlogger.info(`[ConversationSearch] Fetching ${rerankCandidates} candidates for reranking`);\n\t\tlogger.info(`[ConversationSearch] Weights - Semantic: ${hybridOptions.semanticWeight}, BM25: ${hybridOptions.bm25Weight}`);\n\n\t\t// Fetch a large pool of candidates with NO threshold - let reranking decide\n\t\tconst results: ConversationSearchResult[] = await collections['conversation-history']['searchMultiple']({\n\t\t\tuserPrompt,\n\t\t\tuserId,\n\t\t\tlimit: rerankCandidates,\n\t\t\tthreshold: 0 // No threshold - get all candidates for reranking\n\t\t});\n\n\t\tif (!results || results.length === 0) {\n\t\t\tlogger.info('[ConversationSearch] No conversations found in database');\n\t\t\treturn null;\n\t\t}\n\n\t\tlogger.info(`[ConversationSearch] Retrieved ${results.length} candidates for reranking`);\n\n\t\t// Prepare results for reranking - extract userPrompt from metadata\n\t\tconst candidatesForReranking = results.map(r => ({\n\t\t\t...r,\n\t\t\tuserPrompt: r.metadata?.userPrompt || ''\n\t\t}));\n\n\t\t// Rerank using hybrid BM25L + semantic scoring\n\t\tconst reranked = rerankConversationResults(userPrompt, candidatesForReranking, hybridOptions);\n\n\t\tif (reranked.length === 0) {\n\t\t\tlogger.info('[ConversationSearch] No results after reranking');\n\t\t\treturn null;\n\t\t}\n\n\t\t// Get the best result after reranking\n\t\tconst best = reranked[0];\n\t\tconst hybridScore = best.hybridScore;\n\t\tconst semanticScore = best.similarity || 0;\n\t\tconst matchedUserPrompt = (best as any).userPrompt || best.metadata?.userPrompt || '';\n\n\t\tlogger.info(`[ConversationSearch] Best match after reranking:`);\n\t\tlogger.info(` - Hybrid score: ${(hybridScore * 100).toFixed(2)}%`);\n\t\tlogger.info(` - Semantic score: ${(semanticScore * 100).toFixed(2)}%`);\n\t\tlogger.info(` - BM25L score: ${best.bm25Score.toFixed(4)}`);\n\t\tlogger.info(` - Matched prompt: \"${matchedUserPrompt}\"`);\n\t\tlogger.info(` - Query prompt: \"${userPrompt}\"`);\n\n\t\t// Apply threshold on SEMANTIC score (not hybrid)\n\t\t// Hybrid score can be inflated by normalization with few candidates\n\t\t// Semantic score is the true measure of meaning similarity\n\t\t// BM25 reranking only helps pick the best among candidates that already pass semantic threshold\n\t\tif (semanticScore < similarityThreshold) {\n\t\t\tlogger.info(\n\t\t\t\t`[ConversationSearch] Semantic score ${(semanticScore * 100).toFixed(2)}% below threshold ${(similarityThreshold * 100).toFixed(2)}% - rejecting match`\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\n\t\tlogger.info(\n\t\t\t`[ConversationSearch] ✓ Found match with semantic score ${(semanticScore * 100).toFixed(2)}%`\n\t\t);\n\t\tlogger.info(` - Returning cached result for: \"${matchedUserPrompt}\"`);\n\n\t\treturn {\n\t\t\tuiBlock: best.uiBlock,\n\t\t\tsimilarity: semanticScore,\n\t\t\thybridScore: hybridScore,\n\t\t\tbm25Score: best.bm25Score,\n\t\t\tmetadata: best.metadata\n\t\t};\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\tlogger.warn(`[ConversationSearch] Error in hybrid search: ${errorMsg}`);\n\t\t// Return null on error - don't fail the entire request\n\t\treturn null;\n\t}\n};\n\nconst ConversationSearch = {\n\tsearchConversations,\n\tsearchConversationsWithReranking\n};\n\nexport default ConversationSearch;\n","/**\n * BM25L Reranker for hybrid semantic search\n *\n * BM25L is an improved variant of BM25 that provides better handling of\n * long documents and term frequency saturation. This implementation is\n * designed to rerank semantic search results from ChromaDB.\n *\n * The hybrid approach combines:\n * 1. Semantic similarity from ChromaDB embeddings (dense vectors)\n * 2. Lexical matching from BM25L (sparse, keyword-based)\n *\n * This addresses the weakness of pure semantic search which may miss\n * exact keyword matches that are important for user intent.\n */\n\nexport interface BM25LOptions {\n\t/** Term frequency saturation parameter (default: 1.5) */\n\tk1?: number;\n\t/** Length normalization parameter (default: 0.75) */\n\tb?: number;\n\t/** Lower-bound adjustment from BM25L paper (default: 0.5) */\n\tdelta?: number;\n}\n\nexport interface RerankedResult<T> {\n\titem: T;\n\toriginalIndex: number;\n\tsemanticScore: number;\n\tbm25Score: number;\n\thybridScore: number;\n}\n\nexport interface HybridSearchOptions extends BM25LOptions {\n\t/** Weight for semantic score (0-1, default: 0.7) */\n\tsemanticWeight?: number;\n\t/** Weight for BM25 score (0-1, default: 0.3) */\n\tbm25Weight?: number;\n\t/** Minimum hybrid score threshold (0-1, default: 0) */\n\tminScore?: number;\n}\n\n/**\n * BM25L implementation for lexical scoring\n */\nexport class BM25L {\n\tprivate k1: number;\n\tprivate b: number;\n\tprivate delta: number;\n\tprivate documents: string[][];\n\tprivate docLengths: number[];\n\tprivate avgDocLength: number;\n\tprivate termDocFreq: Record<string, number>;\n\n\t/**\n\t * @param documents - Array of raw documents (strings)\n\t * @param opts - Optional BM25L parameters\n\t */\n\tconstructor(documents: string[] = [], opts: BM25LOptions = {}) {\n\t\tif (!Array.isArray(documents)) {\n\t\t\tthrow new Error('BM25L: documents must be an array of strings.');\n\t\t}\n\n\t\tthis.k1 = typeof opts.k1 === 'number' ? opts.k1 : 1.5;\n\t\tthis.b = typeof opts.b === 'number' ? opts.b : 0.75;\n\t\tthis.delta = typeof opts.delta === 'number' ? opts.delta : 0.5;\n\n\t\t// Tokenize documents safely\n\t\tthis.documents = documents.map(d => (typeof d === 'string' ? this.tokenize(d) : []));\n\n\t\t// Precompute stats\n\t\tthis.docLengths = this.documents.map(doc => doc.length);\n\t\tthis.avgDocLength =\n\t\t\tthis.docLengths.reduce((a, b) => a + b, 0) / (this.docLengths.length || 1);\n\n\t\t// Compute document frequency (df)\n\t\tthis.termDocFreq = {};\n\t\tthis.documents.forEach(doc => {\n\t\t\tconst seen = new Set<string>();\n\t\t\tdoc.forEach(term => {\n\t\t\t\tif (!seen.has(term)) {\n\t\t\t\t\tseen.add(term);\n\t\t\t\t\tthis.termDocFreq[term] = (this.termDocFreq[term] || 0) + 1;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Tokenize text into lowercase alphanumeric tokens\n\t */\n\ttokenize(text: string): string[] {\n\t\tif (typeof text !== 'string') return [];\n\t\treturn text\n\t\t\t.toLowerCase()\n\t\t\t.replace(/[^a-z0-9\\s]/g, ' ')\n\t\t\t.split(/\\s+/)\n\t\t\t.filter(Boolean);\n\t}\n\n\t/**\n\t * Compute IDF (Inverse Document Frequency) with smoothing\n\t */\n\tprivate idf(term: string): number {\n\t\tconst df = this.termDocFreq[term] || 0;\n\t\tconst N = this.documents.length || 1;\n\t\treturn Math.log(1 + (N - df + 0.5) / (df + 0.5));\n\t}\n\n\t/**\n\t * Compute BM25L score for a single document\n\t */\n\tscore(query: string, docIndex: number): number {\n\t\tif (typeof query !== 'string') return 0;\n\t\tif (docIndex < 0 || docIndex >= this.documents.length) return 0;\n\n\t\tconst tokens = this.tokenize(query);\n\t\tif (tokens.length === 0) return 0;\n\n\t\tconst doc = this.documents[docIndex];\n\t\tconst docLength = this.docLengths[docIndex] || 1;\n\n\t\t// Term frequencies\n\t\tconst freq: Record<string, number> = {};\n\t\tfor (const t of doc) {\n\t\t\tfreq[t] = (freq[t] || 0) + 1;\n\t\t}\n\n\t\tlet sum = 0;\n\n\t\tfor (const term of tokens) {\n\t\t\tconst tf = freq[term] || 0;\n\t\t\tif (tf === 0) continue;\n\n\t\t\tconst idfVal = this.idf(term);\n\n\t\t\t// BM25L adjusted TF\n\t\t\tlet tfL = tf - this.b * (docLength / this.avgDocLength) + this.delta;\n\t\t\tif (tfL < 0) tfL = 0;\n\n\t\t\tsum += idfVal * (tfL / (this.k1 + tfL));\n\t\t}\n\n\t\treturn sum;\n\t}\n\n\t/**\n\t * Search and rank all documents\n\t */\n\tsearch(query: string): Array<{ index: number; score: number }> {\n\t\treturn this.documents\n\t\t\t.map((_, i) => ({\n\t\t\t\tindex: i,\n\t\t\t\tscore: this.score(query, i)\n\t\t\t}))\n\t\t\t.sort((a, b) => b.score - a.score);\n\t}\n}\n\n/**\n * Normalize scores to 0-1 range using min-max normalization\n */\nfunction normalizeScores(scores: number[]): number[] {\n\tif (scores.length === 0) return [];\n\n\tconst min = Math.min(...scores);\n\tconst max = Math.max(...scores);\n\n\t// If all scores are the same, return array of 1s (or 0s if all are 0)\n\tif (max === min) {\n\t\treturn scores.map(() => (max === 0 ? 0 : 1));\n\t}\n\n\treturn scores.map(score => (score - min) / (max - min));\n}\n\n/**\n * Hybrid reranker that combines semantic and BM25L scores\n *\n * @param query - The search query\n * @param items - Array of items to rerank\n * @param getDocument - Function to extract document text from an item\n * @param getSemanticScore - Function to extract semantic similarity score from an item\n * @param options - Hybrid search options\n * @returns Reranked items with hybrid scores\n */\nexport function hybridRerank<T>(\n\tquery: string,\n\titems: T[],\n\tgetDocument: (item: T) => string,\n\tgetSemanticScore: (item: T) => number,\n\toptions: HybridSearchOptions = {}\n): RerankedResult<T>[] {\n\tconst {\n\t\tsemanticWeight = 0.7,\n\t\tbm25Weight = 0.3,\n\t\tminScore = 0,\n\t\tk1 = 1.5,\n\t\tb = 0.75,\n\t\tdelta = 0.5\n\t} = options;\n\n\tif (items.length === 0) return [];\n\n\t// Extract documents and semantic scores\n\tconst documents = items.map(getDocument);\n\tconst semanticScores = items.map(getSemanticScore);\n\n\t// Create BM25L index and compute scores\n\tconst bm25 = new BM25L(documents, { k1, b, delta });\n\tconst bm25Scores = items.map((_, i) => bm25.score(query, i));\n\n\t// Normalize both score sets to 0-1 range\n\tconst normalizedSemantic = normalizeScores(semanticScores);\n\tconst normalizedBM25 = normalizeScores(bm25Scores);\n\n\t// Compute hybrid scores and create result objects\n\tconst results: RerankedResult<T>[] = items.map((item, i) => {\n\t\tconst hybridScore =\n\t\t\tsemanticWeight * normalizedSemantic[i] + bm25Weight * normalizedBM25[i];\n\n\t\treturn {\n\t\t\titem,\n\t\t\toriginalIndex: i,\n\t\t\tsemanticScore: semanticScores[i],\n\t\t\tbm25Score: bm25Scores[i],\n\t\t\thybridScore\n\t\t};\n\t});\n\n\t// Sort by hybrid score (descending) and filter by minimum score\n\treturn results\n\t\t.filter(r => r.hybridScore >= minScore)\n\t\t.sort((a, b) => b.hybridScore - a.hybridScore);\n}\n\n/**\n * Simple reranking function for ChromaDB results\n *\n * This is a convenience wrapper for reranking ChromaDB query results\n * that follow the standard { ids, documents, metadatas, distances } format.\n *\n * @param query - The search query\n * @param chromaResults - ChromaDB query results\n * @param options - Hybrid search options\n * @returns Reranked results with hybrid scores\n */\nexport function rerankChromaResults(\n\tquery: string,\n\tchromaResults: {\n\t\tids: string[][];\n\t\tdocuments: (string | null)[][];\n\t\tmetadatas: Record<string, any>[][];\n\t\tdistances: number[][];\n\t},\n\toptions: HybridSearchOptions = {}\n): Array<{\n\tid: string;\n\tdocument: string | null;\n\tmetadata: Record<string, any>;\n\tdistance: number;\n\tsemanticScore: number;\n\tbm25Score: number;\n\thybridScore: number;\n}> {\n\t// Flatten the nested arrays (ChromaDB returns nested arrays for batch queries)\n\tconst ids = chromaResults.ids[0] || [];\n\tconst documents = chromaResults.documents[0] || [];\n\tconst metadatas = chromaResults.metadatas[0] || [];\n\tconst distances = chromaResults.distances[0] || [];\n\n\tif (ids.length === 0) return [];\n\n\t// Create items array\n\tconst items = ids.map((id, i) => ({\n\t\tid,\n\t\tdocument: documents[i],\n\t\tmetadata: metadatas[i],\n\t\tdistance: distances[i]\n\t}));\n\n\t// Rerank using hybrid approach\n\tconst reranked = hybridRerank(\n\t\tquery,\n\t\titems,\n\t\titem => item.document || '',\n\t\t// Convert L2 distance to similarity score\n\t\titem => 1 / (1 + item.distance),\n\t\toptions\n\t);\n\n\t// Return flattened results\n\treturn reranked.map(r => ({\n\t\tid: r.item.id,\n\t\tdocument: r.item.document,\n\t\tmetadata: r.item.metadata,\n\t\tdistance: r.item.distance,\n\t\tsemanticScore: r.semanticScore,\n\t\tbm25Score: r.bm25Score,\n\t\thybridScore: r.hybridScore\n\t}));\n}\n\n/**\n * Rerank conversation search results specifically\n *\n * This function is designed to work with the conversation-history.search collection\n * where we need to fetch more results initially and then rerank them.\n *\n * @param query - The user's search query\n * @param results - Array of conversation search results from ChromaDB\n * @param options - Hybrid search options\n * @returns Reranked results sorted by hybrid score\n */\nexport function rerankConversationResults<T extends { userPrompt?: string; similarity?: number }>(\n\tquery: string,\n\tresults: T[],\n\toptions: HybridSearchOptions = {}\n): Array<T & { hybridScore: number; bm25Score: number }> {\n\tif (results.length === 0) return [];\n\n\tconst reranked = hybridRerank(\n\t\tquery,\n\t\tresults,\n\t\titem => item.userPrompt || '',\n\t\titem => item.similarity || 0,\n\t\toptions\n\t);\n\n\treturn reranked.map(r => ({\n\t\t...r.item,\n\t\thybridScore: r.hybridScore,\n\t\tbm25Score: r.bm25Score\n\t}));\n}\n\nexport default {\n\tBM25L,\n\thybridRerank,\n\trerankChromaResults,\n\trerankConversationResults\n};\n","import dotenv from 'dotenv';\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\n\ndotenv.config();\n\nexport interface AnthropicLLMConfig extends BaseLLMConfig {}\n\n/**\n * AnthropicLLM class for handling AI-powered component generation and matching using Anthropic Claude\n */\nexport class AnthropicLLM extends BaseLLM {\n\tconstructor(config?: AnthropicLLMConfig) {\n\t\tsuper(config);\n\t}\n\n\tprotected getDefaultModel(): string {\n\t\treturn 'anthropic/claude-sonnet-4-5-20250929';\n\t}\n\n\tprotected getDefaultFastModel(): string {\n\t\t// Haiku is 75% cheaper and faster - ideal for simple tasks\n\t\treturn 'anthropic/claude-haiku-4-5-20251001';\n\t}\n\n\tprotected getDefaultApiKey(): string | undefined {\n\t\treturn process.env.ANTHROPIC_API_KEY;\n\t}\n\n\tprotected getProviderName(): string {\n\t\treturn 'Anthropic';\n\t}\n}\n\n// Export a singleton instance\nexport const anthropicLLM = new AnthropicLLM();\n","import dotenv from 'dotenv';\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\n\ndotenv.config();\n\nexport interface GeminiLLMConfig extends BaseLLMConfig {}\n\n/**\n * GeminiLLM class for handling AI-powered component generation and matching using Google Gemini\n */\nexport class GeminiLLM extends BaseLLM {\n\tconstructor(config?: GeminiLLMConfig) {\n\t\tsuper(config);\n\t}\n\n\tprotected getDefaultModel(): string {\n\t\treturn 'gemini/gemini-2.5-flash';\n\t}\n\n\tprotected getDefaultFastModel(): string {\n\t\t// Gemini Flash is already fast/cheap, use the same\n\t\treturn 'gemini/gemini-2.0-flash-exp';\n\t}\n\n\tprotected getDefaultApiKey(): string | undefined {\n\t\treturn process.env.GEMINI_API_KEY;\n\t}\n\n\tprotected getProviderName(): string {\n\t\treturn 'Gemini';\n\t}\n}\n\n// Export a singleton instance\nexport const geminiLLM = new GeminiLLM();\n","import dotenv from 'dotenv';\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\n\ndotenv.config();\n\nexport interface OpenAILLMConfig extends BaseLLMConfig {}\n\n/**\n * OpenAILLM class for handling AI-powered component generation and matching using OpenAI GPT models\n */\nexport class OpenAILLM extends BaseLLM {\n\tconstructor(config?: OpenAILLMConfig) {\n\t\tsuper(config);\n\t}\n\n\tprotected getDefaultModel(): string {\n\t\treturn 'openai/gpt-4.1';\n\t}\n\n\tprotected getDefaultFastModel(): string {\n\t\t// GPT-4o-mini is 60x cheaper than GPT-4o and faster - ideal for simple tasks\n\t\treturn 'openai/gpt-4o-mini';\n\t}\n\n\tprotected getDefaultApiKey(): string | undefined {\n\t\treturn process.env.OPENAI_API_KEY;\n\t}\n\n\tprotected getProviderName(): string {\n\t\treturn 'OpenAI';\n\t}\n}\n\n// Export a singleton instance\nexport const openaiLLM = new OpenAILLM();\n","import { groqLLM } from \"./groq\";\nimport { anthropicLLM } from \"./anthropic\";\nimport { geminiLLM } from \"./gemini\";\nimport { openaiLLM } from \"./openai\";\nimport { Component, LLMProvider, T_RESPONSE } from \"../types\";\nimport dotenv from 'dotenv';\nimport { logger } from \"../utils/logger\";\n\ndotenv.config();\n\n\n\n/**\n * Parse LLM_PROVIDERS from environment variable\n * Expects a stringified JSON array like: '[\"anthropic\",\"groq\"]'\n */\nexport function getLLMProviders(): LLMProvider[] {\n const envProviders = process.env.LLM_PROVIDERS;\n\n const DEFAULT_PROVIDERS: LLMProvider[] = ['anthropic', 'gemini', 'openai', 'groq'];\n if (!envProviders) {\n // Default to anthropic if not specified\n return DEFAULT_PROVIDERS;\n }\n\n try {\n const providers = JSON.parse(envProviders) as LLMProvider[];\n\n // Validate providers\n const validProviders = providers.filter(p => p === 'anthropic' || p === 'groq' || p === 'gemini' || p === 'openai');\n\n if (validProviders.length === 0) {\n return DEFAULT_PROVIDERS;\n }\n\n return validProviders;\n } catch (error) {\n logger.error('Failed to parse LLM_PROVIDERS, defaulting to [\"anthropic\"]:', error);\n return DEFAULT_PROVIDERS;\n }\n}\n\n/**\n * Method 1: Use Anthropic Claude LLM\n */\nexport const useAnthropicMethod = async (\n prompt: string,\n components: Component[],\n apiKey?: string,\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n logger.debug('[useAnthropicMethod] Initializing Anthropic Claude matching method');\n logger.debug(`[useAnthropicMethod] Response mode: ${responseMode}`);\n const msg = `Using Anthropic Claude ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\n // logger.info(msg);\n logCollector?.info(msg);\n\n // Only check components for component mode\n if (responseMode === 'component' && components.length === 0) {\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\n logger.error('[useAnthropicMethod] No components available');\n logCollector?.error(emptyMsg);\n return { success: false, errors: [emptyMsg] };\n }\n\n logger.debug(`[useAnthropicMethod] Processing with ${components.length} components`);\n\n const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n logger.info(`[useAnthropicMethod] Successfully generated ${responseMode} using Anthropic`);\n return matchResult;\n};\n\n/**\n * Method 2: Use Groq LLM\n */\nexport const useGroqMethod = async (\n prompt: string,\n components: Component[],\n apiKey?: string,\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n logger.debug('[useGroqMethod] Initializing Groq LLM matching method');\n logger.debug(`[useGroqMethod] Response mode: ${responseMode}`);\n const msg = `Using Groq LLM ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\n logger.info(msg);\n logCollector?.info(msg);\n\n // Only check components for component mode\n if (responseMode === 'component' && components.length === 0) {\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\n logger.error('[useGroqMethod] No components available');\n logCollector?.error(emptyMsg);\n return { success: false, errors: [emptyMsg] };\n }\n\n logger.debug(`[useGroqMethod] Processing with ${components.length} components`);\n\n const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);\n return matchResult;\n}\n\n/**\n * Method 3: Use Google Gemini LLM\n */\nexport const useGeminiMethod = async (\n prompt: string,\n components: Component[],\n apiKey?: string,\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n logger.debug('[useGeminiMethod] Initializing Gemini LLM matching method');\n logger.debug(`[useGeminiMethod] Response mode: ${responseMode}`);\n const msg = `Using Gemini LLM ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\n logger.info(msg);\n logCollector?.info(msg);\n\n // Only check components for component mode\n if (responseMode === 'component' && components.length === 0) {\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\n logger.error('[useGeminiMethod] No components available');\n logCollector?.error(emptyMsg);\n return { success: false, errors: [emptyMsg] };\n }\n\n logger.debug(`[useGeminiMethod] Processing with ${components.length} components`);\n\n const matchResult = await geminiLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n logger.info(`[useGeminiMethod] Successfully generated ${responseMode} using Gemini`);\n return matchResult;\n}\n\n/**\n * Method 4: Use OpenAI GPT LLM\n */\nexport const useOpenAIMethod = async (\n prompt: string,\n components: Component[],\n apiKey?: string,\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n logger.debug('[useOpenAIMethod] Initializing OpenAI GPT matching method');\n logger.debug(`[useOpenAIMethod] Response mode: ${responseMode}`);\n const msg = `Using OpenAI GPT ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\n logger.info(msg);\n logCollector?.info(msg);\n\n // Only check components for component mode\n if (responseMode === 'component' && components.length === 0) {\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\n logger.error('[useOpenAIMethod] No components available');\n logCollector?.error(emptyMsg);\n return { success: false, errors: [emptyMsg] };\n }\n\n logger.debug(`[useOpenAIMethod] Processing with ${components.length} components`);\n\n const matchResult = await openaiLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n logger.info(`[useOpenAIMethod] Successfully generated ${responseMode} using OpenAI`);\n return matchResult;\n}\n\n//@to-do\nexport const getUserResponseFromCache = async (prompt: string) => {\n return false\n}\n\n/**\n * Get user response with automatic fallback between LLM providers\n * Tries providers in order specified by LLM_PROVIDERS or passed parameter\n * @param responseMode - 'component' for component generation (default), 'text' for text responses\n * @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)\n * @param collections - Collection registry for executing database queries (required for text mode with queries)\n * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called (only for text mode)\n */\nexport const get_user_response = async (\n prompt: string,\n components: Component[],\n anthropicApiKey?: string,\n groqApiKey?: string,\n geminiApiKey?: string,\n openaiApiKey?: string,\n llmProviders?: LLMProvider[],\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n\n logger.debug(`[get_user_response] Starting user response generation for prompt: \"${prompt.substring(0, 50)}...\"`);\n logger.debug(`[get_user_response] Response mode: ${responseMode}`);\n\n //first checking if the same prompt is already asked and we got successful response.\n logger.debug('[get_user_response] Checking cache for existing response');\n const userResponse = await getUserResponseFromCache(prompt);\n if(userResponse){\n logger.info('[get_user_response] User response found in cache - returning cached result');\n logCollector?.info('User response found in cache');\n return {\n success: true,\n data: userResponse,\n errors: []\n };\n }\n\n logger.debug('[get_user_response] No cached response found, proceeding with LLM providers');\n\n const providers = llmProviders || getLLMProviders();\n const errors: string[] = [];\n\n const providerOrder = providers.join(', ');\n logCollector?.info(`LLM Provider order: [${providerOrder}]`);\n\n // Log conversation context info if available\n if (conversationHistory && conversationHistory.length > 0) {\n const exchangeCount = conversationHistory.split('\\n').filter((l: string) => l.startsWith('Q')).length;\n logger.debug(`[get_user_response] Using conversation history with ${exchangeCount} previous exchanges`);\n logCollector?.info(`Using conversation history with ${exchangeCount} previous exchanges`);\n } else {\n logger.debug('[get_user_response] No conversation history available');\n }\n\n for (let i = 0; i < providers.length; i++) {\n const provider = providers[i];\n const isLastProvider = i === providers.length - 1;\n\n const attemptMsg = `Attempting provider: ${provider} (${i + 1}/${providers.length})`;\n logCollector?.info(attemptMsg);\n\n let result: T_RESPONSE;\n if (provider === 'anthropic') {\n result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n } else if (provider === 'groq') {\n result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n } else if (provider === 'gemini') {\n result = await useGeminiMethod(prompt, components, geminiApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n } else if (provider === 'openai') {\n result = await useOpenAIMethod(prompt, components, openaiApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n } else {\n logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);\n errors.push(`Unknown provider: ${provider}`);\n continue; // Skip unknown providers\n }\n\n if (result.success) {\n const successMsg = `Success with provider: ${provider}`;\n logger.info(`${successMsg}`);\n logCollector?.info(successMsg);\n return result;\n } else {\n // Collect errors from result\n const providerErrors = result.errors.map(err => `${provider}: ${err}`);\n errors.push(...providerErrors);\n const warnMsg = `Provider ${provider} returned unsuccessful result: ${result.errors.join(', ')}`;\n logger.warn(`[get_user_response] ${warnMsg}`);\n logCollector?.warn(warnMsg);\n\n // If this is not the last provider, try the next one\n if (!isLastProvider) {\n const fallbackMsg = 'Falling back to next provider...';\n logger.info(`[get_user_response] ${fallbackMsg}`);\n logCollector?.info(fallbackMsg);\n }\n }\n }\n\n // All providers failed\n const failureMsg = `All LLM providers failed`;\n logger.error(`[get_user_response] ${failureMsg}. Errors: ${errors.join('; ')}`);\n logCollector?.error(`${failureMsg}. Errors: ${errors.join('; ')}`);\n\n return {\n success: false,\n errors\n };\n}\n\n","import { Component, LLMProvider, Message, UserPromptRequestMessageSchema, T_RESPONSE } from \"../types\";\nimport { get_user_response } from \"../userResponse\";\nimport { logger } from \"../utils/logger\";\nimport { llmUsageLogger } from \"../utils/llm-usage-logger\";\nimport { userPromptErrorLogger } from \"../utils/user-prompt-error-logger\";\nimport { UILogCollector } from \"../utils/log-collector\";\nimport { saveConversation } from \"../utils/conversation-saver\";\nimport { ThreadManager, UIBlock } from \"../threads\";\nimport { CONTEXT_CONFIG } from \"../config/context\";\nimport { ZodError } from \"zod\";\n\n\n// Define return type for get_user_request extending T_RESPONSE\ninterface UserRequestResponse extends T_RESPONSE {\n\tuiBlockId?: string;\n\tthreadId?: string;\n\tid?: string;\n\twsId?: string;\n}\n\n\nconst get_user_request = async (\n\tdata: any,\n\tcomponents: Component[],\n\tsendMessage: (message: Message) => void,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tcollections?: any,\n\texternalTools?: any[],\n\tuserId?: string\n): Promise<UserRequestResponse> => {\n\tconst errors: string[] = [];\n\n\t// Parse incoming message data\n\tlogger.debug('[USER_PROMPT_REQ] Parsing incoming message data');\n\tconst parseResult = UserPromptRequestMessageSchema.safeParse(data);\n\n\tif (!parseResult.success) {\n\t\tconst zodError = parseResult.error as ZodError;\n\t\tzodError.errors.forEach(err => {\n\t\t\terrors.push(`${err.path.join('.')}: ${err.message}`);\n\t\t});\n\t\treturn { success: false, errors };\n\t}\n\n\tconst userPromptRequest = parseResult.data;\n\tconst { id, payload } = userPromptRequest;\n\n\tconst prompt = payload.prompt;\n\tconst SA_RUNTIME = payload.SA_RUNTIME;\n\tconst wsId = userPromptRequest.from.id || 'unknown';\n\n\t// Reset log files for this new request (clears previous request logs)\n\tconst promptContext = `User Prompt: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? '...' : ''}`;\n\tllmUsageLogger.resetLogFile(promptContext);\n\tuserPromptErrorLogger.resetLogFile(promptContext);\n\n\t\n\t// Validate SA_RUNTIME and extract threadId and uiBlockId\n\tif (!SA_RUNTIME) {\n\t\terrors.push('SA_RUNTIME is required');\n\t}\n\t\n\tconst threadId = SA_RUNTIME?.threadId;\n\tconst existingUiBlockId = SA_RUNTIME?.uiBlockId;\n\t\n\tif (!threadId) {\n\t\terrors.push('threadId in SA_RUNTIME is required');\n\t}\n\t\n\tif (!existingUiBlockId) {\n\t\terrors.push('uiBlockId in SA_RUNTIME is required');\n\t}\n\t\n\tif (!prompt) {\n\t\terrors.push('Prompt not found');\n\t}\n\t\n\tlogger.debug(`[REQUEST ${id}] Full request details - uiBlockId: ${existingUiBlockId}, threadId: ${threadId}, prompt: ${prompt}`);\n\t// if (!components || components.length === 0) {\n\t// \terrors.push('Components not found');\n\t// }\n\n\t// If there are validation errors, return early\n\tif (errors.length > 0) {\n\t\treturn { success: false, errors, id, wsId };\n\t}\n\n\t// Create log collector with uiBlockId\n\tconst logCollector = new UILogCollector(wsId, sendMessage, existingUiBlockId!);\n\n\t// Get or create thread BEFORE processing to enable conversation context\n\tconst threadManager = ThreadManager.getInstance();\n\tlet thread = threadManager.getThread(threadId!);\n\tif (!thread) {\n\t\tthread = threadManager.createThread(threadId!);\n\t\tlogger.info(`Created new thread: ${threadId}`);\n\t}\n\n\tlogCollector.info(`Starting user prompt request with ${components.length} components`);\n\n\t// Extract conversation context from thread (excluding current UIBlock)\n\tconst conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId!);\n\n\t// Get responseMode from payload\n\tconst responseMode = payload.responseMode || 'component' ; \n\tlogger.info('responseMode', responseMode);\n\n\t// Create stream callback for text mode - sends chunks via WebSocket AND accumulates them\n\tlet streamCallback: ((chunk: string) => void) | undefined;\n\tlet accumulatedStreamResponse = ''; // Accumulate all streaming chunks for storage in UIBlock\n\tif (responseMode === 'text') {\n\t\tstreamCallback = (chunk: string) => {\n\t\t\t// Accumulate chunk for storage in UIBlock\n\t\t\taccumulatedStreamResponse += chunk;\n\n\t\t\t// Send streaming chunk to frontend via WebSocket\n\t\t\t// IMPORTANT: Use stream_${uiBlockId} as ID to avoid conflicting with the final response\n\t\t\t// The frontend will match by the stream_ prefix and uiBlockId\n\t\t\tlogger.debug(`[STREAM] Sending chunk (${chunk.length} chars): \"${chunk.substring(0, 20)}...\"`);\n\t\t\tconst streamMessage: Message = {\n\t\t\t\tid: `stream_${existingUiBlockId}`, // Different ID pattern for streaming\n\t\t\t\ttype: 'USER_PROMPT_STREAM',\n\t\t\t\tfrom: { type: 'data-agent' },\n\t\t\t\tto: {\n\t\t\t\t\ttype: 'runtime',\n\t\t\t\t\tid: wsId\n\t\t\t\t},\n\t\t\t\tpayload: {\n\t\t\t\t\tuiBlockId: existingUiBlockId,\n\t\t\t\t\tchunk\n\t\t\t\t}\n\t\t\t};\n\t\t\tsendMessage(streamMessage);\n\t\t\tlogger.debug(`[STREAM] Chunk sent to wsId: ${wsId}`);\n\t\t};\n\t}\n\n\t// Get user response with log collector, conversation context, optional streaming, collections, and external tools\n\tconst userResponse = await get_user_response(\n\t\tprompt!,\n\t\tcomponents,\n\t\tanthropicApiKey,\n\t\tgroqApiKey,\n\t\tgeminiApiKey,\n\t\topenaiApiKey,\n\t\tllmProviders,\n\t\tlogCollector,\n\t\tconversationHistory,\n\t\tresponseMode,\n\t\tstreamCallback,\n\t\tcollections,\n\t\texternalTools,\n\t\tuserId\n\t);\n\t// logger.info('llm userResponse', userResponse);\n\n\t// Log completion (sent immediately if uiBlockId was provided)\n\tlogCollector.info('User prompt request completed');\n\n\t// Use the uiBlockId from SA_RUNTIME (already validated)\n\tconst uiBlockId = existingUiBlockId!;\n\n\t// If response failed, don't create UIBlock and return error\n\tif (!userResponse.success) {\n\t\tlogger.error(`User prompt request failed with errors: ${userResponse.errors.join(', ')}`);\n\n\t\t// Log detailed error information\n\t\tuserPromptErrorLogger.logError('User Response Failed', userResponse.errors.join('\\n'), {\n\t\t\tprompt: prompt,\n\t\t\tuiBlockId,\n\t\t\tthreadId: threadId!,\n\t\t\tresponseData: userResponse.data\n\t\t});\n\t\tuserPromptErrorLogger.writeSummary();\n\t\tllmUsageLogger.logSessionSummary(`FAILED: ${prompt?.substring(0, 30)}`);\n\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tdata: userResponse.data,\n\t\t\terrors: userResponse.errors,\n\t\t\tuiBlockId,\n\t\t\tthreadId: threadId!,\n\t\t\tid,\n\t\t\twsId\n\t\t};\n\t}\n\n\t// Extract component, textResponse, and actions from successful response\n\tlet component = null;\n\tlet textResponse = null;\n\tlet actions = [];\n\n\tif (userResponse.data) {\n\t\tif (typeof userResponse.data === 'object') {\n\t\t\tif ('component' in userResponse.data) {\n\t\t\t\tcomponent = (userResponse.data as any).component;\n\t\t\t}\n\t\t\t// Check for both 'text' and 'textResponse' keys\n\t\t\tif ('text' in userResponse.data) {\n\t\t\t\ttextResponse = (userResponse.data as any).text;\n\t\t\t} else if ('textResponse' in userResponse.data) {\n\t\t\t\ttextResponse = (userResponse.data as any).textResponse;\n\t\t\t}\n\t\t\tif ('actions' in userResponse.data) {\n\t\t\t\tactions = (userResponse.data as any).actions || [];\n\t\t\t}\n\t\t}\n\t}\n\n\t// For text mode, use accumulated stream response which includes ALL messages (analyzing, query, results, etc.)\n\t// For component mode, use the textResponse as-is\n\tconst finalTextResponse = responseMode === 'text' && accumulatedStreamResponse\n\t\t? accumulatedStreamResponse\n\t\t: textResponse;\n\n\t// Create UIBlock with component metadata, empty component data, and full text response\n\tconst uiBlock = new UIBlock(\n\t\tprompt!,\n\t\t{}, // componentData: initially empty, will be filled later\n\t\tcomponent, // generatedComponentMetadata: full component object (ComponentSchema)\n\t\t[], // actions: empty initially, will be set below\n\t\tuiBlockId,\n\t\tfinalTextResponse // textResponse: FULL streaming response including all intermediate messages\n\t);\n\n\t// Store actions in UIBlock if they were generated\n\tif (actions.length > 0) {\n\t\tuiBlock.setActions(actions);\n\t\tlogger.info(`Stored ${actions.length} actions in UIBlock: ${uiBlockId}`);\n\t}\n\n\t// Add UIBlock to Thread\n\tthread.addUIBlock(uiBlock);\n\n\tlogger.info(`Created UIBlock: ${uiBlockId} in Thread: ${threadId}`);\n\n\t// Save conversation to backend for semantic search and history\n\t// Skip saving if response came from exact semantic match (>=99%)\n\tif (userId) {\n\t\tconst responseMethod = userResponse.data?.method || '';\n\t\tconst semanticSimilarity = userResponse.data?.semanticSimilarity || 0;\n\n\t\t// Check if this is an exact semantic match (>=99%)\n\t\tconst isExactMatch =\n\t\t\tresponseMethod.includes('semantic-match') && semanticSimilarity >= 0.99;\n\n\t\tif (isExactMatch) {\n\t\t\tlogger.info(\n\t\t\t\t`Skipping conversation save - response from exact semantic match (${(semanticSimilarity * 100).toFixed(2)}% similarity)`\n\t\t\t);\n\t\t\tlogCollector.info(\n\t\t\t\t`Using exact cached result (${(semanticSimilarity * 100).toFixed(2)}% match) - not saving duplicate conversation`\n\t\t\t);\n\t\t} else {\n\t\t\t// Save new conversation\n\t\t\tconst uiBlockData = uiBlock.toJSON();\n\t\t\tconst saveResult = await saveConversation({\n\t\t\t\tuserId,\n\t\t\t\tuserPrompt: prompt!,\n\t\t\t\tuiblock: uiBlockData,\n\t\t\t\tuiBlockId: uiBlockId,\n\t\t\t\tthreadId: threadId!,\n\t\t\t\tcollections\n\t\t\t});\n\n\t\t\tif (saveResult.success) {\n\t\t\t\tlogger.info(`Conversation saved with ID: ${saveResult.conversationId}`);\n\t\t\t} else {\n\t\t\t\tlogger.warn(`Failed to save conversation: ${saveResult.error}`);\n\t\t\t\t// Continue anyway - don't fail the request if conversation saving fails\n\t\t\t}\n\t\t}\n\t}\n\n\t// Log session summary for this request (writes total usage to log file)\n\tllmUsageLogger.logSessionSummary(prompt?.substring(0, 50));\n\n\t// Return response with uiBlockId and threadId\n\treturn {\n\t\tsuccess: userResponse.success,\n\t\tdata: userResponse.data,\n\t\terrors: userResponse.errors,\n\t\tuiBlockId,\n\t\tthreadId: threadId!,\n\t\tid,\n\t\twsId\n\t};\n}\n\nexport async function handleUserPromptRequest(\n\tdata: any,\n\tcomponents: Component[],\n\tsendMessage: (message: Message) => void,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tcollections?: any,\n\texternalTools?: any[],\n\tuserId?: string\n): Promise<void> {\n\tconst response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools, userId);\n\n\t// Send response using sendDataResponse\n\tsendDataResponse(\n\t\tresponse.id || data.id,\n\t\t{\n\t\t\tsuccess: response.success,\n\t\t\terrors: response.errors,\n\t\t\tdata: response.data,\n\t\t\tuiBlockId: response.uiBlockId,\n\t\t\tthreadId: response.threadId\n\t\t},\n\t\tsendMessage,\n\t\tresponse.wsId || data.from?.id\n\t);\n}\n\n/**\n * Send a data_res response message\n */\nfunction sendDataResponse(\n\tid: string,\n\tres: T_RESPONSE & { uiBlockId?: string; threadId?: string },\n\tsendMessage: (message: Message) => void,\n\tclientId?: string,\n): void {\n\tconst response: Message = {\n\t\tid,\n\t\ttype: 'USER_PROMPT_RES',\n\t\tfrom: { type: 'data-agent' },\n\t\tto: {\n\t\t\ttype: 'runtime',\n\t\t\tid: clientId\n\t\t},\n\t\tpayload: {\n\t\t\t...res,\n\t\t}\n\t};\n\n\tsendMessage(response);\n} ","import { Message } from '../types';\nimport { logger, type LogLevel } from './logger';\n\nexport interface CapturedLog {\n timestamp: number;\n level: 'info' | 'error' | 'warn' | 'debug';\n message: string;\n type?: 'explanation' | 'query' | 'general';\n data?: Record<string, any>;\n}\n\n/**\n * Log level hierarchy for filtering\n */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n errors: 0,\n warnings: 1,\n info: 2,\n verbose: 3,\n};\n\nconst MESSAGE_LEVEL_PRIORITY: Record<'error' | 'warn' | 'info' | 'debug', number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\n/**\n * UILogCollector captures logs during user prompt processing\n * and sends them to runtime via ui_logs message with uiBlockId as the message id\n * Logs are sent in real-time for streaming effect in the UI\n * Respects the global log level configuration\n */\nexport class UILogCollector {\n private logs: CapturedLog[] = [];\n private uiBlockId: string | null;\n private clientId: string;\n private sendMessage: (message: Message) => void;\n private currentLogLevel: LogLevel;\n\n constructor(\n clientId: string,\n sendMessage: (message: Message) => void,\n uiBlockId?: string\n ) {\n this.uiBlockId = uiBlockId || null;\n this.clientId = clientId;\n this.sendMessage = sendMessage;\n this.currentLogLevel = logger.getLogLevel();\n }\n\n /**\n * Check if logging is enabled (uiBlockId is provided)\n */\n isEnabled(): boolean {\n return this.uiBlockId !== null;\n }\n\n /**\n * Check if a message should be logged based on current log level\n */\n private shouldLog(messageLevel: 'error' | 'warn' | 'info' | 'debug'): boolean {\n const currentLevelPriority = LOG_LEVEL_PRIORITY[this.currentLogLevel];\n const messagePriority = MESSAGE_LEVEL_PRIORITY[messageLevel];\n return messagePriority <= currentLevelPriority;\n }\n\n /**\n * Add a log entry with timestamp and immediately send to runtime\n * Only logs that pass the log level filter are captured and sent\n */\n private addLog(\n level: 'info' | 'error' | 'warn' | 'debug',\n message: string,\n type?: 'explanation' | 'query' | 'general',\n data?: Record<string, any>\n ): void {\n // Check if this log level should be captured based on current log level\n if (!this.shouldLog(level)) {\n return;\n }\n\n const log: CapturedLog = {\n timestamp: Date.now(),\n level,\n message,\n ...(type && { type }),\n ...(data && { data }),\n };\n\n this.logs.push(log);\n\n // Send the log immediately to runtime for streaming effect\n this.sendLogImmediately(log);\n\n // Also log to terminal using the main logger based on level\n switch (level) {\n case 'error':\n logger.error('UILogCollector:', log);\n break;\n case 'warn':\n logger.warn('UILogCollector:', log);\n break;\n case 'info':\n logger.info('UILogCollector:', log);\n break;\n case 'debug':\n logger.debug('UILogCollector:', log);\n break;\n }\n }\n\n /**\n * Send a single log to runtime immediately\n */\n private sendLogImmediately(log: CapturedLog): void {\n if (!this.isEnabled()) {\n return;\n }\n\n const response: Message = {\n id: this.uiBlockId!,\n type: 'UI_LOGS',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: this.clientId,\n },\n payload: {\n logs: [log], // Send single log in array\n },\n };\n\n this.sendMessage(response);\n }\n\n /**\n * Log info message\n */\n info(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('info', message, type, data);\n }\n }\n\n /**\n * Log error message\n */\n error(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('error', message, type, data);\n }\n }\n\n /**\n * Log warning message\n */\n warn(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('warn', message, type, data);\n }\n }\n\n /**\n * Log debug message\n */\n debug(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('debug', message, type, data);\n }\n }\n\n /**\n * Log LLM explanation with typed metadata\n */\n logExplanation(message: string, explanation: string, data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('info', message, 'explanation', {\n explanation,\n ...data,\n });\n }\n }\n\n /**\n * Log generated query with typed metadata\n */\n logQuery(message: string, query: string, data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('info', message, 'query', {\n query,\n ...data,\n });\n }\n }\n\n /**\n * Send all collected logs at once (optional, for final summary)\n */\n sendAllLogs(): void {\n if (!this.isEnabled() || this.logs.length === 0) {\n return;\n }\n\n const response: Message = {\n id: this.uiBlockId!,\n type: 'UI_LOGS',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: this.clientId,\n },\n payload: {\n logs: this.logs,\n },\n };\n\n this.sendMessage(response);\n }\n\n /**\n * Get all collected logs\n */\n getLogs(): CapturedLog[] {\n return [...this.logs];\n }\n\n /**\n * Clear all logs\n */\n clearLogs(): void {\n this.logs = [];\n }\n\n /**\n * Set uiBlockId (in case it's provided later)\n */\n setUIBlockId(uiBlockId: string): void {\n this.uiBlockId = uiBlockId;\n }\n}\n","import { logger } from './logger';\n\n/**\n * Unified UIBlock structure for database storage\n * Used in both bookmarks and user-conversations tables\n */\nexport interface DBUIBlock {\n\tid: string;\n\tcomponent: Record<string, any> | null;\n\tanalysis: string | null;\n\tuser_prompt: string;\n}\n\n/**\n * Transform UIBlock.toJSON() output to the unified DB structure\n * Maps: userQuestion -> user_prompt, generatedComponentMetadata -> component, textResponse -> analysis\n * @param uiblock - UIBlock.toJSON() output\n * @param userPrompt - The user's prompt/question\n * @param uiBlockId - The UIBlock ID (passed separately, not in uiblock object)\n */\nexport function transformUIBlockForDB(uiblock: any, userPrompt: string, uiBlockId: string): DBUIBlock {\n\t// Extract component from generatedComponentMetadata, or null if empty\n\tconst component = uiblock?.generatedComponentMetadata && Object.keys(uiblock.generatedComponentMetadata).length > 0\n\t\t? uiblock.generatedComponentMetadata\n\t\t: null;\n\n\treturn {\n\t\tid: uiBlockId || uiblock?.id || '',\n\t\tcomponent: component,\n\t\tanalysis: uiblock?.textResponse || null,\n\t\tuser_prompt: userPrompt || uiblock?.userQuestion || '',\n\t};\n}\n\n/**\n * Parameters for saving a conversation\n */\nexport interface SaveConversationParams {\n\tuserId: string;\n\tuserPrompt: string;\n\tuiblock: any; // UIBlock toJSON() output\n\tuiBlockId: string; // ID of the UIBlock\n\tthreadId: string;\n\tcollections?: any;\n}\n\n/**\n * Result of attempting to save a conversation\n */\nexport interface SaveConversationResult {\n\tsuccess: boolean;\n\tconversationId?: string;\n\tmessage?: string;\n\terror?: string;\n}\n\n/**\n * Saves a user conversation to the backend user_conversations table\n * This enables semantic search and conversation history features\n *\n * @param params - Parameters containing userId, userPrompt, uiblock, threadId, and collections\n * @returns Result indicating success/failure and conversation ID if successful\n */\nexport async function saveConversation(params: SaveConversationParams): Promise<SaveConversationResult> {\n\tconst { userId, userPrompt, uiblock, uiBlockId, threadId, collections } = params;\n\n\t// Validate required parameters\n\tif (!userId) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: userId not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'userId is required'\n\t\t};\n\t}\n\n\tif (!userPrompt) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: userPrompt not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'userPrompt is required'\n\t\t};\n\t}\n\n\tif (!uiblock) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: uiblock not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'uiblock is required'\n\t\t};\n\t}\n\n\tif (!threadId) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: threadId not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'threadId is required'\n\t\t};\n\t}\n\n\tif (!uiBlockId) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: uiBlockId not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'uiBlockId is required'\n\t\t};\n\t}\n\n\t// Check if collections are available\n\tif (!collections?.['user-conversations']?.['create']) {\n\t\tlogger.debug('[CONVERSATION_SAVER] Collection \"user-conversations.create\" not available, skipping save');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'user-conversations.create collection not available'\n\t\t};\n\t}\n\n\ttry {\n\t\tlogger.info(`[CONVERSATION_SAVER] Saving conversation for userId: ${userId}, uiBlockId: ${uiBlockId}, threadId: ${threadId}`);\n\n\t\t// Convert userId to number (SDK stores it as string, backend expects integer)\n\t\tconst userIdNumber = Number(userId);\n\t\tif (isNaN(userIdNumber)) {\n\t\t\tlogger.warn(`[CONVERSATION_SAVER] Invalid userId: ${userId} (not a valid number)`);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: `Invalid userId: ${userId} (not a valid number)`\n\t\t\t};\n\t\t}\n\n\t\t// Transform UIBlock to unified DB structure\n\t\tconst dbUIBlock = transformUIBlockForDB(uiblock, userPrompt, uiBlockId);\n\t\tlogger.debug(`[CONVERSATION_SAVER] Transformed UIBlock for DB: ${JSON.stringify(dbUIBlock)}`);\n\n\t\t// Step 1: Save to PostgreSQL user_conversations table\n\t\tconst saveResult = await collections['user-conversations']['create']({\n\t\t\tuserId: userIdNumber,\n\t\t\tuserPrompt,\n\t\t\tuiblock: dbUIBlock,\n\t\t\tthreadId\n\t\t});\n\n\t\tif (!saveResult?.success) {\n\t\t\tlogger.warn(`[CONVERSATION_SAVER] Failed to save conversation to PostgreSQL: ${saveResult?.message || 'Unknown error'}`);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: saveResult?.message || 'Unknown error from backend'\n\t\t\t};\n\t\t}\n\n\t\tlogger.info(`[CONVERSATION_SAVER] Successfully saved conversation to PostgreSQL, id: ${saveResult.data?.id}`);\n\n\t\t// Step 2: Create embedding in ChromaDB for semantic search\n\t\tif (collections?.['conversation-history']?.['embed']) {\n\t\t\ttry {\n\t\t\t\tlogger.info('[CONVERSATION_SAVER] Creating embedding for semantic search...');\n\t\t\t\tconst embedResult = await collections['conversation-history']['embed']({\n\t\t\t\t\tuiBlockId,\n\t\t\t\t\tuserPrompt,\n\t\t\t\t\tuiBlock: dbUIBlock, // Use the transformed UIBlock\n\t\t\t\t\tuserId: userIdNumber\n\t\t\t\t});\n\n\t\t\t\tif (embedResult?.success) {\n\t\t\t\t\tlogger.info('[CONVERSATION_SAVER] Successfully created embedding');\n\t\t\t\t} else {\n\t\t\t\t\tlogger.warn('[CONVERSATION_SAVER] Failed to create embedding:', embedResult?.error || 'Unknown error');\n\t\t\t\t\t// Don't fail the entire operation if embedding fails\n\t\t\t\t}\n\t\t\t} catch (embedError) {\n\t\t\t\tconst embedErrorMsg = embedError instanceof Error ? embedError.message : String(embedError);\n\t\t\t\tlogger.warn('[CONVERSATION_SAVER] Error creating embedding:', embedErrorMsg);\n\t\t\t\t// Don't fail the entire operation if embedding fails\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.debug('[CONVERSATION_SAVER] Embedding collection not available, skipping ChromaDB storage');\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tconversationId: saveResult.data?.id,\n\t\t\tmessage: 'Conversation saved successfully'\n\t\t};\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\tlogger.error('[CONVERSATION_SAVER] Error saving conversation:', errorMessage);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: errorMessage\n\t\t};\n\t}\n}\n","/**\n * Configuration for conversation context and history management\n */\nexport const CONTEXT_CONFIG = {\n /**\n * Maximum number of previous UIBlocks to include as conversation context\n * Set to 0 to disable conversation history\n * Higher values provide more context but may increase token usage\n */\n MAX_CONVERSATION_CONTEXT_BLOCKS: 3,\n};\n","import { Component, Message, UserPromptSuggestionsMessageSchema, CollectionRegistry } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle user prompt suggestions request\n * Uses token-based search for components and PostgreSQL full-text search for bookmarks\n */\nexport async function handleUserPromptSuggestions(\n data: any,\n components: Component[],\n sendMessage: (message: Message) => void,\n collections: CollectionRegistry,\n userId?: string\n): Promise<void> {\n try {\n const request = UserPromptSuggestionsMessageSchema.parse(data);\n const { id, payload, from } = request;\n\n const { prompt, limit = 10 } = payload;\n const wsId = from.id;\n\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Processing user prompt suggestions: ${prompt}`);\n\n // Validate input\n if (!prompt || prompt.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Prompt is required and cannot be empty'\n }, sendMessage, wsId);\n return;\n }\n\n // COMMENTED OUT: Semantic/embedding-based search (kept for potential future use)\n // const componentSearchHandler = collections?.['components']?.['search'];\n // const bookmarkSearchHandler = collections?.['bookmarks']?.['search'];\n //\n // let componentSuggestions: any[] = [];\n // let bookmarkSuggestions: any[] = [];\n // let useEmbeddingSearch = false;\n //\n // // Build parallel search promises\n // const searchPromises: Promise<void>[] = [];\n //\n // // Search components via embedding\n // if (componentSearchHandler) {\n // searchPromises.push(\n // (async () => {\n // try {\n // logger.info('Using embedding-based search for components');\n // const result = await componentSearchHandler({ prompt, limit });\n //\n // if (result.success && result.suggestions) {\n // componentSuggestions = result.suggestions.map((s: any) => ({\n // ...s,\n // suggestionType: 'component'\n // }));\n // useEmbeddingSearch = true;\n // logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${componentSuggestions.length} component suggestions`);\n // }\n // } catch (embeddingError) {\n // logger.warn('Component embedding search failed:', embeddingError);\n // }\n // })()\n // );\n // }\n //\n // // Search bookmarks via embedding (if userId is available)\n // if (bookmarkSearchHandler && userId && userId !== 'anonymous') {\n // searchPromises.push(\n // (async () => {\n // try {\n // logger.info(`Using embedding-based search for bookmarks (user: ${userId})`);\n // const result = await bookmarkSearchHandler({ prompt, userId, limit });\n //\n // if (result.success && result.suggestions) {\n // bookmarkSuggestions = result.suggestions.map((s: any) => ({\n // ...s,\n // suggestionType: 'bookmark'\n // }));\n // useEmbeddingSearch = true;\n // logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${bookmarkSuggestions.length} bookmark suggestions`);\n // }\n // } catch (embeddingError) {\n // logger.warn('Bookmark embedding search failed:', embeddingError);\n // }\n // })()\n // );\n // }\n //\n // // Wait for all searches to complete in parallel\n // if (searchPromises.length > 0) {\n // await Promise.all(searchPromises);\n // }\n //\n // // If we got embedding results, combine and return\n // if (useEmbeddingSearch && (componentSuggestions.length > 0 || bookmarkSuggestions.length > 0)) {\n // // Combine and sort by similarity (no threshold filtering - show all suggestions)\n // const allSuggestions = [...componentSuggestions, ...bookmarkSuggestions]\n // .sort((a, b) => (b.similarity || 0) - (a.similarity || 0))\n // .slice(0, limit);\n //\n // logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Returning all suggestions: ${componentSuggestions.length} components, ${bookmarkSuggestions.length} bookmarks`);\n //\n // sendResponse(id, {\n // success: true,\n // data: {\n // prompt,\n // suggestions: allSuggestions,\n // count: allSuggestions.length,\n // componentCount: componentSuggestions.length,\n // bookmarkCount: bookmarkSuggestions.length,\n // message: `Found ${allSuggestions.length} suggestions (${componentSuggestions.length} components, ${bookmarkSuggestions.length} bookmarks)`\n // }\n // }, sendMessage, wsId);\n // return;\n // }\n // END COMMENTED OUT SECTION\n\n // Use token-based search for components and PostgreSQL text search for bookmarks\n const displayComponents = components.filter(c => c.isDisplayComp === true);\n const bookmarkTextSearchHandler = collections?.['bookmarks']?.['textSearch'];\n\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Using token-based search for components (${displayComponents.length} display components) and PostgreSQL text search for bookmarks`);\n\n // Build parallel search promises\n const searchPromises: Promise<void>[] = [];\n let componentSuggestions: any[] = [];\n let bookmarkSuggestions: any[] = [];\n\n // Token-based search for components\n if (displayComponents.length > 0) {\n const componentResults = searchComponents(prompt, displayComponents, limit);\n componentSuggestions = componentResults.map((c: Component) => ({\n ...c,\n suggestionType: 'component',\n similarity: 1.0 // Token-based search doesn't have similarity scores\n }));\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${componentSuggestions.length} component suggestions via token search`);\n }\n\n // PostgreSQL text search for bookmarks (if userId is available)\n if (bookmarkTextSearchHandler && userId && userId !== 'anonymous') {\n searchPromises.push(\n (async () => {\n try {\n logger.info(`Using PostgreSQL text search for bookmarks (user: ${userId})`);\n const result = await bookmarkTextSearchHandler({ prompt, userId, limit });\n\n if (result.success && result.suggestions) {\n bookmarkSuggestions = result.suggestions.map((s: any) => ({\n ...s,\n suggestionType: 'bookmark'\n }));\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${bookmarkSuggestions.length} bookmark suggestions via PostgreSQL text search`);\n }\n } catch (searchError) {\n logger.warn('Bookmark PostgreSQL text search failed:', searchError);\n }\n })()\n );\n }\n\n // Wait for bookmark search to complete\n if (searchPromises.length > 0) {\n await Promise.all(searchPromises);\n }\n\n // Combine results\n const allSuggestions = [...componentSuggestions, ...bookmarkSuggestions].slice(0, limit);\n\n // Count how many of each type are actually in the final result\n const finalComponentCount = allSuggestions.filter(s => s.suggestionType === 'component').length;\n const finalBookmarkCount = allSuggestions.filter(s => s.suggestionType === 'bookmark').length;\n\n if (allSuggestions.length === 0) {\n sendResponse(id, {\n success: true,\n data: {\n prompt,\n suggestions: [],\n count: 0,\n componentCount: 0,\n bookmarkCount: 0,\n message: 'No matching suggestions found'\n }\n }, sendMessage, wsId);\n return;\n }\n\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Returning ${allSuggestions.length} suggestions: ${finalComponentCount} components, ${finalBookmarkCount} bookmarks`);\n\n sendResponse(id, {\n success: true,\n data: {\n prompt,\n suggestions: allSuggestions,\n count: allSuggestions.length,\n componentCount: finalComponentCount,\n bookmarkCount: finalBookmarkCount,\n message: `Found ${allSuggestions.length} suggestions (${finalComponentCount} components, ${finalBookmarkCount} bookmarks)`\n }\n }, sendMessage, wsId);\n\n } catch (error) {\n logger.error('Failed to handle user prompt suggestions request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Search components based on prompt keywords\n * Searches in component name, displayName, description, keywords, and category\n * @param prompt - Search prompt\n * @param components - List of components to search in\n * @param limit - Maximum number of results to return\n * @returns Matching components sorted by relevance\n */\nfunction searchComponents(prompt: string, components: Component[], limit: number): Component[] {\n const promptLower = prompt.toLowerCase();\n const promptTokens = promptLower.split(/\\s+/).filter(token => token.length > 0);\n\n // Score each component based on keyword matches\n const scoredComponents = components.map(component => {\n let score = 0;\n\n const componentName = component.name.toLowerCase();\n const componentDisplayName = (component.displayName || '').toLowerCase();\n const componentDesc = component.description.toLowerCase();\n const componentKeywords = (component.keywords || []).map(k => k.toLowerCase());\n const componentCategory = (component.category || '').toLowerCase();\n\n // Search in each field with different weights\n for (const token of promptTokens) {\n // Exact name match (highest weight)\n if (componentName === token) {\n score += 10;\n }\n // Name contains token\n else if (componentName.includes(token)) {\n score += 5;\n }\n\n // DisplayName contains token (high weight - user-friendly name)\n if (componentDisplayName.includes(token)) {\n score += 6;\n }\n\n // Exact keyword match\n if (componentKeywords.includes(token)) {\n score += 8;\n }\n // Keywords contain token\n else if (componentKeywords.some(k => k.includes(token))) {\n score += 4;\n }\n\n // Description contains token\n if (componentDesc.includes(token)) {\n score += 2;\n }\n\n // Category contains token\n if (componentCategory.includes(token)) {\n score += 3;\n }\n }\n\n return { component, score };\n });\n\n // Filter out components with score 0, sort by score (descending), and take top results\n return scoredComponents\n .filter(({ score }) => score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map(({ component }) => component);\n}\n\n/**\n * Send user prompt suggestions response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'USER_PROMPT_SUGGESTIONS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { anthropicLLM } from './anthropic';\nimport { groqLLM } from './groq';\nimport { geminiLLM } from './gemini';\nimport { openaiLLM } from './openai';\nimport { LLMProvider, Component } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Generate next questions based on the original user prompt and generated component\n * Routes to the appropriate LLM provider (Anthropic or Groq)\n * Falls back to next provider if current provider fails or returns empty results\n */\nexport async function generateNextQuestions(\n\toriginalUserPrompt: string,\n\tcomponent: Component,\n\tcomponentData?: Record<string, unknown>,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tlogCollector?: any,\n\tconversationHistory?: string\n): Promise<string[]> {\n\ttry {\n\t\tlogger.debug('[generateNextQuestions] Starting next questions generation');\n\t\tlogger.debug(`[generateNextQuestions] User prompt: \"${originalUserPrompt?.substring(0, 50)}...\"`);\n\t\tlogger.debug(`[generateNextQuestions] Component: ${component?.name || 'unknown'} (${component?.type || 'unknown'})`);\n\t\tlogger.debug(`[generateNextQuestions] Component data available: ${componentData ? 'yes' : 'no'}`);\n\n\t\t// Determine which providers to use\n\t\tconst providers = llmProviders || ['anthropic', 'gemini', 'openai', 'groq'];\n\t\tlogger.info(`[generateNextQuestions] Using LLM providers: [${providers.join(', ')}]`);\n\n\t\t// Log conversation context info\n\t\tif (conversationHistory && conversationHistory.length > 0) {\n\t\t\tconst exchangeCount = conversationHistory.split('\\n').filter((l: string) => l.startsWith('Q')).length;\n\t\t\tlogger.debug(`[generateNextQuestions] Using conversation history with ${exchangeCount} previous exchanges`);\n\t\t} else {\n\t\t\tlogger.debug('[generateNextQuestions] No conversation history available');\n\t\t}\n\n\t\t// Try each provider in order\n\t\tfor (let i = 0; i < providers.length; i++) {\n\t\t\tconst provider = providers[i];\n\t\t\tconst isLastProvider = i === providers.length - 1;\n\n\t\t\ttry {\n\t\t\t\tlogger.info(`[generateNextQuestions] Attempting provider: ${provider} (${i + 1}/${providers.length})`);\n\t\t\t\tlogCollector?.info(`Generating questions with ${provider}...`);\n\n\t\t\t\tlet result: string[] = [];\n\n\t\t\t\tif (provider === 'groq') {\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using Groq LLM for next questions');\n\t\t\t\t\tresult = await groqLLM.generateNextQuestions(\n\t\t\t\t\t\toriginalUserPrompt,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\tcomponentData,\n\t\t\t\t\t\tgroqApiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t);\n\t\t\t\t} else if (provider === 'gemini') {\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using Gemini LLM for next questions');\n\t\t\t\t\tresult = await geminiLLM.generateNextQuestions(\n\t\t\t\t\t\toriginalUserPrompt,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\tcomponentData,\n\t\t\t\t\t\tgeminiApiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t);\n\t\t\t\t} else if (provider === 'openai') {\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using OpenAI LLM for next questions');\n\t\t\t\t\tresult = await openaiLLM.generateNextQuestions(\n\t\t\t\t\t\toriginalUserPrompt,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\tcomponentData,\n\t\t\t\t\t\topenaiApiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Default to Anthropic\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using Anthropic LLM for next questions');\n\t\t\t\t\tresult = await anthropicLLM.generateNextQuestions(\n\t\t\t\t\t\toriginalUserPrompt,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\tcomponentData,\n\t\t\t\t\t\tanthropicApiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// If we got results, return them\n\t\t\t\tif (result && result.length > 0) {\n\t\t\t\t\tlogger.info(`[generateNextQuestions] Successfully generated ${result.length} questions with ${provider}`);\n\t\t\t\t\tlogger.debug(`[generateNextQuestions] Questions: ${JSON.stringify(result)}`);\n\t\t\t\t\tlogCollector?.info(`Generated ${result.length} follow-up questions`);\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tconst warnMsg = `No questions generated from ${provider}${!isLastProvider ? ', trying next provider...' : ''}`;\n\t\t\t\tlogger.warn(`[generateNextQuestions] ${warnMsg}`);\n\t\t\t\tif (!isLastProvider) {\n\t\t\t\t\tlogCollector?.warn(warnMsg);\n\t\t\t\t}\n\t\t\t} catch (providerError) {\n\t\t\t\tconst errorMsg = providerError instanceof Error ? providerError.message : String(providerError);\n\t\t\t\tlogger.error(`[generateNextQuestions] Provider ${provider} failed: ${errorMsg}`);\n\t\t\t\tlogger.debug(`[generateNextQuestions] Provider error details:`, providerError);\n\n\t\t\t\tif (!isLastProvider) {\n\t\t\t\t\tconst fallbackMsg = `Provider ${provider} failed, trying next provider...`;\n\t\t\t\t\tlogger.info(`[generateNextQuestions] ${fallbackMsg}`);\n\t\t\t\t\tlogCollector?.warn(fallbackMsg);\n\t\t\t\t} else {\n\t\t\t\t\tlogCollector?.error(`Failed to generate questions with ${provider}`);\n\t\t\t\t}\n\t\t\t\t// Continue to next provider\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// All providers failed or returned empty results\n\t\tlogger.warn('[generateNextQuestions] All providers failed or returned no questions');\n\t\tlogCollector?.warn('Unable to generate follow-up questions');\n\t\treturn [];\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\tconst errorStack = error instanceof Error ? error.stack : undefined;\n\n\t\tlogger.error(`[generateNextQuestions] Error generating next questions: ${errorMsg}`);\n\t\tlogger.debug('[generateNextQuestions] Error stack trace:', errorStack);\n\t\tlogCollector?.error(`Error generating next questions: ${errorMsg}`);\n\t\t// Return empty array on error\n\t\treturn [];\n\t}\n}\n","import { ActionsRequestMessageSchema, type LLMProvider, type Message } from '../types';\nimport { generateNextQuestions } from '../userResponse/next-questions';\nimport { logger } from '../utils/logger';\nimport { UILogCollector } from '../utils/log-collector';\nimport { ThreadManager } from '../threads';\nimport { CONTEXT_CONFIG } from '../config/context';\n\n/**\n * Handle incoming actions messages from runtime\n * Generates suggested next questions based on the original user prompt and generated component\n */\nexport async function handleActionsRequest(\n data: any,\n sendMessage: (message: Message) => void,\n anthropicApiKey?: string,\n groqApiKey?: string,\n geminiApiKey?: string,\n openaiApiKey?: string,\n llmProviders?: LLMProvider[]\n): Promise<void> {\n try {\n logger.debug('[ACTIONS_REQ] Parsing incoming actions request');\n const actionsRequest = ActionsRequestMessageSchema.parse(data);\n const { id, payload } = actionsRequest;\n const { SA_RUNTIME } = payload;\n\n const wsId = actionsRequest.from.id || 'unknown';\n\n logger.info(`[ACTIONS_REQ ${id}] Processing actions request from client: ${wsId}`);\n logger.debug(`[ACTIONS_REQ ${id}] Request payload:`, JSON.stringify(payload, null, 2).substring(0, 200));\n\n // SA_RUNTIME is required to fetch actions from UIBlock\n if (!SA_RUNTIME) {\n logger.error(`[ACTIONS_REQ ${id}] SA_RUNTIME missing from request`);\n sendResponse(id, {\n success: false,\n error: 'SA_RUNTIME with threadId and uiBlockId is required'\n }, sendMessage, wsId);\n return;\n }\n\n const uiBlockId = SA_RUNTIME.uiBlockId;\n const threadId = SA_RUNTIME.threadId;\n\n logger.debug(`[ACTIONS_REQ ${id}] SA_RUNTIME validated - threadId: ${threadId}, uiBlockId: ${uiBlockId}`);\n\n // Get UIBlock from ThreadManager\n const threadManager = ThreadManager.getInstance();\n const thread = threadManager.getThread(threadId);\n\n if (!thread) {\n logger.error(`[ACTIONS_REQ ${id}] Thread '${threadId}' not found`);\n sendResponse(id, {\n success: false,\n error: `Thread '${threadId}' not found`\n }, sendMessage, wsId);\n return;\n }\n\n logger.debug(`[ACTIONS_REQ ${id}] Thread found with ${thread.getUIBlocks().length} UIBlocks`);\n logger.debug(`[ACTIONS_REQ ${id}] Retrieving UIBlock: ${uiBlockId}`);\n\n const uiBlock = thread.getUIBlock(uiBlockId);\n if (!uiBlock) {\n logger.error(`[ACTIONS_REQ ${id}] UIBlock '${uiBlockId}' not found in thread '${threadId}'`);\n sendResponse(id, {\n success: false,\n error: `UIBlock '${uiBlockId}' not found in thread '${threadId}'`\n }, sendMessage, wsId);\n return;\n }\n\n logger.info(`[ACTIONS_REQ ${id}] UIBlock retrieved successfully`);\n\n // Create log collector with uiBlockId\n logger.debug(`[ACTIONS_REQ ${id}] Creating UILogCollector for uiBlockId: ${uiBlockId}`);\n const logCollector = new UILogCollector(wsId, sendMessage, uiBlockId);\n logger.info(`[ACTIONS_REQ ${id}] UILogCollector initialized`);\n\n // Extract data from UIBlock\n logger.debug(`[ACTIONS_REQ ${id}] Extracting data from UIBlock`);\n const userQuestion = uiBlock.getUserQuestion();\n const component = uiBlock.getComponentMetadata();\n const componentData = uiBlock.getComponentData();\n\n logger.debug(`[ACTIONS_REQ ${id}] User question: \"${userQuestion?.substring(0, 50)}...\"`);\n logger.debug(`[ACTIONS_REQ ${id}] Component: ${component?.name || 'unknown'} (${component?.type || 'unknown'})`);\n logger.debug(`[ACTIONS_REQ ${id}] Component data available: ${componentData ? 'yes' : 'no'}`);\n\n // Extract conversation context from thread (excluding current UIBlock)\n logger.debug(`[ACTIONS_REQ ${id}] Extracting conversation history (max ${CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS} blocks)`);\n const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, uiBlockId);\n const historyLineCount = conversationHistory.split('\\n').filter(l => l.trim()).length;\n logger.info(`[ACTIONS_REQ ${id}] Conversation history extracted: ${historyLineCount} lines`);\n logger.debug(`[ACTIONS_REQ ${id}] Conversation history preview:\\n${conversationHistory.substring(0, 200)}...`);\n\n logCollector.info(`Generating actions for UIBlock: ${uiBlockId}`);\n logger.info(`[ACTIONS_REQ ${id}] Generating actions for component: ${component?.name || 'unknown'}`);\n\n // Use getOrFetchActions to manage action state\n logger.debug(`[ACTIONS_REQ ${id}] Checking if actions are already cached`);\n const startTime = Date.now();\n\n const actions = await uiBlock.getOrFetchActions(async () => {\n logger.info(`[ACTIONS_REQ ${id}] Actions not cached, generating new actions...`);\n logCollector.info('Generating follow-up questions...');\n\n // Generate next questions using extracted data from UIBlock and conversation history\n logger.info(`[ACTIONS_REQ ${id}] Starting next questions generation with ${llmProviders?.join(', ') || 'default'} providers`);\n const nextQuestions = await generateNextQuestions(\n userQuestion,\n component as any,\n componentData,\n anthropicApiKey,\n groqApiKey,\n geminiApiKey,\n openaiApiKey,\n llmProviders,\n logCollector,\n conversationHistory\n );\n\n logger.info(`[ACTIONS_REQ ${id}] Generated ${nextQuestions.length} questions`);\n logger.debug(`[ACTIONS_REQ ${id}] Questions: ${JSON.stringify(nextQuestions)}`);\n\n // Convert questions to actions format\n logger.debug(`[ACTIONS_REQ ${id}] Converting questions to actions format`);\n const convertedActions = nextQuestions.map((question: string, index: number) => ({\n id: `action_${index}_${Date.now()}`,\n name: question,\n type: 'next_question',\n question\n }));\n\n logger.debug(`[ACTIONS_REQ ${id}] Converted ${convertedActions.length} actions`);\n return convertedActions;\n });\n\n const processingTime = Date.now() - startTime;\n logger.info(`[ACTIONS_REQ ${id}] Actions retrieved in ${processingTime}ms - ${actions.length} actions total`);\n\n if (actions.length > 0) {\n logCollector.info(`Generated ${actions.length} follow-up questions successfully`);\n logger.debug(`[ACTIONS_REQ ${id}] Actions: ${actions.map(a => a.name).join(', ')}`);\n } else {\n logger.warn(`[ACTIONS_REQ ${id}] No actions generated`);\n logCollector.warn('No follow-up questions could be generated');\n }\n\n logger.debug(`[ACTIONS_REQ ${id}] Sending successful response to client`);\n sendResponse(id, {\n success: true,\n data: {\n actions,\n componentName: component?.name,\n componentId: component?.id,\n uiBlockId,\n threadId\n }\n }, sendMessage, wsId);\n\n logger.info(`[ACTIONS_REQ ${id}] ✓ Actions request completed successfully`);\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n logger.error(`[ACTIONS_REQ] Failed to handle actions request: ${errorMessage}`);\n logger.debug(`[ACTIONS_REQ] Error stack trace:`, errorStack);\n\n // Try to send error response\n try {\n const parsedData = data as any;\n if (parsedData?.id && parsedData?.from?.id) {\n const logCollector = parsedData?.payload?.SA_RUNTIME?.uiBlockId\n ? new UILogCollector(parsedData.from.id, sendMessage, parsedData.payload.SA_RUNTIME.uiBlockId)\n : undefined;\n\n logCollector?.error(`Failed to generate actions: ${errorMessage}`);\n }\n } catch (logError) {\n logger.debug('[ACTIONS_REQ] Failed to send error logs to UI:', logError);\n }\n\n sendResponse(null, {\n success: false,\n error: errorMessage\n }, sendMessage);\n\n logger.info('[ACTIONS_REQ] ✗ Actions request completed with errors');\n }\n}\n\n/**\n * Send actions response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'ACTIONS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Sending ${res.success ? 'successful' : 'failed'} response to client`);\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Response payload size: ${JSON.stringify(response).length} bytes`);\n\n if (res.data?.actions) {\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Sending ${res.data.actions.length} actions`);\n }\n\n sendMessage(response);\n}\n","import { Component, ComponentListResponseMessageSchema, ComponentSchema, ComponentsSchema, Message, CollectionRegistry } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\nexport async function handleComponentListResponse(\n data: any,\n storeComponents:(components: Component[])=>void,\n collections?: CollectionRegistry\n ): Promise<void> {\n try {\n const componentListResponse = ComponentListResponseMessageSchema.parse(data);\n const { payload } = componentListResponse;\n\n const componentsList = payload.components;\n\n if(!componentsList){\n logger.error('Components list not found in the response');\n return;\n }\n\n const components = ComponentsSchema.parse(componentsList);\n storeComponents(components);\n\n // Embed display components for semantic search if collection is available\n const embedHandler = collections?.['components']?.['embed'];\n if (embedHandler) {\n try {\n logger.info('Embedding display components for semantic search...');\n const result = await embedHandler({ components });\n if (result.success) {\n logger.info(`Successfully embedded ${result.count} display components`);\n } else {\n logger.warn('Failed to embed components:', result.error);\n }\n } catch (embedError) {\n logger.warn('Failed to embed components:', embedError);\n }\n }\n\n return;\n } catch (error) {\n logger.error('Failed to handle user prompt request:', error);\n }\n }\n\n\n","import { UsersRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { getUserManager } from '../auth/user-storage';\nimport { logger } from '../utils/logger';\nimport { userInfo } from 'os';\n\n/**\n * Handle unified users management request\n * Supports operations: create, update, delete, getAll, getOne\n * Only accepts requests from 'admin' type\n *\n * Strategy: Try database collections first, fall back to file-based storage if failed\n */\nexport async function handleUsersRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n return null; // Collection not found, will fall back to file storage\n }\n return await handler(params);\n };\n\n try {\n const request = UsersRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const numericId = requestData?.id;\n const username = requestData?.username;\n const email = requestData?.email;\n const password = requestData?.password;\n const fullname = requestData?.fullname;\n const role = requestData?.role;\n const userInfo = requestData?.userInfo;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Verify request is from admin\n if (from.type !== 'admin' && operation !== 'getOne' && operation !== 'getAll' && operation !== 'query') {\n sendResponse(id, {\n success: false,\n error: 'Unauthorized: Only admin can manage users'\n }, sendMessage, from.id);\n logger.warn(`Unauthorized user management attempt from: ${from.type}`);\n return;\n }\n\n const userManager = getUserManager();\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, { username, email, password, fullname, role, userInfo }, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, numericId, { username, email, password, fullname, role, userInfo }, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, numericId, username, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, numericId, username, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, userManager, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle users request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create user operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleCreate(\n id: string,\n userData: {\n username?: string;\n email?: string;\n password?: string;\n fullname?: string;\n role?: string;\n userInfo?: Record<string, unknown>;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { username, email, password, fullname, role, userInfo } = userData;\n\n // Validate input - username is required\n if (!username || username.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Username is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!password || password.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Password is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n // Validate email format if provided\n if (email && email.trim().length > 0) {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n sendResponse(id, {\n success: false,\n error: 'Invalid email format'\n }, sendMessage, clientId);\n return;\n }\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('users', 'create', {\n username,\n email: email || undefined,\n password,\n fullname: fullname || undefined,\n role: role || undefined,\n userInfo: userInfo || undefined\n });\n\n if (result && result.success) {\n logger.info(`[DB] User created successfully: ${username}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n username: result.data?.username,\n email: result.data?.email,\n fullname: result.data?.fullname,\n role: result.data?.role,\n message: `User '${username}' created successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to create user, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n try {\n // Check if user already exists\n if (userManager.userExists(username)) {\n sendResponse(id, {\n success: false,\n error: `User '${username}' already exists`\n }, sendMessage, clientId);\n return;\n }\n\n // Check if email already exists (if provided)\n if (email && userManager.getUserByEmail(email)) {\n sendResponse(id, {\n success: false,\n error: `User with email '${email}' already exists`\n }, sendMessage, clientId);\n return;\n }\n\n // Create user object\n const newUserData: any = {\n username,\n password,\n };\n\n if (email && email.trim().length > 0) {\n newUserData.email = email.trim();\n }\n\n if (fullname && fullname.trim().length > 0) {\n newUserData.fullname = fullname.trim();\n }\n\n if (role && role.trim().length > 0) {\n newUserData.role = role.trim();\n }\n\n // Create user\n const newUser = userManager.createUser(newUserData);\n\n logger.info(`[FILE] User '${username}' created successfully`);\n sendResponse(id, {\n success: true,\n data: {\n username: newUser.username,\n email: newUser.email,\n fullname: newUser.fullname,\n role: newUser.role,\n message: `User '${username}' created successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create user'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update user operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleUpdate(\n id: string,\n numericId: number | undefined,\n userData: {\n username?: string;\n email?: string;\n password?: string;\n fullname?: string;\n role?: string;\n userInfo?: Record<string, unknown>;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { username, email, password, fullname, role, userInfo } = userData;\n\n // For DB update, we need numeric ID; for file storage, we need username\n if (!numericId && !username) {\n sendResponse(id, {\n success: false,\n error: 'User ID or username is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first (if numeric ID is provided)\n if (numericId) {\n try {\n const result = await executeCollection('users', 'update', {\n id: numericId,\n username,\n email,\n password,\n fullname,\n role,\n userInfo\n });\n\n if (result && result.success) {\n logger.info(`[DB] User updated successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n username: result.data?.username,\n email: result.data?.email,\n fullname: result.data?.fullname,\n role: result.data?.role,\n message: `User updated successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to update user, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n }\n\n // Fallback to file-based storage (requires username)\n if (!username || username.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Username is required for file-based storage update'\n }, sendMessage, clientId);\n return;\n }\n\n // Check if user exists\n if (!userManager.userExists(username)) {\n sendResponse(id, {\n success: false,\n error: `User '${username}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n // Build update object\n const updates: any = {};\n\n // Validate and add email if provided\n if (email !== undefined) {\n if (email.trim().length > 0) {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n sendResponse(id, {\n success: false,\n error: 'Invalid email format'\n }, sendMessage, clientId);\n return;\n }\n\n // Check if email is already used by another user\n const existingUser = userManager.getUserByEmail(email);\n if (existingUser && existingUser.username !== username) {\n sendResponse(id, {\n success: false,\n error: `Email '${email}' is already used by another user`\n }, sendMessage, clientId);\n return;\n }\n\n updates.email = email.trim();\n } else {\n updates.email = undefined;\n }\n }\n\n if (password !== undefined && password.trim().length > 0) {\n updates.password = password.trim();\n }\n\n if (fullname !== undefined) {\n updates.fullname = fullname.trim().length > 0 ? fullname.trim() : undefined;\n }\n\n if (role !== undefined) {\n updates.role = role.trim().length > 0 ? role.trim() : undefined;\n }\n\n if (Object.keys(updates).length === 0) {\n sendResponse(id, {\n success: false,\n error: 'No fields to update. Please provide at least one field to update.'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const updatedUser = userManager.updateUser(username, updates);\n\n logger.info(`[FILE] User '${username}' updated successfully`);\n sendResponse(id, {\n success: true,\n data: {\n username: updatedUser.username,\n email: updatedUser.email,\n fullname: updatedUser.fullname,\n role: updatedUser.role,\n message: `User '${username}' updated successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update user'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete user operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleDelete(\n id: string,\n numericId: number | undefined,\n username: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // For DB delete, we need numeric ID; for file storage, we need username\n if (!numericId && !username) {\n sendResponse(id, {\n success: false,\n error: 'User ID or username is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first (if numeric ID is provided)\n if (numericId) {\n try {\n const result = await executeCollection('users', 'delete', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] User deleted successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n username: result.data?.username,\n message: `User deleted successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to delete user, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n }\n\n // Fallback to file-based storage (requires username)\n if (!username || username.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Username is required for file-based storage delete'\n }, sendMessage, clientId);\n return;\n }\n\n // Check if user exists\n if (!userManager.userExists(username)) {\n sendResponse(id, {\n success: false,\n error: `User '${username}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n const deleted = userManager.deleteUser(username);\n\n if (!deleted) {\n sendResponse(id, {\n success: false,\n error: `Failed to delete user '${username}'`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] User '${username}' deleted successfully`);\n sendResponse(id, {\n success: true,\n data: {\n username: username,\n message: `User '${username}' deleted successfully (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all users operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection first\n try {\n const result = await executeCollection('users', 'getAll', {});\n\n if (result && result.success) {\n // Remove sensitive information like passwords\n const sanitizedUsers = result.data.map((user: any) => ({\n id: user.id,\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n userInfo : user.userInfo,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt\n }));\n\n logger.info(`[DB] Retrieved ${result.count} users`);\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: result.count,\n message: `Retrieved ${result.count} users (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get all users, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n const users = userManager.getAllUsers();\n\n // Remove sensitive information like passwords\n const sanitizedUsers = users.map((user: any) => ({\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n wsIds: user.wsIds || []\n }));\n\n logger.info(`[FILE] Retrieved ${sanitizedUsers.length} users`);\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: sanitizedUsers.length,\n message: `Retrieved ${sanitizedUsers.length} users (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one user operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetOne(\n id: string,\n numericId: number | undefined,\n username: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // For DB getOne, we need numeric ID; for file storage, we need username\n if (!numericId && !username) {\n sendResponse(id, {\n success: false,\n error: 'User ID or username is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first (if numeric ID is provided)\n if (numericId) {\n try {\n const result = await executeCollection('users', 'getOne', { id: numericId });\n\n if (result && result.success) {\n // Remove sensitive information\n const sanitizedUser = {\n id: result.data?.id,\n username: result.data?.username,\n email: result.data?.email,\n fullname: result.data?.fullname,\n role: result.data?.role,\n userInfo: result.data?.userInfo,\n createdAt: result.data?.createdAt,\n updatedAt: result.data?.updatedAt\n };\n\n logger.info(`[DB] Retrieved user ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n user: sanitizedUser,\n message: `Retrieved user (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get user, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n }\n\n // Fallback to file-based storage (requires username)\n if (!username || username.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Username is required for file-based storage lookup'\n }, sendMessage, clientId);\n return;\n }\n\n // Check if user exists\n if (!userManager.userExists(username)) {\n sendResponse(id, {\n success: false,\n error: `User '${username}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n const user = userManager.getUser(username);\n\n // Remove sensitive information\n const sanitizedUser = {\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n wsIds: user.wsIds || []\n };\n\n logger.info(`[FILE] Retrieved user: ${username}`);\n sendResponse(id, {\n success: true,\n data: {\n user: sanitizedUser,\n message: `Retrieved user '${username}' (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle query users operation with filters\n * Database only - no file fallback for query operations\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection\n try {\n const result = await executeCollection('users', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n if (result && result.success) {\n // Remove sensitive information like passwords\n const sanitizedUsers = result.data.map((user: any) => ({\n id: user.id,\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n userInfo: user.userInfo,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt\n }));\n\n logger.info(`[DB] Query returned ${result.count} users`);\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: result.count,\n message: `Query returned ${result.count} users (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to query users: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage (get all and return - no filter support)\n const users = userManager.getAllUsers();\n\n // Remove sensitive information like passwords\n const sanitizedUsers = users.map((user: any) => ({\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n userInfo : user.userInfo,\n wsIds: user.wsIds || []\n }));\n\n logger.info(`[FILE] Retrieved ${sanitizedUsers.length} users (all - no query filter)`);\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: sanitizedUsers.length,\n message: `Retrieved ${sanitizedUsers.length} users (File - no query filter)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Send users response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'USERS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { DashboardManager } from './dashboard-manager';\nimport { logger } from '../utils/logger';\n\nlet dashboardManager: DashboardManager | null = null;\n\n/**\n * Set the dashboard manager instance\n * @param manager - DashboardManager instance to use\n */\nexport function setDashboardManager(manager: DashboardManager): void {\n dashboardManager = manager;\n logger.info('DashboardManager instance set');\n}\n\n/**\n * Get the dashboard manager instance\n * @throws Error if dashboard manager is not initialized\n * @returns DashboardManager instance\n */\nexport function getDashboardManager(): DashboardManager {\n if (!dashboardManager) {\n throw new Error('DashboardManager not initialized. Call setDashboardManager first.');\n }\n return dashboardManager;\n}\n","import { DashboardsRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { getDashboardManager } from '../dashboards/dashboard-storage';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified dashboards management request\n * Supports operations: create, update, delete, getAll, getOne\n * Only accepts requests from 'admin' type\n *\n * Strategy: Try database collections first, fall back to file-based storage if failed\n */\nexport async function handleDashboardsRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n return null; // Collection not found, will fall back to file storage\n }\n return await handler(params);\n };\n\n try {\n const request = DashboardsRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const dashboardId = requestData?.dashboardId;\n const dashboard = requestData?.dashboard;\n const projectId = requestData?.projectId;\n const name = requestData?.name;\n const description = requestData?.description;\n const published = requestData?.published;\n const createdBy = requestData?.createdBy;\n const updatedBy = requestData?.updatedBy;\n const allowedUsers = requestData?.allowedUsers as number[] | undefined;\n const numericId = requestData?.id;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Verify request is from admin\n if (from.type !== 'admin') {\n sendResponse(id, {\n success: false,\n error: 'Unauthorized: Only admin can manage dashboards'\n }, sendMessage, from.id);\n logger.warn(`Unauthorized dashboard management attempt from: ${from.type}`);\n return;\n }\n\n const dashboardManager = getDashboardManager();\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, dashboardId, dashboard, projectId, name, description, published, createdBy, allowedUsers, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, numericId, dashboardId, dashboard, name, description, published, updatedBy, allowedUsers, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, numericId, dashboardId, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, numericId, dashboardId, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle dashboards request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create dashboard operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleCreate(\n id: string,\n dashboardId: string | undefined,\n dashboard: any,\n projectId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n published: boolean | undefined,\n createdBy: number | undefined,\n allowedUsers: number[] | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!dashboardId || dashboardId.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard ID is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!projectId) {\n sendResponse(id, {\n success: false,\n error: 'Project ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'create', {\n dashboardId,\n projectId,\n name: name || '',\n description,\n dashboard,\n published,\n createdBy,\n allowedUsers\n });\n\n if (result && result.success) {\n logger.info(`[DB] Dashboard created successfully, ID: ${result.data?.id}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n dashboardId: result.data?.dashboardId,\n dashboard: result.data?.dashboard || dashboard,\n message: `Dashboard created successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to create dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n try {\n if (!dashboard) {\n dashboard = {};\n }\n\n const createdDashboard = dashboardManager.createDashboard(dashboardId, dashboard);\n\n logger.info(`[FILE] Dashboard '${dashboardId}' created successfully`);\n sendResponse(id, {\n success: true,\n data: {\n dashboardId,\n dashboard: createdDashboard,\n message: `Dashboard '${dashboardId}' created successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create dashboard'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update dashboard operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleUpdate(\n id: string,\n numericId: number | undefined,\n dashboardId: string | undefined,\n dashboard: any,\n name: string | undefined,\n description: string | undefined,\n published: boolean | undefined,\n updatedBy: number | undefined,\n allowedUsers: number[] | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'update', {\n id: numericId,\n name,\n description,\n dashboard,\n published,\n updatedBy,\n allowedUsers\n });\n\n if (result && result.success) {\n logger.info(`[DB] Dashboard updated successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: result.data?.dashboardId,\n dashboard: result.data?.dashboard || dashboard,\n message: `Dashboard updated successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to update dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use dashboardId if exists, otherwise stringify numericId\n const fileStorageId = dashboardId || String(numericId);\n try {\n const updatedDashboard = dashboardManager.updateDashboard(fileStorageId, dashboard);\n\n if (!updatedDashboard) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Dashboard '${fileStorageId}' updated successfully`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: fileStorageId,\n dashboard: updatedDashboard,\n message: `Dashboard '${fileStorageId}' updated successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update dashboard'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete dashboard operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleDelete(\n id: string,\n numericId: number | undefined,\n dashboardId: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'delete', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] Dashboard deleted successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n message: `Dashboard deleted successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to delete dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use dashboardId if exists, otherwise stringify numericId\n const fileStorageId = dashboardId || String(numericId);\n const deleted = dashboardManager.deleteDashboard(fileStorageId);\n\n if (!deleted) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Dashboard '${fileStorageId}' deleted successfully`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: fileStorageId,\n message: `Dashboard '${fileStorageId}' deleted successfully (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all dashboards operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'getAll', {});\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} dashboards`);\n sendResponse(id, {\n success: true,\n data: {\n dashboards: result.data,\n count: result.count,\n message: `Retrieved ${result.count} dashboards (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get all dashboards, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n const dashboards = dashboardManager.getAllDashboards();\n\n logger.info(`[FILE] Retrieved ${dashboards.length} dashboards`);\n sendResponse(id, {\n success: true,\n data: {\n dashboards,\n count: dashboards.length,\n message: `Retrieved ${dashboards.length} dashboards (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one dashboard operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetOne(\n id: string,\n numericId: number | undefined,\n dashboardId: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'getOne', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved dashboard ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: result.data?.dashboardId,\n dashboard: result.data?.dashboard || result.data,\n message: `Retrieved dashboard (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use dashboardId if exists, otherwise stringify numericId\n const fileStorageId = dashboardId || String(numericId);\n const dashboard = dashboardManager.getDashboard(fileStorageId);\n\n if (!dashboard) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Retrieved dashboard: ${fileStorageId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: fileStorageId,\n dashboard,\n message: `Retrieved dashboard '${fileStorageId}' (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle query dashboards operation with filters\n * Database only - no file fallback for query operations\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection\n try {\n const result = await executeCollection('dashboards', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n if (result && result.success) {\n logger.info(`[DB] Query returned ${result.count} dashboards`);\n sendResponse(id, {\n success: true,\n data: {\n dashboards: result.data,\n count: result.count,\n message: `Query returned ${result.count} dashboards (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to query dashboards: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage (get all and return)\n const dashboards = dashboardManager.getAllDashboards();\n\n logger.info(`[FILE] Retrieved ${dashboards.length} dashboards (all - no query filter)`);\n sendResponse(id, {\n success: true,\n data: {\n dashboards,\n count: dashboards.length,\n message: `Retrieved ${dashboards.length} dashboards (File - no query filter)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Send dashboards response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'DASHBOARDS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { ReportManager } from './report-manager';\n\n/**\n * Global report manager instance\n */\nlet reportManager: ReportManager | null = null;\n\n/**\n * Get the global report manager instance\n * @returns ReportManager instance\n * @throws Error if report manager is not initialized\n */\nexport function getReportManager(): ReportManager {\n if (!reportManager) {\n throw new Error('Report manager not initialized. Call setReportManager first.');\n }\n return reportManager;\n}\n\n/**\n * Set the global report manager instance\n * @param manager - ReportManager instance to set\n */\nexport function setReportManager(manager: ReportManager): void {\n reportManager = manager;\n}\n","import { ReportsRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { getReportManager } from '../reports/report-storage';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified reports management request\n * Supports operations: create, update, delete, getAll, getOne, query\n * Only accepts requests from 'admin' type\n *\n * Strategy: Try database collections first, fall back to file-based storage if failed\n */\nexport async function handleReportsRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n return null; // Collection not found, will fall back to file storage\n }\n return await handler(params);\n };\n\n try {\n const request = ReportsRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const reportId = requestData?.reportId;\n const report = requestData?.report;\n const projectId = requestData?.projectId;\n const name = requestData?.name;\n const description = requestData?.description;\n const published = requestData?.published;\n const createdBy = requestData?.createdBy;\n const updatedBy = requestData?.updatedBy;\n const numericId = requestData?.id;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Verify request is from admin\n if (from.type !== 'admin') {\n sendResponse(id, {\n success: false,\n error: 'Unauthorized: Only admin can manage reports'\n }, sendMessage, from.id);\n logger.warn(`Unauthorized report management attempt from: ${from.type}`);\n return;\n }\n\n const reportManager = getReportManager();\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, reportId, report, projectId, name, description, published, createdBy, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, numericId, reportId, report, name, description, published, updatedBy, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, numericId, reportId, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, numericId, reportId, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle reports request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create report operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleCreate(\n id: string,\n reportId: string | undefined,\n report: any,\n projectId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n published: boolean | undefined,\n createdBy: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!reportId || reportId.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Report ID is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!projectId) {\n sendResponse(id, {\n success: false,\n error: 'Project ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'create', {\n reportId,\n projectId,\n name: name || '',\n description,\n report,\n published,\n createdBy\n });\n\n if (result && result.success) {\n logger.info(`[DB] Report created successfully, ID: ${result.data?.id}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n reportId: result.data?.reportId,\n report: result.data?.report || report,\n message: `Report created successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to create report, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n try {\n if (!report) {\n report = {};\n }\n\n const createdReport = reportManager.createReport(reportId, report);\n\n logger.info(`[FILE] Report '${reportId}' created successfully`);\n sendResponse(id, {\n success: true,\n data: {\n reportId,\n report: createdReport,\n message: `Report '${reportId}' created successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create report'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update report operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleUpdate(\n id: string,\n numericId: number | undefined,\n reportId: string | undefined,\n report: any,\n name: string | undefined,\n description: string | undefined,\n published: boolean | undefined,\n updatedBy: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Report ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'update', {\n id: numericId,\n name,\n description,\n report,\n published,\n updatedBy\n });\n\n if (result && result.success) {\n logger.info(`[DB] Report updated successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: result.data?.reportId,\n report: result.data?.report || report,\n message: `Report updated successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to update report, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use reportId if exists, otherwise stringify numericId\n const fileStorageId = reportId || String(numericId);\n try {\n const updatedReport = reportManager.updateReport(fileStorageId, report);\n\n if (!updatedReport) {\n sendResponse(id, {\n success: false,\n error: `Report '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Report '${fileStorageId}' updated successfully`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: fileStorageId,\n report: updatedReport,\n message: `Report '${fileStorageId}' updated successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update report'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete report operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleDelete(\n id: string,\n numericId: number | undefined,\n reportId: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Report ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'delete', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] Report deleted successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n message: `Report deleted successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to delete report, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use reportId if exists, otherwise stringify numericId\n const fileStorageId = reportId || String(numericId);\n const deleted = reportManager.deleteReport(fileStorageId);\n\n if (!deleted) {\n sendResponse(id, {\n success: false,\n error: `Report '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Report '${fileStorageId}' deleted successfully`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: fileStorageId,\n message: `Report '${fileStorageId}' deleted successfully (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all reports operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'getAll', {});\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} reports`);\n sendResponse(id, {\n success: true,\n data: {\n reports: result.data,\n count: result.count,\n message: `Retrieved ${result.count} reports (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get all reports, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n const reports = reportManager.getAllReports();\n\n logger.info(`[FILE] Retrieved ${reports.length} reports`);\n sendResponse(id, {\n success: true,\n data: {\n reports,\n count: reports.length,\n message: `Retrieved ${reports.length} reports (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one report operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetOne(\n id: string,\n numericId: number | undefined,\n reportId: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Report ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'getOne', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved report ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: result.data?.reportId,\n report: result.data?.report || result.data,\n message: `Retrieved report (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get report, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use reportId if exists, otherwise stringify numericId\n const fileStorageId = reportId || String(numericId);\n const report = reportManager.getReport(fileStorageId);\n\n if (!report) {\n sendResponse(id, {\n success: false,\n error: `Report '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Retrieved report: ${fileStorageId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: fileStorageId,\n report,\n message: `Retrieved report '${fileStorageId}' (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle query reports operation with filters\n * Database only - no file fallback for query operations\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection\n try {\n const result = await executeCollection('reports', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n if (result && result.success) {\n logger.info(`[DB] Query returned ${result.count} reports`);\n sendResponse(id, {\n success: true,\n data: {\n reports: result.data,\n count: result.count,\n message: `Query returned ${result.count} reports (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to query reports: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage (get all and return)\n const reports = reportManager.getAllReports();\n\n logger.info(`[FILE] Retrieved ${reports.length} reports (all - no query filter)`);\n sendResponse(id, {\n success: true,\n data: {\n reports,\n count: reports.length,\n message: `Retrieved ${reports.length} reports (File - no query filter)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Send reports response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'REPORTS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { UIsRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified UIs management request\n * Supports operations: create, update, delete, getAll, getOne, query\n * Only accepts requests from 'admin' type\n *\n * Uses database collections only (no file-based fallback)\n */\nexport async function handleUIsRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n throw new Error(`Collection handler not found: ${collection}.${op}`);\n }\n return await handler(params);\n };\n\n try {\n const request = UIsRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const uiId = requestData?.uiId;\n const ui = requestData?.ui;\n const projectId = requestData?.projectId;\n const name = requestData?.name;\n const description = requestData?.description;\n const createdBy = requestData?.createdBy;\n const updatedBy = requestData?.updatedBy;\n const numericId = requestData?.id;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Verify request is from admin\n if (from.type !== 'admin') {\n sendResponse(id, {\n success: false,\n error: 'Unauthorized: Only admin can manage UIs'\n }, sendMessage, from.id);\n logger.warn(`Unauthorized UI management attempt from: ${from.type}`);\n return;\n }\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, uiId, ui, projectId, name, description, createdBy, executeCollection, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, numericId, ui, name, description, updatedBy, executeCollection, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, numericId, executeCollection, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, numericId, executeCollection, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle UIs request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create UI operation\n */\nasync function handleCreate(\n id: string,\n uiId: string | undefined,\n ui: any,\n projectId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n createdBy: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!uiId || uiId.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'UI ID is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!projectId || projectId.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Project ID is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('uis', 'create', {\n uiId,\n projectId,\n name: name || uiId,\n description,\n ui,\n createdBy\n });\n\n if (result && result.success) {\n logger.info(`UI created successfully, ID: ${result.data?.id}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n uiId: result.data?.uiId || uiId,\n ui: result.data?.ui || ui,\n message: `UI created successfully`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to create UI'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create UI'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update UI operation\n */\nasync function handleUpdate(\n id: string,\n numericId: number | undefined,\n ui: any,\n name: string | undefined,\n description: string | undefined,\n updatedBy: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'UI ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('uis', 'update', {\n id: numericId,\n name,\n description,\n ui,\n updatedBy\n });\n\n if (result && result.success) {\n logger.info(`UI updated successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n uiId: result.data?.uiId,\n ui: result.data?.ui || ui,\n message: `UI updated successfully`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to update UI'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update UI'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete UI operation\n */\nasync function handleDelete(\n id: string,\n numericId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'UI ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('uis', 'delete', { id: numericId });\n\n if (result && result.success) {\n logger.info(`UI deleted successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n message: `UI deleted successfully`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to delete UI'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to delete UI'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all UIs operation\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('uis', 'getAll', {});\n\n if (result && result.success) {\n logger.info(`Retrieved ${result.count} UIs`);\n sendResponse(id, {\n success: true,\n data: {\n uis: result.data,\n count: result.count,\n message: `Retrieved ${result.count} UIs`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to get UIs'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to get UIs'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get one UI operation\n */\nasync function handleGetOne(\n id: string,\n numericId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'UI ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('uis', 'getOne', { id: numericId });\n\n if (result && result.success) {\n logger.info(`Retrieved UI ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n uiId: result.data?.uiId,\n ui: result.data?.ui || result.data,\n message: `Retrieved UI`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: `UI not found`\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to get UI'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle query UIs operation with filters\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('uis', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n if (result && result.success) {\n logger.info(`Query returned ${result.count} UIs`);\n sendResponse(id, {\n success: true,\n data: {\n uis: result.data,\n count: result.count,\n message: `Query returned ${result.count} UIs`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to query UIs'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to query UIs'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Send UIs response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'UIS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { BookmarksRequestMessageSchema, Message, CollectionRegistry, DBUIBlock } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified bookmarks management request\n * Supports operations: create, update, delete, getAll, getOne\n * Routes requests to backend collections\n */\nexport async function handleBookmarksRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n throw new Error(`Collection operation ${collection}.${op} not found`);\n }\n return await handler(params);\n };\n try {\n const request = BookmarksRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const bookmarkId = requestData?.id;\n const userId = requestData?.userId;\n const threadId = requestData?.threadId;\n const name = requestData?.name;\n const description = requestData?.description;\n const uiblock = requestData?.uiblock;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, userId, threadId, name, description, uiblock, executeCollection, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, bookmarkId, threadId, name, description, uiblock, executeCollection, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, bookmarkId, executeCollection, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, bookmarkId, executeCollection, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle bookmarks request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create bookmark operation\n */\nasync function handleCreate(\n id: string,\n userId: number | undefined,\n threadId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n uiblock: DBUIBlock | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!userId) {\n sendResponse(id, {\n success: false,\n error: 'userId is required'\n }, sendMessage, clientId);\n return;\n }\n\n if (!uiblock) {\n sendResponse(id, {\n success: false,\n error: 'UIBlock data is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('bookmarks', 'create', { userId, threadId, name, description, uiblock });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n message: 'Bookmark created successfully'\n }, sendMessage, clientId);\n\n logger.info(`Bookmark created: ID ${result.data.id}`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create bookmark'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update bookmark operation\n */\nasync function handleUpdate(\n id: string,\n bookmarkId: number | undefined,\n threadId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n uiblock: DBUIBlock | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!bookmarkId) {\n sendResponse(id, {\n success: false,\n error: 'Bookmark ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('bookmarks', 'update', { id: bookmarkId, threadId, name, description, uiblock });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n message: 'Bookmark updated successfully'\n }, sendMessage, clientId);\n\n logger.info(`Bookmark updated: ID ${bookmarkId}`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update bookmark'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete bookmark operation\n */\nasync function handleDelete(\n id: string,\n bookmarkId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!bookmarkId) {\n sendResponse(id, {\n success: false,\n error: 'Bookmark ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('bookmarks', 'delete', { id: bookmarkId });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n message: 'Bookmark deleted successfully'\n }, sendMessage, clientId);\n\n logger.info(`Bookmark deleted: ID ${bookmarkId}`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to delete bookmark'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all bookmarks operation\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('bookmarks', 'getAll', {});\n\n sendResponse(id, {\n success: true,\n data: result.data,\n count: result.count,\n message: `Retrieved ${result.count} bookmarks`\n }, sendMessage, clientId);\n\n logger.info(`Retrieved all bookmarks (count: ${result.count})`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to get bookmarks'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get one bookmark operation\n */\nasync function handleGetOne(\n id: string,\n bookmarkId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!bookmarkId) {\n sendResponse(id, {\n success: false,\n error: 'Bookmark ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('bookmarks', 'getOne', { id: bookmarkId });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n message: `Retrieved bookmark ID ${bookmarkId}`\n }, sendMessage, clientId);\n\n logger.info(`Retrieved bookmark: ID ${bookmarkId}`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to get bookmark'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle query bookmarks operation with filters\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('bookmarks', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n count: result.count,\n message: `Query returned ${result.count} bookmarks`\n }, sendMessage, clientId);\n\n logger.info(`Query returned ${result.count} bookmarks`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to query bookmarks'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Send bookmarks response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any; count?: number; message?: string },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'BOOKMARKS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'user',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { KbNodesRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified KB Nodes (Knowledge Base) management request\n * Supports operations: create, update, delete, getAll, getOne, search, getByCategory, getByUser, getCategories, getTags\n *\n * Strategy: Uses database collections for all operations\n */\nexport async function handleKbNodesRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n throw new Error(`Collection '${collection}' or operation '${op}' not found`);\n }\n return await handler(params);\n };\n\n try {\n const request = KbNodesRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n\n // Extract fields from request data\n const nodeId = requestData?.id;\n const title = requestData?.title;\n const content = requestData?.content;\n const category = requestData?.category;\n const tags = requestData?.tags;\n const createdBy = requestData?.createdBy;\n const updatedBy = requestData?.updatedBy;\n const userId = requestData?.userId;\n const query = requestData?.query;\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const offset = requestData?.offset;\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, { title, content, category, tags, createdBy }, executeCollection, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, nodeId, { title, content, category, tags, updatedBy }, executeCollection, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, nodeId, executeCollection, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, limit, offset, executeCollection, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, nodeId, executeCollection, sendMessage, from.id);\n break;\n\n case 'search':\n await handleSearch(id, { query, category, tags, createdBy, limit, offset }, executeCollection, sendMessage, from.id);\n break;\n\n case 'getByCategory':\n await handleGetByCategory(id, category, limit, offset, executeCollection, sendMessage, from.id);\n break;\n\n case 'getByUser':\n await handleGetByUser(id, userId, limit, offset, executeCollection, sendMessage, from.id);\n break;\n\n case 'getCategories':\n await handleGetCategories(id, executeCollection, sendMessage, from.id);\n break;\n\n case 'getTags':\n await handleGetTags(id, executeCollection, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle KB nodes request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create KB node operation\n */\nasync function handleCreate(\n id: string,\n nodeData: {\n title?: string;\n content?: string;\n category?: string;\n tags?: string[];\n createdBy?: number;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { title, content, category, tags, createdBy } = nodeData;\n\n // Validate required fields\n if (!title || title.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Title is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!content || content.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Content is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!createdBy) {\n sendResponse(id, {\n success: false,\n error: 'createdBy (user ID) is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'create', {\n title,\n content,\n category: category || undefined,\n tags: tags || undefined,\n createdBy\n });\n\n if (result && result.success) {\n logger.info(`[DB] KB node created successfully: ${title}`);\n sendResponse(id, {\n success: true,\n data: {\n ...result.data,\n message: `Knowledge node '${title}' created successfully`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to create knowledge node'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to create KB node:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create knowledge node'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update KB node operation\n */\nasync function handleUpdate(\n id: string,\n nodeId: number | undefined,\n nodeData: {\n title?: string;\n content?: string;\n category?: string;\n tags?: string[];\n updatedBy?: number;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { title, content, category, tags, updatedBy } = nodeData;\n\n if (!nodeId) {\n sendResponse(id, {\n success: false,\n error: 'Knowledge node ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n if (!updatedBy) {\n sendResponse(id, {\n success: false,\n error: 'updatedBy (user ID) is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'update', {\n id: nodeId,\n title,\n content,\n category,\n tags,\n updatedBy\n });\n\n if (result && result.success) {\n logger.info(`[DB] KB node updated successfully, ID: ${nodeId}`);\n sendResponse(id, {\n success: true,\n data: {\n ...result.data,\n message: `Knowledge node updated successfully`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to update knowledge node'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to update KB node:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update knowledge node'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete KB node operation\n */\nasync function handleDelete(\n id: string,\n nodeId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n if (!nodeId) {\n sendResponse(id, {\n success: false,\n error: 'Knowledge node ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'delete', { id: nodeId });\n\n if (result && result.success) {\n logger.info(`[DB] KB node deleted successfully, ID: ${nodeId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: nodeId,\n ...result.data,\n message: `Knowledge node deleted successfully`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to delete knowledge node'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to delete KB node:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to delete knowledge node'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all KB nodes operation\n */\nasync function handleGetAll(\n id: string,\n limit: number | undefined,\n offset: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('kbNodes', 'getAll', {\n limit: limit || 100,\n offset: offset || 0\n });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} KB nodes`);\n sendResponse(id, {\n success: true,\n data: {\n nodes: result.data,\n count: result.count,\n message: `Retrieved ${result.count} knowledge nodes`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve knowledge nodes'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get all KB nodes:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve knowledge nodes'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get one KB node operation\n */\nasync function handleGetOne(\n id: string,\n nodeId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n if (!nodeId) {\n sendResponse(id, {\n success: false,\n error: 'Knowledge node ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'getOne', { id: nodeId });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved KB node ID: ${nodeId}`);\n sendResponse(id, {\n success: true,\n data: {\n node: result.data,\n message: `Retrieved knowledge node`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve knowledge node'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get KB node:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve knowledge node'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle search KB nodes operation\n */\nasync function handleSearch(\n id: string,\n searchParams: {\n query?: string;\n category?: string;\n tags?: string[];\n createdBy?: number;\n limit?: number;\n offset?: number;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { query, category, tags, createdBy, limit, offset } = searchParams;\n\n try {\n const result = await executeCollection('kbNodes', 'search', {\n query,\n category,\n tags,\n createdBy,\n limit: limit || 50,\n offset: offset || 0\n });\n\n if (result && result.success) {\n logger.info(`[DB] Search returned ${result.count} KB nodes`);\n sendResponse(id, {\n success: true,\n data: {\n nodes: result.data,\n count: result.count,\n message: `Search returned ${result.count} knowledge nodes`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to search knowledge nodes'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to search KB nodes:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to search knowledge nodes'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get KB nodes by category operation\n */\nasync function handleGetByCategory(\n id: string,\n category: string | undefined,\n limit: number | undefined,\n offset: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n if (!category) {\n sendResponse(id, {\n success: false,\n error: 'Category is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'getByCategory', {\n category,\n limit: limit || 50,\n offset: offset || 0\n });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} KB nodes for category: ${category}`);\n sendResponse(id, {\n success: true,\n data: {\n nodes: result.data,\n count: result.count,\n category,\n message: `Retrieved ${result.count} knowledge nodes for category '${category}'`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve knowledge nodes by category'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get KB nodes by category:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve knowledge nodes by category'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get KB nodes by user operation\n */\nasync function handleGetByUser(\n id: string,\n userId: number | undefined,\n limit: number | undefined,\n offset: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n if (!userId) {\n sendResponse(id, {\n success: false,\n error: 'User ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'getByUser', {\n userId,\n limit: limit || 50,\n offset: offset || 0\n });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} KB nodes for user: ${userId}`);\n sendResponse(id, {\n success: true,\n data: {\n nodes: result.data,\n count: result.count,\n userId,\n message: `Retrieved ${result.count} knowledge nodes for user ${userId}`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve knowledge nodes by user'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get KB nodes by user:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve knowledge nodes by user'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all categories operation\n */\nasync function handleGetCategories(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('kbNodes', 'getCategories', {});\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} categories`);\n sendResponse(id, {\n success: true,\n data: {\n categories: result.data,\n count: result.count,\n message: `Retrieved ${result.count} categories`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve categories'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get categories:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve categories'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all tags operation\n */\nasync function handleGetTags(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('kbNodes', 'getTags', {});\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} tags`);\n sendResponse(id, {\n success: true,\n data: {\n tags: result.data,\n count: result.count,\n message: `Retrieved ${result.count} tags`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve tags'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get tags:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve tags'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Send KB nodes response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'KB_NODES_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { Component, LLMProvider, Message, DashCompRequestMessageSchema, T_RESPONSE, CollectionRegistry, Tool } from \"../types\";\nimport { logger } from \"../utils/logger\";\nimport { LLM } from \"../llm\";\nimport { promptLoader } from \"../userResponse/prompt-loader\";\nimport { schema } from \"../userResponse/schema\";\nimport { ZodError } from \"zod\";\n\n// Define return type for dash comp request\ninterface DashCompResponse extends T_RESPONSE {\n\tid?: string;\n\twsId?: string;\n}\n\n/**\n * Pick a component and generate props using LLM\n * Supports both database queries and external tools for data viewing/modification\n */\nasync function pickComponentWithLLM(\n\tprompt: string,\n\tcomponents: Component[],\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\t_collections?: CollectionRegistry,\n\ttools?: Tool[]\n): Promise<T_RESPONSE> {\n\tconst errors: string[] = [];\n\n\t// Format available components for the prompt\n\tlet availableComponentsText = 'No components available';\n\tif (components && components.length > 0) {\n\t\tavailableComponentsText = components\n\t\t\t.map((comp, idx) => {\n\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\n\t\t\t\tconst propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : 'No props';\n\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\n Name: ${comp.name}\n Type: ${comp.type}\n Description: ${comp.description || 'No description'}\n Keywords: ${keywords}\n Props Structure: ${propsPreview}`;\n\t\t\t})\n\t\t\t.join('\\n\\n');\n\t}\n\n\t// Format available external tools for the prompt\n\tlet availableToolsText = 'No external tools available.';\n\tif (tools && tools.length > 0) {\n\t\tavailableToolsText = tools\n\t\t\t.map((tool, idx) => {\n\t\t\t\tconst paramsStr = Object.entries(tool.params || {})\n\t\t\t\t\t.map(([key, type]) => `${key}: ${type}`)\n\t\t\t\t\t.join(', ');\n\t\t\t\treturn `${idx + 1}. ID: ${tool.id}\n Name: ${tool.name}\n Description: ${tool.description}\n Parameters: { ${paramsStr} }`;\n\t\t\t})\n\t\t\t.join('\\n\\n');\n\t}\n\n\ttry {\n\t\t// Get database schema documentation for query generation\n\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t// Get database-specific SQL rules\n\t\tconst databaseRules = await promptLoader.loadDatabaseRules();\n\n\t\t// Load prompts for dash-comp-picker\n\t\tconst prompts = await promptLoader.loadPrompts('dash-comp-picker', {\n\t\t\tUSER_PROMPT: prompt,\n\t\t\tAVAILABLE_COMPONENTS: availableComponentsText,\n\t\t\tSCHEMA_DOC: schemaDoc || 'No database schema available',\n\t\t\tDATABASE_RULES: databaseRules,\n\t\t\tAVAILABLE_TOOLS: availableToolsText\n\t\t});\n\n\t\tlogger.debug('[DASH_COMP_REQ] Loaded dash-comp-picker prompts with schema and tools');\n\n\t\t// Determine which API key to use based on provider order\n\t\tconst providers = llmProviders || ['anthropic', 'gemini', 'openai', 'groq'];\n\t\tlet apiKey: string | undefined;\n\t\t// let model: string = 'anthropic/claude-haiku-4-5-20251001';\n\t\tlet model: string = 'anthropic/claude-sonnet-4-5-20250929';\n\n\t\tfor (const provider of providers) {\n\t\t\tif (provider === 'anthropic' && anthropicApiKey) {\n\t\t\t\tapiKey = anthropicApiKey;\n\t\t\t\t// model = 'anthropic/claude-haiku-4-5-20251001';\n\t\t\t\tmodel = 'anthropic/claude-sonnet-4-5-20250929';\n\t\t\t\tbreak;\n\t\t\t} else if (provider === 'openai' && openaiApiKey) {\n\t\t\t\tapiKey = openaiApiKey;\n\t\t\t\tmodel = 'openai/gpt-4o-mini';\n\t\t\t\tbreak;\n\t\t\t} else if (provider === 'gemini' && geminiApiKey) {\n\t\t\t\tapiKey = geminiApiKey;\n\t\t\t\tmodel = 'google/gemini-2.0-flash-001';\n\t\t\t\tbreak;\n\t\t\t} else if (provider === 'groq' && groqApiKey) {\n\t\t\t\tapiKey = groqApiKey;\n\t\t\t\tmodel = 'groq/llama-3.3-70b-versatile';\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!apiKey) {\n\t\t\terrors.push('No API key available for any LLM provider');\n\t\t\treturn { success: false, errors };\n\t\t}\n\n\t\tlogger.info(`[DASH_COMP_REQ] Using model: ${model}`);\n\n\t\t// Make LLM call\n\t\tconst result = await LLM.stream<any>(\n\t\t\t{\n\t\t\t\tsys: prompts.system,\n\t\t\t\tuser: prompts.user\n\t\t\t},\n\t\t\t{\n\t\t\t\tmodel,\n\t\t\t\tmaxTokens: 8192,\n\t\t\t\ttemperature: 0.2,\n\t\t\t\tapiKey\n\t\t\t},\n\t\t\ttrue // Parse as JSON\n\t\t) as any;\n\n\t\tlogger.debug('[DASH_COMP_REQ] LLM response received');\n\t\tlogger.file('[DASH_COMP_REQ] LLM response:', JSON.stringify(result, null, 2));\n\n\t\t// Validate response structure\n\t\tif (!result.componentId || !result.props) {\n\t\t\terrors.push('Invalid LLM response: missing componentId or props');\n\t\t\treturn { success: false, errors };\n\t\t}\n\n\t\t// Find the original component\n\t\tconst originalComponent = components.find(c => c.id === result.componentId);\n\t\tif (!originalComponent) {\n\t\t\terrors.push(`Component ${result.componentId} not found in available components`);\n\t\t\treturn { success: false, errors };\n\t\t}\n\n\t\t// Build the final component with generated props\n\t\tconst finalComponent: Component = {\n\t\t\t...originalComponent,\n\t\t\tprops: {\n\t\t\t\t...originalComponent.props,\n\t\t\t\t...result.props\n\t\t\t}\n\t\t};\n\n\t\tlogger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);\n\n\t\t// Log data source info\n\t\tif (result.props.query) {\n\t\t\tlogger.info(`[DASH_COMP_REQ] Data source: Database query`);\n\t\t}\n\t\tif (result.props.externalTool) {\n\t\t\tlogger.info(`[DASH_COMP_REQ] Data source: External tool - ${result.props.externalTool.toolName}`);\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tcomponent: finalComponent,\n\t\t\t\treasoning: result.reasoning || 'Component selected based on user prompt',\n\t\t\t\tdataSource: result.props.query ? 'database' : (result.props.externalTool ? 'external_tool' : 'none')\n\t\t\t},\n\t\t\terrors: []\n\t\t};\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\tlogger.error(`[DASH_COMP_REQ] Error picking component: ${errorMsg}`);\n\t\terrors.push(errorMsg);\n\t\treturn { success: false, errors };\n\t}\n}\n\n/**\n * Process DASH_COMP_REQ request\n */\nconst processDashCompRequest = async (\n\tdata: any,\n\tcomponents: Component[],\n\t_sendMessage: (message: Message) => void,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tcollections?: CollectionRegistry,\n\ttools?: Tool[]\n): Promise<DashCompResponse> => {\n\tconst errors: string[] = [];\n\n\t// Parse incoming message data\n\tlogger.debug('[DASH_COMP_REQ] Parsing incoming message data');\n\tconst parseResult = DashCompRequestMessageSchema.safeParse(data);\n\n\tif (!parseResult.success) {\n\t\tconst zodError = parseResult.error as ZodError;\n\t\tzodError.errors.forEach(err => {\n\t\t\terrors.push(`${err.path.join('.')}: ${err.message}`);\n\t\t});\n\t\treturn { success: false, errors };\n\t}\n\n\tconst dashCompRequest = parseResult.data;\n\tconst { id, payload } = dashCompRequest;\n\tconst prompt = payload.prompt;\n\tconst wsId = dashCompRequest.from.id || 'unknown';\n\n\t// Validate required fields\n\tif (!prompt) {\n\t\terrors.push('Prompt is required');\n\t}\n\n\tif (errors.length > 0) {\n\t\treturn { success: false, errors, id, wsId };\n\t}\n\n\tlogger.info(`[DASH_COMP_REQ] Processing request for prompt: \"${prompt.substring(0, 50)}...\"`);\n\tlogger.info(`[DASH_COMP_REQ] Available: ${components?.length || 0} components, ${tools?.length || 0} tools`);\n\n\t// Check if components are available\n\tif (!components || components.length === 0) {\n\t\tlogger.warn('[DASH_COMP_REQ] No components available');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terrors: ['No components available. Please ensure components are loaded.'],\n\t\t\tid,\n\t\t\twsId\n\t\t};\n\t}\n\n\t// Pick component using LLM\n\tconst llmResponse = await pickComponentWithLLM(\n\t\tprompt,\n\t\tcomponents,\n\t\tanthropicApiKey,\n\t\tgroqApiKey,\n\t\tgeminiApiKey,\n\t\topenaiApiKey,\n\t\tllmProviders,\n\t\tcollections,\n\t\ttools\n\t);\n\n\treturn {\n\t\tsuccess: llmResponse.success,\n\t\tdata: llmResponse.data,\n\t\terrors: llmResponse.errors,\n\t\tid,\n\t\twsId\n\t};\n};\n\n/**\n * Handle DASH_COMP_REQ WebSocket message\n */\nexport async function handleDashCompRequest(\n\tdata: any,\n\tcomponents: Component[],\n\tsendMessage: (message: Message) => void,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tcollections?: CollectionRegistry,\n\ttools?: Tool[]\n): Promise<void> {\n\tconst response = await processDashCompRequest(\n\t\tdata,\n\t\tcomponents,\n\t\tsendMessage,\n\t\tanthropicApiKey,\n\t\tgroqApiKey,\n\t\tgeminiApiKey,\n\t\topenaiApiKey,\n\t\tllmProviders,\n\t\tcollections,\n\t\ttools\n\t);\n\n\t// Send response back via WebSocket\n\tsendDashCompResponse(\n\t\tresponse.id || data.id,\n\t\t{\n\t\t\tsuccess: response.success,\n\t\t\terrors: response.errors,\n\t\t\tdata: response.data\n\t\t},\n\t\tsendMessage,\n\t\tresponse.wsId || data.from?.id\n\t);\n}\n\n/**\n * Send DASH_COMP_RES response message\n */\nfunction sendDashCompResponse(\n\tid: string,\n\tres: T_RESPONSE,\n\tsendMessage: (message: Message) => void,\n\tclientId?: string\n): void {\n\tconst response: Message = {\n\t\tid,\n\t\ttype: 'DASH_COMP_RES',\n\t\tfrom: { type: 'data-agent' },\n\t\tto: {\n\t\t\ttype: 'runtime',\n\t\t\tid: clientId\n\t\t},\n\t\tpayload: {\n\t\t\t...res\n\t\t}\n\t};\n\n\tsendMessage(response);\n\tlogger.info(`[DASH_COMP_REQ] Response sent to client ${clientId}`);\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { logger } from '../utils/logger';\nimport { UserSchema, UsersDataSchema, type User, type UsersData } from '../types';\n\n/**\n * UserManager class to handle CRUD operations on users with file persistence\n * and in-memory caching. Changes are synced to file periodically.\n */\nexport class UserManager {\n private users: User[] = [];\n private filePath: string;\n private hasChanged: boolean = false;\n private syncInterval: ReturnType<typeof setInterval> | null = null;\n private syncIntervalMs: number;\n private isInitialized: boolean = false;\n\n /**\n * Initialize UserManager with file path and sync interval\n * @param projectId - Project ID to use in file path (default: 'snowflake-dataset')\n * @param syncIntervalMs - Interval in milliseconds to sync changes to file (default: 5000ms)\n */\n constructor(projectId: string = 'snowflake-dataset', syncIntervalMs: number = 5000) {\n this.filePath = path.join(os.homedir(), '.superatom', 'projects', projectId, 'users.json');\n this.syncIntervalMs = syncIntervalMs;\n }\n\n /**\n * Initialize the UserManager by loading users from file and starting sync interval\n */\n async init(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n try {\n // Load users from file into memory\n await this.loadUsersFromFile();\n logger.info(`UserManager initialized with ${this.users.length} users`);\n\n // Start the sync interval\n this.startSyncInterval();\n this.isInitialized = true;\n } catch (error) {\n logger.error('Failed to initialize UserManager:', error);\n throw error;\n }\n }\n\n /**\n * Load users from the JSON file into memory\n */\n private async loadUsersFromFile(): Promise<void> {\n try {\n // Create directory structure if it doesn't exist\n const dir = path.dirname(this.filePath);\n if (!fs.existsSync(dir)) {\n logger.info(`Creating directory structure: ${dir}`);\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Create file with empty users array if it doesn't exist\n if (!fs.existsSync(this.filePath)) {\n logger.info(`Users file does not exist at ${this.filePath}, creating with empty users`);\n const initialData: UsersData = { users: [] };\n fs.writeFileSync(this.filePath, JSON.stringify(initialData, null, 4));\n this.users = [];\n this.hasChanged = false;\n return;\n }\n\n const fileContent = fs.readFileSync(this.filePath, 'utf-8');\n const rawData = JSON.parse(fileContent);\n\n // Validate using Zod schema\n const validatedData = UsersDataSchema.parse(rawData);\n this.users = validatedData.users;\n this.hasChanged = false;\n logger.debug(`Loaded ${this.users.length} users from file`);\n } catch (error) {\n logger.error('Failed to load users from file:', error);\n throw new Error(`Failed to load users from file: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * Save users from memory to the JSON file\n */\n private async saveUsersToFile(): Promise<void> {\n if (!this.hasChanged) {\n return;\n }\n\n try {\n // Create directory if it doesn't exist\n const dir = path.dirname(this.filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Filter out wsIds before saving to file (wsIds are only stored in memory)\n const usersToSave = this.users.map(user => {\n const { wsIds, ...userWithoutWsIds } = user;\n return userWithoutWsIds;\n });\n\n const data: UsersData = { users: usersToSave };\n fs.writeFileSync(this.filePath, JSON.stringify(data, null, 4));\n\n this.hasChanged = false;\n logger.debug(`Synced ${this.users.length} users to file (wsIds excluded)`);\n } catch (error) {\n logger.error('Failed to save users to file:', error);\n throw new Error(`Failed to save users to file: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * Start the periodic sync interval\n */\n private startSyncInterval(): void {\n if (this.syncInterval) {\n return;\n }\n\n this.syncInterval = setInterval(async () => {\n if (this.hasChanged) {\n try {\n await this.saveUsersToFile();\n logger.debug('Auto-sync: Users saved to file');\n } catch (error) {\n logger.error('Auto-sync failed:', error);\n }\n }\n }, this.syncIntervalMs);\n\n logger.debug(`Sync interval started (${this.syncIntervalMs}ms)`);\n }\n\n /**\n * Stop the periodic sync interval\n */\n public stopSyncInterval(): void {\n if (this.syncInterval) {\n clearInterval(this.syncInterval);\n this.syncInterval = null;\n logger.debug('Sync interval stopped');\n }\n }\n\n /**\n * Force sync users to file immediately\n */\n public async forceSync(): Promise<void> {\n await this.saveUsersToFile();\n }\n\n /**\n * Create a new user\n * @param user - User object to create\n * @returns The created user\n */\n public createUser(user: User): User {\n // Validate user data with Zod schema\n const validatedUser = UserSchema.parse(user);\n\n // Check for duplicate username\n if (this.users.some(u => u.username === validatedUser.username)) {\n throw new Error(`User with username ${validatedUser.username} already exists`);\n }\n\n // Check for duplicate email if email is provided\n if (validatedUser.email && this.users.some(u => u.email === validatedUser.email)) {\n throw new Error(`User with email ${validatedUser.email} already exists`);\n }\n\n this.users.push(validatedUser);\n this.hasChanged = true;\n logger.debug(`User created: ${validatedUser.username}`);\n\n return validatedUser;\n }\n\n /**\n * Read a user by username\n * @param username - Username to retrieve\n * @returns The user if found, undefined otherwise\n */\n public getUser(username: string): User | undefined {\n return this.users.find(u => u.username === username);\n }\n\n /**\n * Read a user by email\n * @param email - Email to retrieve\n * @returns The user if found, undefined otherwise\n */\n public getUserByEmail(email: string): User | undefined {\n return this.users.find(u => u.email === email);\n }\n\n /**\n * Find user by username or email\n * @param identifier - Username or email to search for\n * @returns The user if found, undefined otherwise\n */\n public getUserByUsernameOrEmail(identifier: string): User | undefined {\n return this.users.find(u => u.username === identifier || u.email === identifier);\n }\n\n /**\n * Read all users\n * @returns Array of all users\n */\n public getAllUsers(): User[] {\n return [...this.users];\n }\n\n /**\n * Find users by a predicate function\n * @param predicate - Function to filter users\n * @returns Array of matching users\n */\n public findUsers(predicate: (user: User) => boolean): User[] {\n return this.users.filter(predicate);\n }\n\n /**\n * Update an existing user by username\n * @param username - Username of user to update\n * @param updates - Partial user object with fields to update\n * @returns The updated user\n */\n public updateUser(username: string, updates: Partial<User>): User {\n const userIndex = this.users.findIndex(u => u.username === username);\n if (userIndex === -1) {\n throw new Error(`User with username ${username} not found`);\n }\n\n const updatedUser = { ...this.users[userIndex], ...updates };\n this.users[userIndex] = updatedUser;\n this.hasChanged = true;\n logger.debug(`User updated: ${username}`);\n\n return updatedUser;\n }\n\n /**\n * Delete a user by username\n * @param username - Username of user to delete\n * @returns true if user was deleted, false if not found\n */\n public deleteUser(username: string): boolean {\n const initialLength = this.users.length;\n this.users = this.users.filter(u => u.username !== username);\n\n if (this.users.length < initialLength) {\n this.hasChanged = true;\n logger.debug(`User deleted: ${username}`);\n return true;\n }\n return false;\n }\n\n /**\n * Delete all users\n */\n public deleteAllUsers(): void {\n if (this.users.length > 0) {\n this.users = [];\n this.hasChanged = true;\n logger.debug('All users deleted');\n }\n }\n\n /**\n * Get the count of users\n * @returns Number of users in memory\n */\n public getUserCount(): number {\n return this.users.length;\n }\n\n /**\n * Check if a user exists\n * @param username - Username to check\n * @returns true if user exists, false otherwise\n */\n public userExists(username: string): boolean {\n return this.users.some(u => u.username === username);\n }\n\n /**\n * Add a WebSocket ID to a user's wsIds array\n * @param username - Username to update\n * @param wsId - WebSocket ID to add\n * @returns true if successful, false if user not found\n */\n public addWsId(username: string, wsId: string): boolean {\n const user = this.getUser(username);\n if (!user) {\n return false;\n }\n\n if(!user.wsIds || !Array.isArray(user.wsIds)) {\n user.wsIds = [];\n }\n\n if (!user.wsIds.includes(wsId)) {\n user.wsIds.push(wsId);\n // this.hasChanged = true;\n logger.debug(`WebSocket ID added to user ${username}: ${wsId}`);\n }\n\n return true;\n }\n\n /**\n * Remove a WebSocket ID from a user's wsIds array\n * @param username - Username to update\n * @param wsId - WebSocket ID to remove\n * @returns true if successful, false if user not found\n */\n public removeWsId(username: string, wsId: string): boolean {\n const user = this.getUser(username);\n if (!user) {\n return false;\n }\n\n if(!user.wsIds || !Array.isArray(user.wsIds)) {\n return false;\n }\n\n const initialLength = user.wsIds.length;\n user.wsIds = user.wsIds.filter(id => id !== wsId);\n\n if (user.wsIds.length < initialLength) {\n // this.hasChanged = true;\n logger.debug(`WebSocket ID removed from user ${username}: ${wsId}`);\n }\n\n return true;\n }\n\n /**\n * Get the change status\n * @returns true if there are unsaved changes, false otherwise\n */\n public hasUnsavedChanges(): boolean {\n return this.hasChanged;\n }\n\n /**\n * Cleanup resources and stop sync interval\n */\n public async destroy(): Promise<void> {\n this.stopSyncInterval();\n // Final sync before cleanup\n if (this.hasChanged) {\n await this.saveUsersToFile();\n }\n logger.info('UserManager destroyed');\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { logger } from '../utils/logger';\nimport { DSLRendererProps, DSLRendererPropsSchema } from './types';\n\n/**\n * DashboardManager class to handle CRUD operations on dashboards\n * All operations read/write directly to files (no in-memory caching)\n */\nexport class DashboardManager {\n private dashboardsBasePath: string;\n private projectId: string;\n\n /**\n * Initialize DashboardManager with project ID\n * @param projectId - Project ID to use in file path\n */\n constructor(projectId: string = 'snowflake-dataset') {\n this.projectId = projectId;\n this.dashboardsBasePath = path.join(\n os.homedir(),\n '.superatom',\n 'projects',\n projectId,\n 'dashboards'\n );\n }\n\n /**\n * Get the file path for a specific dashboard\n * @param dashboardId - Dashboard ID\n * @returns Full path to dashboard data.json file\n */\n private getDashboardPath(dashboardId: string): string {\n return path.join(this.dashboardsBasePath, dashboardId, 'data.json');\n }\n\n /**\n * Create a new dashboard\n * @param dashboardId - Unique dashboard ID\n * @param dashboard - Dashboard data\n * @returns Created dashboard with metadata\n */\n createDashboard(dashboardId: string, dashboard: DSLRendererProps): DSLRendererProps {\n const dashboardPath = this.getDashboardPath(dashboardId);\n const dashboardDir = path.dirname(dashboardPath);\n\n // Check if dashboard already exists\n if (fs.existsSync(dashboardPath)) {\n throw new Error(`Dashboard '${dashboardId}' already exists`);\n }\n\n // Validate dashboard structure\n const validated = DSLRendererPropsSchema.parse(dashboard);\n\n // Create directory structure\n fs.mkdirSync(dashboardDir, { recursive: true });\n\n // Write dashboard to file\n fs.writeFileSync(dashboardPath, JSON.stringify(validated, null, 4));\n\n logger.info(`Dashboard created: ${dashboardId}`);\n return validated;\n }\n\n /**\n * Get a specific dashboard by ID\n * @param dashboardId - Dashboard ID\n * @returns Dashboard data or null if not found\n */\n getDashboard(dashboardId: string): DSLRendererProps | null {\n const dashboardPath = this.getDashboardPath(dashboardId);\n\n if (!fs.existsSync(dashboardPath)) {\n logger.warn(`Dashboard not found: ${dashboardId}`);\n return null;\n }\n\n try {\n const fileContent = fs.readFileSync(dashboardPath, 'utf-8');\n const dashboard = JSON.parse(fileContent) as DSLRendererProps;\n\n // Validate structure\n const validated = DSLRendererPropsSchema.parse(dashboard);\n return validated;\n } catch (error) {\n logger.error(`Failed to read dashboard ${dashboardId}:`, error);\n return null;\n }\n }\n\n /**\n * Get all dashboards\n * @returns Array of dashboard objects with their IDs\n */\n getAllDashboards(): Array<{ dashboardId: string; dashboard: DSLRendererProps }> {\n // Create base directory if it doesn't exist\n if (!fs.existsSync(this.dashboardsBasePath)) {\n fs.mkdirSync(this.dashboardsBasePath, { recursive: true });\n return [];\n }\n\n const dashboards: Array<{ dashboardId: string; dashboard: DSLRendererProps }> = [];\n\n try {\n const dashboardDirs = fs.readdirSync(this.dashboardsBasePath);\n\n for (const dashboardId of dashboardDirs) {\n const dashboardPath = this.getDashboardPath(dashboardId);\n\n if (fs.existsSync(dashboardPath)) {\n const dashboard = this.getDashboard(dashboardId);\n if (dashboard) {\n dashboards.push({ dashboardId, dashboard });\n }\n }\n }\n\n logger.debug(`Retrieved ${dashboards.length} dashboards`);\n return dashboards;\n } catch (error) {\n logger.error('Failed to get all dashboards:', error);\n return [];\n }\n }\n\n /**\n * Update an existing dashboard\n * @param dashboardId - Dashboard ID\n * @param dashboard - Updated dashboard data\n * @returns Updated dashboard or null if not found\n */\n updateDashboard(dashboardId: string, dashboard: DSLRendererProps): DSLRendererProps | null {\n const dashboardPath = this.getDashboardPath(dashboardId);\n\n if (!fs.existsSync(dashboardPath)) {\n logger.warn(`Dashboard not found for update: ${dashboardId}`);\n return null;\n }\n\n try {\n // Validate dashboard structure\n const validated = DSLRendererPropsSchema.parse(dashboard);\n\n // Write updated dashboard to file\n fs.writeFileSync(dashboardPath, JSON.stringify(validated, null, 4));\n\n logger.info(`Dashboard updated: ${dashboardId}`);\n return validated;\n } catch (error) {\n logger.error(`Failed to update dashboard ${dashboardId}:`, error);\n throw error;\n }\n }\n\n /**\n * Delete a dashboard\n * @param dashboardId - Dashboard ID\n * @returns True if deleted, false if not found\n */\n deleteDashboard(dashboardId: string): boolean {\n const dashboardPath = this.getDashboardPath(dashboardId);\n const dashboardDir = path.dirname(dashboardPath);\n\n if (!fs.existsSync(dashboardPath)) {\n logger.warn(`Dashboard not found for deletion: ${dashboardId}`);\n return false;\n }\n\n try {\n // Delete the entire dashboard directory\n fs.rmSync(dashboardDir, { recursive: true, force: true });\n\n logger.info(`Dashboard deleted: ${dashboardId}`);\n return true;\n } catch (error) {\n logger.error(`Failed to delete dashboard ${dashboardId}:`, error);\n return false;\n }\n }\n\n /**\n * Check if a dashboard exists\n * @param dashboardId - Dashboard ID\n * @returns True if dashboard exists, false otherwise\n */\n dashboardExists(dashboardId: string): boolean {\n const dashboardPath = this.getDashboardPath(dashboardId);\n return fs.existsSync(dashboardPath);\n }\n\n /**\n * Get dashboard count\n * @returns Number of dashboards\n */\n getDashboardCount(): number {\n if (!fs.existsSync(this.dashboardsBasePath)) {\n return 0;\n }\n\n try {\n const dashboardDirs = fs.readdirSync(this.dashboardsBasePath);\n return dashboardDirs.filter((dir) => {\n const dashboardPath = this.getDashboardPath(dir);\n return fs.existsSync(dashboardPath);\n }).length;\n } catch (error) {\n logger.error('Failed to get dashboard count:', error);\n return 0;\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { logger } from '../utils/logger';\nimport { DSLRendererProps, DSLRendererPropsSchema } from './types';\n\n/**\n * ReportManager class to handle CRUD operations on reports\n * All operations read/write directly to files (no in-memory caching)\n */\nexport class ReportManager {\n private reportsBasePath: string;\n private projectId: string;\n\n /**\n * Initialize ReportManager with project ID\n * @param projectId - Project ID to use in file path\n */\n constructor(projectId: string = 'snowflake-dataset') {\n this.projectId = projectId;\n this.reportsBasePath = path.join(\n os.homedir(),\n '.superatom',\n 'projects',\n projectId,\n 'reports'\n );\n }\n\n /**\n * Get the file path for a specific report\n * @param reportId - Report ID\n * @returns Full path to report data.json file\n */\n private getReportPath(reportId: string): string {\n return path.join(this.reportsBasePath, reportId, 'data.json');\n }\n\n /**\n * Create a new report\n * @param reportId - Unique report ID\n * @param report - Report data\n * @returns Created report with metadata\n */\n createReport(reportId: string, report: DSLRendererProps): DSLRendererProps {\n const reportPath = this.getReportPath(reportId);\n const reportDir = path.dirname(reportPath);\n\n // Check if report already exists\n if (fs.existsSync(reportPath)) {\n throw new Error(`Report '${reportId}' already exists`);\n }\n\n // Validate report structure\n const validated = DSLRendererPropsSchema.parse(report);\n\n // Create directory structure\n fs.mkdirSync(reportDir, { recursive: true });\n\n // Write report to file\n fs.writeFileSync(reportPath, JSON.stringify(validated, null, 4));\n\n logger.info(`Report created: ${reportId}`);\n return validated;\n }\n\n /**\n * Get a specific report by ID\n * @param reportId - Report ID\n * @returns Report data or null if not found\n */\n getReport(reportId: string): DSLRendererProps | null {\n const reportPath = this.getReportPath(reportId);\n\n if (!fs.existsSync(reportPath)) {\n logger.warn(`Report not found: ${reportId}`);\n return null;\n }\n\n try {\n const fileContent = fs.readFileSync(reportPath, 'utf-8');\n const report = JSON.parse(fileContent) as DSLRendererProps;\n\n // Validate structure\n const validated = DSLRendererPropsSchema.parse(report);\n return validated;\n } catch (error) {\n logger.error(`Failed to read report ${reportId}:`, error);\n return null;\n }\n }\n\n /**\n * Get all reports\n * @returns Array of report objects with their IDs\n */\n getAllReports(): Array<{ reportId: string; report: DSLRendererProps }> {\n // Create base directory if it doesn't exist\n if (!fs.existsSync(this.reportsBasePath)) {\n fs.mkdirSync(this.reportsBasePath, { recursive: true });\n return [];\n }\n\n const reports: Array<{ reportId: string; report: DSLRendererProps }> = [];\n\n try {\n const reportDirs = fs.readdirSync(this.reportsBasePath);\n\n for (const reportId of reportDirs) {\n const reportPath = this.getReportPath(reportId);\n\n if (fs.existsSync(reportPath)) {\n const report = this.getReport(reportId);\n if (report) {\n reports.push({ reportId, report });\n }\n }\n }\n\n logger.debug(`Retrieved ${reports.length} reports`);\n return reports;\n } catch (error) {\n logger.error('Failed to get all reports:', error);\n return [];\n }\n }\n\n /**\n * Update an existing report\n * @param reportId - Report ID\n * @param report - Updated report data\n * @returns Updated report or null if not found\n */\n updateReport(reportId: string, report: DSLRendererProps): DSLRendererProps | null {\n const reportPath = this.getReportPath(reportId);\n\n if (!fs.existsSync(reportPath)) {\n logger.warn(`Report not found for update: ${reportId}`);\n return null;\n }\n\n try {\n // Validate report structure\n const validated = DSLRendererPropsSchema.parse(report);\n\n // Write updated report to file\n fs.writeFileSync(reportPath, JSON.stringify(validated, null, 4));\n\n logger.info(`Report updated: ${reportId}`);\n return validated;\n } catch (error) {\n logger.error(`Failed to update report ${reportId}:`, error);\n throw error;\n }\n }\n\n /**\n * Delete a report\n * @param reportId - Report ID\n * @returns True if deleted, false if not found\n */\n deleteReport(reportId: string): boolean {\n const reportPath = this.getReportPath(reportId);\n const reportDir = path.dirname(reportPath);\n\n if (!fs.existsSync(reportPath)) {\n logger.warn(`Report not found for deletion: ${reportId}`);\n return false;\n }\n\n try {\n // Delete the entire report directory\n fs.rmSync(reportDir, { recursive: true, force: true });\n\n logger.info(`Report deleted: ${reportId}`);\n return true;\n } catch (error) {\n logger.error(`Failed to delete report ${reportId}:`, error);\n return false;\n }\n }\n\n /**\n * Check if a report exists\n * @param reportId - Report ID\n * @returns True if report exists, false otherwise\n */\n reportExists(reportId: string): boolean {\n const reportPath = this.getReportPath(reportId);\n return fs.existsSync(reportPath);\n }\n\n /**\n * Get report count\n * @returns Number of reports\n */\n getReportCount(): number {\n if (!fs.existsSync(this.reportsBasePath)) {\n return 0;\n }\n\n try {\n const reportDirs = fs.readdirSync(this.reportsBasePath);\n return reportDirs.filter((dir) => {\n const reportPath = this.getReportPath(dir);\n return fs.existsSync(reportPath);\n }).length;\n } catch (error) {\n logger.error('Failed to get report count:', error);\n return 0;\n }\n }\n}\n","import { ThreadManager } from '../threads';\nimport { logger } from '../utils/logger';\nimport { STORAGE_CONFIG } from '../config/storage';\n\n/**\n * CleanupService handles cleanup of old threads and UIBlocks\n * to prevent memory bloat and maintain optimal performance\n */\nexport class CleanupService {\n private static instance: CleanupService;\n private cleanupInterval: NodeJS.Timeout | null = null;\n\n private constructor() {}\n\n /**\n * Get singleton instance of CleanupService\n */\n static getInstance(): CleanupService {\n if (!CleanupService.instance) {\n CleanupService.instance = new CleanupService();\n }\n return CleanupService.instance;\n }\n\n /**\n * Clean up old threads based on retention period\n * @param retentionDays - Number of days to keep threads (defaults to config)\n * @returns Number of threads deleted\n */\n cleanupOldThreads(retentionDays: number = STORAGE_CONFIG.THREAD_RETENTION_DAYS): number {\n const threadManager = ThreadManager.getInstance();\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\n\n const threads = threadManager.getAllThreads();\n let deletedCount = 0;\n\n for (const thread of threads) {\n if (thread.getCreatedAt() < cutoffDate) {\n const threadId = thread.getId();\n if (threadManager.deleteThread(threadId)) {\n deletedCount++;\n logger.info(`Deleted old thread: ${threadId} (created: ${thread.getCreatedAt().toISOString()})`);\n }\n }\n }\n\n if (deletedCount > 0) {\n logger.info(`Cleanup: Deleted ${deletedCount} old threads (older than ${retentionDays} days)`);\n }\n\n return deletedCount;\n }\n\n /**\n * Clean up old UIBlocks within threads based on retention period\n * @param retentionDays - Number of days to keep UIBlocks (defaults to config)\n * @returns Object with number of UIBlocks deleted per thread\n */\n cleanupOldUIBlocks(retentionDays: number = STORAGE_CONFIG.UIBLOCK_RETENTION_DAYS): { [threadId: string]: number } {\n const threadManager = ThreadManager.getInstance();\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\n\n const threads = threadManager.getAllThreads();\n const deletionStats: { [threadId: string]: number } = {};\n\n for (const thread of threads) {\n const uiblocks = thread.getUIBlocks();\n let deletedInThread = 0;\n\n for (const uiblock of uiblocks) {\n if (uiblock.getCreatedAt() < cutoffDate) {\n if (thread.removeUIBlock(uiblock.getId())) {\n deletedInThread++;\n }\n }\n }\n\n if (deletedInThread > 0) {\n deletionStats[thread.getId()] = deletedInThread;\n logger.info(\n `Deleted ${deletedInThread} old UIBlocks from thread ${thread.getId()} (older than ${retentionDays} days)`\n );\n }\n }\n\n const totalDeleted = Object.values(deletionStats).reduce((sum, count) => sum + count, 0);\n if (totalDeleted > 0) {\n logger.info(`Cleanup: Deleted ${totalDeleted} old UIBlocks across ${Object.keys(deletionStats).length} threads`);\n }\n\n return deletionStats;\n }\n\n /**\n * Clear all component data from UIBlocks to free memory\n * Keeps metadata but removes the actual data\n * @param retentionDays - Number of days to keep full data (defaults to config)\n * @returns Number of UIBlocks whose data was cleared\n */\n clearOldUIBlockData(retentionDays: number = STORAGE_CONFIG.UIBLOCK_RETENTION_DAYS): number {\n const threadManager = ThreadManager.getInstance();\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\n\n const threads = threadManager.getAllThreads();\n let clearedCount = 0;\n\n for (const thread of threads) {\n const uiblocks = thread.getUIBlocks();\n\n for (const uiblock of uiblocks) {\n if (uiblock.getCreatedAt() < cutoffDate) {\n const componentData = uiblock.getComponentData();\n\n // Only clear if data exists\n if (componentData && Object.keys(componentData).length > 0) {\n // Keep metadata but clear actual data\n const metadata = {\n dataCleared: true,\n clearedAt: new Date().toISOString(),\n originalDataInfo: {\n totalRows: componentData.totalRows,\n storedRows: componentData.storedRows,\n isTruncated: componentData.isTruncated,\n },\n };\n\n uiblock.setComponentData({ ...metadata, data: null });\n clearedCount++;\n }\n }\n }\n }\n\n if (clearedCount > 0) {\n logger.info(`Cleanup: Cleared data from ${clearedCount} old UIBlocks (older than ${retentionDays} days)`);\n }\n\n return clearedCount;\n }\n\n /**\n * Run full cleanup (threads, UIBlocks, and data)\n * @returns Cleanup statistics\n */\n runFullCleanup(): {\n threadsDeleted: number;\n uiblocksDeleted: { [threadId: string]: number };\n dataCleared: number;\n } {\n logger.info('Starting full cleanup...');\n\n const stats = {\n threadsDeleted: this.cleanupOldThreads(),\n uiblocksDeleted: this.cleanupOldUIBlocks(),\n dataCleared: this.clearOldUIBlockData(),\n };\n\n const totalUIBlocksDeleted = Object.values(stats.uiblocksDeleted).reduce((sum, count) => sum + count, 0);\n\n logger.info(\n `Full cleanup completed: ${stats.threadsDeleted} threads, ${totalUIBlocksDeleted} UIBlocks deleted, ${stats.dataCleared} UIBlock data cleared`\n );\n\n return stats;\n }\n\n /**\n * Start automatic cleanup at regular intervals\n * @param intervalHours - Hours between cleanup runs (default: 24)\n */\n startAutoCleanup(intervalHours: number = 24): void {\n if (this.cleanupInterval) {\n logger.warn('Auto cleanup is already running');\n\n //stop this and run with new interval\n\n \n return;\n }\n\n const intervalMs = intervalHours * 60 * 60 * 1000;\n\n // Run initial cleanup\n this.runFullCleanup();\n\n // Schedule recurring cleanup\n this.cleanupInterval = setInterval(() => {\n this.runFullCleanup();\n }, intervalMs);\n\n logger.info(`Auto cleanup started: running every ${intervalHours} hours`);\n }\n\n /**\n * Stop automatic cleanup\n */\n stopAutoCleanup(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n logger.info('Auto cleanup stopped');\n }\n }\n\n /**\n * Check if auto cleanup is running\n */\n isAutoCleanupRunning(): boolean {\n return this.cleanupInterval !== null;\n }\n\n /**\n * Get current memory usage statistics\n */\n getMemoryStats(): {\n threadCount: number;\n totalUIBlocks: number;\n avgUIBlocksPerThread: number;\n } {\n const threadManager = ThreadManager.getInstance();\n const threads = threadManager.getAllThreads();\n const threadCount = threads.length;\n\n let totalUIBlocks = 0;\n for (const thread of threads) {\n totalUIBlocks += thread.getUIBlockCount();\n }\n\n return {\n threadCount,\n totalUIBlocks,\n avgUIBlocksPerThread: threadCount > 0 ? totalUIBlocks / threadCount : 0,\n };\n }\n}\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAmMR,MAAM;AAAA;AAAA,MAEP;AAAA,MAEA,yBAAyB;AAAA,QACxB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAkYR,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQP;AAAA,MAEA,WAAW;AAAA,QACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWR,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["fs","import_fs","path","fs","WebSocket","import_zod","import_zod","ExpressionSchema","BindingSchema","ForDirectiveSchema","QuerySpecSchema","UIElementSchema","UIComponentSchema","DSLRendererPropsSchema","DSLRendererPropsSchema","size","import_crypto","result","fs","import_crypto","crypto","sendDataResponse","sendDataResponse","import_path","import_fs","path","fs","schema","import_fs","import_path","path","fs","import_fs","import_path","path","fs","Anthropic","Groq","result","OpenAI","b","ensureQueryLimit","result","elapsedTime","dotenv","import_dotenv","dotenv","import_dotenv","dotenv","import_dotenv","dotenv","import_dotenv","dotenv","LOG_LEVEL_PRIORITY","MESSAGE_LEVEL_PRIORITY","sendDataResponse","sendResponse","sendResponse","sanitizedUsers","sanitizedUser","sendResponse","dashboardManager","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","handleQuery","sendResponse","reportManager","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","handleQuery","sendResponse","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","handleQuery","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","handleQuery","sendResponse","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","sendResponse","import_fs","import_path","path","os","fs","import_fs","import_path","import_os","path","os","fs","import_fs","import_path","import_os","path","os","fs","DSLRendererPropsSchema"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts","../src/userResponse/prompts.ts","../src/userResponse/prompt-loader.ts","../src/userResponse/utils.ts","../src/index.ts","../src/websocket.ts","../src/types.ts","../src/dashboards/types.ts","../src/reports/types.ts","../src/handlers/data-request.ts","../src/threads/uiblock.ts","../src/config/storage.ts","../src/threads/thread.ts","../src/threads/thread-manager.ts","../src/bundle.ts","../src/handlers/bundle-request.ts","../src/auth/utils.ts","../src/auth/user-storage.ts","../src/auth/validator.ts","../src/handlers/auth-login-requests.ts","../src/handlers/auth-verify-request.ts","../src/userResponse/groq.ts","../src/userResponse/base-llm.ts","../src/userResponse/schema.ts","../src/llm.ts","../src/utils/llm-usage-logger.ts","../src/utils/user-prompt-error-logger.ts","../src/userResponse/knowledge-base.ts","../src/userResponse/conversation-search.ts","../src/utils/bm25l-reranker.ts","../src/userResponse/anthropic.ts","../src/userResponse/gemini.ts","../src/userResponse/openai.ts","../src/userResponse/index.ts","../src/handlers/user-prompt-request.ts","../src/utils/log-collector.ts","../src/utils/conversation-saver.ts","../src/config/context.ts","../src/handlers/user-prompt-suggestions.ts","../src/userResponse/next-questions.ts","../src/handlers/actions-request.ts","../src/handlers/components-list-response.ts","../src/handlers/users.ts","../src/dashboards/dashboard-storage.ts","../src/handlers/dashboards.ts","../src/reports/report-storage.ts","../src/handlers/reports.ts","../src/handlers/uis.ts","../src/handlers/bookmarks.ts","../src/handlers/kb-nodes.ts","../src/handlers/dash-comp-request.ts","../src/auth/user-manager.ts","../src/dashboards/dashboard-manager.ts","../src/reports/report-manager.ts","../src/services/cleanup-service.ts"],"sourcesContent":["import fs from 'fs';\nconst PREFIX = '[SuperatomSDK]';\n\n/**\n * Log levels in hierarchical order\n * - errors: only error logs\n * - warnings: warning + error logs\n * - info: info + warning + error logs\n * - verbose: all logs including debug\n */\nexport type LogLevel = 'errors' | 'warnings' | 'info' | 'verbose';\n\n// open a file in stream write mode. if no file is specified then create it.\nconst LOGSTREAM = fs.createWriteStream('superatom-sdk.log', { flags: 'a' });\n\n/**\n * Internal log level hierarchy mapping\n */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n errors: 0,\n warnings: 1,\n info: 2,\n verbose: 3,\n};\n\nconst MESSAGE_LEVEL_PRIORITY: Record<'error' | 'warn' | 'info' | 'debug', number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\n/**\n * Logger class with environment-based log level support\n */\nclass Logger {\n private currentLevel: LogLevel;\n private currentLevelPriority: number;\n\n constructor() {\n // Read log level from environment variable, default to 'info'\n const envLevel = (process.env.SUPERATOM_LOG_LEVEL || 'info').toLowerCase();\n\n // Validate and set log level\n if (this.isValidLogLevel(envLevel)) {\n this.currentLevel = envLevel as LogLevel;\n } else {\n this.currentLevel = 'info';\n console.warn(\n `${PREFIX} Invalid log level \"${envLevel}\". Using default \"info\". Valid levels: errors, warnings, info, verbose`\n );\n }\n\n this.currentLevelPriority = LOG_LEVEL_PRIORITY[this.currentLevel];\n }\n\n /**\n * Check if a string is a valid log level\n */\n private isValidLogLevel(level: string): level is LogLevel {\n return level === 'errors' || level === 'warnings' || level === 'info' || level === 'verbose';\n }\n\n /**\n * Check if a message should be logged based on current log level\n */\n private shouldLog(messageLevel: 'error' | 'warn' | 'info' | 'debug'): boolean {\n const messagePriority = MESSAGE_LEVEL_PRIORITY[messageLevel];\n return messagePriority <= this.currentLevelPriority;\n }\n\n /**\n * Get current log level\n */\n getLogLevel(): LogLevel {\n return this.currentLevel;\n }\n\n /**\n * Set log level programmatically\n */\n setLogLevel(level: LogLevel): void {\n this.currentLevel = level;\n this.currentLevelPriority = LOG_LEVEL_PRIORITY[level];\n }\n\n /**\n * Log info message (shown for info and verbose levels)\n */\n info(...args: any[]): void {\n if (this.shouldLog('info')) {\n console.log(PREFIX, ...args);\n }\n }\n\n /**\n * Log error message (shown for all levels)\n */\n error(...args: any[]): void {\n if (this.shouldLog('error')) {\n console.error(PREFIX, ...args);\n }\n }\n\n /**\n * Log warning message (shown for warnings, info, and verbose levels)\n */\n warn(...args: any[]): void {\n if (this.shouldLog('warn')) {\n console.warn(PREFIX, ...args);\n }\n }\n\n /**\n * Log debug message (only shown for verbose level)\n */\n debug(...args: any[]): void {\n if (this.shouldLog('debug')) {\n console.log(PREFIX, '[DEBUG]', ...args);\n }\n }\n\n file(...args: any[]): void {\n LOGSTREAM.write(args.join(' ') + '\\n');\n }\n}\n\n// Export singleton instance\nexport const logger = new Logger();\n","/**\n * Hardcoded prompt templates\n * These prompts are embedded in the SDK to avoid file system dependencies\n */\n\nexport interface PromptTemplate {\n\tsystem: string;\n\tuser: string;\n}\n\nexport const PROMPTS: Record<string, PromptTemplate> = {\n\n\t'text-response': {\n\t\tsystem: `You are an intelligent AI assistant that provides helpful, accurate, and contextual text responses to user questions. You have access to a database and can execute SQL queries and external tools to answer user requests.\n\n## Your Task\n\nAnalyze the user's question and provide a helpful text response. Your response should:\n\n1. **Be Clear and Concise**: Provide direct answers without unnecessary verbosity\n2. **Be Contextual**: Use conversation history to understand what the user is asking about\n3. **Be Accurate**: Provide factually correct information based on the context\n4. **Be Helpful**: Offer additional relevant information or suggestions when appropriate\n\n## Available Tools\n\nThe following external tools are available for this request (if applicable):\n\n{{AVAILABLE_EXTERNAL_TOOLS}}\n\nWhen a tool is needed to complete the user's request:\n1. **Analyze the request** to determine which tool(s) are needed\n2. **Extract parameters** from the user's question that the tool requires\n3. **Execute the tool** by calling it with the extracted parameters\n4. **Present the results** in your response in a clear, user-friendly format\n5. **Combine with other data** if the user's request requires both database queries and external tool results\n\n## Handling Data Questions\n\nWhen the user asks about data\n\n1. **Generate a SQL query** using the database schema provided above\n2. **Use the execute_query tool** to run the query\n3. **If the query fails**, analyze the error and generate a corrected query\n4. **Format the results** in a clear, readable way for the user\n\n**Query Guidelines:**\n- Use correct table and column names from the schema\n- ALWAYS include a LIMIT clause with a MAXIMUM of 32 rows\n- Ensure valid SQL syntax\n- For time-based queries, use appropriate date functions\n- When using subqueries with scalar operators (=, <, >, etc.), add LIMIT 1 to prevent \"more than one row\" errors\n\n## Database Schema\n{{SCHEMA_DOC}}\n\n**Database Type: PostgreSQL**\n\n**CRITICAL PostgreSQL Query Rules:**\n\n1. **NO AGGREGATE FUNCTIONS IN WHERE CLAUSE** - This is a fundamental SQL error\n ❌ WRONG: \\`WHERE COUNT(orders) > 0\\`\n ❌ WRONG: \\`WHERE SUM(price) > 100\\`\n ❌ WRONG: \\`WHERE AVG(rating) > 4.5\\`\n ❌ WRONG: \\`WHERE FLOOR(AVG(rating)) = 4\\` (aggregate inside any function is still not allowed)\n ❌ WRONG: \\`WHERE ROUND(SUM(price), 2) > 100\\`\n\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\n ✅ CORRECT: Move aggregate logic to HAVING: \\`GROUP BY ... HAVING FLOOR(AVG(rating)) = 4\\`\n ✅ CORRECT: Use subquery for filtering: \\`WHERE product_id IN (SELECT product_id FROM ... GROUP BY ... HAVING AVG(rating) >= 4)\\`\n\n2. **WHERE vs HAVING**\n - WHERE filters rows BEFORE grouping (cannot use aggregates)\n - HAVING filters groups AFTER grouping (can use aggregates)\n - If using HAVING, you MUST have GROUP BY\n\n3. **NO NESTED AGGREGATE FUNCTIONS** - PostgreSQL does NOT allow aggregates inside aggregates\n ❌ WRONG: \\`AVG(ROUND(AVG(column), 2))\\` or \\`SELECT AVG(SUM(price)) FROM ...\\`\n ✅ CORRECT: \\`ROUND(AVG(column), 2)\\`\n\n4. **GROUP BY Requirements**\n - ALL non-aggregated columns in SELECT must be in GROUP BY\n - If you SELECT a column and don't aggregate it, add it to GROUP BY\n\n5. **LIMIT Clause**\n - ALWAYS include LIMIT (max 32 rows)\n - For scalar subqueries in WHERE/HAVING, add LIMIT 1\n\n6. **String Escaping** - PostgreSQL uses double single-quotes, NOT backslash\n ❌ WRONG: \\`'Children\\\\'s furniture'\\`\n ✅ CORRECT: \\`'Children''s furniture'\\`\n\n7. **Always Use Table Aliases for Column References** - Prevent ambiguous column errors\n ❌ WRONG: \\`SELECT product_id FROM products p JOIN product_variants pv ON p.product_id = pv.product_id\\`\n ✅ CORRECT: \\`SELECT p.product_id FROM products p JOIN product_variants pv ON p.product_id = pv.product_id\\`\n - Always prefix columns with table alias (e.g., \\`p.product_id\\`, \\`c.name\\`)\n - Especially critical in subqueries and joins where multiple tables share column names\n\n\n## Response Guidelines\n\n- If the question is about viewing data, use the execute_query tool to fetch data and present it\n- If the question is about creating/updating/deleting data:\n 1. Acknowledge that the system supports this via forms\n 2. **CRITICAL:** Use the database schema to determine which fields are required based on \\`nullable\\` property\n 3. **CRITICAL:** If the form will have select fields for foreign keys, you MUST fetch the options data using execute_query\n 4. **CRITICAL FOR UPDATE/DELETE OPERATIONS:** If it's an update/edit/modify/delete question:\n - **NEVER update ID/primary key columns** (e.g., order_id, customer_id, product_id) - these are immutable identifiers\n - You MUST first fetch the CURRENT values of the record using a SELECT query\n - Identify the record (from user's question - e.g., \"update order 123\" or \"delete order 123\" means order_id = 123)\n - Execute: \\`SELECT * FROM table_name WHERE id = <value> LIMIT 1\\`\n - Present the current values in your response (e.g., \"Current order status: Pending, payment method: Credit Card\")\n - For DELETE: These values will be shown in a disabled form as confirmation before deletion\n - For UPDATE: These values will populate as default values for editing\n 5. Present the options data in your response (e.g., \"Available categories: Furniture (id: 1), Kitchen (id: 2), Decor (id: 3)\")\n 6. The form component will be generated automatically using this data\n- If the question is general knowledge, provide a helpful conversational response\n- If asking for clarification, provide options or ask specific follow-up questions\n- If you don't have enough information, acknowledge it and ask for more details\n- Keep responses focused and avoid going off-topic\n\n**Example for data modification with foreign keys:**\nUser: \"I want to create a new product\"\nYou should:\n1. Execute query: \\`SELECT category_id, name FROM categories LIMIT 32\\`\n2. Execute query: \\`SELECT store_id, name FROM stores LIMIT 32\\`\n3. Present: \"I can help you create a new product. Available categories: Furniture (id: 1), Kitchen (id: 2)... Available stores: Store A (id: 10), Store B (id: 20)...\"\n4. Suggest Form component\n\n## Component Suggestions\n\nAfter analyzing the user's question, you MUST suggest appropriate dashboard components. Use this format:\n\n<DashboardComponents>\n**Dashboard Components:**\nFormat: \\`{number}.{component_type} : {clear reasoning}\\`\n\n\n**Rules for component suggestions:**\n1. If a conclusive answer can be provided based on user question, suggest that as the first component.\n2. ALways suggest context/supporting components that will give the user more information and allow them to explore further.\n3. If the question includes a time range, also explore time-based components for past time ranges.\n4. **For data viewing/analysis questions**: Suggest visualization components (KPICard, BarChart, LineChart, PieChart, DataTable, etc.).\n5. **For data modification questions** (create/add/update/delete):\n - Always suggest 1-2 context components first to provide relevant information (prefer KPICard for showing key metrics)\n - Then suggest \\`Form\\` component for the actual modification\n - Example: \"1.KPICard : Show current order total and status\" then \"2.Form : To update order details\"\n6. Analyze the query results structure and data type\n7. Each component suggestion must be on a new line\n</DashboardComponents>\n\nIMPORTANT:\n- Always wrap component suggestions with <DashboardComponents> tags\n- For data viewing: Include at least one component suggestion when data is returned\n- For data modifications: Always suggest 1-2 context components before Form (e.g., \"1.KPICard : Show current order value\" then \"2.Form : To update order status\")\n\n## Output Format\n\nRespond with plain text that includes:\n\n1. **Query Analysis** (if applicable): Brief explanation of what data was fetched\n2. **Results Summary**: Present the data in a clear, readable format\n3. **Dashboard Components**: List suggested components wrapped in <DashboardComponents> tags\n\n\n**CRITICAL:**\n- Return ONLY plain text (no JSON, no markdown code blocks)\n\n\nYou have access to a database and can execute SQL queries to answer data-related questions. For data modifications, the system provides form-based interfaces.\n\n\n## External Tool Results\n\nThe following external tools were executed for this request (if applicable):\n\n{{EXTERNAL_TOOL_CONTEXT}}\n\nUse this external tool data to:\n- Provide information from external sources (emails, calendar, etc.)\n- Present the data in a user-friendly format\n- Combine external data with database queries when relevant\n- Reference specific results in your response\n\n**Note:** If external tools were not needed, this section will indicate \"No external tools were used for this request.\"\n\n\n## Knowledge Base Context\n\nThe following relevant information has been retrieved from the knowledge base for this question:\n\n{{KNOWLEDGE_BASE_CONTEXT}}\n\nUse this knowledge base information to:\n- Provide more accurate and informed responses\n- Reference specific facts, concepts, or domain knowledge\n- Enhance your understanding of the user's question\n- Give context-aware recommendations\n\n**Note:** If there is previous conversation history, use it to understand context and provide coherent responses:\n- Reference previous questions and answers when relevant\n- Maintain consistency with earlier responses\n- Use the history to resolve ambiguous references like \"that\", \"it\", \"them\", \"the previous data\"\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n`,\n\t\tuser: `{{USER_PROMPT}}\n`\n\t},\n\n\t'match-text-components': {\n\t\tsystem: `You are a component matching expert that creates beautiful, well-structured dashboard visualizations from analysis results.\n\n## Your Task\n\nYou will receive a text response containing:\n1. Query execution results (with \"✅ Query executed successfully!\" markers)\n2. Data analysis and insights\n3. **Dashboard Components:** suggestions (1:component_type : reasoning format)\n\nYour job is to:\n1. **FIRST: Generate a direct answer component** (if the user question can be answered with a single visualization)\n - Determine the BEST visualization type (KPICard, BarChart, DataTable, PieChart, LineChart, etc.) to directly answer the user's question\n - Select the matching component from the available components list\n - Generate complete props for this component (query, title, description, config)\n - This component will be placed in the \\`answerComponent\\` field\n - This component will be streamed to the frontend IMMEDIATELY for instant user feedback\n - **CRITICAL**: Generate this FIRST in your JSON response\n\n2. **THEN: Parse ALL dashboard component suggestions** from the text response (format: 1:component_type : reasoning)\n3. **Match EACH suggestion with an actual component** from the available list\n4. **CRITICAL**: \\`matchedComponents\\` must include **ALL** dashboard components suggested in the text, INCLUDING the component you used as \\`answerComponent\\`\n - The answerComponent is shown first for quick feedback, but the full dashboard shows everything\n5. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched\n6. **Generate title and description** for the dashboard container\n7. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis\n\n**CRITICAL GOAL**: Create dashboard components that display the **same data that was already analyzed** - NOT new data. The queries already ran and got results. You're just creating different visualizations of those results.\n\n## Available Components\n\n{{AVAILABLE_COMPONENTS}}\n\n## Component Matching Rules\nFor each component suggestion (c1, c2, c3, etc.) from the text response:\n\n1. **Match by type**: Find components whose \\`type\\` matches the suggested component type\n2. **Refine by relevance**: If multiple components match, choose based on:\n - Description and keywords matching the use case\n - Best fit for the data being visualized\n3. **Fallback**: If no exact type match, find the closest alternative\n\n## Dashboard Container\nAll matched components will be placed in the default **MultiComponentContainer** layout. Your job is to:\n1. **Generate a clear title** for the dashboard that summarizes what it shows\n2. **Generate a brief description** explaining the dashboard's purpose and scope\n\n## Props Generation Rules\n\nFor each matched component, generate complete props:\n\n### 1. Query - When to Reuse vs Generate\n\n**Option A: REUSE the successful query** (preferred when possible)\n- Look for \"✅ Query executed successfully!\" in the text response\n- Extract the exact SQL query that worked\n- Use this SAME query for components that visualize the same data differently\n\n**Option B: GENERATE a new query** (when necessary)\n- Only generate new queries when you need DIFFERENT data\n- For SELECT queries: Use the database schema below to write valid SQL\n- For mutations (INSERT/UPDATE/DELETE): Only if matching a Form component, generate mutation query with $fieldName placeholders\n\n\n**Decision Logic:**\n- Different aggregation needed → Generate new query ✅\n- Same data, different view → Reuse query ✅\n\n**Database Schema:**\n{{SCHEMA_DOC}}\n\n**Database Type: PostgreSQL**\n\n**CRITICAL PostgreSQL Query Rules**\n\n1. **NO AGGREGATE FUNCTIONS IN WHERE CLAUSE** - This is a fundamental SQL error\n ❌ WRONG: \\`WHERE COUNT(orders) > 0\\`\n ❌ WRONG: \\`WHERE SUM(price) > 100\\`\n ❌ WRONG: \\`WHERE AVG(rating) > 4.5\\`\n ❌ WRONG: \\`WHERE FLOOR(AVG(rating)) = 4\\` (aggregate inside any function is still not allowed)\n ❌ WRONG: \\`WHERE ROUND(SUM(price), 2) > 100\\`\n\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\n ✅ CORRECT: Move aggregate logic to HAVING: \\`GROUP BY ... HAVING FLOOR(AVG(rating)) = 4\\`\n ✅ CORRECT: Use subquery for filtering: \\`WHERE product_id IN (SELECT product_id FROM ... GROUP BY ... HAVING AVG(rating) >= 4)\\`\n\n2. **NO NESTED AGGREGATE FUNCTIONS** - PostgreSQL does NOT allow aggregates inside aggregates\n ❌ WRONG: \\`AVG(ROUND(AVG(column), 2))\\`\n ✅ CORRECT: \\`ROUND(AVG(column), 2)\\`\n\n3. **Aggregate Functions Can Only Appear Once Per Level**\n ❌ WRONG: \\`SELECT AVG(SUM(price)) FROM ...\\` (nested)\n ✅ CORRECT: Use subquery: \\`SELECT AVG(total) FROM (SELECT SUM(price) as total FROM ... GROUP BY ...) subq\\`\n\n4. **WHERE vs HAVING**\n - WHERE filters rows BEFORE grouping (cannot use aggregates)\n - HAVING filters groups AFTER grouping (can use aggregates)\n - Use WHERE for column comparisons: \\`WHERE price > 100\\`\n - Use HAVING for aggregate comparisons: \\`HAVING COUNT(*) > 5\\`\n\n5. **GROUP BY Requirements**\n - ALL non-aggregated columns in SELECT must be in GROUP BY\n - Use proper column references (table.column or aliases)\n - If using HAVING, you MUST have GROUP BY\n\n6. **LIMIT Clause**\n - ALWAYS include LIMIT clause (max 32 rows for dashboard queries)\n - For scalar subqueries in WHERE/HAVING, add LIMIT 1\n\n7. **Scalar Subqueries**\n - Subqueries used with =, <, >, etc. must return single value\n - Always add LIMIT 1 to scalar subqueries\n\n8. **String Escaping** - PostgreSQL uses double single-quotes, NOT backslash\n ❌ WRONG: \\`'Children\\\\'s furniture'\\`\n ✅ CORRECT: \\`'Children''s furniture'\\`\n\n9. **Always Use Table Aliases for Column References** - Prevent ambiguous column errors\n ❌ WRONG: \\`SELECT product_id FROM products p JOIN product_variants pv ON p.product_id = pv.product_id\\`\n ✅ CORRECT: \\`SELECT p.product_id FROM products p JOIN product_variants pv ON p.product_id = pv.product_id\\`\n - Always prefix columns with table alias (e.g., \\`p.product_id\\`, \\`c.name\\`)\n - Especially critical in subqueries and joins where multiple tables share column names\n\n**Query Generation Guidelines** (when creating new queries):\n- Use correct table and column names from the schema above\n- ALWAYS include LIMIT clause (max 32 rows)\n\n### 2. Title\n- Create a clear, descriptive title\n- Should explain what the component shows\n- Use context from the original question\n\n### 3. Description\n- Brief explanation of what this component displays\n- Why it's useful for this data\n\n### 4. Config (for visualization components)\n- **CRITICAL**: Look at the component's \"Props Structure\" to see what config fields it expects\n- Map query result columns to the appropriate config fields\n- Keep other existing config properties that don't need to change\n- Ensure config field values match actual column names from the query\n\n**Special Rules for Bar Charts**\n- \\`xAxisKey\\` = ALWAYS the category/label column (text field )\n- \\`yAxisKey\\` = ALWAYS the numeric value column (number field )\n- \\`orientation\\` = \"vertical\" or \"horizontal\" (controls visual direction only)\n- **DO NOT swap xAxisKey/yAxisKey based on orientation** - they always represent category and value respectively\n\n### 5. Additional Props (match according to component type)\n- **CRITICAL**: Look at the matched component's \"Props Structure\" in the available components list\n- Generate props that match EXACTLY what the component expects\n\n**For Form components (type: \"Form\"):**\n\nProps structure:\n- **query**: \\`{ sql: \"INSERT/UPDATE/DELETE query with $fieldName placeholders\", params: [] }\\`\n - **For UPDATE queries**: Check the database schema - if the table has an \\`updated_at\\` or \\`last_updated\\` column, always include it in the SET clause with \\`CURRENT_TIMESTAMP\\` (e.g., \\`UPDATE table_name SET field = $field, updated_at = CURRENT_TIMESTAMP WHERE id = value\\`)\n- **title**: \"Update Order 5000\", \"Create New Product\", or \"Delete Order 5000\"\n- **description**: What the form does\n- **submitButtonText**: Button text (default: \"Submit\"). For delete: \"Delete\", \"Confirm Delete\"\n- **submitButtonColor**: \"primary\" (blue) or \"danger\" (red). Use \"danger\" for DELETE operations\n- **successMessage**: Success message (default: \"Form submitted successfully!\"). For delete: \"Record deleted successfully!\"\n- **disableFields**: Set \\`true\\` for DELETE operations to show current values but prevent editing\n- **fields**: Array of field objects (structure below)\n\n**Field object:**\n\\`\\`\\`json\n{\n \"name\": \"field_name\", // Matches $field_name in SQL query\n \"description\": \"Field Label\",\n \"type\": \"text|number|email|date|select|multiselect|checkbox|textarea\",\n \"required\": true, // Set based on schema: nullable=false → required=true, nullable=true → required=false\n \"defaultValue\": \"current_value\", // For UPDATE: extract from text response\n \"placeholder\": \"hint text\",\n \"options\": [...], // For select/multiselect\n \"validation\": {\n \"minLength\": { \"value\": 5, \"message\": \"...\" },\n \"maxLength\": { \"value\": 100, \"message\": \"...\" },\n \"min\": { \"value\": 18, \"message\": \"...\" },\n \"max\": { \"value\": 120, \"message\": \"...\" },\n \"pattern\": { \"value\": \"regex\", \"message\": \"...\" }\n }\n}\n\\`\\`\\`\n\n**CRITICAL - Set required based on database schema:**\n- Check the column's \\`nullable\\` property in the database schema\n- If \\`nullable: false\\` → set \\`required: true\\` (field is mandatory)\n- If \\`nullable: true\\` → set \\`required: false\\` (field is optional)\n- Never set fields as required if the schema allows NULL\n\n**Default Values for UPDATE:**\n- **NEVER include ID/primary key fields in UPDATE forms** (e.g., order_id, customer_id, product_id) - these cannot be changed\n- Detect UPDATE by checking if SQL contains \"UPDATE\" keyword\n- Extract current values from text response (look for \"Current values:\" or SELECT results)\n- Set \\`defaultValue\\` for each field with the extracted current value\n\n**CRITICAL - Single field with current value pre-selected:**\nFor UPDATE operations, use ONE field with defaultValue set to current value (not two separate fields).\n\n✅ CORRECT - Single field, current value pre-selected:\n\\`\\`\\`json\n{\n \"name\": \"category_id\",\n \"type\": \"select\",\n \"defaultValue\": 5,\n \"options\": [{\"id\": 1, \"name\": \"Kitchen\"}, {\"id\": 5, \"name\": \"Furniture\"}, {\"id\": 7, \"name\": \"Decor\"}]\n}\n\\`\\`\\`\nUser sees dropdown with \"Furniture\" selected, can change to any other category.\n\n❌ WRONG - Two separate fields:\n\\`\\`\\`json\n[\n {\"name\": \"current_category\", \"type\": \"text\", \"defaultValue\": \"Furniture\", \"disabled\": true},\n {\"name\": \"new_category\", \"type\": \"select\", \"options\": [...]}\n]\n\\`\\`\\`\n\n**Options Format:**\n- **Enum/status fields** (non-foreign keys): String array \\`[\"Pending\", \"Shipped\", \"Delivered\"]\\`\n- **Foreign keys** (reference tables): Object array \\`[{\"id\": 1, \"name\": \"Furniture\"}, {\"id\": 2, \"name\": \"Kitchen\"}]\\`\n- Extract from text response queries and match format to field type\n\n**Example UPDATE form field:**\n\\`\\`\\`json\n{\n \"name\": \"status\",\n \"description\": \"Order Status\",\n \"type\": \"select\",\n \"required\": true,\n \"defaultValue\": \"Pending\", // Current value from database\n \"options\": [\"Pending\", \"Processing\", \"Shipped\", \"Delivered\"]\n}\n\\`\\`\\`\n\n**Example DELETE form props:**\n\\`\\`\\`json\n{\n \"query\": { \"sql\": \"DELETE FROM orders WHERE order_id = 123\", \"params\": [] },\n \"title\": \"Delete Order 123\",\n \"description\": \"Are you sure you want to delete this order?\",\n \"submitButtonText\": \"Confirm Delete\",\n \"submitButtonColor\": \"danger\",\n \"successMessage\": \"Order deleted successfully!\",\n \"disableFields\": true,\n \"fields\": [\n { \"name\": \"order_id\", \"description\": \"Order ID\", \"type\": \"text\", \"defaultValue\": \"123\" },\n { \"name\": \"status\", \"description\": \"Status\", \"type\": \"text\", \"defaultValue\": \"Pending\" }\n ]\n}\n\\`\\`\\`\n\n**For visualization components (Charts, Tables, KPIs):**\n- **query**: String (SQL SELECT query)\n- **title**, **description**, **config**: As per component's props structure\n- Do NOT include fields array\n\n## Follow-Up Questions (Actions) Generation\n\nAfter analyzing the text response and matched components, generate 4-5 intelligent follow-up questions that the user might naturally ask next. These questions should:\n\n1. **Build upon the data analysis** shown in the text response and components\n2. **Explore natural next steps** in the data exploration journey\n3. **Be progressively more detailed or specific** - go deeper into the analysis\n4. **Consider the insights revealed** - suggest questions that help users understand implications\n5. **Be phrased naturally** as if a real user would ask them\n6. **Vary in scope** - include both broad trends and specific details\n7. **Avoid redundancy** - don't ask questions already answered in the text response\n\n\n## Output Format\n\nYou MUST respond with ONLY a valid JSON object (no markdown, no code blocks):\n\n**IMPORTANT JSON FORMATTING RULES:**\n- Put SQL queries on a SINGLE LINE (no newlines in the query string)\n- Escape all quotes in SQL properly (use \\\\\" for quotes inside strings)\n- Remove any newlines, tabs, or special characters from SQL\n- Do NOT use markdown code blocks (no \\`\\`\\`)\n- Return ONLY the JSON object, nothing else\n\n**Example 1: With answer component** (when user question can be answered with single visualization)\n\\`\\`\\`json\n{\n \"hasAnswerComponent\": true,\n \"answerComponent\": {\n \"componentId\": \"id_from_available_list\",\n \"componentName\": \"name_of_component\",\n \"componentType\": \"type_of_component (can be KPICard, BarChart, LineChart, PieChart, DataTable, etc.)\",\n \"reasoning\": \"Why this visualization type best answers the user's question\",\n \"props\": {\n \"query\": \"SQL query for this component\",\n \"title\": \"Component title that directly answers the user's question\",\n \"description\": \"Component description\",\n \"config\": {\n \"field1\": \"value1\",\n \"field2\": \"value2\"\n }\n }\n },\n \"layoutTitle\": \"Clear, concise title for the overall dashboard/layout (5-10 words)\",\n \"layoutDescription\": \"Brief description of what the dashboard shows and its purpose (1-2 sentences)\",\n \"matchedComponents\": [\n {\n \"componentId\": \"id_from_available_list\",\n \"componentName\": \"name_of_component\",\n \"componentType\": \"type_of_component\",\n \"reasoning\": \"Why this component was selected for the dashboard\",\n \"originalSuggestion\": \"c1:table : original reasoning from text\",\n \"props\": {\n \"query\": \"SQL query for this component\",\n \"title\": \"Component title\",\n \"description\": \"Component description\",\n \"config\": {\n \"field1\": \"value1\",\n \"field2\": \"value2\"\n }\n }\n }\n ],\n \"actions\": [\n \"Follow-up question 1?\",\n \"Follow-up question 2?\",\n \"Follow-up question 3?\",\n \"Follow-up question 4?\",\n \"Follow-up question 5?\"\n ]\n}\n\\`\\`\\`\n\n**Example 2: Without answer component** (when user question needs multiple visualizations or dashboard)\n\\`\\`\\`json\n{\n \"hasAnswerComponent\": false,\n \"answerComponent\": null,\n \"layoutTitle\": \"Clear, concise title for the overall dashboard/layout (5-10 words)\",\n \"layoutDescription\": \"Brief description of what the dashboard shows and its purpose (1-2 sentences)\",\n \"matchedComponents\": [\n {\n \"componentId\": \"id_from_available_list\",\n \"componentName\": \"name_of_component\",\n \"componentType\": \"type_of_component\",\n \"reasoning\": \"Why this component was selected for the dashboard\",\n \"originalSuggestion\": \"c1:chart : original reasoning from text\",\n \"props\": {\n \"query\": \"SQL query for this component\",\n \"title\": \"Component title\",\n \"description\": \"Component description\",\n \"config\": {\n \"field1\": \"value1\",\n \"field2\": \"value2\"\n }\n }\n }\n ],\n \"actions\": [\n \"Follow-up question 1?\",\n \"Follow-up question 2?\",\n \"Follow-up question 3?\",\n \"Follow-up question 4?\",\n \"Follow-up question 5?\"\n ]\n}\n\\`\\`\\`\n\n**CRITICAL:**\n- **\\`hasAnswerComponent\\` determines if an answer component exists**\n - Set to \\`true\\` if the user question can be answered with a single visualization\n - Set to \\`false\\` if the user question can not be answered with single visualisation and needs multiple visualizations or a dashboard overview\n- **If \\`hasAnswerComponent\\` is \\`true\\`:**\n - \\`answerComponent\\` MUST be generated FIRST in the JSON before \\`layoutTitle\\`\n - Generate complete props (query, title, description, config)\n- **If \\`hasAnswerComponent\\` is \\`false\\`:**\n - Set \\`answerComponent\\` to \\`null\\`\n- **\\`matchedComponents\\` MUST include ALL dashboard components from the text analysis**\n - **CRITICAL**: Even if you used a component as \\`answerComponent\\`, you MUST STILL include it in \\`matchedComponents\\`\n - The count of matchedComponents should EQUAL the count of dashboard suggestions in the text (e.g., if text has 4 suggestions, matchedComponents should have 4 items)\n - Do NOT skip the answerComponent from matchedComponents\n- \\`matchedComponents\\` come from the dashboard component suggestions in the text response\n- \\`layoutTitle\\` MUST be a clear, concise title (5-10 words) that summarizes what the entire dashboard shows\n- \\`layoutDescription\\` MUST be a brief description (1-2 sentences) explaining the purpose and scope of the dashboard\n - Should describe what insights the dashboard provides and what data it shows\n- \\`actions\\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis\n- Return ONLY valid JSON (no markdown code blocks, no text before/after)\n- Generate complete props for each component\n`,\n\t\tuser: `## Analysis Content\n\n{{ANALYSIS_CONTENT}}\n\n---\n\nMatch the component suggestions from the text response above with available components, and generate proper props for each matched component.\n`\n\t},\n\n\t'actions': {\n\t\tsystem: `You are an expert data analyst. Your task is to suggest intelligent follow-up questions based on the conversation history and the current data visualization. The questions should help users explore the data more deeply and make better insights.\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n**Context Instructions:**\n- Review the entire conversation history to understand the user's journey and interests\n- Suggest questions that naturally progress from previous explorations\n- Avoid suggesting questions about topics already covered in the conversation\n- Build upon insights from previous components to suggest deeper analysis\n- Consider what the user might want to explore next based on their question pattern`,\n\t\tuser: `Given the following context:\n\nLatest User Question: {{ORIGINAL_USER_PROMPT}}\n\nCurrent Component:\n{{COMPONENT_INFO}}\n\n{{COMPONENT_DATA}}\n\nGenerate a JSON array of 4-5 intelligent follow-up questions that the user might naturally ask next. These questions should:\n1. Build upon the conversation history and insights shown in the current component\n2. NOT repeat questions or topics already covered in the conversation history\n3. Explore natural next steps in the data exploration journey\n4. Be progressively more detailed or specific\n5. Consider the user's apparent interests based on their question pattern\n6. Be phrased naturally as if a real user would ask them\n\nFormat your response as a JSON object with this structure:\n{\n \"nextQuestions\": [\n \"Question 1?\",\n \"Question 2?\",\n ...\n ]\n}\n\nReturn ONLY valid JSON.`\n\t},\n\n\t'category-classification': {\n\t\tsystem: `You are an expert AI that categorizes user questions into specific action categories and identifies required tools/resources.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\n## Available External Tools\n\n{{AVAILABLE_TOOLS}}\n\n---\n\nYour task is to analyze the user's question and determine:\n\n1. **Question Category:**\n - \"data_analysis\": Questions about analyzing, querying, reading, or visualizing data from the database (SELECT operations)\n - \"data_modification\": Questions about creating, updating, deleting, or modifying data in the database (INSERT, UPDATE, DELETE operations)\n\n2. **External Tools Required** (for both categories):\n From the available tools listed above, identify which ones are needed to support the user's request:\n - Match the tool names/descriptions to what the user is asking for\n - Extract specific parameters mentioned in the user's question\n\n3. **Tool Parameters** (if tools are identified):\n Extract specific parameters the user mentioned:\n - For each identified tool, extract relevant parameters (email, recipient, content, etc.)\n - Only include parameters the user explicitly or implicitly mentioned\n\n**Important Guidelines:**\n- If user mentions any of the available external tools → identify those tools and extract their parameters\n- If user asks to \"send\", \"schedule\", \"create event\", \"message\" → check if available tools match\n- If user asks to \"show\", \"analyze\", \"compare\", \"calculate\" data → \"data_analysis\"\n- If user asks to modify/create/update/delete data → \"data_modification\"\n- Always identify tools from the available tools list (not from generic descriptions)\n- Be precise in identifying tool types and required parameters\n- Only include tools that are explicitly mentioned or clearly needed\n\n**Output Format:**\n\\`\\`\\`json\n{\n \"category\": \"data_analysis\" | \"data_modification\",\n \"reasoning\": \"Brief explanation of why this category was chosen\",\n \"externalTools\": [\n {\n \"type\": \"tool_id_from_available_tools\",\n \"name\": \"Tool Display Name\",\n \"description\": \"What this tool will do\",\n \"parameters\": {\n \"param1\": \"extracted value\",\n \"param2\": \"extracted value\"\n }\n }\n ],\n \"dataAnalysisType\": \"visualization\" | \"calculation\" | \"comparison\" | \"trend\" | null,\n \"confidence\": 0-100\n}\n\\`\\`\\`\n\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}`,\n\t\tuser: `{{USER_PROMPT}}`\n\t},\n\n\t'adapt-ui-block-params': {\n\t\tsystem: `You are an expert AI that adapts and modifies UI block component parameters based on the user's current question.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\n## Database Schema Reference\n\n{{SCHEMA_DOC}}\n\nUse this schema to understand available tables, columns, and relationships when modifying SQL queries. Ensure all table and column names you use in adapted queries are valid according to this schema.\n\n## Context\nYou are given:\n1. A previous UI Block response (with component and its props) that matched the user's current question with >90% semantic similarity\n2. The user's current question\n3. The component that needs parameter adaptation\n\nYour task is to:\n1. **Analyze the difference** between the original question (from the matched UIBlock) and the current user question\n2. **Identify what parameters need to change** in the component props to answer the current question\n3. **Modify the props** to match the current request while keeping the same component type(s)\n4. **Preserve component structure** - only change props, not the components themselves\n\n## Component Structure Handling\n\n### For Single Components:\n- Modify props directly (config, actions, query, filters, etc.)\n\n### For MultiComponentContainer:\nThe component will have structure:\n\\`\\`\\`json\n{\n \"type\": \"Container\",\n \"name\": \"MultiComponentContainer\",\n \"props\": {\n \"config\": {\n \"components\": [...], // Array of nested components - ADAPT EACH ONE\n \"title\": \"...\", // Container title - UPDATE based on new question\n \"description\": \"...\" // Container description - UPDATE based on new question\n },\n \"actions\": [...] // ADAPT actions if needed\n }\n}\n\\`\\`\\`\n\nWhen adapting MultiComponentContainer:\n- Update the container-level \\`title\\` and \\`description\\` to reflect the new user question\n- For each component in \\`config.components\\`:\n - Identify what data it shows and how the new question changes what's needed\n - Adapt its query parameters (WHERE clauses, LIMIT, ORDER BY, filters, date ranges)\n - Update its title/description to match the new context\n - Update its config settings (colors, sorting, grouping, metrics)\n- Update \\`actions\\` if the new question requires different actions\n\n## Important Guidelines:\n- Keep the same component type (don't change KPICard to LineChart)\n- Keep the same number of components in the container\n- For each nested component, update:\n - Query WHERE clauses, LIMIT, ORDER BY, filters, date ranges, metrics\n - Title and description to reflect the new question\n - Config settings like colors, sorting, grouping if needed\n- Maintain each component's core purpose while answering the new question\n- If query modification is needed, ensure all table/column names remain valid\n- CRITICAL: Ensure JSON is valid and complete for all nested structures\n\n\n## Output Format:\n\n### For Single Component:\n\\`\\`\\`json\n{\n \"success\": true,\n \"adaptedComponent\": {\n \"id\": \"original_component_id\",\n \"name\": \"component_name\",\n \"type\": \"component_type\",\n \"description\": \"updated_description\",\n \"props\": {\n \"config\": { },\n \"actions\": [],\n }\n },\n \"parametersChanged\": [\n {\n \"field\": \"query\",\n \"reason\": \"Added Q4 date filter\"\n },\n {\n \"field\": \"title\",\n \"reason\": \"Updated to reflect Q4 focus\"\n }\n ],\n \"explanation\": \"How the component was adapted to answer the new question\"\n}\n\\`\\`\\`\n\n### For MultiComponentContainer:\n\\`\\`\\`json\n{\n \"success\": true,\n \"adaptedComponent\": {\n \"id\": \"original_container_id\",\n \"name\": \"MultiComponentContainer\",\n \"type\": \"Container\",\n \"description\": \"updated_container_description\",\n \"props\": {\n \"config\": {\n \"title\": \"Updated dashboard title based on new question\",\n \"description\": \"Updated description reflecting new question context\",\n \"components\": [\n {\n \"id\": \"component_1_id\",\n \"name\": \"component_1_name\",\n \"type\": \"component_1_type\",\n \"description\": \"updated description for this specific component\",\n \"props\": {\n \"query\": \"Modified SQL query with updated WHERE/LIMIT/ORDER BY\",\n \"config\": { \"metric\": \"updated_metric\", \"filters\": {...} }\n }\n },\n {\n \"id\": \"component_2_id\",\n \"name\": \"component_2_name\",\n \"type\": \"component_2_type\",\n \"description\": \"updated description for this component\",\n \"props\": {\n \"query\": \"Modified SQL query for this component\",\n \"config\": { \"metric\": \"updated_metric\", \"filters\": {...} }\n }\n }\n ]\n },\n \"actions\": []\n }\n },\n \"parametersChanged\": [\n {\n \"field\": \"container.title\",\n \"reason\": \"Updated to reflect new dashboard focus\"\n },\n {\n \"field\": \"components[0].query\",\n \"reason\": \"Modified WHERE clause for new metrics\"\n },\n {\n \"field\": \"components[1].config.metric\",\n \"reason\": \"Changed metric from X to Y based on new question\"\n }\n ],\n \"explanation\": \"Detailed explanation of how each component was adapted\"\n}\n\\`\\`\\`\n\nIf adaptation is not possible or would fundamentally change the component:\n\\`\\`\\`json\n{\n \"success\": false,\n \"reason\": \"Cannot adapt component - the new question requires a different visualization type\",\n \"explanation\": \"The original component shows KPI cards but the new question needs a trend chart\"\n}\n\\`\\`\\``,\n\t\tuser: `## Previous Matched UIBlock\n\n**Original Question:** {{ORIGINAL_USER_PROMPT}}\n\n**Matched UIBlock Component:**\n\\`\\`\\`json\n{{MATCHED_UI_BLOCK_COMPONENT}}\n\\`\\`\\`\n\n**Component Properties:**\n\\`\\`\\`json\n{{COMPONENT_PROPS}}\n\\`\\`\\`\n\n## Current User Question\n{{CURRENT_USER_PROMPT}}\n\n---\n\n## Adaptation Instructions\n\n1. **Analyze the difference** between the original question and the current question\n2. **Identify what data needs to change**:\n - For single components: adapt the query/config/actions\n - For MultiComponentContainer: adapt the container title/description AND each nested component's parameters\n\n3. **Modify the parameters**:\n - **Container level** (if MultiComponentContainer):\n - Update \\`title\\` and \\`description\\` to reflect the new user question\n - Update \\`actions\\` if needed\n\n - **For each component** (single or nested in container):\n - Identify what it shows (sales, revenue, inventory, etc.)\n - Adapt SQL queries: modify WHERE clauses, LIMIT, ORDER BY, filters, date ranges\n - Update component title and description\n - Update config settings (metrics, colors, sorting, grouping)\n\n4. **Preserve structure**: Keep the same number and type of components\n\n5. **Return complete JSON** with all adapted properties for all components`\n\t},\n\n\t'dash-comp-picker': {\n\t\tsystem: `You are a component selection expert that picks the best dashboard component and generates complete props based on user requests.\n\n## Your Task\n\nAnalyze the user's request and:\n1. **Select the most appropriate component** from the available components list\n2. **Determine the data source**: Database query OR External tool (ERP)\n3. **Generate complete props** for the selected component including the data retrieval/modification method\n\n## Component Selection Rules\n\n1. **Match by Intent**: Understand what the user wants to display/achieve\n2. **Match by Type**: Choose the component type that best fits the data visualization or action need\n3. **Match by Description**: Use component descriptions and keywords to find the best fit\n\n## Data Source Decision\n\n### Use DATABASE when:\n- User asks about data that exists in the database schema (customers, orders, products, etc.)\n- Questions about internal business data (sales, inventory, users, transactions)\n- CRUD operations on database tables\n\n### Use EXTERNAL TOOL when:\n- User mentions specific external systems (ERP, CRM, email, calendar, etc.)\n- Data not available in database schema\n- Actions that require external integrations (send email, create calendar event, sync with ERP)\n- Tool description matches the user's request\n\n## Props Generation Rules\n\n**CRITICAL**: Look at each component's \"Props Structure\" in the available components list. Generate ALL props that the component expects.\n\n### For Data Viewing Components (charts, tables, KPIs):\n\n**Option A: Database Query** (when data is in database)\n\\`\\`\\`json\n{\n \"query\": {\n \"sql\": \"SELECT column1, column2 FROM table WHERE condition = $param LIMIT 32\",\n \"params\": { \"param\": \"value\" }\n }\n}\n\\`\\`\\`\n\n**Option B: External Tool** (when data is from ERP/external system)\n\\`\\`\\`json\n{\n \"externalTool\": {\n \"toolId\": \"tool_id_from_list\",\n \"toolName\": \"Tool Display Name\",\n \"action\": \"get\",\n \"params\": {\n \"param1\": \"value1\",\n \"param2\": \"value2\"\n }\n }\n}\n\\`\\`\\`\n\n### For Data Modification Components (forms):\n\n**Option A: Database Mutation**\n\\`\\`\\`json\n{\n \"query\": {\n \"sql\": \"INSERT INTO table (col1, col2) VALUES ($col1, $col2)\",\n \"params\": {}\n },\n \"fields\": [\n { \"name\": \"col1\", \"type\": \"text\", \"required\": true },\n { \"name\": \"col2\", \"type\": \"number\", \"required\": false }\n ]\n}\n\\`\\`\\`\n\n**Option B: External Tool Mutation**\n\\`\\`\\`json\n{\n \"externalTool\": {\n \"toolId\": \"tool_id_from_list\",\n \"toolName\": \"Tool Display Name\",\n \"action\": \"create|update|delete\",\n \"params\": {\n \"param1\": \"value_or_placeholder\"\n }\n },\n \"fields\": [\n { \"name\": \"param1\", \"type\": \"text\", \"required\": true }\n ]\n}\n\\`\\`\\`\n\n### Database Query Rules\n{{DATABASE_RULES}}\n\n## Output Format\n\nYou MUST respond with ONLY a valid JSON object (no markdown, no code blocks):\n\n{\n \"componentId\": \"id_from_available_list\",\n \"componentName\": \"name_of_component\",\n \"componentType\": \"type_of_component\",\n \"dataSourceType\": \"database\" | \"external_tool\",\n \"operationType\": \"view\" | \"create\" | \"update\" | \"delete\",\n \"reasoning\": \"Why this component was selected and why this data source\",\n \"props\": {\n // Generate ALL props based on the component's Props Structure\n // Include either \"query\" OR \"externalTool\" based on data source\n // Include all other required props (title, description, config, fields, etc.)\n }\n}\n\n**CRITICAL:**\n- Return ONLY valid JSON (no markdown code blocks, no text before/after)\n- \\`componentId\\` MUST match an ID from the available components list\n- \\`dataSourceType\\` indicates whether data comes from database or external tool\n- \\`operationType\\` indicates the type of operation (view/create/update/delete)\n- Generate COMPLETE props based on the component's \"Props Structure\"\n- For queries, ALWAYS use \\`$paramName\\` placeholders and include \\`params\\` object\n- For external tools, \\`toolId\\` MUST match an ID from the available tools list\n\n---\n\n## CONTEXT (for this specific request)\n\n### Database Schema\n{{SCHEMA_DOC}}\n\n### Available External Tools\n{{AVAILABLE_TOOLS}}\n\n### Available Components\n{{AVAILABLE_COMPONENTS}}`,\n\t\tuser: `{{USER_PROMPT}}`\n\t}\n};\n","import fs from 'fs';\nimport path from 'path';\nimport { logger } from '../utils/logger';\nimport { PROMPTS } from './prompts';\n\nexport interface PromptLoaderConfig {\n\tpromptsDir?: string;\n}\n\ninterface CachedPromptTemplate {\n\tsystem: string;\n\tuser: string;\n}\n\n/**\n * PromptLoader class for loading and processing prompt templates\n * Tries to load from file system first, then falls back to hardcoded prompts\n */\nexport class PromptLoader {\n\tprivate promptsDir: string;\n\tprivate promptCache: Map<string, CachedPromptTemplate> = new Map();\n\tprivate databaseRulesCache: Map<string, string> = new Map();\n\tprivate isInitialized: boolean = false;\n\tprivate databaseType: string = 'postgresql';\n\n\tconstructor(config?: PromptLoaderConfig) {\n\t\tlogger.debug('Initializing PromptLoader...');\n\t\t// Default to backend's .prompts directory (where the SDK is being used)\n\t\tthis.promptsDir = config?.promptsDir || path.join(process.cwd(), '.prompts');\n\t\tlogger.debug(`Prompts directory set to: ${this.promptsDir}`);\n\t}\n\n\t/**\n\t * Load a prompt template from file system OR fallback to hardcoded prompts\n\t * @param promptName - Name of the prompt folder\n\t * @returns Template with system and user prompts\n\t */\n\tprivate loadPromptTemplate(promptName: string): CachedPromptTemplate {\n\t\t// First, try to load from file system (backend's .prompts directory)\n\t\ttry {\n\t\t\tconst systemPath = path.join(this.promptsDir, promptName, 'system.md');\n\t\t\tconst userPath = path.join(this.promptsDir, promptName, 'user.md');\n\n\t\t\tif (fs.existsSync(systemPath) && fs.existsSync(userPath)) {\n\t\t\t\tconst system = fs.readFileSync(systemPath, 'utf-8');\n\t\t\t\tconst user = fs.readFileSync(userPath, 'utf-8');\n\t\t\t\tlogger.info(`✓ Loaded prompt '${promptName}' from file system: ${this.promptsDir}`);\n\t\t\t\treturn { system, user };\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Ignore file system errors and try fallback\n\t\t\tlogger.error(`Could not load '${promptName}' from file system, trying fallback...`);\n\t\t}\n\n\t\t// Fallback to hardcoded prompts\n\t\tconst hardcodedPrompt = PROMPTS[promptName];\n\t\tif (hardcodedPrompt) {\n\t\t\tlogger.info(`✓ Loaded prompt '${promptName}' from hardcoded fallback`);\n\t\t\treturn hardcodedPrompt;\n\t\t}\n\n\t\tthrow new Error(`Prompt template '${promptName}' not found in either ${this.promptsDir} or hardcoded prompts. Available prompts: ${Object.keys(PROMPTS).join(', ')}`);\n\t}\n\n\t/**\n\t * Initialize and cache all prompts into memory\n\t * Tries file system first, then falls back to hardcoded prompts\n\t */\n\tasync initialize(): Promise<void> {\n\t\tif (this.isInitialized) {\n\t\t\tlogger.debug('PromptLoader already initialized, skipping...');\n\t\t\treturn;\n\t\t}\n\n\t\tlogger.info('Loading prompts into memory...');\n\n\t\tconst promptTypes = Object.keys(PROMPTS);\n\n\t\tfor (const promptName of promptTypes) {\n\t\t\ttry {\n\t\t\t\tconst template = this.loadPromptTemplate(promptName);\n\t\t\t\tthis.promptCache.set(promptName, template);\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(`Failed to load prompt '${promptName}':`, error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tthis.isInitialized = true;\n\t\tlogger.info(`Successfully loaded ${this.promptCache.size} prompt templates into memory`);\n\t}\n\n\t/**\n\t * Replace variables in a template string using {{VARIABLE_NAME}} pattern\n\t * @param template - Template string with placeholders\n\t * @param variables - Variables to replace in the template\n\t * @returns Processed string\n\t */\n\tprivate replaceVariables(\n\t\ttemplate: string,\n\t\tvariables: Record<string, string | number | boolean | any[]>\n\t): string {\n\t\tlet content = template;\n\n\t\t// Replace all variables matching {{VARIABLE_NAME}} pattern\n\t\tfor (const [key, value] of Object.entries(variables)) {\n\t\t\tconst pattern = new RegExp(`{{${key}}}`, 'g');\n\t\t\tconst replacementValue = typeof value === 'string' ? value : JSON.stringify(value);\n\t\t\tcontent = content.replace(pattern, replacementValue);\n\t\t}\n\n\t\treturn content;\n\t}\n\n\t/**\n\t * Load both system and user prompts from cache and replace variables\n\t * Supports prompt caching by splitting static and dynamic content\n\t * @param promptName - Name of the prompt\n\t * @param variables - Variables to replace in the templates\n\t * @returns Object containing both system and user prompts (system can be string or array for caching)\n\t */\n\tasync loadPrompts(\n\t\tpromptName: string,\n\t\tvariables: Record<string, string | number | boolean | any[]>\n\t): Promise<{ system: string | any[]; user: string }> {\n\t\tif (!this.isInitialized) {\n\t\t\tlogger.warn('PromptLoader not initialized, initializing now...');\n\t\t\tawait this.initialize();\n\t\t}\n\n\t\tconst template = this.promptCache.get(promptName);\n\n\t\tif (!template) {\n\t\t\tthrow new Error(`Prompt template '${promptName}' not found in cache. Available prompts: ${Array.from(this.promptCache.keys()).join(', ')}`);\n\t\t}\n\n\t\t// Check if the prompt has a context section marker (for caching)\n\t\tconst contextMarker = '---\\n\\n## CONTEXT';\n\n\t\tif (template.system.includes(contextMarker)) {\n\t\t\t// Split into static (cacheable) and dynamic (context) sections\n\t\t\tconst [staticPart, contextPart] = template.system.split(contextMarker);\n\n\t\t\t// Replace variables in BOTH parts\n\t\t\t// Static part may contain schema/rules which are per-project but stable\n\t\t\tconst processedStatic = this.replaceVariables(staticPart, variables);\n\t\t\tconst processedContext = this.replaceVariables(contextMarker + contextPart, variables);\n\n\t\t\tconst staticLength = processedStatic.length;\n\t\t\tconst contextLength = processedContext.length;\n\n\t\t\tlogger.debug(`✓ Prompt caching enabled for '${promptName}' (cached: ${staticLength} chars, dynamic: ${contextLength} chars)`);\n\n\t\t\t// Return as array of blocks for Anthropic caching\n\t\t\t// The static part (with schema) will be cached after first request\n\t\t\treturn {\n\t\t\t\tsystem: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: processedStatic.trim(),\n\t\t\t\t\t\tcache_control: { type: 'ephemeral' }\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: processedContext.trim()\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tuser: this.replaceVariables(template.user, variables)\n\t\t\t};\n\t\t}\n\n\t\t// Fallback: No caching, return as simple string\n\t\treturn {\n\t\t\tsystem: this.replaceVariables(template.system, variables),\n\t\t\tuser: this.replaceVariables(template.user, variables)\n\t\t};\n\t}\n\n\t/**\n\t * DEPRECATED: Use loadPrompts instead\n\t * Load a single prompt file and replace variables using {{VARIABLE_NAME}} pattern\n\t */\n\tasync loadPrompt(\n\t\tpromptName: string,\n\t\tpromptType: 'system' | 'user',\n\t\tvariables: Record<string, string | number | boolean | any[]>\n\t): Promise<string | any[]> {\n\t\tconst prompts = await this.loadPrompts(promptName, variables);\n\t\treturn promptType === 'system' ? prompts.system : prompts.user;\n\t}\n\n\t/**\n\t * Set custom prompts directory (requires re-initialization)\n\t * @param dir - Path to the prompts directory\n\t */\n\tsetPromptsDir(dir: string): void {\n\t\tthis.promptsDir = dir;\n\t\tthis.isInitialized = false;\n\t\tthis.promptCache.clear();\n\t\tlogger.debug(`Prompts directory changed to: ${dir}`);\n\t}\n\n\t/**\n\t * Get current prompts directory\n\t * @returns Path to the prompts directory\n\t */\n\tgetPromptsDir(): string {\n\t\treturn this.promptsDir;\n\t}\n\n\t/**\n\t * Check if prompts are loaded in memory\n\t */\n\tisReady(): boolean {\n\t\treturn this.isInitialized;\n\t}\n\n\t/**\n\t * Get the number of cached prompts\n\t */\n\tgetCacheSize(): number {\n\t\treturn this.promptCache.size;\n\t}\n\n\t/**\n\t * Set the database type for SQL rules loading\n\t * @param type - Database type ('postgresql' | 'mssql')\n\t */\n\tsetDatabaseType(type: string): void {\n\t\tthis.databaseType = type;\n\t\tthis.databaseRulesCache.clear();\n\t\tlogger.debug(`Database type set to: ${type}`);\n\t}\n\n\t/**\n\t * Get current database type\n\t * @returns Database type string\n\t */\n\tgetDatabaseType(): string {\n\t\treturn this.databaseType;\n\t}\n\n\t/**\n\t * Load database-specific SQL rules from file system\n\t * Falls back to minimal default rules if file not found\n\t * @returns Database rules as a string\n\t */\n\tasync loadDatabaseRules(): Promise<string> {\n\t\t// Check cache first\n\t\tif (this.databaseRulesCache.has(this.databaseType)) {\n\t\t\tlogger.debug(`✓ Database rules for '${this.databaseType}' loaded from cache`);\n\t\t\treturn this.databaseRulesCache.get(this.databaseType)!;\n\t\t}\n\n\t\t// Try loading from file system\n\t\tconst rulesPath = path.join(this.promptsDir, 'database-rules', `${this.databaseType}.md`);\n\n\t\ttry {\n\t\t\tif (fs.existsSync(rulesPath)) {\n\t\t\t\tconst rules = fs.readFileSync(rulesPath, 'utf-8');\n\t\t\t\tthis.databaseRulesCache.set(this.databaseType, rules);\n\t\t\t\tlogger.info(`✓ Loaded database rules for '${this.databaseType}' from ${rulesPath}`);\n\t\t\t\treturn rules;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tlogger.warn(`Could not load database rules for '${this.databaseType}' from file system: ${error}`);\n\t\t}\n\n\t\t// Fallback to default rules\n\t\tconst defaultRules = this.getDefaultDatabaseRules();\n\t\tthis.databaseRulesCache.set(this.databaseType, defaultRules);\n\t\tlogger.warn(`Using default database rules for '${this.databaseType}' (file not found at ${rulesPath})`);\n\t\treturn defaultRules;\n\t}\n\n\t/**\n\t * Get default database rules as fallback\n\t * @returns Minimal database rules\n\t */\n\tprivate getDefaultDatabaseRules(): string {\n\t\tif (this.databaseType === 'mssql') {\n\t\t\treturn `**Database Type: Microsoft SQL Server**\n\n**SQL Query Rules:**\n- Use \\`TOP N\\` for row limiting (e.g., \\`SELECT TOP 32 * FROM table\\`)\n- Use \\`1\\` for true, \\`0\\` for false (no native boolean)\n- Use \\`+\\` or \\`CONCAT()\\` for string concatenation\n- Use \\`GETDATE()\\` for current timestamp\n- Use \\`CAST()\\` or \\`CONVERT()\\` for type casting\n- Use \\`OUTPUT INSERTED.*\\` instead of \\`RETURNING\\`\n- NULL values: Use \\`NULL\\` keyword without quotes`;\n\t\t}\n\n\t\t// Default to PostgreSQL\n\t\treturn `**Database Type: PostgreSQL**\n\n**SQL Query Rules:**\n- Use \\`LIMIT N\\` for row limiting (e.g., \\`SELECT * FROM table LIMIT 32\\`)\n- Use \\`true\\` / \\`false\\` for boolean values\n- Use \\`||\\` for string concatenation\n- Use \\`NOW()\\` for current timestamp\n- Use \\`::TYPE\\` or \\`CAST()\\` for type casting\n- Use \\`RETURNING\\` clause for mutations\n- NULL values: Use \\`NULL\\` keyword without quotes`;\n\t}\n}\n\n// Export a singleton instance\n// Default to backend's .prompts directory (where the SDK is being used)\n// If prompts are not found there, the loader will fallback to hardcoded prompts\nconst defaultPromptsPath = process.env.PROMPTS_DIR || path.join(process.cwd(), '.prompts');\n\nexport const promptLoader = new PromptLoader({\n\tpromptsDir: defaultPromptsPath\n});\n","import type { Action } from '../threads/action';\nimport type { DatabaseType } from '../types';\nimport { promptLoader } from './prompt-loader';\n\nexport type { DatabaseType };\n\n/**\n * Gets the current database type from the prompt loader\n * @returns The database type string\n */\nexport function getDatabaseType(): DatabaseType {\n\treturn promptLoader.getDatabaseType() as DatabaseType;\n}\n\n/**\n * Converts LIMIT syntax to TOP syntax for MSSQL\n * MSSQL doesn't support LIMIT keyword - it must use TOP\n * @param query - The SQL query to check\n * @param limit - The limit value to use\n * @returns The query with LIMIT converted to TOP\n */\nexport function convertLimitToTop(query: string, limit: number): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Remove LIMIT clause and add TOP after SELECT\n\tlet modifiedQuery = query.replace(/\\s*\\bLIMIT\\s+\\d+\\b/gi, '').trim();\n\n\t// Add TOP N after SELECT (handles SELECT DISTINCT as well)\n\tmodifiedQuery = modifiedQuery.replace(/^\\s*(SELECT)\\s+(DISTINCT\\s+)?/i, `$1 TOP ${limit} $2`);\n\n\treturn modifiedQuery;\n}\n\n/**\n * Converts TOP syntax to LIMIT syntax for PostgreSQL/Snowflake\n * These databases don't support TOP keyword - they must use LIMIT\n * @param query - The SQL query to check\n * @returns The query with TOP removed (LIMIT will be added separately)\n */\nexport function convertTopToLimit(query: string): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Remove \"TOP N\" from query - LIMIT will be added at the end\n\t// Pattern: SELECT TOP number or SELECT TOP (number)\n\tlet modifiedQuery = query.replace(/\\bSELECT\\s+TOP\\s+\\(?\\d+\\)?\\s*/gi, 'SELECT ');\n\n\treturn modifiedQuery;\n}\n\n/**\n * Ensures a SQL query has a row limiting clause to prevent large result sets\n * Only applies to SELECT queries - leaves INSERT, UPDATE, DELETE, etc. unchanged\n * Database-aware: Uses TOP for MSSQL, LIMIT for PostgreSQL/Snowflake/MySQL\n * Enforces a maximum limit to prevent excessive data retrieval\n * @param query - The SQL query to check\n * @param defaultLimit - Default limit to apply if none exists (default: 32)\n * @param maxLimit - Maximum allowed limit (default: 32)\n * @param dbType - Database type (optional, defaults to promptLoader's database type)\n * @returns The query with appropriate row limiting clause (if it's a SELECT query)\n */\nexport function ensureQueryLimit(\n\tquery: string,\n\tdefaultLimit: number = 32,\n\tmaxLimit: number = 32,\n\tdbType?: DatabaseType\n): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Get database type from parameter or prompt loader\n\tconst databaseType = dbType || getDatabaseType();\n\tconst isMssql = databaseType === 'mssql';\n\n\tlet trimmedQuery = query.trim();\n\n\t// Only apply limits to SELECT queries\n\t// Check if the query is a SELECT statement (not INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, etc.)\n\tconst isSelectQuery = /^\\s*SELECT\\b/i.test(trimmedQuery) ||\n\t\t/^\\s*WITH\\b.*\\bSELECT\\b/is.test(trimmedQuery); // Also handle CTEs (WITH clause)\n\n\tif (!isSelectQuery) {\n\t\t// Not a SELECT query, return as-is\n\t\treturn query;\n\t}\n\n\t// Remove any trailing semicolon for processing\n\tconst hadSemicolon = trimmedQuery.endsWith(';');\n\tif (hadSemicolon) {\n\t\ttrimmedQuery = trimmedQuery.slice(0, -1).trim();\n\t}\n\n\tif (isMssql) {\n\t\t// MSSQL: Use TOP syntax\n\t\treturn ensureMssqlTop(trimmedQuery, defaultLimit, maxLimit, hadSemicolon);\n\t} else {\n\t\t// PostgreSQL/Snowflake/MySQL: Use LIMIT syntax\n\t\treturn ensurePostgresLimit(trimmedQuery, defaultLimit, maxLimit, hadSemicolon);\n\t}\n}\n\n/**\n * Ensures MSSQL query has TOP clause for row limiting\n */\nfunction ensureMssqlTop(query: string, defaultLimit: number, maxLimit: number, hadSemicolon: boolean): string {\n\tlet trimmedQuery = query;\n\n\t// First, remove any LIMIT clauses (might be added by LLM incorrectly)\n\ttrimmedQuery = trimmedQuery.replace(/\\s*\\bLIMIT\\s+\\d+\\b/gi, '').trim();\n\n\t// Check if TOP already exists\n\tconst topMatch = trimmedQuery.match(/\\bSELECT\\s+TOP\\s+\\(?\\s*(\\d+)\\s*\\)?/i);\n\n\tif (topMatch) {\n\t\tconst existingTop = parseInt(topMatch[1], 10);\n\n\t\t// If existing TOP is within limits, keep it\n\t\tif (existingTop <= maxLimit) {\n\t\t\tif (hadSemicolon) {\n\t\t\t\ttrimmedQuery += ';';\n\t\t\t}\n\t\t\treturn trimmedQuery;\n\t\t}\n\n\t\t// If existing TOP exceeds maxLimit, replace it\n\t\tconsole.warn(`⚠️ Query TOP ${existingTop} exceeds maximum of ${maxLimit}. Reducing to ${maxLimit}...`);\n\t\ttrimmedQuery = trimmedQuery.replace(/\\bSELECT\\s+TOP\\s+\\(?\\s*\\d+\\s*\\)?/i, `SELECT TOP ${maxLimit}`);\n\n\t\tif (hadSemicolon) {\n\t\t\ttrimmedQuery += ';';\n\t\t}\n\t\treturn trimmedQuery;\n\t}\n\n\t// No TOP exists, add it after SELECT (handle SELECT DISTINCT)\n\ttrimmedQuery = trimmedQuery.replace(\n\t\t/^\\s*(SELECT)\\s+(DISTINCT\\s+)?/i,\n\t\t`$1 TOP ${defaultLimit} $2`\n\t);\n\n\tif (hadSemicolon) {\n\t\ttrimmedQuery += ';';\n\t}\n\treturn trimmedQuery;\n}\n\n/**\n * Ensures PostgreSQL/Snowflake/MySQL query has LIMIT clause for row limiting\n */\nfunction ensurePostgresLimit(query: string, defaultLimit: number, maxLimit: number, hadSemicolon: boolean): string {\n\tlet trimmedQuery = query;\n\n\t// First, convert any TOP syntax to standard format (remove TOP, will add LIMIT)\n\ttrimmedQuery = convertTopToLimit(trimmedQuery);\n\n\t// Remove any duplicate LIMIT clauses\n\tconst limitMatches = trimmedQuery.match(/\\bLIMIT\\s+(\\d+)\\b/gi);\n\n\tif (limitMatches && limitMatches.length > 0) {\n\t\tif (limitMatches.length > 1) {\n\t\t\t// Multiple LIMIT clauses, remove all and add fresh one\n\t\t\tconsole.warn(`⚠️ Query had ${limitMatches.length} LIMIT clauses. Removing duplicates...`);\n\t\t\ttrimmedQuery = trimmedQuery.replace(/\\s*\\bLIMIT\\s+\\d+\\b/gi, '').trim();\n\t\t} else {\n\t\t\t// Single LIMIT exists - check if it exceeds maxLimit\n\t\t\tconst existingLimitMatch = trimmedQuery.match(/\\bLIMIT\\s+(\\d+)\\b/i);\n\t\t\tif (existingLimitMatch) {\n\t\t\t\tconst existingLimit = parseInt(existingLimitMatch[1], 10);\n\n\t\t\t\tif (existingLimit <= maxLimit) {\n\t\t\t\t\tif (hadSemicolon) {\n\t\t\t\t\t\ttrimmedQuery += ';';\n\t\t\t\t\t}\n\t\t\t\t\treturn trimmedQuery;\n\t\t\t\t}\n\n\t\t\t\tconsole.warn(`⚠️ Query LIMIT ${existingLimit} exceeds maximum of ${maxLimit}. Reducing to ${maxLimit}...`);\n\t\t\t\ttrimmedQuery = trimmedQuery.replace(/\\bLIMIT\\s+\\d+\\b/i, `LIMIT ${maxLimit}`);\n\n\t\t\t\tif (hadSemicolon) {\n\t\t\t\t\ttrimmedQuery += ';';\n\t\t\t\t}\n\t\t\t\treturn trimmedQuery;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add LIMIT clause at the end\n\ttrimmedQuery = `${trimmedQuery} LIMIT ${defaultLimit}`;\n\n\tif (hadSemicolon) {\n\t\ttrimmedQuery += ';';\n\t}\n\treturn trimmedQuery;\n}\n\n/**\n * Validates and fixes scalar subqueries to ensure they return exactly one row\n * Database-aware: Adds TOP 1 for MSSQL, LIMIT 1 for PostgreSQL/Snowflake/MySQL\n * Fixes subqueries used with scalar comparison operators (=, <, >, <=, >=, <>)\n *\n * @param query - The SQL query to validate\n * @param dbType - Database type (optional, defaults to promptLoader's database type)\n * @returns The query with fixed scalar subqueries\n */\nexport function fixScalarSubqueries(query: string, dbType?: DatabaseType): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Get database type from parameter or prompt loader\n\tconst databaseType = dbType || getDatabaseType();\n\tconst isMssql = databaseType === 'mssql';\n\n\tlet modifiedQuery = query;\n\tlet hasChanges = false;\n\n\t// Find all subqueries preceded by scalar comparison operators\n\t// Pattern: operator followed by (SELECT ...)\n\tconst scalarOperatorPattern = /([=<>!]=?|<>)\\s*\\(\\s*SELECT\\s/gi;\n\n\tconst matches = [...modifiedQuery.matchAll(scalarOperatorPattern)];\n\n\t// Process matches in reverse order to maintain string positions\n\tfor (let i = matches.length - 1; i >= 0; i--) {\n\t\tconst match = matches[i];\n\t\tconst startPos = match.index! + match[0].length - 'SELECT '.length;\n\n\t\t// Find the matching closing parenthesis\n\t\tlet parenDepth = 1;\n\t\tlet endPos = startPos;\n\t\tlet foundEnd = false;\n\n\t\tfor (let j = startPos; j < modifiedQuery.length; j++) {\n\t\t\tconst char = modifiedQuery[j];\n\t\t\tif (char === '(') parenDepth++;\n\t\t\tif (char === ')') {\n\t\t\t\tparenDepth--;\n\t\t\t\tif (parenDepth === 0) {\n\t\t\t\t\tendPos = j;\n\t\t\t\t\tfoundEnd = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!foundEnd) continue;\n\n\t\t// Extract the subquery content\n\t\tconst subquery = modifiedQuery.substring(startPos, endPos);\n\n\t\tif (isMssql) {\n\t\t\t// Check if it already has TOP\n\t\t\tif (/\\bSELECT\\s+TOP\\s+\\d+/i.test(subquery)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Add TOP 1 after SELECT for MSSQL\n\t\t\tconst fixedSubquery = subquery.replace(/^\\s*SELECT\\s+/i, 'SELECT TOP 1 ');\n\t\t\tmodifiedQuery =\n\t\t\t\tmodifiedQuery.substring(0, startPos) +\n\t\t\t\tfixedSubquery +\n\t\t\t\tmodifiedQuery.substring(endPos);\n\t\t} else {\n\t\t\t// Check if it already has LIMIT\n\t\t\tif (/\\bLIMIT\\s+\\d+/i.test(subquery)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Add LIMIT 1 at the end for PostgreSQL/Snowflake/MySQL\n\t\t\tconst fixedSubquery = subquery.trim() + ' LIMIT 1';\n\t\t\tmodifiedQuery =\n\t\t\t\tmodifiedQuery.substring(0, startPos) +\n\t\t\t\tfixedSubquery +\n\t\t\t\tmodifiedQuery.substring(endPos);\n\t\t}\n\n\t\thasChanges = true;\n\t\tconst limitType = isMssql ? 'TOP 1' : 'LIMIT 1';\n\t\tconsole.warn(`⚠️ Fixed scalar subquery: added ${limitType} to prevent multiple row error`);\n\t}\n\n\tif (hasChanges) {\n\t\tconst dbName = isMssql ? 'MSSQL' : 'PostgreSQL';\n\t\tconsole.log(`✓ Query validated and fixed for ${dbName} scalar subquery compatibility`);\n\t}\n\n\treturn modifiedQuery;\n}\n\n/**\n * Converts question strings to Action objects format\n * Used for follow-up questions generated by LLM\n * @param questions - Array of question strings\n * @returns Array of Action objects\n */\nexport function convertQuestionsToActions(questions: string[]): Action[] {\n\treturn questions.map((question: string, index: number) => ({\n\t\tid: `action_${index}_${Date.now()}`,\n\t\tname: question,\n\t\ttype: 'next_question',\n\t\tquestion\n\t}));\n}\n\n/**\n * Calculates the size of a JSON object in bytes\n * @param obj - The object to measure\n * @returns Size in bytes\n */\nexport function getJsonSizeInBytes(obj: any): number {\n\tconst jsonString = JSON.stringify(obj);\n\treturn Buffer.byteLength(jsonString, 'utf8');\n}\n\n/**\n * Checks if a message exceeds the WebSocket size limit\n * @param message - The message object to check\n * @param maxSize - Maximum size in bytes (default: 1MB)\n * @returns Object with isValid flag and size information\n */\nexport function validateMessageSize(message: any, maxSize: number = 1048576): { isValid: boolean; size: number; maxSize: number } {\n\tconst size = getJsonSizeInBytes(message);\n\treturn {\n\t\tisValid: size <= maxSize,\n\t\tsize,\n\t\tmaxSize\n\t};\n}","import { createWebSocket } from './websocket';\nimport {\n IncomingMessageSchema,\n type Message,\n type IncomingMessage,\n type SuperatomSDKConfig,\n type CollectionRegistry,\n type CollectionHandler,\n type CollectionOperation,\n type DatabaseType,\n type ModelStrategy,\n Component,\n LLMProvider,\n Tool,\n} from './types';\nimport { logger } from './utils/logger';\nimport { handleDataRequest } from './handlers/data-request';\nimport { handleBundleRequest } from './handlers/bundle-request';\nimport { handleAuthLoginRequest } from './handlers/auth-login-requests';\nimport { handleAuthVerifyRequest } from './handlers/auth-verify-request';\nimport { handleUserPromptRequest } from './handlers/user-prompt-request';\nimport { handleUserPromptSuggestions } from './handlers/user-prompt-suggestions';\nimport { handleActionsRequest } from './handlers/actions-request';\nimport { handleComponentListResponse } from './handlers/components-list-response';\nimport { handleUsersRequest } from './handlers/users';\nimport { handleDashboardsRequest } from './handlers/dashboards';\nimport { handleReportsRequest } from './handlers/reports';\nimport { handleUIsRequest } from './handlers/uis';\nimport { handleBookmarksRequest } from './handlers/bookmarks';\nimport { handleKbNodesRequest } from './handlers/kb-nodes';\nimport { handleDashCompRequest } from './handlers/dash-comp-request';\nimport { getLLMProviders, anthropicLLM, groqLLM, geminiLLM, openaiLLM } from './userResponse';\nimport { setUserManager, cleanupUserStorage } from './auth/user-storage';\nimport { UserManager } from './auth/user-manager';\nimport { setDashboardManager } from './dashboards/dashboard-storage';\nimport { DashboardManager } from './dashboards/dashboard-manager';\nimport { setReportManager } from './reports/report-storage';\nimport { ReportManager } from './reports/report-manager';\nimport { promptLoader } from './userResponse/prompt-loader';\n\nexport const SDK_VERSION = '0.0.8';\n\nconst DEFAULT_WS_URL = 'wss://ws.superatom.ai/websocket';\n\ntype MessageTypeHandler = (message: IncomingMessage) => void | Promise<void>;\n\nexport class SuperatomSDK {\n private ws: ReturnType<typeof createWebSocket> | null = null;\n private url: string;\n private apiKey?: string;\n private projectId: string;\n private userId: string;\n private type: string;\n private bundleDir: string | undefined;\n private messageHandlers: Map<string, (message: IncomingMessage) => void> = new Map();\n private messageTypeHandlers: Map<string, MessageTypeHandler> = new Map();\n private connected: boolean = false;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = 5;\n private collections: CollectionRegistry = {};\n\tprivate components: Component[] = [];\n private tools: Tool[] = [];\n private anthropicApiKey: string;\n private groqApiKey: string;\n private geminiApiKey: string;\n private openaiApiKey: string;\n private llmProviders: LLMProvider[];\n private databaseType: DatabaseType;\n private modelStrategy: ModelStrategy;\n private userManager: UserManager;\n private dashboardManager: DashboardManager;\n private reportManager: ReportManager;\n\n // Heartbeat properties for keeping WebSocket connection alive\n private pingInterval: NodeJS.Timeout | null = null;\n private lastPong: number = Date.now();\n private readonly PING_INTERVAL_MS = 180000; // 3 minutes\n private readonly PONG_TIMEOUT_MS = 210000; // 3.5 minutes (PING_INTERVAL + 30s grace)\n\n constructor(config: SuperatomSDKConfig) {\n // Set log level if provided in config (overrides environment variable)\n if (config.logLevel) {\n logger.setLogLevel(config.logLevel);\n }\n\n this.apiKey = config.apiKey;\n this.projectId = config.projectId;\n this.userId = config.userId || 'anonymous';\n this.type = config.type || 'data-agent';\n this.bundleDir = config.bundleDir;\n this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;\n this.anthropicApiKey = config.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY || '';\n this.groqApiKey = config.GROQ_API_KEY || process.env.GROQ_API_KEY || '';\n this.geminiApiKey = config.GEMINI_API_KEY || process.env.GEMINI_API_KEY || '';\n this.openaiApiKey = config.OPENAI_API_KEY || process.env.OPENAI_API_KEY || '';\n this.llmProviders = config.LLM_PROVIDERS || getLLMProviders();\n this.databaseType = config.databaseType || 'postgresql';\n this.modelStrategy = config.modelStrategy || 'fast';\n\n // Apply model strategy to all LLM providers\n this.applyModelStrategy(this.modelStrategy);\n\n logger.info(`Initializing Superatom SDK v${SDK_VERSION} for project ${this.projectId}, llm providers: ${this.llmProviders.join(', ')}, database type: ${this.databaseType}, model strategy: ${this.modelStrategy}`);\n\n // Initialize UserManager for this SDK instance\n this.userManager = new UserManager(this.projectId, 5000);\n\n // Initialize DashboardManager for this SDK instance\n this.dashboardManager = new DashboardManager(this.projectId);\n\n // Initialize ReportManager for this SDK instance\n this.reportManager = new ReportManager(this.projectId);\n\n // Initialize PromptLoader (load prompts into memory)\n this.initializePromptLoader(config.promptsDir).catch((error) => {\n logger.error('Failed to initialize PromptLoader:', error);\n });\n\n // Initialize UserManager with projectId (startup)\n this.initializeUserManager().catch((error) => {\n logger.error('Failed to initialize UserManager:', error);\n });\n\n // Initialize DashboardManager\n this.initializeDashboardManager();\n\n // Initialize ReportManager\n this.initializeReportManager();\n\n // Note: Connection is not automatic - call connect() explicitly when ready\n }\n\n /**\n * Initialize PromptLoader and load prompts into memory\n * Tries to load from file system first, then falls back to hardcoded prompts\n */\n private async initializePromptLoader(promptsDir?: string): Promise<void> {\n try {\n // Set custom prompts directory if provided\n if (promptsDir) {\n promptLoader.setPromptsDir(promptsDir);\n }\n\n // Set database type for SQL rules loading\n promptLoader.setDatabaseType(this.databaseType);\n\n await promptLoader.initialize();\n logger.info(`PromptLoader initialized with ${promptLoader.getCacheSize()} prompts from ${promptLoader.getPromptsDir()}, database type: ${this.databaseType}`);\n } catch (error) {\n logger.error('Failed to initialize PromptLoader:', error);\n throw error;\n }\n }\n\n /**\n * Initialize UserManager for the project\n */\n private async initializeUserManager(): Promise<void> {\n try {\n await this.userManager.init();\n // Set the global reference for backward compatibility with existing auth code\n setUserManager(this.userManager);\n logger.info(`UserManager initialized for project: ${this.projectId}`);\n } catch (error) {\n logger.error('Failed to initialize UserManager:', error);\n throw error;\n }\n }\n\n /**\n * Get the UserManager instance for this SDK\n */\n public getUserManager(): UserManager {\n return this.userManager;\n }\n\n /**\n * Initialize DashboardManager for the project\n */\n private initializeDashboardManager(): void {\n // Set the global reference for dashboard operations\n setDashboardManager(this.dashboardManager);\n logger.info(`DashboardManager initialized for project: ${this.projectId}`);\n }\n\n /**\n * Get the DashboardManager instance for this SDK\n */\n public getDashboardManager(): DashboardManager {\n return this.dashboardManager;\n }\n\n /**\n * Initialize ReportManager for the project\n */\n private initializeReportManager(): void {\n // Set the global reference for report operations\n setReportManager(this.reportManager);\n logger.info(`ReportManager initialized for project: ${this.projectId}`);\n }\n\n /**\n * Get the ReportManager instance for this SDK\n */\n public getReportManager(): ReportManager {\n return this.reportManager;\n }\n\n /**\n * Connect to the Superatom WebSocket service\n */\n async connect(): Promise<void> {\n // If already connected, return immediately\n if (this.connected && this.ws && this.ws.readyState === this.ws.OPEN) {\n logger.info('Already connected to WebSocket');\n return Promise.resolve();\n }\n\n return new Promise((resolve, reject) => {\n try {\n // Add all required query parameters\n const url = new URL(this.url);\n if (this.apiKey) {\n url.searchParams.set('apiKey', this.apiKey);\n }\n url.searchParams.set('projectId', this.projectId);\n url.searchParams.set('userId', this.userId);\n url.searchParams.set('type', this.type);\n\n logger.info(`Connecting to WebSocket: ${url.toString()}`);\n\n this.ws = createWebSocket(url.toString());\n\n this.ws.addEventListener('open', () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n logger.info('WebSocket connected successfully');\n this.startHeartbeat(); // Start heartbeat to keep connection alive\n resolve();\n });\n\n this.ws.addEventListener('message', (event: any) => {\n this.handleMessage(event.data);\n });\n\n this.ws.addEventListener('error', (error: any) => {\n logger.error('WebSocket error:', error);\n reject(error);\n });\n\n this.ws.addEventListener('close', () => {\n this.connected = false;\n logger.warn('WebSocket closed');\n this.handleReconnect();\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Handle incoming WebSocket messages\n */\n private handleMessage(data: string): void {\n try {\n const parsed = JSON.parse(data);\n const message = IncomingMessageSchema.parse(parsed);\n\n logger.debug('Received message:', message.type);\n\n // Route message by type\n switch (message.type) {\n case 'PONG':\n // Handle heartbeat PONG response\n this.handlePong();\n break;\n\n case 'DATA_REQ':\n handleDataRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle data request:', error);\n });\n break;\n\n case 'BUNDLE_REQ':\n handleBundleRequest(parsed, this.bundleDir, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle bundle request:', error);\n });\n break;\n\n case 'AUTH_LOGIN_REQ':\n handleAuthLoginRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle auth login request:', error);\n });\n break;\n\n case 'AUTH_VERIFY_REQ':\n handleAuthVerifyRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle auth verify request:', error);\n });\n break;\n\n case 'USER_PROMPT_REQ':\n handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools, this.userId).catch((error) => {\n logger.error('Failed to handle user prompt request:', error);\n });\n break;\n\n case 'ACTIONS':\n handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders).catch((error) => {\n logger.error('Failed to handle actions request:', error);\n });\n break;\n\n case 'USER_PROMPT_SUGGESTIONS_REQ':\n handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections, this.userId).catch((error) => {\n logger.error('Failed to handle user prompt suggestions request:', error);\n });\n break;\n\n case 'COMPONENT_LIST_RES':\n handleComponentListResponse(parsed, (com) => this.storeComponents(com), this.collections).catch((error) => {\n logger.error('Failed to handle component list request:', error);\n });\n break;\n\n case 'USERS':\n handleUsersRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle users request:', error);\n });\n break;\n\n case 'DASHBOARDS':\n handleDashboardsRequest(parsed, this.collections, (msg: Message) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle dashboards request:', error);\n });\n break;\n\n case 'REPORTS':\n handleReportsRequest(parsed, this.collections, (msg: Message) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle reports request:', error);\n });\n break;\n\n case 'UIS':\n handleUIsRequest(parsed, this.collections, (msg: Message) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle UIs request:', error);\n });\n break;\n\n case 'BOOKMARKS':\n handleBookmarksRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle bookmarks request:', error);\n });\n break;\n\n case 'KB_NODES':\n handleKbNodesRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle KB nodes request:', error);\n });\n break;\n\n case 'DASH_COMP_REQ':\n handleDashCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {\n logger.error('Failed to handle dash comp request:', error);\n });\n break;\n\n default:\n // Check for custom message type handlers\n const handler = this.messageTypeHandlers.get(message.type);\n if (handler) {\n Promise.resolve(handler(message)).catch((error) => {\n logger.error(`Failed to handle ${message.type}:`, error);\n });\n }\n break;\n }\n\n // Call registered message handlers\n this.messageHandlers.forEach((handler) => {\n handler(message);\n });\n } catch (error) {\n logger.error('Failed to parse incoming message:', error);\n }\n }\n\n /**\n * Send a message to the Superatom service\n */\n send(message: Message): void {\n if (!this.ws || !this.connected) {\n throw new Error('WebSocket is not connected. Call connect() first.');\n }\n\n if (this.ws.readyState !== this.ws.OPEN) {\n throw new Error('WebSocket is not ready to send messages.');\n }\n\n const payload = JSON.stringify(message);\n this.ws.send(payload);\n }\n\n /**\n * Register a message handler to receive all messages\n */\n onMessage(handler: (message: IncomingMessage) => void): () => void {\n const id = Math.random().toString(36).substring(7);\n this.messageHandlers.set(id, handler);\n\n // Return unsubscribe function\n return () => {\n this.messageHandlers.delete(id);\n };\n }\n\n /**\n * Register a handler for a specific message type\n */\n onMessageType(type: string, handler: MessageTypeHandler): () => void {\n this.messageTypeHandlers.set(type, handler);\n\n // Return unsubscribe function\n return () => {\n this.messageTypeHandlers.delete(type);\n };\n }\n\n /**\n * Disconnect from the WebSocket service\n */\n disconnect(): void {\n this.stopHeartbeat(); // Stop heartbeat before disconnecting\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n this.connected = false;\n }\n }\n\n /**\n * Cleanup and disconnect - stops reconnection attempts and closes the connection\n */\n async destroy(): Promise<void> {\n // Stop heartbeat first\n this.stopHeartbeat();\n\n // Prevent further reconnection attempts\n this.maxReconnectAttempts = 0;\n this.reconnectAttempts = 0;\n\n // Clear all message handlers\n this.messageHandlers.clear();\n\n // Clear all collections\n this.collections = {};\n\n // Cleanup UserManager\n try {\n await cleanupUserStorage();\n logger.info('UserManager cleanup completed');\n } catch (error) {\n logger.error('Error during UserManager cleanup:', error);\n }\n\n // Disconnect\n this.disconnect();\n }\n\n /**\n * Check if the SDK is currently connected\n */\n isConnected(): boolean {\n return this.connected && this.ws !== null && this.ws.readyState === this.ws.OPEN;\n }\n\n /**\n * Register a collection handler for data operations\n */\n addCollection<TParams = any, TResult = any>(\n collectionName: string,\n operation: CollectionOperation | string,\n handler: CollectionHandler<TParams, TResult>\n ): void {\n if (!this.collections[collectionName]) {\n this.collections[collectionName] = {};\n }\n this.collections[collectionName][operation] = handler;\n }\n\n private handleReconnect(): void {\n if (this.reconnectAttempts < this.maxReconnectAttempts) {\n this.reconnectAttempts++;\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 10000);\n\n setTimeout(() => {\n logger.info(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);\n this.connect().catch((error) => {\n logger.error('Reconnection failed:', error);\n });\n }, delay);\n } else {\n logger.error('Max reconnection attempts reached');\n }\n }\n\n /**\n * Start heartbeat to keep WebSocket connection alive\n * Sends PING every 3 minutes to prevent idle timeout from cloud infrastructure\n */\n private startHeartbeat(): void {\n this.stopHeartbeat(); // Clear any existing interval\n this.lastPong = Date.now();\n\n this.pingInterval = setInterval(() => {\n if (!this.ws || this.ws.readyState !== this.ws.OPEN) {\n logger.warn('WebSocket not open during heartbeat check, stopping heartbeat');\n this.stopHeartbeat();\n return;\n }\n\n // Check if we received a PONG within the timeout period\n const timeSinceLastPong = Date.now() - this.lastPong;\n if (timeSinceLastPong > this.PONG_TIMEOUT_MS) {\n logger.warn(`No PONG received for ${timeSinceLastPong}ms, connection may be dead. Reconnecting...`);\n this.stopHeartbeat();\n this.ws.close(); // This will trigger handleReconnect via the close event\n return;\n }\n\n // Send PING message\n try {\n const pingMessage: Message = {\n type: 'PING',\n from: { type: this.type },\n payload: { timestamp: Date.now() }\n };\n this.ws.send(JSON.stringify(pingMessage));\n logger.debug('Heartbeat PING sent');\n } catch (error) {\n logger.error('Failed to send PING:', error);\n this.stopHeartbeat();\n this.ws.close();\n }\n }, this.PING_INTERVAL_MS);\n\n logger.info(`Heartbeat started (PING every ${this.PING_INTERVAL_MS / 1000}s)`);\n }\n\n /**\n * Stop the heartbeat interval\n */\n private stopHeartbeat(): void {\n if (this.pingInterval) {\n clearInterval(this.pingInterval);\n this.pingInterval = null;\n logger.debug('Heartbeat stopped');\n }\n }\n\n /**\n * Handle PONG response from server\n */\n private handlePong(): void {\n this.lastPong = Date.now();\n logger.debug('Heartbeat PONG received');\n }\n\n private storeComponents(components: Component[]){\n this.components = components;\n }\n\n /**\n * Set tools for the SDK instance\n */\n public setTools(tools: Tool[]): void {\n this.tools = tools;\n logger.info(`Tools stored in SDK: ${tools.length} tools`);\n }\n\n /**\n * Get the stored tools\n */\n public getTools(): Tool[] {\n return this.tools;\n }\n\n /**\n * Apply model strategy to all LLM provider singletons\n * @param strategy - 'best', 'fast', or 'balanced'\n */\n private applyModelStrategy(strategy: ModelStrategy): void {\n anthropicLLM.setModelStrategy(strategy);\n groqLLM.setModelStrategy(strategy);\n geminiLLM.setModelStrategy(strategy);\n openaiLLM.setModelStrategy(strategy);\n logger.info(`Model strategy '${strategy}' applied to all LLM providers`);\n }\n\n /**\n * Set model strategy at runtime\n * @param strategy - 'best', 'fast', or 'balanced'\n */\n public setModelStrategy(strategy: ModelStrategy): void {\n this.modelStrategy = strategy;\n this.applyModelStrategy(strategy);\n }\n\n /**\n * Get current model strategy\n */\n public getModelStrategy(): ModelStrategy {\n return this.modelStrategy;\n }\n\n}\n\n// Export types\nexport type { Message, IncomingMessage, SuperatomSDKConfig, CollectionHandler, CollectionOperation, User, UsersData, Tool, DBUIBlock, KbNodesRequestPayload, KbNodesQueryFilters, DatabaseType, ModelStrategy } from './types';\nexport {LLM} from './llm';\nexport { UserManager } from './auth/user-manager';\nexport { UILogCollector, type CapturedLog } from './utils/log-collector';\nexport { Thread, UIBlock, ThreadManager, type Action } from './threads';\nexport { CleanupService } from './services/cleanup-service';\nexport { STORAGE_CONFIG } from './config/storage';\nexport { CONTEXT_CONFIG } from './config/context';\nexport { logger, type LogLevel } from './utils/logger';\n// LLM Usage Logger for tracking API costs and performance\nexport { llmUsageLogger, type LLMUsageEntry } from './utils/llm-usage-logger';\n// User Prompt Error Logger for capturing detailed error information\nexport { userPromptErrorLogger } from './utils/user-prompt-error-logger';\n// BM25L Reranker for hybrid semantic search\nexport {\n BM25L,\n hybridRerank,\n rerankChromaResults,\n rerankConversationResults,\n type BM25LOptions,\n type HybridSearchOptions,\n type RerankedResult\n} from './utils/bm25l-reranker';\n// LLM Model Strategy for configuring model usage (ModelStrategy exported from types above)\nexport {\n type TaskType,\n type BaseLLMConfig,\n anthropicLLM,\n groqLLM,\n geminiLLM,\n openaiLLM\n} from './userResponse';","import WebSocket from 'ws';\nimport type { WebSocketLike } from './types';\n\n/**\n * Creates a WebSocket instance for Node.js using the ws package\n */\nexport function createWebSocket(url: string): WebSocketLike {\n return new WebSocket(url) as WebSocketLike;\n}\n","import { z } from 'zod';\n\n// Re-export DBUIBlock for external use\nexport type { DBUIBlock } from './utils/conversation-saver';\n\n// User schema for authentication and management\nexport const UserSchema = z.object({\n username: z.string().min(1, 'Username is required'),\n email: z.string().email('Invalid email format').optional(),\n password: z.string().min(1, 'Password is required'),\n fullname: z.string().optional(),\n role: z.string().optional(),\n userInfo: z.record(z.unknown()).optional(),\n wsIds: z.array(z.string()).optional(), // Only in memory, not persisted to file\n});\n\nexport type User = z.infer<typeof UserSchema>;\n\nexport const UsersDataSchema = z.object({\n users: z.array(UserSchema),\n});\n\nexport type UsersData = z.infer<typeof UsersDataSchema>;\n\n// From/To object schema for WebSocket messages\nexport const MessageParticipantSchema = z.object({\n id: z.string().optional(),\n type: z.string().optional(),\n});\n\nexport type MessageParticipant = z.infer<typeof MessageParticipantSchema>;\n\n// Message schemas for WebSocket communication\nexport const MessageSchema = z.object({\n id: z.string().optional(),\n type: z.string(),\n from: MessageParticipantSchema,\n to: MessageParticipantSchema.optional(),\n payload: z.unknown(),\n});\n\nexport type Message = z.infer<typeof MessageSchema>;\n\nexport const IncomingMessageSchema = z.object({\n id: z.string().optional(),\n type: z.string(),\n from: MessageParticipantSchema,\n to: MessageParticipantSchema.optional(),\n payload: z.unknown(),\n});\n\nexport type IncomingMessage = z.infer<typeof IncomingMessageSchema>;\n\n// Data request/response schemas\nexport const DataRequestPayloadSchema = z.object({\n collection: z.string(),\n op: z.string(),\n params: z.record(z.unknown()).optional(),\n SA_RUNTIME: z.record(z.unknown()).optional(),\n});\n\nexport type DataRequestPayload = z.infer<typeof DataRequestPayloadSchema>;\n\nexport const DataRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('DATA_REQ'),\n payload: DataRequestPayloadSchema,\n});\n\nexport type DataRequestMessage = z.infer<typeof DataRequestMessageSchema>;\n\nexport const AuthLoginRequestPayloadSchema = z.object({\n login_data: z.string(),\n});\n\nexport type AuthLoginRequestPayload = z.infer<typeof AuthLoginRequestPayloadSchema>;\n\nexport const AuthLoginRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('AUTH_LOGIN_REQ'),\n payload: AuthLoginRequestPayloadSchema,\n});\n\nexport type AuthLoginRequestMessage = z.infer<typeof AuthLoginRequestMessageSchema>;\n\nexport const AuthVerifyRequestPayloadSchema = z.object({\n token: z.string(),\n});\n\nexport type AuthVerifyRequestPayload = z.infer<typeof AuthVerifyRequestPayloadSchema>;\n\nexport const AuthVerifyRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('AUTH_VERIFY_REQ'),\n payload: AuthVerifyRequestPayloadSchema,\n});\n\nexport type AuthVerifyRequestMessage = z.infer<typeof AuthVerifyRequestMessageSchema>;\n\nexport const UserPromptRequestPayloadSchema = z.object({\n prompt: z.string(),\n SA_RUNTIME: z.object({\n threadId: z.string(),\n uiBlockId: z.string(),\n }).optional(),\n responseMode: z.enum(['component', 'text']).optional(),\n});\n\nexport type UserPromptRequestPayload = z.infer<typeof UserPromptRequestPayloadSchema>;\n\nexport const UserPromptRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('USER_PROMPT_REQ'),\n payload: UserPromptRequestPayloadSchema,\n});\n\nexport type UserPromptRequestMessage = z.infer<typeof UserPromptRequestMessageSchema>;\n\nexport const UserPromptSuggestionsPayloadSchema = z.object({\n prompt: z.string(),\n limit: z.number().int().positive().default(5),\n similarityThreshold: z.number().min(0).max(1).default(0.4),\n});\n\nexport type UserPromptSuggestionsPayload = z.infer<typeof UserPromptSuggestionsPayloadSchema>;\n\nexport const UserPromptSuggestionsMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('USER_PROMPT_SUGGESTIONS_REQ'),\n payload: UserPromptSuggestionsPayloadSchema,\n});\n\nexport type UserPromptSuggestionsMessage = z.infer<typeof UserPromptSuggestionsMessageSchema>;\n\n\nexport const ComponentPropsSchema = z.object({\n query: z.string().or(z.object({})).optional(),\n title: z.string().optional(),\n description: z.string().optional(),\n config: z.record(z.unknown()).optional(),\n actions: z.array(z.any()).optional(),\n}).passthrough(); // Allow additional props beyond the defined ones\n\nexport const ComponentSchema = z.object({\n id: z.string(),\n name: z.string(),\n displayName: z.string().optional(),\n isDisplayComp: z.boolean().optional(),\n type: z.string(),\n description: z.string(),\n props: ComponentPropsSchema,\n category: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n});\n\nexport const ComponentsSchema = z.array(ComponentSchema);\n\nexport type Component = z.infer<typeof ComponentSchema>;\n\nexport const ComponentListResponsePayloadSchema = z.object({\n components: z.array(ComponentSchema),\n});\n\nexport type ComponentListResponsePayload = z.infer<typeof ComponentListResponsePayloadSchema>; \n\nexport const ComponentListResponseMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('COMPONENT_LIST_RES'),\n payload: ComponentListResponsePayloadSchema,\n});\n\nexport type ComponentListResponseMessage = z.infer<typeof ComponentListResponseMessageSchema>;\n\n// Tool schemas\nexport const ToolSchema = z.object({\n id: z.string(),\n name: z.string(),\n description: z.string(),\n params: z.record(z.string()),\n fn: z.function().args(z.any()).returns(z.any())\n});\n\nexport type Tool = z.infer<typeof ToolSchema>;\n\n// Admin User Management Request/Response schemas (Unified)\n\n// Query filters schema for users\nexport const UserQueryFiltersSchema = z.object({\n username: z.string().optional(),\n email: z.string().optional(),\n role: z.string().optional(),\n fullname: z.string().optional(),\n});\n\nexport type UserQueryFilters = z.infer<typeof UserQueryFiltersSchema>;\n\nexport const UsersRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n username: z.string().optional(),\n email: z.string().email('Invalid email format').optional(),\n password: z.string().optional(),\n fullname: z.string().optional(),\n role: z.string().optional(),\n userInfo: z.record(z.unknown()).optional(),\n // Query operation fields\n filters: UserQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type UsersRequestPayload = z.infer<typeof UsersRequestPayloadSchema>;\n\nexport const UsersRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('USERS'),\n payload: UsersRequestPayloadSchema,\n});\n\nexport type UsersRequestMessage = z.infer<typeof UsersRequestMessageSchema>;\n\n// UI Logs schema for tracking user request execution\nexport const UILogsPayloadSchema = z.object({\n logs: z.array(z.object({\n timestamp: z.number(),\n level: z.enum(['info', 'error', 'warn', 'debug']),\n message: z.string(),\n type: z.enum(['explanation', 'query', 'general']).optional(),\n data: z.record(z.unknown()).optional(),\n })),\n});\n\nexport type UILogsPayload = z.infer<typeof UILogsPayloadSchema>;\n\nexport const UILogsMessageSchema = z.object({\n id: z.string(), // uiBlockId\n from: MessageParticipantSchema,\n type: z.literal('UI_LOGS'),\n payload: UILogsPayloadSchema,\n});\n\nexport type UILogsMessage = z.infer<typeof UILogsMessageSchema>;\n\n// Actions request schema - for runtime to send component actions and request next questions\nexport const ActionsRequestPayloadSchema = z.object({\n SA_RUNTIME: z.object({\n threadId: z.string(),\n uiBlockId: z.string(),\n }).optional(),\n});\n\nexport type ActionsRequestPayload = z.infer<typeof ActionsRequestPayloadSchema>;\n\nexport const ActionsRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('ACTIONS'),\n payload: ActionsRequestPayloadSchema,\n});\n\nexport type ActionsRequestMessage = z.infer<typeof ActionsRequestMessageSchema>;\n\n// Collection operation types\nexport type CollectionOperation =\n | 'getMany'\n | 'getOne'\n | 'query'\n | 'mutation'\n | 'updateOne'\n | 'deleteOne'\n | 'createOne';\n\nexport type CollectionHandler<TParams = any, TResult = any> = (\n params: TParams\n) => Promise<TResult> | TResult;\n\nexport interface CollectionRegistry {\n [collectionName: string]: {\n [operation: string]: CollectionHandler;\n };\n}\n\nexport type LLMProvider = 'anthropic' | 'groq' | 'gemini' | 'openai';\n\nimport type { LogLevel } from './utils/logger';\n\nexport type DatabaseType = 'postgresql' | 'mssql' | 'snowflake' | 'mysql';\n\n/**\n * Model strategy for controlling which models are used for different tasks\n * - 'best': Use the best model (e.g., Sonnet) for all tasks - highest quality, higher cost\n * - 'fast': Use the fast model (e.g., Haiku) for all tasks - lower quality, lower cost\n * - 'balanced': Use best model for complex tasks, fast model for simple tasks (default)\n */\nexport type ModelStrategy = 'best' | 'fast' | 'balanced';\n\n/**\n * Model configuration for DASH_COMP flow (dashboard component picking)\n * Allows separate control of models used for component selection\n */\nexport interface DashCompModelConfig {\n /**\n * Primary model for DASH_COMP requests\n * Format: \"provider/model-name\" (e.g., \"anthropic/claude-sonnet-4-5-20250929\")\n */\n model?: string;\n /**\n * Fast model for simpler DASH_COMP tasks (optional)\n * Format: \"provider/model-name\" (e.g., \"anthropic/claude-haiku-4-5-20251001\")\n */\n fastModel?: string;\n}\n\nexport interface SuperatomSDKConfig {\n url?: string;\n apiKey?: string;\n projectId: string;\n userId?: string;\n type?: string;\n bundleDir?: string;\n promptsDir?: string; // Path to custom prompts directory (defaults to .prompts in SDK)\n databaseType?: DatabaseType; // Database type for SQL generation rules (defaults to 'postgresql')\n ANTHROPIC_API_KEY?: string;\n GROQ_API_KEY?: string;\n GEMINI_API_KEY?: string;\n OPENAI_API_KEY?: string;\n LLM_PROVIDERS?: LLMProvider[];\n logLevel?: LogLevel; // Log level for SDK logging (errors, warnings, info, verbose)\n /**\n * Model selection strategy for LLM API calls:\n * - 'best': Use best model for all tasks (highest quality, higher cost)\n * - 'fast': Use fast model for all tasks (lower quality, lower cost)\n * - 'balanced': Use best model for complex tasks, fast model for simple tasks (default)\n */\n modelStrategy?: ModelStrategy;\n /**\n * Separate model configuration for DASH_COMP flow (dashboard component picking)\n * If not provided, falls back to provider-based model selection\n */\n dashCompModels?: DashCompModelConfig;\n}\n\n// ==================== Dashboard CRUD Message Schemas ====================\n\n// Import DSL types from dashboards module\nimport { DSLRendererPropsSchema } from './dashboards/types';\nexport type { DSLRendererProps } from './dashboards/types';\n\n// Query filters schema for dashboards\nexport const DashboardQueryFiltersSchema = z.object({\n dashboardId: z.string().optional(),\n projectId: z.string().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n name: z.string().optional(),\n published: z.boolean().optional(),\n});\n\nexport type DashboardQueryFilters = z.infer<typeof DashboardQueryFiltersSchema>;\n\n// Dashboard CRUD request payload\nexport const DashboardsRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n dashboardId: z.string().optional(),\n projectId: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n published: z.boolean().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n allowedUsers: z.array(z.number()).optional(),\n dashboard: DSLRendererPropsSchema.optional(),\n // Query operation fields\n filters: DashboardQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type DashboardsRequestPayload = z.infer<typeof DashboardsRequestPayloadSchema>;\n\nexport const DashboardsRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('DASHBOARDS'),\n payload: DashboardsRequestPayloadSchema,\n});\n\nexport type DashboardsRequestMessage = z.infer<typeof DashboardsRequestMessageSchema>;\n\n// ==================== Report CRUD Message Schemas ====================\n\n// Import DSL types from reports module\nimport { DSLRendererPropsSchema as ReportDSLRendererPropsSchema } from './reports/types';\nexport type { DSLRendererProps as ReportDSLRendererProps } from './reports/types';\n\n// Query filters schema for reports\nexport const ReportQueryFiltersSchema = z.object({\n reportId: z.string().optional(),\n projectId: z.string().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n name: z.string().optional(),\n published: z.boolean().optional(),\n});\n\nexport type ReportQueryFilters = z.infer<typeof ReportQueryFiltersSchema>;\n\n// Report CRUD request payload\nexport const ReportsRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n reportId: z.string().optional(),\n projectId: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n published: z.boolean().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n report: ReportDSLRendererPropsSchema.optional(),\n // Query operation fields\n filters: ReportQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type ReportsRequestPayload = z.infer<typeof ReportsRequestPayloadSchema>;\n\nexport const ReportsRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('REPORTS'),\n payload: ReportsRequestPayloadSchema,\n});\n\nexport type ReportsRequestMessage = z.infer<typeof ReportsRequestMessageSchema>;\n\n// ==================== UIs CRUD Message Schemas ====================\n\n// Import DSL types from uis module (same as dashboards)\nimport { DSLRendererPropsSchema as UIDSLRendererPropsSchema } from './dashboards/types';\nexport type { DSLRendererProps as UIDSLRendererProps } from './dashboards/types';\n\n// Query filters schema for UIs\nexport const UIQueryFiltersSchema = z.object({\n uiId: z.string().optional(),\n projectId: z.string().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n name: z.string().optional(),\n});\n\nexport type UIQueryFilters = z.infer<typeof UIQueryFiltersSchema>;\n\n// UI CRUD request payload\nexport const UIsRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n uiId: z.string().optional(),\n projectId: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n ui: UIDSLRendererPropsSchema.optional(),\n // Query operation fields\n filters: UIQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type UIsRequestPayload = z.infer<typeof UIsRequestPayloadSchema>;\n\nexport const UIsRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('UIS'),\n payload: UIsRequestPayloadSchema,\n});\n\nexport type UIsRequestMessage = z.infer<typeof UIsRequestMessageSchema>;\n\n// ==================== UI Block (Conversation History) ====================\n\n/**\n * UIBlock represents a stored conversation response with component and actions\n * Used for semantic search matching in conversation history\n */\nexport const UIBlockSchema = z.object({\n id: z.string().optional(),\n userQuestion: z.string().optional(),\n user_prompt: z.string().optional(), // DB field name\n text: z.string().optional(),\n textResponse: z.string().optional(),\n analysis: z.string().optional(), // DB field name for textResponse\n component: ComponentSchema.optional(), // DB field name / Legacy field\n generatedComponentMetadata: ComponentSchema.optional(), // Actual field used by UIBlock class\n componentData: z.record(z.any()).optional(),\n actions: z.array(z.any()).optional(),\n isFetchingActions: z.boolean().optional(),\n createdAt: z.string().optional(),\n metadata: z.object({\n timestamp: z.number().optional(),\n userPrompt: z.string().optional(),\n similarity: z.number().optional(),\n }).optional(),\n});\n\nexport type UIBlock = z.infer<typeof UIBlockSchema>;\n\n// ==================== Bookmarks CRUD Message Schemas ====================\n\n// DBUIBlock schema for database storage (matches DBUIBlock interface from conversation-saver.ts)\nexport const DBUIBlockSchema = z.object({\n id: z.string(),\n component: z.record(z.string(), z.any()).nullable(),\n analysis: z.string().nullable(),\n user_prompt: z.string(),\n});\n\n// Bookmark data schema\nexport const BookmarkDataSchema = z.object({\n id: z.number().optional(),\n uiblock: DBUIBlockSchema, // Typed JSON object\n created_at: z.string().optional(),\n updated_at: z.string().optional(),\n});\n\nexport type BookmarkData = z.infer<typeof BookmarkDataSchema>;\n\n// Query filters schema for bookmarks\nexport const BookmarkQueryFiltersSchema = z.object({\n userId: z.number().optional(),\n threadId: z.string().optional(),\n name: z.string().optional(),\n});\n\nexport type BookmarkQueryFilters = z.infer<typeof BookmarkQueryFiltersSchema>;\n\n// Bookmarks CRUD request payload\nexport const BookmarksRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'query']),\n data: z.object({\n id: z.number().optional(),\n userId: z.number().optional(),\n threadId: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n uiblock: DBUIBlockSchema.optional(),\n // Query operation fields\n filters: BookmarkQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n sort: z.enum(['ASC', 'DESC']).optional(),\n }).optional(),\n});\n\nexport type BookmarksRequestPayload = z.infer<typeof BookmarksRequestPayloadSchema>;\n\nexport const BookmarksRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('BOOKMARKS'),\n payload: BookmarksRequestPayloadSchema,\n});\n\nexport type BookmarksRequestMessage = z.infer<typeof BookmarksRequestMessageSchema>;\n\n// KB Nodes (Knowledge Base) request schema\nexport const KbNodesQueryFiltersSchema = z.object({\n query: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n createdBy: z.number().optional(),\n});\n\nexport type KbNodesQueryFilters = z.infer<typeof KbNodesQueryFiltersSchema>;\n\nexport const KbNodesRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne', 'search', 'getByCategory', 'getByUser', 'getCategories', 'getTags']),\n data: z.object({\n id: z.number().optional(),\n title: z.string().optional(),\n content: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n createdBy: z.number().optional(),\n updatedBy: z.number().optional(),\n userId: z.number().optional(),\n // Query/search operation fields\n query: z.string().optional(),\n filters: KbNodesQueryFiltersSchema.optional(),\n limit: z.number().optional(),\n offset: z.number().optional(),\n }).optional(),\n});\n\nexport type KbNodesRequestPayload = z.infer<typeof KbNodesRequestPayloadSchema>;\n\nexport const KbNodesRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('KB_NODES'),\n payload: KbNodesRequestPayloadSchema,\n});\n\nexport type KbNodesRequestMessage = z.infer<typeof KbNodesRequestMessageSchema>;\n\n// ==================== Dashboard Component Request Schema ====================\n\nexport const DashCompRequestPayloadSchema = z.object({\n prompt: z.string(),\n SA_RUNTIME: z.object({\n threadId: z.string().optional(),\n uiBlockId: z.string().optional(),\n }).optional(),\n});\n\nexport type DashCompRequestPayload = z.infer<typeof DashCompRequestPayloadSchema>;\n\nexport const DashCompRequestMessageSchema = z.object({\n id: z.string(),\n from: MessageParticipantSchema,\n type: z.literal('DASH_COMP_REQ'),\n payload: DashCompRequestPayloadSchema,\n});\n\nexport type DashCompRequestMessage = z.infer<typeof DashCompRequestMessageSchema>;\n\n// ==================== Response Types ====================\n\n// Standard response format for LLM operations\nexport interface T_RESPONSE {\n success: boolean;\n data?: any;\n errors: string[];\n}\n\nexport interface WebSocketLike {\n send(data: string): void;\n close(): void;\n addEventListener(event: string, listener: (event: any) => void): void;\n removeEventListener(event: string, listener: (event: any) => void): void;\n readyState: number;\n CONNECTING: number;\n OPEN: number;\n CLOSING: number;\n CLOSED: number;\n}\n\n","import { z } from 'zod';\n\n// ==================== Dashboard DSL Schemas ====================\n\n// Expression schema for dynamic values\nexport const ExpressionSchema = z.object({\n $exp: z.string(),\n $deps: z.array(z.string()).optional(),\n});\n\nexport type Expression = z.infer<typeof ExpressionSchema>;\n\n// Binding schema for data binding\nexport const BindingSchema = z.object({\n $bind: z.string(),\n $transform: z\n .array(\n z.object({\n name: z.string(),\n args: z.array(z.any()).optional(),\n }),\n )\n .optional(),\n});\n\nexport type Binding = z.infer<typeof BindingSchema>;\n\n// For directive schema\nexport const ForDirectiveSchema = z.object({\n in: z.union([ExpressionSchema, BindingSchema, z.string()]),\n as: z.string(),\n key: z.string().optional(),\n index: z.string().optional(),\n});\n\nexport type ForDirective = z.infer<typeof ForDirectiveSchema>;\n\n// Query specification schema\nexport const QuerySpecSchema = z.object({\n graphql: z.string().optional(),\n sql: z.string().optional(),\n variables: z.record(z.string(), z.any()).optional(),\n params: z.record(z.string(), z.any()).optional(),\n key: z.string().optional(),\n refetchPolicy: z\n .enum(['cache-first', 'network-only', 'cache-and-network'])\n .optional(),\n dependencies: z.array(z.string()).optional(),\n});\n\nexport type QuerySpec = z.infer<typeof QuerySpecSchema>;\n\n// UI Element schema\nexport const UIElementSchema: z.ZodType<any> = z.lazy(() =>\n z.object({\n id: z.string(),\n type: z.string(),\n key: z.union([z.string(), ExpressionSchema]).optional(),\n props: z.record(z.string(), z.any()).optional(),\n query: QuerySpecSchema.optional(),\n if: ExpressionSchema.optional(),\n elseIf: ExpressionSchema.optional(),\n for: ForDirectiveSchema.optional(),\n 'link-to': z\n .union([\n z.string(),\n ExpressionSchema,\n BindingSchema,\n z.object({\n ui: z.union([z.string(), ExpressionSchema, BindingSchema]),\n params: z.record(z.string(), z.any()).optional(),\n }),\n ])\n .optional(),\n _meta: z\n .object({\n id: z.string().optional(),\n version: z.string().optional(),\n created: z.string().optional(),\n lastModified: z.string().optional(),\n })\n .optional(),\n children: z.any().optional(),\n else: UIElementSchema.optional(),\n slots: z\n .record(z.string(), z.union([UIElementSchema, z.array(UIElementSchema)]))\n .optional(),\n platform: z\n .object({\n web: z.any().optional(),\n ios: z.any().optional(),\n android: z.any().optional(),\n })\n .optional(),\n })\n);\n\nexport type UIElement = z.infer<typeof UIElementSchema>;\n\n// Page schema for multi-page dashboards\nexport const PageSchema = z.object({\n id: z.string(),\n name: z.string(),\n order: z.number(),\n icon: z.string().optional(),\n render: UIElementSchema,\n});\n\nexport type Page = z.infer<typeof PageSchema>;\n\n// UI Component schema\nexport const UIComponentSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n props: z.record(z.string(), z.any()).optional(),\n states: z.record(z.string(), z.any()).optional(),\n methods: z\n .record(\n z.string(),\n z.object({\n fn: z.string(),\n params: z.record(z.string(), z.any()).optional(),\n }),\n )\n .optional(),\n effects: z\n .array(\n z.object({\n fn: z.string(),\n deps: z.array(z.string()).optional(),\n }),\n )\n .optional(),\n data: z.record(z.string(), z.any()).optional(),\n render: UIElementSchema.optional(),\n pages: z.array(PageSchema).optional(),\n defaultPageId: z.string().optional(),\n query: QuerySpecSchema.optional(),\n});\n\nexport type UIComponent = z.infer<typeof UIComponentSchema>;\n\n// DSL Renderer Props schema\nexport const DSLRendererPropsSchema = z.object({\n dsl: UIComponentSchema,\n data: z.record(z.string(), z.any()).optional(),\n context: z.record(z.string(), z.any()).optional(),\n});\n\nexport type DSLRendererProps = z.infer<typeof DSLRendererPropsSchema>;\n","import { z } from 'zod';\n\n// ==================== Report DSL Schemas ====================\n\n// Expression schema for dynamic values\nexport const ExpressionSchema = z.object({\n $exp: z.string(),\n $deps: z.array(z.string()).optional(),\n});\n\nexport type Expression = z.infer<typeof ExpressionSchema>;\n\n// Binding schema for data binding\nexport const BindingSchema = z.object({\n $bind: z.string(),\n $transform: z\n .array(\n z.object({\n name: z.string(),\n args: z.array(z.any()).optional(),\n }),\n )\n .optional(),\n});\n\nexport type Binding = z.infer<typeof BindingSchema>;\n\n// For directive schema\nexport const ForDirectiveSchema = z.object({\n in: z.union([ExpressionSchema, BindingSchema, z.string()]),\n as: z.string(),\n key: z.string().optional(),\n index: z.string().optional(),\n});\n\nexport type ForDirective = z.infer<typeof ForDirectiveSchema>;\n\n// Query specification schema\nexport const QuerySpecSchema = z.object({\n graphql: z.string().optional(),\n sql: z.string().optional(),\n variables: z.record(z.string(), z.any()).optional(),\n params: z.record(z.string(), z.any()).optional(),\n key: z.string().optional(),\n refetchPolicy: z\n .enum(['cache-first', 'network-only', 'cache-and-network'])\n .optional(),\n dependencies: z.array(z.string()).optional(),\n});\n\nexport type QuerySpec = z.infer<typeof QuerySpecSchema>;\n\n// UI Element schema\nexport const UIElementSchema: z.ZodType<any> = z.lazy(() =>\n z.object({\n id: z.string(),\n type: z.string(),\n key: z.union([z.string(), ExpressionSchema]).optional(),\n props: z.record(z.string(), z.any()).optional(),\n query: QuerySpecSchema.optional(),\n if: ExpressionSchema.optional(),\n elseIf: ExpressionSchema.optional(),\n for: ForDirectiveSchema.optional(),\n 'link-to': z\n .union([\n z.string(),\n ExpressionSchema,\n BindingSchema,\n z.object({\n ui: z.union([z.string(), ExpressionSchema, BindingSchema]),\n params: z.record(z.string(), z.any()).optional(),\n }),\n ])\n .optional(),\n _meta: z\n .object({\n id: z.string().optional(),\n version: z.string().optional(),\n created: z.string().optional(),\n lastModified: z.string().optional(),\n })\n .optional(),\n children: z.any().optional(),\n else: UIElementSchema.optional(),\n slots: z\n .record(z.string(), z.union([UIElementSchema, z.array(UIElementSchema)]))\n .optional(),\n platform: z\n .object({\n web: z.any().optional(),\n ios: z.any().optional(),\n android: z.any().optional(),\n })\n .optional(),\n })\n);\n\nexport type UIElement = z.infer<typeof UIElementSchema>;\n\n// UI Component schema\nexport const UIComponentSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n props: z.record(z.string(), z.any()).optional(),\n states: z.record(z.string(), z.any()).optional(),\n methods: z\n .record(\n z.string(),\n z.object({\n fn: z.string(),\n params: z.record(z.string(), z.any()).optional(),\n }),\n )\n .optional(),\n effects: z\n .array(\n z.object({\n fn: z.string(),\n deps: z.array(z.string()).optional(),\n }),\n )\n .optional(),\n data: z.record(z.string(), z.any()).optional(),\n render: UIElementSchema,\n query: QuerySpecSchema.optional(),\n});\n\nexport type UIComponent = z.infer<typeof UIComponentSchema>;\n\n// DSL Renderer Props schema\nexport const DSLRendererPropsSchema = z.object({\n dsl: UIComponentSchema,\n data: z.record(z.string(), z.any()).optional(),\n context: z.record(z.string(), z.any()).optional(),\n});\n\nexport type DSLRendererProps = z.infer<typeof DSLRendererPropsSchema>;\n","import { DataRequestMessageSchema, type CollectionRegistry, type Message } from '../types';\nimport { logger } from '../utils/logger';\nimport { ThreadManager } from '../threads';\n\n/**\n * Handle incoming data_req messages and execute collection handlers\n */\nexport async function handleDataRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n const dataRequest = DataRequestMessageSchema.parse(data);\n const { id, payload } = dataRequest;\n const { collection, op, params, SA_RUNTIME } = payload;\n\n // Check if collection and operation exist\n if (!collections[collection]) {\n sendDataResponse(id, collection, op, null, {\n error: `Collection '${collection}' not found`,\n }, sendMessage);\n return;\n }\n\n if (!collections[collection][op]) {\n sendDataResponse(id, collection, op, null, {\n error: `Operation '${op}' not found for collection '${collection}'`,\n }, sendMessage);\n return;\n }\n\n // Execute the handler and measure execution time\n const startTime = performance.now();\n const handler = collections[collection][op];\n const result = await handler(params || {});\n const executionMs = Math.round(performance.now() - startTime);\n\n logger.info(`Executed ${collection}.${op} in ${executionMs}ms`);\n\n // Update UIBlock with component data if SA_RUNTIME has uiBlockId\n if (SA_RUNTIME && typeof SA_RUNTIME === 'object' && 'uiBlockId' in SA_RUNTIME) {\n const uiBlockId = (SA_RUNTIME as any).uiBlockId;\n const threadId = (SA_RUNTIME as any).threadId;\n\n const threadManager = ThreadManager.getInstance();\n let uiBlock = null;\n let thread = null;\n\n // If threadId is provided, get the specific thread\n if (threadId) {\n thread = threadManager.getThread(threadId);\n if (thread) {\n uiBlock = thread.getUIBlock(uiBlockId);\n }\n } else {\n // Otherwise search across all threads\n const result = threadManager.findUIBlockById(uiBlockId);\n if (result) {\n thread = result.thread;\n uiBlock = result.uiBlock;\n }\n }\n\n // Update UIBlock's componentData with a summary (not full result) to save memory\n // The full result is sent to the frontend via WebSocket, no need to store it\n if (uiBlock) {\n // Store only metadata, not the full data to reduce memory usage\n const dataSummary = {\n _dataReceived: true,\n _timestamp: new Date().toISOString(),\n _collection: collection,\n _operation: op,\n _recordCount: Array.isArray(result) ? result.length :\n (result?.data?.length || result?.contacts?.length || result?.salesorders?.length || 'unknown')\n };\n uiBlock.setComponentData(dataSummary);\n logger.info(`Updated UIBlock ${uiBlockId} with data summary from ${collection}.${op} (full data not stored to save memory)`);\n } else {\n logger.warn(`UIBlock ${uiBlockId} not found in threads`);\n }\n }\n\n // Send response\n sendDataResponse(id, collection, op, result, { executionMs }, sendMessage);\n } catch (error) {\n logger.error('Failed to handle data request:', error);\n // Not a data_req message or invalid format\n }\n}\n\n/**\n * Send a data_res response message\n */\nfunction sendDataResponse(\n id: string,\n collection: string,\n op: string,\n data: any,\n meta: { executionMs?: number; error?: string },\n sendMessage: (message: Message) => void\n): void {\n const response: Message = {\n id,\n from: { type: 'data-agent' },\n type: 'DATA_RES',\n payload: {\n collection,\n op,\n data,\n ...meta,\n },\n };\n\n sendMessage(response);\n}\n","import { randomUUID } from 'crypto';\nimport { logger } from '../utils/logger';\nimport { STORAGE_CONFIG } from '../config/storage';\nimport { Action } from './action';\n\n/**\n * UIBlock represents a single user and assistant message block in a thread\n * Contains user question, component metadata, component data, text response, and available actions\n */\nexport class UIBlock {\n private id: string;\n private userQuestion: string;\n private generatedComponentMetadata: Record<string, any>;\n private componentData: Record<string, any>;\n private textResponse: string | null;\n private actions: Action[] | null | Promise<Action[]>;\n private createdAt: Date;\n\n /**\n * Creates a new UIBlock instance\n * @param userQuestion - The user's question or input\n * @param componentData - The component data object\n * @param generatedComponentMetadata - Optional metadata about the generated component\n * @param actions - Optional array of available actions\n * @param id - Optional custom ID, generates UUID if not provided\n * @param textResponse - Optional text response from LLM\n */\n constructor(\n userQuestion: string,\n componentData: Record<string, any> = {},\n generatedComponentMetadata: Record<string, any> = {},\n actions: Action[] = [],\n id?: string,\n textResponse: string | null = null\n ) {\n this.id = id || randomUUID();\n this.userQuestion = userQuestion;\n this.componentData = componentData;\n this.generatedComponentMetadata = generatedComponentMetadata;\n this.actions = actions;\n this.textResponse = textResponse;\n this.createdAt = new Date();\n }\n\n /**\n * Get the UIBlock ID\n */\n getId(): string {\n return this.id;\n }\n\n /**\n * Get the user question\n */\n getUserQuestion(): string {\n return this.userQuestion;\n }\n\n /**\n * Set or update the user question\n */\n setUserQuestion(question: string): void {\n this.userQuestion = question;\n }\n\n /**\n * Get component metadata\n */\n getComponentMetadata(): Record<string, any> {\n return this.generatedComponentMetadata;\n }\n\n getTextResponse(): string {\n return this.textResponse || '';\n }\n\n /**\n * Set or update component metadata\n */\n setComponentMetadata(metadata: Record<string, any>): void {\n this.generatedComponentMetadata = { ...this.generatedComponentMetadata, ...metadata };\n }\n\n /**\n * Get component data\n */\n getComponentData(): Record<string, any> {\n return this.componentData;\n }\n\n /**\n * Calculate size of data in bytes\n */\n private getDataSizeInBytes(data: any): number {\n try {\n const jsonString = JSON.stringify(data);\n return Buffer.byteLength(jsonString, 'utf8');\n } catch (error) {\n logger.error('Error calculating data size:', error);\n return 0;\n }\n }\n\n /**\n * Limit array data to maximum rows\n */\n private limitArrayData(data: any[]): { data: any[]; metadata: any } {\n const totalRows = data.length;\n const limitedData = data.slice(0, STORAGE_CONFIG.MAX_ROWS_PER_BLOCK);\n\n return {\n data: limitedData,\n metadata: {\n totalRows,\n storedRows: limitedData.length,\n isTruncated: totalRows > STORAGE_CONFIG.MAX_ROWS_PER_BLOCK,\n },\n };\n }\n\n /**\n * Check if data exceeds size limit\n */\n private exceedsSizeLimit(data: any): boolean {\n const size = this.getDataSizeInBytes(data);\n return size > STORAGE_CONFIG.MAX_SIZE_PER_BLOCK_BYTES;\n }\n\n /**\n * Process and limit data before storing\n */\n private processDataForStorage(data: any): any {\n // If data is an array, limit rows\n if (Array.isArray(data)) {\n const { data: limitedData, metadata } = this.limitArrayData(data);\n\n // Check size after limiting rows\n const size = this.getDataSizeInBytes(limitedData);\n\n logger.info(\n `UIBlock ${this.id}: Storing ${metadata.storedRows}/${metadata.totalRows} rows (${(size / 1024).toFixed(2)} KB)`\n );\n\n // If still too large, store only metadata\n if (this.exceedsSizeLimit(limitedData)) {\n logger.warn(\n `UIBlock ${this.id}: Data too large (${(size / 1024 / 1024).toFixed(2)} MB), storing metadata only`\n );\n return {\n ...metadata,\n preview: limitedData.slice(0, 3), // Store only first 3 rows as preview\n dataTooLarge: true,\n };\n }\n\n return {\n data: limitedData,\n ...metadata,\n };\n }\n\n // For non-array data, check size\n const size = this.getDataSizeInBytes(data);\n\n if (this.exceedsSizeLimit(data)) {\n logger.warn(\n `UIBlock ${this.id}: Data too large (${(size / 1024 / 1024).toFixed(2)} MB), storing summary only`\n );\n return {\n dataTooLarge: true,\n dataType: typeof data,\n keys: typeof data === 'object' ? Object.keys(data) : undefined,\n };\n }\n\n return data;\n }\n\n /**\n * Set or update component data with size and row limits\n */\n setComponentData(data: Record<string, any>): void {\n const processedData = this.processDataForStorage(data);\n this.componentData = { ...this.componentData, ...processedData };\n }\n\n\n\n /**\n * Set or update text response\n */\n setTextResponse(textResponse: string | null): void {\n this.textResponse = textResponse;\n }\n\n /**\n * Get all actions (only if they are resolved, not if fetching)\n */\n getActions(): Action[] | null | Promise<Action[]> {\n return this.actions;\n }\n\n /**\n * Get or fetch actions\n * If actions don't exist or are a Promise, calls the generateFn and stores the promise\n * If actions already exist, returns them\n * @param generateFn - Async function to generate actions\n * @returns Promise resolving to Action[]\n */\n async getOrFetchActions(generateFn: () => Promise<Action[]>): Promise<Action[]> {\n // If actions already exist and are not a Promise, return them\n\n if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions) && this.actions.length > 0) {\n return this.actions;\n }\n\n // If already fetching, cancel and start new fetch\n // Set new promise for fetching\n const fetchPromise = generateFn();\n this.actions = fetchPromise;\n\n try {\n // Wait for the promise to resolve\n const resolvedActions = await fetchPromise;\n // Store the resolved actions\n logger.info(`Fetched ${resolvedActions.length} actions for UIBlock: ${this.id}`);\n this.actions = resolvedActions;\n return resolvedActions;\n } catch (error) {\n // If generation fails, reset to null\n this.actions = null;\n throw error;\n }\n }\n\n /**\n * Set or replace all actions\n */\n setActions(actions: Action[]): void {\n this.actions = actions;\n }\n\n /**\n * Add a single action (only if actions are resolved)\n */\n addAction(action: Action): void {\n if (this.actions && Array.isArray(this.actions)) {\n this.actions.push(action);\n }\n }\n\n /**\n * Add multiple actions (only if actions are resolved)\n */\n addActions(actions: Action[]): void {\n if (this.actions && Array.isArray(this.actions)) {\n this.actions.push(...actions);\n }\n }\n\n /**\n * Remove an action by ID (only if actions are resolved)\n */\n removeAction(actionId: string): boolean {\n if (this.actions && Array.isArray(this.actions)) {\n const index = this.actions.findIndex(a => a.id === actionId);\n if (index > -1) {\n this.actions.splice(index, 1);\n return true;\n }\n }\n return false;\n }\n\n /**\n * Clear all actions\n */\n clearActions(): void {\n this.actions = null;\n }\n\n /**\n * Get creation timestamp\n */\n getCreatedAt(): Date {\n return this.createdAt;\n }\n\n /**\n * Convert UIBlock to JSON-serializable object\n */\n toJSON(): Record<string, any> {\n // Handle Promise case for serialization\n let actionsValue: Action[] | null = null;\n if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions)) {\n actionsValue = this.actions;\n }\n\n return {\n id: this.id,\n userQuestion: this.userQuestion,\n generatedComponentMetadata: this.generatedComponentMetadata,\n componentData: this.componentData,\n textResponse: this.textResponse,\n actions: actionsValue,\n isFetchingActions: this.actions instanceof Promise,\n createdAt: this.createdAt.toISOString(),\n };\n }\n}\n","/**\n * Configuration for data storage limits in UIBlocks\n */\nexport const STORAGE_CONFIG = {\n /**\n * Maximum number of rows to store in UIBlock data\n */\n MAX_ROWS_PER_BLOCK: 10,\n\n /**\n * Maximum size in bytes per UIBlock (500KB - reduced to save memory)\n */\n MAX_SIZE_PER_BLOCK_BYTES: 500 * 1024, // 500KB\n\n /**\n * Number of days to keep threads before cleanup\n * Note: This is for in-memory storage. Conversations are also persisted to database.\n */\n THREAD_RETENTION_DAYS: 2, // Reduced from 7 to 1 day for memory efficiency\n\n /**\n * Number of days to keep UIBlocks before cleanup\n * Note: This is for in-memory storage. Data is also persisted to database.\n */\n UIBLOCK_RETENTION_DAYS: 2, // Reduced from 7 to 1 day for memory efficiency\n};\n","import { randomUUID } from 'crypto';\nimport { UIBlock } from './uiblock';\n\n/**\n * Thread represents a conversation thread containing multiple UIBlocks\n * Each UIBlock in a thread represents a user question and assistant response pair\n */\nexport class Thread {\n private id: string;\n private uiblocks: Map<string, UIBlock>;\n private createdAt: Date;\n\n /**\n * Creates a new Thread instance\n * @param id - Optional custom ID, generates UUID if not provided\n */\n constructor(id?: string) {\n this.id = id || randomUUID();\n this.uiblocks = new Map();\n this.createdAt = new Date();\n }\n\n /**\n * Get the thread ID\n */\n getId(): string {\n return this.id;\n }\n\n /**\n * Add a UIBlock to the thread\n */\n addUIBlock(uiblock: UIBlock): void {\n this.uiblocks.set(uiblock.getId(), uiblock);\n }\n\n /**\n * Get a UIBlock by ID\n */\n getUIBlock(id: string): UIBlock | undefined {\n return this.uiblocks.get(id);\n }\n\n /**\n * Get all UIBlocks in the thread\n */\n getUIBlocks(): UIBlock[] {\n return Array.from(this.uiblocks.values());\n }\n\n /**\n * Get UIBlocks as a Map\n */\n getUIBlocksMap(): Map<string, UIBlock> {\n return new Map(this.uiblocks);\n }\n\n /**\n * Remove a UIBlock by ID\n */\n removeUIBlock(id: string): boolean {\n return this.uiblocks.delete(id);\n }\n\n /**\n * Check if UIBlock exists\n */\n hasUIBlock(id: string): boolean {\n return this.uiblocks.has(id);\n }\n\n /**\n * Get number of UIBlocks in the thread\n */\n getUIBlockCount(): number {\n return this.uiblocks.size;\n }\n\n /**\n * Clear all UIBlocks from the thread\n */\n clear(): void {\n this.uiblocks.clear();\n }\n\n /**\n * Get creation timestamp\n */\n getCreatedAt(): Date {\n return this.createdAt;\n }\n\n /**\n * Get conversation context from recent UIBlocks (excluding current one)\n * Returns formatted string with previous questions and component summaries\n * @param limit - Maximum number of previous UIBlocks to include (default: 5)\n * @param currentUIBlockId - ID of current UIBlock to exclude from context (optional)\n * @returns Formatted conversation history string\n */\n getConversationContext(limit: number = 5, currentUIBlockId?: string): string {\n if (limit === 0) {\n return '';\n }\n\n // Get all UIBlocks sorted by creation time (oldest first)\n const allBlocks = Array.from(this.uiblocks.values())\n .filter(block => !currentUIBlockId || block.getId() !== currentUIBlockId)\n .sort((a, b) => a.getCreatedAt().getTime() - b.getCreatedAt().getTime());\n\n if (allBlocks.length === 0) {\n return '';\n }\n\n // Take the last N blocks (most recent)\n const recentBlocks = allBlocks.slice(-limit);\n\n // Format as conversation history\n const contextLines: string[] = [];\n\n recentBlocks.forEach((block, index) => {\n const questionNum = index + 1;\n const question = block.getUserQuestion();\n const metadata = block.getComponentMetadata();\n const textResponse = block.getTextResponse();\n\n // Determine what was generated and build appropriate response\n let assistantResponse = '';\n\n // Check if component was generated (metadata exists and has meaningful content)\n const hasComponent = metadata && Object.keys(metadata).length > 0 && metadata.type;\n\n // Check if text response was generated\n const hasTextResponse = textResponse && textResponse.trim().length > 0;\n\n const responseParts: string[] = [];\n\n if (hasComponent) {\n // Component was generated - show component summary\n const parts: string[] = [];\n\n if (metadata.type) {\n parts.push(`Component Type: ${metadata.type}`);\n }\n if (metadata.name) {\n parts.push(`Name: ${metadata.name}`);\n }\n if (metadata.description) {\n parts.push(`Description: ${metadata.description}`);\n }\n if (metadata.props) {\n parts.push(`Props: ${JSON.stringify(metadata.props)}`);\n }\n\n responseParts.push(parts.join('\\n'));\n }\n\n if (hasTextResponse) {\n // Text response was generated - add it to response parts\n responseParts.push(textResponse);\n }\n\n if (responseParts.length > 0) {\n // Join both component and text response if both exist\n assistantResponse = responseParts.join('\\n');\n } else {\n // Nothing was generated\n assistantResponse = 'No response generated';\n }\n\n contextLines.push(`User:\\n ${question}`);\n contextLines.push(`Assistant:\\n ${assistantResponse}`);\n contextLines.push('---'); // Empty line for readability\n });\n\n return contextLines.join('\\n').trim();\n }\n\n /**\n * Convert Thread to JSON-serializable object\n */\n toJSON(): Record<string, any> {\n return {\n id: this.id,\n uiblocks: Array.from(this.uiblocks.values()).map(block => block.toJSON()),\n createdAt: this.createdAt.toISOString(),\n };\n }\n}\n","import { Thread } from './thread';\nimport { UIBlock } from './uiblock';\n\n/**\n * ThreadManager manages all threads globally\n * Provides methods to create, retrieve, and delete threads\n */\nexport class ThreadManager {\n private static instance: ThreadManager;\n private threads: Map<string, Thread>;\n\n private constructor() {\n this.threads = new Map();\n\n // Initialize cleanup service\n // new CleanupService(this.threads);\n }\n\n /**\n * Get singleton instance of ThreadManager\n */\n static getInstance(): ThreadManager {\n if (!ThreadManager.instance) {\n ThreadManager.instance = new ThreadManager();\n }\n return ThreadManager.instance;\n }\n\n /**\n * Create a new thread\n * @param id - Optional custom ID, generates UUID if not provided\n * @returns The created Thread instance\n */\n createThread(id?: string): Thread {\n const thread = new Thread(id);\n this.threads.set(thread.getId(), thread);\n return thread;\n }\n\n /**\n * Get a thread by ID\n */\n getThread(id: string): Thread | undefined {\n return this.threads.get(id);\n }\n\n /**\n * Get all threads\n */\n getAllThreads(): Thread[] {\n return Array.from(this.threads.values());\n }\n\n /**\n * Get threads as a Map\n */\n getThreadsMap(): Map<string, Thread> {\n return new Map(this.threads);\n }\n\n /**\n * Delete a thread by ID\n */\n deleteThread(id: string): boolean {\n return this.threads.delete(id);\n }\n\n /**\n * Check if thread exists\n */\n hasThread(id: string): boolean {\n return this.threads.has(id);\n }\n\n /**\n * Get number of threads\n */\n getThreadCount(): number {\n return this.threads.size;\n }\n\n /**\n * Clear all threads\n */\n clearAll(): void {\n this.threads.clear();\n }\n\n /**\n * Find a UIBlock by ID across all threads\n * @param uiBlockId - The UIBlock ID to search for\n * @returns Object with thread and uiBlock if found, undefined otherwise\n */\n findUIBlockById(uiBlockId: string): { thread: Thread; uiBlock: UIBlock } | undefined {\n for (const thread of this.threads.values()) {\n const uiBlock = thread.getUIBlock(uiBlockId);\n if (uiBlock) {\n return { thread, uiBlock };\n }\n }\n return undefined;\n }\n\n /**\n * Convert all threads to JSON-serializable object\n */\n toJSON(): Record<string, any> {\n return {\n threads: Array.from(this.threads.values()).map(thread => thread.toJSON()),\n count: this.threads.size,\n };\n }\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { logger } from './utils/logger';\n\n/**\n * Get the bundle directory from config or environment variable\n */\nexport function getBundleDir(configDir?: string): string {\n const bundleDir = configDir || process.env.SA_BUNDLE_DIR;\n\n if (!bundleDir) {\n throw new Error(\n 'Bundle directory not configured. Please provide bundleDir in config or set SA_BUNDLE_DIR environment variable.'\n );\n }\n\n return bundleDir;\n}\n\n/**\n * Load the JavaScript bundle from the configured directory\n */\nexport function getJS(bundleDir: string): string {\n try {\n // Check if directory exists\n if (!fs.existsSync(bundleDir)) {\n throw new Error(`Bundle directory does not exist: ${bundleDir}`);\n }\n\n // Check if it's actually a directory\n const stats = fs.statSync(bundleDir);\n if (!stats.isDirectory()) {\n throw new Error(`Bundle path is not a directory: ${bundleDir}`);\n }\n\n // Read directory contents\n let files: string[];\n try {\n files = fs.readdirSync(bundleDir);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read bundle directory: ${errorMessage}`);\n }\n\n // Find the bundle file\n const indexFile = files.find((file) => file.startsWith('index-') && file.endsWith('.js'));\n\n if (!indexFile) {\n logger.warn(`Available files in ${bundleDir}:`, files);\n throw new Error(\n `Could not find index-*.js file in ${bundleDir}. ` +\n `Expected a file matching pattern: index-*.js`\n );\n }\n\n // Read the bundle file\n const filePath = path.join(bundleDir, indexFile);\n logger.info(`Loading bundle from ${filePath}`);\n\n try {\n return fs.readFileSync(filePath, 'utf8');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read bundle file: ${errorMessage}`);\n }\n } catch (error) {\n if (error instanceof Error) {\n logger.error('Failed to load bundle:', error.message);\n } else {\n logger.error('Failed to load bundle:', error);\n }\n throw error;\n }\n}\n","import { getJS, getBundleDir } from '../bundle';\nimport { logger } from '../utils/logger';\nimport type { Message } from '../types';\n\nconst CHUNK_SIZE = 900 * 1024; // 900 KB chunks (leaving room for metadata, max 1MB per message)\n\n/**\n * Handle incoming bundle_req messages and send chunked bundle response\n */\nexport async function handleBundleRequest(\n data: any,\n bundleDir: string | undefined,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n const id = data.id || 'unknown';\n const fromId = data.from?.id;\n\n // Get bundle directory and load bundle\n const dir = getBundleDir(bundleDir);\n const js = getJS(dir);\n const bundleSize = Buffer.byteLength(js, 'utf8');\n\n logger.info(`Bundle size: ${(bundleSize / 1024).toFixed(2)} KB`);\n\n // Split bundle into chunks\n const totalChunks = Math.ceil(bundleSize / CHUNK_SIZE);\n logger.info(`Splitting bundle into ${totalChunks} chunks`);\n\n for (let i = 0; i < totalChunks; i++) {\n const start = i * CHUNK_SIZE;\n const end = Math.min(start + CHUNK_SIZE, js.length);\n const chunk = js.substring(start, end);\n const isComplete = i === totalChunks - 1;\n const progress = ((i + 1) / totalChunks) * 100;\n\n const chunkMessage: Message = {\n id: `${id}-chunk-${i}`,\n type: 'BUNDLE_CHUNK',\n from: { type: 'data-agent' },\n to: fromId ? { id: fromId } : undefined,\n payload: {\n chunk: chunk,\n chunkIndex: i,\n totalChunks: totalChunks,\n isComplete: isComplete,\n progress: parseFloat(progress.toFixed(2)),\n },\n };\n\n sendMessage(chunkMessage);\n logger.debug(`Sent chunk ${i + 1}/${totalChunks} (${progress.toFixed(2)}%)`);\n }\n\n logger.info('Bundle sending complete');\n } catch (error) {\n logger.error('Failed to handle bundle request:', error);\n\n // Send error response\n const errorMessage: Message = {\n id: data.id || 'unknown',\n type: 'BUNDLE_RES',\n from: { type: 'data-agent' },\n to: data.from?.id ? { id: data.from.id } : undefined,\n payload: {\n error: error instanceof Error ? error.message : 'Unknown error',\n },\n };\n\n sendMessage(errorMessage);\n }\n}\n","import crypto from 'crypto';\n\n/**\n * Decode base64 encoded string and parse JSON\n * @param base64Data - Base64 encoded string\n * @returns Parsed JSON object\n */\nexport function decodeBase64ToJson(base64Data: string): any {\n try {\n const decodedString = Buffer.from(base64Data, 'base64').toString('utf-8');\n return JSON.parse(decodedString);\n } catch (error) {\n throw new Error(`Failed to decode base64 data: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\n/**\n * Hash password using SHA1\n * @param password - Plain text password\n * @returns SHA1 hashed password\n */\nexport function hashPassword(password: string): string {\n return crypto.createHash('sha1').update(password).digest('hex');\n}\n","import { UserManager } from './user-manager';\nimport { type User, type UsersData } from '../types';\nimport { logger } from '../utils/logger';\n\n// Global reference to the current SDK's UserManager instance\nlet currentUserManager: UserManager | null = null;\n\n/**\n * Set the UserManager instance (called by SuperatomSDK during initialization)\n * This should be called with the SDK's UserManager instance\n * @param userManager - UserManager instance from SuperatomSDK\n */\nexport function setUserManager(userManager: UserManager): void {\n if (!userManager) {\n throw new Error('userManager cannot be null');\n }\n currentUserManager = userManager;\n logger.debug('UserManager instance set');\n}\n\n/**\n * Get the current UserManager instance\n */\nexport function getUserManager(): UserManager {\n if (!currentUserManager) {\n throw new Error(\n 'UserManager not initialized. Make sure SuperatomSDK is initialized before using user storage.'\n );\n }\n return currentUserManager;\n}\n\n/**\n * Load users from memory (UserManager maintains the cache)\n * @returns UsersData object containing all users\n */\nexport function loadUsers(): UsersData {\n const manager = getUserManager();\n return {\n users: manager.getAllUsers()\n };\n}\n\n/**\n * Save users to file immediately (forces sync)\n * @param usersData - UsersData object to save\n */\nexport async function saveUsers(usersData: UsersData): Promise<void> {\n const manager = getUserManager();\n\n // Clear existing users and repopulate\n manager.deleteAllUsers();\n\n // Add all users from the provided data\n for (const user of usersData.users) {\n try {\n manager.createUser(user);\n } catch (error) {\n // User might already exist, update instead\n if (manager.userExists(user.username)) {\n manager.updateUser(user.username, user);\n }\n }\n }\n\n // Force immediate sync to file\n await manager.forceSync();\n}\n\n/**\n * Find a user by username\n * @param username - Username to search for\n * @returns User object if found, null otherwise\n */\nexport function findUserByUsername(username: string): User | null {\n const manager = getUserManager();\n const user = manager.getUser(username);\n return user || null;\n}\n\n/**\n * Find a user by email\n * @param email - Email to search for\n * @returns User object if found, null otherwise\n */\nexport function findUserByEmail(email: string): User | null {\n const manager = getUserManager();\n const user = manager.getUserByEmail(email);\n return user || null;\n}\n\n/**\n * Find a user by username or email\n * @param identifier - Username or email to search for\n * @returns User object if found, null otherwise\n */\nexport function findUserByUsernameOrEmail(identifier: string): User | null {\n const manager = getUserManager();\n const user = manager.getUserByUsernameOrEmail(identifier);\n return user || null;\n}\n\n/**\n * Add WebSocket ID to a user's wsIds array\n * @param username - Username to update\n * @param wsId - WebSocket ID to add\n * @returns true if successful, false otherwise\n */\nexport function addWsIdToUser(username: string, wsId: string): boolean {\n try {\n const manager = getUserManager();\n return manager.addWsId(username, wsId);\n } catch (error) {\n logger.error('Error adding WebSocket ID:', error);\n return false;\n }\n}\n\n/**\n * Remove WebSocket ID from a user's wsIds array\n * @param username - Username to update\n * @param wsId - WebSocket ID to remove\n * @returns true if successful, false otherwise\n */\nexport function removeWsIdFromUser(username: string, wsId: string): boolean {\n try {\n const manager = getUserManager();\n return manager.removeWsId(username, wsId);\n } catch (error) {\n logger.error('Error removing WebSocket ID:', error);\n return false;\n }\n}\n\n/**\n * Cleanup and destroy the UserManager\n */\nexport async function cleanupUserStorage(): Promise<void> {\n if (currentUserManager) {\n await currentUserManager.destroy();\n currentUserManager = null;\n logger.info('UserManager cleaned up');\n }\n}\n\n// Export types\nexport type { User, UsersData } from '../types';\n","import { findUserByUsernameOrEmail, addWsIdToUser } from \"./user-storage\";\nimport { hashPassword } from \"./utils\";\nimport { logger } from \"../utils/logger\";\nimport type { CollectionRegistry } from \"../types\";\n\nexport interface LoginCredentials {\n username?: string;\n email?: string;\n password: string;\n}\n\nexport interface ValidationResult {\n success: boolean;\n error?: string;\n data?: any;\n username?: string;\n userId?: number;\n}\n\n/**\n * Validate user credentials against database first, then file storage as fallback\n * @param credentials - Login credentials with username/email and password\n * @param collections - Optional collection registry for database lookup\n * @returns ValidationResult indicating success or failure\n */\nexport async function validateUser(\n credentials: LoginCredentials,\n collections?: CollectionRegistry\n): Promise<ValidationResult> {\n const { username, email, password } = credentials;\n const identifier = username || email;\n\n logger.debug('[validateUser] Starting user validation');\n logger.debug(`[validateUser] Username provided: ${username ? '✓' : '✗'}, Email provided: ${email ? '✓' : '✗'}, Password provided: ${password ? '✓' : '✗'}`);\n\n // Check if identifier (username or email) and password are provided\n if (!identifier || !password) {\n logger.warn('[validateUser] Validation failed: Username/email and password are required');\n return {\n success: false,\n error: 'Username or email and password are required'\n };\n }\n\n // Try database lookup first if collections are available\n if (collections && collections['users'] && collections['users']['authenticate']) {\n logger.debug(`[validateUser] Attempting database authentication for: ${identifier}`);\n try {\n const dbResult = await collections['users']['authenticate']({\n identifier,\n password\n });\n\n logger.info('[validateUser] Database authentication attempt completed', dbResult);\n\n if (dbResult && dbResult.success && dbResult.data) {\n logger.info(`[validateUser] ✓ User authenticated via database: ${dbResult.data.username}`);\n return {\n success: true,\n data: dbResult.data.username,\n username: dbResult.data.username,\n userId: dbResult.data.id\n };\n } else {\n logger.debug(`[validateUser] Database auth failed for ${identifier}: ${dbResult?.error || 'Invalid credentials'}`);\n // Don't fall back to file if DB explicitly says invalid credentials\n if (dbResult && dbResult.error === 'Invalid credentials') {\n return {\n success: false,\n error: 'Invalid credentials'\n };\n }\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.debug(`[validateUser] Database lookup error: ${errorMsg}, falling back to file storage`);\n }\n } else {\n logger.debug('[validateUser] No users collection available, using file storage only');\n }\n\n // Fall back to file-based validation\n logger.info(`[validateUser] Attempting file-based validation for: ${identifier}`);\n\n // Find user by username or email from in-memory cache\n const user = findUserByUsernameOrEmail(identifier);\n\n if (!user) {\n logger.warn(`[validateUser] Validation failed: User not found - ${identifier}`);\n return {\n success: false,\n error: 'Invalid username or email'\n };\n }\n\n logger.debug(`[validateUser] User found in file storage: ${user.username}, verifying password`);\n\n // Hash the stored password and compare with provided password\n const hashedPassword = hashPassword(user.password);\n\n if (hashedPassword !== password) {\n logger.warn(`[validateUser] Validation failed: Invalid password for user - ${user.username}`);\n logger.debug(`[validateUser] Password hash mismatch for user: ${user.username}`);\n return {\n success: false,\n error: 'Invalid password'\n };\n }\n\n logger.info(`[validateUser] ✓ User validated via file storage: ${user.username}`);\n return {\n success: true,\n data: user.username,\n username: user.username\n };\n}\n\n/**\n * Authenticate user and store WebSocket ID\n * Uses database first via collections, then falls back to file storage\n * @param credentials - Login credentials\n * @param wsId - WebSocket ID to store\n * @param collections - Optional collection registry for database lookup\n * @returns ValidationResult with authentication status\n */\nexport async function authenticateAndStoreWsId(\n credentials: LoginCredentials,\n wsId: string,\n collections?: CollectionRegistry\n): Promise<ValidationResult> {\n const identifier = credentials.username || credentials.email;\n logger.debug('[authenticateAndStoreWsId] Starting authentication and WebSocket ID storage');\n\n // Validate user credentials first\n logger.debug('[authenticateAndStoreWsId] Validating user credentials');\n const validationResult = await validateUser(credentials, collections);\n\n if (!validationResult.success) {\n logger.warn(`[authenticateAndStoreWsId] User validation failed for: ${identifier}`);\n return validationResult;\n }\n\n // Use the username from validation result (guaranteed to exist if validation succeeded)\n const username = validationResult.username!;\n logger.info(`[authenticateAndStoreWsId] User ${username} validated, storing WebSocket ID`);\n\n // Store wsId in user's wsIds array using UserManager\n // Changes are automatically synced to file via setInterval\n logger.debug(`[authenticateAndStoreWsId] Calling addWsIdToUser for ${username}`);\n addWsIdToUser(username, wsId);\n\n logger.debug(`[authenticateAndStoreWsId] WebSocket ID ${wsId} associated with user ${username}`);\n return validationResult;\n}\n\n/**\n * Verify authentication token\n * @param authToken - Base64 encoded auth token containing username and password\n * @param collections - Optional collection registry for database lookup\n * @returns ValidationResult indicating if token is valid\n */\nexport async function verifyAuthToken(\n authToken: string,\n collections?: CollectionRegistry\n): Promise<ValidationResult> {\n try {\n logger.debug('[verifyAuthToken] Starting token verification');\n\n // Decode base64 token\n logger.debug('[verifyAuthToken] Decoding base64 token');\n const decodedString = Buffer.from(authToken, 'base64').toString('utf-8');\n\n logger.debug('[verifyAuthToken] Parsing decoded token as JSON');\n const credentials = JSON.parse(decodedString);\n\n logger.debug('[verifyAuthToken] Token decoded and parsed successfully');\n logger.debug(`[verifyAuthToken] Token contains username: ${credentials.username ? '✓' : '✗'}`);\n\n // Validate credentials\n logger.debug('[verifyAuthToken] Validating credentials from token');\n const result = await validateUser(credentials, collections);\n\n if (result.success) {\n logger.info(`[verifyAuthToken] ✓ Token verified successfully for user: ${credentials.username || 'unknown'}`);\n } else {\n logger.warn(`[verifyAuthToken] Token verification failed: ${result.error}`);\n }\n\n return result;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(`[verifyAuthToken] Failed to verify auth token: ${errorMsg}`);\n logger.debug('[verifyAuthToken] Token verification error details:', error);\n\n return {\n success: false,\n error: 'Invalid token format'\n };\n }\n}\n","import { decodeBase64ToJson } from \"../auth/utils\";\nimport { authenticateAndStoreWsId } from \"../auth/validator\";\nimport { AuthLoginRequestMessageSchema, Message, CollectionRegistry } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\n\nexport async function handleAuthLoginRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n logger.debug('[AUTH_LOGIN_REQ] Parsing incoming auth login request');\n const authRequest = AuthLoginRequestMessageSchema.parse(data);\n const { id, payload } = authRequest;\n\n const login_data = payload.login_data;\n\n const wsId = authRequest.from.id ;\n\n logger.info(`[AUTH_LOGIN_REQ ${id}] Processing auth login request from client: ${wsId}`);\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Login data present: ${!!login_data}`);\n\n if(!login_data){\n logger.error(`[AUTH_LOGIN_REQ ${id}] Login data not found in request`);\n sendDataResponse(id, {\n success: false,\n error: 'Login data not found'\n }, sendMessage, wsId);\n return;\n }\n\n\n // Decode base64 data and parse JSON\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Decoding base64 login data`);\n let loginData: any;\n try {\n loginData = decodeBase64ToJson(login_data);\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Login data decoded successfully`);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(`[AUTH_LOGIN_REQ ${id}] Failed to decode login data: ${errorMsg}`);\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Decode error details:`, error);\n sendDataResponse(id, {\n success: false,\n error: 'Invalid login data format'\n }, sendMessage, wsId);\n return;\n }\n\n // Extract username/email and password from decoded data\n const { username, email, password } = loginData;\n const identifier = username || email;\n\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Validating credentials - username: ${username ? '✓' : '✗'}, email: ${email ? '✓' : '✗'}, password: ${password ? '✓' : '✗'}`);\n\n if (!identifier) {\n logger.error(`[AUTH_LOGIN_REQ ${id}] Username or email not found in login data`);\n sendDataResponse(id, {\n success: false,\n error: 'Username or email is required'\n }, sendMessage, wsId);\n return;\n }\n\n if (!password) {\n logger.error(`[AUTH_LOGIN_REQ ${id}] Password not found in login data`);\n sendDataResponse(id, {\n success: false,\n error: 'Password not found in login data'\n }, sendMessage, wsId);\n return;\n }\n\n\n if(!wsId){\n logger.error(`[AUTH_LOGIN_REQ ${id}] WebSocket ID not found in request`);\n sendDataResponse(id, {\n success: false,\n error: 'WebSocket ID not found'\n }, sendMessage, wsId);\n return;\n }\n\n logger.info(`[AUTH_LOGIN_REQ ${id}] Credentials validated, authenticating user: ${identifier} username: ${username} email: ${email} password: ${password}`);\n\n // Authenticate user and store wsId\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Calling authenticateAndStoreWsId for user: ${identifier}`);\n const authResult = await authenticateAndStoreWsId(\n { username, email, password },\n wsId,\n collections\n );\n\n logger.info(`[AUTH_LOGIN_REQ ${id}] Authentication result for ${identifier}: ${authResult.success ? 'success' : 'failed'}`);\n if (!authResult.success) {\n logger.warn(`[AUTH_LOGIN_REQ ${id}] Authentication failed for ${identifier}: ${authResult.error}`);\n } else {\n logger.info(`[AUTH_LOGIN_REQ ${id}] User ${authResult.username || identifier} authenticated successfully`);\n }\n\n // Send response\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Sending auth response to client`);\n sendDataResponse(id, authResult, sendMessage, wsId);\n\n logger.info(`[AUTH_LOGIN_REQ ${id}] ${authResult.success ? '✓' : '✗'} Auth login request completed`);\n return ;\n }\n catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n logger.error(`[AUTH_LOGIN_REQ] Failed to handle auth login request: ${errorMessage}`);\n logger.debug(`[AUTH_LOGIN_REQ] Error stack trace:`, errorStack);\n\n // Try to send error response\n try {\n const parsedData = data as any;\n if (parsedData?.id) {\n sendDataResponse(parsedData.id, {\n success: false,\n error: `Internal error: ${errorMessage}`\n }, sendMessage, parsedData.from?.id);\n }\n } catch (sendError) {\n logger.error('[AUTH_LOGIN_REQ] Failed to send error response:', sendError);\n }\n }\n}\n\n\n/**\n * Send a data_res response message\n */\nfunction sendDataResponse(\n id: string,\n res: {success: boolean; error?: string; data?: any},\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id,\n type: 'AUTH_LOGIN_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: clientId\n },\n payload:{\n ...res,\n }\n };\n\n logger.debug(`[AUTH_LOGIN_RES ${id}] Sending ${res.success ? 'successful' : 'failed'} auth response to client: ${clientId}`);\n logger.debug(`[AUTH_LOGIN_RES ${id}] Response payload size: ${JSON.stringify(response).length} bytes`);\n\n if (res.error) {\n logger.debug(`[AUTH_LOGIN_RES ${id}] Error message: ${res.error}`);\n }\n\n sendMessage(response);\n}\n\n","import { verifyAuthToken } from \"../auth/validator\";\nimport { AuthVerifyRequestMessageSchema, Message, CollectionRegistry } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\nexport async function handleAuthVerifyRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n logger.debug('[AUTH_VERIFY_REQ] Parsing incoming auth verify request');\n const authRequest = AuthVerifyRequestMessageSchema.parse(data);\n const { id, payload } = authRequest;\n\n const token = payload.token;\n\n const wsId = authRequest.from.id ;\n\n logger.info(`[AUTH_VERIFY_REQ ${id}] Processing auth verify request from client: ${wsId}`);\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Token present: ${!!token}`);\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Token length: ${token ? token.length : 0} characters`);\n\n if(!token){\n logger.error(`[AUTH_VERIFY_REQ ${id}] Token not found in request`);\n sendDataResponse(id, {\n success: false,\n error: 'Token not found'\n }, sendMessage, wsId);\n return;\n }\n\n\n if(!wsId){\n logger.error(`[AUTH_VERIFY_REQ ${id}] WebSocket ID not found in request`);\n sendDataResponse(id, {\n success: false,\n error: 'WebSocket ID not found'\n }, sendMessage, wsId);\n return;\n }\n\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token validation starting`);\n logger.debug(`[AUTH_VERIFY_REQ ${id}] WebSocket ID: ${wsId}`);\n\n // Verify token\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Calling verifyAuthToken`);\n const startTime = Date.now();\n\n const authResult = await verifyAuthToken(token, collections);\n\n const verificationTime = Date.now() - startTime;\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token verification completed in ${verificationTime}ms - ${authResult.success ? 'valid' : 'invalid'}`);\n\n if (!authResult.success) {\n logger.warn(`[AUTH_VERIFY_REQ ${id}] Token verification failed: ${authResult.error}`);\n } else {\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token verified successfully for user: ${authResult.data || 'unknown'}`);\n }\n\n // Send response\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Sending verification response to client`);\n sendDataResponse(id, authResult, sendMessage, wsId);\n\n logger.info(`[AUTH_VERIFY_REQ ${id}] ${authResult.success ? '✓' : '✗'} Auth verify request completed`);\n return ;\n }\n catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n logger.error(`[AUTH_VERIFY_REQ] Failed to handle auth verify request: ${errorMessage}`);\n logger.debug(`[AUTH_VERIFY_REQ] Error stack trace:`, errorStack);\n\n // Try to send error response\n try {\n const parsedData = data as any;\n if (parsedData?.id) {\n sendDataResponse(parsedData.id, {\n success: false,\n error: `Internal error: ${errorMessage}`\n }, sendMessage, parsedData.from?.id);\n }\n } catch (sendError) {\n logger.error('[AUTH_VERIFY_REQ] Failed to send error response:', sendError);\n }\n }\n}\n\n/**\n * Send a data_res response message\n */\nfunction sendDataResponse(\n id: string,\n res: {success: boolean; error?: string; data?: any},\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id,\n type: 'AUTH_VERIFY_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: clientId\n },\n payload:{\n ...res,\n }\n };\n\n logger.debug(`[AUTH_VERIFY_RES ${id}] Sending ${res.success ? 'successful' : 'failed'} verification response to client: ${clientId}`);\n logger.debug(`[AUTH_VERIFY_RES ${id}] Response payload size: ${JSON.stringify(response).length} bytes`);\n\n if (res.error) {\n logger.debug(`[AUTH_VERIFY_RES ${id}] Error message: ${res.error}`);\n }\n\n if (res.data) {\n logger.debug(`[AUTH_VERIFY_RES ${id}] User verified: ${res.data}`);\n }\n\n sendMessage(response);\n} ","import dotenv from 'dotenv';\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\n\ndotenv.config();\n\nexport interface GroqLLMConfig extends BaseLLMConfig {}\n\n/**\n * GroqLLM class for handling AI-powered component generation and matching using Groq\n */\nexport class GroqLLM extends BaseLLM {\n\tconstructor(config?: GroqLLMConfig) {\n\t\tsuper(config);\n\t}\n\n\tprotected getDefaultModel(): string {\n\t\treturn 'groq/openai/gpt-oss-120b';\n\t}\n\n\tprotected getDefaultFastModel(): string {\n\t\t// Llama 3.1 8B is extremely fast and cheap on Groq\n\t\treturn 'groq/llama-3.1-8b-instant';\n\t}\n\n\tprotected getDefaultApiKey(): string | undefined {\n\t\treturn process.env.GROQ_API_KEY;\n\t}\n\n\tprotected getProviderName(): string {\n\t\treturn 'Groq';\n\t}\n}\n\n// Export a singleton instance\nexport const groqLLM = new GroqLLM();\n","import { Component, T_RESPONSE, ModelStrategy } from '../types';\nimport { ensureQueryLimit, fixScalarSubqueries, convertQuestionsToActions } from './utils';\nimport { schema } from './schema';\nimport { promptLoader } from './prompt-loader';\nimport { LLM } from '../llm';\nimport { logger } from '../utils/logger';\nimport { userPromptErrorLogger } from '../utils/user-prompt-error-logger';\nimport type { Action } from '../threads/action';\nimport KB from './knowledge-base';\nimport ConversationSearch from './conversation-search';\n\n// Re-export ModelStrategy for backward compatibility\nexport type { ModelStrategy } from '../types';\n\n/**\n * Task types for model selection\n * - 'complex': Text generation, component matching, parameter adaptation (uses best model in balanced mode)\n * - 'simple': Classification, action generation (uses fast model in balanced mode)\n */\nexport type TaskType = 'complex' | 'simple';\n\nexport interface BaseLLMConfig {\n\tmodel?: string;\n\tfastModel?: string; // Cheaper/faster model for simple tasks (classification, matching, actions)\n\tdefaultLimit?: number;\n\tapiKey?: string;\n\t/**\n\t * Model selection strategy:\n\t * - 'best': Use best model for all tasks (highest quality, higher cost)\n\t * - 'fast': Use fast model for all tasks (lower quality, lower cost)\n\t * - 'balanced': Use best model for complex tasks, fast model for simple tasks (default)\n\t */\n\tmodelStrategy?: ModelStrategy;\n}\n\n/**\n * BaseLLM abstract class for AI-powered component generation and matching\n * Provides common functionality for all LLM providers\n */\nexport abstract class BaseLLM {\n\tprotected model: string;\n\tprotected fastModel: string; // Used for classification, matching, actions (cheaper)\n\tprotected defaultLimit: number;\n\tprotected apiKey?: string;\n\tprotected modelStrategy: ModelStrategy;\n\n\tconstructor(config?: BaseLLMConfig) {\n\t\tthis.model = config?.model || this.getDefaultModel();\n\t\tthis.fastModel = config?.fastModel || this.getDefaultFastModel();\n\t\tthis.defaultLimit = config?.defaultLimit || 50;\n\t\tthis.apiKey = config?.apiKey;\n\t\tthis.modelStrategy = config?.modelStrategy || 'fast';\n\t}\n\n\t/**\n\t * Get the appropriate model based on task type and model strategy\n\t * @param taskType - 'complex' for text generation/matching, 'simple' for classification/actions\n\t * @returns The model string to use for this task\n\t */\n\tprotected getModelForTask(taskType: TaskType): string {\n\t\tswitch (this.modelStrategy) {\n\t\t\tcase 'best':\n\t\t\t\t// Use best model for all tasks\n\t\t\t\treturn this.model;\n\t\t\tcase 'fast':\n\t\t\t\t// Use fast model for all tasks\n\t\t\t\treturn this.fastModel;\n\t\t\tcase 'balanced':\n\t\t\tdefault:\n\t\t\t\t// Use best model for complex tasks, fast model for simple tasks\n\t\t\t\treturn taskType === 'complex' ? this.model : this.fastModel;\n\t\t}\n\t}\n\n\t/**\n\t * Set the model strategy at runtime\n\t * @param strategy - 'best', 'fast', or 'balanced'\n\t */\n\tpublic setModelStrategy(strategy: ModelStrategy): void {\n\t\tthis.modelStrategy = strategy;\n\t\tlogger.info(`[${this.getProviderName()}] Model strategy set to: ${strategy}`);\n\t}\n\n\t/**\n\t * Get the current model strategy\n\t * @returns The current model strategy\n\t */\n\tpublic getModelStrategy(): ModelStrategy {\n\t\treturn this.modelStrategy;\n\t}\n\n\t/**\n\t * Get the default model for this provider (used for complex tasks like text generation)\n\t */\n\tprotected abstract getDefaultModel(): string;\n\n\t/**\n\t * Get the default fast model for this provider (used for simple tasks: classification, matching, actions)\n\t * Should return a cheaper/faster model like Haiku for Anthropic\n\t */\n\tprotected abstract getDefaultFastModel(): string;\n\n\t/**\n\t * Get the default API key from environment\n\t */\n\tprotected abstract getDefaultApiKey(): string | undefined;\n\n\t/**\n\t * Get the provider name (for logging)\n\t */\n\tprotected abstract getProviderName(): string;\n\n\t/**\n\t * Get the API key (from instance, parameter, or environment)\n\t */\n\tprotected getApiKey(apiKey?: string): string | undefined {\n\t\treturn apiKey || this.apiKey || this.getDefaultApiKey();\n\t}\n\n\t/**\n\t * Check if a component contains a Form (data_modification component)\n\t * Forms have hardcoded defaultValues that become stale when cached\n\t * This checks both single Form components and Forms inside MultiComponentContainer\n\t */\n\tprotected containsFormComponent(component: any): boolean {\n\t\tif (!component) return false;\n\n\t\t// Check if this component itself is a Form\n\t\tif (component.type === 'Form' || component.name === 'DynamicForm') {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check if this is a Container with nested components\n\t\tif (component.type === 'Container' || component.name === 'MultiComponentContainer') {\n\t\t\tconst nestedComponents = component.props?.config?.components || [];\n\t\t\tfor (const nested of nestedComponents) {\n\t\t\t\tif (nested.type === 'Form' || nested.name === 'DynamicForm') {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\n\t/**\n\t * Match components from text response suggestions and generate follow-up questions\n\t * Takes a text response with component suggestions (c1:type format) and matches with available components\n\t * Also generates title, description, and intelligent follow-up questions (actions) based on the analysis\n\t * All components are placed in a default MultiComponentContainer layout\n\t * @param analysisContent - The text response containing component suggestions\n\t * @param components - List of available components\n\t * @param apiKey - Optional API key\n\t * @param logCollector - Optional log collector\n\t * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified\n\t * @returns Object containing matched components, layout title/description, and follow-up actions\n\t */\n\tasync matchComponentsFromAnalysis(\n\t\tanalysisContent: string,\n\t\tcomponents: Component[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tcomponentStreamCallback?: (component: Component) => void,\n\t\tdeferredTools?: any[],\n\t\texecutedTools?: any[]\n\t): Promise<{\n\t\tcomponents: Component[];\n\t\tlayoutTitle: string;\n\t\tlayoutDescription: string;\n\t\tactions: Action[];\n\t}> {\n\t\ttry {\n\t\t\tlogger.debug(`[${this.getProviderName()}] Starting component matching from text response`);\n\n\t\t\t// Format available components for the prompt\n\t\t\tlet availableComponentsText = 'No components available';\n\t\t\tif (components && components.length > 0) {\n\t\t\t\tavailableComponentsText = components\n\t\t\t\t\t.map((comp, idx) => {\n\t\t\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\n\t\t\t\t\t\tconst propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : 'No props';\n\t\t\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\n Name: ${comp.name}\n Type: ${comp.type}\n Description: ${comp.description || 'No description'}\n Keywords: ${keywords}\n Props Structure: ${propsPreview}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join('\\n\\n');\n\t\t\t}\n\n\t\t\t// Format deferred tools for Form generation\n\t\t\tlet deferredToolsText = 'No deferred external tools for this request.';\n\t\t\tif (deferredTools && deferredTools.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools to component matching`);\n\t\t\t\tdeferredToolsText = 'The following external tools need user input via a Form component.\\n' +\n\t\t\t\t\t'**IMPORTANT: Use these EXACT values when generating Form externalTool prop.**\\n\\n' +\n\t\t\t\t\tdeferredTools.map((tool, idx) => {\n\t\t\t\t\t\treturn `${idx + 1}. **${tool.name}**\n toolId: \"${tool.id}\" (USE THIS EXACT VALUE - do not modify!)\n toolName: \"${tool.name}\"\n parameters: ${JSON.stringify(tool.params || {})}\n requiredFields:\n${JSON.stringify(tool.requiredFields || [], null, 2)}`;\n\t\t\t\t\t}).join('\\n\\n');\n\t\t\t}\n\n\t\t\t// Format executed tools for data visualization components\n\t\t\tlet executedToolsText = 'No external tools were executed for data fetching.';\n\t\t\tif (executedTools && executedTools.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Passing ${executedTools.length} executed tools to component matching`);\n\t\t\t\texecutedToolsText = 'The following external tools were executed to fetch data.\\n' +\n\t\t\t\t\t'**IMPORTANT: For components displaying this data, use externalTool prop instead of query.**\\n' +\n\t\t\t\t\t'**IMPORTANT: Use the result data to populate deferred tool parameters when applicable.**\\n\\n' +\n\t\t\t\t\texecutedTools.map((tool, idx) => {\n\t\t\t\t\t\t// Format result - limit size to avoid token overflow\n\t\t\t\t\t\tlet resultPreview = 'No result data';\n\t\t\t\t\t\tif (tool.result) {\n\t\t\t\t\t\t\tconst resultStr = typeof tool.result === 'string' ? tool.result : JSON.stringify(tool.result, null, 2);\n\t\t\t\t\t\t\t// Limit result preview to first 2000 chars to avoid token overflow\n\t\t\t\t\t\t\tresultPreview = resultStr.length > 2000 ? resultStr.substring(0, 2000) + '\\n... (truncated)' : resultStr;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn `${idx + 1}. **${tool.name}**\n toolId: \"${tool.id}\" (USE THIS EXACT VALUE for externalTool.toolId)\n toolName: \"${tool.name}\" (USE THIS EXACT VALUE for externalTool.toolName)\n parameters: ${JSON.stringify(tool.params || {})} (USE THESE for externalTool.parameters)\n result: ${resultPreview}`;\n\t\t\t\t\t}).join('\\n\\n');\n\t\t\t}\n\n\t\t\t// Get schema documentation for query generation\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t\t// Get database-specific SQL rules\n\t\t\tconst databaseRules = await promptLoader.loadDatabaseRules();\n\n\t\t\tlogger.file('\\n=============================\\nText analysis response:', analysisContent);\n\t\t\tlogger.file('\\n=============================\\nDeferred tools:', deferredToolsText);\n\t\t\tlogger.file('\\n=============================\\nExecuted tools:', executedToolsText);\n\t\t\tconst prompts = await promptLoader.loadPrompts('match-text-components', {\n\t\t\t\tANALYSIS_CONTENT: analysisContent,\n\t\t\t\tAVAILABLE_COMPONENTS: availableComponentsText,\n\t\t\t\tSCHEMA_DOC: schemaDoc,\n\t\t\t\tDATABASE_RULES: databaseRules,\n\t\t\t\tDEFERRED_TOOLS: deferredToolsText,\n\t\t\t\tEXECUTED_TOOLS: executedToolsText\n\t\t\t});\n\n\t\t\tlogger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);\n\t\t\tlogger.file('\\n=============================\\nmatch text components system prompt:', prompts.system);\n\n\t\t\tlogCollector?.info('Matching components from text response...');\n\n\t\t\t// Partial JSON streaming to extract answerComponent as soon as it's available\n\t\t\tlet fullResponseText = '';\n\t\t\tlet answerComponentExtracted = false;\n\n\t\t\t// Streaming callback to detect and extract answerComponent early\n\t\t\t// Capture componentStreamCallback in closure\n\t\t\tconst answerCallback = componentStreamCallback;\n\t\t\tconst partialCallback = answerCallback ? (chunk: string) => {\n\t\t\t\tfullResponseText += chunk;\n\n\t\t\t\t// Only try to extract answerComponent if we haven't already and if we have a callback\n\t\t\t\tif (!answerComponentExtracted && answerCallback) {\n\t\t\t\t\t// Check if hasAnswerComponent is true first\n\t\t\t\t\tconst hasAnswerComponentMatch = fullResponseText.match(/\"hasAnswerComponent\"\\s*:\\s*(true|false)/);\n\t\t\t\t\tif (!hasAnswerComponentMatch || hasAnswerComponentMatch[1] !== 'true') {\n\t\t\t\t\t\treturn; // No answer component or not true yet\n\t\t\t\t\t}\n\n\t\t\t\t\t// Look for \"answerComponent\": { and extract the complete object\n\t\t\t\t\tconst answerComponentStartMatch = fullResponseText.match(/\"answerComponent\"\\s*:\\s*\\{/);\n\t\t\t\t\tif (!answerComponentStartMatch) {\n\t\t\t\t\t\treturn; // answerComponent field not found yet\n\t\t\t\t\t}\n\n\t\t\t\t\t// Find the start position of the object\n\t\t\t\t\tconst startPos = answerComponentStartMatch.index! + answerComponentStartMatch[0].length - 1; // Position of opening {\n\n\t\t\t\t\t// Track brace depth to find the matching closing brace\n\t\t\t\t\tlet braceDepth = 0;\n\t\t\t\t\tlet inString = false;\n\t\t\t\t\tlet escapeNext = false;\n\t\t\t\t\tlet endPos = -1;\n\n\t\t\t\t\tfor (let i = startPos; i < fullResponseText.length; i++) {\n\t\t\t\t\t\tconst char = fullResponseText[i];\n\n\t\t\t\t\t\tif (escapeNext) {\n\t\t\t\t\t\t\tescapeNext = false;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (char === '\\\\') {\n\t\t\t\t\t\t\tescapeNext = true;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (char === '\"') {\n\t\t\t\t\t\t\tinString = !inString;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!inString) {\n\t\t\t\t\t\t\tif (char === '{') {\n\t\t\t\t\t\t\t\tbraceDepth++;\n\t\t\t\t\t\t\t} else if (char === '}') {\n\t\t\t\t\t\t\t\tbraceDepth--;\n\t\t\t\t\t\t\t\tif (braceDepth === 0) {\n\t\t\t\t\t\t\t\t\tendPos = i + 1;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (endPos > startPos) {\n\t\t\t\t\t\t// We found the complete answerComponent object\n\t\t\t\t\t\tconst answerComponentString = fullResponseText.substring(startPos, endPos);\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst answerComponentData = JSON.parse(answerComponentString);\n\n\t\t\t\t\t\t\tif (answerComponentData && answerComponentData.componentId) {\n\t\t\t\t\t\t\t\t// Find the component and build it\n\t\t\t\t\t\t\t\tconst originalComponent = components.find(c => c.id === answerComponentData.componentId);\n\n\t\t\t\t\t\t\t\tif (originalComponent) {\n\t\t\t\t\t\t\t\t\tconst answerComponent: Component = {\n\t\t\t\t\t\t\t\t\t\t...originalComponent,\n\t\t\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\t\t\t...originalComponent.props,\n\t\t\t\t\t\t\t\t\t\t\t...answerComponentData.props\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\tconst streamTime = new Date().toISOString();\n\t\t\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type}) - STREAMING TO FRONTEND NOW`);\n\t\t\t\t\t\t\t\t\tlogCollector?.info(`✓ Answer component: ${answerComponent.name} (${answerComponent.type}) - streaming to frontend at ${streamTime}`);\n\n\t\t\t\t\t\t\t\t\tif (answerComponentData.props?.query) {\n\t\t\t\t\t\t\t\t\t\tlogCollector?.logQuery(\n\t\t\t\t\t\t\t\t\t\t\t'Answer component query',\n\t\t\t\t\t\t\t\t\t\t\tanswerComponentData.props.query,\n\t\t\t\t\t\t\t\t\t\t\t{ componentName: answerComponent.name, componentType: answerComponent.type, reasoning: answerComponentData.reasoning }\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// STREAM ANSWER COMPONENT IMMEDIATELY\n\t\t\t\t\t\t\t\t\tanswerCallback(answerComponent);\n\t\t\t\t\t\t\t\t\tanswerComponentExtracted = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t// JSON not complete or malformed, will try again with more data\n\t\t\t\t\t\t\tlogger.debug(`[${this.getProviderName()}] Partial answerComponent parse failed, waiting for more data...`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} : undefined;\n\n\t\t\t// Let LLM.stream handle JSON parsing automatically, but also use partial callback\n\t\t// Use full model for component matching (requires complex SQL generation and prop mapping)\n\t\t\tconst result = await LLM.stream<any>(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmodel: this.getModelForTask('complex'),\n\t\t\t\t\tmaxTokens: 8192,\n\t\t\t\t\ttemperature: 0.2,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey),\n\t\t\t\t\tpartial: partialCallback\n\t\t\t\t},\n\t\t\t\ttrue // Parse as JSON\n\t\t\t) as any;\n\n\t\t\tlogger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);\n\n\t\t\t// Extract component suggestions from text analysis (format: c1:type : reasoning)\n\t\t\tconst componentSuggestionPattern = /c\\d+:(\\w+)\\s*:\\s*(.+)/g;\n\t\t\tconst suggestedComponents = [];\n\t\t\tlet match;\n\t\t\twhile ((match = componentSuggestionPattern.exec(analysisContent)) !== null) {\n\t\t\t\tsuggestedComponents.push({\n\t\t\t\t\ttype: match[1],\n\t\t\t\t\treasoning: match[2].trim()\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst matchedComponents = result.matchedComponents || [];\n\t\t\tconst layoutTitle = result.layoutTitle || 'Dashboard';\n\t\t\tconst layoutDescription = result.layoutDescription || 'Multi-component dashboard';\n\n\t\t\tlogger.info(`[${this.getProviderName()}] 📊 Component Suggestions from Text Analysis: ${suggestedComponents.length}`);\n\t\t\tsuggestedComponents.forEach((comp, idx) => {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] c${idx + 1}: ${comp.type} - ${comp.reasoning}`);\n\t\t\t});\n\n\t\t\tlogger.info(`[${this.getProviderName()}] 📦 Matched Components from LLM: ${matchedComponents.length}`);\n\t\t\tmatchedComponents.forEach((comp: any, idx: number) => {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || 'N/A'}`);\n\t\t\t});\n\n\t\t\tlogger.file('\\n=============================\\nFull LLM response:', JSON.stringify(result, null, 2));\n\t\t\t// Convert question strings to Action objects]\n\t\t\tconst rawActions = result.actions || [];\n\t\t\tconst actions = convertQuestionsToActions(rawActions);\n\n\t\t\tlogger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);\n\t\t\tlogger.info(`[${this.getProviderName()}] Layout title: \"${layoutTitle}\"`);\n\t\t\tlogger.info(`[${this.getProviderName()}] Layout description: \"${layoutDescription}\"`);\n\t\t\tlogger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);\n\n\t\t\t// Log component suggestions vs matched components\n\t\t\tif (suggestedComponents.length > 0) {\n\t\t\t\tlogCollector?.info(`📝 Text Analysis suggested ${suggestedComponents.length} dashboard components:`);\n\t\t\t\tsuggestedComponents.forEach((comp, idx) => {\n\t\t\t\t\tlogCollector?.info(` c${idx + 1}: ${comp.type} - ${comp.reasoning}`);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Log matched components\n\t\t\tif (matchedComponents.length > 0) {\n\t\t\t\tlogCollector?.info(`📦 Matched ${matchedComponents.length} components for dashboard`);\n\t\t\t\tif (suggestedComponents.length !== matchedComponents.length) {\n\t\t\t\t\tlogCollector?.warn(`⚠️ Component count mismatch: Suggested ${suggestedComponents.length}, but matched ${matchedComponents.length}`);\n\t\t\t\t}\n\t\t\t\tlogCollector?.info(`Dashboard: \"${layoutTitle}\"`);\n\t\t\t\tmatchedComponents.forEach((comp: any, idx: number) => {\n\t\t\t\t\tlogCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);\n\t\t\t\t\tif (comp.props?.query) {\n\t\t\t\t\t\tlogCollector?.logQuery(\n\t\t\t\t\t\t\t`Component ${idx + 1} query`,\n\t\t\t\t\t\t\tcomp.props.query,\n\t\t\t\t\t\t\t{ componentName: comp.componentName, title: comp.props.title }\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Log generated actions\n\t\t\tif (actions.length > 0) {\n\t\t\t\tlogCollector?.info(`Generated ${actions.length} follow-up questions`);\n\t\t\t\tactions.forEach((action: Action, idx: number) => {\n\t\t\t\t\tlogCollector?.info(` ${idx + 1}. ${action.name}`);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Build final component objects with full metadata\n\t\t\tconst finalComponents: Component[] = matchedComponents.map((mc: any) => {\n\t\t\t\t// Find the original component from the list to preserve all metadata\n\t\t\t\tconst originalComponent = components.find(c => c.id === mc.componentId);\n\n\t\t\t\tif (!originalComponent) {\n\t\t\t\t\tlogger.warn(`[${this.getProviderName()}] Component ${mc.componentId} not found in available components`);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Merge generated props with original component\n\t\t\t\treturn {\n\t\t\t\t\t...originalComponent,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...originalComponent.props,\n\t\t\t\t\t\t...mc.props\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}).filter(Boolean) as Component[];\n\n\t\t\treturn {\n\t\t\t\tcomponents: finalComponents,\n\t\t\t\tlayoutTitle,\n\t\t\t\tlayoutDescription,\n\t\t\t\tactions\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error matching components: ${errorMsg}`);\n\t\t\tlogCollector?.error(`Failed to match components: ${errorMsg}`);\n\n\t\t\t// Return empty results on error\n\t\t\treturn {\n\t\t\t\tcomponents: [],\n\t\t\t\tlayoutTitle: 'Dashboard',\n\t\t\t\tlayoutDescription: 'Failed to generate dashboard',\n\t\t\t\tactions: []\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Classify user question into category and detect external tools needed\n\t * Determines if question is for data analysis, requires external tools, or needs text response\n\t */\n\tasync classifyQuestionCategory(\n\t\tuserPrompt: string,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string,\n\t\texternalTools?: any[]\n\t): Promise<{\n\t\tcategory: 'data_analysis' | 'data_modification' | 'general';\n\t\texternalTools: Array<{\n\t\t\ttype: string;\n\t\t\tname: string;\n\t\t\tdescription: string;\n\t\t\tparameters: Record<string, any>;\n\t\t}>;\n\t\tdataAnalysisType?: 'visualization' | 'calculation' | 'comparison' | 'trend';\n\t\treasoning: string;\n\t\tconfidence: number;\n\t}> {\n\t\ttry {\n\t\t\t// Get database schema documentation - CRITICAL for proper category classification\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t\t// Format available external tools for the system prompt\n\t\t\tconst availableToolsDoc = externalTools && externalTools.length > 0\n\t\t\t\t? externalTools.map(tool => {\n\t\t\t\t\tconst paramsStr = Object.entries(tool.params || {})\n\t\t\t\t\t\t.map(([key, type]) => `${key}: ${type}`)\n\t\t\t\t\t\t.join(', ');\n\t\t\t\t\treturn `- **${tool.name}** (id: ${tool.id})\\n Description: ${tool.description}\\n Parameters: ${paramsStr}`;\n\t\t\t\t}).join('\\n\\n')\n\t\t\t\t: 'No external tools available';\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('category-classification', {\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation',\n\t\t\t\tAVAILABLE_TOOLS: availableToolsDoc,\n\t\t\t\tSCHEMA_DOC: schemaDoc || 'No database schema available'\n\t\t\t});\n\n\t\t\t// Use appropriate model based on strategy (simple task)\n\t\t\tconst result = await LLM.stream<any>(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmodel: this.getModelForTask('simple'),\n\t\t\t\t\tmaxTokens: 1500,\n\t\t\t\t\ttemperature: 0.2,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\n\t\t\t\t},\n\t\t\t\ttrue // Parse as JSON\n\t\t\t) as any;\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'Question category classified',\n\t\t\t\tresult.reasoning || 'No reasoning provided',\n\t\t\t\t{\n\t\t\t\t\tcategory: result.category,\n\t\t\t\t\texternalTools: result.externalTools || [],\n\t\t\t\t\tdataAnalysisType: result.dataAnalysisType,\n\t\t\t\t\tconfidence: result.confidence\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tcategory: result.category || 'data_analysis',\n\t\t\t\texternalTools: result.externalTools || [],\n\t\t\t\tdataAnalysisType: result.dataAnalysisType,\n\t\t\t\treasoning: result.reasoning || 'No reasoning provided',\n\t\t\t\tconfidence: result.confidence || 0\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error classifying question category: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Category classification error details:`, error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Adapt UI block parameters based on current user question\n\t * Takes a matched UI block from semantic search and modifies its props to answer the new question\n\t */\n\tasync adaptUIBlockParameters(\n\t\tcurrentUserPrompt: string,\n\t\toriginalUserPrompt: string,\n\t\tmatchedUIBlock: any,\n\t\tapiKey?: string,\n\t\tlogCollector?: any\n\t): Promise<{\n\t\tsuccess: boolean;\n\t\tadaptedComponent?: Component;\n\t\tparametersChanged?: Array<{ field: string; reason: string }>;\n\t\texplanation: string;\n\t}> {\n\t\ttry {\n\t\t\t// Support both old format (generatedComponentMetadata) and new format (component)\n\t\t\tconst component = matchedUIBlock?.generatedComponentMetadata || matchedUIBlock?.component;\n\n\t\t\tif (!matchedUIBlock || !component) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\texplanation: 'No component found in matched UI block'\n\t\t\t\t};\n\t\t\t}\n\n\t\t// Get schema documentation for query adaptation\n\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t// Get database-specific SQL rules\n\t\tconst databaseRules = await promptLoader.loadDatabaseRules();\n\n\t\tconst prompts = await promptLoader.loadPrompts('adapt-ui-block-params', {\n\t\t\tORIGINAL_USER_PROMPT: originalUserPrompt,\n\t\t\tCURRENT_USER_PROMPT: currentUserPrompt,\n\t\t\tMATCHED_UI_BLOCK_COMPONENT: JSON.stringify(component, null, 2),\n\t\t\tCOMPONENT_PROPS: JSON.stringify(component.props, null, 2),\n\t\t\tSCHEMA_DOC: schemaDoc || 'No schema available',\n\t\t\tDATABASE_RULES: databaseRules\n\t\t});\n\n\t\t\tconst result = await LLM.stream<any>(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmodel: this.getModelForTask('complex'),\n\t\t\t\t\tmaxTokens: 3000,\n\t\t\t\t\ttemperature: 0.2,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\n\t\t\t\t},\n\t\t\t\ttrue // Parse as JSON\n\t\t\t) as any;\n\n\t\t\tif (!result.success) {\n\t\t\t\tlogger.info(\n\t\t\t\t\t`[${this.getProviderName()}] Could not adapt UI block: ${result.reason}`\n\t\t\t\t);\n\t\t\t\tlogCollector?.warn(\n\t\t\t\t\t'Could not adapt matched UI block',\n\t\t\t\t\t'explanation',\n\t\t\t\t\t{ reason: result.reason }\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\texplanation: result.explanation || 'Adaptation not possible'\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Ensure query has proper LIMIT clause if modified\n\t\t\tif (result.adaptedComponent?.props?.query) {\n\t\t\t\tresult.adaptedComponent.props.query = ensureQueryLimit(\n\t\t\t\t\tresult.adaptedComponent.props.query,\n\t\t\t\t\tthis.defaultLimit\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'UI block parameters adapted',\n\t\t\t\tresult.explanation || 'Parameters adapted successfully',\n\t\t\t\t{\n\t\t\t\t\tparametersChanged: result.parametersChanged || [],\n\t\t\t\t\tcomponentType: result.adaptedComponent?.type\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tadaptedComponent: result.adaptedComponent,\n\t\t\t\tparametersChanged: result.parametersChanged,\n\t\t\t\texplanation: result.explanation || 'Parameters adapted successfully'\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error adapting UI block parameters: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Adaptation error details:`, error);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\texplanation: `Error adapting parameters: ${errorMsg}`\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Generate text-based response for user question\n\t * This provides conversational text responses instead of component generation\n\t * Supports tool calling for query execution with automatic retry on errors (max 3 attempts)\n\t * After generating text response, if components are provided, matches suggested components\n\t * @param streamCallback - Optional callback function to receive text chunks as they stream\n\t * @param collections - Collection registry for executing database queries via database.execute\n\t * @param components - Optional list of available components for matching suggestions\n\t * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called\n\t * @param category - Question category ('data_analysis' | 'data_modification' | 'general'). For data_modification, answer component streaming is skipped. For general, component generation is skipped entirely.\n\t */\n\tasync generateTextResponse(\n\t\tuserPrompt: string,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string,\n\t\tstreamCallback?: (chunk: string) => void,\n\t\tcollections?: any,\n\t\tcomponents?: Component[],\n\t\texternalTools?: any[],\n\t\tcategory?: 'data_analysis' | 'data_modification' | 'general'\n\t): Promise<T_RESPONSE> {\n\t\tconst errors: string[] = [];\n\n\t\tlogger.debug(`[${this.getProviderName()}] Starting text response generation`);\n\t\tlogger.debug(`[${this.getProviderName()}] User prompt: \"${userPrompt.substring(0, 50)}...\"`);\n\n\t\ttry {\n\t\t\t// Step 1: Format available external tools for the system prompt\n\t\t\t// Separate tools by execution type\n\t\t\tlet availableToolsDoc = 'No external tools are available for this request.';\n\t\t\tif (externalTools && externalTools.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] External tools available: ${externalTools.map(t => t.name).join(', ')}`);\n\n\t\t\t\t// Separate immediate and deferred tools\n\t\t\t\tconst immediateTools = externalTools.filter(t => t.executionType === 'immediate' || (t.executionType === 'deferred' && t.userProvidedData));\n\t\t\t\tconst deferredTools = externalTools.filter(t => t.executionType === 'deferred' && !t.userProvidedData);\n\n\t\t\t\tlet toolsDocParts: string[] = [];\n\n\t\t\t\t// Document IMMEDIATE tools (to be executed)\n\t\t\t\tif (immediateTools.length > 0) {\n\t\t\t\t\tconst immediateDoc = '## IMMEDIATE EXECUTION TOOLS\\n' +\n\t\t\t\t\t\t'Execute these tools right away:\\n\\n' +\n\t\t\t\t\t\timmediateTools.map((tool, idx) => {\n\t\t\t\t\t\t\tconst paramsText = Object.entries(tool.params || {})\n\t\t\t\t\t\t\t\t.map(([key, value]) => {\n\t\t\t\t\t\t\t\t\tconst valueType = typeof value;\n\t\t\t\t\t\t\t\t\tif (valueType === 'string' && ['string', 'number', 'integer', 'boolean', 'array', 'object'].includes(String(value).toLowerCase())) {\n\t\t\t\t\t\t\t\t\t\treturn `- ${key}: ${value}`;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn `- ${key}: ${JSON.stringify(value)} (default value - use this)`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.join('\\n ');\n\n\t\t\t\t\t\t\t// If deferred tool with user data, include the data\n\t\t\t\t\t\t\tlet userDataText = '';\n\t\t\t\t\t\t\tif (tool.userProvidedData) {\n\t\t\t\t\t\t\t\tuserDataText = '\\n **User Provided Data** (use these values):\\n ' +\n\t\t\t\t\t\t\t\t\tObject.entries(tool.userProvidedData)\n\t\t\t\t\t\t\t\t\t\t.map(([key, value]) => `- ${key}: ${JSON.stringify(value)}`)\n\t\t\t\t\t\t\t\t\t\t.join('\\n ');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn `${idx + 1}. **${tool.name}** (ID: ${tool.id})\\n Execution Type: IMMEDIATE\\n Description: ${tool.description}\\n Parameters:\\n ${paramsText}${userDataText}`;\n\t\t\t\t\t\t}).join('\\n\\n');\n\t\t\t\t\ttoolsDocParts.push(immediateDoc);\n\t\t\t\t}\n\n\t\t\t\t// Document DEFERRED tools (need user input - will generate Form)\n\t\t\t\tif (deferredTools.length > 0) {\n\t\t\t\t\tconst deferredDoc = '## DEFERRED TOOLS (DO NOT EXECUTE)\\n' +\n\t\t\t\t\t\t'These tools need user input. A Form component will be generated to collect the data.\\n' +\n\t\t\t\t\t\t'**DO NOT call these tools.** Instead, acknowledge the request and inform user that a form will be shown.\\n\\n' +\n\t\t\t\t\t\tdeferredTools.map((tool, idx) => {\n\t\t\t\t\t\t\tconst requiredFieldsText = (tool.requiredFields || [])\n\t\t\t\t\t\t\t\t.map((f: any) => `- ${f.label || f.name} (${f.type})${f.required ? ' *required*' : ''}`)\n\t\t\t\t\t\t\t\t.join('\\n ');\n\n\t\t\t\t\t\t\treturn `${idx + 1}. **${tool.name}** (ID: ${tool.id})\\n Execution Type: DEFERRED (needs form input)\\n Description: ${tool.description}\\n Reason: ${tool.executionReason || 'Write operation requires user confirmation'}\\n Required Fields:\\n ${requiredFieldsText || '(fields will be determined by form)'}`;\n\t\t\t\t\t\t}).join('\\n\\n');\n\t\t\t\t\ttoolsDocParts.push(deferredDoc);\n\t\t\t\t}\n\n\t\t\t\tavailableToolsDoc = toolsDocParts.join('\\n\\n---\\n\\n');\n\t\t\t}\n\n\t\t\t// Get schema documentation\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t\t// Get database-specific SQL rules\n\t\t\tconst databaseRules = await promptLoader.loadDatabaseRules();\n\n\t\t\t// Get relevant knowledge base context (best match only)\n\t\t\tconst knowledgeBaseContext = await KB.getKnowledgeBase({\n\t\t\t\tprompt: userPrompt,\n\t\t\t\tcollections,\n\t\t\t\ttopK: 1\n\t\t\t});\n\n\t\t\tlogger.file('\\n=============================\\nknowledge base context:', knowledgeBaseContext);\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('text-response', {\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation',\n\t\t\t\tSCHEMA_DOC: schemaDoc,\n\t\t\t\tDATABASE_RULES: databaseRules,\n\t\t\t\tKNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || 'No additional knowledge base context available.',\n\t\t\t\tAVAILABLE_EXTERNAL_TOOLS: availableToolsDoc\n\t\t\t});\n\n\t\t\tlogger.file('\\n=============================\\nsystem prompt:', prompts.system);\n\t\t\tlogger.file('\\n=============================\\nuser prompt:', prompts.user);\n\n\t\t\tlogger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);\n\n\t\t\tlogCollector?.info('Generating text response with query execution capability...');\n\n\t\t\t// Define tools: execute_query + external tools identified by category classification\n\t\t\tconst tools = [{\n\t\t\t\tname: 'execute_query',\n\t\t\t\tdescription: 'Executes a parameterized SQL query against the database. CRITICAL: NEVER hardcode literal values in WHERE/HAVING conditions - ALWAYS use $paramName placeholders and pass actual values in params object.',\n\t\t\t\tinput_schema: {\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tsql: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: 'SQL query with $paramName placeholders for ALL literal values in WHERE/HAVING conditions. NEVER hardcode values like WHERE status = \\'Delivered\\' - instead use WHERE status = $status. Table names, column names, and SQL keywords stay as-is.'\n\t\t\t\t\t\t},\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tdescription: 'REQUIRED when SQL has WHERE/HAVING conditions. Maps each $paramName placeholder (without $) to its actual value. Pattern: WHERE col = $name → params: { \"name\": \"value\" }. Every placeholder in SQL MUST have a corresponding entry here.',\n\t\t\t\t\t\t\tadditionalProperties: true\n\t\t\t\t\t\t},\n\t\t\t\t\t\treasoning: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: 'Brief explanation of what this query does and why it answers the user\\'s question.'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\trequired: ['sql'],\n\t\t\t\t\tadditionalProperties: false\n\t\t\t\t}\n\t\t\t}];\n\n\t\t\t// Add external tools to the tools array (if any were identified by category classification)\n\t\t\t// IMPORTANT: Only add tools that should be executed (immediate OR deferred with user data)\n\t\t\tif (externalTools && externalTools.length > 0) {\n\t\t\t\t// Filter to only executable tools\n\t\t\t\tconst executableTools = externalTools.filter(t =>\n\t\t\t\t\tt.executionType === 'immediate' || (t.executionType === 'deferred' && t.userProvidedData)\n\t\t\t\t);\n\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Executable tools: ${executableTools.length} of ${externalTools.length} total`);\n\n\t\t\t\texecutableTools.forEach(tool => {\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Processing executable tool:`, JSON.stringify(tool, null, 2));\n\t\t\t\t\tconst properties: any = {};\n\t\t\t\t\tconst required: string[] = [];\n\n\t\t\t\t\tObject.entries(tool.params || {}).forEach(([key, typeOrValue]) => {\n\t\t\t\t\t\t// Normalize type to valid JSON Schema types\n\t\t\t\t\t\t// Handle both type strings and actual values from LLM classification\n\t\t\t\t\t\tlet schemaType: string;\n\t\t\t\t\t\tlet hasDefaultValue = false;\n\t\t\t\t\t\tlet defaultValue: any;\n\n\t\t\t\t\t\t// Check if this is an actual value (not a type string)\n\t\t\t\t\t\tconst valueType = typeof typeOrValue;\n\t\t\t\t\t\tif (valueType === 'number') {\n\t\t\t\t\t\t\t// If it's a number value, infer the type and mark as having default\n\t\t\t\t\t\t\tschemaType = Number.isInteger(typeOrValue) ? 'integer' : 'number';\n\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t} else if (valueType === 'boolean') {\n\t\t\t\t\t\t\tschemaType = 'boolean';\n\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t} else if (Array.isArray(typeOrValue)) {\n\t\t\t\t\t\t\tschemaType = 'array';\n\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t} else if (valueType === 'object' && typeOrValue !== null) {\n\t\t\t\t\t\t\tschemaType = 'object';\n\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// It's a string - could be a type name or a string value\n\t\t\t\t\t\t\tconst typeStr = String(typeOrValue).toLowerCase().trim();\n\n\t\t\t\t\t\t\t// Check if it's a known type name\n\t\t\t\t\t\t\tif (typeStr === 'string' || typeStr === 'str') {\n\t\t\t\t\t\t\t\tschemaType = 'string';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'number' || typeStr === 'num' || typeStr === 'float' || typeStr === 'double') {\n\t\t\t\t\t\t\t\tschemaType = 'number';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'integer' || typeStr === 'int') {\n\t\t\t\t\t\t\t\tschemaType = 'integer';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'boolean' || typeStr === 'bool') {\n\t\t\t\t\t\t\t\tschemaType = 'boolean';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'array' || typeStr === 'list') {\n\t\t\t\t\t\t\t\tschemaType = 'array';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else if (typeStr === 'object' || typeStr === 'dict') {\n\t\t\t\t\t\t\t\tschemaType = 'object';\n\t\t\t\t\t\t\t\t// Type name, no default\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Not a recognized type name, assume it's a string value - infer type as string\n\t\t\t\t\t\t\t\tschemaType = 'string';\n\t\t\t\t\t\t\t\thasDefaultValue = true;\n\t\t\t\t\t\t\t\tdefaultValue = typeOrValue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst propertySchema: any = {\n\t\t\t\t\t\t\ttype: schemaType,\n\t\t\t\t\t\t\tdescription: `${key} parameter for ${tool.name}`\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// Add default value to schema if present\n\t\t\t\t\t\tif (hasDefaultValue) {\n\t\t\t\t\t\t\tpropertySchema.default = defaultValue;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Only mark as required if no default value\n\t\t\t\t\t\t\trequired.push(key);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tproperties[key] = propertySchema;\n\t\t\t\t\t});\n\n\t\t\t\t\tconst inputSchema: any = {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\tadditionalProperties: false\n\t\t\t\t\t};\n\n\t\t\t\t\t// Only include required array if there are required fields\n\t\t\t\t\tif (required.length > 0) {\n\t\t\t\t\t\tinputSchema.required = required;\n\t\t\t\t\t}\n\n\t\t\t\t\ttools.push({\n\t\t\t\t\t\tname: tool.id,\n\t\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\t\tinput_schema: inputSchema\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Added ${executableTools.length} executable tools to tool calling capability (${externalTools.length - executableTools.length} deferred tools await form input)`);\n\t\t\t\t// Debug: Log the complete tools array to verify schema\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Complete tools array:`, JSON.stringify(tools, null, 2));\n\t\t\t}\n\n\t\t\t// Track query attempts for retry logic (max 6 attempts per unique query pattern)\n\t\t\tconst queryAttempts = new Map<string, number>();\n\t\t\tconst MAX_QUERY_ATTEMPTS = 6;\n\n\t\t\t// Track external tool attempts for retry logic (max 3 attempts per tool)\n\t\t\tconst toolAttempts = new Map<string, number>();\n\t\t\tconst MAX_TOOL_ATTEMPTS = 3;\n\n\t\t\t// Track successfully executed external tools (for passing to component matching)\n\t\t\tconst executedToolsList: any[] = [];\n\n\t\t\tlet maxAttemptsReached = false;\n\n\t\t\t// Capture all streamed text to pass to component matching\n\t\t\tlet fullStreamedText = '';\n\n\t\t\t// Wrap the streamCallback to capture all text\n\t\t\tconst wrappedStreamCallback = streamCallback ? (chunk: string) => {\n\t\t\t\tfullStreamedText += chunk;\n\t\t\t\tstreamCallback(chunk);\n\t\t\t} : undefined;\n\n\t\t\t// Tool handler with retry logic and streaming updates\n\t\t\tconst toolHandler = async (toolName: string, toolInput: any) => {\n\t\t\t\tif (toolName === 'execute_query') {\n\t\t\t\t\tlet sql = toolInput.sql;\n\t\t\t\t\tconst params = toolInput.params || {};\n\t\t\t\t\tconst reasoning = toolInput.reasoning;\n\n\t\t\t\t\t// Ensure query has proper LIMIT clause (max 32 rows)\n\t\t\t\t\tconst { ensureQueryLimit } = await import('./utils');\n\t\t\t\t\tsql = ensureQueryLimit(sql, 32, 32);\n\n\t\t\t\t\t// Track attempts for this query pattern (normalized)\n\t\t\t\t\tconst queryKey = sql.toLowerCase().replace(/\\s+/g, ' ').trim();\n\t\t\t\t\tconst attempts = (queryAttempts.get(queryKey) || 0) + 1;\n\t\t\t\t\tqueryAttempts.set(queryKey, attempts);\n\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Executing query (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${sql.substring(0, 100)}...`);\n\t\t\t\t\tif (Object.keys(params).length > 0) {\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Query params: ${JSON.stringify(params)}`);\n\t\t\t\t\t}\n\t\t\t\t\tif (reasoning) {\n\t\t\t\t\t\tlogCollector?.info(`Query reasoning: ${reasoning}`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check if max attempts reached\n\t\t\t\t\tif (attempts > MAX_QUERY_ATTEMPTS) {\n\t\t\t\t\t\tconst errorMsg = `Maximum query attempts (${MAX_QUERY_ATTEMPTS}) reached. Unable to generate a valid query for your question.`;\n\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] ${errorMsg}`);\n\t\t\t\t\t\tlogCollector?.error(errorMsg);\n\n\t\t\t\t\t\t// Set flag instead of throwing\n\t\t\t\t\t\tmaxAttemptsReached = true;\n\n\t\t\t\t\t\t// Stream error to frontend\n\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n❌ ${errorMsg}\\n\\nPlease try rephrasing your question or simplifying your request.\\n\\n`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Return error message to stop the tool calling loop\n\t\t\t\t\t\tthrow new Error(errorMsg);\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Stream query generation message to frontend\n\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\tconst paramsDisplay = Object.keys(params).length > 0 ? `\\n**Parameters:** ${JSON.stringify(params)}` : '';\n\t\t\t\t\t\t\tif (attempts === 1) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔍 **Analyzing your question...**\\n\\n`);\n\t\t\t\t\t\t\t\tif (reasoning) {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`💭 ${reasoning}\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twrappedStreamCallback(`📝 **Generated SQL Query:**\\n\\`\\`\\`sql\\n${sql}\\n\\`\\`\\`${paramsDisplay}\\n\\n`);\n\t\t\t\t\t\t\t\twrappedStreamCallback(`⚡ **Executing query...**\\n\\n`);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔄 **Retrying with corrected query (attempt ${attempts}/${MAX_QUERY_ATTEMPTS})...**\\n\\n`);\n\t\t\t\t\t\t\t\tif (reasoning) {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`💭 ${reasoning}\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twrappedStreamCallback(`📝 **Corrected SQL Query:**\\n\\`\\`\\`sql\\n${sql}\\n\\`\\`\\`${paramsDisplay}\\n\\n`);\n\t\t\t\t\t\t\t\twrappedStreamCallback(`⚡ **Executing query...**\\n\\n`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Log the query with params\n\t\t\t\t\t\tlogCollector?.logQuery(\n\t\t\t\t\t\t\t`Executing SQL query (attempt ${attempts})`,\n\t\t\t\t\t\t\t{ sql, params },\n\t\t\t\t\t\t\t{ reasoning, attempt: attempts }\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Execute query using collections system (database.execute)\n\t\t\t\t\t\t// Pass { sql, params } format for parameterized queries\n\t\t\t\t\t\tif (!collections || !collections['database'] || !collections['database']['execute']) {\n\t\t\t\t\t\t\tthrow new Error('Database collection not registered. Please register database.execute collection to execute queries.');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Build the query payload - if params exist, send as JSON structure for parameterized query\n\t\t\t\t\t\tconst queryPayload = Object.keys(params).length > 0\n\t\t\t\t\t\t\t? { sql: JSON.stringify({ sql, values: params }) }\n\t\t\t\t\t\t\t: { sql };\n\n\t\t\t\t\t\tconst result = await collections['database']['execute'](queryPayload);\n\n\t\t\t\t\t\t// Extract data from result\n\t\t\t\t\t\tconst data = result?.data || result;\n\t\t\t\t\t\tconst rowCount = result?.count ?? (Array.isArray(data) ? data.length : 'N/A');\n\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Query executed successfully, rows returned: ${rowCount}`);\n\t\t\t\t\t\tlogCollector?.info(`Query successful, returned ${rowCount} rows`);\n\n\t\t\t\t\t\t// Stream success message and data preview to frontend\n\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\twrappedStreamCallback(`✅ **Query executed successfully!**\\n\\n`);\n\n\t\t\t\t\t\t\t// Check if it's a count query or aggregate\n\t\t\t\t\t\t\tif (Array.isArray(data) && data.length > 0) {\n\t\t\t\t\t\t\t\tconst firstRow = data[0];\n\t\t\t\t\t\t\t\tconst columns = Object.keys(firstRow);\n\n\t\t\t\t\t\t\t\t// If single row with single column (likely a count/aggregate)\n\t\t\t\t\t\t\t\tif (data.length === 1 && columns.length === 1) {\n\t\t\t\t\t\t\t\t\tconst value = firstRow[columns[0]];\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`**Result:** ${value}\\n\\n`);\n\t\t\t\t\t\t\t\t} else if (data.length > 0) {\n\t\t\t\t\t\t\t\t\t// Multiple rows or columns - embed DataTable component\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`**Retrieved ${rowCount} rows**\\n\\n`);\n\n\t\t\t\t\t\t\t\t\t// Stream the data as a DataTable component\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`<DataTable>${JSON.stringify(data)}</DataTable>\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (Array.isArray(data) && data.length === 0) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`**No rows returned.**\\n\\n`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\twrappedStreamCallback(`📊 **Analyzing results...**\\n\\n`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Return full result as JSON string for the LLM to analyze\n\t\t\t\t\t\treturn JSON.stringify(data, null, 2);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] Query execution failed (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${errorMsg}`);\n\t\t\t\t\t\tlogCollector?.error(`Query failed (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${errorMsg}`);\n\n\t\t\t\t\t\t// Log full SQL error details to error log file\n\t\t\t\t\t\tuserPromptErrorLogger.logSqlError(sql, error instanceof Error ? error : new Error(errorMsg), Object.keys(params).length > 0 ? Object.values(params) : undefined);\n\n\t\t\t\t\t\t// Stream error message to frontend\n\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\twrappedStreamCallback(`❌ **Query execution failed:**\\n\\`\\`\\`\\n${errorMsg}\\n\\`\\`\\`\\n\\n`);\n\n\t\t\t\t\t\t\tif (attempts < MAX_QUERY_ATTEMPTS) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`🔧 **Generating corrected query...**\\n\\n`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Return error to LLM so it can retry with corrected query\n\t\t\t\t\t\tthrow new Error(`Query execution failed: ${errorMsg}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Handle external tools identified by category classification\n\t\t\t\t\tconst externalTool = externalTools?.find(t => t.id === toolName);\n\t\t\t\t\tif (externalTool) {\n\t\t\t\t\t\t// Track attempts for this tool\n\t\t\t\t\t\tconst attempts = (toolAttempts.get(toolName) || 0) + 1;\n\t\t\t\t\t\ttoolAttempts.set(toolName, attempts);\n\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Executing external tool: ${externalTool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})`);\n\t\t\t\t\t\tlogCollector?.info(`Executing external tool: ${externalTool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})...`);\n\n\t\t\t\t\t\t// Check if max attempts reached\n\t\t\t\t\t\tif (attempts > MAX_TOOL_ATTEMPTS) {\n\t\t\t\t\t\t\tconst errorMsg = `Maximum attempts (${MAX_TOOL_ATTEMPTS}) reached for tool: ${externalTool.name}`;\n\t\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] ${errorMsg}`);\n\t\t\t\t\t\t\tlogCollector?.error(errorMsg);\n\n\t\t\t\t\t\t\t// Stream error to frontend\n\t\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n❌ ${errorMsg}\\n\\nPlease try rephrasing your request or contact support.\\n\\n`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Return error message to stop the tool calling loop\n\t\t\t\t\t\t\tthrow new Error(errorMsg);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Stream tool execution message\n\t\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\t\tif (attempts === 1) {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔗 **Executing ${externalTool.name}...**\\n\\n`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔄 **Retrying ${externalTool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})...**\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Execute the external tool function with parameters from LLM\n\t\t\t\t\t\t\tconst result = await externalTool.fn(toolInput);\n\n\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] External tool ${externalTool.name} executed successfully`);\n\t\t\t\t\t\t\tlogCollector?.info(`✓ ${externalTool.name} executed successfully`);\n\n\t\t\t\t\t\t\t// Track successfully executed tool (for passing to component matching)\n\t\t\t\t\t\t\t// Only add if not already tracked (avoid duplicates on retry)\n\t\t\t\t\t\t\tif (!executedToolsList.find(t => t.id === externalTool.id)) {\n\t\t\t\t\t\t\t\t// Create a lightweight summary instead of storing full result to reduce memory\n\t\t\t\t\t\t\t\t// The component matching prompt only needs: toolId, toolName, parameters\n\t\t\t\t\t\t\t\t// and a brief preview of results for context\n\t\t\t\t\t\t\t\tlet resultSummary: any = null;\n\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\tconst resultStr = typeof result === 'string' ? result : JSON.stringify(result);\n\t\t\t\t\t\t\t\t\t// Store only first 1000 chars as preview (enough for LLM context)\n\t\t\t\t\t\t\t\t\tif (resultStr.length > 1000) {\n\t\t\t\t\t\t\t\t\t\tresultSummary = {\n\t\t\t\t\t\t\t\t\t\t\t_preview: resultStr.substring(0, 1000) + '... (truncated)',\n\t\t\t\t\t\t\t\t\t\t\t_totalLength: resultStr.length,\n\t\t\t\t\t\t\t\t\t\t\t_recordCount: Array.isArray(result) ? result.length :\n\t\t\t\t\t\t\t\t\t\t\t\t(result?.data?.length || result?.contacts?.length || result?.salesorders?.length || 'unknown')\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tresultSummary = result;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\texecutedToolsList.push({\n\t\t\t\t\t\t\t\t\tid: externalTool.id,\n\t\t\t\t\t\t\t\t\tname: externalTool.name,\n\t\t\t\t\t\t\t\t\tparams: toolInput, // The actual parameters used in this execution\n\t\t\t\t\t\t\t\t\tresult: resultSummary // Store summary instead of full result to save memory\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Tracked executed tool: ${externalTool.name} with params: ${JSON.stringify(toolInput)}`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Stream success message\n\t\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`✅ **${externalTool.name} completed successfully**\\n\\n`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Return result as JSON string for the LLM\n\t\t\t\t\t\t\treturn JSON.stringify(result, null, 2);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] External tool ${externalTool.name} failed (attempt ${attempts}/${MAX_TOOL_ATTEMPTS}): ${errorMsg}`);\n\t\t\t\t\t\t\tlogCollector?.error(`✗ ${externalTool.name} failed: ${errorMsg}`);\n\n\t\t\t\t\t\t\t// Log full tool error details to error log file\n\t\t\t\t\t\t\tuserPromptErrorLogger.logToolError(externalTool.name, toolInput, error instanceof Error ? error : new Error(errorMsg));\n\n\t\t\t\t\t\t\t// Stream error message\n\t\t\t\t\t\t\tif (wrappedStreamCallback) {\n\t\t\t\t\t\t\t\twrappedStreamCallback(`❌ **${externalTool.name} failed:**\\n\\`\\`\\`\\n${errorMsg}\\n\\`\\`\\`\\n\\n`);\n\n\t\t\t\t\t\t\t\tif (attempts < MAX_TOOL_ATTEMPTS) {\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`🔧 **Retrying with adjusted parameters...**\\n\\n`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Throw error so LLM can handle it and retry with adjusted parameters\n\t\t\t\t\t\t\tthrow new Error(`Tool execution failed: ${errorMsg}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow new Error(`Unknown tool: ${toolName}`);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Use tool calling with streaming\n\t\t\t// Max iterations needs to account for:\n\t\t\t// - Up to 6 query retry attempts (MAX_QUERY_ATTEMPTS)\n\t\t\t// - Up to 3 external tool retry attempts per tool (MAX_TOOL_ATTEMPTS)\n\t\t\t// - 1 additional iteration for final text response\n\t\t\t// - Buffer for multiple tool calls in one iteration\n\t\t\tconst result = await LLM.streamWithTools(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\ttools,\n\t\t\t\ttoolHandler,\n\t\t\t\t{\n\t\t\t\t\tmodel: this.getModelForTask('complex'),\n\t\t\t\t\tmaxTokens: 4000,\n\t\t\t\t\ttemperature: 0.7,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey),\n\t\t\t\t\tpartial: wrappedStreamCallback // Pass the wrapped streaming callback to LLM\n\t\t\t\t},\n\t\t\t\t20 // max iterations: allows for 6 query retries + 3 tool retries + final response + buffer\n\t\t\t);\n\n\t\t\tlogger.info(`[${this.getProviderName()}] Text response stream completed`);\n\n\t\t\t// Use fullStreamedText if available (contains all streamed content), otherwise fallback to result\n\t\t\tconst textResponse = fullStreamedText || result || 'I apologize, but I was unable to generate a response.';\n\n\t\t\t// Check if max query attempts were reached\n\t\t\tif (maxAttemptsReached) {\n\t\t\t\tlogger.warn(`[${this.getProviderName()}] Max query attempts reached, returning failure response`);\n\t\t\t\tlogCollector?.error('Failed to generate valid query after maximum attempts');\n\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terrors: [`Maximum query attempts (${MAX_QUERY_ATTEMPTS}) reached. Unable to generate a valid query for your question.`],\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttext: textResponse, // Include the streamed text showing all attempts\n\t\t\t\t\t\tmatchedComponents: [],\n\t\t\t\t\t\tactions: [],\n\t\t\t\t\t\tmethod: `${this.getProviderName()}-text-response-max-attempts`\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Log the text response\n\t\t\tlogCollector?.info(`Text response: ${textResponse.substring(0, 100)}${textResponse.length > 100 ? '...' : ''}`);\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'Text response generated',\n\t\t\t\t'Generated plain text response with component suggestions',\n\t\t\t\t{\n\t\t\t\t\ttextLength: textResponse.length\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t// Send marker message to frontend indicating text generation is complete\n\t\t\t// and component matching is starting (skip for general category)\n\t\t\tif (wrappedStreamCallback && components && components.length > 0 && category !== 'general') {\n\t\t\t\twrappedStreamCallback('__TEXT_COMPLETE__COMPONENT_GENERATION_START__');\n\t\t\t}\n\n\t\t\t// If components are provided, match them from the text response\n\t\t\t// Skip component generation for 'general' category (greetings, small talk, etc.)\n\t\t\tlet matchedComponents: Component[] = [];\n\t\t\tlet layoutTitle = 'Dashboard';\n\t\t\tlet layoutDescription = 'Multi-component dashboard';\n\t\t\tlet actions: Action[] = [];\n\n\t\t\tif (category === 'general') {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Skipping component generation for general/conversational question`);\n\t\t\t\tlogCollector?.info('Skipping component generation for general question');\n\n\t\t\t\t// Generate follow-up actions for general questions using text response as context\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Generating actions for general question...`);\n\t\t\t\tconst nextQuestions = await this.generateNextQuestions(\n\t\t\t\t\tuserPrompt,\n\t\t\t\t\tnull, // no component\n\t\t\t\t\tundefined, // no component data\n\t\t\t\t\tapiKey,\n\t\t\t\t\tlogCollector,\n\t\t\t\t\tconversationHistory,\n\t\t\t\t\ttextResponse // pass text response as context\n\t\t\t\t);\n\t\t\t\tactions = convertQuestionsToActions(nextQuestions);\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions for general question`);\n\t\t\t} else if (components && components.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Matching components from text response...`);\n\n\t\t\t\t// Component streaming callback to send answer component immediately to frontend\n\t\t\t\t// For data_modification, skip answer component streaming - show full dashboard directly\n\t\t\t\tconst componentStreamCallback = (wrappedStreamCallback && category !== 'data_modification') ? (component: Component) => {\n\t\t\t\t\t// Send special marker to indicate answer component is ready\n\t\t\t\t\tconst answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;\n\t\t\t\t\twrappedStreamCallback(answerMarker);\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);\n\t\t\t\t} : undefined;\n\n\t\t\t\t// Extract deferred tools (tools that need user input via Form)\n\t\t\t\t// For data_modification category, tools with Create/Update/Delete in name are deferred\n\t\t\t\tconst deferredTools = externalTools?.filter(t => {\n\t\t\t\t\t// Explicit deferred type\n\t\t\t\t\tif (t.executionType === 'deferred' && !t.userProvidedData) return true;\n\t\t\t\t\t// Infer deferred for data_modification category based on tool name patterns\n\t\t\t\t\tif (category === 'data_modification' && !t.userProvidedData) {\n\t\t\t\t\t\tconst name = (t.name || t.id || '').toLowerCase();\n\t\t\t\t\t\tconst isWriteOperation = /create|add|insert|new|update|edit|modify|delete|remove|send/.test(name);\n\t\t\t\t\t\tif (isWriteOperation) {\n\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Inferred deferred execution for tool: ${t.name}`);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}) || [];\n\n\t\t\t\tif (deferredTools.length > 0) {\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools for Form generation`);\n\t\t\t\t}\n\n\t\t\t\t// logger.info(`[${this.getProviderName()}] passing deferred tools to the matching function: ${JSON.stringify(deferredTools,null,2)}`);\n\t\t\t\t// logger.info(`[${this.getProviderName()}] passing executed tools to the matching function: ${JSON.stringify(executedToolsList,null,2)}`);\n\n\t\t\t\tconst matchResult = await this.matchComponentsFromAnalysis(\n\t\t\t\t\ttextResponse,\n\t\t\t\t\tcomponents,\n\t\t\t\t\tapiKey,\n\t\t\t\t\tlogCollector,\n\t\t\t\t\tcomponentStreamCallback,\n\t\t\t\t\tdeferredTools,\n\t\t\t\t\texecutedToolsList\n\t\t\t\t);\n\t\t\t\tmatchedComponents = matchResult.components;\n\t\t\t\tlayoutTitle = matchResult.layoutTitle;\n\t\t\t\tlayoutDescription = matchResult.layoutDescription;\n\t\t\t\tactions = matchResult.actions;\n\t\t\t}\n\n\t\t\tlet container_componet:Component | null = null;\n\n\t\t\tif(matchedComponents.length > 0){\n\t\t\t\t// Create MultiComponentContainer with matched components\n\t\t\t\t\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Created MultiComponentContainer: \"${layoutTitle}\" with ${matchedComponents.length} components and ${actions.length} actions`);\n\t\t\t\tlogCollector?.info(`Created dashboard: \"${layoutTitle}\" with ${matchedComponents.length} components and ${actions.length} actions`);\n\n\t\t\t\tcontainer_componet = {\n\t\t\t\t\tid: `container_${Date.now()}`,\n\t\t\t\t\tname: 'MultiComponentContainer',\n\t\t\t\t\ttype: 'Container',\n\t\t\t\t\tdescription: layoutDescription,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tconfig: {\n\t\t\t\t\t\t\ttitle: layoutTitle,\n\t\t\t\t\t\t\tdescription: layoutDescription,\n\t\t\t\t\t\t\tcomponents: matchedComponents\n\t\t\t\t\t\t},\n\t\t\t\t\t\tactions: actions\n\t\t\t\t\t}\n\t\t\t\t};\t\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\ttext: textResponse,\n\t\t\t\t\tmatchedComponents: matchedComponents,\n\t\t\t\t\tcomponent: container_componet,\n\t\t\t\t\tactions: actions,\n\t\t\t\t\tmethod: `${this.getProviderName()}-text-response`\n\t\t\t\t},\n\t\t\t\terrors: []\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating text response: ${errorMsg}`);\n\t\t\tlogCollector?.error(`Error generating text response: ${errorMsg}`);\n\n\t\t\t// Log LLM error with full details\n\t\t\tuserPromptErrorLogger.logLlmError(\n\t\t\t\tthis.getProviderName(),\n\t\t\t\tthis.model,\n\t\t\t\t'generateTextResponse',\n\t\t\t\terror instanceof Error ? error : new Error(errorMsg),\n\t\t\t\t{ userPrompt }\n\t\t\t);\n\n\t\t\terrors.push(errorMsg);\n\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terrors,\n\t\t\t\tdata: {\n\t\t\t\t\ttext: 'I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.',\n\t\t\t\t\tmatchedComponents: [],\n\t\t\t\t\tactions: [],\n\t\t\t\t\tmethod: `${this.getProviderName()}-text-response-error`\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t}\n\n\n\t/**\n\t * Main orchestration function with semantic search and multi-step classification\n\t * NEW FLOW (Recommended):\n\t * 1. Semantic search: Check previous conversations (>60% match)\n\t * - If match found → Adapt UI block parameters and return\n\t * 2. Category classification: Determine if data_analysis, requires_external_tools, or text_response\n\t * 3. Route appropriately based on category and response mode\n\t *\n\t * @param responseMode - 'component' for component generation (default), 'text' for text responses\n\t * @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)\n\t * @param collections - Collection registry for executing database queries (required for text mode)\n\t * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called (only for text mode)\n\t */\n\tasync handleUserRequest(\n\t\tuserPrompt: string,\n\t\tcomponents: Component[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string,\n\t\tresponseMode: 'component' | 'text' = 'text',\n\t\tstreamCallback?: (chunk: string) => void,\n\t\tcollections?: any,\n\t\texternalTools?: any[],\n\t\tuserId?: string\n\t): Promise<T_RESPONSE> {\n\t\tconst startTime = Date.now();\n\t\tlogger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);\n\t\tlogCollector?.info(`Starting request processing with mode: ${responseMode}`);\n\n\t\ttry {\n\t\t\t// STEP 1: Semantic search - Check if this question matches previous conversations (>60% similarity)\n\t\t\tlogger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);\n\t\t\tlogCollector?.info('Step 1: Searching for similar previous conversations...');\n\n\t\t\t// const conversationMatch = await ConversationSearch.searchConversations({\n\t\t\t// \tuserPrompt,\n\t\t\t// \tcollections,\n\t\t\t// \tuserId,\n\t\t\t// \tsimilarityThreshold: 0.6 // 60% threshold\n\t\t\t// });\n\n\t\t\tconst conversationMatch = await ConversationSearch.searchConversationsWithReranking({\n\t\t\t\tuserPrompt,\n\t\t\t\tcollections,\n\t\t\t\tuserId,\n\t\t\t\tsimilarityThreshold: 0.6 // 60% threshold\n\t\t\t});\n\n\t\t\t// logger.info('conversationMatch:', conversationMatch);\n\n\t\t\tif (conversationMatch) {\n\t\t\t\t// Found a match! Check if it's a 100% match (exact same question)\n\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);\n\t\t\t\tlogCollector?.info(\n\t\t\t\t\t`✓ Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`\n\t\t\t\t);\n\n\t\t\t\t// Extract the component from the UI block\n\t\t\t\tconst rawComponent = conversationMatch.uiBlock?.component || conversationMatch.uiBlock?.generatedComponentMetadata;\n\n\t\t\t\t// Check if component is valid (not null, not empty object)\n\t\t\t\tconst isValidComponent = rawComponent && typeof rawComponent === 'object' && Object.keys(rawComponent).length > 0;\n\t\t\t\tconst component = isValidComponent ? rawComponent : null;\n\n\t\t\t\t// Extract text response - DB stores as 'analysis'\n\t\t\t\tconst cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || '';\n\n\n\t\t\t\t// Check if cached component contains a Form (data_modification)\n\t\t\t\t// Forms have hardcoded defaultValues that become stale - always fetch fresh data\n\t\t\t\tif (this.containsFormComponent(component)) {\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Skipping cached result - Form components contain stale defaultValues, fetching fresh data`);\n\t\t\t\t\tlogCollector?.info('Skipping cache for form - fetching current values from database...');\n\t\t\t\t\t// Fall through to category classification to generate fresh form with current values\n\t\t\t\t}\n\t\t\t\t// Check if this was a general conversation (no component)\n\t\t\t\t// If so, return text response for exact match or skip adaptation for similar match\n\t\t\t\telse if (!component) {\n\t\t\t\t\tif (conversationMatch.similarity >= 0.99) {\n\t\t\t\t\t\t// Exact match for general question - return cached text response\n\t\t\t\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ Exact match for general question - returning cached text response`);\n\t\t\t\t\t\tlogCollector?.info(`✓ Exact match for general question - returning cached response`);\n\t\t\t\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\ttext: cachedTextResponse,\n\t\t\t\t\t\t\t\tcomponent: null,\n\t\t\t\t\t\t\t\tmatchedComponents: [],\n\t\t\t\t\t\t\t\tactions: conversationMatch.uiBlock?.actions || [],\n\t\t\t\t\t\t\t\treasoning: `Exact match from previous general conversation`,\n\t\t\t\t\t\t\t\tmethod: `${this.getProviderName()}-semantic-match-general`,\n\t\t\t\t\t\t\t\tsemanticSimilarity: conversationMatch.similarity\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terrors: []\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Similar match but no component (general question) - skip adaptation and process fresh\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Similar match but no component (general question) - processing fresh`);\n\t\t\t\t\t\tlogCollector?.info('Similar match found but was a general conversation - processing as new question');\n\t\t\t\t\t\t// Fall through to category classification\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Has component - proceed with normal flow\n\t\t\t\t\t// If similarity >= 99%, it's essentially the same question - return UI block directly\n\t\t\t\t\tif (conversationMatch.similarity >= 0.99) {\n\t\t\t\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ 100% match - returning UI block directly without adaptation`);\n\t\t\t\t\t\tlogCollector?.info(`✓ Exact match (${(conversationMatch.similarity * 100).toFixed(2)}%) - returning cached result`);\n\t\t\t\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\t\t\t\t\t// Stream the cached text response to frontend if available\n\t\t\t\t\t\tif (streamCallback && cachedTextResponse) {\n\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Streaming cached text response to frontend`);\n\t\t\t\t\t\t\tstreamCallback(cachedTextResponse);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Extract cached actions from UI block\n\t\t\t\t\t\tconst cachedActions = conversationMatch.uiBlock?.actions || [];\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\ttext: cachedTextResponse,\n\t\t\t\t\t\t\t\tcomponent: component,\n\t\t\t\t\t\t\t\tmatchedComponents: component?.props?.config?.components || [],\n\t\t\t\t\t\t\t\tactions: cachedActions,\n\t\t\t\t\t\t\t\treasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,\n\t\t\t\t\t\t\t\tmethod: `${this.getProviderName()}-semantic-match-exact`,\n\t\t\t\t\t\t\t\tsemanticSimilarity: conversationMatch.similarity\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terrors: []\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Similarity between 60-99%, adapt the UI block parameters\n\t\t\t\t\tlogCollector?.info(`Adapting parameters for similar question...`);\n\n\t\t\t\t\t// Get the original prompt from the matched UIBlock\n\t\t\t\t\tconst originalPrompt = conversationMatch.metadata?.userPrompt || 'Previous question';\n\n\t\t\t\t\t// Adapt the UI block parameters to the current question\n\t\t\t\t\tconst adaptResult = await this.adaptUIBlockParameters(\n\t\t\t\t\t\tuserPrompt,\n\t\t\t\t\t\toriginalPrompt,\n\t\t\t\t\t\tconversationMatch.uiBlock,\n\t\t\t\t\t\tapiKey,\n\t\t\t\t\t\tlogCollector\n\t\t\t\t\t);\n\n\t\t\t\t\tif (adaptResult.success && adaptResult.adaptedComponent) {\n\t\t\t\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ Successfully adapted UI block parameters`);\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\t\t\t\tlogCollector?.info(`✓ UI block adapted successfully`);\n\t\t\t\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\t\t\t\t\t// Stream the cached text response to frontend if available\n\t\t\t\t\t\tif (streamCallback && cachedTextResponse) {\n\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Streaming cached text response to frontend (adapted match)`);\n\t\t\t\t\t\t\tstreamCallback(cachedTextResponse);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Extract cached actions from UI block\n\t\t\t\t\t\tconst cachedActions = conversationMatch.uiBlock?.actions || [];\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\ttext: cachedTextResponse,\n\t\t\t\t\t\t\t\tcomponent: adaptResult.adaptedComponent,\n\t\t\t\t\t\t\t\tmatchedComponents: adaptResult.adaptedComponent?.props?.config?.components || [],\n\t\t\t\t\t\t\t\tactions: cachedActions,\n\t\t\t\t\t\t\t\treasoning: `Adapted from previous conversation: ${originalPrompt}`,\n\t\t\t\t\t\t\t\tmethod: `${this.getProviderName()}-semantic-match`,\n\t\t\t\t\t\t\t\tsemanticSimilarity: conversationMatch.similarity,\n\t\t\t\t\t\t\t\tparametersChanged: adaptResult.parametersChanged\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terrors: []\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Could not adapt matched conversation, continuing to category classification`);\n\t\t\t\t\t\tlogCollector?.warn(`Could not adapt matched conversation: ${adaptResult.explanation}`);\n\t\t\t\t\t\t// Fall through to category classification\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] No matching previous conversations found, proceeding to category classification`);\n\t\t\t\tlogCollector?.info('No similar previous conversations found. Proceeding to category classification...');\n\t\t\t}\n\n\t\t\t// STEP 2: Category classification - Determine the type of request\n\t\t\tlogger.info(`[${this.getProviderName()}] Step 2: Classifying question category...`);\n\t\t\tlogCollector?.info('Step 2: Classifying question category...');\n\n\t\t\tconst categoryClassification = await this.classifyQuestionCategory(\n\t\t\t\tuserPrompt,\n\t\t\t\tapiKey,\n\t\t\t\tlogCollector,\n\t\t\t\tconversationHistory,\n\t\t\t\texternalTools\n\t\t\t);\n\n\t\t\tlogger.info(\n\t\t\t\t`[${this.getProviderName()}] Question classified as: ${categoryClassification.category} (confidence: ${categoryClassification.confidence}%)`\n\t\t\t);\n\t\t\tlogCollector?.info(\n\t\t\t\t`Category: ${categoryClassification.category} | Confidence: ${categoryClassification.confidence}%`\n\t\t\t);\n\n\t\t\t// STEP 3: Prepare tools based on category classification\n\t\t\t// Only use tools identified by the LLM classification\n\t\t\tlet toolsToUse: any[] = [];\n\t\t\tif (categoryClassification.externalTools && categoryClassification.externalTools.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Identified ${categoryClassification.externalTools.length} external tools needed`);\n\t\t\t\tlogCollector?.info(`Identified external tools: ${categoryClassification.externalTools.map((t: any) => t.name || t.type).join(', ')}`);\n\n\t\t\t\t// Log the raw external tools from category classification for debugging\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Raw external tools from classification: ${JSON.stringify(categoryClassification.externalTools, null, 2)}`);\n\n\t\t\t\ttoolsToUse = categoryClassification.externalTools?.map((t: any) => {\n\t\t\t\t\t// Look up the real tool implementation\n\t\t\t\t\tconst realTool = externalTools?.find(tool => tool.id === t.type);\n\n\t\t\t\t\t// Log execution type for debugging\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Tool ${t.name}: executionType=${t.executionType}, userProvidedData=${t.userProvidedData ? 'present' : 'null'}`);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: t.type,\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparams: t.parameters || {},\n\t\t\t\t\t\t// NEW: Include execution type info from category classification\n\t\t\t\t\t\texecutionType: t.executionType || 'immediate',\n\t\t\t\t\t\texecutionReason: t.executionReason || '',\n\t\t\t\t\t\trequiredFields: t.requiredFields || [],\n\t\t\t\t\t\tuserProvidedData: t.userProvidedData || null,\n\t\t\t\t\t\tfn: (() => {\n\t\t\t\t\t\t\tif (realTool) {\n\t\t\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);\n\t\t\t\t\t\t\t\treturn realTool.fn; // Use the real function!\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlogger.warn(`[${this.getProviderName()}] Tool ${t.type} not found in registered tools`);\n\t\t\t\t\t\t\t\treturn async () => ({ success: false, message: `Tool ${t.name || t.type} not registered` });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})()\n\t\t\t\t\t};\n\t\t\t\t}) || [];\n\n\t\t\t}\n\n\t\t\t// STEP 4: Route based on category\n\t\t\tif (categoryClassification.category === 'general') {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);\n\t\t\t\tlogCollector?.info('Routing to general conversation...');\n\t\t\t} else if (categoryClassification.category === 'data_analysis') {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Routing to data analysis (SELECT operations)`);\n\t\t\t\tlogCollector?.info('Routing to data analysis...');\n\t\t\t} else if (categoryClassification.category === 'data_modification') {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Routing to data modification (INSERT/UPDATE/DELETE operations)`);\n\t\t\t\tlogCollector?.info('Routing to data modification...');\n\t\t\t}\n\n\t\t\t// Generate text response with identified tools\n\t\t\tconst textResponse = await this.generateTextResponse(\n\t\t\t\tuserPrompt,\n\t\t\t\tapiKey,\n\t\t\t\tlogCollector,\n\t\t\t\tconversationHistory,\n\t\t\t\tstreamCallback,\n\t\t\t\tcollections,\n\t\t\t\tcomponents,\n\t\t\t\ttoolsToUse,\n\t\t\t\tcategoryClassification.category\n\t\t\t);\n\n\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\treturn textResponse;\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error in handleUserRequest: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Error details:`, error);\n\t\t\tlogCollector?.error(`Error processing request: ${errorMsg}`);\n\n\t\t\t// Log error with full details\n\t\t\tuserPromptErrorLogger.logError(\n\t\t\t\t'handleUserRequest',\n\t\t\t\terror instanceof Error ? error : new Error(errorMsg),\n\t\t\t\t{ userPrompt }\n\t\t\t);\n\n\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terrors: [errorMsg],\n\t\t\t\tdata: {\n\t\t\t\t\ttext: 'I apologize, but I encountered an error processing your request. Please try again.',\n\t\t\t\t\tmethod: `${this.getProviderName()}-orchestration-error`\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Generate next questions that the user might ask based on the original prompt and generated component\n\t * This helps provide intelligent suggestions for follow-up queries\n\t * For general/conversational questions without components, pass textResponse instead\n\t */\n\tasync generateNextQuestions(\n\t\toriginalUserPrompt: string,\n\t\tcomponent?: Component | null,\n\t\tcomponentData?: Record<string, unknown>,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string,\n\t\ttextResponse?: string\n\t): Promise<string[]> {\n\t\ttry {\n\t\t\t// Build component info - use component if available, otherwise use text response\n\t\t\tlet component_info: string;\n\t\t\tif (component) {\n\t\t\t\tcomponent_info = `\n\t\t\t\tComponent Name: ${component.name}\n\t\t\t\tComponent Type: ${component.type}\n\t\t\t\tComponent Description: ${component.description || 'No description'}\n\t\t\t\tComponent Props: ${component.props ? JSON.stringify(component.props, null, 2) : 'No props'}\n\t\t\t`;\n\t\t\t} else if (textResponse) {\n\t\t\t\tcomponent_info = `\n\t\t\t\tResponse Type: Text/Conversational Response\n\t\t\t\tResponse Content: ${textResponse.substring(0, 1000)}${textResponse.length > 1000 ? '...' : ''}\n\t\t\t`;\n\t\t\t} else {\n\t\t\t\tcomponent_info = 'No component or response context available';\n\t\t\t}\n\n\t\t\tconst component_data = componentData ? `Component Data: ${JSON.stringify(componentData, null, 2)}` : '';\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('actions', {\n\t\t\t\tORIGINAL_USER_PROMPT: originalUserPrompt,\n\t\t\t\tCOMPONENT_INFO: component_info,\n\t\t\t\tCOMPONENT_DATA: component_data,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\n\t\t\t});\n\n\t\t\t// Use appropriate model based on strategy (simple task)\n\t\t\tconst result = await LLM.stream<any>(\n\t\t\t\t{\n\t\t\t\t\tsys: prompts.system,\n\t\t\t\t\tuser: prompts.user\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmodel: this.getModelForTask('simple'),\n\t\t\t\t\tmaxTokens: 1200,\n\t\t\t\t\ttemperature: 0.7,\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\n\t\t\t\t},\n\t\t\t\ttrue // Parse as JSON\n\t\t\t) as any;\n\n\t\t\tconst nextQuestions = result.nextQuestions || [];\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'Next questions generated',\n\t\t\t\t'Generated intelligent follow-up questions based on component',\n\t\t\t\t{\n\t\t\t\t\tcount: nextQuestions.length,\n\t\t\t\t\tquestions: nextQuestions\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn nextQuestions;\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating next questions: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Next questions generation error details:`, error);\n\t\t\tlogCollector?.error(`Error generating next questions: ${errorMsg}`);\n\t\t\t// Return empty array on error instead of throwing\n\t\t\treturn [];\n\t\t}\n\t}\n\n}\n","import path from 'path';\nimport fs from 'fs';\nimport { logger } from '../utils/logger';\n\n/**\n * Schema class for managing database schema operations\n */\nexport class Schema {\n private schemaFilePath: string;\n private cachedSchema: any = null;\n\n constructor(schemaFilePath?: string) {\n this.schemaFilePath = schemaFilePath || path.join(process.cwd(), '../analysis/data/schema.json');\n }\n\n /**\n * Gets the database schema from the schema file\n * @returns Parsed schema object or null if error occurs\n */\n getDatabaseSchema(): any | null {\n logger.info(`SCHEMA_FILE_PATH: ${this.schemaFilePath}`);\n\n try {\n // Create directory structure if it doesn't exist\n const dir = path.dirname(this.schemaFilePath);\n if (!fs.existsSync(dir)) {\n logger.info(`Creating directory structure: ${dir}`);\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Create file with empty schema if it doesn't exist\n if (!fs.existsSync(this.schemaFilePath)) {\n logger.info(`Schema file does not exist at ${this.schemaFilePath}, creating with empty schema`);\n const initialSchema = {\n database: '',\n schema: '',\n description: '',\n tables: [],\n relationships: []\n };\n fs.writeFileSync(this.schemaFilePath, JSON.stringify(initialSchema, null, 4));\n this.cachedSchema = initialSchema;\n return initialSchema;\n }\n\n const fileContent = fs.readFileSync(this.schemaFilePath, 'utf-8');\n const schema = JSON.parse(fileContent);\n this.cachedSchema = schema;\n return schema;\n } catch (error) {\n logger.error('Error parsing schema file:', error);\n return null;\n }\n }\n\n /**\n * Gets the cached schema or loads it if not cached\n * @returns Cached schema or freshly loaded schema\n */\n getSchema(): any | null {\n if (this.cachedSchema) {\n return this.cachedSchema;\n }\n return this.getDatabaseSchema();\n }\n\n /**\n * Generates database schema documentation for LLM from Snowflake JSON schema\n * @returns Formatted schema documentation string\n */\n generateSchemaDocumentation(): string {\n const schema = this.getSchema();\n\n if (!schema) {\n logger.warn('No database schema found.');\n return 'No database schema available.';\n }\n\n const tables: string[] = [];\n\n // Header information\n tables.push(`Database: ${schema.database}`);\n tables.push(`Schema: ${schema.schema}`);\n tables.push(`Description: ${schema.description}`);\n tables.push('');\n tables.push('='.repeat(80));\n tables.push('');\n\n // Process each table\n for (const table of schema.tables) {\n const tableInfo: string[] = [];\n\n tableInfo.push(`TABLE: ${table.fullName}`);\n tableInfo.push(`Description: ${table.description}`);\n tableInfo.push(`Row Count: ~${table.rowCount.toLocaleString()}`);\n tableInfo.push('');\n tableInfo.push('Columns:');\n\n // Process columns\n for (const column of table.columns) {\n let columnLine = ` - ${column.name}: ${column.type}`;\n\n if ((column as any).isPrimaryKey) {\n columnLine += ' (PRIMARY KEY)';\n }\n\n if ((column as any).isForeignKey && (column as any).references) {\n columnLine += ` (FK -> ${(column as any).references.table}.${(column as any).references.column})`;\n }\n\n if (!column.nullable) {\n columnLine += ' NOT NULL';\n }\n\n if (column.description) {\n columnLine += ` - ${column.description}`;\n }\n\n tableInfo.push(columnLine);\n\n // Add value examples for categorical columns\n if ((column as any).sampleValues && (column as any).sampleValues.length > 0) {\n tableInfo.push(` Sample values: [${(column as any).sampleValues.join(', ')}]`);\n }\n\n // Add statistics if available\n if ((column as any).statistics) {\n const stats = (column as any).statistics;\n if (stats.min !== undefined && stats.max !== undefined) {\n tableInfo.push(` Range: ${stats.min} to ${stats.max}`);\n }\n if (stats.distinct !== undefined) {\n tableInfo.push(` Distinct values: ${stats.distinct.toLocaleString()}`);\n }\n }\n }\n\n tableInfo.push('');\n tables.push(tableInfo.join('\\n'));\n }\n\n // Add relationships section\n tables.push('='.repeat(80));\n tables.push('');\n tables.push('TABLE RELATIONSHIPS:');\n tables.push('');\n\n for (const rel of schema.relationships) {\n tables.push(`${rel.from} -> ${rel.to} (${rel.type}): ${rel.keys.join(' = ')}`);\n }\n\n return tables.join('\\n');\n }\n\n /**\n * Clears the cached schema, forcing a reload on next access\n */\n clearCache(): void {\n this.cachedSchema = null;\n }\n\n /**\n * Sets a custom schema file path\n * @param filePath - Path to the schema file\n */\n setSchemaPath(filePath: string): void {\n this.schemaFilePath = filePath;\n this.clearCache();\n }\n}\n\n// Export a singleton instance for use across the application\nexport const schema = new Schema();\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport Groq from \"groq-sdk\";\nimport { GoogleGenerativeAI, SchemaType, FunctionDeclarationSchemaProperty } from \"@google/generative-ai\";\nimport OpenAI from \"openai\";\nimport { jsonrepair } from 'jsonrepair';\nimport { llmUsageLogger, LLMUsageEntry } from './utils/llm-usage-logger';\nimport { userPromptErrorLogger } from './utils/user-prompt-error-logger';\n\n// System prompt can be either a simple string or an array of content blocks for caching\ntype SystemPrompt = string | Anthropic.Messages.TextBlockParam[];\n\ninterface LLMMessages {\n sys: SystemPrompt;\n user: string;\n prefill?: string; // Optional assistant prefill to force specific output format (e.g., \"{\" for JSON)\n}\n\ninterface LLMOptions {\n model?: string;\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n apiKey?: string;\n partial?: (chunk: string) => void; // Callback for each chunk\n}\n\ninterface Tool {\n name: string;\n description: string;\n input_schema: {\n type: string;\n properties: Record<string, any>;\n required?: string[];\n };\n}\n\ninterface ToolResult {\n tool_use_id: string;\n content: string;\n is_error?: boolean;\n}\n\nexport class LLM {\n /* Get a complete text response from an LLM (Anthropic or Groq) */\n static async text(messages: LLMMessages, options: LLMOptions = {}): Promise<string> {\n const [provider, modelName] = this._parseModel(options.model);\n\n if (provider === 'anthropic') {\n return this._anthropicText(messages, modelName, options);\n } else if (provider === 'groq') {\n return this._groqText(messages, modelName, options);\n } else if (provider === 'gemini') {\n return this._geminiText(messages, modelName, options);\n } else if (provider === 'openai') {\n return this._openaiText(messages, modelName, options);\n } else {\n throw new Error(`Unsupported provider: ${provider}. Use \"anthropic\", \"groq\", \"gemini\", or \"openai\"`);\n }\n }\n\n /* Stream response from an LLM (Anthropic or Groq) */\n static async stream<T = string>(\n messages: LLMMessages,\n options: LLMOptions = {},\n json?: boolean\n ): Promise<T extends string ? string : any> {\n const [provider, modelName] = this._parseModel(options.model);\n\n if (provider === 'anthropic') {\n return this._anthropicStream(messages, modelName, options, json);\n } else if (provider === 'groq') {\n return this._groqStream(messages, modelName, options, json);\n } else if (provider === 'gemini') {\n return this._geminiStream(messages, modelName, options, json);\n } else if (provider === 'openai') {\n return this._openaiStream(messages, modelName, options, json);\n } else {\n throw new Error(`Unsupported provider: ${provider}. Use \"anthropic\", \"groq\", \"gemini\", or \"openai\"`);\n }\n }\n\n /* Stream response with tool calling support (Anthropic and Gemini) */\n static async streamWithTools(\n messages: LLMMessages,\n tools: Tool[],\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\n options: LLMOptions = {},\n maxIterations: number = 3\n ): Promise<string> {\n const [provider, modelName] = this._parseModel(options.model);\n\n if (provider === 'anthropic') {\n return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);\n } else if (provider === 'gemini') {\n return this._geminiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);\n } else if (provider === 'openai') {\n return this._openaiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);\n } else {\n throw new Error(`Tool calling is only supported for Anthropic, Gemini, and OpenAI models`);\n }\n }\n\n // ============================================================\n // PRIVATE HELPER METHODS\n // ============================================================\n\n /**\n * Normalize system prompt to Anthropic format\n * Converts string to array format if needed\n * @param sys - System prompt (string or array of blocks)\n * @returns Normalized system prompt for Anthropic API\n */\n private static _normalizeSystemPrompt(sys: SystemPrompt): string | Anthropic.Messages.TextBlockParam[] {\n // If it's already a string, return as-is for backward compatibility\n if (typeof sys === 'string') {\n return sys;\n }\n\n // If it's an array, return it for caching support\n return sys;\n }\n\n /**\n * Log cache usage metrics from Anthropic API response\n * Shows cache hits, costs, and savings\n */\n private static _logCacheUsage(usage: any): void {\n if (!usage) return;\n\n const inputTokens = usage.input_tokens || 0;\n const cacheCreationTokens = usage.cache_creation_input_tokens || 0;\n const cacheReadTokens = usage.cache_read_input_tokens || 0;\n const outputTokens = usage.output_tokens || 0;\n\n // Pricing (per 1M tokens) for Claude Haiku 4.5\n const INPUT_PRICE = 0.80; // $0.80 per 1M tokens\n const OUTPUT_PRICE = 4.00; // $4.00 per 1M tokens\n const CACHE_WRITE_PRICE = 1.00; // $1.00 per 1M tokens (25% markup)\n const CACHE_READ_PRICE = 0.08; // $0.08 per 1M tokens (90% discount)\n\n // Calculate costs\n const regularInputCost = (inputTokens / 1_000_000) * INPUT_PRICE;\n const cacheWriteCost = (cacheCreationTokens / 1_000_000) * CACHE_WRITE_PRICE;\n const cacheReadCost = (cacheReadTokens / 1_000_000) * CACHE_READ_PRICE;\n const outputCost = (outputTokens / 1_000_000) * OUTPUT_PRICE;\n const totalCost = regularInputCost + cacheWriteCost + cacheReadCost + outputCost;\n\n // Calculate what it would have cost without caching\n const totalInputTokens = inputTokens + cacheCreationTokens + cacheReadTokens;\n const costWithoutCache = (totalInputTokens / 1_000_000) * INPUT_PRICE + outputCost;\n const savings = costWithoutCache - totalCost;\n const savingsPercent = costWithoutCache > 0 ? (savings / costWithoutCache * 100) : 0;\n\n // Log metrics\n console.log('\\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.log('💰 PROMPT CACHING METRICS');\n console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n\n console.log('\\n📊 Token Usage:');\n console.log(` Input (regular): ${inputTokens.toLocaleString()} tokens`);\n if (cacheCreationTokens > 0) {\n console.log(` Cache write: ${cacheCreationTokens.toLocaleString()} tokens (first request)`);\n }\n if (cacheReadTokens > 0) {\n console.log(` Cache read: ${cacheReadTokens.toLocaleString()} tokens ⚡ HIT!`);\n }\n console.log(` Output: ${outputTokens.toLocaleString()} tokens`);\n console.log(` Total input: ${totalInputTokens.toLocaleString()} tokens`);\n\n console.log('\\n💵 Cost Breakdown:');\n console.log(` Input (regular): $${regularInputCost.toFixed(6)}`);\n if (cacheCreationTokens > 0) {\n console.log(` Cache write: $${cacheWriteCost.toFixed(6)}`);\n }\n if (cacheReadTokens > 0) {\n console.log(` Cache read: $${cacheReadCost.toFixed(6)} (90% off!)`);\n }\n console.log(` Output: $${outputCost.toFixed(6)}`);\n console.log(` ─────────────────────────────────────`);\n console.log(` Total cost: $${totalCost.toFixed(6)}`);\n\n if (cacheReadTokens > 0) {\n console.log(`\\n💎 Savings: $${savings.toFixed(6)} (${savingsPercent.toFixed(1)}% off)`);\n console.log(` Without cache: $${costWithoutCache.toFixed(6)}`);\n } else if (cacheCreationTokens > 0) {\n console.log(`\\n⏱️ Cache created - next request will be ~90% cheaper!`);\n }\n\n console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n');\n }\n\n /**\n * Parse model string to extract provider and model name\n * @param modelString - Format: \"provider/model-name\" or just \"model-name\"\n * @returns [provider, modelName]\n *\n * @example\n * \"anthropic/claude-sonnet-4-5\" → [\"anthropic\", \"claude-sonnet-4-5\"]\n * \"groq/openai/gpt-oss-120b\" → [\"groq\", \"openai/gpt-oss-120b\"]\n * \"claude-sonnet-4-5\" → [\"anthropic\", \"claude-sonnet-4-5\"] (default)\n */\n private static _parseModel(modelString?: string): [string, string] {\n if (!modelString) {\n // Default to Anthropic Claude\n return ['anthropic', 'claude-sonnet-4-5'];\n }\n\n // Check if model string has provider prefix\n if (modelString.includes('/')) {\n // Split only on the FIRST slash to handle models like \"groq/openai/gpt-oss-120b\"\n const firstSlashIndex = modelString.indexOf('/');\n const provider = modelString.substring(0, firstSlashIndex).toLowerCase().trim();\n const model = modelString.substring(firstSlashIndex + 1).trim();\n return [provider, model];\n }\n\n // No prefix, assume Anthropic\n return ['anthropic', modelString];\n }\n\n // ============================================================\n // ANTHROPIC IMPLEMENTATION\n // ============================================================\n\n private static async _anthropicText(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions\n ): Promise<string> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\n const client = new Anthropic({\n apiKey: apiKey,\n });\n\n try {\n const response = await client.messages.create({\n model: modelName,\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n system: this._normalizeSystemPrompt(messages.sys) as any,\n messages: [{\n role: \"user\",\n content: messages.user\n }]\n });\n\n const durationMs = Date.now() - startTime;\n const usage = response.usage as any;\n\n // Log usage\n const inputTokens = usage?.input_tokens || 0;\n const outputTokens = usage?.output_tokens || 0;\n const cacheReadTokens = usage?.cache_read_input_tokens || 0;\n const cacheWriteTokens = usage?.cache_creation_input_tokens || 0;\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: 'text',\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n totalTokens: inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens),\n durationMs,\n success: true,\n });\n\n const textBlock = response.content.find(block => block.type === 'text');\n return textBlock?.type === 'text' ? textBlock.text : '';\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: 'text',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _anthropicStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\n const client = new Anthropic({\n apiKey: apiKey,\n });\n\n try {\n // Build messages array\n const apiMessages: Anthropic.Messages.MessageParam[] = [{\n role: \"user\",\n content: messages.user\n }];\n\n // Add prefill to force specific output format (e.g., \"{\" for JSON)\n // For JSON mode, automatically prefill with \"{\" if no explicit prefill provided\n const prefill = messages.prefill || (json ? \"{\" : undefined);\n if (prefill) {\n apiMessages.push({\n role: \"assistant\",\n content: prefill\n });\n }\n\n const stream = await client.messages.create({\n model: modelName,\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n system: this._normalizeSystemPrompt(messages.sys) as any,\n messages: apiMessages,\n stream: true,\n });\n\n // Start with prefill if provided (since model continues from there)\n let fullText = prefill || '';\n let usage: any = null;\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheReadTokens = 0;\n let cacheWriteTokens = 0;\n\n // Process stream\n for await (const chunk of stream) {\n if (chunk.type === 'content_block_delta' && chunk.delta.type === 'text_delta') {\n const text = chunk.delta.text;\n fullText += text;\n\n // Call partial callback if provided\n if (options.partial) {\n options.partial(text);\n }\n } else if (chunk.type === 'message_start' && (chunk as any).message?.usage) {\n // Capture input tokens from message_start\n const msgUsage = (chunk as any).message.usage;\n inputTokens = msgUsage.input_tokens || 0;\n cacheReadTokens = msgUsage.cache_read_input_tokens || 0;\n cacheWriteTokens = msgUsage.cache_creation_input_tokens || 0;\n } else if (chunk.type === 'message_delta' && (chunk as any).usage) {\n // Capture output tokens from message_delta event\n usage = (chunk as any).usage;\n outputTokens = usage.output_tokens || 0;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Log usage\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: 'stream',\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n totalTokens: inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens),\n durationMs,\n success: true,\n });\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: 'stream',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _anthropicStreamWithTools(\n messages: LLMMessages,\n tools: Tool[],\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\n modelName: string,\n options: LLMOptions,\n maxIterations: number\n ): Promise<string> {\n const methodStartTime = Date.now();\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\n const client = new Anthropic({\n apiKey: apiKey,\n });\n\n // Conversation history for tool calling loop\n const conversationMessages: Anthropic.MessageParam[] = [{\n role: \"user\",\n content: messages.user\n }];\n\n let iterations = 0;\n let finalText = '';\n let totalToolCalls = 0;\n\n // Track cumulative usage across all iterations\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCacheReadTokens = 0;\n let totalCacheWriteTokens = 0;\n\n while (iterations < maxIterations) {\n iterations++;\n const iterationStartTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n\n // Use streaming API\n const stream = await client.messages.create({\n model: modelName,\n max_tokens: options.maxTokens || 4000,\n temperature: options.temperature,\n system: this._normalizeSystemPrompt(messages.sys) as any,\n messages: conversationMessages,\n tools: tools as any,\n stream: true, // Enable streaming\n });\n\n // Collect the response content and stop reason\n let stopReason: string | null = null;\n const contentBlocks: any[] = [];\n let currentTextBlock = '';\n let currentToolUse: any = null;\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheReadTokens = 0;\n let cacheWriteTokens = 0;\n\n // Process the stream\n for await (const chunk of stream) {\n if (chunk.type === 'message_start') {\n // Reset for new message\n contentBlocks.length = 0;\n currentTextBlock = '';\n currentToolUse = null;\n // Capture input tokens from message_start\n const msgUsage = (chunk as any).message?.usage;\n if (msgUsage) {\n inputTokens = msgUsage.input_tokens || 0;\n cacheReadTokens = msgUsage.cache_read_input_tokens || 0;\n cacheWriteTokens = msgUsage.cache_creation_input_tokens || 0;\n }\n }\n\n if (chunk.type === 'content_block_start') {\n if (chunk.content_block.type === 'text') {\n currentTextBlock = '';\n } else if (chunk.content_block.type === 'tool_use') {\n currentToolUse = {\n type: 'tool_use',\n id: chunk.content_block.id,\n name: chunk.content_block.name,\n input: {}\n };\n }\n }\n\n if (chunk.type === 'content_block_delta') {\n if (chunk.delta.type === 'text_delta') {\n // Stream text chunks to callback\n const text = chunk.delta.text;\n currentTextBlock += text;\n if (options.partial) {\n options.partial(text);\n }\n } else if (chunk.delta.type === 'input_json_delta' && currentToolUse) {\n // Accumulate tool input JSON\n currentToolUse.inputJson = (currentToolUse.inputJson || '') + chunk.delta.partial_json;\n }\n }\n\n if (chunk.type === 'content_block_stop') {\n if (currentTextBlock) {\n contentBlocks.push({\n type: 'text',\n text: currentTextBlock\n });\n finalText = currentTextBlock; // Keep track of final text\n currentTextBlock = '';\n } else if (currentToolUse) {\n // Parse the accumulated JSON input\n try {\n currentToolUse.input = currentToolUse.inputJson ? JSON.parse(currentToolUse.inputJson) : {};\n } catch (error) {\n currentToolUse.input = {};\n }\n delete currentToolUse.inputJson;\n contentBlocks.push(currentToolUse);\n currentToolUse = null;\n }\n }\n\n if (chunk.type === 'message_delta') {\n stopReason = chunk.delta.stop_reason || stopReason;\n // Capture output tokens from message_delta\n if ((chunk as any).usage) {\n outputTokens = (chunk as any).usage.output_tokens || 0;\n }\n }\n\n if (chunk.type === 'message_stop') {\n // Message complete\n break;\n }\n }\n\n const iterationDuration = Date.now() - iterationStartTime;\n const toolUsesInIteration = contentBlocks.filter(block => block.type === 'tool_use').length;\n totalToolCalls += toolUsesInIteration;\n\n // Update cumulative totals\n totalInputTokens += inputTokens;\n totalOutputTokens += outputTokens;\n totalCacheReadTokens += cacheReadTokens;\n totalCacheWriteTokens += cacheWriteTokens;\n\n // Log this iteration\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'anthropic',\n model: modelName,\n method: `streamWithTools[iter=${iterations}]`,\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n totalTokens: inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens),\n durationMs: iterationDuration,\n toolCalls: toolUsesInIteration,\n success: true,\n });\n\n // Check stop reason\n if (stopReason === 'end_turn') {\n // Final text response already streamed\n break;\n }\n\n if (stopReason === 'tool_use') {\n // Find all tool use blocks\n const toolUses = contentBlocks.filter(block => block.type === 'tool_use');\n\n if (toolUses.length === 0) {\n break;\n }\n\n // Add assistant's response to conversation\n conversationMessages.push({\n role: \"assistant\",\n content: contentBlocks\n });\n\n // Execute all tools and collect results\n const toolResults: Anthropic.MessageParam = {\n role: \"user\",\n content: []\n };\n\n for (const toolUse of toolUses) {\n try {\n const result = await toolHandler(toolUse.name, toolUse.input);\n // Truncate very large results to reduce memory and token usage\n let resultContent = typeof result === 'string' ? result : JSON.stringify(result);\n const MAX_RESULT_LENGTH = 50000; // ~12k tokens max per tool result\n if (resultContent.length > MAX_RESULT_LENGTH) {\n resultContent = resultContent.substring(0, MAX_RESULT_LENGTH) +\n '\\n\\n... [Result truncated - showing first 50000 characters of ' + resultContent.length + ' total]';\n }\n (toolResults.content as any[]).push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: resultContent\n });\n } catch (error) {\n (toolResults.content as any[]).push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: error instanceof Error ? error.message : String(error),\n is_error: true\n });\n }\n }\n\n // Add tool results to conversation\n conversationMessages.push(toolResults);\n } else {\n // Unexpected stop reason, final text already streamed\n break;\n }\n }\n\n // Log total summary for all iterations\n const totalDuration = Date.now() - methodStartTime;\n if (iterations > 1) {\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId: llmUsageLogger.generateRequestId(),\n provider: 'anthropic',\n model: modelName,\n method: `streamWithTools[TOTAL:${iterations}iters]`,\n inputTokens: totalInputTokens,\n outputTokens: totalOutputTokens,\n cacheReadTokens: totalCacheReadTokens,\n cacheWriteTokens: totalCacheWriteTokens,\n totalTokens: totalInputTokens + totalOutputTokens + totalCacheReadTokens + totalCacheWriteTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, totalInputTokens, totalOutputTokens, totalCacheReadTokens, totalCacheWriteTokens),\n durationMs: totalDuration,\n toolCalls: totalToolCalls,\n success: true,\n });\n }\n\n if (iterations >= maxIterations) {\n throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);\n }\n\n return finalText;\n }\n\n // ============================================================\n // GROQ IMPLEMENTATION\n // ============================================================\n\n private static async _groqText(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions\n ): Promise<string> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const client = new Groq({\n apiKey: options.apiKey || process.env.GROQ_API_KEY || \"\",\n });\n\n try {\n const response = await client.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: messages.sys as string },\n { role: 'user', content: messages.user }\n ],\n temperature: options.temperature,\n max_tokens: options.maxTokens || 1000,\n });\n\n const durationMs = Date.now() - startTime;\n const usage = response.usage;\n const inputTokens = usage?.prompt_tokens || 0;\n const outputTokens = usage?.completion_tokens || 0;\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'groq',\n model: modelName,\n method: 'text',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n return response.choices[0]?.message?.content || '';\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'groq',\n model: modelName,\n method: 'text',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _groqStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.GROQ_API_KEY || \"\";\n const client = new Groq({\n apiKey: apiKey,\n });\n\n try {\n const stream = await client.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: messages.sys as string },\n { role: 'user', content: messages.user }\n ],\n temperature: options.temperature,\n max_tokens: options.maxTokens || 1000,\n stream: true,\n response_format: json ? { type: 'json_object' } : undefined\n });\n\n let fullText = '';\n let inputTokens = 0;\n let outputTokens = 0;\n\n // Process stream\n for await (const chunk of stream) {\n const text = chunk.choices[0]?.delta?.content || '';\n if (text) {\n fullText += text;\n\n // Call partial callback if provided\n if (options.partial) {\n options.partial(text);\n }\n }\n // Groq provides usage in the last chunk\n if ((chunk as any).x_groq?.usage) {\n inputTokens = (chunk as any).x_groq.usage.prompt_tokens || 0;\n outputTokens = (chunk as any).x_groq.usage.completion_tokens || 0;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Estimate tokens if not provided (Groq streaming may not always provide usage)\n if (inputTokens === 0) {\n // Rough estimate: 1 token ≈ 4 characters\n const sysPrompt = typeof messages.sys === 'string' ? messages.sys : messages.sys.map(b => b.text).join('');\n inputTokens = Math.ceil((sysPrompt.length + messages.user.length) / 4);\n }\n if (outputTokens === 0) {\n outputTokens = Math.ceil(fullText.length / 4);\n }\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'groq',\n model: modelName,\n method: 'stream',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'groq',\n model: modelName,\n method: 'stream',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n // ============================================================\n // GEMINI IMPLEMENTATION\n // ============================================================\n\n private static async _geminiText(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions\n ): Promise<string> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.GEMINI_API_KEY || \"\";\n const genAI = new GoogleGenerativeAI(apiKey);\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n try {\n const model = genAI.getGenerativeModel({\n model: modelName,\n systemInstruction: systemPrompt,\n generationConfig: {\n maxOutputTokens: options.maxTokens || 1000,\n temperature: options.temperature,\n topP: options.topP,\n }\n });\n\n const result = await model.generateContent(messages.user);\n const response = await result.response;\n const text = response.text();\n const durationMs = Date.now() - startTime;\n\n // Gemini provides usage metadata\n const usage = response.usageMetadata;\n const inputTokens = usage?.promptTokenCount || Math.ceil((systemPrompt.length + messages.user.length) / 4);\n const outputTokens = usage?.candidatesTokenCount || Math.ceil(text.length / 4);\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: 'text',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n return text;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: 'text',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _geminiStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.GEMINI_API_KEY || \"\";\n const genAI = new GoogleGenerativeAI(apiKey);\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n try {\n const model = genAI.getGenerativeModel({\n model: modelName,\n systemInstruction: systemPrompt,\n generationConfig: {\n maxOutputTokens: options.maxTokens || 1000,\n temperature: options.temperature,\n topP: options.topP,\n responseMimeType: json ? 'application/json' : undefined,\n }\n });\n\n const result = await model.generateContentStream(messages.user);\n\n let fullText = '';\n let inputTokens = 0;\n let outputTokens = 0;\n\n // Process stream\n for await (const chunk of result.stream) {\n const text = chunk.text();\n if (text) {\n fullText += text;\n\n // Call partial callback if provided\n if (options.partial) {\n options.partial(text);\n }\n }\n // Capture usage from final chunk\n if (chunk.usageMetadata) {\n inputTokens = chunk.usageMetadata.promptTokenCount || 0;\n outputTokens = chunk.usageMetadata.candidatesTokenCount || 0;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Estimate tokens if not provided\n if (inputTokens === 0) {\n inputTokens = Math.ceil((systemPrompt.length + messages.user.length) / 4);\n }\n if (outputTokens === 0) {\n outputTokens = Math.ceil(fullText.length / 4);\n }\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: 'stream',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: 'stream',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _geminiStreamWithTools(\n messages: LLMMessages,\n tools: Tool[],\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\n modelName: string,\n options: LLMOptions,\n maxIterations: number\n ): Promise<string> {\n const methodStartTime = Date.now();\n const apiKey = options.apiKey || process.env.GEMINI_API_KEY || \"\";\n const genAI = new GoogleGenerativeAI(apiKey);\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n // Convert tools to Gemini function declarations format\n const functionDeclarations = tools.map(tool => ({\n name: tool.name,\n description: tool.description,\n parameters: {\n type: SchemaType.OBJECT,\n properties: tool.input_schema.properties as { [key: string]: FunctionDeclarationSchemaProperty },\n required: tool.input_schema.required || []\n }\n }));\n\n const model = genAI.getGenerativeModel({\n model: modelName,\n systemInstruction: systemPrompt,\n tools: [{ functionDeclarations }],\n generationConfig: {\n maxOutputTokens: options.maxTokens || 4000,\n temperature: options.temperature,\n topP: options.topP,\n }\n });\n\n // Start a chat session to maintain conversation history for tool calling loop\n const chat = model.startChat({\n history: []\n });\n\n let iterations = 0;\n let finalText = '';\n let currentUserMessage = messages.user;\n let totalToolCalls = 0;\n\n // Track cumulative usage across all iterations\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n\n while (iterations < maxIterations) {\n iterations++;\n const iterationStartTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n\n // Send message and stream the response\n const result = await chat.sendMessageStream(currentUserMessage);\n\n let responseText = '';\n const functionCalls: Array<{ name: string; args: any }> = [];\n let inputTokens = 0;\n let outputTokens = 0;\n\n // Process the stream\n for await (const chunk of result.stream) {\n const candidate = chunk.candidates?.[0];\n if (!candidate) continue;\n\n for (const part of candidate.content?.parts || []) {\n if (part.text) {\n responseText += part.text;\n // Stream text chunks to callback\n if (options.partial) {\n options.partial(part.text);\n }\n } else if (part.functionCall) {\n functionCalls.push({\n name: part.functionCall.name,\n args: part.functionCall.args\n });\n }\n }\n\n // Capture usage from chunks\n if (chunk.usageMetadata) {\n inputTokens = chunk.usageMetadata.promptTokenCount || 0;\n outputTokens = chunk.usageMetadata.candidatesTokenCount || 0;\n }\n }\n\n const iterationDuration = Date.now() - iterationStartTime;\n const toolCallsInIteration = functionCalls.length;\n totalToolCalls += toolCallsInIteration;\n\n // Estimate tokens if not provided by API\n if (inputTokens === 0) {\n const userMsg = typeof currentUserMessage === 'string' ? currentUserMessage : JSON.stringify(currentUserMessage);\n inputTokens = Math.ceil((systemPrompt.length + userMsg.length) / 4);\n }\n if (outputTokens === 0) {\n outputTokens = Math.ceil(responseText.length / 4);\n }\n\n // Update cumulative totals\n totalInputTokens += inputTokens;\n totalOutputTokens += outputTokens;\n\n // Log this iteration\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'gemini',\n model: modelName,\n method: `streamWithTools[iter=${iterations}]`,\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs: iterationDuration,\n toolCalls: toolCallsInIteration,\n success: true,\n });\n\n // If no function calls, we're done\n if (functionCalls.length === 0) {\n finalText = responseText;\n break;\n }\n\n // Execute all function calls and collect results\n const functionResponses: Array<{ name: string; response: any }> = [];\n\n for (const fc of functionCalls) {\n try {\n const result = await toolHandler(fc.name, fc.args);\n // Truncate very large results to reduce memory and token usage\n let resultContent = typeof result === 'string' ? result : JSON.stringify(result);\n const MAX_RESULT_LENGTH = 50000; // ~12k tokens max per tool result\n if (resultContent.length > MAX_RESULT_LENGTH) {\n resultContent = resultContent.substring(0, MAX_RESULT_LENGTH) +\n '\\n\\n... [Result truncated - showing first 50000 characters of ' + resultContent.length + ' total]';\n }\n functionResponses.push({\n name: fc.name,\n response: { result: resultContent }\n });\n } catch (error) {\n functionResponses.push({\n name: fc.name,\n response: { error: error instanceof Error ? error.message : String(error) }\n });\n }\n }\n\n // Send function responses back to the model\n // Build the function response parts for the next message\n const functionResponseParts = functionResponses.map(fr => ({\n functionResponse: {\n name: fr.name,\n response: fr.response\n }\n }));\n\n // Send function responses as the next user message\n currentUserMessage = functionResponseParts as any;\n }\n\n // Log total summary for all iterations\n const totalDuration = Date.now() - methodStartTime;\n if (iterations > 1) {\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId: llmUsageLogger.generateRequestId(),\n provider: 'gemini',\n model: modelName,\n method: `streamWithTools[TOTAL:${iterations}iters]`,\n inputTokens: totalInputTokens,\n outputTokens: totalOutputTokens,\n totalTokens: totalInputTokens + totalOutputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, totalInputTokens, totalOutputTokens),\n durationMs: totalDuration,\n toolCalls: totalToolCalls,\n success: true,\n });\n }\n\n if (iterations >= maxIterations) {\n throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);\n }\n\n return finalText;\n }\n\n // ============================================================\n // OPENAI IMPLEMENTATION\n // ============================================================\n\n private static async _openaiText(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions\n ): Promise<string> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.OPENAI_API_KEY || \"\";\n const openai = new OpenAI({ apiKey });\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n try {\n const response = await openai.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: messages.user }\n ],\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n top_p: options.topP,\n });\n\n const durationMs = Date.now() - startTime;\n const usage = response.usage;\n const inputTokens = usage?.prompt_tokens || 0;\n const outputTokens = usage?.completion_tokens || 0;\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'openai',\n model: modelName,\n method: 'text',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n return response.choices[0]?.message?.content || '';\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'openai',\n model: modelName,\n method: 'text',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _openaiStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const startTime = Date.now();\n const requestId = llmUsageLogger.generateRequestId();\n const apiKey = options.apiKey || process.env.OPENAI_API_KEY || \"\";\n const openai = new OpenAI({ apiKey });\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n try {\n const stream = await openai.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: messages.user }\n ],\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n top_p: options.topP,\n response_format: json ? { type: 'json_object' } : undefined,\n stream: true,\n stream_options: { include_usage: true }, // Request usage info in stream\n });\n\n let fullText = '';\n let inputTokens = 0;\n let outputTokens = 0;\n\n for await (const chunk of stream) {\n const content = chunk.choices[0]?.delta?.content || '';\n if (content) {\n fullText += content;\n\n // Call partial callback if provided\n if (options.partial) {\n options.partial(content);\n }\n }\n // OpenAI provides usage in the final chunk when stream_options.include_usage is true\n if (chunk.usage) {\n inputTokens = chunk.usage.prompt_tokens || 0;\n outputTokens = chunk.usage.completion_tokens || 0;\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Estimate tokens if not provided\n if (inputTokens === 0) {\n inputTokens = Math.ceil((systemPrompt.length + messages.user.length) / 4);\n }\n if (outputTokens === 0) {\n outputTokens = Math.ceil(fullText.length / 4);\n }\n\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'openai',\n model: modelName,\n method: 'stream',\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: llmUsageLogger.calculateCost(modelName, inputTokens, outputTokens),\n durationMs,\n success: true,\n });\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n llmUsageLogger.log({\n timestamp: new Date().toISOString(),\n requestId,\n provider: 'openai',\n model: modelName,\n method: 'stream',\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n costUSD: 0,\n durationMs,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private static async _openaiStreamWithTools(\n messages: LLMMessages,\n tools: Tool[],\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\n modelName: string,\n options: LLMOptions,\n maxIterations: number\n ): Promise<string> {\n const apiKey = options.apiKey || process.env.OPENAI_API_KEY || \"\";\n const openai = new OpenAI({ apiKey });\n\n // Convert system prompt to string if it's an array\n const systemPrompt = typeof messages.sys === 'string'\n ? messages.sys\n : messages.sys.map(block => block.text).join('\\n');\n\n // Convert tools to OpenAI function format\n const openaiTools: OpenAI.Chat.Completions.ChatCompletionTool[] = tools.map(tool => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: tool.input_schema.type,\n properties: tool.input_schema.properties,\n required: tool.input_schema.required || []\n }\n }\n }));\n\n // Build conversation messages\n const conversationMessages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: messages.user }\n ];\n\n let iterations = 0;\n let finalText = '';\n\n while (iterations < maxIterations) {\n iterations++;\n\n const stream = await openai.chat.completions.create({\n model: modelName,\n messages: conversationMessages,\n max_tokens: options.maxTokens || 4000,\n temperature: options.temperature,\n top_p: options.topP,\n tools: openaiTools,\n stream: true,\n });\n\n let responseText = '';\n const toolCalls: Array<{\n id: string;\n name: string;\n arguments: string;\n }> = [];\n\n // Track tool call assembly (OpenAI streams tool calls in chunks)\n const toolCallsInProgress: Map<number, { id: string; name: string; arguments: string }> = new Map();\n\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n // Handle text content\n if (delta?.content) {\n responseText += delta.content;\n if (options.partial) {\n options.partial(delta.content);\n }\n }\n\n // Handle tool calls\n if (delta?.tool_calls) {\n for (const toolCallDelta of delta.tool_calls) {\n const index = toolCallDelta.index;\n\n if (!toolCallsInProgress.has(index)) {\n toolCallsInProgress.set(index, {\n id: toolCallDelta.id || '',\n name: toolCallDelta.function?.name || '',\n arguments: ''\n });\n }\n\n const tc = toolCallsInProgress.get(index)!;\n\n if (toolCallDelta.id) {\n tc.id = toolCallDelta.id;\n }\n if (toolCallDelta.function?.name) {\n tc.name = toolCallDelta.function.name;\n }\n if (toolCallDelta.function?.arguments) {\n tc.arguments += toolCallDelta.function.arguments;\n }\n }\n }\n }\n\n // Collect completed tool calls\n for (const tc of toolCallsInProgress.values()) {\n if (tc.id && tc.name) {\n toolCalls.push(tc);\n }\n }\n\n // If no tool calls, we're done\n if (toolCalls.length === 0) {\n finalText = responseText;\n break;\n }\n\n // Add assistant message with tool calls to conversation\n conversationMessages.push({\n role: 'assistant',\n content: responseText || null,\n tool_calls: toolCalls.map(tc => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.name,\n arguments: tc.arguments\n }\n }))\n });\n\n // Execute tool calls and add results\n for (const tc of toolCalls) {\n let result: string;\n try {\n const args = JSON.parse(tc.arguments);\n const toolResult = await toolHandler(tc.name, args);\n result = typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult);\n // Truncate very large results to reduce memory and token usage\n const MAX_RESULT_LENGTH = 50000; // ~12k tokens max per tool result\n if (result.length > MAX_RESULT_LENGTH) {\n result = result.substring(0, MAX_RESULT_LENGTH) +\n '\\n\\n... [Result truncated - showing first 50000 characters of ' + result.length + ' total]';\n }\n } catch (error) {\n result = JSON.stringify({ error: error instanceof Error ? error.message : String(error) });\n }\n\n conversationMessages.push({\n role: 'tool',\n tool_call_id: tc.id,\n content: result\n });\n }\n }\n\n if (iterations >= maxIterations) {\n throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);\n }\n\n return finalText;\n }\n\n // ============================================================\n // JSON PARSING HELPER\n // ============================================================\n\n /**\n * Parse JSON string, handling markdown code blocks and surrounding text\n * Enhanced version with jsonrepair to handle malformed JSON from LLMs\n * @param text - Text that may contain JSON wrapped in ```json...``` or with surrounding text\n * @returns Parsed JSON object or array\n */\n private static _parseJSON(text: string): any {\n let jsonText = text.trim();\n\n // Step 1: Remove markdown code blocks (jsonrepair doesn't handle markdown)\n if (jsonText.startsWith('```json')) {\n jsonText = jsonText.replace(/^```json\\s*\\n?/, '').replace(/\\n?```\\s*$/, '');\n } else if (jsonText.startsWith('```')) {\n jsonText = jsonText.replace(/^```\\s*\\n?/, '').replace(/\\n?```\\s*$/, '');\n }\n\n // Step 2: Extract JSON from surrounding text using proper brace matching\n // Find the first JSON object or array and extract only that\n const firstBrace = jsonText.indexOf('{');\n const firstBracket = jsonText.indexOf('[');\n\n // Determine if it's an object or array\n let startIdx = -1;\n let openChar = '';\n let closeChar = '';\n\n if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {\n // Object starts first\n startIdx = firstBrace;\n openChar = '{';\n closeChar = '}';\n } else if (firstBracket !== -1) {\n // Array starts first\n startIdx = firstBracket;\n openChar = '[';\n closeChar = ']';\n }\n\n // If no JSON structure found at all, throw a clear error\n if (startIdx === -1) {\n const error = new Error(`No JSON found in response. LLM returned plain text instead of JSON.`);\n userPromptErrorLogger.logJsonParseError('LLM._parseJSON - No JSON structure found', text, error);\n throw error;\n }\n\n // Find the MATCHING closing brace/bracket (not the last one in the document)\n let depth = 0;\n let inString = false;\n let endIdx = -1;\n\n for (let i = startIdx; i < jsonText.length; i++) {\n const char = jsonText[i];\n const prevChar = i > 0 ? jsonText[i - 1] : '';\n\n // Handle string literals (skip content inside quotes)\n if (char === '\"' && prevChar !== '\\\\') {\n inString = !inString;\n continue;\n }\n\n if (!inString) {\n if (char === openChar) {\n depth++;\n } else if (char === closeChar) {\n depth--;\n if (depth === 0) {\n endIdx = i;\n break;\n }\n }\n }\n }\n\n if (endIdx !== -1) {\n jsonText = jsonText.substring(startIdx, endIdx + 1);\n } else {\n // No matching closing brace found\n const error = new Error(`Incomplete JSON - no matching closing ${closeChar} found.`);\n userPromptErrorLogger.logJsonParseError('LLM._parseJSON - Incomplete JSON', text, error);\n throw error;\n }\n\n // Step 3: Use jsonrepair to fix malformed JSON before parsing\n // This handles: missing commas, trailing commas, incomplete JSON, improper escaping, etc.\n try {\n const repairedJson = jsonrepair(jsonText);\n return JSON.parse(repairedJson);\n } catch (error) {\n // If jsonrepair fails, log the full raw string and throw\n const parseError = error instanceof Error ? error : new Error(String(error));\n userPromptErrorLogger.logJsonParseError('LLM._parseJSON - JSON parse/repair failed', text, parseError);\n throw new Error(`Failed to parse JSON: ${parseError.message}`);\n }\n }\n}","import fs from 'fs';\nimport path from 'path';\n\n/**\n * LLM Usage Logger - Tracks token usage, costs, and timing for all LLM API calls\n */\n\nexport interface LLMUsageEntry {\n timestamp: string;\n requestId: string;\n provider: string;\n model: string;\n method: string; // 'text' | 'stream' | 'streamWithTools'\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n totalTokens: number;\n costUSD: number;\n durationMs: number;\n toolCalls?: number;\n success: boolean;\n error?: string;\n}\n\n// Pricing per 1M tokens\nconst PRICING: Record<string, { input: number; output: number; cacheRead?: number; cacheWrite?: number }> = {\n // Anthropic (December 2025)\n 'claude-opus-4-5': { input: 5.00, output: 25.00, cacheRead: 0.50, cacheWrite: 6.25 },\n 'claude-opus-4-5-20251101': { input: 5.00, output: 25.00, cacheRead: 0.50, cacheWrite: 6.25 },\n 'claude-sonnet-4-5': { input: 3.00, output: 15.00, cacheRead: 0.30, cacheWrite: 3.75 },\n 'claude-sonnet-4-5-20250929': { input: 3.00, output: 15.00, cacheRead: 0.30, cacheWrite: 3.75 },\n 'claude-haiku-4-5': { input: 1.00, output: 5.00, cacheRead: 0.10, cacheWrite: 1.25 },\n 'claude-haiku-4-5-20251001': { input: 1.00, output: 5.00, cacheRead: 0.10, cacheWrite: 1.25 },\n 'claude-3-5-sonnet-20241022': { input: 3.00, output: 15.00, cacheRead: 0.30, cacheWrite: 3.75 },\n 'claude-3-5-haiku-20241022': { input: 1.00, output: 5.00, cacheRead: 0.10, cacheWrite: 1.25 },\n 'claude-3-opus-20240229': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },\n 'claude-3-sonnet-20240229': { input: 3.00, output: 15.00, cacheRead: 0.30, cacheWrite: 3.75 },\n 'claude-3-haiku-20240307': { input: 0.25, output: 1.25, cacheRead: 0.03, cacheWrite: 0.30 },\n\n // OpenAI (December 2025)\n 'gpt-5': { input: 1.25, output: 10.00 },\n 'gpt-5-mini': { input: 0.25, output: 2.00 },\n 'gpt-4o': { input: 5.00, output: 15.00 }, // Updated pricing as of late 2025\n 'gpt-4o-mini': { input: 0.15, output: 0.60 },\n 'gpt-4-turbo': { input: 10.00, output: 30.00 },\n 'gpt-4': { input: 30.00, output: 60.00 },\n 'gpt-3.5-turbo': { input: 0.50, output: 1.50 },\n\n // Google Gemini (December 2025)\n 'gemini-3-pro-preview': { input: 2.00, output: 12.00 }, // New Gemini 3\n 'gemini-3-flash-preview': { input: 0.50, output: 3.00 }, // For prompts ≤200K tokens, 2x for >200K\n 'gemini-2.5-flash': { input: 0.15, output: 0.60 }, // Standard mode (thinking disabled: $0.60, thinking enabled: $3.50)\n 'gemini-2.5-flash-lite': { input: 0.10, output: 0.40 },\n 'gemini-2.0-flash': { input: 0.10, output: 0.40 },\n 'gemini-2.0-flash-lite': { input: 0.075, output: 0.30 },\n 'gemini-1.5-pro': { input: 1.25, output: 5.00 },\n 'gemini-1.5-flash': { input: 0.075, output: 0.30 },\n\n // Groq (December 2025)\n 'llama-3.3-70b-versatile': { input: 0.59, output: 0.79 },\n 'llama-3.1-70b-versatile': { input: 0.59, output: 0.79 },\n 'llama-3.1-8b-instant': { input: 0.05, output: 0.08 },\n 'llama-4-scout-17b-16e': { input: 0.11, output: 0.34 },\n 'llama-4-maverick-17b-128e': { input: 0.20, output: 0.60 },\n 'mixtral-8x7b-32768': { input: 0.27, output: 0.27 },\n 'qwen3-32b': { input: 0.29, output: 0.59 },\n};\n\n// Default pricing for unknown models\nconst DEFAULT_PRICING = { input: 3.00, output: 15.00 };\n\nclass LLMUsageLogger {\n private logStream: fs.WriteStream | null = null;\n private logPath: string;\n private enabled: boolean;\n private sessionStats = {\n totalCalls: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheWriteTokens: 0,\n totalCostUSD: 0,\n totalDurationMs: 0,\n };\n\n constructor() {\n // Get log path from environment or use default\n this.logPath = process.env.LLM_USAGE_LOG_PATH || path.join(process.cwd(), 'llm-usage-logs');\n this.enabled = process.env.LLM_USAGE_LOGGING !== 'false';\n\n if (this.enabled) {\n this.initLogStream();\n }\n }\n\n private initLogStream(): void {\n try {\n // Ensure directory exists\n const dir = path.dirname(this.logPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n this.logStream = fs.createWriteStream(this.logPath, { flags: 'a' });\n\n // Write header if file is new/empty\n if (!fs.existsSync(this.logPath) || fs.statSync(this.logPath).size === 0) {\n this.writeHeader();\n }\n } catch (error) {\n console.error('[LLM-Usage-Logger] Failed to initialize log stream:', error);\n this.enabled = false;\n }\n }\n\n private writeHeader(): void {\n const header = `\n================================================================================\nLLM USAGE LOG - Session Started: ${new Date().toISOString()}\n================================================================================\nFormat: [TIMESTAMP] [REQUEST_ID] [PROVIDER/MODEL] [METHOD]\n Tokens: IN=input OUT=output CACHE_R=cache_read CACHE_W=cache_write TOTAL=total\n Cost: $X.XXXXXX | Time: Xms\n================================================================================\n\n`;\n this.logStream?.write(header);\n }\n\n /**\n * Calculate cost based on token usage and model\n */\n calculateCost(\n model: string,\n inputTokens: number,\n outputTokens: number,\n cacheReadTokens = 0,\n cacheWriteTokens = 0\n ): number {\n // Find pricing for model (try exact match, then partial match)\n let pricing = PRICING[model];\n if (!pricing) {\n // Try to find a partial match\n const modelLower = model.toLowerCase();\n for (const [key, value] of Object.entries(PRICING)) {\n if (modelLower.includes(key.toLowerCase()) || key.toLowerCase().includes(modelLower)) {\n pricing = value;\n break;\n }\n }\n }\n pricing = pricing || DEFAULT_PRICING;\n\n const inputCost = (inputTokens / 1_000_000) * pricing.input;\n const outputCost = (outputTokens / 1_000_000) * pricing.output;\n const cacheReadCost = (cacheReadTokens / 1_000_000) * (pricing.cacheRead || pricing.input * 0.1);\n const cacheWriteCost = (cacheWriteTokens / 1_000_000) * (pricing.cacheWrite || pricing.input * 1.25);\n\n return inputCost + outputCost + cacheReadCost + cacheWriteCost;\n }\n\n /**\n * Log an LLM API call\n */\n log(entry: LLMUsageEntry): void {\n if (!this.enabled) return;\n\n // Update session stats\n this.sessionStats.totalCalls++;\n this.sessionStats.totalInputTokens += entry.inputTokens;\n this.sessionStats.totalOutputTokens += entry.outputTokens;\n this.sessionStats.totalCacheReadTokens += entry.cacheReadTokens || 0;\n this.sessionStats.totalCacheWriteTokens += entry.cacheWriteTokens || 0;\n this.sessionStats.totalCostUSD += entry.costUSD;\n this.sessionStats.totalDurationMs += entry.durationMs;\n\n // Format log entry\n const cacheInfo = entry.cacheReadTokens || entry.cacheWriteTokens\n ? ` CACHE_R=${entry.cacheReadTokens || 0} CACHE_W=${entry.cacheWriteTokens || 0}`\n : '';\n\n const toolInfo = entry.toolCalls ? ` | Tools: ${entry.toolCalls}` : '';\n const errorInfo = entry.error ? ` | ERROR: ${entry.error}` : '';\n const status = entry.success ? '✓' : '✗';\n\n // Calculate cache savings\n let cacheStatus = '';\n if (entry.cacheReadTokens && entry.cacheReadTokens > 0) {\n const savedCost = (entry.cacheReadTokens / 1_000_000) * 2.70; // Difference between regular and cache price\n cacheStatus = ` ⚡ CACHE HIT! Saved ~$${savedCost.toFixed(4)}`;\n } else if (entry.cacheWriteTokens && entry.cacheWriteTokens > 0) {\n cacheStatus = ' 📝 Cache created (next request will be cheaper)';\n }\n\n const logLine = `[${entry.timestamp}] [${entry.requestId}] ${status} ${entry.provider}/${entry.model} [${entry.method}]\n Tokens: IN=${entry.inputTokens} OUT=${entry.outputTokens}${cacheInfo} TOTAL=${entry.totalTokens}\n Cost: $${entry.costUSD.toFixed(6)} | Time: ${entry.durationMs}ms${toolInfo}${errorInfo}${cacheStatus}\n`;\n\n this.logStream?.write(logLine);\n\n // Log cache status to console (always show cache hits/writes)\n if (entry.cacheReadTokens && entry.cacheReadTokens > 0) {\n console.log(`[LLM] ⚡ CACHE HIT: ${entry.cacheReadTokens.toLocaleString()} tokens read from cache (${entry.method})`);\n } else if (entry.cacheWriteTokens && entry.cacheWriteTokens > 0) {\n console.log(`[LLM] 📝 CACHE WRITE: ${entry.cacheWriteTokens.toLocaleString()} tokens cached for future requests (${entry.method})`);\n }\n\n // Also log to console in verbose mode\n if (process.env.SUPERATOM_LOG_LEVEL === 'verbose') {\n console.log('\\n[LLM-Usage]', logLine);\n }\n }\n\n /**\n * Log session summary (call at end of request)\n */\n logSessionSummary(requestContext?: string): void {\n if (!this.enabled || this.sessionStats.totalCalls === 0) return;\n\n // Calculate cache savings\n const cacheReadSavings = (this.sessionStats.totalCacheReadTokens / 1_000_000) * 2.70; // Saved per 1M tokens\n const hasCaching = this.sessionStats.totalCacheReadTokens > 0 || this.sessionStats.totalCacheWriteTokens > 0;\n\n let cacheSection = '';\n if (hasCaching) {\n cacheSection = `\nCache Statistics:\n Cache Read Tokens: ${this.sessionStats.totalCacheReadTokens.toLocaleString()}${this.sessionStats.totalCacheReadTokens > 0 ? ' ⚡' : ''}\n Cache Write Tokens: ${this.sessionStats.totalCacheWriteTokens.toLocaleString()}${this.sessionStats.totalCacheWriteTokens > 0 ? ' 📝' : ''}\n Estimated Savings: $${cacheReadSavings.toFixed(4)}`;\n }\n\n const summary = `\n--------------------------------------------------------------------------------\nSESSION SUMMARY${requestContext ? ` (${requestContext})` : ''}\n--------------------------------------------------------------------------------\nTotal LLM Calls: ${this.sessionStats.totalCalls}\nTotal Input Tokens: ${this.sessionStats.totalInputTokens.toLocaleString()}\nTotal Output Tokens: ${this.sessionStats.totalOutputTokens.toLocaleString()}\nTotal Tokens: ${(this.sessionStats.totalInputTokens + this.sessionStats.totalOutputTokens).toLocaleString()}\nTotal Cost: $${this.sessionStats.totalCostUSD.toFixed(6)}\nTotal Time: ${this.sessionStats.totalDurationMs}ms (${(this.sessionStats.totalDurationMs / 1000).toFixed(2)}s)\nAvg Cost/Call: $${(this.sessionStats.totalCostUSD / this.sessionStats.totalCalls).toFixed(6)}\nAvg Time/Call: ${Math.round(this.sessionStats.totalDurationMs / this.sessionStats.totalCalls)}ms${cacheSection}\n--------------------------------------------------------------------------------\n\n`;\n this.logStream?.write(summary);\n\n // Always log summary to console\n console.log('\\n[LLM-Usage] Session Summary:');\n console.log(` Calls: ${this.sessionStats.totalCalls} | Tokens: ${(this.sessionStats.totalInputTokens + this.sessionStats.totalOutputTokens).toLocaleString()} | Cost: $${this.sessionStats.totalCostUSD.toFixed(4)} | Time: ${(this.sessionStats.totalDurationMs / 1000).toFixed(2)}s`);\n if (hasCaching) {\n console.log(` Cache: ${this.sessionStats.totalCacheReadTokens.toLocaleString()} read, ${this.sessionStats.totalCacheWriteTokens.toLocaleString()} written | Savings: ~$${cacheReadSavings.toFixed(4)}`);\n }\n }\n\n /**\n * Reset session stats (call at start of new user request)\n */\n resetSession(): void {\n this.sessionStats = {\n totalCalls: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheWriteTokens: 0,\n totalCostUSD: 0,\n totalDurationMs: 0,\n };\n }\n\n /**\n * Reset the log file for a new request (clears previous logs)\n * Call this at the start of each USER_PROMPT_REQ\n */\n resetLogFile(requestContext?: string): void {\n if (!this.enabled) return;\n\n try {\n // Close existing stream\n if (this.logStream) {\n this.logStream.end();\n this.logStream = null;\n }\n\n // Truncate the file by opening in write mode (not append)\n this.logStream = fs.createWriteStream(this.logPath, { flags: 'w' });\n\n // Write new header\n const header = `\n================================================================================\nLLM USAGE LOG - Request Started: ${new Date().toISOString()}\n${requestContext ? `Context: ${requestContext}` : ''}\n================================================================================\nFormat: [TIMESTAMP] [REQUEST_ID] [PROVIDER/MODEL] [METHOD]\n Tokens: IN=input OUT=output CACHE_R=cache_read CACHE_W=cache_write TOTAL=total\n Cost: $X.XXXXXX | Time: Xms\n================================================================================\n\n`;\n this.logStream.write(header);\n\n // Reset session stats\n this.resetSession();\n\n console.log(`[LLM-Usage] Log file reset for new request: ${this.logPath}`);\n } catch (error) {\n console.error('[LLM-Usage-Logger] Failed to reset log file:', error);\n }\n }\n\n /**\n * Get current session stats\n */\n getSessionStats() {\n return { ...this.sessionStats };\n }\n\n /**\n * Generate a unique request ID\n */\n generateRequestId(): string {\n return `req-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;\n }\n}\n\n// Export singleton instance\nexport const llmUsageLogger = new LLMUsageLogger();\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * User Prompt Error Logger - Captures detailed errors for USER_PROMPT_REQ\n * Logs full error details including raw strings for parse failures\n */\n\nclass UserPromptErrorLogger {\n private logStream: fs.WriteStream | null = null;\n private logPath: string;\n private enabled: boolean;\n private hasErrors: boolean = false;\n\n constructor() {\n // Get log path from environment or use default\n this.logPath = process.env.USER_PROMPT_ERROR_LOG_PATH || path.join(process.cwd(), 'user-prompt-req-errors');\n this.enabled = process.env.USER_PROMPT_ERROR_LOGGING !== 'false';\n }\n\n /**\n * Reset the error log file for a new request\n */\n resetLogFile(requestContext?: string): void {\n if (!this.enabled) return;\n\n try {\n // Close existing stream\n if (this.logStream) {\n this.logStream.end();\n this.logStream = null;\n }\n\n // Ensure directory exists\n const dir = path.dirname(this.logPath);\n if (dir !== '.' && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Truncate the file by opening in write mode (not append)\n this.logStream = fs.createWriteStream(this.logPath, { flags: 'w' });\n this.hasErrors = false;\n\n // Write header\n const header = `================================================================================\nUSER PROMPT REQUEST ERROR LOG\nRequest Started: ${new Date().toISOString()}\n${requestContext ? `Context: ${requestContext}` : ''}\n================================================================================\n\n`;\n this.logStream.write(header);\n\n } catch (error) {\n console.error('[UserPromptErrorLogger] Failed to reset log file:', error);\n }\n }\n\n /**\n * Log a JSON parse error with the raw string that failed\n */\n logJsonParseError(context: string, rawString: string, error: Error): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] JSON PARSE ERROR\n--------------------------------------------------------------------------------\nContext: ${context}\nError: ${error.message}\n\nRaw String (${rawString.length} chars):\n--------------------------------------------------------------------------------\n${rawString}\n--------------------------------------------------------------------------------\n\nStack Trace:\n${error.stack || 'No stack trace available'}\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] JSON Parse Error in ${context}: ${error.message}`);\n }\n\n /**\n * Log a general error with full details\n */\n logError(context: string, error: Error | string, additionalData?: Record<string, any>): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const errorMessage = error instanceof Error ? error.message : error;\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n let entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] ERROR\n--------------------------------------------------------------------------------\nContext: ${context}\nError: ${errorMessage}\n`;\n\n if (additionalData) {\n entry += `\nAdditional Data:\n${JSON.stringify(additionalData, null, 2)}\n`;\n }\n\n if (errorStack) {\n entry += `\nStack Trace:\n${errorStack}\n`;\n }\n\n entry += `--------------------------------------------------------------------------------\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] ${context}: ${errorMessage}`);\n }\n\n /**\n * Log a SQL query error with the full query\n */\n logSqlError(query: string, error: Error | string, params?: any[]): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const errorMessage = error instanceof Error ? error.message : error;\n\n const entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] SQL QUERY ERROR\n--------------------------------------------------------------------------------\nError: ${errorMessage}\n\nQuery (${query.length} chars):\n--------------------------------------------------------------------------------\n${query}\n--------------------------------------------------------------------------------\n${params ? `\\nParameters: ${JSON.stringify(params)}` : ''}\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] SQL Error: ${errorMessage}`);\n }\n\n /**\n * Log an LLM API error\n */\n logLlmError(provider: string, model: string, method: string, error: Error | string, requestData?: any): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const errorMessage = error instanceof Error ? error.message : error;\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n let entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] LLM API ERROR\n--------------------------------------------------------------------------------\nProvider: ${provider}\nModel: ${model}\nMethod: ${method}\nError: ${errorMessage}\n`;\n\n if (requestData) {\n // Truncate large request data\n const dataStr = JSON.stringify(requestData, null, 2);\n const truncated = dataStr.length > 5000 ? dataStr.substring(0, 5000) + '\\n... [truncated]' : dataStr;\n entry += `\nRequest Data:\n${truncated}\n`;\n }\n\n if (errorStack) {\n entry += `\nStack Trace:\n${errorStack}\n`;\n }\n\n entry += `--------------------------------------------------------------------------------\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] LLM Error (${provider}/${model}): ${errorMessage}`);\n }\n\n /**\n * Log tool execution error\n */\n logToolError(toolName: string, toolInput: any, error: Error | string): void {\n if (!this.enabled) return;\n this.hasErrors = true;\n\n const errorMessage = error instanceof Error ? error.message : error;\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n const entry = `\n--------------------------------------------------------------------------------\n[${new Date().toISOString()}] TOOL EXECUTION ERROR\n--------------------------------------------------------------------------------\nTool: ${toolName}\nError: ${errorMessage}\n\nTool Input:\n${JSON.stringify(toolInput, null, 2)}\n${errorStack ? `\\nStack Trace:\\n${errorStack}` : ''}\n--------------------------------------------------------------------------------\n\n`;\n this.write(entry);\n console.error(`[UserPromptError] Tool Error (${toolName}): ${errorMessage}`);\n }\n\n /**\n * Write final summary if there were errors\n */\n writeSummary(): void {\n if (!this.enabled || !this.hasErrors) return;\n\n const summary = `\n================================================================================\nREQUEST COMPLETED WITH ERRORS\nTime: ${new Date().toISOString()}\n================================================================================\n`;\n this.write(summary);\n }\n\n /**\n * Check if any errors were logged\n */\n hadErrors(): boolean {\n return this.hasErrors;\n }\n\n private write(content: string): void {\n if (this.logStream) {\n this.logStream.write(content);\n }\n }\n}\n\n// Export singleton instance\nexport const userPromptErrorLogger = new UserPromptErrorLogger();\n","import { logger } from '../utils/logger';\n\n/**\n * Knowledge Base result interface\n */\nexport interface KnowledgeBaseResult {\n content: string;\n metadata?: {\n sources?: Array<{\n title: string;\n similarity?: number;\n kb_id?: string | number;\n }>;\n };\n}\n\n/**\n * Get relevant knowledge base context for a user prompt\n * Calls the registered 'knowledge-base.query' collection\n *\n * @param prompt - The user's question/prompt\n * @param collections - The collection registry containing knowledge-base.query\n * @param topK - Number of top results to retrieve (default: 1)\n * @returns Formatted knowledge base context string, or empty string if collection not registered\n */\nconst getKnowledgeBase = async ({\n prompt,\n collections,\n topK = 1\n}: {\n prompt: string;\n collections?: any;\n topK?: number;\n}): Promise<string> => {\n try {\n // Check if knowledge-base collection is registered\n if (!collections || !collections['knowledge-base'] || !collections['knowledge-base']['query']) {\n logger.info('[KnowledgeBase] knowledge-base.query collection not registered, skipping');\n return '';\n }\n\n logger.info(`[KnowledgeBase] Querying knowledge base for: \"${prompt.substring(0, 50)}...\"`);\n\n // Call the registered knowledge-base.query collection\n const result: KnowledgeBaseResult = await collections['knowledge-base']['query']({\n prompt,\n topK\n });\n\n if (!result || !result.content) {\n logger.error('[KnowledgeBase] No knowledge base results returned');\n return '';\n }\n\n logger.info(`[KnowledgeBase] Retrieved knowledge base context (${result.content.length} chars)`);\n\n // Log sources if available\n if (result.metadata?.sources && result.metadata.sources.length > 0) {\n logger.debug(`[KnowledgeBase] Sources: ${result.metadata.sources.map(s => s.title).join(', ')}`);\n }\n\n return result.content;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.warn(`[KnowledgeBase] Error querying knowledge base: ${errorMsg}`);\n // Return empty string on error - don't fail the entire request\n return '';\n }\n};\n\nconst KB = {\n getKnowledgeBase\n};\n\nexport default KB;","import { logger } from '../utils/logger';\nimport { rerankConversationResults, type HybridSearchOptions } from '../utils/bm25l-reranker';\nimport type { UIBlock } from '../types';\n\n/**\n * Conversation Search result interface\n */\nexport interface ConversationSearchResult {\n\tuiBlock: UIBlock;\n\tsimilarity: number;\n\tmetadata?: {\n\t\tuserPrompt?: string;\n\t\ttimestamp?: number;\n\t};\n\t/** Hybrid score combining semantic and BM25L lexical matching */\n\thybridScore?: number;\n\t/** BM25L lexical score */\n\tbm25Score?: number;\n}\n\n/**\n * Options for conversation search with reranking\n */\nexport interface ConversationSearchOptions {\n\tuserPrompt: string;\n\tcollections?: any;\n\tuserId?: string;\n\tsimilarityThreshold?: number;\n\t/** Enable hybrid reranking with BM25L (default: true) */\n\tenableReranking?: boolean;\n\t/** Number of candidates to fetch for reranking (default: 5) */\n\trerankCandidates?: number;\n\t/** Hybrid search options for BM25L reranking */\n\thybridOptions?: HybridSearchOptions;\n}\n\n/**\n * Search for semantically similar previous conversations for a user\n * Calls the registered 'conversation-history.search' collection\n * Returns the best match if similarity > threshold (default: 0.6)\n *\n * @param userPrompt - The current user's question/prompt\n * @param collections - The collection registry containing conversation-history.search\n * @param similarityThreshold - Minimum similarity threshold (0-1, default: 0.6)\n * @returns Matching UIBlock if found with similarity > threshold, null otherwise\n */\nconst searchConversations = async ({\n\tuserPrompt,\n\tcollections,\n\tuserId,\n\tsimilarityThreshold = 0.6\n}: {\n\tuserPrompt: string;\n\tcollections?: any;\n\tuserId?: string;\n\tsimilarityThreshold?: number;\n}): Promise<ConversationSearchResult | null> => {\n\ttry {\n\t\t// Check if conversation-history collection is registered\n\t\tif (\n\t\t\t!collections ||\n\t\t\t!collections['conversation-history'] ||\n\t\t\t!collections['conversation-history']['search']\n\t\t) {\n\t\t\tlogger.info('[ConversationSearch] conversation-history.search collection not registered, skipping');\n\t\t\treturn null;\n\t\t}\n\n\t\tlogger.info(`[ConversationSearch] Searching conversations for: \"${userPrompt.substring(0, 50)}...\"`);\n\t\tlogger.info(`[ConversationSearch] Using similarity threshold: ${(similarityThreshold! * 100).toFixed(0)}%`);\n\n\t\t// Call the registered conversation-history.search collection\n\t\tconst result: ConversationSearchResult = await collections['conversation-history']['search']({\n\t\t\tuserPrompt,\n\t\t\tuserId,\n\t\t\tthreshold: similarityThreshold\n\t\t});\n\n\t\tif (!result) {\n\t\t\tlogger.info('[ConversationSearch] No matching conversations found');\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!result.uiBlock) {\n\t\t\tlogger.error('[ConversationSearch] No UI block in conversation search result');\n\t\t\treturn null;\n\t\t}\n\n\t\tconst similarity = result.similarity || 0;\n\t\tlogger.info(`[ConversationSearch] Best match similarity: ${(similarity * 100).toFixed(2)}%`);\n\t\t// Check if similarity meets threshold\n\t\tif (similarity < similarityThreshold) {\n\t\t\tlogger.info(\n\t\t\t\t`[ConversationSearch] Best match has similarity ${(similarity * 100).toFixed(2)}% but below threshold ${(similarityThreshold * 100).toFixed(2)}%`\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\n\t\tlogger.info(\n\t\t\t`[ConversationSearch] Found matching conversation with similarity ${(similarity * 100).toFixed(2)}%`\n\t\t);\n\t\tlogger.debug(`[ConversationSearch] Matched prompt: \"${result.metadata?.userPrompt?.substring(0, 50)}...\"`);\n\n\t\treturn result;\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\tlogger.warn(`[ConversationSearch] Error searching conversations: ${errorMsg}`);\n\t\t// Return null on error - don't fail the entire request\n\t\treturn null;\n\t}\n};\n\n/**\n * Search for semantically similar previous conversations with hybrid reranking\n *\n * This is an enhanced version of searchConversations that uses BM25L reranking\n * to improve search accuracy by combining semantic similarity with lexical matching.\n *\n * Flow:\n * 1. Fetch a large pool of candidates from ChromaDB (default: 50) with no threshold\n * 2. Apply BM25L reranking on all candidates to find the best lexical + semantic match\n * 3. Return the top result only if it meets the similarity threshold\n *\n * This approach ensures we don't miss good lexical matches that might have\n * lower semantic similarity but are actually more relevant to the query.\n *\n * @param options - Search options including userPrompt, collections, userId, and reranking settings\n * @returns Matching UIBlock if found with hybrid score > threshold, null otherwise\n */\nconst searchConversationsWithReranking = async (options: ConversationSearchOptions): Promise<ConversationSearchResult | null> => {\n\tconst {\n\t\tuserPrompt,\n\t\tcollections,\n\t\tuserId,\n\t\tsimilarityThreshold = 0.6,\n\t\trerankCandidates = 50, // Fetch more candidates for better reranking\n\t\thybridOptions = {\n\t\t\tsemanticWeight: 0.7,\n\t\t\tbm25Weight: 0.3\n\t\t}\n\t} = options;\n\n\ttry {\n\t\t// Check if conversation-history collection is registered\n\t\tif (\n\t\t\t!collections ||\n\t\t\t!collections['conversation-history']\n\t\t) {\n\t\t\tlogger.info('[ConversationSearch] conversation-history collection not registered, skipping');\n\t\t\treturn null;\n\t\t}\n\n\t\t// Check if searchMultiple is available for reranking\n\t\tif (!collections['conversation-history']['searchMultiple']) {\n\t\t\tlogger.info('[ConversationSearch] searchMultiple not available, falling back to standard search');\n\t\t\treturn searchConversations({\n\t\t\t\tuserPrompt,\n\t\t\t\tcollections,\n\t\t\t\tuserId,\n\t\t\t\tsimilarityThreshold\n\t\t\t});\n\t\t}\n\n\t\tlogger.info(`[ConversationSearch] Hybrid search for: \"${userPrompt.substring(0, 50)}...\"`);\n\t\tlogger.info(`[ConversationSearch] Fetching ${rerankCandidates} candidates for reranking`);\n\t\tlogger.info(`[ConversationSearch] Weights - Semantic: ${hybridOptions.semanticWeight}, BM25: ${hybridOptions.bm25Weight}`);\n\n\t\t// Fetch a large pool of candidates with NO threshold - let reranking decide\n\t\tconst results: ConversationSearchResult[] = await collections['conversation-history']['searchMultiple']({\n\t\t\tuserPrompt,\n\t\t\tuserId,\n\t\t\tlimit: rerankCandidates,\n\t\t\tthreshold: 0 // No threshold - get all candidates for reranking\n\t\t});\n\n\t\tif (!results || results.length === 0) {\n\t\t\tlogger.info('[ConversationSearch] No conversations found in database');\n\t\t\treturn null;\n\t\t}\n\n\t\tlogger.info(`[ConversationSearch] Retrieved ${results.length} candidates for reranking`);\n\n\t\t// Prepare results for reranking - extract userPrompt from metadata\n\t\tconst candidatesForReranking = results.map(r => ({\n\t\t\t...r,\n\t\t\tuserPrompt: r.metadata?.userPrompt || ''\n\t\t}));\n\n\t\t// Rerank using hybrid BM25L + semantic scoring\n\t\tconst reranked = rerankConversationResults(userPrompt, candidatesForReranking, hybridOptions);\n\n\t\tif (reranked.length === 0) {\n\t\t\tlogger.info('[ConversationSearch] No results after reranking');\n\t\t\treturn null;\n\t\t}\n\n\t\t// Get the best result after reranking\n\t\tconst best = reranked[0];\n\t\tconst hybridScore = best.hybridScore;\n\t\tconst semanticScore = best.similarity || 0;\n\t\tconst matchedUserPrompt = (best as any).userPrompt || best.metadata?.userPrompt || '';\n\n\t\tlogger.info(`[ConversationSearch] Best match after reranking:`);\n\t\tlogger.info(` - Hybrid score: ${(hybridScore * 100).toFixed(2)}%`);\n\t\tlogger.info(` - Semantic score: ${(semanticScore * 100).toFixed(2)}%`);\n\t\tlogger.info(` - BM25L score: ${best.bm25Score.toFixed(4)}`);\n\t\tlogger.info(` - Matched prompt: \"${matchedUserPrompt}\"`);\n\t\tlogger.info(` - Query prompt: \"${userPrompt}\"`);\n\n\t\t// Apply threshold on SEMANTIC score (not hybrid)\n\t\t// Hybrid score can be inflated by normalization with few candidates\n\t\t// Semantic score is the true measure of meaning similarity\n\t\t// BM25 reranking only helps pick the best among candidates that already pass semantic threshold\n\t\tif (semanticScore < similarityThreshold) {\n\t\t\tlogger.info(\n\t\t\t\t`[ConversationSearch] Semantic score ${(semanticScore * 100).toFixed(2)}% below threshold ${(similarityThreshold * 100).toFixed(2)}% - rejecting match`\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\n\t\tlogger.info(\n\t\t\t`[ConversationSearch] ✓ Found match with semantic score ${(semanticScore * 100).toFixed(2)}%`\n\t\t);\n\t\tlogger.info(` - Returning cached result for: \"${matchedUserPrompt}\"`);\n\n\t\treturn {\n\t\t\tuiBlock: best.uiBlock,\n\t\t\tsimilarity: semanticScore,\n\t\t\thybridScore: hybridScore,\n\t\t\tbm25Score: best.bm25Score,\n\t\t\tmetadata: best.metadata\n\t\t};\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\tlogger.warn(`[ConversationSearch] Error in hybrid search: ${errorMsg}`);\n\t\t// Return null on error - don't fail the entire request\n\t\treturn null;\n\t}\n};\n\nconst ConversationSearch = {\n\tsearchConversations,\n\tsearchConversationsWithReranking\n};\n\nexport default ConversationSearch;\n","/**\n * BM25L Reranker for hybrid semantic search\n *\n * BM25L is an improved variant of BM25 that provides better handling of\n * long documents and term frequency saturation. This implementation is\n * designed to rerank semantic search results from ChromaDB.\n *\n * The hybrid approach combines:\n * 1. Semantic similarity from ChromaDB embeddings (dense vectors)\n * 2. Lexical matching from BM25L (sparse, keyword-based)\n *\n * This addresses the weakness of pure semantic search which may miss\n * exact keyword matches that are important for user intent.\n */\n\nexport interface BM25LOptions {\n\t/** Term frequency saturation parameter (default: 1.5) */\n\tk1?: number;\n\t/** Length normalization parameter (default: 0.75) */\n\tb?: number;\n\t/** Lower-bound adjustment from BM25L paper (default: 0.5) */\n\tdelta?: number;\n}\n\nexport interface RerankedResult<T> {\n\titem: T;\n\toriginalIndex: number;\n\tsemanticScore: number;\n\tbm25Score: number;\n\thybridScore: number;\n}\n\nexport interface HybridSearchOptions extends BM25LOptions {\n\t/** Weight for semantic score (0-1, default: 0.7) */\n\tsemanticWeight?: number;\n\t/** Weight for BM25 score (0-1, default: 0.3) */\n\tbm25Weight?: number;\n\t/** Minimum hybrid score threshold (0-1, default: 0) */\n\tminScore?: number;\n}\n\n/**\n * BM25L implementation for lexical scoring\n */\nexport class BM25L {\n\tprivate k1: number;\n\tprivate b: number;\n\tprivate delta: number;\n\tprivate documents: string[][];\n\tprivate docLengths: number[];\n\tprivate avgDocLength: number;\n\tprivate termDocFreq: Record<string, number>;\n\n\t/**\n\t * @param documents - Array of raw documents (strings)\n\t * @param opts - Optional BM25L parameters\n\t */\n\tconstructor(documents: string[] = [], opts: BM25LOptions = {}) {\n\t\tif (!Array.isArray(documents)) {\n\t\t\tthrow new Error('BM25L: documents must be an array of strings.');\n\t\t}\n\n\t\tthis.k1 = typeof opts.k1 === 'number' ? opts.k1 : 1.5;\n\t\tthis.b = typeof opts.b === 'number' ? opts.b : 0.75;\n\t\tthis.delta = typeof opts.delta === 'number' ? opts.delta : 0.5;\n\n\t\t// Tokenize documents safely\n\t\tthis.documents = documents.map(d => (typeof d === 'string' ? this.tokenize(d) : []));\n\n\t\t// Precompute stats\n\t\tthis.docLengths = this.documents.map(doc => doc.length);\n\t\tthis.avgDocLength =\n\t\t\tthis.docLengths.reduce((a, b) => a + b, 0) / (this.docLengths.length || 1);\n\n\t\t// Compute document frequency (df)\n\t\tthis.termDocFreq = {};\n\t\tthis.documents.forEach(doc => {\n\t\t\tconst seen = new Set<string>();\n\t\t\tdoc.forEach(term => {\n\t\t\t\tif (!seen.has(term)) {\n\t\t\t\t\tseen.add(term);\n\t\t\t\t\tthis.termDocFreq[term] = (this.termDocFreq[term] || 0) + 1;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Tokenize text into lowercase alphanumeric tokens\n\t */\n\ttokenize(text: string): string[] {\n\t\tif (typeof text !== 'string') return [];\n\t\treturn text\n\t\t\t.toLowerCase()\n\t\t\t.replace(/[^a-z0-9\\s]/g, ' ')\n\t\t\t.split(/\\s+/)\n\t\t\t.filter(Boolean);\n\t}\n\n\t/**\n\t * Compute IDF (Inverse Document Frequency) with smoothing\n\t */\n\tprivate idf(term: string): number {\n\t\tconst df = this.termDocFreq[term] || 0;\n\t\tconst N = this.documents.length || 1;\n\t\treturn Math.log(1 + (N - df + 0.5) / (df + 0.5));\n\t}\n\n\t/**\n\t * Compute BM25L score for a single document\n\t */\n\tscore(query: string, docIndex: number): number {\n\t\tif (typeof query !== 'string') return 0;\n\t\tif (docIndex < 0 || docIndex >= this.documents.length) return 0;\n\n\t\tconst tokens = this.tokenize(query);\n\t\tif (tokens.length === 0) return 0;\n\n\t\tconst doc = this.documents[docIndex];\n\t\tconst docLength = this.docLengths[docIndex] || 1;\n\n\t\t// Term frequencies\n\t\tconst freq: Record<string, number> = {};\n\t\tfor (const t of doc) {\n\t\t\tfreq[t] = (freq[t] || 0) + 1;\n\t\t}\n\n\t\tlet sum = 0;\n\n\t\tfor (const term of tokens) {\n\t\t\tconst tf = freq[term] || 0;\n\t\t\tif (tf === 0) continue;\n\n\t\t\tconst idfVal = this.idf(term);\n\n\t\t\t// BM25L adjusted TF\n\t\t\tlet tfL = tf - this.b * (docLength / this.avgDocLength) + this.delta;\n\t\t\tif (tfL < 0) tfL = 0;\n\n\t\t\tsum += idfVal * (tfL / (this.k1 + tfL));\n\t\t}\n\n\t\treturn sum;\n\t}\n\n\t/**\n\t * Search and rank all documents\n\t */\n\tsearch(query: string): Array<{ index: number; score: number }> {\n\t\treturn this.documents\n\t\t\t.map((_, i) => ({\n\t\t\t\tindex: i,\n\t\t\t\tscore: this.score(query, i)\n\t\t\t}))\n\t\t\t.sort((a, b) => b.score - a.score);\n\t}\n}\n\n/**\n * Normalize scores to 0-1 range using min-max normalization\n */\nfunction normalizeScores(scores: number[]): number[] {\n\tif (scores.length === 0) return [];\n\n\tconst min = Math.min(...scores);\n\tconst max = Math.max(...scores);\n\n\t// If all scores are the same, return array of 1s (or 0s if all are 0)\n\tif (max === min) {\n\t\treturn scores.map(() => (max === 0 ? 0 : 1));\n\t}\n\n\treturn scores.map(score => (score - min) / (max - min));\n}\n\n/**\n * Hybrid reranker that combines semantic and BM25L scores\n *\n * @param query - The search query\n * @param items - Array of items to rerank\n * @param getDocument - Function to extract document text from an item\n * @param getSemanticScore - Function to extract semantic similarity score from an item\n * @param options - Hybrid search options\n * @returns Reranked items with hybrid scores\n */\nexport function hybridRerank<T>(\n\tquery: string,\n\titems: T[],\n\tgetDocument: (item: T) => string,\n\tgetSemanticScore: (item: T) => number,\n\toptions: HybridSearchOptions = {}\n): RerankedResult<T>[] {\n\tconst {\n\t\tsemanticWeight = 0.7,\n\t\tbm25Weight = 0.3,\n\t\tminScore = 0,\n\t\tk1 = 1.5,\n\t\tb = 0.75,\n\t\tdelta = 0.5\n\t} = options;\n\n\tif (items.length === 0) return [];\n\n\t// Extract documents and semantic scores\n\tconst documents = items.map(getDocument);\n\tconst semanticScores = items.map(getSemanticScore);\n\n\t// Create BM25L index and compute scores\n\tconst bm25 = new BM25L(documents, { k1, b, delta });\n\tconst bm25Scores = items.map((_, i) => bm25.score(query, i));\n\n\t// Normalize both score sets to 0-1 range\n\tconst normalizedSemantic = normalizeScores(semanticScores);\n\tconst normalizedBM25 = normalizeScores(bm25Scores);\n\n\t// Compute hybrid scores and create result objects\n\tconst results: RerankedResult<T>[] = items.map((item, i) => {\n\t\tconst hybridScore =\n\t\t\tsemanticWeight * normalizedSemantic[i] + bm25Weight * normalizedBM25[i];\n\n\t\treturn {\n\t\t\titem,\n\t\t\toriginalIndex: i,\n\t\t\tsemanticScore: semanticScores[i],\n\t\t\tbm25Score: bm25Scores[i],\n\t\t\thybridScore\n\t\t};\n\t});\n\n\t// Sort by hybrid score (descending) and filter by minimum score\n\treturn results\n\t\t.filter(r => r.hybridScore >= minScore)\n\t\t.sort((a, b) => b.hybridScore - a.hybridScore);\n}\n\n/**\n * Simple reranking function for ChromaDB results\n *\n * This is a convenience wrapper for reranking ChromaDB query results\n * that follow the standard { ids, documents, metadatas, distances } format.\n *\n * @param query - The search query\n * @param chromaResults - ChromaDB query results\n * @param options - Hybrid search options\n * @returns Reranked results with hybrid scores\n */\nexport function rerankChromaResults(\n\tquery: string,\n\tchromaResults: {\n\t\tids: string[][];\n\t\tdocuments: (string | null)[][];\n\t\tmetadatas: Record<string, any>[][];\n\t\tdistances: number[][];\n\t},\n\toptions: HybridSearchOptions = {}\n): Array<{\n\tid: string;\n\tdocument: string | null;\n\tmetadata: Record<string, any>;\n\tdistance: number;\n\tsemanticScore: number;\n\tbm25Score: number;\n\thybridScore: number;\n}> {\n\t// Flatten the nested arrays (ChromaDB returns nested arrays for batch queries)\n\tconst ids = chromaResults.ids[0] || [];\n\tconst documents = chromaResults.documents[0] || [];\n\tconst metadatas = chromaResults.metadatas[0] || [];\n\tconst distances = chromaResults.distances[0] || [];\n\n\tif (ids.length === 0) return [];\n\n\t// Create items array\n\tconst items = ids.map((id, i) => ({\n\t\tid,\n\t\tdocument: documents[i],\n\t\tmetadata: metadatas[i],\n\t\tdistance: distances[i]\n\t}));\n\n\t// Rerank using hybrid approach\n\tconst reranked = hybridRerank(\n\t\tquery,\n\t\titems,\n\t\titem => item.document || '',\n\t\t// Convert L2 distance to similarity score\n\t\titem => 1 / (1 + item.distance),\n\t\toptions\n\t);\n\n\t// Return flattened results\n\treturn reranked.map(r => ({\n\t\tid: r.item.id,\n\t\tdocument: r.item.document,\n\t\tmetadata: r.item.metadata,\n\t\tdistance: r.item.distance,\n\t\tsemanticScore: r.semanticScore,\n\t\tbm25Score: r.bm25Score,\n\t\thybridScore: r.hybridScore\n\t}));\n}\n\n/**\n * Rerank conversation search results specifically\n *\n * This function is designed to work with the conversation-history.search collection\n * where we need to fetch more results initially and then rerank them.\n *\n * @param query - The user's search query\n * @param results - Array of conversation search results from ChromaDB\n * @param options - Hybrid search options\n * @returns Reranked results sorted by hybrid score\n */\nexport function rerankConversationResults<T extends { userPrompt?: string; similarity?: number }>(\n\tquery: string,\n\tresults: T[],\n\toptions: HybridSearchOptions = {}\n): Array<T & { hybridScore: number; bm25Score: number }> {\n\tif (results.length === 0) return [];\n\n\tconst reranked = hybridRerank(\n\t\tquery,\n\t\tresults,\n\t\titem => item.userPrompt || '',\n\t\titem => item.similarity || 0,\n\t\toptions\n\t);\n\n\treturn reranked.map(r => ({\n\t\t...r.item,\n\t\thybridScore: r.hybridScore,\n\t\tbm25Score: r.bm25Score\n\t}));\n}\n\nexport default {\n\tBM25L,\n\thybridRerank,\n\trerankChromaResults,\n\trerankConversationResults\n};\n","import dotenv from 'dotenv';\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\n\ndotenv.config();\n\nexport interface AnthropicLLMConfig extends BaseLLMConfig {}\n\n/**\n * AnthropicLLM class for handling AI-powered component generation and matching using Anthropic Claude\n */\nexport class AnthropicLLM extends BaseLLM {\n\tconstructor(config?: AnthropicLLMConfig) {\n\t\tsuper(config);\n\t}\n\n\tprotected getDefaultModel(): string {\n\t\treturn 'anthropic/claude-sonnet-4-5-20250929';\n\t}\n\n\tprotected getDefaultFastModel(): string {\n\t\t// Haiku is 75% cheaper and faster - ideal for simple tasks\n\t\treturn 'anthropic/claude-haiku-4-5-20251001';\n\t}\n\n\tprotected getDefaultApiKey(): string | undefined {\n\t\treturn process.env.ANTHROPIC_API_KEY;\n\t}\n\n\tprotected getProviderName(): string {\n\t\treturn 'Anthropic';\n\t}\n}\n\n// Export a singleton instance\nexport const anthropicLLM = new AnthropicLLM();\n","import dotenv from 'dotenv';\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\n\ndotenv.config();\n\nexport interface GeminiLLMConfig extends BaseLLMConfig {}\n\n/**\n * GeminiLLM class for handling AI-powered component generation and matching using Google Gemini\n */\nexport class GeminiLLM extends BaseLLM {\n\tconstructor(config?: GeminiLLMConfig) {\n\t\tsuper(config);\n\t}\n\n\tprotected getDefaultModel(): string {\n\t\treturn 'gemini/gemini-3-pro-preview';\n\t}\n\n\tprotected getDefaultFastModel(): string {\n\t\t// Gemini Flash is already fast/cheap, use the same\n\t\treturn 'gemini/gemini-3-flash-preview';\n\t}\n\n\tprotected getDefaultApiKey(): string | undefined {\n\t\treturn process.env.GEMINI_API_KEY;\n\t}\n\n\tprotected getProviderName(): string {\n\t\treturn 'Gemini';\n\t}\n}\n\n// Export a singleton instance\nexport const geminiLLM = new GeminiLLM();\n","import dotenv from 'dotenv';\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\n\ndotenv.config();\n\nexport interface OpenAILLMConfig extends BaseLLMConfig {}\n\n/**\n * OpenAILLM class for handling AI-powered component generation and matching using OpenAI GPT models\n */\nexport class OpenAILLM extends BaseLLM {\n\tconstructor(config?: OpenAILLMConfig) {\n\t\tsuper(config);\n\t}\n\n\tprotected getDefaultModel(): string {\n\t\treturn 'openai/gpt-4.1';\n\t}\n\n\tprotected getDefaultFastModel(): string {\n\t\t// GPT-4o-mini is 60x cheaper than GPT-4o and faster - ideal for simple tasks\n\t\treturn 'openai/gpt-4o-mini';\n\t}\n\n\tprotected getDefaultApiKey(): string | undefined {\n\t\treturn process.env.OPENAI_API_KEY;\n\t}\n\n\tprotected getProviderName(): string {\n\t\treturn 'OpenAI';\n\t}\n}\n\n// Export a singleton instance\nexport const openaiLLM = new OpenAILLM();\n","import { groqLLM } from \"./groq\";\nimport { anthropicLLM } from \"./anthropic\";\nimport { geminiLLM } from \"./gemini\";\nimport { openaiLLM } from \"./openai\";\nimport { Component, LLMProvider, T_RESPONSE } from \"../types\";\nimport dotenv from 'dotenv';\nimport { logger } from \"../utils/logger\";\n\ndotenv.config();\n\n// Export types and singletons for model strategy configuration\n// Note: ModelStrategy is exported from types.ts (defined there for SDK config)\nexport { TaskType, BaseLLMConfig } from './base-llm';\nexport { anthropicLLM } from './anthropic';\nexport { groqLLM } from './groq';\nexport { geminiLLM } from './gemini';\nexport { openaiLLM } from './openai';\n\n\n\n/**\n * Parse LLM_PROVIDERS from environment variable\n * Expects a stringified JSON array like: '[\"anthropic\",\"groq\"]'\n */\nexport function getLLMProviders(): LLMProvider[] {\n const envProviders = process.env.LLM_PROVIDERS;\n\n const DEFAULT_PROVIDERS: LLMProvider[] = ['anthropic', 'gemini', 'openai', 'groq'];\n if (!envProviders) {\n // Default to anthropic if not specified\n return DEFAULT_PROVIDERS;\n }\n\n try {\n const providers = JSON.parse(envProviders) as LLMProvider[];\n\n // Validate providers\n const validProviders = providers.filter(p => p === 'anthropic' || p === 'groq' || p === 'gemini' || p === 'openai');\n\n if (validProviders.length === 0) {\n return DEFAULT_PROVIDERS;\n }\n\n return validProviders;\n } catch (error) {\n logger.error('Failed to parse LLM_PROVIDERS, defaulting to [\"anthropic\"]:', error);\n return DEFAULT_PROVIDERS;\n }\n}\n\n/**\n * Method 1: Use Anthropic Claude LLM\n */\nexport const useAnthropicMethod = async (\n prompt: string,\n components: Component[],\n apiKey?: string,\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n logger.debug('[useAnthropicMethod] Initializing Anthropic Claude matching method');\n logger.debug(`[useAnthropicMethod] Response mode: ${responseMode}`);\n const msg = `Using Anthropic Claude ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\n // logger.info(msg);\n logCollector?.info(msg);\n\n // Only check components for component mode\n if (responseMode === 'component' && components.length === 0) {\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\n logger.error('[useAnthropicMethod] No components available');\n logCollector?.error(emptyMsg);\n return { success: false, errors: [emptyMsg] };\n }\n\n logger.debug(`[useAnthropicMethod] Processing with ${components.length} components`);\n\n const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n logger.info(`[useAnthropicMethod] Successfully generated ${responseMode} using Anthropic`);\n return matchResult;\n};\n\n/**\n * Method 2: Use Groq LLM\n */\nexport const useGroqMethod = async (\n prompt: string,\n components: Component[],\n apiKey?: string,\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n logger.debug('[useGroqMethod] Initializing Groq LLM matching method');\n logger.debug(`[useGroqMethod] Response mode: ${responseMode}`);\n const msg = `Using Groq LLM ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\n logger.info(msg);\n logCollector?.info(msg);\n\n // Only check components for component mode\n if (responseMode === 'component' && components.length === 0) {\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\n logger.error('[useGroqMethod] No components available');\n logCollector?.error(emptyMsg);\n return { success: false, errors: [emptyMsg] };\n }\n\n logger.debug(`[useGroqMethod] Processing with ${components.length} components`);\n\n const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);\n return matchResult;\n}\n\n/**\n * Method 3: Use Google Gemini LLM\n */\nexport const useGeminiMethod = async (\n prompt: string,\n components: Component[],\n apiKey?: string,\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n logger.debug('[useGeminiMethod] Initializing Gemini LLM matching method');\n logger.debug(`[useGeminiMethod] Response mode: ${responseMode}`);\n const msg = `Using Gemini LLM ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\n logger.info(msg);\n logCollector?.info(msg);\n\n // Only check components for component mode\n if (responseMode === 'component' && components.length === 0) {\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\n logger.error('[useGeminiMethod] No components available');\n logCollector?.error(emptyMsg);\n return { success: false, errors: [emptyMsg] };\n }\n\n logger.debug(`[useGeminiMethod] Processing with ${components.length} components`);\n\n const matchResult = await geminiLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n logger.info(`[useGeminiMethod] Successfully generated ${responseMode} using Gemini`);\n return matchResult;\n}\n\n/**\n * Method 4: Use OpenAI GPT LLM\n */\nexport const useOpenAIMethod = async (\n prompt: string,\n components: Component[],\n apiKey?: string,\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n logger.debug('[useOpenAIMethod] Initializing OpenAI GPT matching method');\n logger.debug(`[useOpenAIMethod] Response mode: ${responseMode}`);\n const msg = `Using OpenAI GPT ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\n logger.info(msg);\n logCollector?.info(msg);\n\n // Only check components for component mode\n if (responseMode === 'component' && components.length === 0) {\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\n logger.error('[useOpenAIMethod] No components available');\n logCollector?.error(emptyMsg);\n return { success: false, errors: [emptyMsg] };\n }\n\n logger.debug(`[useOpenAIMethod] Processing with ${components.length} components`);\n\n const matchResult = await openaiLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n logger.info(`[useOpenAIMethod] Successfully generated ${responseMode} using OpenAI`);\n return matchResult;\n}\n\n//@to-do\nexport const getUserResponseFromCache = async (prompt: string) => {\n return false\n}\n\n/**\n * Get user response with automatic fallback between LLM providers\n * Tries providers in order specified by LLM_PROVIDERS or passed parameter\n * @param responseMode - 'component' for component generation (default), 'text' for text responses\n * @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)\n * @param collections - Collection registry for executing database queries (required for text mode with queries)\n * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called (only for text mode)\n */\nexport const get_user_response = async (\n prompt: string,\n components: Component[],\n anthropicApiKey?: string,\n groqApiKey?: string,\n geminiApiKey?: string,\n openaiApiKey?: string,\n llmProviders?: LLMProvider[],\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any,\n externalTools?: any[],\n userId?: string\n): Promise<T_RESPONSE> => {\n\n logger.debug(`[get_user_response] Starting user response generation for prompt: \"${prompt.substring(0, 50)}...\"`);\n logger.debug(`[get_user_response] Response mode: ${responseMode}`);\n\n //first checking if the same prompt is already asked and we got successful response.\n logger.debug('[get_user_response] Checking cache for existing response');\n const userResponse = await getUserResponseFromCache(prompt);\n if(userResponse){\n logger.info('[get_user_response] User response found in cache - returning cached result');\n logCollector?.info('User response found in cache');\n return {\n success: true,\n data: userResponse,\n errors: []\n };\n }\n\n logger.debug('[get_user_response] No cached response found, proceeding with LLM providers');\n\n const providers = llmProviders || getLLMProviders();\n const errors: string[] = [];\n\n const providerOrder = providers.join(', ');\n logCollector?.info(`LLM Provider order: [${providerOrder}]`);\n\n // Log conversation context info if available\n if (conversationHistory && conversationHistory.length > 0) {\n const exchangeCount = conversationHistory.split('\\n').filter((l: string) => l.startsWith('Q')).length;\n logger.debug(`[get_user_response] Using conversation history with ${exchangeCount} previous exchanges`);\n logCollector?.info(`Using conversation history with ${exchangeCount} previous exchanges`);\n } else {\n logger.debug('[get_user_response] No conversation history available');\n }\n\n for (let i = 0; i < providers.length; i++) {\n const provider = providers[i];\n const isLastProvider = i === providers.length - 1;\n\n const attemptMsg = `Attempting provider: ${provider} (${i + 1}/${providers.length})`;\n logCollector?.info(attemptMsg);\n\n let result: T_RESPONSE;\n if (provider === 'anthropic') {\n result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n } else if (provider === 'groq') {\n result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n } else if (provider === 'gemini') {\n result = await useGeminiMethod(prompt, components, geminiApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n } else if (provider === 'openai') {\n result = await useOpenAIMethod(prompt, components, openaiApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);\n } else {\n logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);\n errors.push(`Unknown provider: ${provider}`);\n continue; // Skip unknown providers\n }\n\n if (result.success) {\n const successMsg = `Success with provider: ${provider}`;\n logger.info(`${successMsg}`);\n logCollector?.info(successMsg);\n return result;\n } else {\n // Collect errors from result\n const providerErrors = result.errors.map(err => `${provider}: ${err}`);\n errors.push(...providerErrors);\n const warnMsg = `Provider ${provider} returned unsuccessful result: ${result.errors.join(', ')}`;\n logger.warn(`[get_user_response] ${warnMsg}`);\n logCollector?.warn(warnMsg);\n\n // If this is not the last provider, try the next one\n if (!isLastProvider) {\n const fallbackMsg = 'Falling back to next provider...';\n logger.info(`[get_user_response] ${fallbackMsg}`);\n logCollector?.info(fallbackMsg);\n }\n }\n }\n\n // All providers failed\n const failureMsg = `All LLM providers failed`;\n logger.error(`[get_user_response] ${failureMsg}. Errors: ${errors.join('; ')}`);\n logCollector?.error(`${failureMsg}. Errors: ${errors.join('; ')}`);\n\n return {\n success: false,\n errors\n };\n}\n\n","import { Component, LLMProvider, Message, UserPromptRequestMessageSchema, T_RESPONSE } from \"../types\";\nimport { get_user_response } from \"../userResponse\";\nimport { logger } from \"../utils/logger\";\nimport { llmUsageLogger } from \"../utils/llm-usage-logger\";\nimport { userPromptErrorLogger } from \"../utils/user-prompt-error-logger\";\nimport { UILogCollector } from \"../utils/log-collector\";\nimport { saveConversation } from \"../utils/conversation-saver\";\nimport { ThreadManager, UIBlock } from \"../threads\";\nimport { CONTEXT_CONFIG } from \"../config/context\";\nimport { ZodError } from \"zod\";\n\n\n// Define return type for get_user_request extending T_RESPONSE\ninterface UserRequestResponse extends T_RESPONSE {\n\tuiBlockId?: string;\n\tthreadId?: string;\n\tid?: string;\n\twsId?: string;\n}\n\n\nconst get_user_request = async (\n\tdata: any,\n\tcomponents: Component[],\n\tsendMessage: (message: Message) => void,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tcollections?: any,\n\texternalTools?: any[],\n\tuserId?: string\n): Promise<UserRequestResponse> => {\n\tconst errors: string[] = [];\n\n\t// Parse incoming message data\n\tlogger.debug('[USER_PROMPT_REQ] Parsing incoming message data');\n\tconst parseResult = UserPromptRequestMessageSchema.safeParse(data);\n\n\tif (!parseResult.success) {\n\t\tconst zodError = parseResult.error as ZodError;\n\t\tzodError.errors.forEach(err => {\n\t\t\terrors.push(`${err.path.join('.')}: ${err.message}`);\n\t\t});\n\t\treturn { success: false, errors };\n\t}\n\n\tconst userPromptRequest = parseResult.data;\n\tconst { id, payload } = userPromptRequest;\n\n\tconst prompt = payload.prompt;\n\tconst SA_RUNTIME = payload.SA_RUNTIME;\n\tconst wsId = userPromptRequest.from.id || 'unknown';\n\n\t// Reset log files for this new request (clears previous request logs)\n\tconst promptContext = `User Prompt: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? '...' : ''}`;\n\tllmUsageLogger.resetLogFile(promptContext);\n\tuserPromptErrorLogger.resetLogFile(promptContext);\n\n\t\n\t// Validate SA_RUNTIME and extract threadId and uiBlockId\n\tif (!SA_RUNTIME) {\n\t\terrors.push('SA_RUNTIME is required');\n\t}\n\t\n\tconst threadId = SA_RUNTIME?.threadId;\n\tconst existingUiBlockId = SA_RUNTIME?.uiBlockId;\n\t\n\tif (!threadId) {\n\t\terrors.push('threadId in SA_RUNTIME is required');\n\t}\n\t\n\tif (!existingUiBlockId) {\n\t\terrors.push('uiBlockId in SA_RUNTIME is required');\n\t}\n\t\n\tif (!prompt) {\n\t\terrors.push('Prompt not found');\n\t}\n\t\n\tlogger.debug(`[REQUEST ${id}] Full request details - uiBlockId: ${existingUiBlockId}, threadId: ${threadId}, prompt: ${prompt}`);\n\t// if (!components || components.length === 0) {\n\t// \terrors.push('Components not found');\n\t// }\n\n\t// If there are validation errors, return early\n\tif (errors.length > 0) {\n\t\treturn { success: false, errors, id, wsId };\n\t}\n\n\t// Create log collector with uiBlockId\n\tconst logCollector = new UILogCollector(wsId, sendMessage, existingUiBlockId!);\n\n\t// Get or create thread BEFORE processing to enable conversation context\n\tconst threadManager = ThreadManager.getInstance();\n\tlet thread = threadManager.getThread(threadId!);\n\tif (!thread) {\n\t\tthread = threadManager.createThread(threadId!);\n\t\tlogger.info(`Created new thread: ${threadId}`);\n\t}\n\n\tlogCollector.info(`Starting user prompt request with ${components.length} components`);\n\n\t// Extract conversation context from thread (excluding current UIBlock)\n\tconst conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId!);\n\n\t// Get responseMode from payload\n\tconst responseMode = payload.responseMode || 'component' ; \n\tlogger.info('responseMode', responseMode);\n\n\t// Create stream callback for text mode - sends chunks via WebSocket AND accumulates them\n\tlet streamCallback: ((chunk: string) => void) | undefined;\n\tlet accumulatedStreamResponse = ''; // Accumulate all streaming chunks for storage in UIBlock\n\tif (responseMode === 'text') {\n\t\tstreamCallback = (chunk: string) => {\n\t\t\t// Accumulate chunk for storage in UIBlock\n\t\t\taccumulatedStreamResponse += chunk;\n\n\t\t\t// Send streaming chunk to frontend via WebSocket\n\t\t\t// IMPORTANT: Use stream_${uiBlockId} as ID to avoid conflicting with the final response\n\t\t\t// The frontend will match by the stream_ prefix and uiBlockId\n\t\t\tlogger.debug(`[STREAM] Sending chunk (${chunk.length} chars): \"${chunk.substring(0, 20)}...\"`);\n\t\t\tconst streamMessage: Message = {\n\t\t\t\tid: `stream_${existingUiBlockId}`, // Different ID pattern for streaming\n\t\t\t\ttype: 'USER_PROMPT_STREAM',\n\t\t\t\tfrom: { type: 'data-agent' },\n\t\t\t\tto: {\n\t\t\t\t\ttype: 'runtime',\n\t\t\t\t\tid: wsId\n\t\t\t\t},\n\t\t\t\tpayload: {\n\t\t\t\t\tuiBlockId: existingUiBlockId,\n\t\t\t\t\tchunk\n\t\t\t\t}\n\t\t\t};\n\t\t\tsendMessage(streamMessage);\n\t\t\tlogger.debug(`[STREAM] Chunk sent to wsId: ${wsId}`);\n\t\t};\n\t}\n\n\t// Get user response with log collector, conversation context, optional streaming, collections, and external tools\n\tconst userResponse = await get_user_response(\n\t\tprompt!,\n\t\tcomponents,\n\t\tanthropicApiKey,\n\t\tgroqApiKey,\n\t\tgeminiApiKey,\n\t\topenaiApiKey,\n\t\tllmProviders,\n\t\tlogCollector,\n\t\tconversationHistory,\n\t\tresponseMode,\n\t\tstreamCallback,\n\t\tcollections,\n\t\texternalTools,\n\t\tuserId\n\t);\n\t// logger.info('llm userResponse', userResponse);\n\n\t// Log completion (sent immediately if uiBlockId was provided)\n\tlogCollector.info('User prompt request completed');\n\n\t// Use the uiBlockId from SA_RUNTIME (already validated)\n\tconst uiBlockId = existingUiBlockId!;\n\n\t// If response failed, don't create UIBlock and return error\n\tif (!userResponse.success) {\n\t\tlogger.error(`User prompt request failed with errors: ${userResponse.errors.join(', ')}`);\n\n\t\t// Log detailed error information\n\t\tuserPromptErrorLogger.logError('User Response Failed', userResponse.errors.join('\\n'), {\n\t\t\tprompt: prompt,\n\t\t\tuiBlockId,\n\t\t\tthreadId: threadId!,\n\t\t\tresponseData: userResponse.data\n\t\t});\n\t\tuserPromptErrorLogger.writeSummary();\n\t\tllmUsageLogger.logSessionSummary(`FAILED: ${prompt?.substring(0, 30)}`);\n\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tdata: userResponse.data,\n\t\t\terrors: userResponse.errors,\n\t\t\tuiBlockId,\n\t\t\tthreadId: threadId!,\n\t\t\tid,\n\t\t\twsId\n\t\t};\n\t}\n\n\t// Extract component, textResponse, and actions from successful response\n\tlet component = null;\n\tlet textResponse = null;\n\tlet actions = [];\n\n\tif (userResponse.data) {\n\t\tif (typeof userResponse.data === 'object') {\n\t\t\tif ('component' in userResponse.data) {\n\t\t\t\tcomponent = (userResponse.data as any).component;\n\t\t\t}\n\t\t\t// Check for both 'text' and 'textResponse' keys\n\t\t\tif ('text' in userResponse.data) {\n\t\t\t\ttextResponse = (userResponse.data as any).text;\n\t\t\t} else if ('textResponse' in userResponse.data) {\n\t\t\t\ttextResponse = (userResponse.data as any).textResponse;\n\t\t\t}\n\t\t\tif ('actions' in userResponse.data) {\n\t\t\t\tactions = (userResponse.data as any).actions || [];\n\t\t\t}\n\t\t}\n\t}\n\n\t// For text mode, use accumulated stream response which includes ALL messages (analyzing, query, results, etc.)\n\t// For component mode, use the textResponse as-is\n\tconst finalTextResponse = responseMode === 'text' && accumulatedStreamResponse\n\t\t? accumulatedStreamResponse\n\t\t: textResponse;\n\n\t// Create UIBlock with component metadata, empty component data, and full text response\n\tconst uiBlock = new UIBlock(\n\t\tprompt!,\n\t\t{}, // componentData: initially empty, will be filled later\n\t\tcomponent, // generatedComponentMetadata: full component object (ComponentSchema)\n\t\t[], // actions: empty initially, will be set below\n\t\tuiBlockId,\n\t\tfinalTextResponse // textResponse: FULL streaming response including all intermediate messages\n\t);\n\n\t// Store actions in UIBlock if they were generated\n\tif (actions.length > 0) {\n\t\tuiBlock.setActions(actions);\n\t\tlogger.info(`Stored ${actions.length} actions in UIBlock: ${uiBlockId}`);\n\t}\n\n\t// Add UIBlock to Thread\n\tthread.addUIBlock(uiBlock);\n\n\tlogger.info(`Created UIBlock: ${uiBlockId} in Thread: ${threadId}`);\n\n\t// Save conversation to backend for semantic search and history\n\t// Skip saving if response came from exact semantic match (>=99%)\n\tif (userId) {\n\t\tconst responseMethod = userResponse.data?.method || '';\n\t\tconst semanticSimilarity = userResponse.data?.semanticSimilarity || 0;\n\n\t\t// Check if this is an exact semantic match (>=99%)\n\t\tconst isExactMatch =\n\t\t\tresponseMethod.includes('semantic-match') && semanticSimilarity >= 0.99;\n\n\t\tif (isExactMatch) {\n\t\t\tlogger.info(\n\t\t\t\t`Skipping conversation save - response from exact semantic match (${(semanticSimilarity * 100).toFixed(2)}% similarity)`\n\t\t\t);\n\t\t\tlogCollector.info(\n\t\t\t\t`Using exact cached result (${(semanticSimilarity * 100).toFixed(2)}% match) - not saving duplicate conversation`\n\t\t\t);\n\t\t} else {\n\t\t\t// Save new conversation\n\t\t\tconst uiBlockData = uiBlock.toJSON();\n\t\t\tconst saveResult = await saveConversation({\n\t\t\t\tuserId,\n\t\t\t\tuserPrompt: prompt!,\n\t\t\t\tuiblock: uiBlockData,\n\t\t\t\tuiBlockId: uiBlockId,\n\t\t\t\tthreadId: threadId!,\n\t\t\t\tcollections\n\t\t\t});\n\n\t\t\tif (saveResult.success) {\n\t\t\t\tlogger.info(`Conversation saved with ID: ${saveResult.conversationId}`);\n\t\t\t} else {\n\t\t\t\tlogger.warn(`Failed to save conversation: ${saveResult.error}`);\n\t\t\t\t// Continue anyway - don't fail the request if conversation saving fails\n\t\t\t}\n\t\t}\n\t}\n\n\t// Log session summary for this request (writes total usage to log file)\n\tllmUsageLogger.logSessionSummary(prompt?.substring(0, 50));\n\n\t// Return response with uiBlockId and threadId\n\treturn {\n\t\tsuccess: userResponse.success,\n\t\tdata: userResponse.data,\n\t\terrors: userResponse.errors,\n\t\tuiBlockId,\n\t\tthreadId: threadId!,\n\t\tid,\n\t\twsId\n\t};\n}\n\nexport async function handleUserPromptRequest(\n\tdata: any,\n\tcomponents: Component[],\n\tsendMessage: (message: Message) => void,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tcollections?: any,\n\texternalTools?: any[],\n\tuserId?: string\n): Promise<void> {\n\tconst response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools, userId);\n\n\t// Send response using sendDataResponse\n\tsendDataResponse(\n\t\tresponse.id || data.id,\n\t\t{\n\t\t\tsuccess: response.success,\n\t\t\terrors: response.errors,\n\t\t\tdata: response.data,\n\t\t\tuiBlockId: response.uiBlockId,\n\t\t\tthreadId: response.threadId\n\t\t},\n\t\tsendMessage,\n\t\tresponse.wsId || data.from?.id\n\t);\n}\n\n/**\n * Send a data_res response message\n */\nfunction sendDataResponse(\n\tid: string,\n\tres: T_RESPONSE & { uiBlockId?: string; threadId?: string },\n\tsendMessage: (message: Message) => void,\n\tclientId?: string,\n): void {\n\tconst response: Message = {\n\t\tid,\n\t\ttype: 'USER_PROMPT_RES',\n\t\tfrom: { type: 'data-agent' },\n\t\tto: {\n\t\t\ttype: 'runtime',\n\t\t\tid: clientId\n\t\t},\n\t\tpayload: {\n\t\t\t...res,\n\t\t}\n\t};\n\n\tsendMessage(response);\n} ","import { Message } from '../types';\nimport { logger, type LogLevel } from './logger';\n\nexport interface CapturedLog {\n timestamp: number;\n level: 'info' | 'error' | 'warn' | 'debug';\n message: string;\n type?: 'explanation' | 'query' | 'general';\n data?: Record<string, any>;\n}\n\n/**\n * Log level hierarchy for filtering\n */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n errors: 0,\n warnings: 1,\n info: 2,\n verbose: 3,\n};\n\nconst MESSAGE_LEVEL_PRIORITY: Record<'error' | 'warn' | 'info' | 'debug', number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\n/**\n * UILogCollector captures logs during user prompt processing\n * and sends them to runtime via ui_logs message with uiBlockId as the message id\n * Logs are sent in real-time for streaming effect in the UI\n * Respects the global log level configuration\n */\nexport class UILogCollector {\n private logs: CapturedLog[] = [];\n private uiBlockId: string | null;\n private clientId: string;\n private sendMessage: (message: Message) => void;\n private currentLogLevel: LogLevel;\n\n constructor(\n clientId: string,\n sendMessage: (message: Message) => void,\n uiBlockId?: string\n ) {\n this.uiBlockId = uiBlockId || null;\n this.clientId = clientId;\n this.sendMessage = sendMessage;\n this.currentLogLevel = logger.getLogLevel();\n }\n\n /**\n * Check if logging is enabled (uiBlockId is provided)\n */\n isEnabled(): boolean {\n return this.uiBlockId !== null;\n }\n\n /**\n * Check if a message should be logged based on current log level\n */\n private shouldLog(messageLevel: 'error' | 'warn' | 'info' | 'debug'): boolean {\n const currentLevelPriority = LOG_LEVEL_PRIORITY[this.currentLogLevel];\n const messagePriority = MESSAGE_LEVEL_PRIORITY[messageLevel];\n return messagePriority <= currentLevelPriority;\n }\n\n /**\n * Add a log entry with timestamp and immediately send to runtime\n * Only logs that pass the log level filter are captured and sent\n */\n private addLog(\n level: 'info' | 'error' | 'warn' | 'debug',\n message: string,\n type?: 'explanation' | 'query' | 'general',\n data?: Record<string, any>\n ): void {\n // Check if this log level should be captured based on current log level\n if (!this.shouldLog(level)) {\n return;\n }\n\n const log: CapturedLog = {\n timestamp: Date.now(),\n level,\n message,\n ...(type && { type }),\n ...(data && { data }),\n };\n\n this.logs.push(log);\n\n // Send the log immediately to runtime for streaming effect\n this.sendLogImmediately(log);\n\n // Also log to terminal using the main logger based on level\n switch (level) {\n case 'error':\n logger.error('UILogCollector:', log);\n break;\n case 'warn':\n logger.warn('UILogCollector:', log);\n break;\n case 'info':\n logger.info('UILogCollector:', log);\n break;\n case 'debug':\n logger.debug('UILogCollector:', log);\n break;\n }\n }\n\n /**\n * Send a single log to runtime immediately\n */\n private sendLogImmediately(log: CapturedLog): void {\n if (!this.isEnabled()) {\n return;\n }\n\n const response: Message = {\n id: this.uiBlockId!,\n type: 'UI_LOGS',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: this.clientId,\n },\n payload: {\n logs: [log], // Send single log in array\n },\n };\n\n this.sendMessage(response);\n }\n\n /**\n * Log info message\n */\n info(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('info', message, type, data);\n }\n }\n\n /**\n * Log error message\n */\n error(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('error', message, type, data);\n }\n }\n\n /**\n * Log warning message\n */\n warn(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('warn', message, type, data);\n }\n }\n\n /**\n * Log debug message\n */\n debug(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('debug', message, type, data);\n }\n }\n\n /**\n * Log LLM explanation with typed metadata\n */\n logExplanation(message: string, explanation: string, data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('info', message, 'explanation', {\n explanation,\n ...data,\n });\n }\n }\n\n /**\n * Log generated query with typed metadata\n */\n logQuery(message: string, query: string, data?: Record<string, any>): void {\n if (this.isEnabled()) {\n this.addLog('info', message, 'query', {\n query,\n ...data,\n });\n }\n }\n\n /**\n * Send all collected logs at once (optional, for final summary)\n */\n sendAllLogs(): void {\n if (!this.isEnabled() || this.logs.length === 0) {\n return;\n }\n\n const response: Message = {\n id: this.uiBlockId!,\n type: 'UI_LOGS',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: this.clientId,\n },\n payload: {\n logs: this.logs,\n },\n };\n\n this.sendMessage(response);\n }\n\n /**\n * Get all collected logs\n */\n getLogs(): CapturedLog[] {\n return [...this.logs];\n }\n\n /**\n * Clear all logs\n */\n clearLogs(): void {\n this.logs = [];\n }\n\n /**\n * Set uiBlockId (in case it's provided later)\n */\n setUIBlockId(uiBlockId: string): void {\n this.uiBlockId = uiBlockId;\n }\n}\n","import { logger } from './logger';\n\n/**\n * Unified UIBlock structure for database storage\n * Used in both bookmarks and user-conversations tables\n */\nexport interface DBUIBlock {\n\tid: string;\n\tcomponent: Record<string, any> | null;\n\tanalysis: string | null;\n\tuser_prompt: string;\n}\n\n/**\n * Transform UIBlock.toJSON() output to the unified DB structure\n * Maps: userQuestion -> user_prompt, generatedComponentMetadata -> component, textResponse -> analysis\n * @param uiblock - UIBlock.toJSON() output\n * @param userPrompt - The user's prompt/question\n * @param uiBlockId - The UIBlock ID (passed separately, not in uiblock object)\n */\nexport function transformUIBlockForDB(uiblock: any, userPrompt: string, uiBlockId: string): DBUIBlock {\n\t// Extract component from generatedComponentMetadata, or null if empty\n\tconst component = uiblock?.generatedComponentMetadata && Object.keys(uiblock.generatedComponentMetadata).length > 0\n\t\t? uiblock.generatedComponentMetadata\n\t\t: null;\n\n\treturn {\n\t\tid: uiBlockId || uiblock?.id || '',\n\t\tcomponent: component,\n\t\tanalysis: uiblock?.textResponse || null,\n\t\tuser_prompt: userPrompt || uiblock?.userQuestion || '',\n\t};\n}\n\n/**\n * Parameters for saving a conversation\n */\nexport interface SaveConversationParams {\n\tuserId: string;\n\tuserPrompt: string;\n\tuiblock: any; // UIBlock toJSON() output\n\tuiBlockId: string; // ID of the UIBlock\n\tthreadId: string;\n\tcollections?: any;\n}\n\n/**\n * Result of attempting to save a conversation\n */\nexport interface SaveConversationResult {\n\tsuccess: boolean;\n\tconversationId?: string;\n\tmessage?: string;\n\terror?: string;\n}\n\n/**\n * Saves a user conversation to the backend user_conversations table\n * This enables semantic search and conversation history features\n *\n * @param params - Parameters containing userId, userPrompt, uiblock, threadId, and collections\n * @returns Result indicating success/failure and conversation ID if successful\n */\nexport async function saveConversation(params: SaveConversationParams): Promise<SaveConversationResult> {\n\tconst { userId, userPrompt, uiblock, uiBlockId, threadId, collections } = params;\n\n\t// Validate required parameters\n\tif (!userId) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: userId not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'userId is required'\n\t\t};\n\t}\n\n\tif (!userPrompt) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: userPrompt not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'userPrompt is required'\n\t\t};\n\t}\n\n\tif (!uiblock) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: uiblock not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'uiblock is required'\n\t\t};\n\t}\n\n\tif (!threadId) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: threadId not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'threadId is required'\n\t\t};\n\t}\n\n\tif (!uiBlockId) {\n\t\tlogger.warn('[CONVERSATION_SAVER] Skipping save: uiBlockId not provided');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'uiBlockId is required'\n\t\t};\n\t}\n\n\t// Check if collections are available\n\tif (!collections?.['user-conversations']?.['create']) {\n\t\tlogger.debug('[CONVERSATION_SAVER] Collection \"user-conversations.create\" not available, skipping save');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: 'user-conversations.create collection not available'\n\t\t};\n\t}\n\n\ttry {\n\t\tlogger.info(`[CONVERSATION_SAVER] Saving conversation for userId: ${userId}, uiBlockId: ${uiBlockId}, threadId: ${threadId}`);\n\n\t\t// Convert userId to number (SDK stores it as string, backend expects integer)\n\t\tconst userIdNumber = Number(userId);\n\t\tif (isNaN(userIdNumber)) {\n\t\t\tlogger.warn(`[CONVERSATION_SAVER] Invalid userId: ${userId} (not a valid number)`);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: `Invalid userId: ${userId} (not a valid number)`\n\t\t\t};\n\t\t}\n\n\t\t// Transform UIBlock to unified DB structure\n\t\tconst dbUIBlock = transformUIBlockForDB(uiblock, userPrompt, uiBlockId);\n\t\tlogger.debug(`[CONVERSATION_SAVER] Transformed UIBlock for DB: ${JSON.stringify(dbUIBlock)}`);\n\n\t\t// Step 1: Save to PostgreSQL user_conversations table\n\t\tconst saveResult = await collections['user-conversations']['create']({\n\t\t\tuserId: userIdNumber,\n\t\t\tuserPrompt,\n\t\t\tuiblock: dbUIBlock,\n\t\t\tthreadId\n\t\t});\n\n\t\tif (!saveResult?.success) {\n\t\t\tlogger.warn(`[CONVERSATION_SAVER] Failed to save conversation to PostgreSQL: ${saveResult?.message || 'Unknown error'}`);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: saveResult?.message || 'Unknown error from backend'\n\t\t\t};\n\t\t}\n\n\t\tlogger.info(`[CONVERSATION_SAVER] Successfully saved conversation to PostgreSQL, id: ${saveResult.data?.id}`);\n\n\t\t// Step 2: Create embedding in ChromaDB for semantic search\n\t\tif (collections?.['conversation-history']?.['embed']) {\n\t\t\ttry {\n\t\t\t\tlogger.info('[CONVERSATION_SAVER] Creating embedding for semantic search...');\n\t\t\t\tconst embedResult = await collections['conversation-history']['embed']({\n\t\t\t\t\tuiBlockId,\n\t\t\t\t\tuserPrompt,\n\t\t\t\t\tuiBlock: dbUIBlock, // Use the transformed UIBlock\n\t\t\t\t\tuserId: userIdNumber\n\t\t\t\t});\n\n\t\t\t\tif (embedResult?.success) {\n\t\t\t\t\tlogger.info('[CONVERSATION_SAVER] Successfully created embedding');\n\t\t\t\t} else {\n\t\t\t\t\tlogger.warn('[CONVERSATION_SAVER] Failed to create embedding:', embedResult?.error || 'Unknown error');\n\t\t\t\t\t// Don't fail the entire operation if embedding fails\n\t\t\t\t}\n\t\t\t} catch (embedError) {\n\t\t\t\tconst embedErrorMsg = embedError instanceof Error ? embedError.message : String(embedError);\n\t\t\t\tlogger.warn('[CONVERSATION_SAVER] Error creating embedding:', embedErrorMsg);\n\t\t\t\t// Don't fail the entire operation if embedding fails\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.debug('[CONVERSATION_SAVER] Embedding collection not available, skipping ChromaDB storage');\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tconversationId: saveResult.data?.id,\n\t\t\tmessage: 'Conversation saved successfully'\n\t\t};\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\tlogger.error('[CONVERSATION_SAVER] Error saving conversation:', errorMessage);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: errorMessage\n\t\t};\n\t}\n}\n","/**\n * Configuration for conversation context and history management\n */\nexport const CONTEXT_CONFIG = {\n /**\n * Maximum number of previous UIBlocks to include as conversation context\n * Set to 0 to disable conversation history\n * Higher values provide more context but may increase token usage\n */\n MAX_CONVERSATION_CONTEXT_BLOCKS: 3,\n};\n","import { Component, Message, UserPromptSuggestionsMessageSchema, CollectionRegistry } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle user prompt suggestions request\n * Uses token-based search for components and PostgreSQL full-text search for bookmarks\n */\nexport async function handleUserPromptSuggestions(\n data: any,\n components: Component[],\n sendMessage: (message: Message) => void,\n collections: CollectionRegistry,\n userId?: string\n): Promise<void> {\n try {\n const request = UserPromptSuggestionsMessageSchema.parse(data);\n const { id, payload, from } = request;\n\n const { prompt, limit = 10 } = payload;\n const wsId = from.id;\n\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Processing user prompt suggestions: ${prompt}`);\n\n // Validate input\n if (!prompt || prompt.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Prompt is required and cannot be empty'\n }, sendMessage, wsId);\n return;\n }\n\n // COMMENTED OUT: Semantic/embedding-based search (kept for potential future use)\n // const componentSearchHandler = collections?.['components']?.['search'];\n // const bookmarkSearchHandler = collections?.['bookmarks']?.['search'];\n //\n // let componentSuggestions: any[] = [];\n // let bookmarkSuggestions: any[] = [];\n // let useEmbeddingSearch = false;\n //\n // // Build parallel search promises\n // const searchPromises: Promise<void>[] = [];\n //\n // // Search components via embedding\n // if (componentSearchHandler) {\n // searchPromises.push(\n // (async () => {\n // try {\n // logger.info('Using embedding-based search for components');\n // const result = await componentSearchHandler({ prompt, limit });\n //\n // if (result.success && result.suggestions) {\n // componentSuggestions = result.suggestions.map((s: any) => ({\n // ...s,\n // suggestionType: 'component'\n // }));\n // useEmbeddingSearch = true;\n // logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${componentSuggestions.length} component suggestions`);\n // }\n // } catch (embeddingError) {\n // logger.warn('Component embedding search failed:', embeddingError);\n // }\n // })()\n // );\n // }\n //\n // // Search bookmarks via embedding (if userId is available)\n // if (bookmarkSearchHandler && userId && userId !== 'anonymous') {\n // searchPromises.push(\n // (async () => {\n // try {\n // logger.info(`Using embedding-based search for bookmarks (user: ${userId})`);\n // const result = await bookmarkSearchHandler({ prompt, userId, limit });\n //\n // if (result.success && result.suggestions) {\n // bookmarkSuggestions = result.suggestions.map((s: any) => ({\n // ...s,\n // suggestionType: 'bookmark'\n // }));\n // useEmbeddingSearch = true;\n // logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${bookmarkSuggestions.length} bookmark suggestions`);\n // }\n // } catch (embeddingError) {\n // logger.warn('Bookmark embedding search failed:', embeddingError);\n // }\n // })()\n // );\n // }\n //\n // // Wait for all searches to complete in parallel\n // if (searchPromises.length > 0) {\n // await Promise.all(searchPromises);\n // }\n //\n // // If we got embedding results, combine and return\n // if (useEmbeddingSearch && (componentSuggestions.length > 0 || bookmarkSuggestions.length > 0)) {\n // // Combine and sort by similarity (no threshold filtering - show all suggestions)\n // const allSuggestions = [...componentSuggestions, ...bookmarkSuggestions]\n // .sort((a, b) => (b.similarity || 0) - (a.similarity || 0))\n // .slice(0, limit);\n //\n // logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Returning all suggestions: ${componentSuggestions.length} components, ${bookmarkSuggestions.length} bookmarks`);\n //\n // sendResponse(id, {\n // success: true,\n // data: {\n // prompt,\n // suggestions: allSuggestions,\n // count: allSuggestions.length,\n // componentCount: componentSuggestions.length,\n // bookmarkCount: bookmarkSuggestions.length,\n // message: `Found ${allSuggestions.length} suggestions (${componentSuggestions.length} components, ${bookmarkSuggestions.length} bookmarks)`\n // }\n // }, sendMessage, wsId);\n // return;\n // }\n // END COMMENTED OUT SECTION\n\n // Use token-based search for components and PostgreSQL text search for bookmarks\n const displayComponents = components.filter(c => c.isDisplayComp === true);\n const bookmarkTextSearchHandler = collections?.['bookmarks']?.['textSearch'];\n\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Using token-based search for components (${displayComponents.length} display components) and PostgreSQL text search for bookmarks`);\n\n // Build parallel search promises\n const searchPromises: Promise<void>[] = [];\n let componentSuggestions: any[] = [];\n let bookmarkSuggestions: any[] = [];\n\n // Token-based search for components\n if (displayComponents.length > 0) {\n const componentResults = searchComponents(prompt, displayComponents, limit);\n componentSuggestions = componentResults.map((c: Component) => ({\n ...c,\n suggestionType: 'component',\n similarity: 1.0 // Token-based search doesn't have similarity scores\n }));\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${componentSuggestions.length} component suggestions via token search`);\n }\n\n // PostgreSQL text search for bookmarks (if userId is available)\n if (bookmarkTextSearchHandler && userId && userId !== 'anonymous') {\n searchPromises.push(\n (async () => {\n try {\n logger.info(`Using PostgreSQL text search for bookmarks (user: ${userId})`);\n const result = await bookmarkTextSearchHandler({ prompt, userId, limit });\n\n if (result.success && result.suggestions) {\n bookmarkSuggestions = result.suggestions.map((s: any) => ({\n ...s,\n suggestionType: 'bookmark'\n }));\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${bookmarkSuggestions.length} bookmark suggestions via PostgreSQL text search`);\n }\n } catch (searchError) {\n logger.warn('Bookmark PostgreSQL text search failed:', searchError);\n }\n })()\n );\n }\n\n // Wait for bookmark search to complete\n if (searchPromises.length > 0) {\n await Promise.all(searchPromises);\n }\n\n // Combine results\n const allSuggestions = [...componentSuggestions, ...bookmarkSuggestions].slice(0, limit);\n\n // Count how many of each type are actually in the final result\n const finalComponentCount = allSuggestions.filter(s => s.suggestionType === 'component').length;\n const finalBookmarkCount = allSuggestions.filter(s => s.suggestionType === 'bookmark').length;\n\n if (allSuggestions.length === 0) {\n sendResponse(id, {\n success: true,\n data: {\n prompt,\n suggestions: [],\n count: 0,\n componentCount: 0,\n bookmarkCount: 0,\n message: 'No matching suggestions found'\n }\n }, sendMessage, wsId);\n return;\n }\n\n logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Returning ${allSuggestions.length} suggestions: ${finalComponentCount} components, ${finalBookmarkCount} bookmarks`);\n\n sendResponse(id, {\n success: true,\n data: {\n prompt,\n suggestions: allSuggestions,\n count: allSuggestions.length,\n componentCount: finalComponentCount,\n bookmarkCount: finalBookmarkCount,\n message: `Found ${allSuggestions.length} suggestions (${finalComponentCount} components, ${finalBookmarkCount} bookmarks)`\n }\n }, sendMessage, wsId);\n\n } catch (error) {\n logger.error('Failed to handle user prompt suggestions request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Search components based on prompt keywords\n * Searches in component name, displayName, description, keywords, and category\n * @param prompt - Search prompt\n * @param components - List of components to search in\n * @param limit - Maximum number of results to return\n * @returns Matching components sorted by relevance\n */\nfunction searchComponents(prompt: string, components: Component[], limit: number): Component[] {\n const promptLower = prompt.toLowerCase();\n const promptTokens = promptLower.split(/\\s+/).filter(token => token.length > 0);\n\n // Score each component based on keyword matches\n const scoredComponents = components.map(component => {\n let score = 0;\n\n const componentName = component.name.toLowerCase();\n const componentDisplayName = (component.displayName || '').toLowerCase();\n const componentDesc = component.description.toLowerCase();\n const componentKeywords = (component.keywords || []).map(k => k.toLowerCase());\n const componentCategory = (component.category || '').toLowerCase();\n\n // Search in each field with different weights\n for (const token of promptTokens) {\n // Exact name match (highest weight)\n if (componentName === token) {\n score += 10;\n }\n // Name contains token\n else if (componentName.includes(token)) {\n score += 5;\n }\n\n // DisplayName contains token (high weight - user-friendly name)\n if (componentDisplayName.includes(token)) {\n score += 6;\n }\n\n // Exact keyword match\n if (componentKeywords.includes(token)) {\n score += 8;\n }\n // Keywords contain token\n else if (componentKeywords.some(k => k.includes(token))) {\n score += 4;\n }\n\n // Description contains token\n if (componentDesc.includes(token)) {\n score += 2;\n }\n\n // Category contains token\n if (componentCategory.includes(token)) {\n score += 3;\n }\n }\n\n return { component, score };\n });\n\n // Filter out components with score 0, sort by score (descending), and take top results\n return scoredComponents\n .filter(({ score }) => score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map(({ component }) => component);\n}\n\n/**\n * Send user prompt suggestions response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'USER_PROMPT_SUGGESTIONS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { anthropicLLM } from './anthropic';\nimport { groqLLM } from './groq';\nimport { geminiLLM } from './gemini';\nimport { openaiLLM } from './openai';\nimport { LLMProvider, Component } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Generate next questions based on the original user prompt and generated component\n * Routes to the appropriate LLM provider (Anthropic or Groq)\n * Falls back to next provider if current provider fails or returns empty results\n */\nexport async function generateNextQuestions(\n\toriginalUserPrompt: string,\n\tcomponent: Component,\n\tcomponentData?: Record<string, unknown>,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tlogCollector?: any,\n\tconversationHistory?: string\n): Promise<string[]> {\n\ttry {\n\t\tlogger.debug('[generateNextQuestions] Starting next questions generation');\n\t\tlogger.debug(`[generateNextQuestions] User prompt: \"${originalUserPrompt?.substring(0, 50)}...\"`);\n\t\tlogger.debug(`[generateNextQuestions] Component: ${component?.name || 'unknown'} (${component?.type || 'unknown'})`);\n\t\tlogger.debug(`[generateNextQuestions] Component data available: ${componentData ? 'yes' : 'no'}`);\n\n\t\t// Determine which providers to use\n\t\tconst providers = llmProviders || ['anthropic', 'gemini', 'openai', 'groq'];\n\t\tlogger.info(`[generateNextQuestions] Using LLM providers: [${providers.join(', ')}]`);\n\n\t\t// Log conversation context info\n\t\tif (conversationHistory && conversationHistory.length > 0) {\n\t\t\tconst exchangeCount = conversationHistory.split('\\n').filter((l: string) => l.startsWith('Q')).length;\n\t\t\tlogger.debug(`[generateNextQuestions] Using conversation history with ${exchangeCount} previous exchanges`);\n\t\t} else {\n\t\t\tlogger.debug('[generateNextQuestions] No conversation history available');\n\t\t}\n\n\t\t// Try each provider in order\n\t\tfor (let i = 0; i < providers.length; i++) {\n\t\t\tconst provider = providers[i];\n\t\t\tconst isLastProvider = i === providers.length - 1;\n\n\t\t\ttry {\n\t\t\t\tlogger.info(`[generateNextQuestions] Attempting provider: ${provider} (${i + 1}/${providers.length})`);\n\t\t\t\tlogCollector?.info(`Generating questions with ${provider}...`);\n\n\t\t\t\tlet result: string[] = [];\n\n\t\t\t\tif (provider === 'groq') {\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using Groq LLM for next questions');\n\t\t\t\t\tresult = await groqLLM.generateNextQuestions(\n\t\t\t\t\t\toriginalUserPrompt,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\tcomponentData,\n\t\t\t\t\t\tgroqApiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t);\n\t\t\t\t} else if (provider === 'gemini') {\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using Gemini LLM for next questions');\n\t\t\t\t\tresult = await geminiLLM.generateNextQuestions(\n\t\t\t\t\t\toriginalUserPrompt,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\tcomponentData,\n\t\t\t\t\t\tgeminiApiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t);\n\t\t\t\t} else if (provider === 'openai') {\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using OpenAI LLM for next questions');\n\t\t\t\t\tresult = await openaiLLM.generateNextQuestions(\n\t\t\t\t\t\toriginalUserPrompt,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\tcomponentData,\n\t\t\t\t\t\topenaiApiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Default to Anthropic\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using Anthropic LLM for next questions');\n\t\t\t\t\tresult = await anthropicLLM.generateNextQuestions(\n\t\t\t\t\t\toriginalUserPrompt,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\tcomponentData,\n\t\t\t\t\t\tanthropicApiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// If we got results, return them\n\t\t\t\tif (result && result.length > 0) {\n\t\t\t\t\tlogger.info(`[generateNextQuestions] Successfully generated ${result.length} questions with ${provider}`);\n\t\t\t\t\tlogger.debug(`[generateNextQuestions] Questions: ${JSON.stringify(result)}`);\n\t\t\t\t\tlogCollector?.info(`Generated ${result.length} follow-up questions`);\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tconst warnMsg = `No questions generated from ${provider}${!isLastProvider ? ', trying next provider...' : ''}`;\n\t\t\t\tlogger.warn(`[generateNextQuestions] ${warnMsg}`);\n\t\t\t\tif (!isLastProvider) {\n\t\t\t\t\tlogCollector?.warn(warnMsg);\n\t\t\t\t}\n\t\t\t} catch (providerError) {\n\t\t\t\tconst errorMsg = providerError instanceof Error ? providerError.message : String(providerError);\n\t\t\t\tlogger.error(`[generateNextQuestions] Provider ${provider} failed: ${errorMsg}`);\n\t\t\t\tlogger.debug(`[generateNextQuestions] Provider error details:`, providerError);\n\n\t\t\t\tif (!isLastProvider) {\n\t\t\t\t\tconst fallbackMsg = `Provider ${provider} failed, trying next provider...`;\n\t\t\t\t\tlogger.info(`[generateNextQuestions] ${fallbackMsg}`);\n\t\t\t\t\tlogCollector?.warn(fallbackMsg);\n\t\t\t\t} else {\n\t\t\t\t\tlogCollector?.error(`Failed to generate questions with ${provider}`);\n\t\t\t\t}\n\t\t\t\t// Continue to next provider\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// All providers failed or returned empty results\n\t\tlogger.warn('[generateNextQuestions] All providers failed or returned no questions');\n\t\tlogCollector?.warn('Unable to generate follow-up questions');\n\t\treturn [];\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\tconst errorStack = error instanceof Error ? error.stack : undefined;\n\n\t\tlogger.error(`[generateNextQuestions] Error generating next questions: ${errorMsg}`);\n\t\tlogger.debug('[generateNextQuestions] Error stack trace:', errorStack);\n\t\tlogCollector?.error(`Error generating next questions: ${errorMsg}`);\n\t\t// Return empty array on error\n\t\treturn [];\n\t}\n}\n","import { ActionsRequestMessageSchema, type LLMProvider, type Message } from '../types';\nimport { generateNextQuestions } from '../userResponse/next-questions';\nimport { logger } from '../utils/logger';\nimport { UILogCollector } from '../utils/log-collector';\nimport { ThreadManager } from '../threads';\nimport { CONTEXT_CONFIG } from '../config/context';\n\n/**\n * Handle incoming actions messages from runtime\n * Generates suggested next questions based on the original user prompt and generated component\n */\nexport async function handleActionsRequest(\n data: any,\n sendMessage: (message: Message) => void,\n anthropicApiKey?: string,\n groqApiKey?: string,\n geminiApiKey?: string,\n openaiApiKey?: string,\n llmProviders?: LLMProvider[]\n): Promise<void> {\n try {\n logger.debug('[ACTIONS_REQ] Parsing incoming actions request');\n const actionsRequest = ActionsRequestMessageSchema.parse(data);\n const { id, payload } = actionsRequest;\n const { SA_RUNTIME } = payload;\n\n const wsId = actionsRequest.from.id || 'unknown';\n\n logger.info(`[ACTIONS_REQ ${id}] Processing actions request from client: ${wsId}`);\n logger.debug(`[ACTIONS_REQ ${id}] Request payload:`, JSON.stringify(payload, null, 2).substring(0, 200));\n\n // SA_RUNTIME is required to fetch actions from UIBlock\n if (!SA_RUNTIME) {\n logger.error(`[ACTIONS_REQ ${id}] SA_RUNTIME missing from request`);\n sendResponse(id, {\n success: false,\n error: 'SA_RUNTIME with threadId and uiBlockId is required'\n }, sendMessage, wsId);\n return;\n }\n\n const uiBlockId = SA_RUNTIME.uiBlockId;\n const threadId = SA_RUNTIME.threadId;\n\n logger.debug(`[ACTIONS_REQ ${id}] SA_RUNTIME validated - threadId: ${threadId}, uiBlockId: ${uiBlockId}`);\n\n // Get UIBlock from ThreadManager\n const threadManager = ThreadManager.getInstance();\n const thread = threadManager.getThread(threadId);\n\n if (!thread) {\n logger.error(`[ACTIONS_REQ ${id}] Thread '${threadId}' not found`);\n sendResponse(id, {\n success: false,\n error: `Thread '${threadId}' not found`\n }, sendMessage, wsId);\n return;\n }\n\n logger.debug(`[ACTIONS_REQ ${id}] Thread found with ${thread.getUIBlocks().length} UIBlocks`);\n logger.debug(`[ACTIONS_REQ ${id}] Retrieving UIBlock: ${uiBlockId}`);\n\n const uiBlock = thread.getUIBlock(uiBlockId);\n if (!uiBlock) {\n logger.error(`[ACTIONS_REQ ${id}] UIBlock '${uiBlockId}' not found in thread '${threadId}'`);\n sendResponse(id, {\n success: false,\n error: `UIBlock '${uiBlockId}' not found in thread '${threadId}'`\n }, sendMessage, wsId);\n return;\n }\n\n logger.info(`[ACTIONS_REQ ${id}] UIBlock retrieved successfully`);\n\n // Create log collector with uiBlockId\n logger.debug(`[ACTIONS_REQ ${id}] Creating UILogCollector for uiBlockId: ${uiBlockId}`);\n const logCollector = new UILogCollector(wsId, sendMessage, uiBlockId);\n logger.info(`[ACTIONS_REQ ${id}] UILogCollector initialized`);\n\n // Extract data from UIBlock\n logger.debug(`[ACTIONS_REQ ${id}] Extracting data from UIBlock`);\n const userQuestion = uiBlock.getUserQuestion();\n const component = uiBlock.getComponentMetadata();\n const componentData = uiBlock.getComponentData();\n\n logger.debug(`[ACTIONS_REQ ${id}] User question: \"${userQuestion?.substring(0, 50)}...\"`);\n logger.debug(`[ACTIONS_REQ ${id}] Component: ${component?.name || 'unknown'} (${component?.type || 'unknown'})`);\n logger.debug(`[ACTIONS_REQ ${id}] Component data available: ${componentData ? 'yes' : 'no'}`);\n\n // Extract conversation context from thread (excluding current UIBlock)\n logger.debug(`[ACTIONS_REQ ${id}] Extracting conversation history (max ${CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS} blocks)`);\n const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, uiBlockId);\n const historyLineCount = conversationHistory.split('\\n').filter(l => l.trim()).length;\n logger.info(`[ACTIONS_REQ ${id}] Conversation history extracted: ${historyLineCount} lines`);\n logger.debug(`[ACTIONS_REQ ${id}] Conversation history preview:\\n${conversationHistory.substring(0, 200)}...`);\n\n logCollector.info(`Generating actions for UIBlock: ${uiBlockId}`);\n logger.info(`[ACTIONS_REQ ${id}] Generating actions for component: ${component?.name || 'unknown'}`);\n\n // Use getOrFetchActions to manage action state\n logger.debug(`[ACTIONS_REQ ${id}] Checking if actions are already cached`);\n const startTime = Date.now();\n\n const actions = await uiBlock.getOrFetchActions(async () => {\n logger.info(`[ACTIONS_REQ ${id}] Actions not cached, generating new actions...`);\n logCollector.info('Generating follow-up questions...');\n\n // Generate next questions using extracted data from UIBlock and conversation history\n logger.info(`[ACTIONS_REQ ${id}] Starting next questions generation with ${llmProviders?.join(', ') || 'default'} providers`);\n const nextQuestions = await generateNextQuestions(\n userQuestion,\n component as any,\n componentData,\n anthropicApiKey,\n groqApiKey,\n geminiApiKey,\n openaiApiKey,\n llmProviders,\n logCollector,\n conversationHistory\n );\n\n logger.info(`[ACTIONS_REQ ${id}] Generated ${nextQuestions.length} questions`);\n logger.debug(`[ACTIONS_REQ ${id}] Questions: ${JSON.stringify(nextQuestions)}`);\n\n // Convert questions to actions format\n logger.debug(`[ACTIONS_REQ ${id}] Converting questions to actions format`);\n const convertedActions = nextQuestions.map((question: string, index: number) => ({\n id: `action_${index}_${Date.now()}`,\n name: question,\n type: 'next_question',\n question\n }));\n\n logger.debug(`[ACTIONS_REQ ${id}] Converted ${convertedActions.length} actions`);\n return convertedActions;\n });\n\n const processingTime = Date.now() - startTime;\n logger.info(`[ACTIONS_REQ ${id}] Actions retrieved in ${processingTime}ms - ${actions.length} actions total`);\n\n if (actions.length > 0) {\n logCollector.info(`Generated ${actions.length} follow-up questions successfully`);\n logger.debug(`[ACTIONS_REQ ${id}] Actions: ${actions.map(a => a.name).join(', ')}`);\n } else {\n logger.warn(`[ACTIONS_REQ ${id}] No actions generated`);\n logCollector.warn('No follow-up questions could be generated');\n }\n\n logger.debug(`[ACTIONS_REQ ${id}] Sending successful response to client`);\n sendResponse(id, {\n success: true,\n data: {\n actions,\n componentName: component?.name,\n componentId: component?.id,\n uiBlockId,\n threadId\n }\n }, sendMessage, wsId);\n\n logger.info(`[ACTIONS_REQ ${id}] ✓ Actions request completed successfully`);\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n logger.error(`[ACTIONS_REQ] Failed to handle actions request: ${errorMessage}`);\n logger.debug(`[ACTIONS_REQ] Error stack trace:`, errorStack);\n\n // Try to send error response\n try {\n const parsedData = data as any;\n if (parsedData?.id && parsedData?.from?.id) {\n const logCollector = parsedData?.payload?.SA_RUNTIME?.uiBlockId\n ? new UILogCollector(parsedData.from.id, sendMessage, parsedData.payload.SA_RUNTIME.uiBlockId)\n : undefined;\n\n logCollector?.error(`Failed to generate actions: ${errorMessage}`);\n }\n } catch (logError) {\n logger.debug('[ACTIONS_REQ] Failed to send error logs to UI:', logError);\n }\n\n sendResponse(null, {\n success: false,\n error: errorMessage\n }, sendMessage);\n\n logger.info('[ACTIONS_REQ] ✗ Actions request completed with errors');\n }\n}\n\n/**\n * Send actions response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'ACTIONS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'runtime',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Sending ${res.success ? 'successful' : 'failed'} response to client`);\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Response payload size: ${JSON.stringify(response).length} bytes`);\n\n if (res.data?.actions) {\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Sending ${res.data.actions.length} actions`);\n }\n\n sendMessage(response);\n}\n","import { Component, ComponentListResponseMessageSchema, ComponentSchema, ComponentsSchema, Message, CollectionRegistry } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\nexport async function handleComponentListResponse(\n data: any,\n storeComponents:(components: Component[])=>void,\n collections?: CollectionRegistry\n ): Promise<void> {\n try {\n const componentListResponse = ComponentListResponseMessageSchema.parse(data);\n const { payload } = componentListResponse;\n\n const componentsList = payload.components;\n\n if(!componentsList){\n logger.error('Components list not found in the response');\n return;\n }\n\n const components = ComponentsSchema.parse(componentsList);\n storeComponents(components);\n\n // Embed display components for semantic search if collection is available\n const embedHandler = collections?.['components']?.['embed'];\n if (embedHandler) {\n try {\n logger.info('Embedding display components for semantic search...');\n const result = await embedHandler({ components });\n if (result.success) {\n logger.info(`Successfully embedded ${result.count} display components`);\n } else {\n logger.warn('Failed to embed components:', result.error);\n }\n } catch (embedError) {\n logger.warn('Failed to embed components:', embedError);\n }\n }\n\n return;\n } catch (error) {\n logger.error('Failed to handle user prompt request:', error);\n }\n }\n\n\n","import { UsersRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { getUserManager } from '../auth/user-storage';\nimport { logger } from '../utils/logger';\nimport { userInfo } from 'os';\n\n/**\n * Handle unified users management request\n * Supports operations: create, update, delete, getAll, getOne\n * Only accepts requests from 'admin' type\n *\n * Strategy: Try database collections first, fall back to file-based storage if failed\n */\nexport async function handleUsersRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n return null; // Collection not found, will fall back to file storage\n }\n return await handler(params);\n };\n\n try {\n const request = UsersRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const numericId = requestData?.id;\n const username = requestData?.username;\n const email = requestData?.email;\n const password = requestData?.password;\n const fullname = requestData?.fullname;\n const role = requestData?.role;\n const userInfo = requestData?.userInfo;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Verify request is from admin\n if (from.type !== 'admin' && operation !== 'getOne' && operation !== 'getAll' && operation !== 'query') {\n sendResponse(id, {\n success: false,\n error: 'Unauthorized: Only admin can manage users'\n }, sendMessage, from.id);\n logger.warn(`Unauthorized user management attempt from: ${from.type}`);\n return;\n }\n\n const userManager = getUserManager();\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, { username, email, password, fullname, role, userInfo }, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, numericId, { username, email, password, fullname, role, userInfo }, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, numericId, username, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, numericId, username, executeCollection, userManager, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, userManager, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle users request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create user operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleCreate(\n id: string,\n userData: {\n username?: string;\n email?: string;\n password?: string;\n fullname?: string;\n role?: string;\n userInfo?: Record<string, unknown>;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { username, email, password, fullname, role, userInfo } = userData;\n\n // Validate input - username is required\n if (!username || username.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Username is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!password || password.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Password is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n // Validate email format if provided\n if (email && email.trim().length > 0) {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n sendResponse(id, {\n success: false,\n error: 'Invalid email format'\n }, sendMessage, clientId);\n return;\n }\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('users', 'create', {\n username,\n email: email || undefined,\n password,\n fullname: fullname || undefined,\n role: role || undefined,\n userInfo: userInfo || undefined\n });\n\n if (result && result.success) {\n logger.info(`[DB] User created successfully: ${username}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n username: result.data?.username,\n email: result.data?.email,\n fullname: result.data?.fullname,\n role: result.data?.role,\n message: `User '${username}' created successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to create user, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n try {\n // Check if user already exists\n if (userManager.userExists(username)) {\n sendResponse(id, {\n success: false,\n error: `User '${username}' already exists`\n }, sendMessage, clientId);\n return;\n }\n\n // Check if email already exists (if provided)\n if (email && userManager.getUserByEmail(email)) {\n sendResponse(id, {\n success: false,\n error: `User with email '${email}' already exists`\n }, sendMessage, clientId);\n return;\n }\n\n // Create user object\n const newUserData: any = {\n username,\n password,\n };\n\n if (email && email.trim().length > 0) {\n newUserData.email = email.trim();\n }\n\n if (fullname && fullname.trim().length > 0) {\n newUserData.fullname = fullname.trim();\n }\n\n if (role && role.trim().length > 0) {\n newUserData.role = role.trim();\n }\n\n // Create user\n const newUser = userManager.createUser(newUserData);\n\n logger.info(`[FILE] User '${username}' created successfully`);\n sendResponse(id, {\n success: true,\n data: {\n username: newUser.username,\n email: newUser.email,\n fullname: newUser.fullname,\n role: newUser.role,\n message: `User '${username}' created successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create user'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update user operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleUpdate(\n id: string,\n numericId: number | undefined,\n userData: {\n username?: string;\n email?: string;\n password?: string;\n fullname?: string;\n role?: string;\n userInfo?: Record<string, unknown>;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { username, email, password, fullname, role, userInfo } = userData;\n\n // For DB update, we need numeric ID; for file storage, we need username\n if (!numericId && !username) {\n sendResponse(id, {\n success: false,\n error: 'User ID or username is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first (if numeric ID is provided)\n if (numericId) {\n try {\n const result = await executeCollection('users', 'update', {\n id: numericId,\n username,\n email,\n password,\n fullname,\n role,\n userInfo\n });\n\n if (result && result.success) {\n logger.info(`[DB] User updated successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n username: result.data?.username,\n email: result.data?.email,\n fullname: result.data?.fullname,\n role: result.data?.role,\n message: `User updated successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to update user, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n }\n\n // Fallback to file-based storage (requires username)\n if (!username || username.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Username is required for file-based storage update'\n }, sendMessage, clientId);\n return;\n }\n\n // Check if user exists\n if (!userManager.userExists(username)) {\n sendResponse(id, {\n success: false,\n error: `User '${username}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n // Build update object\n const updates: any = {};\n\n // Validate and add email if provided\n if (email !== undefined) {\n if (email.trim().length > 0) {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n sendResponse(id, {\n success: false,\n error: 'Invalid email format'\n }, sendMessage, clientId);\n return;\n }\n\n // Check if email is already used by another user\n const existingUser = userManager.getUserByEmail(email);\n if (existingUser && existingUser.username !== username) {\n sendResponse(id, {\n success: false,\n error: `Email '${email}' is already used by another user`\n }, sendMessage, clientId);\n return;\n }\n\n updates.email = email.trim();\n } else {\n updates.email = undefined;\n }\n }\n\n if (password !== undefined && password.trim().length > 0) {\n updates.password = password.trim();\n }\n\n if (fullname !== undefined) {\n updates.fullname = fullname.trim().length > 0 ? fullname.trim() : undefined;\n }\n\n if (role !== undefined) {\n updates.role = role.trim().length > 0 ? role.trim() : undefined;\n }\n\n if (Object.keys(updates).length === 0) {\n sendResponse(id, {\n success: false,\n error: 'No fields to update. Please provide at least one field to update.'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const updatedUser = userManager.updateUser(username, updates);\n\n logger.info(`[FILE] User '${username}' updated successfully`);\n sendResponse(id, {\n success: true,\n data: {\n username: updatedUser.username,\n email: updatedUser.email,\n fullname: updatedUser.fullname,\n role: updatedUser.role,\n message: `User '${username}' updated successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update user'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete user operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleDelete(\n id: string,\n numericId: number | undefined,\n username: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // For DB delete, we need numeric ID; for file storage, we need username\n if (!numericId && !username) {\n sendResponse(id, {\n success: false,\n error: 'User ID or username is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first (if numeric ID is provided)\n if (numericId) {\n try {\n const result = await executeCollection('users', 'delete', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] User deleted successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n username: result.data?.username,\n message: `User deleted successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to delete user, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n }\n\n // Fallback to file-based storage (requires username)\n if (!username || username.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Username is required for file-based storage delete'\n }, sendMessage, clientId);\n return;\n }\n\n // Check if user exists\n if (!userManager.userExists(username)) {\n sendResponse(id, {\n success: false,\n error: `User '${username}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n const deleted = userManager.deleteUser(username);\n\n if (!deleted) {\n sendResponse(id, {\n success: false,\n error: `Failed to delete user '${username}'`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] User '${username}' deleted successfully`);\n sendResponse(id, {\n success: true,\n data: {\n username: username,\n message: `User '${username}' deleted successfully (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all users operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection first\n try {\n const result = await executeCollection('users', 'getAll', {});\n\n if (result && result.success) {\n // Remove sensitive information like passwords\n const sanitizedUsers = result.data.map((user: any) => ({\n id: user.id,\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n userInfo : user.userInfo,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt\n }));\n\n logger.info(`[DB] Retrieved ${result.count} users`);\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: result.count,\n message: `Retrieved ${result.count} users (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get all users, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n const users = userManager.getAllUsers();\n\n // Remove sensitive information like passwords\n const sanitizedUsers = users.map((user: any) => ({\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n wsIds: user.wsIds || []\n }));\n\n logger.info(`[FILE] Retrieved ${sanitizedUsers.length} users`);\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: sanitizedUsers.length,\n message: `Retrieved ${sanitizedUsers.length} users (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one user operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetOne(\n id: string,\n numericId: number | undefined,\n username: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // For DB getOne, we need numeric ID; for file storage, we need username\n if (!numericId && !username) {\n sendResponse(id, {\n success: false,\n error: 'User ID or username is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first (if numeric ID is provided)\n if (numericId) {\n try {\n const result = await executeCollection('users', 'getOne', { id: numericId });\n\n if (result && result.success) {\n // Remove sensitive information\n const sanitizedUser = {\n id: result.data?.id,\n username: result.data?.username,\n email: result.data?.email,\n fullname: result.data?.fullname,\n role: result.data?.role,\n userInfo: result.data?.userInfo,\n createdAt: result.data?.createdAt,\n updatedAt: result.data?.updatedAt\n };\n\n logger.info(`[DB] Retrieved user ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n user: sanitizedUser,\n message: `Retrieved user (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get user, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n }\n\n // Fallback to file-based storage (requires username)\n if (!username || username.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Username is required for file-based storage lookup'\n }, sendMessage, clientId);\n return;\n }\n\n // Check if user exists\n if (!userManager.userExists(username)) {\n sendResponse(id, {\n success: false,\n error: `User '${username}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n const user = userManager.getUser(username);\n\n // Remove sensitive information\n const sanitizedUser = {\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n wsIds: user.wsIds || []\n };\n\n logger.info(`[FILE] Retrieved user: ${username}`);\n sendResponse(id, {\n success: true,\n data: {\n user: sanitizedUser,\n message: `Retrieved user '${username}' (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle query users operation with filters\n * Database only - no file fallback for query operations\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection\n try {\n const result = await executeCollection('users', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n if (result && result.success) {\n // Remove sensitive information like passwords\n const sanitizedUsers = result.data.map((user: any) => ({\n id: user.id,\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n userInfo: user.userInfo,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt\n }));\n\n logger.info(`[DB] Query returned ${result.count} users`);\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: result.count,\n message: `Query returned ${result.count} users (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to query users: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage (get all and return - no filter support)\n const users = userManager.getAllUsers();\n\n // Remove sensitive information like passwords\n const sanitizedUsers = users.map((user: any) => ({\n username: user.username,\n email: user.email,\n fullname: user.fullname,\n role: user.role,\n userInfo : user.userInfo,\n wsIds: user.wsIds || []\n }));\n\n logger.info(`[FILE] Retrieved ${sanitizedUsers.length} users (all - no query filter)`);\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: sanitizedUsers.length,\n message: `Retrieved ${sanitizedUsers.length} users (File - no query filter)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Send users response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'USERS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { DashboardManager } from './dashboard-manager';\nimport { logger } from '../utils/logger';\n\nlet dashboardManager: DashboardManager | null = null;\n\n/**\n * Set the dashboard manager instance\n * @param manager - DashboardManager instance to use\n */\nexport function setDashboardManager(manager: DashboardManager): void {\n dashboardManager = manager;\n logger.info('DashboardManager instance set');\n}\n\n/**\n * Get the dashboard manager instance\n * @throws Error if dashboard manager is not initialized\n * @returns DashboardManager instance\n */\nexport function getDashboardManager(): DashboardManager {\n if (!dashboardManager) {\n throw new Error('DashboardManager not initialized. Call setDashboardManager first.');\n }\n return dashboardManager;\n}\n","import { DashboardsRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { getDashboardManager } from '../dashboards/dashboard-storage';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified dashboards management request\n * Supports operations: create, update, delete, getAll, getOne\n * Only accepts requests from 'admin' type\n *\n * Strategy: Try database collections first, fall back to file-based storage if failed\n */\nexport async function handleDashboardsRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n return null; // Collection not found, will fall back to file storage\n }\n return await handler(params);\n };\n\n try {\n const request = DashboardsRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const dashboardId = requestData?.dashboardId;\n const dashboard = requestData?.dashboard;\n const projectId = requestData?.projectId;\n const name = requestData?.name;\n const description = requestData?.description;\n const published = requestData?.published;\n const createdBy = requestData?.createdBy;\n const updatedBy = requestData?.updatedBy;\n const allowedUsers = requestData?.allowedUsers as number[] | undefined;\n const numericId = requestData?.id;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Verify request is from admin\n if (from.type !== 'admin') {\n sendResponse(id, {\n success: false,\n error: 'Unauthorized: Only admin can manage dashboards'\n }, sendMessage, from.id);\n logger.warn(`Unauthorized dashboard management attempt from: ${from.type}`);\n return;\n }\n\n const dashboardManager = getDashboardManager();\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, dashboardId, dashboard, projectId, name, description, published, createdBy, allowedUsers, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, numericId, dashboardId, dashboard, name, description, published, updatedBy, allowedUsers, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, numericId, dashboardId, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, numericId, dashboardId, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, dashboardManager, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle dashboards request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create dashboard operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleCreate(\n id: string,\n dashboardId: string | undefined,\n dashboard: any,\n projectId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n published: boolean | undefined,\n createdBy: number | undefined,\n allowedUsers: number[] | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!dashboardId || dashboardId.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard ID is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!projectId) {\n sendResponse(id, {\n success: false,\n error: 'Project ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'create', {\n dashboardId,\n projectId,\n name: name || '',\n description,\n dashboard,\n published,\n createdBy,\n allowedUsers\n });\n\n if (result && result.success) {\n logger.info(`[DB] Dashboard created successfully, ID: ${result.data?.id}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n dashboardId: result.data?.dashboardId,\n dashboard: result.data?.dashboard || dashboard,\n message: `Dashboard created successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to create dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n try {\n if (!dashboard) {\n dashboard = {};\n }\n\n const createdDashboard = dashboardManager.createDashboard(dashboardId, dashboard);\n\n logger.info(`[FILE] Dashboard '${dashboardId}' created successfully`);\n sendResponse(id, {\n success: true,\n data: {\n dashboardId,\n dashboard: createdDashboard,\n message: `Dashboard '${dashboardId}' created successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create dashboard'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update dashboard operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleUpdate(\n id: string,\n numericId: number | undefined,\n dashboardId: string | undefined,\n dashboard: any,\n name: string | undefined,\n description: string | undefined,\n published: boolean | undefined,\n updatedBy: number | undefined,\n allowedUsers: number[] | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'update', {\n id: numericId,\n name,\n description,\n dashboard,\n published,\n updatedBy,\n allowedUsers\n });\n\n if (result && result.success) {\n logger.info(`[DB] Dashboard updated successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: result.data?.dashboardId,\n dashboard: result.data?.dashboard || dashboard,\n message: `Dashboard updated successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to update dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use dashboardId if exists, otherwise stringify numericId\n const fileStorageId = dashboardId || String(numericId);\n try {\n const updatedDashboard = dashboardManager.updateDashboard(fileStorageId, dashboard);\n\n if (!updatedDashboard) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Dashboard '${fileStorageId}' updated successfully`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: fileStorageId,\n dashboard: updatedDashboard,\n message: `Dashboard '${fileStorageId}' updated successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update dashboard'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete dashboard operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleDelete(\n id: string,\n numericId: number | undefined,\n dashboardId: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'delete', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] Dashboard deleted successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n message: `Dashboard deleted successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to delete dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use dashboardId if exists, otherwise stringify numericId\n const fileStorageId = dashboardId || String(numericId);\n const deleted = dashboardManager.deleteDashboard(fileStorageId);\n\n if (!deleted) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Dashboard '${fileStorageId}' deleted successfully`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: fileStorageId,\n message: `Dashboard '${fileStorageId}' deleted successfully (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all dashboards operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'getAll', {});\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} dashboards`);\n sendResponse(id, {\n success: true,\n data: {\n dashboards: result.data,\n count: result.count,\n message: `Retrieved ${result.count} dashboards (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get all dashboards, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n const dashboards = dashboardManager.getAllDashboards();\n\n logger.info(`[FILE] Retrieved ${dashboards.length} dashboards`);\n sendResponse(id, {\n success: true,\n data: {\n dashboards,\n count: dashboards.length,\n message: `Retrieved ${dashboards.length} dashboards (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one dashboard operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetOne(\n id: string,\n numericId: number | undefined,\n dashboardId: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('dashboards', 'getOne', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved dashboard ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: result.data?.dashboardId,\n dashboard: result.data?.dashboard || result.data,\n message: `Retrieved dashboard (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use dashboardId if exists, otherwise stringify numericId\n const fileStorageId = dashboardId || String(numericId);\n const dashboard = dashboardManager.getDashboard(fileStorageId);\n\n if (!dashboard) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Retrieved dashboard: ${fileStorageId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n dashboardId: fileStorageId,\n dashboard,\n message: `Retrieved dashboard '${fileStorageId}' (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle query dashboards operation with filters\n * Database only - no file fallback for query operations\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection\n try {\n const result = await executeCollection('dashboards', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n if (result && result.success) {\n logger.info(`[DB] Query returned ${result.count} dashboards`);\n sendResponse(id, {\n success: true,\n data: {\n dashboards: result.data,\n count: result.count,\n message: `Query returned ${result.count} dashboards (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to query dashboards: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage (get all and return)\n const dashboards = dashboardManager.getAllDashboards();\n\n logger.info(`[FILE] Retrieved ${dashboards.length} dashboards (all - no query filter)`);\n sendResponse(id, {\n success: true,\n data: {\n dashboards,\n count: dashboards.length,\n message: `Retrieved ${dashboards.length} dashboards (File - no query filter)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Send dashboards response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'DASHBOARDS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { ReportManager } from './report-manager';\n\n/**\n * Global report manager instance\n */\nlet reportManager: ReportManager | null = null;\n\n/**\n * Get the global report manager instance\n * @returns ReportManager instance\n * @throws Error if report manager is not initialized\n */\nexport function getReportManager(): ReportManager {\n if (!reportManager) {\n throw new Error('Report manager not initialized. Call setReportManager first.');\n }\n return reportManager;\n}\n\n/**\n * Set the global report manager instance\n * @param manager - ReportManager instance to set\n */\nexport function setReportManager(manager: ReportManager): void {\n reportManager = manager;\n}\n","import { ReportsRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { getReportManager } from '../reports/report-storage';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified reports management request\n * Supports operations: create, update, delete, getAll, getOne, query\n * Only accepts requests from 'admin' type\n *\n * Strategy: Try database collections first, fall back to file-based storage if failed\n */\nexport async function handleReportsRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n return null; // Collection not found, will fall back to file storage\n }\n return await handler(params);\n };\n\n try {\n const request = ReportsRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const reportId = requestData?.reportId;\n const report = requestData?.report;\n const projectId = requestData?.projectId;\n const name = requestData?.name;\n const description = requestData?.description;\n const published = requestData?.published;\n const createdBy = requestData?.createdBy;\n const updatedBy = requestData?.updatedBy;\n const numericId = requestData?.id;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Verify request is from admin\n if (from.type !== 'admin') {\n sendResponse(id, {\n success: false,\n error: 'Unauthorized: Only admin can manage reports'\n }, sendMessage, from.id);\n logger.warn(`Unauthorized report management attempt from: ${from.type}`);\n return;\n }\n\n const reportManager = getReportManager();\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, reportId, report, projectId, name, description, published, createdBy, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, numericId, reportId, report, name, description, published, updatedBy, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, numericId, reportId, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, numericId, reportId, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, reportManager, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle reports request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create report operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleCreate(\n id: string,\n reportId: string | undefined,\n report: any,\n projectId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n published: boolean | undefined,\n createdBy: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!reportId || reportId.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Report ID is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!projectId) {\n sendResponse(id, {\n success: false,\n error: 'Project ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'create', {\n reportId,\n projectId,\n name: name || '',\n description,\n report,\n published,\n createdBy\n });\n\n if (result && result.success) {\n logger.info(`[DB] Report created successfully, ID: ${result.data?.id}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n reportId: result.data?.reportId,\n report: result.data?.report || report,\n message: `Report created successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to create report, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n try {\n if (!report) {\n report = {};\n }\n\n const createdReport = reportManager.createReport(reportId, report);\n\n logger.info(`[FILE] Report '${reportId}' created successfully`);\n sendResponse(id, {\n success: true,\n data: {\n reportId,\n report: createdReport,\n message: `Report '${reportId}' created successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create report'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update report operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleUpdate(\n id: string,\n numericId: number | undefined,\n reportId: string | undefined,\n report: any,\n name: string | undefined,\n description: string | undefined,\n published: boolean | undefined,\n updatedBy: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Report ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'update', {\n id: numericId,\n name,\n description,\n report,\n published,\n updatedBy\n });\n\n if (result && result.success) {\n logger.info(`[DB] Report updated successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: result.data?.reportId,\n report: result.data?.report || report,\n message: `Report updated successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to update report, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use reportId if exists, otherwise stringify numericId\n const fileStorageId = reportId || String(numericId);\n try {\n const updatedReport = reportManager.updateReport(fileStorageId, report);\n\n if (!updatedReport) {\n sendResponse(id, {\n success: false,\n error: `Report '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Report '${fileStorageId}' updated successfully`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: fileStorageId,\n report: updatedReport,\n message: `Report '${fileStorageId}' updated successfully (File)`\n }\n }, sendMessage, clientId);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update report'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete report operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleDelete(\n id: string,\n numericId: number | undefined,\n reportId: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Report ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'delete', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] Report deleted successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n message: `Report deleted successfully (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to delete report, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use reportId if exists, otherwise stringify numericId\n const fileStorageId = reportId || String(numericId);\n const deleted = reportManager.deleteReport(fileStorageId);\n\n if (!deleted) {\n sendResponse(id, {\n success: false,\n error: `Report '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Report '${fileStorageId}' deleted successfully`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: fileStorageId,\n message: `Report '${fileStorageId}' deleted successfully (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all reports operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'getAll', {});\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} reports`);\n sendResponse(id, {\n success: true,\n data: {\n reports: result.data,\n count: result.count,\n message: `Retrieved ${result.count} reports (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get all reports, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage\n const reports = reportManager.getAllReports();\n\n logger.info(`[FILE] Retrieved ${reports.length} reports`);\n sendResponse(id, {\n success: true,\n data: {\n reports,\n count: reports.length,\n message: `Retrieved ${reports.length} reports (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one report operation\n * Tries database collection first, falls back to file storage if failed\n */\nasync function handleGetOne(\n id: string,\n numericId: number | undefined,\n reportId: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'Report ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n // Try database collection first\n try {\n const result = await executeCollection('reports', 'getOne', { id: numericId });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved report ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: result.data?.reportId,\n report: result.data?.report || result.data,\n message: `Retrieved report (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to get report, falling back to file storage: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage - use reportId if exists, otherwise stringify numericId\n const fileStorageId = reportId || String(numericId);\n const report = reportManager.getReport(fileStorageId);\n\n if (!report) {\n sendResponse(id, {\n success: false,\n error: `Report '${fileStorageId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`[FILE] Retrieved report: ${fileStorageId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n reportId: fileStorageId,\n report,\n message: `Retrieved report '${fileStorageId}' (File)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle query reports operation with filters\n * Database only - no file fallback for query operations\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Try database collection\n try {\n const result = await executeCollection('reports', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n if (result && result.success) {\n logger.info(`[DB] Query returned ${result.count} reports`);\n sendResponse(id, {\n success: true,\n data: {\n reports: result.data,\n count: result.count,\n message: `Query returned ${result.count} reports (DB)`\n }\n }, sendMessage, clientId);\n return;\n }\n } catch (dbError) {\n logger.warn(`[DB] Failed to query reports: ${dbError instanceof Error ? dbError.message : 'Unknown error'}`);\n }\n\n // Fallback to file-based storage (get all and return)\n const reports = reportManager.getAllReports();\n\n logger.info(`[FILE] Retrieved ${reports.length} reports (all - no query filter)`);\n sendResponse(id, {\n success: true,\n data: {\n reports,\n count: reports.length,\n message: `Retrieved ${reports.length} reports (File - no query filter)`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Send reports response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'REPORTS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { UIsRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified UIs management request\n * Supports operations: create, update, delete, getAll, getOne, query\n * Only accepts requests from 'admin' type\n *\n * Uses database collections only (no file-based fallback)\n */\nexport async function handleUIsRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n throw new Error(`Collection handler not found: ${collection}.${op}`);\n }\n return await handler(params);\n };\n\n try {\n const request = UIsRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const uiId = requestData?.uiId;\n const ui = requestData?.ui;\n const projectId = requestData?.projectId;\n const name = requestData?.name;\n const description = requestData?.description;\n const createdBy = requestData?.createdBy;\n const updatedBy = requestData?.updatedBy;\n const numericId = requestData?.id;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Verify request is from admin\n if (from.type !== 'admin') {\n sendResponse(id, {\n success: false,\n error: 'Unauthorized: Only admin can manage UIs'\n }, sendMessage, from.id);\n logger.warn(`Unauthorized UI management attempt from: ${from.type}`);\n return;\n }\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, uiId, ui, projectId, name, description, createdBy, executeCollection, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, numericId, ui, name, description, updatedBy, executeCollection, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, numericId, executeCollection, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, numericId, executeCollection, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle UIs request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create UI operation\n */\nasync function handleCreate(\n id: string,\n uiId: string | undefined,\n ui: any,\n projectId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n createdBy: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!uiId || uiId.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'UI ID is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!projectId || projectId.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Project ID is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('uis', 'create', {\n uiId,\n projectId,\n name: name || uiId,\n description,\n ui,\n createdBy\n });\n\n if (result && result.success) {\n logger.info(`UI created successfully, ID: ${result.data?.id}`);\n sendResponse(id, {\n success: true,\n data: {\n id: result.data?.id,\n uiId: result.data?.uiId || uiId,\n ui: result.data?.ui || ui,\n message: `UI created successfully`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to create UI'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create UI'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update UI operation\n */\nasync function handleUpdate(\n id: string,\n numericId: number | undefined,\n ui: any,\n name: string | undefined,\n description: string | undefined,\n updatedBy: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'UI ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('uis', 'update', {\n id: numericId,\n name,\n description,\n ui,\n updatedBy\n });\n\n if (result && result.success) {\n logger.info(`UI updated successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n uiId: result.data?.uiId,\n ui: result.data?.ui || ui,\n message: `UI updated successfully`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to update UI'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update UI'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete UI operation\n */\nasync function handleDelete(\n id: string,\n numericId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'UI ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('uis', 'delete', { id: numericId });\n\n if (result && result.success) {\n logger.info(`UI deleted successfully, ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n message: `UI deleted successfully`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to delete UI'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to delete UI'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all UIs operation\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('uis', 'getAll', {});\n\n if (result && result.success) {\n logger.info(`Retrieved ${result.count} UIs`);\n sendResponse(id, {\n success: true,\n data: {\n uis: result.data,\n count: result.count,\n message: `Retrieved ${result.count} UIs`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to get UIs'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to get UIs'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get one UI operation\n */\nasync function handleGetOne(\n id: string,\n numericId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!numericId) {\n sendResponse(id, {\n success: false,\n error: 'UI ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('uis', 'getOne', { id: numericId });\n\n if (result && result.success) {\n logger.info(`Retrieved UI ID: ${numericId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: numericId,\n uiId: result.data?.uiId,\n ui: result.data?.ui || result.data,\n message: `Retrieved UI`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: `UI not found`\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to get UI'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle query UIs operation with filters\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('uis', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n if (result && result.success) {\n logger.info(`Query returned ${result.count} UIs`);\n sendResponse(id, {\n success: true,\n data: {\n uis: result.data,\n count: result.count,\n message: `Query returned ${result.count} UIs`\n }\n }, sendMessage, clientId);\n } else {\n sendResponse(id, {\n success: false,\n error: 'Failed to query UIs'\n }, sendMessage, clientId);\n }\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to query UIs'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Send UIs response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'UIS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { BookmarksRequestMessageSchema, Message, CollectionRegistry, DBUIBlock } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified bookmarks management request\n * Supports operations: create, update, delete, getAll, getOne\n * Routes requests to backend collections\n */\nexport async function handleBookmarksRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n throw new Error(`Collection operation ${collection}.${op} not found`);\n }\n return await handler(params);\n };\n try {\n const request = BookmarksRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n const bookmarkId = requestData?.id;\n const userId = requestData?.userId;\n const threadId = requestData?.threadId;\n const name = requestData?.name;\n const description = requestData?.description;\n const uiblock = requestData?.uiblock;\n // Query operation fields\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const sort = requestData?.sort;\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, userId, threadId, name, description, uiblock, executeCollection, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, bookmarkId, threadId, name, description, uiblock, executeCollection, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, bookmarkId, executeCollection, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, executeCollection, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, bookmarkId, executeCollection, sendMessage, from.id);\n break;\n\n case 'query':\n await handleQuery(id, filters, limit, sort, executeCollection, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle bookmarks request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create bookmark operation\n */\nasync function handleCreate(\n id: string,\n userId: number | undefined,\n threadId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n uiblock: DBUIBlock | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!userId) {\n sendResponse(id, {\n success: false,\n error: 'userId is required'\n }, sendMessage, clientId);\n return;\n }\n\n if (!uiblock) {\n sendResponse(id, {\n success: false,\n error: 'UIBlock data is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('bookmarks', 'create', { userId, threadId, name, description, uiblock });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n message: 'Bookmark created successfully'\n }, sendMessage, clientId);\n\n logger.info(`Bookmark created: ID ${result.data.id}`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create bookmark'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update bookmark operation\n */\nasync function handleUpdate(\n id: string,\n bookmarkId: number | undefined,\n threadId: string | undefined,\n name: string | undefined,\n description: string | undefined,\n uiblock: DBUIBlock | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!bookmarkId) {\n sendResponse(id, {\n success: false,\n error: 'Bookmark ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('bookmarks', 'update', { id: bookmarkId, threadId, name, description, uiblock });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n message: 'Bookmark updated successfully'\n }, sendMessage, clientId);\n\n logger.info(`Bookmark updated: ID ${bookmarkId}`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update bookmark'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete bookmark operation\n */\nasync function handleDelete(\n id: string,\n bookmarkId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!bookmarkId) {\n sendResponse(id, {\n success: false,\n error: 'Bookmark ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('bookmarks', 'delete', { id: bookmarkId });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n message: 'Bookmark deleted successfully'\n }, sendMessage, clientId);\n\n logger.info(`Bookmark deleted: ID ${bookmarkId}`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to delete bookmark'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all bookmarks operation\n */\nasync function handleGetAll(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('bookmarks', 'getAll', {});\n\n sendResponse(id, {\n success: true,\n data: result.data,\n count: result.count,\n message: `Retrieved ${result.count} bookmarks`\n }, sendMessage, clientId);\n\n logger.info(`Retrieved all bookmarks (count: ${result.count})`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to get bookmarks'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get one bookmark operation\n */\nasync function handleGetOne(\n id: string,\n bookmarkId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\n if (!bookmarkId) {\n sendResponse(id, {\n success: false,\n error: 'Bookmark ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('bookmarks', 'getOne', { id: bookmarkId });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n message: `Retrieved bookmark ID ${bookmarkId}`\n }, sendMessage, clientId);\n\n logger.info(`Retrieved bookmark: ID ${bookmarkId}`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to get bookmark'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle query bookmarks operation with filters\n */\nasync function handleQuery(\n id: string,\n filters: any,\n limit: number | undefined,\n sort: string | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('bookmarks', 'query', {\n filters: filters || {},\n limit,\n sort\n });\n\n sendResponse(id, {\n success: true,\n data: result.data,\n count: result.count,\n message: `Query returned ${result.count} bookmarks`\n }, sendMessage, clientId);\n\n logger.info(`Query returned ${result.count} bookmarks`);\n } catch (error) {\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to query bookmarks'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Send bookmarks response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any; count?: number; message?: string },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'BOOKMARKS_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'user',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { KbNodesRequestMessageSchema, Message, CollectionRegistry } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified KB Nodes (Knowledge Base) management request\n * Supports operations: create, update, delete, getAll, getOne, search, getByCategory, getByUser, getCategories, getTags\n *\n * Strategy: Uses database collections for all operations\n */\nexport async function handleKbNodesRequest(\n data: any,\n collections: CollectionRegistry,\n sendMessage: (message: Message) => void\n): Promise<void> {\n // Helper function to execute collection operations\n const executeCollection = async (collection: string, op: string, params: any): Promise<any> => {\n const handler = collections[collection]?.[op];\n if (!handler) {\n throw new Error(`Collection '${collection}' or operation '${op}' not found`);\n }\n return await handler(params);\n };\n\n try {\n const request = KbNodesRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\n\n // Extract fields from request data\n const nodeId = requestData?.id;\n const title = requestData?.title;\n const content = requestData?.content;\n const category = requestData?.category;\n const tags = requestData?.tags;\n const createdBy = requestData?.createdBy;\n const updatedBy = requestData?.updatedBy;\n const userId = requestData?.userId;\n const query = requestData?.query;\n const filters = requestData?.filters;\n const limit = requestData?.limit;\n const offset = requestData?.offset;\n\n // Route to appropriate operation handler\n switch (operation) {\n case 'create':\n await handleCreate(id, { title, content, category, tags, createdBy }, executeCollection, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, nodeId, { title, content, category, tags, updatedBy }, executeCollection, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, nodeId, executeCollection, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, limit, offset, executeCollection, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, nodeId, executeCollection, sendMessage, from.id);\n break;\n\n case 'search':\n await handleSearch(id, { query, category, tags, createdBy, limit, offset }, executeCollection, sendMessage, from.id);\n break;\n\n case 'getByCategory':\n await handleGetByCategory(id, category, limit, offset, executeCollection, sendMessage, from.id);\n break;\n\n case 'getByUser':\n await handleGetByUser(id, userId, limit, offset, executeCollection, sendMessage, from.id);\n break;\n\n case 'getCategories':\n await handleGetCategories(id, executeCollection, sendMessage, from.id);\n break;\n\n case 'getTags':\n await handleGetTags(id, executeCollection, sendMessage, from.id);\n break;\n\n default:\n sendResponse(id, {\n success: false,\n error: `Unknown operation: ${operation}`\n }, sendMessage, from.id);\n }\n\n } catch (error) {\n logger.error('Failed to handle KB nodes request:', error);\n sendResponse(null, {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred'\n }, sendMessage);\n }\n}\n\n/**\n * Handle create KB node operation\n */\nasync function handleCreate(\n id: string,\n nodeData: {\n title?: string;\n content?: string;\n category?: string;\n tags?: string[];\n createdBy?: number;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { title, content, category, tags, createdBy } = nodeData;\n\n // Validate required fields\n if (!title || title.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Title is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!content || content.trim().length === 0) {\n sendResponse(id, {\n success: false,\n error: 'Content is required and cannot be empty'\n }, sendMessage, clientId);\n return;\n }\n\n if (!createdBy) {\n sendResponse(id, {\n success: false,\n error: 'createdBy (user ID) is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'create', {\n title,\n content,\n category: category || undefined,\n tags: tags || undefined,\n createdBy\n });\n\n if (result && result.success) {\n logger.info(`[DB] KB node created successfully: ${title}`);\n sendResponse(id, {\n success: true,\n data: {\n ...result.data,\n message: `Knowledge node '${title}' created successfully`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to create knowledge node'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to create KB node:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to create knowledge node'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle update KB node operation\n */\nasync function handleUpdate(\n id: string,\n nodeId: number | undefined,\n nodeData: {\n title?: string;\n content?: string;\n category?: string;\n tags?: string[];\n updatedBy?: number;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { title, content, category, tags, updatedBy } = nodeData;\n\n if (!nodeId) {\n sendResponse(id, {\n success: false,\n error: 'Knowledge node ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n if (!updatedBy) {\n sendResponse(id, {\n success: false,\n error: 'updatedBy (user ID) is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'update', {\n id: nodeId,\n title,\n content,\n category,\n tags,\n updatedBy\n });\n\n if (result && result.success) {\n logger.info(`[DB] KB node updated successfully, ID: ${nodeId}`);\n sendResponse(id, {\n success: true,\n data: {\n ...result.data,\n message: `Knowledge node updated successfully`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to update knowledge node'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to update KB node:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to update knowledge node'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle delete KB node operation\n */\nasync function handleDelete(\n id: string,\n nodeId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n if (!nodeId) {\n sendResponse(id, {\n success: false,\n error: 'Knowledge node ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'delete', { id: nodeId });\n\n if (result && result.success) {\n logger.info(`[DB] KB node deleted successfully, ID: ${nodeId}`);\n sendResponse(id, {\n success: true,\n data: {\n id: nodeId,\n ...result.data,\n message: `Knowledge node deleted successfully`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to delete knowledge node'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to delete KB node:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to delete knowledge node'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all KB nodes operation\n */\nasync function handleGetAll(\n id: string,\n limit: number | undefined,\n offset: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('kbNodes', 'getAll', {\n limit: limit || 100,\n offset: offset || 0\n });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} KB nodes`);\n sendResponse(id, {\n success: true,\n data: {\n nodes: result.data,\n count: result.count,\n message: `Retrieved ${result.count} knowledge nodes`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve knowledge nodes'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get all KB nodes:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve knowledge nodes'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get one KB node operation\n */\nasync function handleGetOne(\n id: string,\n nodeId: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n if (!nodeId) {\n sendResponse(id, {\n success: false,\n error: 'Knowledge node ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'getOne', { id: nodeId });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved KB node ID: ${nodeId}`);\n sendResponse(id, {\n success: true,\n data: {\n node: result.data,\n message: `Retrieved knowledge node`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve knowledge node'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get KB node:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve knowledge node'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle search KB nodes operation\n */\nasync function handleSearch(\n id: string,\n searchParams: {\n query?: string;\n category?: string;\n tags?: string[];\n createdBy?: number;\n limit?: number;\n offset?: number;\n },\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { query, category, tags, createdBy, limit, offset } = searchParams;\n\n try {\n const result = await executeCollection('kbNodes', 'search', {\n query,\n category,\n tags,\n createdBy,\n limit: limit || 50,\n offset: offset || 0\n });\n\n if (result && result.success) {\n logger.info(`[DB] Search returned ${result.count} KB nodes`);\n sendResponse(id, {\n success: true,\n data: {\n nodes: result.data,\n count: result.count,\n message: `Search returned ${result.count} knowledge nodes`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to search knowledge nodes'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to search KB nodes:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to search knowledge nodes'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get KB nodes by category operation\n */\nasync function handleGetByCategory(\n id: string,\n category: string | undefined,\n limit: number | undefined,\n offset: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n if (!category) {\n sendResponse(id, {\n success: false,\n error: 'Category is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'getByCategory', {\n category,\n limit: limit || 50,\n offset: offset || 0\n });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} KB nodes for category: ${category}`);\n sendResponse(id, {\n success: true,\n data: {\n nodes: result.data,\n count: result.count,\n category,\n message: `Retrieved ${result.count} knowledge nodes for category '${category}'`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve knowledge nodes by category'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get KB nodes by category:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve knowledge nodes by category'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get KB nodes by user operation\n */\nasync function handleGetByUser(\n id: string,\n userId: number | undefined,\n limit: number | undefined,\n offset: number | undefined,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n if (!userId) {\n sendResponse(id, {\n success: false,\n error: 'User ID is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const result = await executeCollection('kbNodes', 'getByUser', {\n userId,\n limit: limit || 50,\n offset: offset || 0\n });\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} KB nodes for user: ${userId}`);\n sendResponse(id, {\n success: true,\n data: {\n nodes: result.data,\n count: result.count,\n userId,\n message: `Retrieved ${result.count} knowledge nodes for user ${userId}`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve knowledge nodes by user'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get KB nodes by user:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve knowledge nodes by user'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all categories operation\n */\nasync function handleGetCategories(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('kbNodes', 'getCategories', {});\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} categories`);\n sendResponse(id, {\n success: true,\n data: {\n categories: result.data,\n count: result.count,\n message: `Retrieved ${result.count} categories`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve categories'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get categories:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve categories'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Handle get all tags operation\n */\nasync function handleGetTags(\n id: string,\n executeCollection: (collection: string, op: string, params: any) => Promise<any>,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n try {\n const result = await executeCollection('kbNodes', 'getTags', {});\n\n if (result && result.success) {\n logger.info(`[DB] Retrieved ${result.count} tags`);\n sendResponse(id, {\n success: true,\n data: {\n tags: result.data,\n count: result.count,\n message: `Retrieved ${result.count} tags`\n }\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: false,\n error: 'Failed to retrieve tags'\n }, sendMessage, clientId);\n } catch (error) {\n logger.error('[DB] Failed to get tags:', error);\n sendResponse(id, {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve tags'\n }, sendMessage, clientId);\n }\n}\n\n/**\n * Send KB nodes response\n */\nfunction sendResponse(\n id: string | null,\n res: { success: boolean; error?: string; data?: any },\n sendMessage: (message: Message) => void,\n clientId?: string,\n): void {\n const response: Message = {\n id: id || 'unknown',\n type: 'KB_NODES_RES',\n from: { type: 'data-agent' },\n to: {\n type: 'admin',\n id: clientId\n },\n payload: {\n ...res,\n }\n };\n\n sendMessage(response);\n}\n","import { Component, LLMProvider, Message, DashCompRequestMessageSchema, T_RESPONSE, CollectionRegistry, Tool, DashCompModelConfig } from \"../types\";\nimport { logger } from \"../utils/logger\";\nimport { LLM } from \"../llm\";\nimport { promptLoader } from \"../userResponse/prompt-loader\";\nimport { schema } from \"../userResponse/schema\";\nimport { llmUsageLogger } from \"../utils/llm-usage-logger\";\nimport { userPromptErrorLogger } from \"../utils/user-prompt-error-logger\";\nimport { ZodError } from \"zod\";\n\n// Default models for DASH_COMP flow (can be overridden via config)\n// Using faster/cheaper models since DASH_COMP is a simpler task\nconst DEFAULT_DASH_COMP_MODELS: Record<LLMProvider, string> = {\n\tanthropic: 'anthropic/claude-haiku-4-5-20251001',\n\tgemini: 'gemini/gemini-3-flash-preview',\n\topenai: 'openai/gpt-4o-mini',\n\tgroq: 'groq/llama-3.3-70b-versatile'\n};\n\n// Define return type for dash comp request\ninterface DashCompResponse extends T_RESPONSE {\n\tid?: string;\n\twsId?: string;\n}\n\n/**\n * Pick a component and generate props using LLM\n * Supports both database queries and external tools for data viewing/modification\n */\nasync function pickComponentWithLLM(\n\tprompt: string,\n\tcomponents: Component[],\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\t_collections?: CollectionRegistry,\n\ttools?: Tool[],\n\tdashCompModels?: DashCompModelConfig\n): Promise<T_RESPONSE> {\n\tconst errors: string[] = [];\n\n\t// Format available components for the prompt\n\tlet availableComponentsText = 'No components available';\n\tif (components && components.length > 0) {\n\t\tavailableComponentsText = components\n\t\t\t.map((comp, idx) => {\n\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\n\t\t\t\tconst propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : 'No props';\n\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\n Name: ${comp.name}\n Type: ${comp.type}\n Description: ${comp.description || 'No description'}\n Keywords: ${keywords}\n Props Structure: ${propsPreview}`;\n\t\t\t})\n\t\t\t.join('\\n\\n');\n\t}\n\n\t// Format available external tools for the prompt\n\tlet availableToolsText = 'No external tools available.';\n\tif (tools && tools.length > 0) {\n\t\tavailableToolsText = tools\n\t\t\t.map((tool, idx) => {\n\t\t\t\tconst paramsStr = Object.entries(tool.params || {})\n\t\t\t\t\t.map(([key, type]) => `${key}: ${type}`)\n\t\t\t\t\t.join(', ');\n\t\t\t\treturn `${idx + 1}. ID: ${tool.id}\n Name: ${tool.name}\n Description: ${tool.description}\n Parameters: { ${paramsStr} }`;\n\t\t\t})\n\t\t\t.join('\\n\\n');\n\t}\n\n\ttry {\n\t\t// Get database schema documentation for query generation\n\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t// Get database-specific SQL rules\n\t\tconst databaseRules = await promptLoader.loadDatabaseRules();\n\n\t\t// Load prompts for dash-comp-picker\n\t\tconst prompts = await promptLoader.loadPrompts('dash-comp-picker', {\n\t\t\tUSER_PROMPT: prompt,\n\t\t\tAVAILABLE_COMPONENTS: availableComponentsText,\n\t\t\tSCHEMA_DOC: schemaDoc || 'No database schema available',\n\t\t\tDATABASE_RULES: databaseRules,\n\t\t\tAVAILABLE_TOOLS: availableToolsText\n\t\t});\n\n\t\tlogger.debug('[DASH_COMP_REQ] Loaded dash-comp-picker prompts with schema and tools');\n\n\t\t// Determine which API key and model to use\n\t\tconst providers = llmProviders || ['anthropic', 'gemini', 'openai', 'groq'];\n\t\tlet apiKey: string | undefined;\n\t\tlet model: string | undefined;\n\n\t\t// Check if custom model is configured via dashCompModels\n\t\tif (dashCompModels?.model) {\n\t\t\tmodel = dashCompModels.model;\n\t\t\t// Extract provider from model string (e.g., \"anthropic/claude-sonnet-4-5\" -> \"anthropic\")\n\t\t\tconst modelProvider = model.split('/')[0] as LLMProvider;\n\n\t\t\t// Get the API key for the model's provider\n\t\t\tif (modelProvider === 'anthropic') apiKey = anthropicApiKey;\n\t\t\telse if (modelProvider === 'gemini') apiKey = geminiApiKey;\n\t\t\telse if (modelProvider === 'openai') apiKey = openaiApiKey;\n\t\t\telse if (modelProvider === 'groq') apiKey = groqApiKey;\n\n\t\t\tlogger.info(`[DASH_COMP_REQ] Using configured model: ${model}`);\n\t\t} else {\n\t\t\t// Fallback to provider-based model selection\n\t\t\tfor (const provider of providers) {\n\t\t\t\tif (provider === 'anthropic' && anthropicApiKey) {\n\t\t\t\t\tapiKey = anthropicApiKey;\n\t\t\t\t\tmodel = DEFAULT_DASH_COMP_MODELS.anthropic;\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (provider === 'gemini' && geminiApiKey) {\n\t\t\t\t\tapiKey = geminiApiKey;\n\t\t\t\t\tmodel = DEFAULT_DASH_COMP_MODELS.gemini;\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (provider === 'openai' && openaiApiKey) {\n\t\t\t\t\tapiKey = openaiApiKey;\n\t\t\t\t\tmodel = DEFAULT_DASH_COMP_MODELS.openai;\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (provider === 'groq' && groqApiKey) {\n\t\t\t\t\tapiKey = groqApiKey;\n\t\t\t\t\tmodel = DEFAULT_DASH_COMP_MODELS.groq;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!apiKey || !model) {\n\t\t\terrors.push('No API key available for any LLM provider');\n\t\t\treturn { success: false, errors };\n\t\t}\n\n\t\tlogger.info(`[DASH_COMP_REQ] Using model: ${model}`);\n\n\t\t// Make LLM call\n\t\tconst result = await LLM.stream<any>(\n\t\t\t{\n\t\t\t\tsys: prompts.system,\n\t\t\t\tuser: prompts.user\n\t\t\t},\n\t\t\t{\n\t\t\t\tmodel,\n\t\t\t\tmaxTokens: 8192,\n\t\t\t\ttemperature: 0.2,\n\t\t\t\tapiKey\n\t\t\t},\n\t\t\ttrue // Parse as JSON\n\t\t) as any;\n\n\t\tlogger.debug('[DASH_COMP_REQ] LLM response received');\n\t\tlogger.file('[DASH_COMP_REQ] LLM response:', JSON.stringify(result, null, 2));\n\n\t\t// Validate response structure\n\t\tif (!result.componentId || !result.props) {\n\t\t\terrors.push('Invalid LLM response: missing componentId or props');\n\t\t\tuserPromptErrorLogger.logError('DASH_COMP_REQ', 'Invalid LLM response structure', {\n\t\t\t\tprompt,\n\t\t\t\tresult,\n\t\t\t\tmissingFields: { componentId: !result.componentId, props: !result.props }\n\t\t\t});\n\t\t\treturn { success: false, errors };\n\t\t}\n\n\t\t// Find the original component\n\t\tconst originalComponent = components.find(c => c.id === result.componentId);\n\t\tif (!originalComponent) {\n\t\t\terrors.push(`Component ${result.componentId} not found in available components`);\n\t\t\tuserPromptErrorLogger.logError('DASH_COMP_REQ', 'Component not found', {\n\t\t\t\tprompt,\n\t\t\t\tcomponentId: result.componentId,\n\t\t\t\tavailableComponentIds: components.map(c => c.id)\n\t\t\t});\n\t\t\treturn { success: false, errors };\n\t\t}\n\n\t\t// Build the final component with generated props\n\t\tconst finalComponent: Component = {\n\t\t\t...originalComponent,\n\t\t\tprops: {\n\t\t\t\t...originalComponent.props,\n\t\t\t\t...result.props\n\t\t\t}\n\t\t};\n\n\t\tlogger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);\n\n\t\t// Log data source info\n\t\tif (result.props.query) {\n\t\t\tlogger.info(`[DASH_COMP_REQ] Data source: Database query`);\n\t\t}\n\t\tif (result.props.externalTool) {\n\t\t\tlogger.info(`[DASH_COMP_REQ] Data source: External tool - ${result.props.externalTool.toolName}`);\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tcomponent: finalComponent,\n\t\t\t\treasoning: result.reasoning || 'Component selected based on user prompt',\n\t\t\t\tdataSource: result.props.query ? 'database' : (result.props.externalTool ? 'external_tool' : 'none')\n\t\t\t},\n\t\t\terrors: []\n\t\t};\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\tlogger.error(`[DASH_COMP_REQ] Error picking component: ${errorMsg}`);\n\n\t\t// Log error with full details\n\t\tuserPromptErrorLogger.logError('DASH_COMP_REQ', error instanceof Error ? error : new Error(errorMsg), {\n\t\t\tprompt,\n\t\t\tcomponentsCount: components.length,\n\t\t\ttoolsCount: tools?.length || 0\n\t\t});\n\n\t\terrors.push(errorMsg);\n\t\treturn { success: false, errors };\n\t}\n}\n\n/**\n * Process DASH_COMP_REQ request\n */\nconst processDashCompRequest = async (\n\tdata: any,\n\tcomponents: Component[],\n\t_sendMessage: (message: Message) => void,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tcollections?: CollectionRegistry,\n\ttools?: Tool[],\n\tdashCompModels?: DashCompModelConfig\n): Promise<DashCompResponse> => {\n\tconst errors: string[] = [];\n\n\t// Parse incoming message data\n\tlogger.debug('[DASH_COMP_REQ] Parsing incoming message data');\n\tconst parseResult = DashCompRequestMessageSchema.safeParse(data);\n\n\tif (!parseResult.success) {\n\t\tconst zodError = parseResult.error as ZodError;\n\t\tzodError.errors.forEach(err => {\n\t\t\terrors.push(`${err.path.join('.')}: ${err.message}`);\n\t\t});\n\t\treturn { success: false, errors };\n\t}\n\n\tconst dashCompRequest = parseResult.data;\n\tconst { id, payload } = dashCompRequest;\n\tconst prompt = payload.prompt;\n\tconst wsId = dashCompRequest.from.id || 'unknown';\n\n\t// Reset log files for this request\n\tconst promptContext = `DASH_COMP: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? '...' : ''}`;\n\tllmUsageLogger.resetLogFile(promptContext);\n\n\t// Validate required fields\n\tif (!prompt) {\n\t\terrors.push('Prompt is required');\n\t}\n\n\tif (errors.length > 0) {\n\t\treturn { success: false, errors, id, wsId };\n\t}\n\n\tlogger.info(`[DASH_COMP_REQ] Processing request for prompt: \"${prompt.substring(0, 50)}...\"`);\n\tlogger.info(`[DASH_COMP_REQ] Available: ${components?.length || 0} components, ${tools?.length || 0} tools`);\n\n\t// Check if components are available\n\tif (!components || components.length === 0) {\n\t\tlogger.warn('[DASH_COMP_REQ] No components available');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terrors: ['No components available. Please ensure components are loaded.'],\n\t\t\tid,\n\t\t\twsId\n\t\t};\n\t}\n\n\t// Pick component using LLM\n\tconst llmResponse = await pickComponentWithLLM(\n\t\tprompt,\n\t\tcomponents,\n\t\tanthropicApiKey,\n\t\tgroqApiKey,\n\t\tgeminiApiKey,\n\t\topenaiApiKey,\n\t\tllmProviders,\n\t\tcollections,\n\t\ttools,\n\t\tdashCompModels\n\t);\n\n\t// Log session summary\n\tllmUsageLogger.logSessionSummary(`DASH_COMP: ${prompt?.substring(0, 30)}`);\n\n\treturn {\n\t\tsuccess: llmResponse.success,\n\t\tdata: llmResponse.data,\n\t\terrors: llmResponse.errors,\n\t\tid,\n\t\twsId\n\t};\n};\n\n/**\n * Handle DASH_COMP_REQ WebSocket message\n */\nexport async function handleDashCompRequest(\n\tdata: any,\n\tcomponents: Component[],\n\tsendMessage: (message: Message) => void,\n\tanthropicApiKey?: string,\n\tgroqApiKey?: string,\n\tgeminiApiKey?: string,\n\topenaiApiKey?: string,\n\tllmProviders?: LLMProvider[],\n\tcollections?: CollectionRegistry,\n\ttools?: Tool[],\n\tdashCompModels?: DashCompModelConfig\n): Promise<void> {\n\tconst response = await processDashCompRequest(\n\t\tdata,\n\t\tcomponents,\n\t\tsendMessage,\n\t\tanthropicApiKey,\n\t\tgroqApiKey,\n\t\tgeminiApiKey,\n\t\topenaiApiKey,\n\t\tllmProviders,\n\t\tcollections,\n\t\ttools,\n\t\tdashCompModels\n\t);\n\n\t// Send response back via WebSocket\n\tsendDashCompResponse(\n\t\tresponse.id || data.id,\n\t\t{\n\t\t\tsuccess: response.success,\n\t\t\terrors: response.errors,\n\t\t\tdata: response.data\n\t\t},\n\t\tsendMessage,\n\t\tresponse.wsId || data.from?.id\n\t);\n}\n\n/**\n * Send DASH_COMP_RES response message\n */\nfunction sendDashCompResponse(\n\tid: string,\n\tres: T_RESPONSE,\n\tsendMessage: (message: Message) => void,\n\tclientId?: string\n): void {\n\tconst response: Message = {\n\t\tid,\n\t\ttype: 'DASH_COMP_RES',\n\t\tfrom: { type: 'data-agent' },\n\t\tto: {\n\t\t\ttype: 'runtime',\n\t\t\tid: clientId\n\t\t},\n\t\tpayload: {\n\t\t\t...res\n\t\t}\n\t};\n\n\tsendMessage(response);\n\tlogger.info(`[DASH_COMP_REQ] Response sent to client ${clientId}`);\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { logger } from '../utils/logger';\nimport { UserSchema, UsersDataSchema, type User, type UsersData } from '../types';\n\n/**\n * UserManager class to handle CRUD operations on users with file persistence\n * and in-memory caching. Changes are synced to file periodically.\n */\nexport class UserManager {\n private users: User[] = [];\n private filePath: string;\n private hasChanged: boolean = false;\n private syncInterval: ReturnType<typeof setInterval> | null = null;\n private syncIntervalMs: number;\n private isInitialized: boolean = false;\n\n /**\n * Initialize UserManager with file path and sync interval\n * @param projectId - Project ID to use in file path (default: 'snowflake-dataset')\n * @param syncIntervalMs - Interval in milliseconds to sync changes to file (default: 5000ms)\n */\n constructor(projectId: string = 'snowflake-dataset', syncIntervalMs: number = 5000) {\n this.filePath = path.join(os.homedir(), '.superatom', 'projects', projectId, 'users.json');\n this.syncIntervalMs = syncIntervalMs;\n }\n\n /**\n * Initialize the UserManager by loading users from file and starting sync interval\n */\n async init(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n try {\n // Load users from file into memory\n await this.loadUsersFromFile();\n logger.info(`UserManager initialized with ${this.users.length} users`);\n\n // Start the sync interval\n this.startSyncInterval();\n this.isInitialized = true;\n } catch (error) {\n logger.error('Failed to initialize UserManager:', error);\n throw error;\n }\n }\n\n /**\n * Load users from the JSON file into memory\n */\n private async loadUsersFromFile(): Promise<void> {\n try {\n // Create directory structure if it doesn't exist\n const dir = path.dirname(this.filePath);\n if (!fs.existsSync(dir)) {\n logger.info(`Creating directory structure: ${dir}`);\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Create file with empty users array if it doesn't exist\n if (!fs.existsSync(this.filePath)) {\n logger.info(`Users file does not exist at ${this.filePath}, creating with empty users`);\n const initialData: UsersData = { users: [] };\n fs.writeFileSync(this.filePath, JSON.stringify(initialData, null, 4));\n this.users = [];\n this.hasChanged = false;\n return;\n }\n\n const fileContent = fs.readFileSync(this.filePath, 'utf-8');\n const rawData = JSON.parse(fileContent);\n\n // Validate using Zod schema\n const validatedData = UsersDataSchema.parse(rawData);\n this.users = validatedData.users;\n this.hasChanged = false;\n logger.debug(`Loaded ${this.users.length} users from file`);\n } catch (error) {\n logger.error('Failed to load users from file:', error);\n throw new Error(`Failed to load users from file: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * Save users from memory to the JSON file\n */\n private async saveUsersToFile(): Promise<void> {\n if (!this.hasChanged) {\n return;\n }\n\n try {\n // Create directory if it doesn't exist\n const dir = path.dirname(this.filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Filter out wsIds before saving to file (wsIds are only stored in memory)\n const usersToSave = this.users.map(user => {\n const { wsIds, ...userWithoutWsIds } = user;\n return userWithoutWsIds;\n });\n\n const data: UsersData = { users: usersToSave };\n fs.writeFileSync(this.filePath, JSON.stringify(data, null, 4));\n\n this.hasChanged = false;\n logger.debug(`Synced ${this.users.length} users to file (wsIds excluded)`);\n } catch (error) {\n logger.error('Failed to save users to file:', error);\n throw new Error(`Failed to save users to file: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * Start the periodic sync interval\n */\n private startSyncInterval(): void {\n if (this.syncInterval) {\n return;\n }\n\n this.syncInterval = setInterval(async () => {\n if (this.hasChanged) {\n try {\n await this.saveUsersToFile();\n logger.debug('Auto-sync: Users saved to file');\n } catch (error) {\n logger.error('Auto-sync failed:', error);\n }\n }\n }, this.syncIntervalMs);\n\n logger.debug(`Sync interval started (${this.syncIntervalMs}ms)`);\n }\n\n /**\n * Stop the periodic sync interval\n */\n public stopSyncInterval(): void {\n if (this.syncInterval) {\n clearInterval(this.syncInterval);\n this.syncInterval = null;\n logger.debug('Sync interval stopped');\n }\n }\n\n /**\n * Force sync users to file immediately\n */\n public async forceSync(): Promise<void> {\n await this.saveUsersToFile();\n }\n\n /**\n * Create a new user\n * @param user - User object to create\n * @returns The created user\n */\n public createUser(user: User): User {\n // Validate user data with Zod schema\n const validatedUser = UserSchema.parse(user);\n\n // Check for duplicate username\n if (this.users.some(u => u.username === validatedUser.username)) {\n throw new Error(`User with username ${validatedUser.username} already exists`);\n }\n\n // Check for duplicate email if email is provided\n if (validatedUser.email && this.users.some(u => u.email === validatedUser.email)) {\n throw new Error(`User with email ${validatedUser.email} already exists`);\n }\n\n this.users.push(validatedUser);\n this.hasChanged = true;\n logger.debug(`User created: ${validatedUser.username}`);\n\n return validatedUser;\n }\n\n /**\n * Read a user by username\n * @param username - Username to retrieve\n * @returns The user if found, undefined otherwise\n */\n public getUser(username: string): User | undefined {\n return this.users.find(u => u.username === username);\n }\n\n /**\n * Read a user by email\n * @param email - Email to retrieve\n * @returns The user if found, undefined otherwise\n */\n public getUserByEmail(email: string): User | undefined {\n return this.users.find(u => u.email === email);\n }\n\n /**\n * Find user by username or email\n * @param identifier - Username or email to search for\n * @returns The user if found, undefined otherwise\n */\n public getUserByUsernameOrEmail(identifier: string): User | undefined {\n return this.users.find(u => u.username === identifier || u.email === identifier);\n }\n\n /**\n * Read all users\n * @returns Array of all users\n */\n public getAllUsers(): User[] {\n return [...this.users];\n }\n\n /**\n * Find users by a predicate function\n * @param predicate - Function to filter users\n * @returns Array of matching users\n */\n public findUsers(predicate: (user: User) => boolean): User[] {\n return this.users.filter(predicate);\n }\n\n /**\n * Update an existing user by username\n * @param username - Username of user to update\n * @param updates - Partial user object with fields to update\n * @returns The updated user\n */\n public updateUser(username: string, updates: Partial<User>): User {\n const userIndex = this.users.findIndex(u => u.username === username);\n if (userIndex === -1) {\n throw new Error(`User with username ${username} not found`);\n }\n\n const updatedUser = { ...this.users[userIndex], ...updates };\n this.users[userIndex] = updatedUser;\n this.hasChanged = true;\n logger.debug(`User updated: ${username}`);\n\n return updatedUser;\n }\n\n /**\n * Delete a user by username\n * @param username - Username of user to delete\n * @returns true if user was deleted, false if not found\n */\n public deleteUser(username: string): boolean {\n const initialLength = this.users.length;\n this.users = this.users.filter(u => u.username !== username);\n\n if (this.users.length < initialLength) {\n this.hasChanged = true;\n logger.debug(`User deleted: ${username}`);\n return true;\n }\n return false;\n }\n\n /**\n * Delete all users\n */\n public deleteAllUsers(): void {\n if (this.users.length > 0) {\n this.users = [];\n this.hasChanged = true;\n logger.debug('All users deleted');\n }\n }\n\n /**\n * Get the count of users\n * @returns Number of users in memory\n */\n public getUserCount(): number {\n return this.users.length;\n }\n\n /**\n * Check if a user exists\n * @param username - Username to check\n * @returns true if user exists, false otherwise\n */\n public userExists(username: string): boolean {\n return this.users.some(u => u.username === username);\n }\n\n /**\n * Add a WebSocket ID to a user's wsIds array\n * @param username - Username to update\n * @param wsId - WebSocket ID to add\n * @returns true if successful, false if user not found\n */\n public addWsId(username: string, wsId: string): boolean {\n const user = this.getUser(username);\n if (!user) {\n return false;\n }\n\n if(!user.wsIds || !Array.isArray(user.wsIds)) {\n user.wsIds = [];\n }\n\n if (!user.wsIds.includes(wsId)) {\n user.wsIds.push(wsId);\n // this.hasChanged = true;\n logger.debug(`WebSocket ID added to user ${username}: ${wsId}`);\n }\n\n return true;\n }\n\n /**\n * Remove a WebSocket ID from a user's wsIds array\n * @param username - Username to update\n * @param wsId - WebSocket ID to remove\n * @returns true if successful, false if user not found\n */\n public removeWsId(username: string, wsId: string): boolean {\n const user = this.getUser(username);\n if (!user) {\n return false;\n }\n\n if(!user.wsIds || !Array.isArray(user.wsIds)) {\n return false;\n }\n\n const initialLength = user.wsIds.length;\n user.wsIds = user.wsIds.filter(id => id !== wsId);\n\n if (user.wsIds.length < initialLength) {\n // this.hasChanged = true;\n logger.debug(`WebSocket ID removed from user ${username}: ${wsId}`);\n }\n\n return true;\n }\n\n /**\n * Get the change status\n * @returns true if there are unsaved changes, false otherwise\n */\n public hasUnsavedChanges(): boolean {\n return this.hasChanged;\n }\n\n /**\n * Cleanup resources and stop sync interval\n */\n public async destroy(): Promise<void> {\n this.stopSyncInterval();\n // Final sync before cleanup\n if (this.hasChanged) {\n await this.saveUsersToFile();\n }\n logger.info('UserManager destroyed');\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { logger } from '../utils/logger';\nimport { DSLRendererProps, DSLRendererPropsSchema } from './types';\n\n/**\n * DashboardManager class to handle CRUD operations on dashboards\n * All operations read/write directly to files (no in-memory caching)\n */\nexport class DashboardManager {\n private dashboardsBasePath: string;\n private projectId: string;\n\n /**\n * Initialize DashboardManager with project ID\n * @param projectId - Project ID to use in file path\n */\n constructor(projectId: string = 'snowflake-dataset') {\n this.projectId = projectId;\n this.dashboardsBasePath = path.join(\n os.homedir(),\n '.superatom',\n 'projects',\n projectId,\n 'dashboards'\n );\n }\n\n /**\n * Get the file path for a specific dashboard\n * @param dashboardId - Dashboard ID\n * @returns Full path to dashboard data.json file\n */\n private getDashboardPath(dashboardId: string): string {\n return path.join(this.dashboardsBasePath, dashboardId, 'data.json');\n }\n\n /**\n * Create a new dashboard\n * @param dashboardId - Unique dashboard ID\n * @param dashboard - Dashboard data\n * @returns Created dashboard with metadata\n */\n createDashboard(dashboardId: string, dashboard: DSLRendererProps): DSLRendererProps {\n const dashboardPath = this.getDashboardPath(dashboardId);\n const dashboardDir = path.dirname(dashboardPath);\n\n // Check if dashboard already exists\n if (fs.existsSync(dashboardPath)) {\n throw new Error(`Dashboard '${dashboardId}' already exists`);\n }\n\n // Validate dashboard structure\n const validated = DSLRendererPropsSchema.parse(dashboard);\n\n // Create directory structure\n fs.mkdirSync(dashboardDir, { recursive: true });\n\n // Write dashboard to file\n fs.writeFileSync(dashboardPath, JSON.stringify(validated, null, 4));\n\n logger.info(`Dashboard created: ${dashboardId}`);\n return validated;\n }\n\n /**\n * Get a specific dashboard by ID\n * @param dashboardId - Dashboard ID\n * @returns Dashboard data or null if not found\n */\n getDashboard(dashboardId: string): DSLRendererProps | null {\n const dashboardPath = this.getDashboardPath(dashboardId);\n\n if (!fs.existsSync(dashboardPath)) {\n logger.warn(`Dashboard not found: ${dashboardId}`);\n return null;\n }\n\n try {\n const fileContent = fs.readFileSync(dashboardPath, 'utf-8');\n const dashboard = JSON.parse(fileContent) as DSLRendererProps;\n\n // Validate structure\n const validated = DSLRendererPropsSchema.parse(dashboard);\n return validated;\n } catch (error) {\n logger.error(`Failed to read dashboard ${dashboardId}:`, error);\n return null;\n }\n }\n\n /**\n * Get all dashboards\n * @returns Array of dashboard objects with their IDs\n */\n getAllDashboards(): Array<{ dashboardId: string; dashboard: DSLRendererProps }> {\n // Create base directory if it doesn't exist\n if (!fs.existsSync(this.dashboardsBasePath)) {\n fs.mkdirSync(this.dashboardsBasePath, { recursive: true });\n return [];\n }\n\n const dashboards: Array<{ dashboardId: string; dashboard: DSLRendererProps }> = [];\n\n try {\n const dashboardDirs = fs.readdirSync(this.dashboardsBasePath);\n\n for (const dashboardId of dashboardDirs) {\n const dashboardPath = this.getDashboardPath(dashboardId);\n\n if (fs.existsSync(dashboardPath)) {\n const dashboard = this.getDashboard(dashboardId);\n if (dashboard) {\n dashboards.push({ dashboardId, dashboard });\n }\n }\n }\n\n logger.debug(`Retrieved ${dashboards.length} dashboards`);\n return dashboards;\n } catch (error) {\n logger.error('Failed to get all dashboards:', error);\n return [];\n }\n }\n\n /**\n * Update an existing dashboard\n * @param dashboardId - Dashboard ID\n * @param dashboard - Updated dashboard data\n * @returns Updated dashboard or null if not found\n */\n updateDashboard(dashboardId: string, dashboard: DSLRendererProps): DSLRendererProps | null {\n const dashboardPath = this.getDashboardPath(dashboardId);\n\n if (!fs.existsSync(dashboardPath)) {\n logger.warn(`Dashboard not found for update: ${dashboardId}`);\n return null;\n }\n\n try {\n // Validate dashboard structure\n const validated = DSLRendererPropsSchema.parse(dashboard);\n\n // Write updated dashboard to file\n fs.writeFileSync(dashboardPath, JSON.stringify(validated, null, 4));\n\n logger.info(`Dashboard updated: ${dashboardId}`);\n return validated;\n } catch (error) {\n logger.error(`Failed to update dashboard ${dashboardId}:`, error);\n throw error;\n }\n }\n\n /**\n * Delete a dashboard\n * @param dashboardId - Dashboard ID\n * @returns True if deleted, false if not found\n */\n deleteDashboard(dashboardId: string): boolean {\n const dashboardPath = this.getDashboardPath(dashboardId);\n const dashboardDir = path.dirname(dashboardPath);\n\n if (!fs.existsSync(dashboardPath)) {\n logger.warn(`Dashboard not found for deletion: ${dashboardId}`);\n return false;\n }\n\n try {\n // Delete the entire dashboard directory\n fs.rmSync(dashboardDir, { recursive: true, force: true });\n\n logger.info(`Dashboard deleted: ${dashboardId}`);\n return true;\n } catch (error) {\n logger.error(`Failed to delete dashboard ${dashboardId}:`, error);\n return false;\n }\n }\n\n /**\n * Check if a dashboard exists\n * @param dashboardId - Dashboard ID\n * @returns True if dashboard exists, false otherwise\n */\n dashboardExists(dashboardId: string): boolean {\n const dashboardPath = this.getDashboardPath(dashboardId);\n return fs.existsSync(dashboardPath);\n }\n\n /**\n * Get dashboard count\n * @returns Number of dashboards\n */\n getDashboardCount(): number {\n if (!fs.existsSync(this.dashboardsBasePath)) {\n return 0;\n }\n\n try {\n const dashboardDirs = fs.readdirSync(this.dashboardsBasePath);\n return dashboardDirs.filter((dir) => {\n const dashboardPath = this.getDashboardPath(dir);\n return fs.existsSync(dashboardPath);\n }).length;\n } catch (error) {\n logger.error('Failed to get dashboard count:', error);\n return 0;\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { logger } from '../utils/logger';\nimport { DSLRendererProps, DSLRendererPropsSchema } from './types';\n\n/**\n * ReportManager class to handle CRUD operations on reports\n * All operations read/write directly to files (no in-memory caching)\n */\nexport class ReportManager {\n private reportsBasePath: string;\n private projectId: string;\n\n /**\n * Initialize ReportManager with project ID\n * @param projectId - Project ID to use in file path\n */\n constructor(projectId: string = 'snowflake-dataset') {\n this.projectId = projectId;\n this.reportsBasePath = path.join(\n os.homedir(),\n '.superatom',\n 'projects',\n projectId,\n 'reports'\n );\n }\n\n /**\n * Get the file path for a specific report\n * @param reportId - Report ID\n * @returns Full path to report data.json file\n */\n private getReportPath(reportId: string): string {\n return path.join(this.reportsBasePath, reportId, 'data.json');\n }\n\n /**\n * Create a new report\n * @param reportId - Unique report ID\n * @param report - Report data\n * @returns Created report with metadata\n */\n createReport(reportId: string, report: DSLRendererProps): DSLRendererProps {\n const reportPath = this.getReportPath(reportId);\n const reportDir = path.dirname(reportPath);\n\n // Check if report already exists\n if (fs.existsSync(reportPath)) {\n throw new Error(`Report '${reportId}' already exists`);\n }\n\n // Validate report structure\n const validated = DSLRendererPropsSchema.parse(report);\n\n // Create directory structure\n fs.mkdirSync(reportDir, { recursive: true });\n\n // Write report to file\n fs.writeFileSync(reportPath, JSON.stringify(validated, null, 4));\n\n logger.info(`Report created: ${reportId}`);\n return validated;\n }\n\n /**\n * Get a specific report by ID\n * @param reportId - Report ID\n * @returns Report data or null if not found\n */\n getReport(reportId: string): DSLRendererProps | null {\n const reportPath = this.getReportPath(reportId);\n\n if (!fs.existsSync(reportPath)) {\n logger.warn(`Report not found: ${reportId}`);\n return null;\n }\n\n try {\n const fileContent = fs.readFileSync(reportPath, 'utf-8');\n const report = JSON.parse(fileContent) as DSLRendererProps;\n\n // Validate structure\n const validated = DSLRendererPropsSchema.parse(report);\n return validated;\n } catch (error) {\n logger.error(`Failed to read report ${reportId}:`, error);\n return null;\n }\n }\n\n /**\n * Get all reports\n * @returns Array of report objects with their IDs\n */\n getAllReports(): Array<{ reportId: string; report: DSLRendererProps }> {\n // Create base directory if it doesn't exist\n if (!fs.existsSync(this.reportsBasePath)) {\n fs.mkdirSync(this.reportsBasePath, { recursive: true });\n return [];\n }\n\n const reports: Array<{ reportId: string; report: DSLRendererProps }> = [];\n\n try {\n const reportDirs = fs.readdirSync(this.reportsBasePath);\n\n for (const reportId of reportDirs) {\n const reportPath = this.getReportPath(reportId);\n\n if (fs.existsSync(reportPath)) {\n const report = this.getReport(reportId);\n if (report) {\n reports.push({ reportId, report });\n }\n }\n }\n\n logger.debug(`Retrieved ${reports.length} reports`);\n return reports;\n } catch (error) {\n logger.error('Failed to get all reports:', error);\n return [];\n }\n }\n\n /**\n * Update an existing report\n * @param reportId - Report ID\n * @param report - Updated report data\n * @returns Updated report or null if not found\n */\n updateReport(reportId: string, report: DSLRendererProps): DSLRendererProps | null {\n const reportPath = this.getReportPath(reportId);\n\n if (!fs.existsSync(reportPath)) {\n logger.warn(`Report not found for update: ${reportId}`);\n return null;\n }\n\n try {\n // Validate report structure\n const validated = DSLRendererPropsSchema.parse(report);\n\n // Write updated report to file\n fs.writeFileSync(reportPath, JSON.stringify(validated, null, 4));\n\n logger.info(`Report updated: ${reportId}`);\n return validated;\n } catch (error) {\n logger.error(`Failed to update report ${reportId}:`, error);\n throw error;\n }\n }\n\n /**\n * Delete a report\n * @param reportId - Report ID\n * @returns True if deleted, false if not found\n */\n deleteReport(reportId: string): boolean {\n const reportPath = this.getReportPath(reportId);\n const reportDir = path.dirname(reportPath);\n\n if (!fs.existsSync(reportPath)) {\n logger.warn(`Report not found for deletion: ${reportId}`);\n return false;\n }\n\n try {\n // Delete the entire report directory\n fs.rmSync(reportDir, { recursive: true, force: true });\n\n logger.info(`Report deleted: ${reportId}`);\n return true;\n } catch (error) {\n logger.error(`Failed to delete report ${reportId}:`, error);\n return false;\n }\n }\n\n /**\n * Check if a report exists\n * @param reportId - Report ID\n * @returns True if report exists, false otherwise\n */\n reportExists(reportId: string): boolean {\n const reportPath = this.getReportPath(reportId);\n return fs.existsSync(reportPath);\n }\n\n /**\n * Get report count\n * @returns Number of reports\n */\n getReportCount(): number {\n if (!fs.existsSync(this.reportsBasePath)) {\n return 0;\n }\n\n try {\n const reportDirs = fs.readdirSync(this.reportsBasePath);\n return reportDirs.filter((dir) => {\n const reportPath = this.getReportPath(dir);\n return fs.existsSync(reportPath);\n }).length;\n } catch (error) {\n logger.error('Failed to get report count:', error);\n return 0;\n }\n }\n}\n","import { ThreadManager } from '../threads';\nimport { logger } from '../utils/logger';\nimport { STORAGE_CONFIG } from '../config/storage';\n\n/**\n * CleanupService handles cleanup of old threads and UIBlocks\n * to prevent memory bloat and maintain optimal performance\n */\nexport class CleanupService {\n private static instance: CleanupService;\n private cleanupInterval: NodeJS.Timeout | null = null;\n\n private constructor() {}\n\n /**\n * Get singleton instance of CleanupService\n */\n static getInstance(): CleanupService {\n if (!CleanupService.instance) {\n CleanupService.instance = new CleanupService();\n }\n return CleanupService.instance;\n }\n\n /**\n * Clean up old threads based on retention period\n * @param retentionDays - Number of days to keep threads (defaults to config)\n * @returns Number of threads deleted\n */\n cleanupOldThreads(retentionDays: number = STORAGE_CONFIG.THREAD_RETENTION_DAYS): number {\n const threadManager = ThreadManager.getInstance();\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\n\n const threads = threadManager.getAllThreads();\n let deletedCount = 0;\n\n for (const thread of threads) {\n if (thread.getCreatedAt() < cutoffDate) {\n const threadId = thread.getId();\n if (threadManager.deleteThread(threadId)) {\n deletedCount++;\n logger.info(`Deleted old thread: ${threadId} (created: ${thread.getCreatedAt().toISOString()})`);\n }\n }\n }\n\n if (deletedCount > 0) {\n logger.info(`Cleanup: Deleted ${deletedCount} old threads (older than ${retentionDays} days)`);\n }\n\n return deletedCount;\n }\n\n /**\n * Clean up old UIBlocks within threads based on retention period\n * @param retentionDays - Number of days to keep UIBlocks (defaults to config)\n * @returns Object with number of UIBlocks deleted per thread\n */\n cleanupOldUIBlocks(retentionDays: number = STORAGE_CONFIG.UIBLOCK_RETENTION_DAYS): { [threadId: string]: number } {\n const threadManager = ThreadManager.getInstance();\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\n\n const threads = threadManager.getAllThreads();\n const deletionStats: { [threadId: string]: number } = {};\n\n for (const thread of threads) {\n const uiblocks = thread.getUIBlocks();\n let deletedInThread = 0;\n\n for (const uiblock of uiblocks) {\n if (uiblock.getCreatedAt() < cutoffDate) {\n if (thread.removeUIBlock(uiblock.getId())) {\n deletedInThread++;\n }\n }\n }\n\n if (deletedInThread > 0) {\n deletionStats[thread.getId()] = deletedInThread;\n logger.info(\n `Deleted ${deletedInThread} old UIBlocks from thread ${thread.getId()} (older than ${retentionDays} days)`\n );\n }\n }\n\n const totalDeleted = Object.values(deletionStats).reduce((sum, count) => sum + count, 0);\n if (totalDeleted > 0) {\n logger.info(`Cleanup: Deleted ${totalDeleted} old UIBlocks across ${Object.keys(deletionStats).length} threads`);\n }\n\n return deletionStats;\n }\n\n /**\n * Clear all component data from UIBlocks to free memory\n * Keeps metadata but removes the actual data\n * @param retentionDays - Number of days to keep full data (defaults to config)\n * @returns Number of UIBlocks whose data was cleared\n */\n clearOldUIBlockData(retentionDays: number = STORAGE_CONFIG.UIBLOCK_RETENTION_DAYS): number {\n const threadManager = ThreadManager.getInstance();\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\n\n const threads = threadManager.getAllThreads();\n let clearedCount = 0;\n\n for (const thread of threads) {\n const uiblocks = thread.getUIBlocks();\n\n for (const uiblock of uiblocks) {\n if (uiblock.getCreatedAt() < cutoffDate) {\n const componentData = uiblock.getComponentData();\n\n // Only clear if data exists\n if (componentData && Object.keys(componentData).length > 0) {\n // Keep metadata but clear actual data\n const metadata = {\n dataCleared: true,\n clearedAt: new Date().toISOString(),\n originalDataInfo: {\n totalRows: componentData.totalRows,\n storedRows: componentData.storedRows,\n isTruncated: componentData.isTruncated,\n },\n };\n\n uiblock.setComponentData({ ...metadata, data: null });\n clearedCount++;\n }\n }\n }\n }\n\n if (clearedCount > 0) {\n logger.info(`Cleanup: Cleared data from ${clearedCount} old UIBlocks (older than ${retentionDays} days)`);\n }\n\n return clearedCount;\n }\n\n /**\n * Run full cleanup (threads, UIBlocks, and data)\n * @returns Cleanup statistics\n */\n runFullCleanup(): {\n threadsDeleted: number;\n uiblocksDeleted: { [threadId: string]: number };\n dataCleared: number;\n } {\n logger.info('Starting full cleanup...');\n\n const stats = {\n threadsDeleted: this.cleanupOldThreads(),\n uiblocksDeleted: this.cleanupOldUIBlocks(),\n dataCleared: this.clearOldUIBlockData(),\n };\n\n const totalUIBlocksDeleted = Object.values(stats.uiblocksDeleted).reduce((sum, count) => sum + count, 0);\n\n logger.info(\n `Full cleanup completed: ${stats.threadsDeleted} threads, ${totalUIBlocksDeleted} UIBlocks deleted, ${stats.dataCleared} UIBlock data cleared`\n );\n\n return stats;\n }\n\n /**\n * Start automatic cleanup at regular intervals\n * @param intervalHours - Hours between cleanup runs (default: 24)\n */\n startAutoCleanup(intervalHours: number = 24): void {\n if (this.cleanupInterval) {\n logger.warn('Auto cleanup is already running');\n\n //stop this and run with new interval\n\n \n return;\n }\n\n const intervalMs = intervalHours * 60 * 60 * 1000;\n\n // Run initial cleanup\n this.runFullCleanup();\n\n // Schedule recurring cleanup\n this.cleanupInterval = setInterval(() => {\n this.runFullCleanup();\n }, intervalMs);\n\n logger.info(`Auto cleanup started: running every ${intervalHours} hours`);\n }\n\n /**\n * Stop automatic cleanup\n */\n stopAutoCleanup(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n logger.info('Auto cleanup stopped');\n }\n }\n\n /**\n * Check if auto cleanup is running\n */\n isAutoCleanupRunning(): boolean {\n return this.cleanupInterval !== null;\n }\n\n /**\n * Get current memory usage statistics\n */\n getMemoryStats(): {\n threadCount: number;\n totalUIBlocks: number;\n avgUIBlocksPerThread: number;\n } {\n const threadManager = ThreadManager.getInstance();\n const threads = threadManager.getAllThreads();\n const threadCount = threads.length;\n\n let totalUIBlocks = 0;\n for (const thread of threads) {\n totalUIBlocks += thread.getUIBlockCount();\n }\n\n return {\n threadCount,\n totalUIBlocks,\n avgUIBlocksPerThread: threadCount > 0 ? totalUIBlocks / threadCount : 0,\n };\n }\n}\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAmMR,MAAM;AAAA;AAAA,MAEP;AAAA,MAEA,yBAAyB;AAAA,QACxB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAkYR,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQP;AAAA,MAEA,WAAW;AAAA,QACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWR,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["fs","import_fs","path","fs","WebSocket","import_zod","import_zod","ExpressionSchema","BindingSchema","ForDirectiveSchema","QuerySpecSchema","UIElementSchema","UIComponentSchema","DSLRendererPropsSchema","DSLRendererPropsSchema","size","import_crypto","result","fs","import_crypto","crypto","sendDataResponse","sendDataResponse","import_path","import_fs","path","fs","schema","import_fs","import_path","path","fs","import_fs","import_path","path","fs","Anthropic","Groq","result","OpenAI","b","ensureQueryLimit","result","elapsedTime","dotenv","import_dotenv","dotenv","import_dotenv","dotenv","import_dotenv","dotenv","import_dotenv","dotenv","LOG_LEVEL_PRIORITY","MESSAGE_LEVEL_PRIORITY","sendDataResponse","sendResponse","sendResponse","sanitizedUsers","sanitizedUser","sendResponse","dashboardManager","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","handleQuery","sendResponse","reportManager","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","handleQuery","sendResponse","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","handleQuery","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","handleQuery","sendResponse","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","sendResponse","import_fs","import_path","path","os","fs","import_fs","import_path","import_os","path","os","fs","import_fs","import_path","import_os","path","os","fs","DSLRendererPropsSchema"]}
|