@superatomai/sdk-node 0.0.10 → 0.0.11
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/README.md +942 -942
- package/dist/index.js +65 -106
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -106
- 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/userResponse/utils.ts","../src/index.ts","../src/websocket.ts","../src/types.ts","../src/dashboards/types.ts","../src/reports/types.ts","../src/utils/logger.ts","../src/threads/uiblock.ts","../src/config/storage.ts","../src/threads/thread.ts","../src/threads/thread-manager.ts","../src/handlers/data-request.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/userResponse/prompt-loader.ts","../src/userResponse/prompts.ts","../src/llm.ts","../src/userResponse/knowledge-base.ts","../src/userResponse/anthropic.ts","../src/userResponse/index.ts","../src/utils/log-collector.ts","../src/config/context.ts","../src/handlers/user-prompt-request.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/auth/user-manager.ts","../src/dashboards/dashboard-manager.ts","../src/reports/report-manager.ts","../src/services/cleanup-service.ts"],"sourcesContent":["import type { Action } from '../threads/action';\r\n\r\n/**\r\n * Converts T-SQL TOP syntax to Snowflake LIMIT syntax\r\n * Snowflake doesn't support TOP keyword - it must use LIMIT\r\n * @param query - The SQL query to check\r\n * @returns The query with TOP converted to LIMIT\r\n */\r\nexport function convertTopToLimit(query: string): string {\r\n\tif (!query || query.trim().length === 0) {\r\n\t\treturn query;\r\n\t}\r\n\r\n\t// Replace \"TOP N\" with nothing (we'll add LIMIT at the end)\r\n\t// Pattern: SELECT TOP number or SELECT TOP (number)\r\n\tlet modifiedQuery = query.replace(/\\bSELECT\\s+TOP\\s+(\\d+)\\b/gi, 'SELECT');\r\n\r\n\tif (modifiedQuery !== query) {\r\n\t\tconsole.warn(`⚠️ Query had TOP syntax. Converting to LIMIT for Snowflake compatibility.`);\r\n\t}\r\n\r\n\treturn modifiedQuery;\r\n}\r\n\r\n/**\r\n * Ensures a SQL query has a LIMIT clause to prevent large result sets\r\n * Only applies to SELECT queries - leaves INSERT, UPDATE, DELETE, etc. unchanged\r\n * Also removes any duplicate LIMIT clauses to prevent SQL errors\r\n * Converts T-SQL TOP syntax to Snowflake LIMIT syntax\r\n * Enforces a maximum limit to prevent excessive data retrieval\r\n * @param query - The SQL query to check\r\n * @param defaultLimit - Default limit to apply if none exists (default: 32)\r\n * @param maxLimit - Maximum allowed limit (default: 32)\r\n * @returns The query with a single LIMIT clause (if it's a SELECT query)\r\n */\r\nexport function ensureQueryLimit(query: string, defaultLimit: number = 32, maxLimit: number = 32): string {\r\n\tif (!query || query.trim().length === 0) {\r\n\t\treturn query;\r\n\t}\r\n\r\n\tlet trimmedQuery = query.trim();\r\n\r\n\t// Only apply LIMIT to SELECT queries\r\n\t// Check if the query is a SELECT statement (not INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, etc.)\r\n\tconst isSelectQuery = /^\\s*SELECT\\b/i.test(trimmedQuery) ||\r\n\t\t/^\\s*WITH\\b.*\\bSELECT\\b/is.test(trimmedQuery); // Also handle CTEs (WITH clause)\r\n\r\n\tif (!isSelectQuery) {\r\n\t\t// Not a SELECT query, return as-is\r\n\t\treturn query;\r\n\t}\r\n\r\n\t// Step 1: Convert TOP syntax to standard format\r\n\ttrimmedQuery = convertTopToLimit(trimmedQuery);\r\n\r\n\t// Remove any trailing semicolon for processing\r\n\tconst hadSemicolon = trimmedQuery.endsWith(';');\r\n\tif (hadSemicolon) {\r\n\t\ttrimmedQuery = trimmedQuery.slice(0, -1).trim();\r\n\t}\r\n\r\n\t// Remove any duplicate LIMIT clauses (keep only the last one, or remove all to add a fresh one)\r\n\t// This regex matches LIMIT followed by a number, case-insensitive\r\n\tconst limitMatches = trimmedQuery.match(/\\bLIMIT\\s+(\\d+)\\b/gi);\r\n\r\n\tif (limitMatches && limitMatches.length > 0) {\r\n\t\t// If there are multiple LIMIT clauses, remove them all and add a fresh one\r\n\t\tif (limitMatches.length > 1) {\r\n\t\t\tconsole.warn(`⚠️ Query had ${limitMatches.length} LIMIT clauses. Removing duplicates...`);\r\n\t\t\ttrimmedQuery = trimmedQuery.replace(/\\s*\\bLIMIT\\s+\\d+\\b/gi, '').trim();\r\n\t\t} else {\r\n\t\t\t// Single LIMIT exists - check if it exceeds maxLimit\r\n\t\t\tconst existingLimitMatch = trimmedQuery.match(/\\bLIMIT\\s+(\\d+)\\b/i);\r\n\t\t\tif (existingLimitMatch) {\r\n\t\t\t\tconst existingLimit = parseInt(existingLimitMatch[1], 10);\r\n\r\n\t\t\t\t// If existing limit is less than or equal to maxLimit, keep it\r\n\t\t\t\tif (existingLimit <= maxLimit) {\r\n\t\t\t\t\tif (hadSemicolon) {\r\n\t\t\t\t\t\ttrimmedQuery += ';';\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn trimmedQuery;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// If existing limit exceeds maxLimit, replace it with maxLimit\r\n\t\t\t\tconsole.warn(`⚠️ Query LIMIT ${existingLimit} exceeds maximum of ${maxLimit}. Reducing to ${maxLimit}...`);\r\n\t\t\t\ttrimmedQuery = trimmedQuery.replace(/\\bLIMIT\\s+\\d+\\b/i, `LIMIT ${maxLimit}`);\r\n\r\n\t\t\t\tif (hadSemicolon) {\r\n\t\t\t\t\ttrimmedQuery += ';';\r\n\t\t\t\t}\r\n\t\t\t\treturn trimmedQuery;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Add LIMIT clause at the end\r\n\ttrimmedQuery = `${trimmedQuery} LIMIT ${defaultLimit}`;\r\n\r\n\t// Add back the semicolon if it was there\r\n\tif (hadSemicolon) {\r\n\t\ttrimmedQuery += ';';\r\n\t}\r\n\r\n\treturn trimmedQuery;\r\n}\r\n\r\n/**\r\n * Validates and fixes scalar subqueries to ensure they return exactly one row\r\n * Adds LIMIT 1 to subqueries used with scalar comparison operators (=, <, >, <=, >=, <>)\r\n *\r\n * @param query - The SQL query to validate\r\n * @returns The query with fixed scalar subqueries\r\n */\r\nexport function fixScalarSubqueries(query: string): string {\r\n\tif (!query || query.trim().length === 0) {\r\n\t\treturn query;\r\n\t}\r\n\r\n\tlet modifiedQuery = query;\r\n\tlet hasChanges = false;\r\n\r\n\t// Find all subqueries preceded by scalar comparison operators\r\n\t// Pattern: operator followed by (SELECT ...)\r\n\tconst scalarOperatorPattern = /([=<>!]=?|<>)\\s*\\(\\s*SELECT\\s/gi;\r\n\r\n\tconst matches = [...modifiedQuery.matchAll(scalarOperatorPattern)];\r\n\r\n\t// Process matches in reverse order to maintain string positions\r\n\tfor (let i = matches.length - 1; i >= 0; i--) {\r\n\t\tconst match = matches[i];\r\n\t\tconst startPos = match.index! + match[0].length - 'SELECT '.length;\r\n\r\n\t\t// Find the matching closing parenthesis\r\n\t\tlet parenDepth = 1;\r\n\t\tlet endPos = startPos;\r\n\t\tlet foundEnd = false;\r\n\r\n\t\tfor (let j = startPos; j < modifiedQuery.length; j++) {\r\n\t\t\tconst char = modifiedQuery[j];\r\n\t\t\tif (char === '(') parenDepth++;\r\n\t\t\tif (char === ')') {\r\n\t\t\t\tparenDepth--;\r\n\t\t\t\tif (parenDepth === 0) {\r\n\t\t\t\t\tendPos = j;\r\n\t\t\t\t\tfoundEnd = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!foundEnd) continue;\r\n\r\n\t\t// Extract the subquery content\r\n\t\tconst subquery = modifiedQuery.substring(startPos, endPos);\r\n\r\n\t\t// Check if it already has LIMIT\r\n\t\tif (/\\bLIMIT\\s+\\d+/i.test(subquery)) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Add LIMIT 1 before the closing parenthesis\r\n\t\tconst fixedSubquery = subquery.trim() + ' LIMIT 1';\r\n\t\tmodifiedQuery =\r\n\t\t\tmodifiedQuery.substring(0, startPos) +\r\n\t\t\tfixedSubquery +\r\n\t\t\tmodifiedQuery.substring(endPos);\r\n\r\n\t\thasChanges = true;\r\n\t\tconsole.warn(`⚠️ Fixed scalar subquery: added LIMIT 1 to prevent multiple row error`);\r\n\t}\r\n\r\n\tif (hasChanges) {\r\n\t\tconsole.log('✓ Query validated and fixed for PostgreSQL scalar subquery compatibility');\r\n\t}\r\n\r\n\treturn modifiedQuery;\r\n}\r\n\r\n/**\r\n * Converts question strings to Action objects format\r\n * Used for follow-up questions generated by LLM\r\n * @param questions - Array of question strings\r\n * @returns Array of Action objects\r\n */\r\nexport function convertQuestionsToActions(questions: string[]): Action[] {\r\n\treturn questions.map((question: string, index: number) => ({\r\n\t\tid: `action_${index}_${Date.now()}`,\r\n\t\tname: question,\r\n\t\ttype: 'next_question',\r\n\t\tquestion\r\n\t}));\r\n}\r\n\r\n/**\r\n * Calculates the size of a JSON object in bytes\r\n * @param obj - The object to measure\r\n * @returns Size in bytes\r\n */\r\nexport function getJsonSizeInBytes(obj: any): number {\r\n\tconst jsonString = JSON.stringify(obj);\r\n\treturn Buffer.byteLength(jsonString, 'utf8');\r\n}\r\n\r\n/**\r\n * Checks if a message exceeds the WebSocket size limit\r\n * @param message - The message object to check\r\n * @param maxSize - Maximum size in bytes (default: 1MB)\r\n * @returns Object with isValid flag and size information\r\n */\r\nexport function validateMessageSize(message: any, maxSize: number = 1048576): { isValid: boolean; size: number; maxSize: number } {\r\n\tconst size = getJsonSizeInBytes(message);\r\n\treturn {\r\n\t\tisValid: size <= maxSize,\r\n\t\tsize,\r\n\t\tmaxSize\r\n\t};\r\n}","import { createWebSocket } from './websocket';\r\nimport {\r\n IncomingMessageSchema,\r\n type Message,\r\n type IncomingMessage,\r\n type SuperatomSDKConfig,\r\n type CollectionRegistry,\r\n type CollectionHandler,\r\n type CollectionOperation,\r\n Component,\r\n LLMProvider,\r\n} from './types';\r\nimport { logger } from './utils/logger';\r\nimport { handleDataRequest } from './handlers/data-request';\r\nimport { handleBundleRequest } from './handlers/bundle-request';\r\nimport { handleAuthLoginRequest } from './handlers/auth-login-requests';\r\nimport { handleAuthVerifyRequest } from './handlers/auth-verify-request';\r\nimport { handleUserPromptRequest } from './handlers/user-prompt-request';\r\nimport { handleUserPromptSuggestions } from './handlers/user-prompt-suggestions';\r\nimport { handleActionsRequest } from './handlers/actions-request';\r\nimport { handleComponentListResponse } from './handlers/components-list-response';\r\nimport { handleUsersRequest } from './handlers/users';\r\nimport { handleDashboardsRequest } from './handlers/dashboards';\r\nimport { handleReportsRequest } from './handlers/reports';\r\nimport { getLLMProviders } from './userResponse';\r\nimport { setUserManager, cleanupUserStorage } from './auth/user-storage';\r\nimport { UserManager } from './auth/user-manager';\r\nimport { setDashboardManager } from './dashboards/dashboard-storage';\r\nimport { DashboardManager } from './dashboards/dashboard-manager';\r\nimport { setReportManager } from './reports/report-storage';\r\nimport { ReportManager } from './reports/report-manager';\r\nimport { promptLoader } from './userResponse/prompt-loader';\r\n\r\nexport const SDK_VERSION = '0.0.8';\r\n\r\nconst DEFAULT_WS_URL = 'wss://ws.superatom.ai/websocket';\r\n\r\ntype MessageTypeHandler = (message: IncomingMessage) => void | Promise<void>;\r\n\r\nexport class SuperatomSDK {\r\n private ws: ReturnType<typeof createWebSocket> | null = null;\r\n private url: string;\r\n private apiKey: string;\r\n private projectId: string;\r\n private userId: string;\r\n private type: string;\r\n private bundleDir: string | undefined;\r\n private messageHandlers: Map<string, (message: IncomingMessage) => void> = new Map();\r\n private messageTypeHandlers: Map<string, MessageTypeHandler> = new Map();\r\n private connected: boolean = false;\r\n private reconnectAttempts: number = 0;\r\n private maxReconnectAttempts: number = 5;\r\n private collections: CollectionRegistry = {};\r\n\tprivate components: Component[] = [];\r\n private anthropicApiKey: string;\r\n private groqApiKey: string;\r\n private llmProviders: LLMProvider[];\r\n private userManager: UserManager;\r\n private dashboardManager: DashboardManager;\r\n private reportManager: ReportManager;\r\n\r\n constructor(config: SuperatomSDKConfig) {\r\n // Set log level if provided in config (overrides environment variable)\r\n if (config.logLevel) {\r\n logger.setLogLevel(config.logLevel);\r\n }\r\n\r\n this.apiKey = config.apiKey;\r\n this.projectId = config.projectId;\r\n this.userId = config.userId || 'anonymous';\r\n this.type = config.type || 'data-agent';\r\n this.bundleDir = config.bundleDir;\r\n this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;\r\n this.anthropicApiKey = config.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY || '';\r\n this.groqApiKey = config.GROQ_API_KEY || process.env.GROQ_API_KEY || '';\r\n this.llmProviders = config.LLM_PROVIDERS || getLLMProviders();\r\n\r\n // Initialize UserManager for this SDK instance\r\n this.userManager = new UserManager(this.projectId, 5000);\r\n\r\n // Initialize DashboardManager for this SDK instance\r\n this.dashboardManager = new DashboardManager(this.projectId);\r\n\r\n // Initialize ReportManager for this SDK instance\r\n this.reportManager = new ReportManager(this.projectId);\r\n\r\n // Initialize PromptLoader (load prompts into memory)\r\n this.initializePromptLoader(config.promptsDir).catch((error) => {\r\n logger.error('Failed to initialize PromptLoader:', error);\r\n });\r\n\r\n // Initialize UserManager with projectId (startup)\r\n this.initializeUserManager().catch((error) => {\r\n logger.error('Failed to initialize UserManager:', error);\r\n });\r\n\r\n // Initialize DashboardManager\r\n this.initializeDashboardManager();\r\n\r\n // Initialize ReportManager\r\n this.initializeReportManager();\r\n\r\n // Note: Connection is not automatic - call connect() explicitly when ready\r\n }\r\n\r\n /**\r\n * Initialize PromptLoader and load prompts into memory\r\n * Tries to load from file system first, then falls back to hardcoded prompts\r\n */\r\n private async initializePromptLoader(promptsDir?: string): Promise<void> {\r\n try {\r\n // Set custom prompts directory if provided\r\n if (promptsDir) {\r\n promptLoader.setPromptsDir(promptsDir);\r\n }\r\n\r\n await promptLoader.initialize();\r\n logger.info(`PromptLoader initialized with ${promptLoader.getCacheSize()} prompts from ${promptLoader.getPromptsDir()}`);\r\n } catch (error) {\r\n logger.error('Failed to initialize PromptLoader:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Initialize UserManager for the project\r\n */\r\n private async initializeUserManager(): Promise<void> {\r\n try {\r\n await this.userManager.init();\r\n // Set the global reference for backward compatibility with existing auth code\r\n setUserManager(this.userManager);\r\n logger.info(`UserManager initialized for project: ${this.projectId}`);\r\n } catch (error) {\r\n logger.error('Failed to initialize UserManager:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Get the UserManager instance for this SDK\r\n */\r\n public getUserManager(): UserManager {\r\n return this.userManager;\r\n }\r\n\r\n /**\r\n * Initialize DashboardManager for the project\r\n */\r\n private initializeDashboardManager(): void {\r\n // Set the global reference for dashboard operations\r\n setDashboardManager(this.dashboardManager);\r\n logger.info(`DashboardManager initialized for project: ${this.projectId}`);\r\n }\r\n\r\n /**\r\n * Get the DashboardManager instance for this SDK\r\n */\r\n public getDashboardManager(): DashboardManager {\r\n return this.dashboardManager;\r\n }\r\n\r\n /**\r\n * Initialize ReportManager for the project\r\n */\r\n private initializeReportManager(): void {\r\n // Set the global reference for report operations\r\n setReportManager(this.reportManager);\r\n logger.info(`ReportManager initialized for project: ${this.projectId}`);\r\n }\r\n\r\n /**\r\n * Get the ReportManager instance for this SDK\r\n */\r\n public getReportManager(): ReportManager {\r\n return this.reportManager;\r\n }\r\n\r\n /**\r\n * Connect to the Superatom WebSocket service\r\n */\r\n async connect(): Promise<void> {\r\n // If already connected, return immediately\r\n if (this.connected && this.ws && this.ws.readyState === this.ws.OPEN) {\r\n logger.info('Already connected to WebSocket');\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n // Add all required query parameters\r\n const url = new URL(this.url);\r\n url.searchParams.set('apiKey', this.apiKey);\r\n url.searchParams.set('projectId', this.projectId);\r\n url.searchParams.set('userId', this.userId);\r\n url.searchParams.set('type', this.type);\r\n\r\n logger.info(`Connecting to WebSocket: ${url.toString()}`);\r\n\r\n this.ws = createWebSocket(url.toString());\r\n\r\n this.ws.addEventListener('open', () => {\r\n this.connected = true;\r\n this.reconnectAttempts = 0;\r\n logger.info('WebSocket connected successfully');\r\n resolve();\r\n });\r\n\r\n this.ws.addEventListener('message', (event: any) => {\r\n this.handleMessage(event.data);\r\n });\r\n\r\n this.ws.addEventListener('error', (error: any) => {\r\n logger.error('WebSocket error:', error);\r\n reject(error);\r\n });\r\n\r\n this.ws.addEventListener('close', () => {\r\n this.connected = false;\r\n logger.warn('WebSocket closed');\r\n this.handleReconnect();\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Handle incoming WebSocket messages\r\n */\r\n private handleMessage(data: string): void {\r\n try {\r\n const parsed = JSON.parse(data);\r\n const message = IncomingMessageSchema.parse(parsed);\r\n\r\n logger.debug('Received message:', message.type);\r\n\r\n // Route message by type\r\n switch (message.type) {\r\n case 'DATA_REQ':\r\n handleDataRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {\r\n logger.error('Failed to handle data request:', error);\r\n });\r\n break;\r\n\r\n case 'BUNDLE_REQ':\r\n handleBundleRequest(parsed, this.bundleDir, (msg) => this.send(msg)).catch((error) => {\r\n logger.error('Failed to handle bundle request:', error);\r\n });\r\n break;\r\n\r\n case 'AUTH_LOGIN_REQ':\r\n handleAuthLoginRequest(parsed, (msg) => this.send(msg)).catch((error) => {\r\n logger.error('Failed to handle auth login request:', error);\r\n });\r\n break;\r\n\r\n case 'AUTH_VERIFY_REQ':\r\n handleAuthVerifyRequest(parsed, (msg) => this.send(msg)).catch((error) => {\r\n logger.error('Failed to handle auth verify request:', error);\r\n });\r\n break;\r\n\r\n case 'USER_PROMPT_REQ':\r\n handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections).catch((error) => {\r\n logger.error('Failed to handle user prompt request:', error);\r\n });\r\n break;\r\n\r\n case 'ACTIONS':\r\n handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders).catch((error) => {\r\n logger.error('Failed to handle actions request:', error);\r\n });\r\n break;\r\n\r\n case 'USER_PROMPT_SUGGESTIONS_REQ':\r\n handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg)).catch((error) => {\r\n logger.error('Failed to handle user prompt suggestions request:', error);\r\n });\r\n break;\r\n\r\n case 'COMPONENT_LIST_RES':\r\n handleComponentListResponse(parsed, (com) => this.storeComponents(com)).catch((error) => {\r\n logger.error('Failed to handle component list request:', error);\r\n });\r\n break;\r\n\r\n case 'USERS':\r\n handleUsersRequest(parsed, (msg) => this.send(msg)).catch((error) => {\r\n logger.error('Failed to handle users request:', error);\r\n });\r\n break;\r\n\r\n case 'DASHBOARDS':\r\n handleDashboardsRequest(parsed, (msg) => this.send(msg)).catch((error) => {\r\n logger.error('Failed to handle dashboards request:', error);\r\n });\r\n break;\r\n\r\n case 'REPORTS':\r\n handleReportsRequest(parsed, (msg) => this.send(msg)).catch((error) => {\r\n logger.error('Failed to handle reports request:', error);\r\n });\r\n break;\r\n\r\n default:\r\n // Check for custom message type handlers\r\n const handler = this.messageTypeHandlers.get(message.type);\r\n if (handler) {\r\n Promise.resolve(handler(message)).catch((error) => {\r\n logger.error(`Failed to handle ${message.type}:`, error);\r\n });\r\n }\r\n break;\r\n }\r\n\r\n // Call registered message handlers\r\n this.messageHandlers.forEach((handler) => {\r\n handler(message);\r\n });\r\n } catch (error) {\r\n logger.error('Failed to parse incoming message:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Send a message to the Superatom service\r\n */\r\n send(message: Message): void {\r\n if (!this.ws || !this.connected) {\r\n throw new Error('WebSocket is not connected. Call connect() first.');\r\n }\r\n\r\n if (this.ws.readyState !== this.ws.OPEN) {\r\n throw new Error('WebSocket is not ready to send messages.');\r\n }\r\n\r\n const payload = JSON.stringify(message);\r\n this.ws.send(payload);\r\n }\r\n\r\n /**\r\n * Register a message handler to receive all messages\r\n */\r\n onMessage(handler: (message: IncomingMessage) => void): () => void {\r\n const id = Math.random().toString(36).substring(7);\r\n this.messageHandlers.set(id, handler);\r\n\r\n // Return unsubscribe function\r\n return () => {\r\n this.messageHandlers.delete(id);\r\n };\r\n }\r\n\r\n /**\r\n * Register a handler for a specific message type\r\n */\r\n onMessageType(type: string, handler: MessageTypeHandler): () => void {\r\n this.messageTypeHandlers.set(type, handler);\r\n\r\n // Return unsubscribe function\r\n return () => {\r\n this.messageTypeHandlers.delete(type);\r\n };\r\n }\r\n\r\n /**\r\n * Disconnect from the WebSocket service\r\n */\r\n disconnect(): void {\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n this.connected = false;\r\n }\r\n }\r\n\r\n /**\r\n * Cleanup and disconnect - stops reconnection attempts and closes the connection\r\n */\r\n async destroy(): Promise<void> {\r\n // Prevent further reconnection attempts\r\n this.maxReconnectAttempts = 0;\r\n this.reconnectAttempts = 0;\r\n\r\n // Clear all message handlers\r\n this.messageHandlers.clear();\r\n\r\n // Clear all collections\r\n this.collections = {};\r\n\r\n // Cleanup UserManager\r\n try {\r\n await cleanupUserStorage();\r\n logger.info('UserManager cleanup completed');\r\n } catch (error) {\r\n logger.error('Error during UserManager cleanup:', error);\r\n }\r\n\r\n // Disconnect\r\n this.disconnect();\r\n }\r\n\r\n /**\r\n * Check if the SDK is currently connected\r\n */\r\n isConnected(): boolean {\r\n return this.connected && this.ws !== null && this.ws.readyState === this.ws.OPEN;\r\n }\r\n\r\n /**\r\n * Register a collection handler for data operations\r\n */\r\n addCollection<TParams = any, TResult = any>(\r\n collectionName: string,\r\n operation: CollectionOperation | string,\r\n handler: CollectionHandler<TParams, TResult>\r\n ): void {\r\n if (!this.collections[collectionName]) {\r\n this.collections[collectionName] = {};\r\n }\r\n this.collections[collectionName][operation] = handler;\r\n }\r\n\r\n private handleReconnect(): void {\r\n if (this.reconnectAttempts < this.maxReconnectAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 10000);\r\n\r\n setTimeout(() => {\r\n logger.info(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);\r\n this.connect().catch((error) => {\r\n logger.error('Reconnection failed:', error);\r\n });\r\n }, delay);\r\n } else {\r\n logger.error('Max reconnection attempts reached');\r\n }\r\n }\r\n\r\n private storeComponents(components: Component[]){\r\n this.components = components;\r\n }\r\n \r\n}\r\n\r\n// Export types\r\nexport type { Message, IncomingMessage, SuperatomSDKConfig, CollectionHandler, CollectionOperation, User, UsersData } from './types';\r\nexport {LLM} from './llm';\r\nexport { UserManager } from './auth/user-manager';\r\nexport { UILogCollector, type CapturedLog } from './utils/log-collector';\r\nexport { Thread, UIBlock, ThreadManager, type Action } from './threads';\r\nexport { CleanupService } from './services/cleanup-service';\r\nexport { STORAGE_CONFIG } from './config/storage';\r\nexport { CONTEXT_CONFIG } from './config/context';\r\nexport { logger, type LogLevel } from './utils/logger';","import WebSocket from 'ws';\r\nimport type { WebSocketLike } from './types';\r\n\r\n/**\r\n * Creates a WebSocket instance for Node.js using the ws package\r\n */\r\nexport function createWebSocket(url: string): WebSocketLike {\r\n return new WebSocket(url) as WebSocketLike;\r\n}\r\n","import { z } from 'zod';\r\n\r\n// User schema for authentication and management\r\nexport const UserSchema = z.object({\r\n username: z.string().min(1, 'Username is required'),\r\n email: z.string().email('Invalid email format').optional(),\r\n password: z.string().min(1, 'Password is required'),\r\n fullname: z.string().optional(),\r\n role: z.string().optional(),\r\n wsIds: z.array(z.string()).optional(), // Only in memory, not persisted to file\r\n});\r\n\r\nexport type User = z.infer<typeof UserSchema>;\r\n\r\nexport const UsersDataSchema = z.object({\r\n users: z.array(UserSchema),\r\n});\r\n\r\nexport type UsersData = z.infer<typeof UsersDataSchema>;\r\n\r\n// From/To object schema for WebSocket messages\r\nexport const MessageParticipantSchema = z.object({\r\n id: z.string().optional(),\r\n type: z.string().optional(),\r\n});\r\n\r\nexport type MessageParticipant = z.infer<typeof MessageParticipantSchema>;\r\n\r\n// Message schemas for WebSocket communication\r\nexport const MessageSchema = z.object({\r\n id: z.string().optional(),\r\n type: z.string(),\r\n from: MessageParticipantSchema,\r\n to: MessageParticipantSchema.optional(),\r\n payload: z.unknown(),\r\n});\r\n\r\nexport type Message = z.infer<typeof MessageSchema>;\r\n\r\nexport const IncomingMessageSchema = z.object({\r\n id: z.string().optional(),\r\n type: z.string(),\r\n from: MessageParticipantSchema,\r\n to: MessageParticipantSchema.optional(),\r\n payload: z.unknown(),\r\n});\r\n\r\nexport type IncomingMessage = z.infer<typeof IncomingMessageSchema>;\r\n\r\n// Data request/response schemas\r\nexport const DataRequestPayloadSchema = z.object({\r\n collection: z.string(),\r\n op: z.string(),\r\n params: z.record(z.unknown()).optional(),\r\n SA_RUNTIME: z.record(z.unknown()).optional(),\r\n});\r\n\r\nexport type DataRequestPayload = z.infer<typeof DataRequestPayloadSchema>;\r\n\r\nexport const DataRequestMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('DATA_REQ'),\r\n payload: DataRequestPayloadSchema,\r\n});\r\n\r\nexport type DataRequestMessage = z.infer<typeof DataRequestMessageSchema>;\r\n\r\nexport const AuthLoginRequestPayloadSchema = z.object({\r\n login_data: z.string(),\r\n});\r\n\r\nexport type AuthLoginRequestPayload = z.infer<typeof AuthLoginRequestPayloadSchema>;\r\n\r\nexport const AuthLoginRequestMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('AUTH_LOGIN_REQ'),\r\n payload: AuthLoginRequestPayloadSchema,\r\n});\r\n\r\nexport type AuthLoginRequestMessage = z.infer<typeof AuthLoginRequestMessageSchema>;\r\n\r\nexport const AuthVerifyRequestPayloadSchema = z.object({\r\n token: z.string(),\r\n});\r\n\r\nexport type AuthVerifyRequestPayload = z.infer<typeof AuthVerifyRequestPayloadSchema>;\r\n\r\nexport const AuthVerifyRequestMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('AUTH_VERIFY_REQ'),\r\n payload: AuthVerifyRequestPayloadSchema,\r\n});\r\n\r\nexport type AuthVerifyRequestMessage = z.infer<typeof AuthVerifyRequestMessageSchema>;\r\n\r\nexport const UserPromptRequestPayloadSchema = z.object({\r\n prompt: z.string(),\r\n SA_RUNTIME: z.object({\r\n threadId: z.string(),\r\n uiBlockId: z.string(),\r\n }).optional(),\r\n responseMode: z.enum(['component', 'text']).optional(),\r\n});\r\n\r\nexport type UserPromptRequestPayload = z.infer<typeof UserPromptRequestPayloadSchema>;\r\n\r\nexport const UserPromptRequestMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('USER_PROMPT_REQ'),\r\n payload: UserPromptRequestPayloadSchema,\r\n});\r\n\r\nexport type UserPromptRequestMessage = z.infer<typeof UserPromptRequestMessageSchema>;\r\n\r\nexport const UserPromptSuggestionsPayloadSchema = z.object({\r\n prompt: z.string(),\r\n limit: z.number().int().positive().default(5),\r\n});\r\n\r\nexport type UserPromptSuggestionsPayload = z.infer<typeof UserPromptSuggestionsPayloadSchema>;\r\n\r\nexport const UserPromptSuggestionsMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('USER_PROMPT_SUGGESTIONS_REQ'),\r\n payload: UserPromptSuggestionsPayloadSchema,\r\n});\r\n\r\nexport type UserPromptSuggestionsMessage = z.infer<typeof UserPromptSuggestionsMessageSchema>;\r\n\r\n\r\nexport const ComponentPropsSchema = z.object({\r\n query: z.string().or(z.object({})).optional(),\r\n title: z.string().optional(),\r\n description: z.string().optional(),\r\n config: z.record(z.unknown()).optional(),\r\n actions: z.array(z.any()).optional(),\r\n});\r\n\r\nexport const ComponentSchema = z.object({\r\n id: z.string(),\r\n name: z.string(),\r\n type: z.string(),\r\n description: z.string(),\r\n props: ComponentPropsSchema,\r\n category: z.string().optional(),\r\n keywords: z.array(z.string()).optional(),\r\n});\r\n\r\nexport const ComponentsSchema = z.array(ComponentSchema);\r\n\r\nexport type Component = z.infer<typeof ComponentSchema>;\r\n\r\nexport const ComponentListResponsePayloadSchema = z.object({\r\n components: z.array(ComponentSchema),\r\n});\r\n\r\nexport type ComponentListResponsePayload = z.infer<typeof ComponentListResponsePayloadSchema>; \r\n\r\nexport const ComponentListResponseMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('COMPONENT_LIST_RES'),\r\n payload: ComponentListResponsePayloadSchema,\r\n});\r\n\r\nexport type ComponentListResponseMessage = z.infer<typeof ComponentListResponseMessageSchema>;\r\n\r\n// Admin User Management Request/Response schemas (Unified)\r\nexport const UsersRequestPayloadSchema = z.object({\r\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne']),\r\n data: z.object({\r\n username: z.string().optional(),\r\n email: z.string().email('Invalid email format').optional(),\r\n password: z.string().optional(),\r\n fullname: z.string().optional(),\r\n role: z.string().optional(),\r\n }).optional(),\r\n});\r\n\r\nexport type UsersRequestPayload = z.infer<typeof UsersRequestPayloadSchema>;\r\n\r\nexport const UsersRequestMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('USERS'),\r\n payload: UsersRequestPayloadSchema,\r\n});\r\n\r\nexport type UsersRequestMessage = z.infer<typeof UsersRequestMessageSchema>;\r\n\r\n// UI Logs schema for tracking user request execution\r\nexport const UILogsPayloadSchema = z.object({\r\n logs: z.array(z.object({\r\n timestamp: z.number(),\r\n level: z.enum(['info', 'error', 'warn', 'debug']),\r\n message: z.string(),\r\n type: z.enum(['explanation', 'query', 'general']).optional(),\r\n data: z.record(z.unknown()).optional(),\r\n })),\r\n});\r\n\r\nexport type UILogsPayload = z.infer<typeof UILogsPayloadSchema>;\r\n\r\nexport const UILogsMessageSchema = z.object({\r\n id: z.string(), // uiBlockId\r\n from: MessageParticipantSchema,\r\n type: z.literal('UI_LOGS'),\r\n payload: UILogsPayloadSchema,\r\n});\r\n\r\nexport type UILogsMessage = z.infer<typeof UILogsMessageSchema>;\r\n\r\n// Actions request schema - for runtime to send component actions and request next questions\r\nexport const ActionsRequestPayloadSchema = z.object({\r\n SA_RUNTIME: z.object({\r\n threadId: z.string(),\r\n uiBlockId: z.string(),\r\n }).optional(),\r\n});\r\n\r\nexport type ActionsRequestPayload = z.infer<typeof ActionsRequestPayloadSchema>;\r\n\r\nexport const ActionsRequestMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('ACTIONS'),\r\n payload: ActionsRequestPayloadSchema,\r\n});\r\n\r\nexport type ActionsRequestMessage = z.infer<typeof ActionsRequestMessageSchema>;\r\n\r\n// Collection operation types\r\nexport type CollectionOperation =\r\n | 'getMany'\r\n | 'getOne'\r\n | 'query'\r\n | 'mutation'\r\n | 'updateOne'\r\n | 'deleteOne'\r\n | 'createOne';\r\n\r\nexport type CollectionHandler<TParams = any, TResult = any> = (\r\n params: TParams\r\n) => Promise<TResult> | TResult;\r\n\r\nexport interface CollectionRegistry {\r\n [collectionName: string]: {\r\n [operation: string]: CollectionHandler;\r\n };\r\n}\r\n\r\nexport type LLMProvider = 'anthropic' | 'groq';\r\n\r\nimport type { LogLevel } from './utils/logger';\r\n\r\nexport interface SuperatomSDKConfig {\r\n url?: string;\r\n apiKey: string;\r\n projectId: string;\r\n userId?: string;\r\n type?: string;\r\n bundleDir?: string;\r\n promptsDir?: string; // Path to custom prompts directory (defaults to .prompts in SDK)\r\n ANTHROPIC_API_KEY?: string;\r\n GROQ_API_KEY?: string;\r\n LLM_PROVIDERS?: LLMProvider[];\r\n logLevel?: LogLevel; // Log level for SDK logging (errors, warnings, info, verbose)\r\n}\r\n\r\n// ==================== Dashboard CRUD Message Schemas ====================\r\n\r\n// Import DSL types from dashboards module\r\nimport { DSLRendererPropsSchema } from './dashboards/types';\r\nexport type { DSLRendererProps } from './dashboards/types';\r\n\r\n// Dashboard CRUD request payload\r\n\r\nexport const DashboardsRequestPayloadSchema = z.object({\r\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne']),\r\n data: z.object({\r\n dashboardId: z.string().optional(),\r\n dashboard: DSLRendererPropsSchema.optional(),\r\n }).optional(),\r\n});\r\n\r\nexport type DashboardsRequestPayload = z.infer<typeof DashboardsRequestPayloadSchema>;\r\n\r\nexport const DashboardsRequestMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('DASHBOARDS'),\r\n payload: DashboardsRequestPayloadSchema,\r\n});\r\n\r\nexport type DashboardsRequestMessage = z.infer<typeof DashboardsRequestMessageSchema>;\r\n\r\n// ==================== Report CRUD Message Schemas ====================\r\n\r\n// Import DSL types from reports module\r\nimport { DSLRendererPropsSchema as ReportDSLRendererPropsSchema } from './reports/types';\r\nexport type { DSLRendererProps as ReportDSLRendererProps } from './reports/types';\r\n\r\n// Report CRUD request payload\r\nexport const ReportsRequestPayloadSchema = z.object({\r\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne']),\r\n data: z.object({\r\n reportId: z.string().optional(),\r\n report: ReportDSLRendererPropsSchema.optional(),\r\n }).optional(),\r\n});\r\n\r\nexport type ReportsRequestPayload = z.infer<typeof ReportsRequestPayloadSchema>;\r\n\r\nexport const ReportsRequestMessageSchema = z.object({\r\n id: z.string(),\r\n from: MessageParticipantSchema,\r\n type: z.literal('REPORTS'),\r\n payload: ReportsRequestPayloadSchema,\r\n});\r\n\r\nexport type ReportsRequestMessage = z.infer<typeof ReportsRequestMessageSchema>;\r\n\r\n// ==================== Response Types ====================\r\n\r\n// Standard response format for LLM operations\r\nexport interface T_RESPONSE {\r\n success: boolean;\r\n data?: any;\r\n errors: string[];\r\n}\r\n\r\nexport interface WebSocketLike {\r\n send(data: string): void;\r\n close(): void;\r\n addEventListener(event: string, listener: (event: any) => void): void;\r\n removeEventListener(event: string, listener: (event: any) => void): void;\r\n readyState: number;\r\n CONNECTING: number;\r\n OPEN: number;\r\n CLOSING: number;\r\n CLOSED: number;\r\n}\r\n\r\n","import { z } from 'zod';\r\n\r\n// ==================== Dashboard DSL Schemas ====================\r\n\r\n// Expression schema for dynamic values\r\nexport const ExpressionSchema = z.object({\r\n $exp: z.string(),\r\n $deps: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type Expression = z.infer<typeof ExpressionSchema>;\r\n\r\n// Binding schema for data binding\r\nexport const BindingSchema = z.object({\r\n $bind: z.string(),\r\n $transform: z\r\n .array(\r\n z.object({\r\n name: z.string(),\r\n args: z.array(z.any()).optional(),\r\n }),\r\n )\r\n .optional(),\r\n});\r\n\r\nexport type Binding = z.infer<typeof BindingSchema>;\r\n\r\n// For directive schema\r\nexport const ForDirectiveSchema = z.object({\r\n in: z.union([ExpressionSchema, BindingSchema, z.string()]),\r\n as: z.string(),\r\n key: z.string().optional(),\r\n index: z.string().optional(),\r\n});\r\n\r\nexport type ForDirective = z.infer<typeof ForDirectiveSchema>;\r\n\r\n// Query specification schema\r\nexport const QuerySpecSchema = z.object({\r\n graphql: z.string().optional(),\r\n sql: z.string().optional(),\r\n variables: z.record(z.string(), z.any()).optional(),\r\n params: z.record(z.string(), z.any()).optional(),\r\n key: z.string().optional(),\r\n refetchPolicy: z\r\n .enum(['cache-first', 'network-only', 'cache-and-network'])\r\n .optional(),\r\n dependencies: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type QuerySpec = z.infer<typeof QuerySpecSchema>;\r\n\r\n// UI Element schema\r\nexport const UIElementSchema: z.ZodType<any> = z.lazy(() =>\r\n z.object({\r\n id: z.string(),\r\n type: z.string(),\r\n key: z.union([z.string(), ExpressionSchema]).optional(),\r\n props: z.record(z.string(), z.any()).optional(),\r\n query: QuerySpecSchema.optional(),\r\n if: ExpressionSchema.optional(),\r\n elseIf: ExpressionSchema.optional(),\r\n for: ForDirectiveSchema.optional(),\r\n 'link-to': z\r\n .union([\r\n z.string(),\r\n ExpressionSchema,\r\n BindingSchema,\r\n z.object({\r\n ui: z.union([z.string(), ExpressionSchema, BindingSchema]),\r\n params: z.record(z.string(), z.any()).optional(),\r\n }),\r\n ])\r\n .optional(),\r\n _meta: z\r\n .object({\r\n id: z.string().optional(),\r\n version: z.string().optional(),\r\n created: z.string().optional(),\r\n lastModified: z.string().optional(),\r\n })\r\n .optional(),\r\n children: z.any().optional(),\r\n else: UIElementSchema.optional(),\r\n slots: z\r\n .record(z.string(), z.union([UIElementSchema, z.array(UIElementSchema)]))\r\n .optional(),\r\n platform: z\r\n .object({\r\n web: z.any().optional(),\r\n ios: z.any().optional(),\r\n android: z.any().optional(),\r\n })\r\n .optional(),\r\n })\r\n);\r\n\r\nexport type UIElement = z.infer<typeof UIElementSchema>;\r\n\r\n// UI Component schema\r\nexport const UIComponentSchema = z.object({\r\n id: z.string(),\r\n name: z.string().optional(),\r\n props: z.record(z.string(), z.any()).optional(),\r\n states: z.record(z.string(), z.any()).optional(),\r\n methods: z\r\n .record(\r\n z.string(),\r\n z.object({\r\n fn: z.string(),\r\n params: z.record(z.string(), z.any()).optional(),\r\n }),\r\n )\r\n .optional(),\r\n effects: z\r\n .array(\r\n z.object({\r\n fn: z.string(),\r\n deps: z.array(z.string()).optional(),\r\n }),\r\n )\r\n .optional(),\r\n data: z.record(z.string(), z.any()).optional(),\r\n render: UIElementSchema,\r\n query: QuerySpecSchema.optional(),\r\n});\r\n\r\nexport type UIComponent = z.infer<typeof UIComponentSchema>;\r\n\r\n// DSL Renderer Props schema\r\nexport const DSLRendererPropsSchema = z.object({\r\n dsl: UIComponentSchema,\r\n data: z.record(z.string(), z.any()).optional(),\r\n context: z.record(z.string(), z.any()).optional(),\r\n});\r\n\r\nexport type DSLRendererProps = z.infer<typeof DSLRendererPropsSchema>;\r\n","import { z } from 'zod';\r\n\r\n// ==================== Report DSL Schemas ====================\r\n\r\n// Expression schema for dynamic values\r\nexport const ExpressionSchema = z.object({\r\n $exp: z.string(),\r\n $deps: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type Expression = z.infer<typeof ExpressionSchema>;\r\n\r\n// Binding schema for data binding\r\nexport const BindingSchema = z.object({\r\n $bind: z.string(),\r\n $transform: z\r\n .array(\r\n z.object({\r\n name: z.string(),\r\n args: z.array(z.any()).optional(),\r\n }),\r\n )\r\n .optional(),\r\n});\r\n\r\nexport type Binding = z.infer<typeof BindingSchema>;\r\n\r\n// For directive schema\r\nexport const ForDirectiveSchema = z.object({\r\n in: z.union([ExpressionSchema, BindingSchema, z.string()]),\r\n as: z.string(),\r\n key: z.string().optional(),\r\n index: z.string().optional(),\r\n});\r\n\r\nexport type ForDirective = z.infer<typeof ForDirectiveSchema>;\r\n\r\n// Query specification schema\r\nexport const QuerySpecSchema = z.object({\r\n graphql: z.string().optional(),\r\n sql: z.string().optional(),\r\n variables: z.record(z.string(), z.any()).optional(),\r\n params: z.record(z.string(), z.any()).optional(),\r\n key: z.string().optional(),\r\n refetchPolicy: z\r\n .enum(['cache-first', 'network-only', 'cache-and-network'])\r\n .optional(),\r\n dependencies: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type QuerySpec = z.infer<typeof QuerySpecSchema>;\r\n\r\n// UI Element schema\r\nexport const UIElementSchema: z.ZodType<any> = z.lazy(() =>\r\n z.object({\r\n id: z.string(),\r\n type: z.string(),\r\n key: z.union([z.string(), ExpressionSchema]).optional(),\r\n props: z.record(z.string(), z.any()).optional(),\r\n query: QuerySpecSchema.optional(),\r\n if: ExpressionSchema.optional(),\r\n elseIf: ExpressionSchema.optional(),\r\n for: ForDirectiveSchema.optional(),\r\n 'link-to': z\r\n .union([\r\n z.string(),\r\n ExpressionSchema,\r\n BindingSchema,\r\n z.object({\r\n ui: z.union([z.string(), ExpressionSchema, BindingSchema]),\r\n params: z.record(z.string(), z.any()).optional(),\r\n }),\r\n ])\r\n .optional(),\r\n _meta: z\r\n .object({\r\n id: z.string().optional(),\r\n version: z.string().optional(),\r\n created: z.string().optional(),\r\n lastModified: z.string().optional(),\r\n })\r\n .optional(),\r\n children: z.any().optional(),\r\n else: UIElementSchema.optional(),\r\n slots: z\r\n .record(z.string(), z.union([UIElementSchema, z.array(UIElementSchema)]))\r\n .optional(),\r\n platform: z\r\n .object({\r\n web: z.any().optional(),\r\n ios: z.any().optional(),\r\n android: z.any().optional(),\r\n })\r\n .optional(),\r\n })\r\n);\r\n\r\nexport type UIElement = z.infer<typeof UIElementSchema>;\r\n\r\n// UI Component schema\r\nexport const UIComponentSchema = z.object({\r\n id: z.string(),\r\n name: z.string().optional(),\r\n props: z.record(z.string(), z.any()).optional(),\r\n states: z.record(z.string(), z.any()).optional(),\r\n methods: z\r\n .record(\r\n z.string(),\r\n z.object({\r\n fn: z.string(),\r\n params: z.record(z.string(), z.any()).optional(),\r\n }),\r\n )\r\n .optional(),\r\n effects: z\r\n .array(\r\n z.object({\r\n fn: z.string(),\r\n deps: z.array(z.string()).optional(),\r\n }),\r\n )\r\n .optional(),\r\n data: z.record(z.string(), z.any()).optional(),\r\n render: UIElementSchema,\r\n query: QuerySpecSchema.optional(),\r\n});\r\n\r\nexport type UIComponent = z.infer<typeof UIComponentSchema>;\r\n\r\n// DSL Renderer Props schema\r\nexport const DSLRendererPropsSchema = z.object({\r\n dsl: UIComponentSchema,\r\n data: z.record(z.string(), z.any()).optional(),\r\n context: z.record(z.string(), z.any()).optional(),\r\n});\r\n\r\nexport type DSLRendererProps = z.infer<typeof DSLRendererPropsSchema>;\r\n","import fs from 'fs';\r\nconst PREFIX = '[SuperatomSDK]';\r\n\r\n/**\r\n * Log levels in hierarchical order\r\n * - errors: only error logs\r\n * - warnings: warning + error logs\r\n * - info: info + warning + error logs\r\n * - verbose: all logs including debug\r\n */\r\nexport type LogLevel = 'errors' | 'warnings' | 'info' | 'verbose';\r\n\r\n// open a file in stream write mode. if no file is specified then create it.\r\nconst LOGSTREAM = fs.createWriteStream('superatom-sdk.log', { flags: 'a' });\r\n\r\n/**\r\n * Internal log level hierarchy mapping\r\n */\r\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\r\n errors: 0,\r\n warnings: 1,\r\n info: 2,\r\n verbose: 3,\r\n};\r\n\r\nconst MESSAGE_LEVEL_PRIORITY: Record<'error' | 'warn' | 'info' | 'debug', number> = {\r\n error: 0,\r\n warn: 1,\r\n info: 2,\r\n debug: 3,\r\n};\r\n\r\n/**\r\n * Logger class with environment-based log level support\r\n */\r\nclass Logger {\r\n private currentLevel: LogLevel;\r\n private currentLevelPriority: number;\r\n\r\n constructor() {\r\n // Read log level from environment variable, default to 'info'\r\n const envLevel = (process.env.SUPERATOM_LOG_LEVEL || 'info').toLowerCase();\r\n\r\n // Validate and set log level\r\n if (this.isValidLogLevel(envLevel)) {\r\n this.currentLevel = envLevel as LogLevel;\r\n } else {\r\n this.currentLevel = 'info';\r\n console.warn(\r\n `${PREFIX} Invalid log level \"${envLevel}\". Using default \"info\". Valid levels: errors, warnings, info, verbose`\r\n );\r\n }\r\n\r\n this.currentLevelPriority = LOG_LEVEL_PRIORITY[this.currentLevel];\r\n }\r\n\r\n /**\r\n * Check if a string is a valid log level\r\n */\r\n private isValidLogLevel(level: string): level is LogLevel {\r\n return level === 'errors' || level === 'warnings' || level === 'info' || level === 'verbose';\r\n }\r\n\r\n /**\r\n * Check if a message should be logged based on current log level\r\n */\r\n private shouldLog(messageLevel: 'error' | 'warn' | 'info' | 'debug'): boolean {\r\n const messagePriority = MESSAGE_LEVEL_PRIORITY[messageLevel];\r\n return messagePriority <= this.currentLevelPriority;\r\n }\r\n\r\n /**\r\n * Get current log level\r\n */\r\n getLogLevel(): LogLevel {\r\n return this.currentLevel;\r\n }\r\n\r\n /**\r\n * Set log level programmatically\r\n */\r\n setLogLevel(level: LogLevel): void {\r\n this.currentLevel = level;\r\n this.currentLevelPriority = LOG_LEVEL_PRIORITY[level];\r\n }\r\n\r\n /**\r\n * Log info message (shown for info and verbose levels)\r\n */\r\n info(...args: any[]): void {\r\n if (this.shouldLog('info')) {\r\n console.log(PREFIX, ...args);\r\n }\r\n }\r\n\r\n /**\r\n * Log error message (shown for all levels)\r\n */\r\n error(...args: any[]): void {\r\n if (this.shouldLog('error')) {\r\n console.error(PREFIX, ...args);\r\n }\r\n }\r\n\r\n /**\r\n * Log warning message (shown for warnings, info, and verbose levels)\r\n */\r\n warn(...args: any[]): void {\r\n if (this.shouldLog('warn')) {\r\n console.warn(PREFIX, ...args);\r\n }\r\n }\r\n\r\n /**\r\n * Log debug message (only shown for verbose level)\r\n */\r\n debug(...args: any[]): void {\r\n if (this.shouldLog('debug')) {\r\n console.log(PREFIX, '[DEBUG]', ...args);\r\n }\r\n }\r\n\r\n file(...args: any[]): void {\r\n LOGSTREAM.write(args.join(' ') + '\\n');\r\n }\r\n}\r\n\r\n// Export singleton instance\r\nexport const logger = new Logger();\r\n","import { randomUUID } from 'crypto';\r\nimport { logger } from '../utils/logger';\r\nimport { STORAGE_CONFIG } from '../config/storage';\r\nimport { Action } from './action';\r\n\r\n/**\r\n * UIBlock represents a single user and assistant message block in a thread\r\n * Contains user question, component metadata, component data, text response, and available actions\r\n */\r\nexport class UIBlock {\r\n private id: string;\r\n private userQuestion: string;\r\n private generatedComponentMetadata: Record<string, any>;\r\n private componentData: Record<string, any>;\r\n private textResponse: string | null;\r\n private actions: Action[] | null | Promise<Action[]>;\r\n private createdAt: Date;\r\n\r\n /**\r\n * Creates a new UIBlock instance\r\n * @param userQuestion - The user's question or input\r\n * @param componentData - The component data object\r\n * @param generatedComponentMetadata - Optional metadata about the generated component\r\n * @param actions - Optional array of available actions\r\n * @param id - Optional custom ID, generates UUID if not provided\r\n * @param textResponse - Optional text response from LLM\r\n */\r\n constructor(\r\n userQuestion: string,\r\n componentData: Record<string, any> = {},\r\n generatedComponentMetadata: Record<string, any> = {},\r\n actions: Action[] = [],\r\n id?: string,\r\n textResponse: string | null = null\r\n ) {\r\n this.id = id || randomUUID();\r\n this.userQuestion = userQuestion;\r\n this.componentData = componentData;\r\n this.generatedComponentMetadata = generatedComponentMetadata;\r\n this.actions = actions;\r\n this.textResponse = textResponse;\r\n this.createdAt = new Date();\r\n }\r\n\r\n /**\r\n * Get the UIBlock ID\r\n */\r\n getId(): string {\r\n return this.id;\r\n }\r\n\r\n /**\r\n * Get the user question\r\n */\r\n getUserQuestion(): string {\r\n return this.userQuestion;\r\n }\r\n\r\n /**\r\n * Set or update the user question\r\n */\r\n setUserQuestion(question: string): void {\r\n this.userQuestion = question;\r\n }\r\n\r\n /**\r\n * Get component metadata\r\n */\r\n getComponentMetadata(): Record<string, any> {\r\n return this.generatedComponentMetadata;\r\n }\r\n\r\n getTextResponse(): string {\r\n return this.textResponse || '';\r\n }\r\n\r\n /**\r\n * Set or update component metadata\r\n */\r\n setComponentMetadata(metadata: Record<string, any>): void {\r\n this.generatedComponentMetadata = { ...this.generatedComponentMetadata, ...metadata };\r\n }\r\n\r\n /**\r\n * Get component data\r\n */\r\n getComponentData(): Record<string, any> {\r\n return this.componentData;\r\n }\r\n\r\n /**\r\n * Calculate size of data in bytes\r\n */\r\n private getDataSizeInBytes(data: any): number {\r\n try {\r\n const jsonString = JSON.stringify(data);\r\n return Buffer.byteLength(jsonString, 'utf8');\r\n } catch (error) {\r\n logger.error('Error calculating data size:', error);\r\n return 0;\r\n }\r\n }\r\n\r\n /**\r\n * Limit array data to maximum rows\r\n */\r\n private limitArrayData(data: any[]): { data: any[]; metadata: any } {\r\n const totalRows = data.length;\r\n const limitedData = data.slice(0, STORAGE_CONFIG.MAX_ROWS_PER_BLOCK);\r\n\r\n return {\r\n data: limitedData,\r\n metadata: {\r\n totalRows,\r\n storedRows: limitedData.length,\r\n isTruncated: totalRows > STORAGE_CONFIG.MAX_ROWS_PER_BLOCK,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Check if data exceeds size limit\r\n */\r\n private exceedsSizeLimit(data: any): boolean {\r\n const size = this.getDataSizeInBytes(data);\r\n return size > STORAGE_CONFIG.MAX_SIZE_PER_BLOCK_BYTES;\r\n }\r\n\r\n /**\r\n * Process and limit data before storing\r\n */\r\n private processDataForStorage(data: any): any {\r\n // If data is an array, limit rows\r\n if (Array.isArray(data)) {\r\n const { data: limitedData, metadata } = this.limitArrayData(data);\r\n\r\n // Check size after limiting rows\r\n const size = this.getDataSizeInBytes(limitedData);\r\n\r\n logger.info(\r\n `UIBlock ${this.id}: Storing ${metadata.storedRows}/${metadata.totalRows} rows (${(size / 1024).toFixed(2)} KB)`\r\n );\r\n\r\n // If still too large, store only metadata\r\n if (this.exceedsSizeLimit(limitedData)) {\r\n logger.warn(\r\n `UIBlock ${this.id}: Data too large (${(size / 1024 / 1024).toFixed(2)} MB), storing metadata only`\r\n );\r\n return {\r\n ...metadata,\r\n preview: limitedData.slice(0, 3), // Store only first 3 rows as preview\r\n dataTooLarge: true,\r\n };\r\n }\r\n\r\n return {\r\n data: limitedData,\r\n ...metadata,\r\n };\r\n }\r\n\r\n // For non-array data, check size\r\n const size = this.getDataSizeInBytes(data);\r\n\r\n if (this.exceedsSizeLimit(data)) {\r\n logger.warn(\r\n `UIBlock ${this.id}: Data too large (${(size / 1024 / 1024).toFixed(2)} MB), storing summary only`\r\n );\r\n return {\r\n dataTooLarge: true,\r\n dataType: typeof data,\r\n keys: typeof data === 'object' ? Object.keys(data) : undefined,\r\n };\r\n }\r\n\r\n return data;\r\n }\r\n\r\n /**\r\n * Set or update component data with size and row limits\r\n */\r\n setComponentData(data: Record<string, any>): void {\r\n const processedData = this.processDataForStorage(data);\r\n this.componentData = { ...this.componentData, ...processedData };\r\n }\r\n\r\n\r\n\r\n /**\r\n * Set or update text response\r\n */\r\n setTextResponse(textResponse: string | null): void {\r\n this.textResponse = textResponse;\r\n }\r\n\r\n /**\r\n * Get all actions (only if they are resolved, not if fetching)\r\n */\r\n getActions(): Action[] | null | Promise<Action[]> {\r\n return this.actions;\r\n }\r\n\r\n /**\r\n * Get or fetch actions\r\n * If actions don't exist or are a Promise, calls the generateFn and stores the promise\r\n * If actions already exist, returns them\r\n * @param generateFn - Async function to generate actions\r\n * @returns Promise resolving to Action[]\r\n */\r\n async getOrFetchActions(generateFn: () => Promise<Action[]>): Promise<Action[]> {\r\n // If actions already exist and are not a Promise, return them\r\n\r\n if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions) && this.actions.length > 0) {\r\n return this.actions;\r\n }\r\n\r\n // If already fetching, cancel and start new fetch\r\n // Set new promise for fetching\r\n const fetchPromise = generateFn();\r\n this.actions = fetchPromise;\r\n\r\n try {\r\n // Wait for the promise to resolve\r\n const resolvedActions = await fetchPromise;\r\n // Store the resolved actions\r\n logger.info(`Fetched ${resolvedActions.length} actions for UIBlock: ${this.id}`);\r\n this.actions = resolvedActions;\r\n return resolvedActions;\r\n } catch (error) {\r\n // If generation fails, reset to null\r\n this.actions = null;\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Set or replace all actions\r\n */\r\n setActions(actions: Action[]): void {\r\n this.actions = actions;\r\n }\r\n\r\n /**\r\n * Add a single action (only if actions are resolved)\r\n */\r\n addAction(action: Action): void {\r\n if (this.actions && Array.isArray(this.actions)) {\r\n this.actions.push(action);\r\n }\r\n }\r\n\r\n /**\r\n * Add multiple actions (only if actions are resolved)\r\n */\r\n addActions(actions: Action[]): void {\r\n if (this.actions && Array.isArray(this.actions)) {\r\n this.actions.push(...actions);\r\n }\r\n }\r\n\r\n /**\r\n * Remove an action by ID (only if actions are resolved)\r\n */\r\n removeAction(actionId: string): boolean {\r\n if (this.actions && Array.isArray(this.actions)) {\r\n const index = this.actions.findIndex(a => a.id === actionId);\r\n if (index > -1) {\r\n this.actions.splice(index, 1);\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Clear all actions\r\n */\r\n clearActions(): void {\r\n this.actions = null;\r\n }\r\n\r\n /**\r\n * Get creation timestamp\r\n */\r\n getCreatedAt(): Date {\r\n return this.createdAt;\r\n }\r\n\r\n /**\r\n * Convert UIBlock to JSON-serializable object\r\n */\r\n toJSON(): Record<string, any> {\r\n // Handle Promise case for serialization\r\n let actionsValue: Action[] | null = null;\r\n if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions)) {\r\n actionsValue = this.actions;\r\n }\r\n\r\n return {\r\n id: this.id,\r\n userQuestion: this.userQuestion,\r\n generatedComponentMetadata: this.generatedComponentMetadata,\r\n componentData: this.componentData,\r\n textResponse: this.textResponse,\r\n actions: actionsValue,\r\n isFetchingActions: this.actions instanceof Promise,\r\n createdAt: this.createdAt.toISOString(),\r\n };\r\n }\r\n}\r\n","/**\r\n * Configuration for data storage limits in UIBlocks\r\n */\r\nexport const STORAGE_CONFIG = {\r\n /**\r\n * Maximum number of rows to store in UIBlock data\r\n */\r\n MAX_ROWS_PER_BLOCK: 10,\r\n\r\n /**\r\n * Maximum size in bytes per UIBlock (1MB)\r\n */\r\n MAX_SIZE_PER_BLOCK_BYTES: 1 * 1024 * 1024, // 1MB\r\n\r\n /**\r\n * Number of days to keep threads before cleanup\r\n */\r\n THREAD_RETENTION_DAYS: 7,\r\n\r\n /**\r\n * Number of days to keep UIBlocks before cleanup\r\n */\r\n UIBLOCK_RETENTION_DAYS: 7,\r\n};\r\n","import { randomUUID } from 'crypto';\r\nimport { UIBlock } from './uiblock';\r\n\r\n/**\r\n * Thread represents a conversation thread containing multiple UIBlocks\r\n * Each UIBlock in a thread represents a user question and assistant response pair\r\n */\r\nexport class Thread {\r\n private id: string;\r\n private uiblocks: Map<string, UIBlock>;\r\n private createdAt: Date;\r\n\r\n /**\r\n * Creates a new Thread instance\r\n * @param id - Optional custom ID, generates UUID if not provided\r\n */\r\n constructor(id?: string) {\r\n this.id = id || randomUUID();\r\n this.uiblocks = new Map();\r\n this.createdAt = new Date();\r\n }\r\n\r\n /**\r\n * Get the thread ID\r\n */\r\n getId(): string {\r\n return this.id;\r\n }\r\n\r\n /**\r\n * Add a UIBlock to the thread\r\n */\r\n addUIBlock(uiblock: UIBlock): void {\r\n this.uiblocks.set(uiblock.getId(), uiblock);\r\n }\r\n\r\n /**\r\n * Get a UIBlock by ID\r\n */\r\n getUIBlock(id: string): UIBlock | undefined {\r\n return this.uiblocks.get(id);\r\n }\r\n\r\n /**\r\n * Get all UIBlocks in the thread\r\n */\r\n getUIBlocks(): UIBlock[] {\r\n return Array.from(this.uiblocks.values());\r\n }\r\n\r\n /**\r\n * Get UIBlocks as a Map\r\n */\r\n getUIBlocksMap(): Map<string, UIBlock> {\r\n return new Map(this.uiblocks);\r\n }\r\n\r\n /**\r\n * Remove a UIBlock by ID\r\n */\r\n removeUIBlock(id: string): boolean {\r\n return this.uiblocks.delete(id);\r\n }\r\n\r\n /**\r\n * Check if UIBlock exists\r\n */\r\n hasUIBlock(id: string): boolean {\r\n return this.uiblocks.has(id);\r\n }\r\n\r\n /**\r\n * Get number of UIBlocks in the thread\r\n */\r\n getUIBlockCount(): number {\r\n return this.uiblocks.size;\r\n }\r\n\r\n /**\r\n * Clear all UIBlocks from the thread\r\n */\r\n clear(): void {\r\n this.uiblocks.clear();\r\n }\r\n\r\n /**\r\n * Get creation timestamp\r\n */\r\n getCreatedAt(): Date {\r\n return this.createdAt;\r\n }\r\n\r\n /**\r\n * Get conversation context from recent UIBlocks (excluding current one)\r\n * Returns formatted string with previous questions and component summaries\r\n * @param limit - Maximum number of previous UIBlocks to include (default: 5)\r\n * @param currentUIBlockId - ID of current UIBlock to exclude from context (optional)\r\n * @returns Formatted conversation history string\r\n */\r\n getConversationContext(limit: number = 5, currentUIBlockId?: string): string {\r\n if (limit === 0) {\r\n return '';\r\n }\r\n\r\n // Get all UIBlocks sorted by creation time (oldest first)\r\n const allBlocks = Array.from(this.uiblocks.values())\r\n .filter(block => !currentUIBlockId || block.getId() !== currentUIBlockId)\r\n .sort((a, b) => a.getCreatedAt().getTime() - b.getCreatedAt().getTime());\r\n\r\n if (allBlocks.length === 0) {\r\n return '';\r\n }\r\n\r\n // Take the last N blocks (most recent)\r\n const recentBlocks = allBlocks.slice(-limit);\r\n\r\n // Format as conversation history\r\n const contextLines: string[] = [];\r\n\r\n recentBlocks.forEach((block, index) => {\r\n const questionNum = index + 1;\r\n const question = block.getUserQuestion();\r\n const metadata = block.getComponentMetadata();\r\n const textResponse = block.getTextResponse();\r\n\r\n // Determine what was generated and build appropriate response\r\n let assistantResponse = '';\r\n\r\n // Check if component was generated (metadata exists and has meaningful content)\r\n const hasComponent = metadata && Object.keys(metadata).length > 0 && metadata.type;\r\n\r\n // Check if text response was generated\r\n const hasTextResponse = textResponse && textResponse.trim().length > 0;\r\n\r\n if (hasComponent) {\r\n // Component was generated - show component summary\r\n const parts: string[] = [];\r\n\r\n if (metadata.type) {\r\n parts.push(`Component Type: ${metadata.type}`);\r\n }\r\n if (metadata.name) {\r\n parts.push(`Name: ${metadata.name}`);\r\n }\r\n if (metadata.props?.title) {\r\n parts.push(`Title: \"${metadata.props.title}\"`);\r\n }\r\n if (metadata.props?.query) {\r\n // Truncate long queries\r\n const query = metadata.props.query;\r\n const truncatedQuery = query.length > 200 ? query.substring(0, 200) + '...' : query;\r\n parts.push(`Query: ${truncatedQuery}`);\r\n }\r\n if (metadata.props?.config?.components && Array.isArray(metadata.props.config.components)) {\r\n // Multi-component container\r\n const componentTypes = metadata.props.config.components.map((c: any) => c.type).join(', ');\r\n parts.push(`Multi-component with: ${componentTypes}`);\r\n }\r\n\r\n assistantResponse = parts.join(', ');\r\n } else if (hasTextResponse) {\r\n // Text response was generated - show full text response\r\n assistantResponse = textResponse;\r\n } else {\r\n // Nothing was generated\r\n assistantResponse = 'No response generated';\r\n }\r\n\r\n contextLines.push(`User:\\n ${question}`);\r\n contextLines.push(`Assistant:\\n ${assistantResponse}`);\r\n contextLines.push('---'); // Empty line for readability\r\n });\r\n\r\n return contextLines.join('\\n').trim();\r\n }\r\n\r\n /**\r\n * Convert Thread to JSON-serializable object\r\n */\r\n toJSON(): Record<string, any> {\r\n return {\r\n id: this.id,\r\n uiblocks: Array.from(this.uiblocks.values()).map(block => block.toJSON()),\r\n createdAt: this.createdAt.toISOString(),\r\n };\r\n }\r\n}\r\n","import { Thread } from './thread';\r\nimport { UIBlock } from './uiblock';\r\n\r\n/**\r\n * ThreadManager manages all threads globally\r\n * Provides methods to create, retrieve, and delete threads\r\n */\r\nexport class ThreadManager {\r\n private static instance: ThreadManager;\r\n private threads: Map<string, Thread>;\r\n\r\n private constructor() {\r\n this.threads = new Map();\r\n\r\n // Initialize cleanup service\r\n // new CleanupService(this.threads);\r\n }\r\n\r\n /**\r\n * Get singleton instance of ThreadManager\r\n */\r\n static getInstance(): ThreadManager {\r\n if (!ThreadManager.instance) {\r\n ThreadManager.instance = new ThreadManager();\r\n }\r\n return ThreadManager.instance;\r\n }\r\n\r\n /**\r\n * Create a new thread\r\n * @param id - Optional custom ID, generates UUID if not provided\r\n * @returns The created Thread instance\r\n */\r\n createThread(id?: string): Thread {\r\n const thread = new Thread(id);\r\n this.threads.set(thread.getId(), thread);\r\n return thread;\r\n }\r\n\r\n /**\r\n * Get a thread by ID\r\n */\r\n getThread(id: string): Thread | undefined {\r\n return this.threads.get(id);\r\n }\r\n\r\n /**\r\n * Get all threads\r\n */\r\n getAllThreads(): Thread[] {\r\n return Array.from(this.threads.values());\r\n }\r\n\r\n /**\r\n * Get threads as a Map\r\n */\r\n getThreadsMap(): Map<string, Thread> {\r\n return new Map(this.threads);\r\n }\r\n\r\n /**\r\n * Delete a thread by ID\r\n */\r\n deleteThread(id: string): boolean {\r\n return this.threads.delete(id);\r\n }\r\n\r\n /**\r\n * Check if thread exists\r\n */\r\n hasThread(id: string): boolean {\r\n return this.threads.has(id);\r\n }\r\n\r\n /**\r\n * Get number of threads\r\n */\r\n getThreadCount(): number {\r\n return this.threads.size;\r\n }\r\n\r\n /**\r\n * Clear all threads\r\n */\r\n clearAll(): void {\r\n this.threads.clear();\r\n }\r\n\r\n /**\r\n * Find a UIBlock by ID across all threads\r\n * @param uiBlockId - The UIBlock ID to search for\r\n * @returns Object with thread and uiBlock if found, undefined otherwise\r\n */\r\n findUIBlockById(uiBlockId: string): { thread: Thread; uiBlock: UIBlock } | undefined {\r\n for (const thread of this.threads.values()) {\r\n const uiBlock = thread.getUIBlock(uiBlockId);\r\n if (uiBlock) {\r\n return { thread, uiBlock };\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Convert all threads to JSON-serializable object\r\n */\r\n toJSON(): Record<string, any> {\r\n return {\r\n threads: Array.from(this.threads.values()).map(thread => thread.toJSON()),\r\n count: this.threads.size,\r\n };\r\n }\r\n}\r\n","import { DataRequestMessageSchema, type CollectionRegistry, type Message } from '../types';\r\nimport { logger } from '../utils/logger';\r\nimport { ThreadManager } from '../threads';\r\n\r\n/**\r\n * Handle incoming data_req messages and execute collection handlers\r\n */\r\nexport async function handleDataRequest(\r\n data: any,\r\n collections: CollectionRegistry,\r\n sendMessage: (message: Message) => void\r\n): Promise<void> {\r\n try {\r\n const dataRequest = DataRequestMessageSchema.parse(data);\r\n const { id, payload } = dataRequest;\r\n const { collection, op, params, SA_RUNTIME } = payload;\r\n\r\n // Check if collection and operation exist\r\n if (!collections[collection]) {\r\n sendDataResponse(id, collection, op, null, {\r\n error: `Collection '${collection}' not found`,\r\n }, sendMessage);\r\n return;\r\n }\r\n\r\n if (!collections[collection][op]) {\r\n sendDataResponse(id, collection, op, null, {\r\n error: `Operation '${op}' not found for collection '${collection}'`,\r\n }, sendMessage);\r\n return;\r\n }\r\n\r\n // Execute the handler and measure execution time\r\n const startTime = performance.now();\r\n const handler = collections[collection][op];\r\n const result = await handler(params || {});\r\n const executionMs = Math.round(performance.now() - startTime);\r\n\r\n logger.info(`Executed ${collection}.${op} in ${executionMs}ms`);\r\n\r\n // Update UIBlock with component data if SA_RUNTIME has uiBlockId\r\n if (SA_RUNTIME && typeof SA_RUNTIME === 'object' && 'uiBlockId' in SA_RUNTIME) {\r\n const uiBlockId = (SA_RUNTIME as any).uiBlockId;\r\n const threadId = (SA_RUNTIME as any).threadId;\r\n\r\n const threadManager = ThreadManager.getInstance();\r\n let uiBlock = null;\r\n let thread = null;\r\n\r\n // If threadId is provided, get the specific thread\r\n if (threadId) {\r\n thread = threadManager.getThread(threadId);\r\n if (thread) {\r\n uiBlock = thread.getUIBlock(uiBlockId);\r\n }\r\n } else {\r\n // Otherwise search across all threads\r\n const result = threadManager.findUIBlockById(uiBlockId);\r\n if (result) {\r\n thread = result.thread;\r\n uiBlock = result.uiBlock;\r\n }\r\n }\r\n\r\n // Update UIBlock's componentData with the response\r\n if (uiBlock) {\r\n uiBlock.setComponentData(result || {});\r\n logger.info(`Updated UIBlock ${uiBlockId} with component data from ${collection}.${op}`);\r\n } else {\r\n logger.warn(`UIBlock ${uiBlockId} not found in threads`);\r\n }\r\n }\r\n\r\n // Send response\r\n sendDataResponse(id, collection, op, result, { executionMs }, sendMessage);\r\n } catch (error) {\r\n logger.error('Failed to handle data request:', error);\r\n // Not a data_req message or invalid format\r\n }\r\n}\r\n\r\n/**\r\n * Send a data_res response message\r\n */\r\nfunction sendDataResponse(\r\n id: string,\r\n collection: string,\r\n op: string,\r\n data: any,\r\n meta: { executionMs?: number; error?: string },\r\n sendMessage: (message: Message) => void\r\n): void {\r\n const response: Message = {\r\n id,\r\n from: { type: 'data-agent' },\r\n type: 'DATA_RES',\r\n payload: {\r\n collection,\r\n op,\r\n data,\r\n ...meta,\r\n },\r\n };\r\n\r\n sendMessage(response);\r\n}\r\n","import * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport { logger } from './utils/logger';\r\n\r\n/**\r\n * Get the bundle directory from config or environment variable\r\n */\r\nexport function getBundleDir(configDir?: string): string {\r\n const bundleDir = configDir || process.env.SA_BUNDLE_DIR;\r\n\r\n if (!bundleDir) {\r\n throw new Error(\r\n 'Bundle directory not configured. Please provide bundleDir in config or set SA_BUNDLE_DIR environment variable.'\r\n );\r\n }\r\n\r\n return bundleDir;\r\n}\r\n\r\n/**\r\n * Load the JavaScript bundle from the configured directory\r\n */\r\nexport function getJS(bundleDir: string): string {\r\n try {\r\n // Check if directory exists\r\n if (!fs.existsSync(bundleDir)) {\r\n throw new Error(`Bundle directory does not exist: ${bundleDir}`);\r\n }\r\n\r\n // Check if it's actually a directory\r\n const stats = fs.statSync(bundleDir);\r\n if (!stats.isDirectory()) {\r\n throw new Error(`Bundle path is not a directory: ${bundleDir}`);\r\n }\r\n\r\n // Read directory contents\r\n let files: string[];\r\n try {\r\n files = fs.readdirSync(bundleDir);\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n throw new Error(`Failed to read bundle directory: ${errorMessage}`);\r\n }\r\n\r\n // Find the bundle file\r\n const indexFile = files.find((file) => file.startsWith('index-') && file.endsWith('.js'));\r\n\r\n if (!indexFile) {\r\n logger.warn(`Available files in ${bundleDir}:`, files);\r\n throw new Error(\r\n `Could not find index-*.js file in ${bundleDir}. ` +\r\n `Expected a file matching pattern: index-*.js`\r\n );\r\n }\r\n\r\n // Read the bundle file\r\n const filePath = path.join(bundleDir, indexFile);\r\n logger.info(`Loading bundle from ${filePath}`);\r\n\r\n try {\r\n return fs.readFileSync(filePath, 'utf8');\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n throw new Error(`Failed to read bundle file: ${errorMessage}`);\r\n }\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error('Failed to load bundle:', error.message);\r\n } else {\r\n logger.error('Failed to load bundle:', error);\r\n }\r\n throw error;\r\n }\r\n}\r\n","import { getJS, getBundleDir } from '../bundle';\r\nimport { logger } from '../utils/logger';\r\nimport type { Message } from '../types';\r\n\r\nconst CHUNK_SIZE = 900 * 1024; // 900 KB chunks (leaving room for metadata, max 1MB per message)\r\n\r\n/**\r\n * Handle incoming bundle_req messages and send chunked bundle response\r\n */\r\nexport async function handleBundleRequest(\r\n data: any,\r\n bundleDir: string | undefined,\r\n sendMessage: (message: Message) => void\r\n): Promise<void> {\r\n try {\r\n const id = data.id || 'unknown';\r\n const fromId = data.from?.id;\r\n\r\n // Get bundle directory and load bundle\r\n const dir = getBundleDir(bundleDir);\r\n const js = getJS(dir);\r\n const bundleSize = Buffer.byteLength(js, 'utf8');\r\n\r\n logger.info(`Bundle size: ${(bundleSize / 1024).toFixed(2)} KB`);\r\n\r\n // Split bundle into chunks\r\n const totalChunks = Math.ceil(bundleSize / CHUNK_SIZE);\r\n logger.info(`Splitting bundle into ${totalChunks} chunks`);\r\n\r\n for (let i = 0; i < totalChunks; i++) {\r\n const start = i * CHUNK_SIZE;\r\n const end = Math.min(start + CHUNK_SIZE, js.length);\r\n const chunk = js.substring(start, end);\r\n const isComplete = i === totalChunks - 1;\r\n const progress = ((i + 1) / totalChunks) * 100;\r\n\r\n const chunkMessage: Message = {\r\n id: `${id}-chunk-${i}`,\r\n type: 'BUNDLE_CHUNK',\r\n from: { type: 'data-agent' },\r\n to: fromId ? { id: fromId } : undefined,\r\n payload: {\r\n chunk: chunk,\r\n chunkIndex: i,\r\n totalChunks: totalChunks,\r\n isComplete: isComplete,\r\n progress: parseFloat(progress.toFixed(2)),\r\n },\r\n };\r\n\r\n sendMessage(chunkMessage);\r\n logger.debug(`Sent chunk ${i + 1}/${totalChunks} (${progress.toFixed(2)}%)`);\r\n }\r\n\r\n logger.info('Bundle sending complete');\r\n } catch (error) {\r\n logger.error('Failed to handle bundle request:', error);\r\n\r\n // Send error response\r\n const errorMessage: Message = {\r\n id: data.id || 'unknown',\r\n type: 'BUNDLE_RES',\r\n from: { type: 'data-agent' },\r\n to: data.from?.id ? { id: data.from.id } : undefined,\r\n payload: {\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n },\r\n };\r\n\r\n sendMessage(errorMessage);\r\n }\r\n}\r\n","import crypto from 'crypto';\r\n\r\n/**\r\n * Decode base64 encoded string and parse JSON\r\n * @param base64Data - Base64 encoded string\r\n * @returns Parsed JSON object\r\n */\r\nexport function decodeBase64ToJson(base64Data: string): any {\r\n try {\r\n const decodedString = Buffer.from(base64Data, 'base64').toString('utf-8');\r\n return JSON.parse(decodedString);\r\n } catch (error) {\r\n throw new Error(`Failed to decode base64 data: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n }\r\n}\r\n\r\n/**\r\n * Hash password using SHA1\r\n * @param password - Plain text password\r\n * @returns SHA1 hashed password\r\n */\r\nexport function hashPassword(password: string): string {\r\n return crypto.createHash('sha1').update(password).digest('hex');\r\n}\r\n","import { UserManager } from './user-manager';\r\nimport { type User, type UsersData } from '../types';\r\nimport { logger } from '../utils/logger';\r\n\r\n// Global reference to the current SDK's UserManager instance\r\nlet currentUserManager: UserManager | null = null;\r\n\r\n/**\r\n * Set the UserManager instance (called by SuperatomSDK during initialization)\r\n * This should be called with the SDK's UserManager instance\r\n * @param userManager - UserManager instance from SuperatomSDK\r\n */\r\nexport function setUserManager(userManager: UserManager): void {\r\n if (!userManager) {\r\n throw new Error('userManager cannot be null');\r\n }\r\n currentUserManager = userManager;\r\n logger.debug('UserManager instance set');\r\n}\r\n\r\n/**\r\n * Get the current UserManager instance\r\n */\r\nexport function getUserManager(): UserManager {\r\n if (!currentUserManager) {\r\n throw new Error(\r\n 'UserManager not initialized. Make sure SuperatomSDK is initialized before using user storage.'\r\n );\r\n }\r\n return currentUserManager;\r\n}\r\n\r\n/**\r\n * Load users from memory (UserManager maintains the cache)\r\n * @returns UsersData object containing all users\r\n */\r\nexport function loadUsers(): UsersData {\r\n const manager = getUserManager();\r\n return {\r\n users: manager.getAllUsers()\r\n };\r\n}\r\n\r\n/**\r\n * Save users to file immediately (forces sync)\r\n * @param usersData - UsersData object to save\r\n */\r\nexport async function saveUsers(usersData: UsersData): Promise<void> {\r\n const manager = getUserManager();\r\n\r\n // Clear existing users and repopulate\r\n manager.deleteAllUsers();\r\n\r\n // Add all users from the provided data\r\n for (const user of usersData.users) {\r\n try {\r\n manager.createUser(user);\r\n } catch (error) {\r\n // User might already exist, update instead\r\n if (manager.userExists(user.username)) {\r\n manager.updateUser(user.username, user);\r\n }\r\n }\r\n }\r\n\r\n // Force immediate sync to file\r\n await manager.forceSync();\r\n}\r\n\r\n/**\r\n * Find a user by username\r\n * @param username - Username to search for\r\n * @returns User object if found, null otherwise\r\n */\r\nexport function findUserByUsername(username: string): User | null {\r\n const manager = getUserManager();\r\n const user = manager.getUser(username);\r\n return user || null;\r\n}\r\n\r\n/**\r\n * Find a user by email\r\n * @param email - Email to search for\r\n * @returns User object if found, null otherwise\r\n */\r\nexport function findUserByEmail(email: string): User | null {\r\n const manager = getUserManager();\r\n const user = manager.getUserByEmail(email);\r\n return user || null;\r\n}\r\n\r\n/**\r\n * Find a user by username or email\r\n * @param identifier - Username or email to search for\r\n * @returns User object if found, null otherwise\r\n */\r\nexport function findUserByUsernameOrEmail(identifier: string): User | null {\r\n const manager = getUserManager();\r\n const user = manager.getUserByUsernameOrEmail(identifier);\r\n return user || null;\r\n}\r\n\r\n/**\r\n * Add WebSocket ID to a user's wsIds array\r\n * @param username - Username to update\r\n * @param wsId - WebSocket ID to add\r\n * @returns true if successful, false otherwise\r\n */\r\nexport function addWsIdToUser(username: string, wsId: string): boolean {\r\n try {\r\n const manager = getUserManager();\r\n return manager.addWsId(username, wsId);\r\n } catch (error) {\r\n logger.error('Error adding WebSocket ID:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Remove WebSocket ID from a user's wsIds array\r\n * @param username - Username to update\r\n * @param wsId - WebSocket ID to remove\r\n * @returns true if successful, false otherwise\r\n */\r\nexport function removeWsIdFromUser(username: string, wsId: string): boolean {\r\n try {\r\n const manager = getUserManager();\r\n return manager.removeWsId(username, wsId);\r\n } catch (error) {\r\n logger.error('Error removing WebSocket ID:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Cleanup and destroy the UserManager\r\n */\r\nexport async function cleanupUserStorage(): Promise<void> {\r\n if (currentUserManager) {\r\n await currentUserManager.destroy();\r\n currentUserManager = null;\r\n logger.info('UserManager cleaned up');\r\n }\r\n}\r\n\r\n// Export types\r\nexport type { User, UsersData } from '../types';\r\n","import { findUserByUsernameOrEmail, addWsIdToUser } from \"./user-storage\";\r\nimport { hashPassword } from \"./utils\";\r\nimport { logger } from \"../utils/logger\";\r\n\r\nexport interface LoginCredentials {\r\n username?: string;\r\n email?: string;\r\n password: string;\r\n}\r\n\r\nexport interface ValidationResult {\r\n success: boolean;\r\n error?: string;\r\n data?: any;\r\n username?: string;\r\n}\r\n\r\n/**\r\n * Validate user credentials against stored user data\r\n * @param credentials - Login credentials with username/email and password\r\n * @returns ValidationResult indicating success or failure\r\n */\r\nexport function validateUser(credentials: LoginCredentials): ValidationResult {\r\n const { username, email, password } = credentials;\r\n const identifier = username || email;\r\n\r\n logger.debug('[validateUser] Starting user validation');\r\n logger.debug(`[validateUser] Username provided: ${username ? '✓' : '✗'}, Email provided: ${email ? '✓' : '✗'}, Password provided: ${password ? '✓' : '✗'}`);\r\n\r\n // Check if identifier (username or email) and password are provided\r\n if (!identifier || !password) {\r\n logger.warn('[validateUser] Validation failed: Username/email and password are required');\r\n return {\r\n success: false,\r\n error: 'Username or email and password are required'\r\n };\r\n }\r\n\r\n // Find user by username or email from in-memory cache\r\n logger.debug(`[validateUser] Looking up user by identifier: ${identifier}`);\r\n const user = findUserByUsernameOrEmail(identifier);\r\n\r\n if (!user) {\r\n logger.warn(`[validateUser] Validation failed: User not found - ${identifier}`);\r\n return {\r\n success: false,\r\n error: 'Invalid username or email'\r\n };\r\n }\r\n\r\n logger.debug(`[validateUser] User found: ${user.username}, verifying password`);\r\n\r\n // Hash the stored password and compare with provided password\r\n const hashedPassword = hashPassword(user.password);\r\n\r\n if (hashedPassword !== password) {\r\n logger.warn(`[validateUser] Validation failed: Invalid password for user - ${user.username}`);\r\n logger.debug(`[validateUser] Password hash mismatch for user: ${user.username}`);\r\n return {\r\n success: false,\r\n error: 'Invalid password'\r\n };\r\n }\r\n\r\n logger.info(`[validateUser] ✓ User validated successfully: ${user.username}`);\r\n logger.debug(`[validateUser] Returning user data for: ${user.username}`);\r\n return {\r\n success: true,\r\n data: user.username,\r\n username: user.username\r\n };\r\n}\r\n\r\n/**\r\n * Authenticate user and store WebSocket ID\r\n * Uses UserManager's in-memory cache with automatic file sync\r\n * @param credentials - Login credentials\r\n * @param wsId - WebSocket ID to store\r\n * @returns ValidationResult with authentication status\r\n */\r\nexport function authenticateAndStoreWsId(credentials: LoginCredentials, wsId: string): ValidationResult {\r\n const identifier = credentials.username || credentials.email;\r\n logger.debug('[authenticateAndStoreWsId] Starting authentication and WebSocket ID storage');\r\n\r\n // Validate user credentials first\r\n logger.debug('[authenticateAndStoreWsId] Validating user credentials');\r\n const validationResult = validateUser(credentials);\r\n\r\n if (!validationResult.success) {\r\n logger.warn(`[authenticateAndStoreWsId] User validation failed for: ${identifier}`);\r\n return validationResult;\r\n }\r\n\r\n // Use the username from validation result (guaranteed to exist if validation succeeded)\r\n const username = validationResult.username!;\r\n logger.info(`[authenticateAndStoreWsId] User ${username} validated, storing WebSocket ID`);\r\n\r\n // Store wsId in user's wsIds array using UserManager\r\n // Changes are automatically synced to file via setInterval\r\n logger.debug(`[authenticateAndStoreWsId] Calling addWsIdToUser for ${username}`);\r\n addWsIdToUser(username, wsId);\r\n\r\n logger.debug(`[authenticateAndStoreWsId] WebSocket ID ${wsId} associated with user ${username}`);\r\n return validationResult;\r\n}\r\n\r\n/**\r\n * Verify authentication token\r\n * @param authToken - Base64 encoded auth token containing username and password\r\n * @returns ValidationResult indicating if token is valid\r\n */\r\nexport function verifyAuthToken(authToken: string): ValidationResult {\r\n try {\r\n logger.debug('[verifyAuthToken] Starting token verification');\r\n\r\n // Decode base64 token\r\n logger.debug('[verifyAuthToken] Decoding base64 token');\r\n const decodedString = Buffer.from(authToken, 'base64').toString('utf-8');\r\n\r\n logger.debug('[verifyAuthToken] Parsing decoded token as JSON');\r\n const credentials = JSON.parse(decodedString);\r\n\r\n logger.debug('[verifyAuthToken] Token decoded and parsed successfully');\r\n logger.debug(`[verifyAuthToken] Token contains username: ${credentials.username ? '✓' : '✗'}`);\r\n\r\n // Validate credentials\r\n logger.debug('[verifyAuthToken] Validating credentials from token');\r\n const result = validateUser(credentials);\r\n\r\n if (result.success) {\r\n logger.info(`[verifyAuthToken] ✓ Token verified successfully for user: ${credentials.username || 'unknown'}`);\r\n } else {\r\n logger.warn(`[verifyAuthToken] Token verification failed: ${result.error}`);\r\n }\r\n\r\n return result;\r\n } catch (error) {\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n logger.error(`[verifyAuthToken] Failed to verify auth token: ${errorMsg}`);\r\n logger.debug('[verifyAuthToken] Token verification error details:', error);\r\n\r\n return {\r\n success: false,\r\n error: 'Invalid token format'\r\n };\r\n }\r\n}\r\n","import { decodeBase64ToJson } from \"../auth/utils\";\r\nimport { authenticateAndStoreWsId } from \"../auth/validator\";\r\nimport { AuthLoginRequestMessageSchema, Message } from \"../types\";\r\nimport { logger } from \"../utils/logger\";\r\n\r\n\r\n\r\nexport async function handleAuthLoginRequest(\r\n data: any,\r\n sendMessage: (message: Message) => void\r\n): Promise<void> {\r\n try {\r\n logger.debug('[AUTH_LOGIN_REQ] Parsing incoming auth login request');\r\n const authRequest = AuthLoginRequestMessageSchema.parse(data);\r\n const { id, payload } = authRequest;\r\n\r\n const login_data = payload.login_data;\r\n\r\n const wsId = authRequest.from.id ;\r\n\r\n logger.info(`[AUTH_LOGIN_REQ ${id}] Processing auth login request from client: ${wsId}`);\r\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Login data present: ${!!login_data}`);\r\n\r\n if(!login_data){\r\n logger.error(`[AUTH_LOGIN_REQ ${id}] Login data not found in request`);\r\n sendDataResponse(id, {\r\n success: false,\r\n error: 'Login data not found'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n\r\n // Decode base64 data and parse JSON\r\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Decoding base64 login data`);\r\n let loginData: any;\r\n try {\r\n loginData = decodeBase64ToJson(login_data);\r\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Login data decoded successfully`);\r\n } catch (error) {\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n logger.error(`[AUTH_LOGIN_REQ ${id}] Failed to decode login data: ${errorMsg}`);\r\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Decode error details:`, error);\r\n sendDataResponse(id, {\r\n success: false,\r\n error: 'Invalid login data format'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n // Extract username/email and password from decoded data\r\n const { username, email, password } = loginData;\r\n const identifier = username || email;\r\n\r\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Validating credentials - username: ${username ? '✓' : '✗'}, email: ${email ? '✓' : '✗'}, password: ${password ? '✓' : '✗'}`);\r\n\r\n if (!identifier) {\r\n logger.error(`[AUTH_LOGIN_REQ ${id}] Username or email not found in login data`);\r\n sendDataResponse(id, {\r\n success: false,\r\n error: 'Username or email is required'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n if (!password) {\r\n logger.error(`[AUTH_LOGIN_REQ ${id}] Password not found in login data`);\r\n sendDataResponse(id, {\r\n success: false,\r\n error: 'Password not found in login data'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n\r\n if(!wsId){\r\n logger.error(`[AUTH_LOGIN_REQ ${id}] WebSocket ID not found in request`);\r\n sendDataResponse(id, {\r\n success: false,\r\n error: 'WebSocket ID not found'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n logger.info(`[AUTH_LOGIN_REQ ${id}] Credentials validated, authenticating user: ${identifier}`);\r\n logger.debug(`[AUTH_LOGIN_REQ ${id}] WebSocket ID: ${wsId}`);\r\n\r\n // Authenticate user and store wsId\r\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Calling authenticateAndStoreWsId for user: ${identifier}`);\r\n const authResult = authenticateAndStoreWsId(\r\n { username, email, password },\r\n wsId\r\n );\r\n\r\n logger.info(`[AUTH_LOGIN_REQ ${id}] Authentication result for ${identifier}: ${authResult.success ? 'success' : 'failed'}`);\r\n if (!authResult.success) {\r\n logger.warn(`[AUTH_LOGIN_REQ ${id}] Authentication failed for ${identifier}: ${authResult.error}`);\r\n } else {\r\n logger.info(`[AUTH_LOGIN_REQ ${id}] User ${authResult.username || identifier} authenticated successfully`);\r\n }\r\n\r\n // Send response\r\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Sending auth response to client`);\r\n sendDataResponse(id, authResult, sendMessage, wsId);\r\n\r\n logger.info(`[AUTH_LOGIN_REQ ${id}] ${authResult.success ? '✓' : '✗'} Auth login request completed`);\r\n return ;\r\n }\r\n catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\r\n const errorStack = error instanceof Error ? error.stack : undefined;\r\n\r\n logger.error(`[AUTH_LOGIN_REQ] Failed to handle auth login request: ${errorMessage}`);\r\n logger.debug(`[AUTH_LOGIN_REQ] Error stack trace:`, errorStack);\r\n\r\n // Try to send error response\r\n try {\r\n const parsedData = data as any;\r\n if (parsedData?.id) {\r\n sendDataResponse(parsedData.id, {\r\n success: false,\r\n error: `Internal error: ${errorMessage}`\r\n }, sendMessage, parsedData.from?.id);\r\n }\r\n } catch (sendError) {\r\n logger.error('[AUTH_LOGIN_REQ] Failed to send error response:', sendError);\r\n }\r\n }\r\n}\r\n\r\n\r\n/**\r\n * Send a data_res response message\r\n */\r\nfunction sendDataResponse(\r\n id: string,\r\n res: {success: boolean; error?: string; data?: any},\r\n sendMessage: (message: Message) => void,\r\n clientId?: string,\r\n): void {\r\n const response: Message = {\r\n id,\r\n type: 'AUTH_LOGIN_RES',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'runtime',\r\n id: clientId\r\n },\r\n payload:{\r\n ...res,\r\n }\r\n };\r\n\r\n logger.debug(`[AUTH_LOGIN_RES ${id}] Sending ${res.success ? 'successful' : 'failed'} auth response to client: ${clientId}`);\r\n logger.debug(`[AUTH_LOGIN_RES ${id}] Response payload size: ${JSON.stringify(response).length} bytes`);\r\n\r\n if (res.error) {\r\n logger.debug(`[AUTH_LOGIN_RES ${id}] Error message: ${res.error}`);\r\n }\r\n\r\n sendMessage(response);\r\n}\r\n\r\n","import { verifyAuthToken } from \"../auth/validator\";\r\nimport { AuthVerifyRequestMessageSchema, Message } from \"../types\";\r\nimport { logger } from \"../utils/logger\";\r\n\r\n\r\nexport async function handleAuthVerifyRequest(\r\n data: any,\r\n sendMessage: (message: Message) => void\r\n): Promise<void> {\r\n try {\r\n logger.debug('[AUTH_VERIFY_REQ] Parsing incoming auth verify request');\r\n const authRequest = AuthVerifyRequestMessageSchema.parse(data);\r\n const { id, payload } = authRequest;\r\n\r\n const token = payload.token;\r\n\r\n const wsId = authRequest.from.id ;\r\n\r\n logger.info(`[AUTH_VERIFY_REQ ${id}] Processing auth verify request from client: ${wsId}`);\r\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Token present: ${!!token}`);\r\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Token length: ${token ? token.length : 0} characters`);\r\n\r\n if(!token){\r\n logger.error(`[AUTH_VERIFY_REQ ${id}] Token not found in request`);\r\n sendDataResponse(id, {\r\n success: false,\r\n error: 'Token not found'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n\r\n if(!wsId){\r\n logger.error(`[AUTH_VERIFY_REQ ${id}] WebSocket ID not found in request`);\r\n sendDataResponse(id, {\r\n success: false,\r\n error: 'WebSocket ID not found'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token validation starting`);\r\n logger.debug(`[AUTH_VERIFY_REQ ${id}] WebSocket ID: ${wsId}`);\r\n\r\n // Verify token\r\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Calling verifyAuthToken`);\r\n const startTime = Date.now();\r\n\r\n const authResult = verifyAuthToken(token);\r\n\r\n const verificationTime = Date.now() - startTime;\r\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token verification completed in ${verificationTime}ms - ${authResult.success ? 'valid' : 'invalid'}`);\r\n\r\n if (!authResult.success) {\r\n logger.warn(`[AUTH_VERIFY_REQ ${id}] Token verification failed: ${authResult.error}`);\r\n } else {\r\n logger.info(`[AUTH_VERIFY_REQ ${id}] Token verified successfully for user: ${authResult.data || 'unknown'}`);\r\n }\r\n\r\n // Send response\r\n logger.debug(`[AUTH_VERIFY_REQ ${id}] Sending verification response to client`);\r\n sendDataResponse(id, authResult, sendMessage, wsId);\r\n\r\n logger.info(`[AUTH_VERIFY_REQ ${id}] ${authResult.success ? '✓' : '✗'} Auth verify request completed`);\r\n return ;\r\n }\r\n catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\r\n const errorStack = error instanceof Error ? error.stack : undefined;\r\n\r\n logger.error(`[AUTH_VERIFY_REQ] Failed to handle auth verify request: ${errorMessage}`);\r\n logger.debug(`[AUTH_VERIFY_REQ] Error stack trace:`, errorStack);\r\n\r\n // Try to send error response\r\n try {\r\n const parsedData = data as any;\r\n if (parsedData?.id) {\r\n sendDataResponse(parsedData.id, {\r\n success: false,\r\n error: `Internal error: ${errorMessage}`\r\n }, sendMessage, parsedData.from?.id);\r\n }\r\n } catch (sendError) {\r\n logger.error('[AUTH_VERIFY_REQ] Failed to send error response:', sendError);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Send a data_res response message\r\n */\r\nfunction sendDataResponse(\r\n id: string,\r\n res: {success: boolean; error?: string; data?: any},\r\n sendMessage: (message: Message) => void,\r\n clientId?: string,\r\n): void {\r\n const response: Message = {\r\n id,\r\n type: 'AUTH_VERIFY_RES',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'runtime',\r\n id: clientId\r\n },\r\n payload:{\r\n ...res,\r\n }\r\n };\r\n\r\n logger.debug(`[AUTH_VERIFY_RES ${id}] Sending ${res.success ? 'successful' : 'failed'} verification response to client: ${clientId}`);\r\n logger.debug(`[AUTH_VERIFY_RES ${id}] Response payload size: ${JSON.stringify(response).length} bytes`);\r\n\r\n if (res.error) {\r\n logger.debug(`[AUTH_VERIFY_RES ${id}] Error message: ${res.error}`);\r\n }\r\n\r\n if (res.data) {\r\n logger.debug(`[AUTH_VERIFY_RES ${id}] User verified: ${res.data}`);\r\n }\r\n\r\n sendMessage(response);\r\n} ","import dotenv from 'dotenv';\r\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\r\n\r\ndotenv.config();\r\n\r\nexport interface GroqLLMConfig extends BaseLLMConfig {}\r\n\r\n/**\r\n * GroqLLM class for handling AI-powered component generation and matching using Groq\r\n */\r\nexport class GroqLLM extends BaseLLM {\r\n\tconstructor(config?: GroqLLMConfig) {\r\n\t\tsuper(config);\r\n\t}\r\n\r\n\tprotected getDefaultModel(): string {\r\n\t\treturn 'groq/openai/gpt-oss-120b';\r\n\t}\r\n\r\n\tprotected getDefaultApiKey(): string | undefined {\r\n\t\treturn process.env.GROQ_API_KEY;\r\n\t}\r\n\r\n\tprotected getProviderName(): string {\r\n\t\treturn 'Groq';\r\n\t}\r\n}\r\n\r\n// Export a singleton instance\r\nexport const groqLLM = new GroqLLM();\r\n","import { Component, T_RESPONSE } from '../types';\r\nimport { ensureQueryLimit, fixScalarSubqueries, convertQuestionsToActions } from './utils';\r\nimport { schema } from './schema';\r\nimport { promptLoader } from './prompt-loader';\r\nimport { LLM } from '../llm';\r\nimport { logger } from '../utils/logger';\r\nimport type { Action } from '../threads/action';\r\nimport KB from './knowledge-base';\r\n\r\nexport interface BaseLLMConfig {\r\n\tmodel?: string;\r\n\tdefaultLimit?: number;\r\n\tapiKey?: string;\r\n}\r\n\r\n/**\r\n * BaseLLM abstract class for AI-powered component generation and matching\r\n * Provides common functionality for all LLM providers\r\n */\r\nexport abstract class BaseLLM {\r\n\tprotected model: string;\r\n\tprotected defaultLimit: number;\r\n\tprotected apiKey?: string;\r\n\r\n\tconstructor(config?: BaseLLMConfig) {\r\n\t\tthis.model = config?.model || this.getDefaultModel();\r\n\t\tthis.defaultLimit = config?.defaultLimit || 50;\r\n\t\tthis.apiKey = config?.apiKey;\r\n\t}\r\n\r\n\t/**\r\n\t * Get the default model for this provider\r\n\t */\r\n\tprotected abstract getDefaultModel(): string;\r\n\r\n\t/**\r\n\t * Get the default API key from environment\r\n\t */\r\n\tprotected abstract getDefaultApiKey(): string | undefined;\r\n\r\n\t/**\r\n\t * Get the provider name (for logging)\r\n\t */\r\n\tprotected abstract getProviderName(): string;\r\n\r\n\t/**\r\n\t * Get the API key (from instance, parameter, or environment)\r\n\t */\r\n\tprotected getApiKey(apiKey?: string): string | undefined {\r\n\t\treturn apiKey || this.apiKey || this.getDefaultApiKey();\r\n\t}\r\n\r\n\t/**\r\n\t * Classify user question to determine the type and required visualizations\r\n\t */\r\n\tasync classifyUserQuestion(\r\n\t\tuserPrompt: string,\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<{\r\n\t\tquestionType: 'analytical' | 'data_modification' | 'general';\r\n\t\tvisualizations: string[];\r\n\t\treasoning: string;\r\n\t\tneedsMultipleComponents: boolean;\r\n\t}> {\r\n\t\t\r\n\t\ttry {\r\n\t\t\tconst prompts = await promptLoader.loadPrompts('classify', {\r\n\t\t\t\tUSER_PROMPT: userPrompt,\r\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\r\n\t\t\t});\r\n\r\n\t\t\tconst result = await LLM.stream<any>(\r\n\t\t\t\t{\r\n\t\t\t\t\tsys: prompts.system,\r\n\t\t\t\t\tuser: prompts.user\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tmodel: this.model,\r\n\t\t\t\t\tmaxTokens: 800,\r\n\t\t\t\t\ttemperature: 0.2,\r\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\r\n\t\t\t\t},\r\n\t\t\t\ttrue // Parse as JSON\r\n\t\t\t) as any;\r\n\r\n\t\t\t// Log the LLM explanation with type\r\n\t\t\tlogCollector?.logExplanation(\r\n\t\t\t\t'User question classified',\r\n\t\t\t\tresult.reasoning || 'No reasoning provided',\r\n\t\t\t\t{\r\n\t\t\t\t\tquestionType: result.questionType || 'general',\r\n\t\t\t\t\tvisualizations: result.visualizations || [],\r\n\t\t\t\t\tneedsMultipleComponents: result.needsMultipleComponents || false\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t\treturn {\r\n\t\t\t\tquestionType: result.questionType || 'general',\r\n\t\t\t\tvisualizations: result.visualizations || [],\r\n\t\t\t\treasoning: result.reasoning || 'No reasoning provided',\r\n\t\t\t\tneedsMultipleComponents: result.needsMultipleComponents || false\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error classifying user question: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Classification error details:`, error);\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Enhanced function that validates and modifies the entire props object based on user request\r\n\t * This includes query, title, description, and config properties\r\n\t */\r\n\tasync validateAndModifyProps(\r\n\t\tuserPrompt: string,\r\n\t\toriginalProps: any,\r\n\t\tcomponentName: string,\r\n\t\tcomponentType: string,\r\n\t\tcomponentDescription?: string,\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<{ props: any; isModified: boolean; reasoning: string; modifications: string[] }> {\r\n\r\n\t\tconst schemaDoc = schema.generateSchemaDocumentation();\r\n\t\ttry {\r\n\t\t\tconst prompts = await promptLoader.loadPrompts('modify-props', {\r\n\t\t\t\tCOMPONENT_NAME: componentName,\r\n\t\t\t\tCOMPONENT_TYPE: componentType,\r\n\t\t\t\tCOMPONENT_DESCRIPTION: componentDescription || 'No description',\r\n\t\t\t\tSCHEMA_DOC: schemaDoc || 'No schema available',\r\n\t\t\t\tDEFAULT_LIMIT: this.defaultLimit,\r\n\t\t\t\tUSER_PROMPT: userPrompt,\r\n\t\t\t\tCURRENT_PROPS: JSON.stringify(originalProps, null, 2),\r\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\r\n\t\t\t});\r\n\r\n\t\t\tlogger.debug('props-modification: System prompt\\n',prompts.system.substring(0, 100), '\\n\\n\\n', 'User prompt:', prompts.user.substring(0, 50));\t\r\n\t\t\tconst result = await LLM.stream<any>(\r\n\t\t\t\t{\r\n\t\t\t\t\tsys: prompts.system,\r\n\t\t\t\t\tuser: prompts.user\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tmodel: this.model,\r\n\t\t\t\t\tmaxTokens: 2500,\r\n\t\t\t\t\ttemperature: 0.2,\r\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\r\n\t\t\t\t},\r\n\t\t\t\ttrue // Parse as JSON\r\n\t\t\t) as any;\r\n\r\n\t\t\t// Ensure all queries have a LIMIT clause and fix scalar subqueries\r\n\t\t\tconst props = result.props || originalProps;\r\n\t\t\tif (props && props.query) {\r\n\t\t\t\t// First fix scalar subqueries to prevent PostgreSQL errors\r\n\t\t\t\tprops.query = fixScalarSubqueries(props.query);\r\n\t\t\t\t// Then ensure LIMIT clause exists\r\n\t\t\t\tprops.query = ensureQueryLimit(props.query, this.defaultLimit);\r\n\t\t\t}\r\n\r\n\t\t\t// Log the generated query and explanation with types\r\n\t\t\tif (props && props.query) {\r\n\t\t\t\tlogCollector?.logQuery(\r\n\t\t\t\t\t'Props query modified',\r\n\t\t\t\t\tprops.query,\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmodifications: result.modifications || [],\r\n\t\t\t\t\t\treasoning: result.reasoning || 'No modifications needed'\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tif (result.reasoning) {\r\n\t\t\t\tlogCollector?.logExplanation(\r\n\t\t\t\t\t'Props modification explanation',\r\n\t\t\t\t\tresult.reasoning,\r\n\t\t\t\t\t{ modifications: result.modifications || [] }\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\treturn {\r\n\t\t\t\tprops: props,\r\n\t\t\t\tisModified: result.isModified || false,\r\n\t\t\t\treasoning: result.reasoning || 'No modifications needed',\r\n\t\t\t\tmodifications: result.modifications || []\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error validating/modifying props: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Props validation error details:`, error);\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Match and select a component from available components filtered by type\r\n\t * This picks the best matching component based on user prompt and modifies its props\r\n\t */\r\n\tasync generateAnalyticalComponent(\r\n\t\tuserPrompt: string,\r\n\t\tcomponents: Component[],\r\n\t\tpreferredVisualizationType?: string,\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<{\r\n\t\tcomponent: Component | null;\r\n\t\treasoning: string;\r\n\t\tisGenerated: boolean;\r\n\t}> {\r\n\t\ttry {\r\n\t\t\t// Filter components by the preferred visualization type\r\n\t\t\tconst filteredComponents = preferredVisualizationType\r\n\t\t\t\t? components.filter(c => c.type === preferredVisualizationType)\r\n\t\t\t\t: components;\r\n\r\n\t\t\tif (filteredComponents.length === 0) {\r\n\t\t\t\tlogCollector?.warn(\r\n\t\t\t\t\t`No components found of type ${preferredVisualizationType}`,\r\n\t\t\t\t\t'explanation',\r\n\t\t\t\t\t{ reason: 'No matching components available for this visualization type' }\r\n\t\t\t\t);\r\n\t\t\t\treturn {\r\n\t\t\t\t\tcomponent: null,\r\n\t\t\t\t\treasoning: `No components available of type ${preferredVisualizationType}`,\r\n\t\t\t\t\tisGenerated: false\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\t// Format filtered components for the prompt\r\n\t\t\tconst componentsText = filteredComponents\r\n\t\t\t\t.map((comp, idx) => {\r\n\t\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\r\n\t\t\t\t\tconst category = comp.category || 'general';\r\n\t\t\t\t\tconst propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : 'No props';\r\n\t\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\r\n Name: ${comp.name}\r\n Type: ${comp.type}\r\n Category: ${category}\r\n Description: ${comp.description || 'No description'}\r\n Keywords: ${keywords}\r\n Props Preview: ${propsPreview}`;\r\n\t\t\t\t})\r\n\t\t\t\t.join('\\n\\n');\r\n\r\n\t\t\tconst visualizationConstraint = preferredVisualizationType\r\n\t\t\t\t? `\\n**IMPORTANT: Components are filtered to type ${preferredVisualizationType}. Select the best match.**\\n`\r\n\t\t\t\t: '';\r\n\r\n\t\t\tconst prompts = await promptLoader.loadPrompts('single-component', {\r\n\t\t\t\tCOMPONENT_TYPE: preferredVisualizationType || 'any',\r\n\t\t\t\tCOMPONENTS_LIST: componentsText,\r\n\t\t\t\tVISUALIZATION_CONSTRAINT: visualizationConstraint,\r\n\t\t\t\tUSER_PROMPT: userPrompt,\r\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\r\n\t\t\t});\r\n\r\n\t\t\tlogger.debug('single-component: System prompt\\n',prompts.system.substring(0, 100), '\\n\\n\\n', 'User prompt:', prompts.user.substring(0, 50));\r\n\t\t\tconst result = await LLM.stream<any>(\r\n\t\t\t\t{\r\n\t\t\t\t\tsys: prompts.system,\r\n\t\t\t\t\tuser: prompts.user\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tmodel: this.model,\r\n\t\t\t\t\tmaxTokens: 2000,\r\n\t\t\t\t\ttemperature: 0.2,\r\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\r\n\t\t\t\t},\r\n\t\t\t\ttrue // Parse as JSON\r\n\t\t\t) as any;\r\n\r\n\t\t\tif (!result.canGenerate || result.confidence < 50) {\r\n\t\t\t\tlogCollector?.warn(\r\n\t\t\t\t\t'Cannot match component',\r\n\t\t\t\t\t'explanation',\r\n\t\t\t\t\t{ reason: result.reasoning || 'Unable to find matching component for this question' }\r\n\t\t\t\t);\r\n\t\t\t\treturn {\r\n\t\t\t\t\tcomponent: null,\r\n\t\t\t\t\treasoning: result.reasoning || 'Unable to find matching component for this question',\r\n\t\t\t\t\tisGenerated: false\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\t// Get the matched component\r\n\t\t\tconst componentIndex = result.componentIndex;\r\n\t\t\tconst componentId = result.componentId;\r\n\t\t\tlet matchedComponent = null;\r\n\r\n\t\t\t// Prefer componentId over componentIndex\r\n\t\t\tif (componentId) {\r\n\t\t\t\tmatchedComponent = filteredComponents.find(c => c.id === componentId);\r\n\t\t\t}\r\n\r\n\t\t\t// Fallback to componentIndex\r\n\t\t\tif (!matchedComponent && componentIndex) {\r\n\t\t\t\tmatchedComponent = filteredComponents[componentIndex - 1];\r\n\t\t\t}\r\n\r\n\t\t\tif (!matchedComponent) {\r\n\t\t\t\t\r\n\t\t\t\tlogCollector?.warn('Component not found in filtered list');\r\n\t\t\t\treturn {\r\n\t\t\t\t\tcomponent: null,\r\n\t\t\t\t\treasoning: 'Component not found in filtered list',\r\n\t\t\t\t\tisGenerated: false\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\tlogCollector?.info(`Matched component: ${matchedComponent.name} (confidence: ${result.confidence}%)`);\r\n\r\n\t\t\t// Now modify the component's props based on user prompt\r\n\t\t\tconst propsValidation = await this.validateAndModifyProps(\r\n\t\t\t\tuserPrompt,\r\n\t\t\t\tmatchedComponent.props,\r\n\t\t\t\tmatchedComponent.name,\r\n\t\t\t\tmatchedComponent.type,\r\n\t\t\t\tmatchedComponent.description,\r\n\t\t\t\tapiKey,\r\n\t\t\t\tlogCollector,\r\n\t\t\t\tconversationHistory\r\n\t\t\t);\r\n\r\n\t\t\t// Create modified component\r\n\t\t\tconst modifiedComponent: Component = {\r\n\t\t\t\t...matchedComponent,\r\n\t\t\t\tprops: propsValidation.props\r\n\t\t\t};\r\n\r\n\t\t\tlogCollector?.logExplanation(\r\n\t\t\t\t'Analytical component selected and modified',\r\n\t\t\t\tresult.reasoning || 'Selected component based on analytical question',\r\n\t\t\t\t{\r\n\t\t\t\t\tcomponentName: matchedComponent.name,\r\n\t\t\t\t\tcomponentType: matchedComponent.type,\r\n\t\t\t\t\tconfidence: result.confidence,\r\n\t\t\t\t\tpropsModified: propsValidation.isModified\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t\treturn {\r\n\t\t\t\tcomponent: modifiedComponent,\r\n\t\t\t\treasoning: result.reasoning || 'Selected and modified component based on analytical question',\r\n\t\t\t\tisGenerated: true\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating analytical component: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Analytical component generation error details:`, error);\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Generate container metadata (title and description) for multi-component dashboard\r\n\t */\r\n\tasync generateContainerMetadata(\r\n\t\tuserPrompt: string,\r\n\t\tvisualizationTypes: string[],\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<{\r\n\t\ttitle: string;\r\n\t\tdescription: string;\r\n\t}> {\r\n\t\ttry {\r\n\t\t\tconst prompts = await promptLoader.loadPrompts('container-metadata', {\r\n\t\t\t\tUSER_PROMPT: userPrompt,\r\n\t\t\t\tVISUALIZATION_TYPES: visualizationTypes.join(', '),\r\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\r\n\t\t\t});\r\n\r\n\t\t\tconst result = await LLM.stream<any>(\r\n\t\t\t\t{\r\n\t\t\t\t\tsys: prompts.system,\r\n\t\t\t\t\tuser: prompts.user\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tmodel: this.model,\r\n\t\t\t\t\tmaxTokens: 500,\r\n\t\t\t\t\ttemperature: 0.3,\r\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\r\n\t\t\t\t},\r\n\t\t\t\ttrue // Parse as JSON\r\n\t\t\t) as any;\r\n\r\n\t\t\tlogCollector?.logExplanation(\r\n\t\t\t\t'Container metadata generated',\r\n\t\t\t\t`Generated title and description for multi-component dashboard`,\r\n\t\t\t\t{\r\n\t\t\t\t\ttitle: result.title,\r\n\t\t\t\t\tdescription: result.description,\r\n\t\t\t\t\tvisualizationTypes\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t\treturn {\r\n\t\t\t\ttitle: result.title || `${userPrompt} - Dashboard`,\r\n\t\t\t\tdescription: result.description || `Multi-component dashboard showing ${visualizationTypes.join(', ')}`\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating container metadata: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Container metadata error details:`, error);\r\n\t\t\t// Return fallback values\r\n\t\t\treturn {\r\n\t\t\t\ttitle: `${userPrompt} - Dashboard`,\r\n\t\t\t\tdescription: `Multi-component dashboard showing ${visualizationTypes.join(', ')}`\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Match component from a list with enhanced props modification\r\n\t */\r\n\tasync matchComponent(\r\n\t\tuserPrompt: string,\r\n\t\tcomponents: Component[],\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<{\r\n\t\tcomponent: Component | null;\r\n\t\treasoning: string;\r\n\t\tqueryModified?: boolean;\r\n\t\tqueryReasoning?: string;\r\n\t\tpropsModified?: boolean;\r\n\t\tpropsModifications?: string[];\r\n\t\tmethod: string;\r\n\t\tconfidence?: number;\r\n\t}> {\r\n\t\ttry {\r\n\t\t\t// Step 1: Enhanced component matching with scoring and multiple candidates\r\n\t\t\tconst componentsText = components\r\n\t\t\t\t.map((comp, idx) => {\r\n\t\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\r\n\t\t\t\t\tconst category = comp.category || 'general';\r\n\t\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\r\n Name: ${comp.name}\r\n Type: ${comp.type}\r\n Category: ${category}\r\n Description: ${comp.description || 'No description'}\r\n Keywords: ${keywords}`;\r\n\t\t\t\t})\r\n\t\t\t\t.join('\\n\\n');\r\n\r\n\t\t\tconst prompts = await promptLoader.loadPrompts('match-component', {\r\n\t\t\t\tCOMPONENTS_TEXT: componentsText,\r\n\t\t\t\tUSER_PROMPT: userPrompt,\r\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\r\n\t\t\t});\r\n\r\n\t\t\tconst result = await LLM.stream<any>(\r\n\t\t\t\t{\r\n\t\t\t\t\tsys: prompts.system,\r\n\t\t\t\t\tuser: prompts.user\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tmodel: this.model,\r\n\t\t\t\t\tmaxTokens: 800,\r\n\t\t\t\t\ttemperature: 0.2,\r\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\r\n\t\t\t\t},\r\n\t\t\t\ttrue // Parse as JSON\r\n\t\t\t) as any;\r\n\r\n\t\t\tconst componentIndex = result.componentIndex;\r\n\t\t\tconst componentId = result.componentId;\r\n\t\t\tconst confidence = result.confidence || 0;\r\n\r\n\t\t\t// Prefer componentId over componentIndex for accuracy\r\n\t\t\tlet component = null;\r\n\t\t\tif (componentId) {\r\n\t\t\t\tcomponent = components.find(c => c.id === componentId);\r\n\t\t\t}\r\n\r\n\t\t\t// Fallback to componentIndex if ID not found\r\n\t\t\tif (!component && componentIndex) {\r\n\t\t\t\tcomponent = components[componentIndex - 1];\r\n\t\t\t}\r\n\r\n\t\t\tconst matchedMsg = `${this.getProviderName()} matched component: ${component?.name || 'None'}`;\r\n\t\t\tlogger.info(`[${this.getProviderName()}] ✓ ${matchedMsg}`);\r\n\t\t\tlogCollector?.info(matchedMsg);\r\n\r\n\t\t\tif (result.alternativeMatches && result.alternativeMatches.length > 0) {\r\n\t\t\t\tlogger.debug(`[${this.getProviderName()}] Alternative matches found: ${result.alternativeMatches.length}`);\r\n\t\t\t\tconst altMatches = result.alternativeMatches.map((alt: any) =>\r\n\t\t\t\t\t`${components[alt.index - 1]?.name} (${alt.score}%): ${alt.reason}`\r\n\t\t\t\t).join(' | ');\r\n\t\t\t\tlogCollector?.info(`Alternative matches: ${altMatches}`);\r\n\t\t\t\tresult.alternativeMatches.forEach((alt: any) => {\r\n\t\t\t\t\tlogger.debug(`[${this.getProviderName()}] - ${components[alt.index - 1]?.name} (${alt.score}%): ${alt.reason}`);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tif (!component) {\r\n\t\t\t\tconst noMatchMsg = `No matching component found (confidence: ${confidence}%)`;\r\n\t\t\t\tlogger.warn(`[${this.getProviderName()}] ✗ ${noMatchMsg}`);\r\n\t\t\t\tlogCollector?.warn(noMatchMsg);\r\n\t\t\t\tconst genMsg = 'Attempting to match component from analytical question...';\r\n\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ ${genMsg}`);\r\n\t\t\t\tlogCollector?.info(genMsg);\r\n\r\n\t\t\t\t// Try to match a component for the analytical question\r\n\t\t\t\tconst generatedResult = await this.generateAnalyticalComponent(userPrompt, components, undefined, apiKey, logCollector, conversationHistory);\r\n\r\n\t\t\t\tif (generatedResult.component) {\r\n\t\t\t\t\tconst genSuccessMsg = `Successfully matched component: ${generatedResult.component.name}`;\r\n\t\t\t\t\tlogCollector?.info(genSuccessMsg);\r\n\t\t\t\t\treturn {\r\n\t\t\t\t\t\tcomponent: generatedResult.component,\r\n\t\t\t\t\t\treasoning: generatedResult.reasoning,\r\n\t\t\t\t\t\tmethod: `${this.getProviderName()}-generated`,\r\n\t\t\t\t\t\tconfidence: 100, // Generated components are considered 100% match to the question\r\n\t\t\t\t\t\tpropsModified: false,\r\n\t\t\t\t\t\tqueryModified: false\r\n\t\t\t\t\t};\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// If matching also failed, return null\r\n\t\t\t\tlogCollector?.error('Failed to match component');\r\n\t\t\t\treturn {\r\n\t\t\t\t\tcomponent: null,\r\n\t\t\t\t\treasoning: result.reasoning || 'No matching component found and unable to match component',\r\n\t\t\t\t\tmethod: `${this.getProviderName()}-llm`,\r\n\t\t\t\t\tconfidence\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\t// Step 2: Validate and modify the entire props object based on user request\r\n\t\t\tlet propsModified = false;\r\n\t\t\tlet propsModifications: string[] = [];\r\n\t\t\tlet queryModified = false;\r\n\t\t\tlet queryReasoning = '';\r\n\r\n\t\t\tif (component && component.props) {\r\n\r\n\t\t\t\tconst propsValidation = await this.validateAndModifyProps(\r\n\t\t\t\t\tuserPrompt,\r\n\t\t\t\t\tcomponent.props,\r\n\t\t\t\t\tcomponent.name,\r\n\t\t\t\t\tcomponent.type,\r\n\t\t\t\t\tcomponent.description,\r\n\t\t\t\t\tapiKey,\r\n\t\t\t\t\tlogCollector,\r\n\t\t\t\t\tconversationHistory\r\n\t\t\t\t);\r\n\r\n\t\t\t\t// Create a new component object with the modified props\r\n\t\t\t\tconst originalQuery = component.props.query;\r\n\t\t\t\tconst modifiedQuery = propsValidation.props.query;\r\n\r\n\t\t\t\tcomponent = {\r\n\t\t\t\t\t...component,\r\n\t\t\t\t\tprops: propsValidation.props\r\n\t\t\t\t};\r\n\r\n\t\t\t\tpropsModified = propsValidation.isModified;\r\n\t\t\t\tpropsModifications = propsValidation.modifications;\r\n\t\t\t\tqueryModified = originalQuery !== modifiedQuery;\r\n\t\t\t\tqueryReasoning = propsValidation.reasoning;\r\n\t\t\t}\r\n\r\n\t\t\treturn {\r\n\t\t\t\tcomponent,\r\n\t\t\t\treasoning: result.reasoning || 'No reasoning provided',\r\n\t\t\t\tqueryModified,\r\n\t\t\t\tqueryReasoning,\r\n\t\t\t\tpropsModified,\r\n\t\t\t\tpropsModifications,\r\n\t\t\t\tmethod: `${this.getProviderName()}-llm`,\r\n\t\t\t\tconfidence\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error matching component: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Component matching error details:`, error);\r\n\t\t\tlogCollector?.error(`Error matching component: ${errorMsg}`);\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Match multiple components for analytical questions by visualization types\r\n\t * This is used when the user needs multiple visualizations\r\n\t */\r\n\tasync generateMultipleAnalyticalComponents(\r\n\t\tuserPrompt: string,\r\n\t\tavailableComponents: Component[],\r\n\t\tvisualizationTypes: string[],\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<{\r\n\t\tcomponents: Component[];\r\n\t\treasoning: string;\r\n\t\tisGenerated: boolean;\r\n\t}> {\r\n\t\ttry {\r\n\t\t\tconsole.log('✓ Matching multiple components:', visualizationTypes);\r\n\r\n\t\t\tconst components: Component[] = [];\r\n\r\n\t\t\t// Match each component type requested\r\n\t\t\tfor (const vizType of visualizationTypes) {\r\n\t\t\t\tconst result = await this.generateAnalyticalComponent(userPrompt, availableComponents, vizType, apiKey, logCollector, conversationHistory);\r\n\r\n\t\t\t\tif (result.component) {\r\n\t\t\t\t\tcomponents.push(result.component);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (components.length === 0) {\r\n\t\t\t\treturn {\r\n\t\t\t\t\tcomponents: [],\r\n\t\t\t\t\treasoning: 'Failed to match any components',\r\n\t\t\t\t\tisGenerated: false\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\treturn {\r\n\t\t\t\tcomponents,\r\n\t\t\t\treasoning: `Matched ${components.length} components: ${visualizationTypes.join(', ')}`,\r\n\t\t\t\tisGenerated: true\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error matching multiple analytical components: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Multiple components matching error details:`, error);\r\n\t\t\treturn {\r\n\t\t\t\tcomponents: [],\r\n\t\t\t\treasoning: 'Error occurred while matching components',\r\n\t\t\t\tisGenerated: false\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Match multiple components and wrap them in a container\r\n\t */\r\n\tasync generateMultiComponentResponse(\r\n\t\tuserPrompt: string,\r\n\t\tavailableComponents: Component[],\r\n\t\tvisualizationTypes: string[],\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<{\r\n\t\tcontainerComponent: Component | null;\r\n\t\treasoning: string;\r\n\t\tisGenerated: boolean;\r\n\t}> {\r\n\t\ttry {\r\n\t\t\t// Match multiple components for each visualization type\r\n\t\t\tconst matchResult = await this.generateMultipleAnalyticalComponents(\r\n\t\t\t\tuserPrompt,\r\n\t\t\t\tavailableComponents,\r\n\t\t\t\tvisualizationTypes,\r\n\t\t\t\tapiKey,\r\n\t\t\t\tlogCollector,\r\n\t\t\t\tconversationHistory\r\n\t\t\t);\r\n\r\n\t\t\tif (!matchResult.isGenerated || matchResult.components.length === 0) {\r\n\t\t\t\treturn {\r\n\t\t\t\t\tcontainerComponent: null,\r\n\t\t\t\t\treasoning: matchResult.reasoning || 'Unable to match multi-component dashboard',\r\n\t\t\t\t\tisGenerated: false\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\tconst generatedComponents = matchResult.components;\r\n\r\n\t\t\t// Log each generated component's query\r\n\t\t\tgeneratedComponents.forEach((component, index) => {\r\n\t\t\t\tif (component.props.query) {\r\n\t\t\t\t\tlogCollector?.logQuery(\r\n\t\t\t\t\t\t`Multi-component query generated (${index + 1}/${generatedComponents.length})`,\r\n\t\t\t\t\t\tcomponent.props.query,\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcomponentType: component.type,\r\n\t\t\t\t\t\t\ttitle: component.props.title,\r\n\t\t\t\t\t\t\tposition: index + 1,\r\n\t\t\t\t\t\t\ttotalComponents: generatedComponents.length\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\t// Generate container title and description\r\n\t\t\tconst containerTitle = `${userPrompt} - Dashboard`;\r\n\t\t\tconst containerDescription = `Multi-component dashboard showing ${visualizationTypes.join(', ')}`;\r\n\r\n\t\t\t// Log the overall explanation for the multi-component dashboard\r\n\t\t\tlogCollector?.logExplanation(\r\n\t\t\t\t'Multi-component dashboard matched',\r\n\t\t\t\tmatchResult.reasoning || `Matched ${generatedComponents.length} components for comprehensive analysis`,\r\n\t\t\t\t{\r\n\t\t\t\t\ttotalComponents: generatedComponents.length,\r\n\t\t\t\t\tcomponentTypes: generatedComponents.map(c => c.type),\r\n\t\t\t\t\tcomponentNames: generatedComponents.map(c => c.name),\r\n\t\t\t\t\tcontainerTitle,\r\n\t\t\t\t\tcontainerDescription\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t\t// Create the MultiComponentContainer wrapper\r\n\t\t\tconst containerComponent: Component = {\r\n\t\t\t\tid: `multi_container_${Date.now()}`,\r\n\t\t\t\tname: 'MultiComponentContainer',\r\n\t\t\t\ttype: 'Container',\r\n\t\t\t\tdescription: containerDescription,\r\n\t\t\t\tcategory: 'dynamic',\r\n\t\t\t\tkeywords: ['multi', 'container', 'dashboard'],\r\n\t\t\t\tprops: {\r\n\t\t\t\t\tconfig: {\r\n\t\t\t\t\t\tcomponents: generatedComponents,\r\n\t\t\t\t\t\tlayout: 'grid',\r\n\t\t\t\t\t\tspacing: 24,\r\n\t\t\t\t\t\ttitle: containerTitle,\r\n\t\t\t\t\t\tdescription: containerDescription\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\treturn {\r\n\t\t\t\tcontainerComponent,\r\n\t\t\t\treasoning: matchResult.reasoning || `Matched multi-component dashboard with ${generatedComponents.length} components`,\r\n\t\t\t\tisGenerated: true\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating multi-component response: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Multi-component response error details:`, error);\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Match components from text response suggestions and generate follow-up questions\r\n\t * Takes a text response with component suggestions (c1:type format) and matches with available components\r\n\t * Also generates intelligent follow-up questions (actions) based on the analysis\r\n\t * @param textResponse - The text response containing component suggestions\r\n\t * @param components - List of available components\r\n\t * @param apiKey - Optional API key\r\n\t * @param logCollector - Optional log collector\r\n\t * @returns Object containing matched components, selected layout, reasoning, and follow-up actions\r\n\t */\r\n\tasync matchComponentsFromTextResponse(\r\n\t\ttextResponse: string,\r\n\t\tcomponents: Component[],\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any\r\n\t): Promise<{\r\n\t\tcomponents: Component[];\r\n\t\tselectedLayoutId: string;\r\n\t\tselectedLayoutComponent: Component | null;\r\n\t\tlayoutReasoning: string;\r\n\t\tactions: Action[];\r\n\t}> {\r\n\t\ttry {\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Starting component matching from text response`);\r\n\r\n\t\t\t// Format available components for the prompt\r\n\t\t\tlet availableComponentsText = 'No components available';\r\n\t\t\tif (components && components.length > 0) {\r\n\t\t\t\tavailableComponentsText = components\r\n\t\t\t\t\t.map((comp, idx) => {\r\n\t\t\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\r\n\t\t\t\t\t\tconst propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : 'No props';\r\n\t\t\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\r\n Name: ${comp.name}\r\n Type: ${comp.type}\r\n Description: ${comp.description || 'No description'}\r\n Keywords: ${keywords}\r\n Props Structure: ${propsPreview}`;\r\n\t\t\t\t\t})\r\n\t\t\t\t\t.join('\\n\\n');\r\n\t\t\t}\r\n\r\n\t\t\t// Get schema documentation for query generation\r\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\r\n\r\n\t\t\tconst prompts = await promptLoader.loadPrompts('match-text-components', {\r\n\t\t\t\tTEXT_RESPONSE: textResponse,\r\n\t\t\t\tAVAILABLE_COMPONENTS: availableComponentsText,\r\n\t\t\t\tSCHEMA_DOC: schemaDoc\r\n\t\t\t});\r\n\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);\r\n\t\t\tlogger.file('\\n=============================\\nmatch text components system prompt:', prompts.system);\r\n\r\n\t\t\tlogCollector?.info('Matching components from text response...');\r\n\r\n\t\t\t// Let LLM.stream handle JSON parsing automatically\r\n\t\t\tconst result = await LLM.stream<any>(\r\n\t\t\t\t{\r\n\t\t\t\t\tsys: prompts.system,\r\n\t\t\t\t\tuser: prompts.user\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tmodel: this.model,\r\n\t\t\t\t\tmaxTokens: 3000,\r\n\t\t\t\t\ttemperature: 0.2,\r\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\r\n\t\t\t\t},\r\n\t\t\t\ttrue // Parse as JSON\r\n\t\t\t) as any;\r\n\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);\r\n\r\n\t\t\tconst matchedComponents = result.matchedComponents || [];\r\n\t\t\tconst selectedLayoutId = result.selectedLayoutId || 'multi-component-container';\r\n\t\t\tconst layoutReasoning = result.layoutReasoning || 'No layout reasoning provided';\r\n\r\n\t\t\t// Convert question strings to Action objects\r\n\t\t\tconst rawActions = result.actions || [];\r\n\t\t\tconst actions = convertQuestionsToActions(rawActions);\r\n\r\n\t\t\t// Find the layout component from available components\r\n\t\t\tlet selectedLayoutComponent: Component | null = null;\r\n\t\t\tif (selectedLayoutId) {\r\n\t\t\t\tselectedLayoutComponent = components.find(c => c.id === selectedLayoutId) || null;\r\n\t\t\t\tif (!selectedLayoutComponent) {\r\n\t\t\t\t\tlogger.warn(`[${this.getProviderName()}] Layout component ${selectedLayoutId} not found in available components`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Selected layout: (ID: ${selectedLayoutId})`);\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Layout reasoning: ${layoutReasoning}`);\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);\r\n\r\n\t\t\t// Log matched components\r\n\t\t\tif (matchedComponents.length > 0) {\r\n\t\t\t\tlogCollector?.info(`Matched ${matchedComponents.length} components for visualization `);\r\n\t\t\t\tlogCollector?.info(`Layout reasoning: ${layoutReasoning}`);\r\n\t\t\t\tmatchedComponents.forEach((comp: any, idx: number) => {\r\n\t\t\t\t\tlogCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);\r\n\t\t\t\t\tif (comp.props?.query) {\r\n\t\t\t\t\t\tlogCollector?.logQuery(\r\n\t\t\t\t\t\t\t`Component ${idx + 1} query`,\r\n\t\t\t\t\t\t\tcomp.props.query,\r\n\t\t\t\t\t\t\t{ componentName: comp.componentName, title: comp.props.title }\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\t// Log generated actions\r\n\t\t\tif (actions.length > 0) {\r\n\t\t\t\tlogCollector?.info(`Generated ${actions.length} follow-up questions`);\r\n\t\t\t\tactions.forEach((action: Action, idx: number) => {\r\n\t\t\t\t\tlogCollector?.info(` ${idx + 1}. ${action.name}`);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\t// Build final component objects with full metadata\r\n\t\t\tconst finalComponents: Component[] = matchedComponents.map((mc: any) => {\r\n\t\t\t\t// Find the original component from the list to preserve all metadata\r\n\t\t\t\tconst originalComponent = components.find(c => c.id === mc.componentId);\r\n\r\n\t\t\t\tif (!originalComponent) {\r\n\t\t\t\t\tlogger.warn(`[${this.getProviderName()}] Component ${mc.componentId} not found in available components`);\r\n\t\t\t\t\treturn null;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Merge generated props with original component\r\n\t\t\t\treturn {\r\n\t\t\t\t\t...originalComponent,\r\n\t\t\t\t\tprops: {\r\n\t\t\t\t\t\t...originalComponent.props,\r\n\t\t\t\t\t\t...mc.props\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t}).filter(Boolean) as Component[];\r\n\r\n\t\t\treturn {\r\n\t\t\t\tcomponents: finalComponents,\r\n\t\t\t\tselectedLayoutId,\r\n\t\t\t\tselectedLayoutComponent,\r\n\t\t\t\tlayoutReasoning,\r\n\t\t\t\tactions\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error matching components: ${errorMsg}`);\r\n\t\t\tlogCollector?.error(`Failed to match components: ${errorMsg}`);\r\n\r\n\t\t\t// Return empty results on error\r\n\t\t\treturn {\r\n\t\t\t\tcomponents: [],\r\n\t\t\t\tselectedLayoutId: '',\r\n\t\t\t\tselectedLayoutComponent: null,\r\n\t\t\t\tlayoutReasoning: 'Failed to match components due to parsing error',\r\n\t\t\t\tactions: []\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Generate text-based response for user question\r\n\t * This provides conversational text responses instead of component generation\r\n\t * Supports tool calling for query execution with automatic retry on errors (max 3 attempts)\r\n\t * After generating text response, if components are provided, matches suggested components\r\n\t * @param streamCallback - Optional callback function to receive text chunks as they stream\r\n\t * @param collections - Collection registry for executing database queries via database.execute\r\n\t * @param components - Optional list of available components for matching suggestions\r\n\t */\r\n\tasync generateTextResponse(\r\n\t\tuserPrompt: string,\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string,\r\n\t\tstreamCallback?: (chunk: string) => void,\r\n\t\tcollections?: any,\r\n\t\tcomponents?: Component[]\r\n\t): Promise<T_RESPONSE> {\r\n\t\tconst errors: string[] = [];\r\n\r\n\t\tlogger.debug(`[${this.getProviderName()}] Starting text response generation`);\r\n\t\tlogger.debug(`[${this.getProviderName()}] User prompt: \"${userPrompt.substring(0, 50)}...\"`);\r\n\r\n\t\ttry {\r\n\t\t\t// Get schema documentation\r\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\r\n\r\n\t\t\t// Get relevant knowledge base context (best match only)\r\n\t\t\tconst knowledgeBaseContext = await KB.getKnowledgeBase({\r\n\t\t\t\tprompt: userPrompt,\r\n\t\t\t\tcollections,\r\n\t\t\t\ttopK: 1\r\n\t\t\t});\r\n\r\n\t\t\t// const knowledgeBaseContext = ''\r\n\r\n\t\t\tlogger.file('\\n=============================\\nknowledge base context:', knowledgeBaseContext);\r\n\r\n\t\t\tconst prompts = await promptLoader.loadPrompts('text-response', {\r\n\t\t\t\tUSER_PROMPT: userPrompt,\r\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation',\r\n\t\t\t\tSCHEMA_DOC: schemaDoc,\r\n\t\t\t\tKNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || 'No additional knowledge base context available.'\r\n\t\t\t});\r\n\r\n\t\t\tlogger.file('\\n=============================\\nsystem prompt:', prompts.system);\r\n\t\t\tlogger.file('\\n=============================\\nuser prompt:', prompts.user);\r\n\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);\r\n\r\n\t\t\tlogCollector?.info('Generating text response with query execution capability...');\r\n\r\n\t\t\t// Define the execute_query tool\r\n\t\t\tconst tools = [{\r\n\t\t\t\tname: 'execute_query',\r\n\t\t\t\tdescription: 'Executes a SQL query against the database and returns the results. Use this when the user asks for data. If the query fails, you will receive the error and can retry with a corrected query.',\r\n\t\t\t\tinput_schema: {\r\n\t\t\t\t\ttype: 'object',\r\n\t\t\t\t\tproperties: {\r\n\t\t\t\t\t\tquery: {\r\n\t\t\t\t\t\t\ttype: 'string',\r\n\t\t\t\t\t\t\tdescription: 'The SQL query to execute. Must be valid SQL syntax using table and column names from the schema.'\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\treasoning: {\r\n\t\t\t\t\t\t\ttype: 'string',\r\n\t\t\t\t\t\t\tdescription: 'Brief explanation of what this query does and why it answers the user\\'s question.'\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t},\r\n\t\t\t\t\trequired: ['query']\r\n\t\t\t\t}\r\n\t\t\t}];\r\n\r\n\t\t\t// Track query attempts for retry logic (max 6 attempts per unique query pattern)\r\n\t\t\tconst queryAttempts = new Map<string, number>();\r\n\t\t\tconst MAX_QUERY_ATTEMPTS = 6;\r\n\t\t\tlet maxAttemptsReached = false;\r\n\r\n\t\t\t// Capture all streamed text to pass to component matching\r\n\t\t\tlet fullStreamedText = '';\r\n\r\n\t\t\t// Wrap the streamCallback to capture all text\r\n\t\t\tconst wrappedStreamCallback = streamCallback ? (chunk: string) => {\r\n\t\t\t\tfullStreamedText += chunk;\r\n\t\t\t\tstreamCallback(chunk);\r\n\t\t\t} : undefined;\r\n\r\n\t\t\t// Tool handler with retry logic and streaming updates\r\n\t\t\tconst toolHandler = async (toolName: string, toolInput: any) => {\r\n\t\t\t\tif (toolName === 'execute_query') {\r\n\t\t\t\t\tlet query = toolInput.query;\r\n\t\t\t\t\tconst reasoning = toolInput.reasoning;\r\n\r\n\t\t\t\t\t// Ensure query has proper LIMIT clause (max 32 rows)\r\n\t\t\t\t\tconst { ensureQueryLimit } = await import('./utils');\r\n\t\t\t\t\tquery = ensureQueryLimit(query, 32, 32);\r\n\r\n\t\t\t\t\t// Track attempts for this query pattern (normalized)\r\n\t\t\t\t\tconst queryKey = query.toLowerCase().replace(/\\s+/g, ' ').trim();\r\n\t\t\t\t\tconst attempts = (queryAttempts.get(queryKey) || 0) + 1;\r\n\t\t\t\t\tqueryAttempts.set(queryKey, attempts);\r\n\r\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Executing query (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${query.substring(0, 100)}...`);\r\n\t\t\t\t\tif (reasoning) {\r\n\t\t\t\t\t\tlogCollector?.info(`Query reasoning: ${reasoning}`);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Check if max attempts reached\r\n\t\t\t\t\tif (attempts > MAX_QUERY_ATTEMPTS) {\r\n\t\t\t\t\t\tconst errorMsg = `Maximum query attempts (${MAX_QUERY_ATTEMPTS}) reached. Unable to generate a valid query for your question.`;\r\n\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] ${errorMsg}`);\r\n\t\t\t\t\t\tlogCollector?.error(errorMsg);\r\n\r\n\t\t\t\t\t\t// Set flag instead of throwing\r\n\t\t\t\t\t\tmaxAttemptsReached = true;\r\n\r\n\t\t\t\t\t\t// Stream error to frontend\r\n\t\t\t\t\t\tif (wrappedStreamCallback) {\r\n\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n❌ ${errorMsg}\\n\\nPlease try rephrasing your question or simplifying your request.\\n\\n`);\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Return error message to stop the tool calling loop\r\n\t\t\t\t\t\tthrow new Error(errorMsg);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\t// Stream query generation message to frontend\r\n\t\t\t\t\t\tif (wrappedStreamCallback) {\r\n\t\t\t\t\t\t\tif (attempts === 1) {\r\n\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔍 **Analyzing your question...**\\n\\n`);\r\n\t\t\t\t\t\t\t\tif (reasoning) {\r\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`💭 ${reasoning}\\n\\n`);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\twrappedStreamCallback(`📝 **Generated SQL Query:**\\n\\`\\`\\`sql\\n${query}\\n\\`\\`\\`\\n\\n`);\r\n\t\t\t\t\t\t\t\twrappedStreamCallback(`⚡ **Executing query...**\\n\\n`);\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\twrappedStreamCallback(`\\n\\n🔄 **Retrying with corrected query (attempt ${attempts}/${MAX_QUERY_ATTEMPTS})...**\\n\\n`);\r\n\t\t\t\t\t\t\t\tif (reasoning) {\r\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`💭 ${reasoning}\\n\\n`);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\twrappedStreamCallback(`📝 **Corrected SQL Query:**\\n\\`\\`\\`sql\\n${query}\\n\\`\\`\\`\\n\\n`);\r\n\t\t\t\t\t\t\t\twrappedStreamCallback(`⚡ **Executing query...**\\n\\n`);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Log the query\r\n\t\t\t\t\t\tlogCollector?.logQuery(\r\n\t\t\t\t\t\t\t`Executing SQL query (attempt ${attempts})`,\r\n\t\t\t\t\t\t\tquery,\r\n\t\t\t\t\t\t\t{ reasoning, attempt: attempts }\r\n\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t// Execute query using collections system (database.execute)\r\n\t\t\t\t\t\tif (!collections || !collections['database'] || !collections['database']['execute']) {\r\n\t\t\t\t\t\t\tthrow new Error('Database collection not registered. Please register database.execute collection to execute queries.');\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tconst result = await collections['database']['execute']({ sql: query });\r\n\r\n\t\t\t\t\t\t// Extract data from result\r\n\t\t\t\t\t\tconst data = result?.data || result;\r\n\t\t\t\t\t\tconst rowCount = result?.count ?? (Array.isArray(data) ? data.length : 'N/A');\r\n\r\n\t\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Query executed successfully, rows returned: ${rowCount}`);\r\n\t\t\t\t\t\tlogCollector?.info(`Query successful, returned ${rowCount} rows`);\r\n\r\n\t\t\t\t\t\t// Stream success message and data preview to frontend\r\n\t\t\t\t\t\tif (wrappedStreamCallback) {\r\n\t\t\t\t\t\t\twrappedStreamCallback(`✅ **Query executed successfully!**\\n\\n`);\r\n\r\n\t\t\t\t\t\t\t// Check if it's a count query or aggregate\r\n\t\t\t\t\t\t\tif (Array.isArray(data) && data.length > 0) {\r\n\t\t\t\t\t\t\t\tconst firstRow = data[0];\r\n\t\t\t\t\t\t\t\tconst columns = Object.keys(firstRow);\r\n\r\n\t\t\t\t\t\t\t\t// If single row with single column (likely a count/aggregate)\r\n\t\t\t\t\t\t\t\tif (data.length === 1 && columns.length === 1) {\r\n\t\t\t\t\t\t\t\t\tconst value = firstRow[columns[0]];\r\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`**Result:** ${value}\\n\\n`);\r\n\t\t\t\t\t\t\t\t} else if (data.length > 0) {\r\n\t\t\t\t\t\t\t\t\t// Multiple rows or columns - embed DataTable component\r\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`**Retrieved ${rowCount} rows**\\n\\n`);\r\n\r\n\t\t\t\t\t\t\t\t\t// Stream the data as a DataTable component\r\n\t\t\t\t\t\t\t\t\twrappedStreamCallback(`<DataTable>${JSON.stringify(data)}</DataTable>\\n\\n`);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t} else if (Array.isArray(data) && data.length === 0) {\r\n\t\t\t\t\t\t\t\twrappedStreamCallback(`**No rows returned.**\\n\\n`);\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\twrappedStreamCallback(`📊 **Analyzing results...**\\n\\n`);\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Return full result as JSON string for the LLM to analyze\r\n\t\t\t\t\t\treturn JSON.stringify(data, null, 2);\r\n\t\t\t\t\t} catch (error) {\r\n\t\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\t\t\t\tlogger.error(`[${this.getProviderName()}] Query execution failed (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${errorMsg}`);\r\n\t\t\t\t\t\tlogCollector?.error(`Query failed (attempt ${attempts}/${MAX_QUERY_ATTEMPTS}): ${errorMsg}`);\r\n\r\n\t\t\t\t\t\t// Stream error message to frontend\r\n\t\t\t\t\t\tif (wrappedStreamCallback) {\r\n\t\t\t\t\t\t\twrappedStreamCallback(`❌ **Query execution failed:**\\n\\`\\`\\`\\n${errorMsg}\\n\\`\\`\\`\\n\\n`);\r\n\r\n\t\t\t\t\t\t\tif (attempts < MAX_QUERY_ATTEMPTS) {\r\n\t\t\t\t\t\t\t\twrappedStreamCallback(`🔧 **Generating corrected query...**\\n\\n`);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Return error to LLM so it can retry with corrected query\r\n\t\t\t\t\t\tthrow new Error(`Query execution failed: ${errorMsg}`);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthrow new Error(`Unknown tool: ${toolName}`);\r\n\t\t\t};\r\n\r\n\t\t\t// Use tool calling with streaming\r\n\t\t\t// Max iterations needs to account for:\r\n\t\t\t// - Up to 6 query retry attempts (MAX_QUERY_ATTEMPTS)\r\n\t\t\t// - 1 additional iteration for final text response\r\n\t\t\t// - Buffer for multiple tool calls in one iteration\r\n\t\t\tconst result = await LLM.streamWithTools(\r\n\t\t\t\t{\r\n\t\t\t\t\tsys: prompts.system,\r\n\t\t\t\t\tuser: prompts.user\r\n\t\t\t\t},\r\n\t\t\t\ttools,\r\n\t\t\t\ttoolHandler,\r\n\t\t\t\t{\r\n\t\t\t\t\tmodel: this.model,\r\n\t\t\t\t\tmaxTokens: 4000,\r\n\t\t\t\t\ttemperature: 0.7,\r\n\t\t\t\t\tapiKey: this.getApiKey(apiKey),\r\n\t\t\t\t\tpartial: wrappedStreamCallback // Pass the wrapped streaming callback to LLM\r\n\t\t\t\t},\r\n\t\t\t\t10 // max iterations: allows for 6 retries + final response + buffer\r\n\t\t\t);\r\n\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Text response stream completed`);\r\n\r\n\t\t\t// Use fullStreamedText if available (contains all streamed content), otherwise fallback to result\r\n\t\t\tconst textResponse = fullStreamedText || result || 'I apologize, but I was unable to generate a response.';\r\n\r\n\t\t\t// Check if max query attempts were reached\r\n\t\t\tif (maxAttemptsReached) {\r\n\t\t\t\tlogger.warn(`[${this.getProviderName()}] Max query attempts reached, returning failure response`);\r\n\t\t\t\tlogCollector?.error('Failed to generate valid query after maximum attempts');\r\n\r\n\t\t\t\treturn {\r\n\t\t\t\t\tsuccess: false,\r\n\t\t\t\t\terrors: [`Maximum query attempts (${MAX_QUERY_ATTEMPTS}) reached. Unable to generate a valid query for your question.`],\r\n\t\t\t\t\tdata: {\r\n\t\t\t\t\t\ttext: textResponse, // Include the streamed text showing all attempts\r\n\t\t\t\t\t\tmatchedComponents: [],\r\n\t\t\t\t\t\tactions: [],\r\n\t\t\t\t\t\tmethod: `${this.getProviderName()}-text-response-max-attempts`\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t}\r\n\r\n\t\t\t// Log the text response\r\n\t\t\tlogCollector?.info(`Text response: ${textResponse.substring(0, 100)}${textResponse.length > 100 ? '...' : ''}`);\r\n\r\n\t\t\tlogCollector?.logExplanation(\r\n\t\t\t\t'Text response generated',\r\n\t\t\t\t'Generated plain text response with component suggestions',\r\n\t\t\t\t{\r\n\t\t\t\t\ttextLength: textResponse.length\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t\t// If components are provided, match them from the text response\r\n\t\t\tlet matchedComponents: Component[] = [];\r\n\t\t\tlet selectedLayoutComponent: Component | null = null;\r\n\t\t\tlet layoutReasoning = 'No layout selected';\r\n\t\t\tlet actions: Action[] = [];\r\n\r\n\t\t\tif (components && components.length > 0) {\r\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Matching components from text response...`);\r\n\t\t\t\tconst matchResult = await this.matchComponentsFromTextResponse(\r\n\t\t\t\t\ttextResponse,\r\n\t\t\t\t\tcomponents,\r\n\t\t\t\t\tapiKey,\r\n\t\t\t\t\tlogCollector\r\n\t\t\t\t);\r\n\t\t\t\tmatchedComponents = matchResult.components;\r\n\t\t\t\tselectedLayoutComponent = matchResult.selectedLayoutComponent;\r\n\t\t\t\tlayoutReasoning = matchResult.layoutReasoning;\r\n\t\t\t\tactions = matchResult.actions;\r\n\t\t\t}\r\n\r\n\t\t\tlet container_componet:Component | null = null;\r\n\r\n\t\t\tif(matchedComponents.length > 0){\r\n\t\t\t\t// Use the selected layout component if available, otherwise create a default container\r\n\t\t\t\tif (selectedLayoutComponent) {\r\n\t\t\t\t\t// Use the actual layout component from the available components\r\n\t\t\t\t\tcontainer_componet = {\r\n\t\t\t\t\t\t...selectedLayoutComponent,\r\n\t\t\t\t\t\tid: `${selectedLayoutComponent.id}_${Date.now()}`, // Make ID unique for each instance\r\n\t\t\t\t\t\tprops: {\r\n\t\t\t\t\t\t\t...selectedLayoutComponent.props,\r\n\t\t\t\t\t\t\tconfig: {\r\n\t\t\t\t\t\t\t\t...(selectedLayoutComponent.props?.config || {}),\r\n\t\t\t\t\t\t\t\tcomponents: matchedComponents\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tactions: actions\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Created ${selectedLayoutComponent.name} (${selectedLayoutComponent.type}) container with ${matchedComponents.length} components and ${actions.length} actions`);\r\n\t\t\t\t\tlogCollector?.info(`Created ${selectedLayoutComponent.name} with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Fallback to MultiComponentContainer if no layout component was found\r\n\t\t\t\t\tcontainer_componet = {\r\n\t\t\t\t\t\tid: `multi_container_${Date.now()}`,\r\n\t\t\t\t\t\tname: 'MultiComponentContainer',\r\n\t\t\t\t\t\ttype: 'Container',\r\n\t\t\t\t\t\tdescription: layoutReasoning,\r\n\t\t\t\t\t\tcategory: 'dynamic',\r\n\t\t\t\t\t\tkeywords: ['dashboard', 'layout', 'container'],\r\n\t\t\t\t\t\tprops: {\r\n\t\t\t\t\t\t\tconfig: {\r\n\t\t\t\t\t\t\t\tcomponents: matchedComponents\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tactions: actions\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tlogger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions`);\r\n\t\t\t\t\tlogCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn {\r\n\t\t\t\tsuccess: true,\r\n\t\t\t\tdata: {\r\n\t\t\t\t\ttext: textResponse,\r\n\t\t\t\t\tmatchedComponents: matchedComponents,\r\n\t\t\t\t\tcomponent: container_componet,\r\n\t\t\t\t\tlayoutReasoning: layoutReasoning,\r\n\t\t\t\t\tactions: actions,\r\n\t\t\t\t\tmethod: `${this.getProviderName()}-text-response`\r\n\t\t\t\t},\r\n\t\t\t\terrors: []\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating text response: ${errorMsg}`);\r\n\t\t\tlogCollector?.error(`Error generating text response: ${errorMsg}`);\r\n\r\n\t\t\terrors.push(errorMsg);\r\n\r\n\t\t\treturn {\r\n\t\t\t\tsuccess: false,\r\n\t\t\t\terrors,\r\n\t\t\t\tdata: {\r\n\t\t\t\t\ttext: 'I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.',\r\n\t\t\t\t\tmatchedComponents: [],\r\n\t\t\t\t\tactions: [],\r\n\t\t\t\t\tmethod: `${this.getProviderName()}-text-response-error`\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Generate component response for user question\r\n\t * This provides conversational component suggestions based on user question\r\n\t * Supports component generation and matching\r\n\t */\r\n\tasync generateComponentResponse(\r\n\t\tuserPrompt: string,\r\n\t\tcomponents: Component[],\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<T_RESPONSE> {\r\n\t\tconst errors: string[] = [];\r\n\r\n\t\ttry {\r\n\t\t\t// Component mode (default) - existing flow\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Using component response mode`);\r\n\r\n\t\t\t// Step 1: Classify the user's question\r\n\t\t\tconst classifyMsg = 'Classifying user question...';\r\n\t\t\tlogCollector?.info(classifyMsg);\r\n\t\t\tconst classification = await this.classifyUserQuestion(userPrompt, apiKey, logCollector, conversationHistory);\r\n\t\t\tconst classInfo = `Question type: ${classification.questionType}, Visualizations: ${classification.visualizations.join(', ') || 'None'}, Multiple components: ${classification.needsMultipleComponents}`;\r\n\t\t\tlogCollector?.info(classInfo);\r\n\r\n\t\t// Step 2: Route based on question type\r\n\t\tif (classification.questionType === 'analytical') {\r\n\t\t\t// For analytical questions with specific visualization types\r\n\t\t\tif (classification.visualizations.length > 1) {\r\n\t\t\t\t// Multiple visualization types - match component for each type\r\n\t\t\t\tconst multiMsg = `Matching ${classification.visualizations.length} components for types: ${classification.visualizations.join(', ')}`;\r\n\t\t\t\tlogCollector?.info(multiMsg);\r\n\r\n\t\t\t\t// Generate all components in parallel using Promise.allSettled\r\n\t\t\t\tconst componentPromises = classification.visualizations.map(vizType => {\r\n\t\t\t\t\tlogCollector?.info(`Matching component for type: ${vizType}`);\r\n\t\t\t\t\treturn this.generateAnalyticalComponent(\r\n\t\t\t\t\t\tuserPrompt,\r\n\t\t\t\t\t\tcomponents,\r\n\t\t\t\t\t\tvizType,\r\n\t\t\t\t\t\tapiKey,\r\n\t\t\t\t\t\tlogCollector,\r\n\t\t\t\t\t\tconversationHistory\r\n\t\t\t\t\t).then(result => ({ vizType, result }));\r\n\t\t\t\t});\r\n\r\n\t\t\t\tconst settledResults = await Promise.allSettled(componentPromises);\r\n\r\n\t\t\t\t// Extract successfully matched components, skip failed ones\r\n\t\t\t\tconst matchedComponents: Component[] = [];\r\n\t\t\t\tfor (const settledResult of settledResults) {\r\n\t\t\t\t\tif (settledResult.status === 'fulfilled') {\r\n\t\t\t\t\t\tconst { vizType, result } = settledResult.value;\r\n\t\t\t\t\t\tif (result.component) {\r\n\t\t\t\t\t\t\tmatchedComponents.push(result.component);\r\n\t\t\t\t\t\t\tlogCollector?.info(`Matched: ${result.component.name}`);\r\n\t\t\t\t\t\t\tlogger.info('Component : ', result.component.name,' props: ', result.component.props);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tlogCollector?.warn(`Failed to match component for type: ${vizType}`);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t// Promise rejected - log the error and continue\r\n\t\t\t\t\t\tlogCollector?.warn(`Error matching component: ${settledResult.reason?.message || 'Unknown error'}`);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlogger.debug(`[${this.getProviderName()}] Matched ${matchedComponents.length} components for multi-component container`);\r\n\r\n\t\t\t\tif (matchedComponents.length === 0) {\r\n\t\t\t\t\treturn {\r\n\t\t\t\t\t\tsuccess: true,\r\n\t\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t\tcomponent: null,\r\n\t\t\t\t\t\t\treasoning: 'Failed to match any components for the requested visualization types',\r\n\t\t\t\t\t\t\tmethod: 'classification-multi-failed',\r\n\t\t\t\t\t\t\tquestionType: classification.questionType,\r\n\t\t\t\t\t\t\tneedsMultipleComponents: true,\r\n\t\t\t\t\t\t\tpropsModified: false,\r\n\t\t\t\t\t\t\tqueryModified: false\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\terrors: []\r\n\t\t\t\t\t};\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Generate container metadata from user request\r\n\t\t\t\tlogCollector?.info('Generating container metadata...');\r\n\t\t\t\t\r\n\t\t\t\tconst containerMetadata = await this.generateContainerMetadata(\r\n\t\t\t\t\tuserPrompt,\r\n\t\t\t\t\tclassification.visualizations,\r\n\t\t\t\t\tapiKey,\r\n\t\t\t\t\tlogCollector,\r\n\t\t\t\t\tconversationHistory\r\n\t\t\t\t);\r\n\r\n\r\n\r\n\t\t\t\tconst containerComponent: Component = {\r\n\t\t\t\t\tid: `multi_container_${Date.now()}`,\r\n\t\t\t\t\tname: 'MultiComponentContainer',\r\n\t\t\t\t\ttype: 'Container',\r\n\t\t\t\t\tdescription: containerMetadata.description,\r\n\t\t\t\t\tcategory: 'dynamic',\r\n\t\t\t\t\tkeywords: ['multi', 'container', 'dashboard'],\r\n\t\t\t\t\tprops: {\r\n\t\t\t\t\t\tconfig: {\r\n\t\t\t\t\t\t\tcomponents: matchedComponents,\r\n\t\t\t\t\t\t\tlayout: 'grid',\r\n\t\t\t\t\t\t\tspacing: 24,\r\n\t\t\t\t\t\t\ttitle: containerMetadata.title,\r\n\t\t\t\t\t\t\tdescription: containerMetadata.description\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\r\n\t\t\t\tlogCollector?.info(`Created multi-component container with ${matchedComponents.length} components: \"${containerMetadata.title}\"`);\r\n\r\n\t\t\t\treturn {\r\n\t\t\t\t\tsuccess: true,\r\n\t\t\t\t\tdata: {\r\n\t\t\t\t\t\tcomponent: containerComponent,\r\n\t\t\t\t\t\treasoning: `Matched ${matchedComponents.length} components for visualization types: ${classification.visualizations.join(', ')}`,\r\n\t\t\t\t\t\tmethod: 'classification-multi-generated',\r\n\t\t\t\t\t\tquestionType: classification.questionType,\r\n\t\t\t\t\t\tneedsMultipleComponents: true,\r\n\t\t\t\t\t\tpropsModified: false,\r\n\t\t\t\t\t\tqueryModified: false\r\n\t\t\t\t\t},\r\n\t\t\t\t\terrors: []\r\n\t\t\t\t};\r\n\t\t\t} else if (classification.visualizations.length === 1) {\r\n\t\t\t\t// Single visualization type - match one component\r\n\t\t\t\tconst vizType = classification.visualizations[0];\r\n\t\t\t\tlogCollector?.info(`Matching single component for type: ${vizType}`);\r\n\t\t\t\tconst result = await this.generateAnalyticalComponent(userPrompt, components, vizType, apiKey, logCollector, conversationHistory);\r\n\r\n\t\t\t\treturn {\r\n\t\t\t\t\tsuccess: true,\r\n\t\t\t\t\tdata: {\r\n\t\t\t\t\t\tcomponent: result.component,\r\n\t\t\t\t\t\treasoning: result.reasoning,\r\n\t\t\t\t\t\tmethod: 'classification-generated',\r\n\t\t\t\t\t\tquestionType: classification.questionType,\r\n\t\t\t\t\t\tneedsMultipleComponents: false,\r\n\t\t\t\t\t\tpropsModified: false,\r\n\t\t\t\t\t\tqueryModified: false\r\n\t\t\t\t\t},\r\n\t\t\t\t\terrors: []\r\n\t\t\t\t};\r\n\t\t\t} else {\r\n\t\t\t\t// No specific visualization type, match from all components\r\n\t\t\t\tlogCollector?.info('No specific visualization type - matching from all components');\r\n\t\t\t\tconst result = await this.generateAnalyticalComponent(userPrompt, components, undefined, apiKey, logCollector, conversationHistory);\r\n\r\n\t\t\t\treturn {\r\n\t\t\t\t\tsuccess: true,\r\n\t\t\t\t\tdata: {\r\n\t\t\t\t\t\tcomponent: result.component,\r\n\t\t\t\t\t\treasoning: result.reasoning,\r\n\t\t\t\t\t\tmethod: 'classification-generated-auto',\r\n\t\t\t\t\t\tquestionType: classification.questionType,\r\n\t\t\t\t\t\tneedsMultipleComponents: false,\r\n\t\t\t\t\t\tpropsModified: false,\r\n\t\t\t\t\t\tqueryModified: false\r\n\t\t\t\t\t},\r\n\t\t\t\t\terrors: []\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t} else if (classification.questionType === 'data_modification' || classification.questionType === 'general') {\r\n\t\t\t// For data modification, use the old component matching flow\r\n\t\t\tconst matchMsg = 'Using component matching for data modification...';\r\n\t\t\tlogCollector?.info(matchMsg);\r\n\t\t\tconst matchResult = await this.matchComponent(userPrompt, components, apiKey, logCollector, conversationHistory);\r\n\r\n\t\t\treturn {\r\n\t\t\t\tsuccess: true,\r\n\t\t\t\tdata: {\r\n\t\t\t\t\tcomponent: matchResult.component,\r\n\t\t\t\t\treasoning: matchResult.reasoning,\r\n\t\t\t\t\tmethod: 'classification-matched',\r\n\t\t\t\t\tquestionType: classification.questionType,\r\n\t\t\t\t\tneedsMultipleComponents: false,\r\n\t\t\t\t\tpropsModified: matchResult.propsModified,\r\n\t\t\t\t\tqueryModified: matchResult.queryModified\r\n\t\t\t\t},\r\n\t\t\t\terrors: []\r\n\t\t\t};\r\n\t\t} else {\r\n\t\t\tlogCollector?.info('General question - no component needed');\r\n\t\t\treturn {\r\n\t\t\t\tsuccess: true,\r\n\t\t\t\tdata: {\r\n\t\t\t\t\tcomponent: null,\r\n\t\t\t\t\treasoning: 'General question - no component needed',\r\n\t\t\t\t\tmethod: 'classification-general',\r\n\t\t\t\t\tquestionType: classification.questionType,\r\n\t\t\t\t\tneedsMultipleComponents: false,\r\n\t\t\t\t\tpropsModified: false,\r\n\t\t\t\t\tqueryModified: false\r\n\t\t\t\t},\r\n\t\t\t\terrors: []\r\n\t\t\t};\r\n\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating component response: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Component response generation error details:`, error);\r\n\t\t\tlogCollector?.error(`Error generating component response: ${errorMsg}`);\r\n\r\n\t\t\terrors.push(errorMsg);\r\n\r\n\t\t\treturn {\r\n\t\t\t\tsuccess: false,\r\n\t\t\t\terrors,\r\n\t\t\t\tdata: undefined\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Main orchestration function that classifies question and routes to appropriate handler\r\n\t * This is the NEW recommended entry point for handling user requests\r\n\t * Supports both component generation and text response modes\r\n\t *\r\n\t * @param responseMode - 'component' for component generation (default), 'text' for text responses\r\n\t * @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)\r\n\t * @param collections - Collection registry for executing database queries (required for text mode)\r\n\t */\r\n\tasync handleUserRequest(\r\n\t\tuserPrompt: string,\r\n\t\tcomponents: Component[],\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string,\r\n\t\tresponseMode: 'component' | 'text' = 'component',\r\n\t\tstreamCallback?: (chunk: string) => void,\r\n\t\tcollections?: any\r\n\t): Promise<T_RESPONSE> {\r\n\t\tconst startTime = Date.now();\r\n\t\tlogger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);\r\n\r\n\t\t// If text response mode is requested, skip classification and generate text response\r\n\t\tif (responseMode === 'text') {\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Using text response mode`);\r\n\t\t\tlogCollector?.info('Generating text response...');\r\n\r\n\t\t\tconst textResponse = await this.generateTextResponse(\r\n\t\t\t\tuserPrompt,\r\n\t\t\t\tapiKey,\r\n\t\t\t\tlogCollector,\r\n\t\t\t\tconversationHistory,\r\n\t\t\t\tstreamCallback,\r\n\t\t\t\tcollections,\r\n\t\t\t\tcomponents\r\n\t\t\t);\r\n\r\n\t\t\t// If text response generation failed, return the error\r\n\t\t\tif (!textResponse.success) {\r\n\t\t\t\tconst elapsedTime = Date.now() - startTime;\r\n\t\t\t\tlogger.error(`[${this.getProviderName()}] Text response generation failed`);\r\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\r\n\t\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\r\n\t\t\t\treturn textResponse;\r\n\t\t\t}\r\n\r\n\t\t\tconst elapsedTime = Date.now() - startTime;\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Text response generated successfully`);\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\r\n\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\r\n\r\n\t\t\treturn textResponse\r\n\t\t}\r\n\r\n\t\tconst componentResponse = await this.generateComponentResponse(\r\n\t\t\tuserPrompt,\r\n\t\t\tcomponents,\r\n\t\t\tapiKey,\r\n\t\t\tlogCollector,\r\n\t\t\tconversationHistory\r\n\t\t);\r\n\r\n\t\t// If component response generation failed, return the error\r\n\t\tif (!componentResponse.success) {\r\n\t\t\tconst elapsedTime = Date.now() - startTime;\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Component response generation failed`);\r\n\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\r\n\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\r\n\t\t\treturn componentResponse;\r\n\t\t}\r\n\r\n\t\tconst elapsedTime = Date.now() - startTime;\r\n\t\tlogger.info(`[${this.getProviderName()}] Component response generated successfully`);\r\n\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\r\n\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\r\n\r\n\t\treturn componentResponse\r\n\t}\r\n\r\n\t/**\r\n\t * Generate next questions that the user might ask based on the original prompt and generated component\r\n\t * This helps provide intelligent suggestions for follow-up queries\r\n\t */\r\n\tasync generateNextQuestions(\r\n\t\toriginalUserPrompt: string,\r\n\t\tcomponent: Component,\r\n\t\tcomponentData?: Record<string, unknown>,\r\n\t\tapiKey?: string,\r\n\t\tlogCollector?: any,\r\n\t\tconversationHistory?: string\r\n\t): Promise<string[]> {\r\n\t\ttry {\r\n\t\t\tconst component_info = `\r\n\t\t\t\tComponent Name: ${component.name}\r\n\t\t\t\tComponent Type: ${component.type}\r\n\t\t\t\tComponent Description: ${component.description || 'No description'}\r\n\t\t\t\tComponent Props: ${component.props ? JSON.stringify(component.props, null, 2) : 'No props'}\r\n\t\t\t`;\r\n\r\n\t\t\tconst component_data = componentData ? `Component Data: ${JSON.stringify(componentData, null, 2)}` : '';\r\n\r\n\t\t\tconst prompts = await promptLoader.loadPrompts('actions', {\r\n\t\t\t\tORIGINAL_USER_PROMPT: originalUserPrompt,\r\n\t\t\t\tCOMPONENT_INFO: component_info,\r\n\t\t\t\tCOMPONENT_DATA: component_data,\r\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\r\n\t\t\t});\r\n\r\n\t\t\tconst result = await LLM.stream<any>(\r\n\t\t\t\t{\r\n\t\t\t\t\tsys: prompts.system,\r\n\t\t\t\t\tuser: prompts.user\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tmodel: this.model,\r\n\t\t\t\t\tmaxTokens: 800,\r\n\t\t\t\t\ttemperature: 0.7,\r\n\t\t\t\t\tapiKey: this.getApiKey(apiKey)\r\n\t\t\t\t},\r\n\t\t\t\ttrue // Parse as JSON\r\n\t\t\t) as any;\r\n\r\n\t\t\tconst nextQuestions = result.nextQuestions || [];\r\n\r\n\t\t\tlogCollector?.logExplanation(\r\n\t\t\t\t'Next questions generated',\r\n\t\t\t\t'Generated intelligent follow-up questions based on component',\r\n\t\t\t\t{\r\n\t\t\t\t\tcount: nextQuestions.length,\r\n\t\t\t\t\tquestions: nextQuestions\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t\treturn nextQuestions;\r\n\t\t} catch (error) {\r\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\t\tlogger.error(`[${this.getProviderName()}] Error generating next questions: ${errorMsg}`);\r\n\t\t\tlogger.debug(`[${this.getProviderName()}] Next questions generation error details:`, error);\r\n\t\t\tlogCollector?.error(`Error generating next questions: ${errorMsg}`);\r\n\t\t\t// Return empty array on error instead of throwing\r\n\t\t\treturn [];\r\n\t\t}\r\n\t}\r\n\r\n}\r\n","import path from 'path';\r\nimport fs from 'fs';\r\nimport { logger } from '../utils/logger';\r\n\r\n/**\r\n * Schema class for managing database schema operations\r\n */\r\nexport class Schema {\r\n private schemaFilePath: string;\r\n private cachedSchema: any = null;\r\n\r\n constructor(schemaFilePath?: string) {\r\n this.schemaFilePath = schemaFilePath || path.join(process.cwd(), '../analysis/data/schema.json');\r\n }\r\n\r\n /**\r\n * Gets the database schema from the schema file\r\n * @returns Parsed schema object or null if error occurs\r\n */\r\n getDatabaseSchema(): any | null {\r\n logger.info(`SCHEMA_FILE_PATH: ${this.schemaFilePath}`);\r\n\r\n try {\r\n // Create directory structure if it doesn't exist\r\n const dir = path.dirname(this.schemaFilePath);\r\n if (!fs.existsSync(dir)) {\r\n logger.info(`Creating directory structure: ${dir}`);\r\n fs.mkdirSync(dir, { recursive: true });\r\n }\r\n\r\n // Create file with empty schema if it doesn't exist\r\n if (!fs.existsSync(this.schemaFilePath)) {\r\n logger.info(`Schema file does not exist at ${this.schemaFilePath}, creating with empty schema`);\r\n const initialSchema = {\r\n database: '',\r\n schema: '',\r\n description: '',\r\n tables: [],\r\n relationships: []\r\n };\r\n fs.writeFileSync(this.schemaFilePath, JSON.stringify(initialSchema, null, 4));\r\n this.cachedSchema = initialSchema;\r\n return initialSchema;\r\n }\r\n\r\n const fileContent = fs.readFileSync(this.schemaFilePath, 'utf-8');\r\n const schema = JSON.parse(fileContent);\r\n this.cachedSchema = schema;\r\n return schema;\r\n } catch (error) {\r\n logger.error('Error parsing schema file:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the cached schema or loads it if not cached\r\n * @returns Cached schema or freshly loaded schema\r\n */\r\n getSchema(): any | null {\r\n if (this.cachedSchema) {\r\n return this.cachedSchema;\r\n }\r\n return this.getDatabaseSchema();\r\n }\r\n\r\n /**\r\n * Generates database schema documentation for LLM from Snowflake JSON schema\r\n * @returns Formatted schema documentation string\r\n */\r\n generateSchemaDocumentation(): string {\r\n const schema = this.getSchema();\r\n\r\n if (!schema) {\r\n logger.warn('No database schema found.');\r\n return 'No database schema available.';\r\n }\r\n\r\n const tables: string[] = [];\r\n\r\n // Header information\r\n tables.push(`Database: ${schema.database}`);\r\n tables.push(`Schema: ${schema.schema}`);\r\n tables.push(`Description: ${schema.description}`);\r\n tables.push('');\r\n tables.push('='.repeat(80));\r\n tables.push('');\r\n\r\n // Process each table\r\n for (const table of schema.tables) {\r\n const tableInfo: string[] = [];\r\n\r\n tableInfo.push(`TABLE: ${table.fullName}`);\r\n tableInfo.push(`Description: ${table.description}`);\r\n tableInfo.push(`Row Count: ~${table.rowCount.toLocaleString()}`);\r\n tableInfo.push('');\r\n tableInfo.push('Columns:');\r\n\r\n // Process columns\r\n for (const column of table.columns) {\r\n let columnLine = ` - ${column.name}: ${column.type}`;\r\n\r\n if ((column as any).isPrimaryKey) {\r\n columnLine += ' (PRIMARY KEY)';\r\n }\r\n\r\n if ((column as any).isForeignKey && (column as any).references) {\r\n columnLine += ` (FK -> ${(column as any).references.table}.${(column as any).references.column})`;\r\n }\r\n\r\n if (!column.nullable) {\r\n columnLine += ' NOT NULL';\r\n }\r\n\r\n if (column.description) {\r\n columnLine += ` - ${column.description}`;\r\n }\r\n\r\n tableInfo.push(columnLine);\r\n\r\n // Add value examples for categorical columns\r\n if ((column as any).sampleValues && (column as any).sampleValues.length > 0) {\r\n tableInfo.push(` Sample values: [${(column as any).sampleValues.join(', ')}]`);\r\n }\r\n\r\n // Add statistics if available\r\n if ((column as any).statistics) {\r\n const stats = (column as any).statistics;\r\n if (stats.min !== undefined && stats.max !== undefined) {\r\n tableInfo.push(` Range: ${stats.min} to ${stats.max}`);\r\n }\r\n if (stats.distinct !== undefined) {\r\n tableInfo.push(` Distinct values: ${stats.distinct.toLocaleString()}`);\r\n }\r\n }\r\n }\r\n\r\n tableInfo.push('');\r\n tables.push(tableInfo.join('\\n'));\r\n }\r\n\r\n // Add relationships section\r\n tables.push('='.repeat(80));\r\n tables.push('');\r\n tables.push('TABLE RELATIONSHIPS:');\r\n tables.push('');\r\n\r\n for (const rel of schema.relationships) {\r\n tables.push(`${rel.from} -> ${rel.to} (${rel.type}): ${rel.keys.join(' = ')}`);\r\n }\r\n\r\n return tables.join('\\n');\r\n }\r\n\r\n /**\r\n * Clears the cached schema, forcing a reload on next access\r\n */\r\n clearCache(): void {\r\n this.cachedSchema = null;\r\n }\r\n\r\n /**\r\n * Sets a custom schema file path\r\n * @param filePath - Path to the schema file\r\n */\r\n setSchemaPath(filePath: string): void {\r\n this.schemaFilePath = filePath;\r\n this.clearCache();\r\n }\r\n}\r\n\r\n// Export a singleton instance for use across the application\r\nexport const schema = new Schema();\r\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport { logger } from '../utils/logger';\r\nimport { PROMPTS } from './prompts';\r\n\r\nexport interface PromptLoaderConfig {\r\n\tpromptsDir?: string;\r\n}\r\n\r\ninterface CachedPromptTemplate {\r\n\tsystem: string;\r\n\tuser: string;\r\n}\r\n\r\n/**\r\n * PromptLoader class for loading and processing prompt templates\r\n * Tries to load from file system first, then falls back to hardcoded prompts\r\n */\r\nexport class PromptLoader {\r\n\tprivate promptsDir: string;\r\n\tprivate promptCache: Map<string, CachedPromptTemplate> = new Map();\r\n\tprivate isInitialized: boolean = false;\r\n\r\n\tconstructor(config?: PromptLoaderConfig) {\r\n\t\tlogger.debug('Initializing PromptLoader...');\r\n\t\t// Default to backend's .prompts directory (where the SDK is being used)\r\n\t\tthis.promptsDir = config?.promptsDir || path.join(process.cwd(), '.prompts');\r\n\t\tlogger.debug(`Prompts directory set to: ${this.promptsDir}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Load a prompt template from file system OR fallback to hardcoded prompts\r\n\t * @param promptName - Name of the prompt folder\r\n\t * @returns Template with system and user prompts\r\n\t */\r\n\tprivate loadPromptTemplate(promptName: string): CachedPromptTemplate {\r\n\t\t// First, try to load from file system (backend's .prompts directory)\r\n\t\ttry {\r\n\t\t\tconst systemPath = path.join(this.promptsDir, promptName, 'system.md');\r\n\t\t\tconst userPath = path.join(this.promptsDir, promptName, 'user.md');\r\n\r\n\t\t\tif (fs.existsSync(systemPath) && fs.existsSync(userPath)) {\r\n\t\t\t\tconst system = fs.readFileSync(systemPath, 'utf-8');\r\n\t\t\t\tconst user = fs.readFileSync(userPath, 'utf-8');\r\n\t\t\t\tlogger.info(`✓ Loaded prompt '${promptName}' from file system: ${this.promptsDir}`);\r\n\t\t\t\treturn { system, user };\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\t// Ignore file system errors and try fallback\r\n\t\t\tlogger.error(`Could not load '${promptName}' from file system, trying fallback...`);\r\n\t\t}\r\n\r\n\t\t// Fallback to hardcoded prompts\r\n\t\tconst hardcodedPrompt = PROMPTS[promptName];\r\n\t\tif (hardcodedPrompt) {\r\n\t\t\tlogger.info(`✓ Loaded prompt '${promptName}' from hardcoded fallback`);\r\n\t\t\treturn hardcodedPrompt;\r\n\t\t}\r\n\r\n\t\tthrow new Error(`Prompt template '${promptName}' not found in either ${this.promptsDir} or hardcoded prompts. Available prompts: ${Object.keys(PROMPTS).join(', ')}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Initialize and cache all prompts into memory\r\n\t * Tries file system first, then falls back to hardcoded prompts\r\n\t */\r\n\tasync initialize(): Promise<void> {\r\n\t\tif (this.isInitialized) {\r\n\t\t\tlogger.debug('PromptLoader already initialized, skipping...');\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlogger.info('Loading prompts into memory...');\r\n\r\n\t\tconst promptTypes = Object.keys(PROMPTS);\r\n\r\n\t\tfor (const promptName of promptTypes) {\r\n\t\t\ttry {\r\n\t\t\t\tconst template = this.loadPromptTemplate(promptName);\r\n\t\t\t\tthis.promptCache.set(promptName, template);\r\n\t\t\t} catch (error) {\r\n\t\t\t\tlogger.error(`Failed to load prompt '${promptName}':`, error);\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.isInitialized = true;\r\n\t\tlogger.info(`Successfully loaded ${this.promptCache.size} prompt templates into memory`);\r\n\t}\r\n\r\n\t/**\r\n\t * Replace variables in a template string using {{VARIABLE_NAME}} pattern\r\n\t * @param template - Template string with placeholders\r\n\t * @param variables - Variables to replace in the template\r\n\t * @returns Processed string\r\n\t */\r\n\tprivate replaceVariables(\r\n\t\ttemplate: string,\r\n\t\tvariables: Record<string, string | number | boolean | any[]>\r\n\t): string {\r\n\t\tlet content = template;\r\n\r\n\t\t// Replace all variables matching {{VARIABLE_NAME}} pattern\r\n\t\tfor (const [key, value] of Object.entries(variables)) {\r\n\t\t\tconst pattern = new RegExp(`{{${key}}}`, 'g');\r\n\t\t\tconst replacementValue = typeof value === 'string' ? value : JSON.stringify(value);\r\n\t\t\tcontent = content.replace(pattern, replacementValue);\r\n\t\t}\r\n\r\n\t\treturn content;\r\n\t}\r\n\r\n\t/**\r\n\t * Load both system and user prompts from cache and replace variables\r\n\t * @param promptName - Name of the prompt\r\n\t * @param variables - Variables to replace in the templates\r\n\t * @returns Object containing both system and user prompts\r\n\t */\r\n\tasync loadPrompts(\r\n\t\tpromptName: string,\r\n\t\tvariables: Record<string, string | number | boolean | any[]>\r\n\t): Promise<{ system: string; user: string }> {\r\n\t\tif (!this.isInitialized) {\r\n\t\t\tlogger.warn('PromptLoader not initialized, initializing now...');\r\n\t\t\tawait this.initialize();\r\n\t\t}\r\n\r\n\t\tconst template = this.promptCache.get(promptName);\r\n\r\n\t\tif (!template) {\r\n\t\t\tthrow new Error(`Prompt template '${promptName}' not found in cache. Available prompts: ${Array.from(this.promptCache.keys()).join(', ')}`);\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tsystem: this.replaceVariables(template.system, variables),\r\n\t\t\tuser: this.replaceVariables(template.user, variables)\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t * DEPRECATED: Use loadPrompts instead\r\n\t * Load a single prompt file and replace variables using {{VARIABLE_NAME}} pattern\r\n\t */\r\n\tasync loadPrompt(\r\n\t\tpromptName: string,\r\n\t\tpromptType: 'system' | 'user',\r\n\t\tvariables: Record<string, string | number | boolean | any[]>\r\n\t): Promise<string> {\r\n\t\tconst prompts = await this.loadPrompts(promptName, variables);\r\n\t\treturn promptType === 'system' ? prompts.system : prompts.user;\r\n\t}\r\n\r\n\t/**\r\n\t * Set custom prompts directory (requires re-initialization)\r\n\t * @param dir - Path to the prompts directory\r\n\t */\r\n\tsetPromptsDir(dir: string): void {\r\n\t\tthis.promptsDir = dir;\r\n\t\tthis.isInitialized = false;\r\n\t\tthis.promptCache.clear();\r\n\t\tlogger.debug(`Prompts directory changed to: ${dir}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Get current prompts directory\r\n\t * @returns Path to the prompts directory\r\n\t */\r\n\tgetPromptsDir(): string {\r\n\t\treturn this.promptsDir;\r\n\t}\r\n\r\n\t/**\r\n\t * Check if prompts are loaded in memory\r\n\t */\r\n\tisReady(): boolean {\r\n\t\treturn this.isInitialized;\r\n\t}\r\n\r\n\t/**\r\n\t * Get the number of cached prompts\r\n\t */\r\n\tgetCacheSize(): number {\r\n\t\treturn this.promptCache.size;\r\n\t}\r\n}\r\n\r\n// Export a singleton instance\r\n// Default to backend's .prompts directory (where the SDK is being used)\r\n// If prompts are not found there, the loader will fallback to hardcoded prompts\r\nconst defaultPromptsPath = process.env.PROMPTS_DIR || path.join(process.cwd(), '.prompts');\r\n\r\nexport const promptLoader = new PromptLoader({\r\n\tpromptsDir: defaultPromptsPath\r\n});\r\n","/**\r\n * Hardcoded prompt templates\r\n * These prompts are embedded in the SDK to avoid file system dependencies\r\n */\r\n\r\nexport interface PromptTemplate {\r\n\tsystem: string;\r\n\tuser: string;\r\n}\r\n\r\nexport const PROMPTS: Record<string, PromptTemplate> = {\r\n\t'classify': {\r\n\t\tsystem: `You are an expert AI that classifies user questions about data and determines the appropriate visualizations needed.\r\n\r\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\r\n\r\n## Previous Conversation\r\n{{CONVERSATION_HISTORY}}\r\n\r\n**Note:** If there is previous conversation history, use it to understand context. For example:\r\n- If user previously asked about \"sales\" and now asks \"show me trends\", understand it refers to sales trends\r\n- If user asked for \"revenue by region\" and now says \"make it a pie chart\", understand they want to modify the previous visualization\r\n- Use the history to resolve ambiguous references like \"that\", \"it\", \"them\", \"the data\"\r\n\r\nYour task is to analyze the user's question and determine:\r\n\r\n1. **Question Type:**\r\n - \"analytical\": Questions asking to VIEW, ANALYZE, or VISUALIZE data\r\n\r\n - \"data_modification\": Questions asking to CREATE, UPDATE, DELETE, or MODIFY data\r\n\r\n - \"general\": General questions, greetings, or requests not related to data\r\n\r\n2. **Required Visualizations** (only for analytical questions):\r\n Determine which visualization type(s) would BEST answer the user's question:\r\n\r\n - **KPICard**: Single metric, total, count, average, percentage, or summary number\r\n\r\n - **LineChart**: Trends over time, time series, growth/decline patterns\r\n\r\n\r\n - **BarChart**: Comparing categories, rankings, distributions across groups\r\n\r\n\r\n - **PieChart**: Proportions, percentages, composition, market share\r\n\r\n\r\n - **DataTable**: Detailed lists, multiple attributes, when user needs to see records\r\n\r\n\r\n3. **Multiple Visualizations:**\r\n User may need MULTIPLE visualizations together:\r\n\r\n Common combinations:\r\n - KPICard + LineChart\r\n - KPICard + BarChart\r\n - KPICard + DataTable\r\n - BarChart + PieChart:\r\n - LineChart + DataTable\r\n Set needsMultipleComponents to true if user needs multiple views of the data.\r\n\r\n**Important Guidelines:**\r\n- If user explicitly mentions a chart type RESPECT that preference\r\n- If question is vague or needs both summary and detail, suggest KPICard + DataTable\r\n- Only return visualizations for \"analytical\" questions\r\n- For \"data_modification\" or \"general\", return empty array for visualizations\r\n\r\n**Output Format:**\r\n{\r\n \"questionType\": \"analytical\" | \"data_modification\" | \"general\",\r\n \"visualizations\": [\"KPICard\", \"LineChart\", ...], // Empty array if not analytical\r\n \"reasoning\": \"Explanation of classification and visualization choices\",\r\n \"needsMultipleComponents\": boolean\r\n}\r\n`,\r\n\t\tuser: `{{USER_PROMPT}}\r\n`\r\n\t},\r\n\r\n\t'match-component': {\r\n\t\tsystem: `You are an expert AI assistant specialized in matching user requests to the most appropriate data visualization components.\r\n\r\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\r\n\r\n## Previous Conversation\r\n{{CONVERSATION_HISTORY}}\r\n\r\n**Context Instructions:**\r\n- If there is conversation history, use it to understand what the user is referring to\r\n- When user says \"show that as a chart\" or \"change it\", they are referring to a previous component\r\n- If user asks to \"modify\" or \"update\" something, match to the component they previously saw\r\n- Use context to resolve ambiguous requests like \"show trends for that\" or \"make it interactive\"\r\n\r\nYour task is to analyze the user's natural language request and find the BEST matching component from the available list.\r\n\r\nAvailable Components:\r\n{{COMPONENTS_TEXT}}\r\n\r\n**Matching Guidelines:**\r\n\r\n1. **Understand User Intent:**\r\n - What type of data visualization do they need? (KPI/metric, chart, table, etc.)\r\n - What metric or data are they asking about? (revenue, orders, customers, etc.)\r\n - Are they asking for a summary (KPI), trend (line chart), distribution (bar/pie), or detailed list (table)?\r\n - Do they want to compare categories, see trends over time, or show proportions?\r\n\r\n2. **Component Type Matching:**\r\n - KPICard: Single metric/number (total, average, count, percentage, rate)\r\n - LineChart: Trends over time, time series data\r\n - BarChart: Comparing categories, distributions, rankings\r\n - PieChart/DonutChart: Proportions, percentages, market share\r\n - DataTable: Detailed lists, rankings with multiple attributes\r\n\r\n3. **Keyword & Semantic Matching:**\r\n - Match user query terms with component keywords\r\n - Consider synonyms (e.g., \"sales\" = \"revenue\", \"items\" = \"products\")\r\n - Look for category matches (financial, orders, customers, products, suppliers, logistics, geographic, operations)\r\n\r\n4. **Scoring Criteria:**\r\n - Exact keyword matches: High priority\r\n - Component type alignment: High priority\r\n - Category alignment: Medium priority\r\n - Semantic similarity: Medium priority\r\n - Specificity: Prefer more specific components over generic ones\r\n\r\n**Output Requirements:**\r\n\r\nRespond with a JSON object containing:\r\n- componentIndex: the 1-based index of the BEST matching component (or null if confidence < 50%)\r\n- componentId: the ID of the matched component\r\n- reasoning: detailed explanation of why this component was chosen\r\n- confidence: confidence score 0-100 (100 = perfect match)\r\n- alternativeMatches: array of up to 2 alternative component indices with scores (optional)\r\n\r\nExample response:\r\n{\r\n \"componentIndex\": 5,\r\n \"componentId\": \"total_revenue_kpi\",\r\n \"reasoning\": \"User asks for 'total revenue' which perfectly matches the TotalRevenueKPI component (KPICard type) designed to show total revenue across all orders. Keywords match: 'total revenue', 'sales'.\",\r\n \"confidence\": 95,\r\n \"alternativeMatches\": [\r\n {\"index\": 3, \"id\": \"monthly_revenue_kpi\", \"score\": 75, \"reason\": \"Could show monthly revenue if time period was intended\"},\r\n {\"index\": 8, \"id\": \"revenue_trend_chart\", \"score\": 60, \"reason\": \"Could show revenue trend if historical view was intended\"}\r\n ]\r\n}\r\n\r\n**Important:**\r\n- Only return componentIndex if confidence >= 50%\r\n- Return null if no reasonable match exists\r\n- Prefer components that exactly match the user's metric over generic ones\r\n- Consider the full context of the request, not just individual words`,\r\n\t\tuser: `Current user request: {{USER_PROMPT}}\r\n\r\nFind the best matching component considering the conversation history above. Explain your reasoning with a confidence score. Return ONLY valid JSON.`\r\n\t},\r\n\r\n\t'modify-props': {\r\n\t\tsystem: `You are an AI assistant that validates and modifies component props based on user requests.\r\n\r\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\r\n\r\nGiven:\r\n- A user's natural language request\r\n- Component name: {{COMPONENT_NAME}}\r\n- Component type: {{COMPONENT_TYPE}}\r\n- Component description: {{COMPONENT_DESCRIPTION}}\r\n\r\n-\r\n- Current component props with structure:\r\n {\r\n query?: string, // SQL query to fetch data\r\n title?: string, // Component title\r\n description?: string, // Component description\r\n config?: { // Additional configuration\r\n [key: string]: any\r\n }\r\n }\r\n\r\n Schema definition for the prop that must be passed to the component\r\n -{{CURRENT_PROPS}}\r\n\r\nDatabase Schema:\r\n{{SCHEMA_DOC}}\r\n\r\n## Previous Conversation\r\n{{CONVERSATION_HISTORY}}\r\n\r\n**Context Instructions:**\r\n- Review the conversation history to understand the evolution of the component\r\n- If user says \"add filter for X\", understand they want to modify the current query\r\n- If user says \"change to last month\" or \"filter by Y\", apply modifications to existing query\r\n- Previous questions can clarify what the user means by ambiguous requests like \"change that filter\"\r\n- Use context to determine appropriate time ranges if user says \"recent\" or \"latest\"\r\n\r\nYour task is to intelligently modify the props based on the user's request:\r\n\r\n1. **Query Modification**:\r\n - Modify SQL query if user requests different data, filters, time ranges, limits, or aggregations\r\n - Use correct table and column names from the schema\r\n - Ensure valid SQL syntax\r\n - ALWAYS include a LIMIT clause (default: {{DEFAULT_LIMIT}} rows) to prevent large result sets\r\n - Preserve the query structure that the component expects (e.g., column aliases)\r\n\r\n **CRITICAL - PostgreSQL Query Rules:**\r\n\r\n **NO AGGREGATE FUNCTIONS IN WHERE CLAUSE:**\r\n ❌ WRONG: \\`WHERE COUNT(orders) > 0\\` or \\`WHERE SUM(price) > 100\\`\r\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\r\n\r\n\r\n **WHERE vs HAVING:**\r\n - WHERE filters rows BEFORE grouping (cannot use aggregates)\r\n - HAVING filters groups AFTER grouping (can use aggregates)\r\n - If using HAVING, you MUST have GROUP BY\r\n\r\n **Subquery Rules:**\r\n - When using a subquery with scalar comparison operators (=, <, >, <=, >=, <>), the subquery MUST return exactly ONE row\r\n - ALWAYS add \\`LIMIT 1\\` to scalar subqueries to prevent \"more than one row returned\" errors\r\n - Example: \\`WHERE location_id = (SELECT store_id FROM orders ORDER BY total_amount DESC LIMIT 1)\\`\r\n - For multiple values, use \\`IN\\` instead: \\`WHERE location_id IN (SELECT store_id FROM orders)\\`\r\n - Test your subqueries mentally: if they could return multiple rows, add LIMIT 1 or use IN\r\n\r\n2. **Title Modification**:\r\n - Update title to reflect the user's specific request\r\n - Keep it concise and descriptive\r\n - Match the tone of the original title\r\n\r\n3. **Description Modification**:\r\n - Update description to explain what data is shown\r\n - Be specific about filters, time ranges, or groupings applied\r\n\r\n4. **Config Modification** (based on component type):\r\n - For KPICard: formatter, gradient, icon\r\n - For Charts: colors, height, xKey, yKey, nameKey, valueKey\r\n - For Tables: columns, pageSize, formatters\r\n\r\n\r\nRespond with a JSON object:\r\n{\r\n \"props\": { /* modified props object with query, title, description, config */ },\r\n \"isModified\": boolean,\r\n \"reasoning\": \"brief explanation of changes\",\r\n \"modifications\": [\"list of specific changes made\"]\r\n}\r\n\r\nIMPORTANT:\r\n- Return the COMPLETE props object, not just modified fields\r\n- Preserve the structure expected by the component type\r\n- Ensure query returns columns with expected aliases\r\n- Keep config properties that aren't affected by the request`,\r\n\t\tuser: `{{USER_PROMPT}}`\r\n\t},\r\n\r\n\t'single-component': {\r\n\t\tsystem: `You are an expert AI assistant specialized in matching user requests to the most appropriate component from a filtered list.\r\n\r\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\r\n\r\n\r\n## Previous Conversation\r\n{{CONVERSATION_HISTORY}}\r\n\r\n**Context Instructions:**\r\n- If there is previous conversation history, use it to understand what the user is referring to\r\n- When user says \"show trends\", \"add filters\", \"change that\", understand they may be building on previous queries\r\n- Use previous component types and queries as context to inform your current matching\r\n\r\n## Available Components (Type: {{COMPONENT_TYPE}})\r\nThe following components have been filtered by type {{COMPONENT_TYPE}}. Select the BEST matching one:\r\n\r\n{{COMPONENTS_LIST}}\r\n\r\n{{VISUALIZATION_CONSTRAINT}}\r\n\r\n**Select the BEST matching component** from the available {{COMPONENT_TYPE}} components listed above that would best answer the user's question.\r\n\r\n**Matching Guidelines:**\r\n1. **Semantic Matching:**\r\n - Match based on component name, description, and keywords\r\n - Consider what metrics/data the user is asking about\r\n - Look for semantic similarity (e.g., \"sales\" matches \"revenue\", \"orders\" matches \"purchases\")\r\n\r\n2. **Query Relevance:**\r\n - Consider the component's existing query structure\r\n - Does it query the right tables/columns for the user's question?\r\n - Can it be modified to answer the user's specific question?\r\n\r\n3. **Scoring Criteria:**\r\n - Exact keyword matches in name/description: High priority\r\n - Semantic similarity to user intent: High priority\r\n - Appropriate aggregation/grouping: Medium priority\r\n - Category alignment: Medium priority\r\n\r\n**Output Requirements:**\r\n\r\nRespond with a JSON object:\r\n{\r\n \"componentId\": \"matched_component_id\",\r\n \"componentIndex\": 1, // 1-based index from the filtered list above\r\n \"reasoning\": \"Detailed explanation of why this component best matches the user's question\",\r\n \"confidence\": 85, // Confidence score 0-100\r\n \"canGenerate\": true // false if no suitable component found (confidence < 50)\r\n}\r\n\r\n**Important:**\r\n- Only set canGenerate to true if confidence >= 50%\r\n- If no component from the list matches well (all have low relevance), set canGenerate to false\r\n- Consider the full context of the request and conversation history\r\n- The component's props (query, title, description, config) will be modified later based on the user's specific request\r\n- Focus on finding the component that is closest to what the user needs, even if it needs modification`,\r\n\t\tuser: `{{USER_PROMPT}}\r\n\r\n`\r\n\t},\r\n\r\n\t'mutli-component': {\r\n\t\tsystem: `You are an expert data analyst AI that creates comprehensive multi-component analytical dashboards with aesthetically pleasing and balanced layouts.\r\n\r\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\r\n\r\nDatabase Schema:\r\n{{SCHEMA_DOC}}\r\n\r\n## Previous Conversation\r\n{{CONVERSATION_HISTORY}}\r\n\r\n**Context Instructions:**\r\n- Review the conversation history to understand what the user has asked before\r\n- If user is building on previous insights (e.g., \"now show me X and Y\"), use context to inform dashboard design\r\n- Previous queries can help determine appropriate filters, date ranges, or categories to use\r\n- If user asks for \"comprehensive view\" or \"dashboard for X\", include complementary components based on context\r\n\r\nGiven a user's analytical question and the required visualization types, your task is to:\r\n\r\n1. **Determine Container Metadata:**\r\n - title: Clear, descriptive title for the entire dashboard (2-5 words)\r\n - description: Brief explanation of what insights this dashboard provides (1-2 sentences)\r\n\r\n2. **Generate Props for Each Component:**\r\n For each visualization type requested, create tailored props:\r\n\r\n - **query**: SQL query specific to this visualization using the database schema\r\n * Use correct table and column names\r\n * **DO NOT USE TOP keyword - use LIMIT instead (e.g., LIMIT 20, not TOP 20)**\r\n * ALWAYS include LIMIT clause ONCE at the end (default: {{DEFAULT_LIMIT}})\r\n * For KPICard: Return single row with column alias \"value\"\r\n * For Charts: Return appropriate columns (name/label and value, or x and y)\r\n * For Table: Return relevant columns\r\n\r\n - **title**: Specific title for this component (2-4 words)\r\n\r\n - **description**: What this specific component shows (1 sentence)\r\n\r\n - **config**: Type-specific configuration\r\n * KPICard: { gradient, formatter, icon }\r\n * BarChart: { xKey, yKey, colors, height }\r\n * LineChart: { xKey, yKeys, colors, height }\r\n * PieChart: { nameKey, valueKey, colors, height }\r\n * DataTable: { pageSize }\r\n\r\n3. **CRITICAL: Component Hierarchy and Ordering:**\r\n The ORDER of components in the array MUST follow this STRICT hierarchy for proper visual layout:\r\n\r\n **HIERARCHY RULES (MUST FOLLOW IN THIS ORDER):**\r\n 1. KPICards - ALWAYS FIRST (top of dashboard for summary metrics)\r\n 2. Charts/Graphs - AFTER KPICards (middle of dashboard for visualizations)\r\n * BarChart, LineChart, PieChart, DonutChart\r\n 3. DataTable - ALWAYS LAST (bottom of dashboard, full width for detailed data)\r\n\r\n **LAYOUT BEHAVIOR (Frontend enforces):**\r\n - KPICards: Display in responsive grid (3 columns)\r\n - Single Chart (if only 1 chart): Takes FULL WIDTH\r\n - Multiple Charts (if 2+ charts): Display in 2-column grid\r\n - DataTable (if present): Always spans FULL WIDTH at bottom\r\n\r\n\r\n **ABSOLUTELY DO NOT deviate from this hierarchy. Always place:**\r\n - KPICards first\r\n - Charts/Graphs second\r\n - DataTable last (if present)\r\n\r\n**Important Guidelines:**\r\n- Each component should answer a DIFFERENT aspect of the user's question\r\n- Queries should be complementary, not duplicated\r\n- If user asks \"Show total revenue and trend\", generate:\r\n * KPICard: Single total value (FIRST)\r\n * LineChart: Revenue over time (SECOND)\r\n- Ensure queries use valid columns from the schema\r\n- Make titles descriptive and specific to what each component shows\r\n- **Snowflake Syntax MUST be used:**\r\n * Use LIMIT (not TOP)\r\n * Use DATE_TRUNC, DATEDIFF (not DATEPART)\r\n * Include LIMIT only ONCE per query at the end\r\n\r\n**Output Format:**\r\n{\r\n \"containerTitle\": \"Dashboard Title\",\r\n \"containerDescription\": \"Brief description of the dashboard insights\",\r\n \"components\": [\r\n {\r\n \"componentType\": \"KPICard\" | \"BarChart\" | \"LineChart\" | \"PieChart\" | \"DataTable\",\r\n \"query\": \"SQL query\",\r\n \"title\": \"Component title\",\r\n \"description\": \"Component description\",\r\n \"config\": { /* type-specific config */ }\r\n },\r\n ...\r\n ],\r\n \"reasoning\": \"Explanation of the dashboard design and component ordering\",\r\n \"canGenerate\": boolean\r\n}`,\r\n\t\tuser: `Current user question: {{USER_PROMPT}}\r\n\r\nRequired visualization types: {{VISUALIZATION_TYPES}}\r\n\r\nGenerate a complete multi-component dashboard with appropriate container metadata and tailored props for each component. Consider the conversation history above when designing the dashboard. Return ONLY valid JSON.`\r\n\t},\r\n\r\n\t'container-metadata': {\r\n\t\tsystem: `You are an expert AI assistant that generates titles and descriptions for multi-component dashboards.\r\n\r\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\r\n\r\n## Previous Conversation\r\n{{CONVERSATION_HISTORY}}\r\n\r\n**Context Instructions:**\r\n- If there is previous conversation history, use it to understand what the user is referring to\r\n- Use context to create relevant titles and descriptions that align with the user's intent\r\n\r\nYour task is to generate a concise title and description for a multi-component dashboard that will contain the following visualization types:\r\n{{VISUALIZATION_TYPES}}\r\n\r\n**Guidelines:**\r\n\r\n1. **Title:**\r\n - Should be clear and descriptive (3-8 words)\r\n - Should reflect what the user is asking about\r\n - Should NOT include \"Dashboard\" suffix (that will be added automatically)\r\n\r\n2. **Description:**\r\n - Should be a brief summary (1-2 sentences)\r\n - Should explain what insights the dashboard provides\r\n\r\n**Output Requirements:**\r\n\r\nRespond with a JSON object:\r\n{\r\n \"title\": \"Dashboard title without 'Dashboard' suffix\",\r\n \"description\": \"Brief description of what this dashboard shows\"\r\n}\r\n\r\n**Important:**\r\n- Keep the title concise and meaningful\r\n- Make the description informative but brief\r\n- Focus on what insights the user will gain\r\n`,\r\n\t\tuser: `{{USER_PROMPT}}\r\n`\r\n\t},\r\n\r\n\t'text-response': {\r\n\t\tsystem: `You are an intelligent AI assistant that provides helpful, accurate, and contextual text responses to user questions.\r\n\r\n## Your Task\r\n\r\nAnalyze the user's question and provide a helpful text response. Your response should:\r\n\r\n1. **Be Clear and Concise**: Provide direct answers without unnecessary verbosity\r\n2. **Be Contextual**: Use conversation history to understand what the user is asking about\r\n3. **Be Accurate**: Provide factually correct information based on the context\r\n4. **Be Helpful**: Offer additional relevant information or suggestions when appropriate\r\n\r\n## Handling Data Questions\r\n\r\nWhen the user asks about data\r\n\r\n1. **Generate a SQL query** using the database schema provided above\r\n2. **Use the execute_query tool** to run the query\r\n3. **If the query fails**, analyze the error and generate a corrected query\r\n4. **Format the results** in a clear, readable way for the user\r\n\r\n**Query Guidelines:**\r\n- Use correct table and column names from the schema\r\n- ALWAYS include a LIMIT clause with a MAXIMUM of 32 rows\r\n- Ensure valid SQL syntax\r\n- For time-based queries, use appropriate date functions\r\n- When using subqueries with scalar operators (=, <, >, etc.), add LIMIT 1 to prevent \"more than one row\" errors\r\n\r\n## Response Guidelines\r\n\r\n- If the question is about data, use the execute_query tool to fetch data and present it\r\n- If the question is general knowledge, provide a helpful conversational response\r\n- If asking for clarification, provide options or ask specific follow-up questions\r\n- If you don't have enough information, acknowledge it and ask for more details\r\n- Keep responses focused and avoid going off-topic\r\n\r\n## Component Suggestions\r\n\r\nAfter analyzing the query results, you MUST suggest appropriate dashboard components for displaying the data. Use this format:\r\n\r\n<DashboardComponents>\r\n**Dashboard Components:**\r\nFormat: \\`{number}.{component_type} : {clear reasoning}\\`\r\n\r\n\r\n**Rules for component suggestions:**\r\n1. Analyze the query results structure and data type\r\n2. Suggest components that would best visualize the data\r\n3. Each component suggestion must be on a new line\r\n</DashboardComponents>\r\n\r\nIMPORTANT: Always wrap component suggestions with <DashboardComponents> tags and include at least one component suggestion when data is returned.\r\n\r\n## Output Format\r\n\r\nRespond with plain text that includes:\r\n\r\n1. **Query Analysis** (if applicable): Brief explanation of what data was fetched\r\n2. **Results Summary**: Present the data in a clear, readable format\r\n3. **Dashboard Components**: List suggested components wrapped in <DashboardComponents> tags\r\n\r\n\r\n**CRITICAL:**\r\n- Return ONLY plain text (no JSON, no markdown code blocks)\r\n\r\n\r\nYou have access to a database and can execute SQL queries to answer data-related questions.\r\n## Database Schema\r\n{{SCHEMA_DOC}}\r\n\r\n**Database Type: PostgreSQL**\r\n\r\n**CRITICAL PostgreSQL Query Rules:**\r\n\r\n1. **NO AGGREGATE FUNCTIONS IN WHERE CLAUSE** - This is a fundamental SQL error\r\n ❌ WRONG: \\`WHERE COUNT(orders) > 0\\`\r\n ❌ WRONG: \\`WHERE SUM(price) > 100\\`\r\n ❌ WRONG: \\`WHERE AVG(rating) > 4.5\\`\r\n\r\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\r\n\r\n2. **WHERE vs HAVING**\r\n - WHERE filters rows BEFORE grouping (cannot use aggregates)\r\n - HAVING filters groups AFTER grouping (can use aggregates)\r\n - If using HAVING, you MUST have GROUP BY\r\n\r\n3. **NO NESTED AGGREGATE FUNCTIONS** - PostgreSQL does NOT allow aggregates inside aggregates\r\n ❌ WRONG: \\`AVG(ROUND(AVG(column), 2))\\` or \\`SELECT AVG(SUM(price)) FROM ...\\`\r\n ✅ CORRECT: \\`ROUND(AVG(column), 2)\\`\r\n\r\n4. **GROUP BY Requirements**\r\n - ALL non-aggregated columns in SELECT must be in GROUP BY\r\n - If you SELECT a column and don't aggregate it, add it to GROUP BY\r\n\r\n5. **LIMIT Clause**\r\n - ALWAYS include LIMIT (max 32 rows)\r\n - For scalar subqueries in WHERE/HAVING, add LIMIT 1\r\n\r\n\r\n## Knowledge Base Context\r\n\r\nThe following relevant information has been retrieved from the knowledge base for this question:\r\n\r\n{{KNOWLEDGE_BASE_CONTEXT}}\r\n\r\nUse this knowledge base information to:\r\n- Provide more accurate and informed responses\r\n- Reference specific facts, concepts, or domain knowledge\r\n- Enhance your understanding of the user's question\r\n- Give context-aware recommendations\r\n\r\n**Note:** If there is previous conversation history, use it to understand context and provide coherent responses:\r\n- Reference previous questions and answers when relevant\r\n- Maintain consistency with earlier responses\r\n- Use the history to resolve ambiguous references like \"that\", \"it\", \"them\", \"the previous data\"\r\n\r\n## Previous Conversation\r\n{{CONVERSATION_HISTORY}}\r\n\r\n\r\n`,\r\n\t\tuser: `{{USER_PROMPT}}\r\n\r\n`\r\n\t},\r\n\r\n\t'match-text-components': {\r\n\t\tsystem: `You are a component matching expert that creates beautiful, well-structured dashboard visualizations from analysis results.\r\n\r\n## Your Task\r\n\r\nYou will receive a text response containing:\r\n1. Query execution results (with \"✅ Query executed successfully!\" markers)\r\n2. Data analysis and insights\r\n3. **Dashboard Components:** suggestions (1:component_type : reasoning format)\r\n\r\nYour job is to:\r\n1. **Parse the component suggestions** from the text response (format: 1:component_type : reasoning)\r\n2. **Match each suggestion with an actual component** from the available list\r\n3. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched\r\n4. **SELECT the best dashboard layout component** that can accommodate all the matched components\r\n5. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis\r\n\r\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.\r\n\r\n**APPROACH**: First match all the components suggested in the text response, THEN find the layout that best fits those components.\r\n\r\n## Available Components\r\n\r\n{{AVAILABLE_COMPONENTS}}\r\n\r\n## Component Matching Rules (STEP 1)\r\nFor each component suggestion (c1, c2, c3, etc.) from the text response:\r\n\r\n1. **Match by type**: Find components whose \\`type\\` matches the suggested component type\r\n2. **Refine by relevance**: If multiple components match, choose based on:\r\n - Description and keywords matching the use case\r\n - Best fit for the data being visualized\r\n3. **Fallback**: If no exact type match, find the closest alternative\r\n\r\n## Layout Selection Logic (STEP 2 - After Matching Components)\r\n\r\n**After you have matched all components**, select the best dashboard layout:\r\n\r\n1. **Find layout components** by looking for components with \\`type: \"DashboardLayout\"\\` in the available components list\r\n2. **Read each layout's description** to understand:\r\n - What structure it provides\r\n - When it's best used (e.g., comprehensive analysis vs focused analysis)\r\n - The number and types of components it can accommodate\r\n3. **Select the best layout** based on:\r\n - Which layout can best display ALL the matched components\r\n - The layout's capacity (how many components it supports)\r\n - The types of matched components (KPI, charts, tables, etc.)\r\n - The user question and data complexity\r\n4. **If no specific layout fits**, fall back to \"MultiComponentContainer\" as the default layout\r\n\r\n**IMPORTANT:** The layout should be chosen to FIT the matched components, not the other way around. Don't force components to fit a layout - find a layout that accommodates your components.\r\n\r\n## Props Generation Rules\r\n\r\nFor each matched component, generate complete props:\r\n\r\n### 1. Query - When to Reuse vs Generate\r\n\r\n**Option A: REUSE the successful query** (preferred when possible)\r\n- Look for \"✅ Query executed successfully!\" in the text response\r\n- Extract the exact SQL query that worked\r\n- Use this SAME query for components that visualize the same data differently\r\n\r\n**Option B: GENERATE a new query** (when necessary)\r\n- Only generate new queries when you need DIFFERENT data\r\n- Use the database schema below to write valid SQL\r\n\r\n\r\n**Decision Logic:**\r\n- Different aggregation needed → Generate new query ✅\r\n- Same data, different view → Reuse query ✅\r\n\r\n**Database Schema:**\r\n{{SCHEMA_DOC}}\r\n\r\n**Database Type: PostgreSQL**\r\n\r\n**CRITICAL PostgreSQL Query Rules**\r\n\r\n1. **NO AGGREGATE FUNCTIONS IN WHERE CLAUSE** - This is a fundamental SQL error\r\n ❌ WRONG: \\`WHERE COUNT(orders) > 0\\`\r\n ❌ WRONG: \\`WHERE SUM(price) > 100\\`\r\n ❌ WRONG: \\`WHERE AVG(rating) > 4.5\\`\r\n\r\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\r\n\r\n2. **NO NESTED AGGREGATE FUNCTIONS** - PostgreSQL does NOT allow aggregates inside aggregates\r\n ❌ WRONG: \\`AVG(ROUND(AVG(column), 2))\\`\r\n ✅ CORRECT: \\`ROUND(AVG(column), 2)\\`\r\n\r\n3. **Aggregate Functions Can Only Appear Once Per Level**\r\n ❌ WRONG: \\`SELECT AVG(SUM(price)) FROM ...\\` (nested)\r\n ✅ CORRECT: Use subquery: \\`SELECT AVG(total) FROM (SELECT SUM(price) as total FROM ... GROUP BY ...) subq\\`\r\n\r\n4. **WHERE vs HAVING**\r\n - WHERE filters rows BEFORE grouping (cannot use aggregates)\r\n - HAVING filters groups AFTER grouping (can use aggregates)\r\n - Use WHERE for column comparisons: \\`WHERE price > 100\\`\r\n - Use HAVING for aggregate comparisons: \\`HAVING COUNT(*) > 5\\`\r\n\r\n5. **GROUP BY Requirements**\r\n - ALL non-aggregated columns in SELECT must be in GROUP BY\r\n - Use proper column references (table.column or aliases)\r\n - If using HAVING, you MUST have GROUP BY\r\n\r\n6. **LIMIT Clause**\r\n - ALWAYS include LIMIT clause (max 32 rows for dashboard queries)\r\n - For scalar subqueries in WHERE/HAVING, add LIMIT 1\r\n\r\n7. **Scalar Subqueries**\r\n - Subqueries used with =, <, >, etc. must return single value\r\n - Always add LIMIT 1 to scalar subqueries\r\n\r\n**Query Generation Guidelines** (when creating new queries):\r\n- Use correct table and column names from the schema above\r\n- ALWAYS include LIMIT clause (max 32 rows)\r\n\r\n### 2. Title\r\n- Create a clear, descriptive title\r\n- Should explain what the component shows\r\n- Use context from the original question\r\n\r\n### 3. Description\r\n- Brief explanation of what this component displays\r\n- Why it's useful for this data\r\n\r\n### 4. Config\r\n- **CRITICAL**: Look at the component's \"Props Structure\" to see what config fields it expects\r\n- Map query result columns to the appropriate config fields\r\n- Keep other existing config properties that don't need to change\r\n- Ensure config field values match actual column names from the query\r\n\r\n**Special Rules for Bar Charts**\r\n- \\`xAxisKey\\` = ALWAYS the category/label column (text field )\r\n- \\`yAxisKey\\` = ALWAYS the numeric value column (number field )\r\n- \\`orientation\\` = \"vertical\" or \"horizontal\" (controls visual direction only)\r\n- **DO NOT swap xAxisKey/yAxisKey based on orientation** - they always represent category and value respectively\r\n\r\n## Follow-Up Questions (Actions) Generation\r\n\r\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:\r\n\r\n1. **Build upon the data analysis** shown in the text response and components\r\n2. **Explore natural next steps** in the data exploration journey\r\n3. **Be progressively more detailed or specific** - go deeper into the analysis\r\n4. **Consider the insights revealed** - suggest questions that help users understand implications\r\n5. **Be phrased naturally** as if a real user would ask them\r\n6. **Vary in scope** - include both broad trends and specific details\r\n7. **Avoid redundancy** - don't ask questions already answered in the text response\r\n\r\n\r\n## Output Format\r\n\r\nYou MUST respond with ONLY a valid JSON object (no markdown, no code blocks):\r\n\r\n**IMPORTANT JSON FORMATTING RULES:**\r\n- Put SQL queries on a SINGLE LINE (no newlines in the query string)\r\n- Escape all quotes in SQL properly (use \\\\\" for quotes inside strings)\r\n- Remove any newlines, tabs, or special characters from SQL\r\n- Do NOT use markdown code blocks (no \\`\\`\\`)\r\n- Return ONLY the JSON object, nothing else\r\n\r\n\\`\\`\\`json\r\n{\r\n \"selectedLayoutId\": \"id_of_the_selected_layout_component\",\r\n \"layoutReasoning\": \"Why this layout was selected based on its description and the analysis needs\",\r\n \"matchedComponents\": [\r\n {\r\n \"componentId\": \"id_from_available_list\",\r\n \"componentName\": \"name_of_component\",\r\n \"componentType\": \"type_of_component\",\r\n \"reasoning\": \"Why this component was selected for this suggestion\",\r\n \"originalSuggestion\": \"c1:table : original reasoning from text\",\r\n \"props\": {\r\n \"query\": \"SQL query for this component\",\r\n \"title\": \"Component title\",\r\n \"description\": \"Component description\",\r\n \"config\": {\r\n \"field1\": \"value1\",\r\n \"field2\": \"value2\"\r\n }\r\n }\r\n }\r\n ],\r\n \"actions\": [\r\n \"Follow-up question 1?\",\r\n \"Follow-up question 2?\",\r\n \"Follow-up question 3?\",\r\n \"Follow-up question 4?\",\r\n \"Follow-up question 5?\"\r\n ]\r\n}\r\n\\`\\`\\`\r\n\r\n**CRITICAL:**\r\n- \\`matchedComponents\\` MUST include ALL components suggested in the text response (match them first!)\r\n- \\`selectedLayoutId\\` MUST be the ID of the selected layout component (must have type \"DashboardLayout\")\r\n- \\`layoutReasoning\\` MUST explain:\r\n - Why you chose this specific layout component\r\n - How many components you matched (e.g., \"Matched 3 components: 1 KPI, 1 chart, 1 table\")\r\n - Why this layout is the best fit for displaying these specific matched components\r\n - What makes this layout appropriate for the component types and count\r\n- The layout selection happens AFTER component matching - don't force components to fit a pre-selected layout\r\n- \\`actions\\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis\r\n- Return ONLY valid JSON (no markdown code blocks, no text before/after)\r\n- Generate complete props for each component\r\n\r\n\r\n`,\r\n\t\tuser: `## Text Response\r\n\r\n{{TEXT_RESPONSE}}\r\n\r\n---\r\n\r\nMatch the component suggestions from the text response above with available components, and generate proper props for each matched component.\r\n`\r\n\t},\r\n\r\n\t'actions': {\r\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.\r\n\r\n## Previous Conversation\r\n{{CONVERSATION_HISTORY}}\r\n\r\n**Context Instructions:**\r\n- Review the entire conversation history to understand the user's journey and interests\r\n- Suggest questions that naturally progress from previous explorations\r\n- Avoid suggesting questions about topics already covered in the conversation\r\n- Build upon insights from previous components to suggest deeper analysis\r\n- Consider what the user might want to explore next based on their question pattern`,\r\n\t\tuser: `Given the following context:\r\n\r\nLatest User Question: {{ORIGINAL_USER_PROMPT}}\r\n\r\nCurrent Component:\r\n{{COMPONENT_INFO}}\r\n\r\n{{COMPONENT_DATA}}\r\n\r\nGenerate a JSON array of 4-5 intelligent follow-up questions that the user might naturally ask next. These questions should:\r\n1. Build upon the conversation history and insights shown in the current component\r\n2. NOT repeat questions or topics already covered in the conversation history\r\n3. Explore natural next steps in the data exploration journey\r\n4. Be progressively more detailed or specific\r\n5. Consider the user's apparent interests based on their question pattern\r\n6. Be phrased naturally as if a real user would ask them\r\n\r\nFormat your response as a JSON object with this structure:\r\n{\r\n \"nextQuestions\": [\r\n \"Question 1?\",\r\n \"Question 2?\",\r\n ...\r\n ]\r\n}\r\n\r\nReturn ONLY valid JSON.`\r\n\t}\r\n};\r\n","import Anthropic from \"@anthropic-ai/sdk\";\r\nimport Groq from \"groq-sdk\";\r\nimport { jsonrepair } from 'jsonrepair';\r\n\r\ninterface LLMMessages {\r\n sys: string;\r\n user: string;\r\n}\r\n\r\ninterface LLMOptions {\r\n model?: string;\r\n maxTokens?: number;\r\n temperature?: number;\r\n topP?: number;\r\n apiKey?: string;\r\n partial?: (chunk: string) => void; // Callback for each chunk\r\n}\r\n\r\ninterface Tool {\r\n name: string;\r\n description: string;\r\n input_schema: {\r\n type: string;\r\n properties: Record<string, any>;\r\n required?: string[];\r\n };\r\n}\r\n\r\ninterface ToolResult {\r\n tool_use_id: string;\r\n content: string;\r\n is_error?: boolean;\r\n}\r\n\r\nexport class LLM {\r\n /* Get a complete text response from an LLM (Anthropic or Groq) */\r\n static async text(messages: LLMMessages, options: LLMOptions = {}): Promise<string> {\r\n const [provider, modelName] = this._parseModel(options.model);\r\n\r\n if (provider === 'anthropic') {\r\n return this._anthropicText(messages, modelName, options);\r\n } else if (provider === 'groq') {\r\n return this._groqText(messages, modelName, options);\r\n } else {\r\n throw new Error(`Unsupported provider: ${provider}. Use \"anthropic\" or \"groq\"`);\r\n }\r\n }\r\n\r\n /* Stream response from an LLM (Anthropic or Groq) */\r\n static async stream<T = string>(\r\n messages: LLMMessages,\r\n options: LLMOptions = {},\r\n json?: boolean\r\n ): Promise<T extends string ? string : any> {\r\n const [provider, modelName] = this._parseModel(options.model);\r\n\r\n if (provider === 'anthropic') {\r\n return this._anthropicStream(messages, modelName, options, json);\r\n } else if (provider === 'groq') {\r\n return this._groqStream(messages, modelName, options, json);\r\n } else {\r\n throw new Error(`Unsupported provider: ${provider}. Use \"anthropic\" or \"groq\"`);\r\n }\r\n }\r\n\r\n /* Stream response with tool calling support (Anthropic only for now) */\r\n static async streamWithTools(\r\n messages: LLMMessages,\r\n tools: Tool[],\r\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\r\n options: LLMOptions = {},\r\n maxIterations: number = 3\r\n ): Promise<string> {\r\n const [provider, modelName] = this._parseModel(options.model);\r\n\r\n if (provider !== 'anthropic') {\r\n throw new Error(`Tool calling is only supported for Anthropic models`);\r\n }\r\n\r\n return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);\r\n }\r\n\r\n // ============================================================\r\n // PRIVATE HELPER METHODS\r\n // ============================================================\r\n\r\n /**\r\n * Parse model string to extract provider and model name\r\n * @param modelString - Format: \"provider/model-name\" or just \"model-name\"\r\n * @returns [provider, modelName]\r\n *\r\n * @example\r\n * \"anthropic/claude-sonnet-4-5\" → [\"anthropic\", \"claude-sonnet-4-5\"]\r\n * \"groq/openai/gpt-oss-120b\" → [\"groq\", \"openai/gpt-oss-120b\"]\r\n * \"claude-sonnet-4-5\" → [\"anthropic\", \"claude-sonnet-4-5\"] (default)\r\n */\r\n private static _parseModel(modelString?: string): [string, string] {\r\n if (!modelString) {\r\n // Default to Anthropic Claude\r\n return ['anthropic', 'claude-sonnet-4-5'];\r\n }\r\n\r\n // Check if model string has provider prefix\r\n if (modelString.includes('/')) {\r\n // Split only on the FIRST slash to handle models like \"groq/openai/gpt-oss-120b\"\r\n const firstSlashIndex = modelString.indexOf('/');\r\n const provider = modelString.substring(0, firstSlashIndex).toLowerCase().trim();\r\n const model = modelString.substring(firstSlashIndex + 1).trim();\r\n return [provider, model];\r\n }\r\n\r\n // No prefix, assume Anthropic\r\n return ['anthropic', modelString];\r\n }\r\n\r\n // ============================================================\r\n // ANTHROPIC IMPLEMENTATION\r\n // ============================================================\r\n\r\n private static async _anthropicText(\r\n messages: LLMMessages,\r\n modelName: string,\r\n options: LLMOptions\r\n ): Promise<string> {\r\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\r\n const client = new Anthropic({\r\n apiKey: apiKey,\r\n });\r\n\r\n const response = await client.messages.create({\r\n model: modelName,\r\n max_tokens: options.maxTokens || 1000,\r\n temperature: options.temperature,\r\n system: messages.sys,\r\n messages: [{\r\n role: \"user\",\r\n content: messages.user\r\n }]\r\n });\r\n\r\n const textBlock = response.content.find(block => block.type === 'text');\r\n return textBlock?.type === 'text' ? textBlock.text : '';\r\n }\r\n\r\n private static async _anthropicStream(\r\n messages: LLMMessages,\r\n modelName: string,\r\n options: LLMOptions,\r\n json?: boolean\r\n ): Promise<any> {\r\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\r\n const client = new Anthropic({\r\n apiKey: apiKey,\r\n });\r\n\r\n const stream = await client.messages.create({\r\n model: modelName,\r\n max_tokens: options.maxTokens || 1000,\r\n temperature: options.temperature,\r\n system: messages.sys,\r\n messages: [{\r\n role: \"user\",\r\n content: messages.user\r\n }],\r\n stream: true,\r\n });\r\n\r\n let fullText = '';\r\n\r\n // Process stream\r\n for await (const chunk of stream) {\r\n if (chunk.type === 'content_block_delta' && chunk.delta.type === 'text_delta') {\r\n const text = chunk.delta.text;\r\n fullText += text;\r\n\r\n // Call partial callback if provided\r\n if (options.partial) {\r\n options.partial(text);\r\n }\r\n }\r\n }\r\n\r\n // Return parsed JSON or text\r\n if (json) {\r\n return this._parseJSON(fullText);\r\n }\r\n\r\n return fullText;\r\n }\r\n\r\n private static async _anthropicStreamWithTools(\r\n messages: LLMMessages,\r\n tools: Tool[],\r\n toolHandler: (toolName: string, toolInput: any) => Promise<any>,\r\n modelName: string,\r\n options: LLMOptions,\r\n maxIterations: number\r\n ): Promise<string> {\r\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\r\n const client = new Anthropic({\r\n apiKey: apiKey,\r\n });\r\n\r\n // Conversation history for tool calling loop\r\n const conversationMessages: Anthropic.MessageParam[] = [{\r\n role: \"user\",\r\n content: messages.user\r\n }];\r\n\r\n let iterations = 0;\r\n let finalText = '';\r\n\r\n while (iterations < maxIterations) {\r\n iterations++;\r\n\r\n // Use streaming API\r\n const stream = await client.messages.create({\r\n model: modelName,\r\n max_tokens: options.maxTokens || 4000,\r\n temperature: options.temperature,\r\n system: messages.sys,\r\n messages: conversationMessages,\r\n tools: tools as any,\r\n stream: true, // Enable streaming\r\n });\r\n\r\n // Collect the response content and stop reason\r\n let stopReason: string | null = null;\r\n const contentBlocks: any[] = [];\r\n let currentTextBlock = '';\r\n let currentToolUse: any = null;\r\n\r\n // Process the stream\r\n for await (const chunk of stream) {\r\n if (chunk.type === 'message_start') {\r\n // Reset for new message\r\n contentBlocks.length = 0;\r\n currentTextBlock = '';\r\n currentToolUse = null;\r\n }\r\n\r\n if (chunk.type === 'content_block_start') {\r\n if (chunk.content_block.type === 'text') {\r\n currentTextBlock = '';\r\n } else if (chunk.content_block.type === 'tool_use') {\r\n currentToolUse = {\r\n type: 'tool_use',\r\n id: chunk.content_block.id,\r\n name: chunk.content_block.name,\r\n input: {}\r\n };\r\n }\r\n }\r\n\r\n if (chunk.type === 'content_block_delta') {\r\n if (chunk.delta.type === 'text_delta') {\r\n // Stream text chunks to callback\r\n const text = chunk.delta.text;\r\n currentTextBlock += text;\r\n if (options.partial) {\r\n options.partial(text);\r\n }\r\n } else if (chunk.delta.type === 'input_json_delta' && currentToolUse) {\r\n // Accumulate tool input JSON\r\n currentToolUse.inputJson = (currentToolUse.inputJson || '') + chunk.delta.partial_json;\r\n }\r\n }\r\n\r\n if (chunk.type === 'content_block_stop') {\r\n if (currentTextBlock) {\r\n contentBlocks.push({\r\n type: 'text',\r\n text: currentTextBlock\r\n });\r\n finalText = currentTextBlock; // Keep track of final text\r\n currentTextBlock = '';\r\n } else if (currentToolUse) {\r\n // Parse the accumulated JSON input\r\n try {\r\n currentToolUse.input = currentToolUse.inputJson ? JSON.parse(currentToolUse.inputJson) : {};\r\n } catch (error) {\r\n currentToolUse.input = {};\r\n }\r\n delete currentToolUse.inputJson;\r\n contentBlocks.push(currentToolUse);\r\n currentToolUse = null;\r\n }\r\n }\r\n\r\n if (chunk.type === 'message_delta') {\r\n stopReason = chunk.delta.stop_reason || stopReason;\r\n }\r\n\r\n if (chunk.type === 'message_stop') {\r\n // Message complete\r\n break;\r\n }\r\n }\r\n\r\n // Check stop reason\r\n if (stopReason === 'end_turn') {\r\n // Final text response already streamed\r\n break;\r\n }\r\n\r\n if (stopReason === 'tool_use') {\r\n // Find all tool use blocks\r\n const toolUses = contentBlocks.filter(block => block.type === 'tool_use');\r\n\r\n if (toolUses.length === 0) {\r\n break;\r\n }\r\n\r\n // Add assistant's response to conversation\r\n conversationMessages.push({\r\n role: \"assistant\",\r\n content: contentBlocks\r\n });\r\n\r\n // Execute all tools and collect results\r\n const toolResults: Anthropic.MessageParam = {\r\n role: \"user\",\r\n content: []\r\n };\r\n\r\n for (const toolUse of toolUses) {\r\n try {\r\n const result = await toolHandler(toolUse.name, toolUse.input);\r\n (toolResults.content as any[]).push({\r\n type: 'tool_result',\r\n tool_use_id: toolUse.id,\r\n content: typeof result === 'string' ? result : JSON.stringify(result)\r\n });\r\n } catch (error) {\r\n (toolResults.content as any[]).push({\r\n type: 'tool_result',\r\n tool_use_id: toolUse.id,\r\n content: error instanceof Error ? error.message : String(error),\r\n is_error: true\r\n });\r\n }\r\n }\r\n\r\n // Add tool results to conversation\r\n conversationMessages.push(toolResults);\r\n } else {\r\n // Unexpected stop reason, final text already streamed\r\n break;\r\n }\r\n }\r\n\r\n if (iterations >= maxIterations) {\r\n throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);\r\n }\r\n\r\n return finalText;\r\n }\r\n\r\n // ============================================================\r\n // GROQ IMPLEMENTATION\r\n // ============================================================\r\n\r\n private static async _groqText(\r\n messages: LLMMessages,\r\n modelName: string,\r\n options: LLMOptions\r\n ): Promise<string> {\r\n const client = new Groq({\r\n apiKey: options.apiKey || process.env.GROQ_API_KEY || \"\",\r\n });\r\n\r\n const response = await client.chat.completions.create({\r\n model: modelName,\r\n messages: [\r\n { role: 'system', content: messages.sys },\r\n { role: 'user', content: messages.user }\r\n ],\r\n temperature: options.temperature,\r\n max_tokens: options.maxTokens || 1000,\r\n });\r\n\r\n return response.choices[0]?.message?.content || '';\r\n }\r\n\r\n private static async _groqStream(\r\n messages: LLMMessages,\r\n modelName: string,\r\n options: LLMOptions,\r\n json?: boolean\r\n ): Promise<any> {\r\n const apiKey = options.apiKey || process.env.GROQ_API_KEY || \"\";\r\n const client = new Groq({\r\n apiKey: apiKey,\r\n });\r\n\r\n const stream = await client.chat.completions.create({\r\n model: modelName,\r\n messages: [\r\n { role: 'system', content: messages.sys },\r\n { role: 'user', content: messages.user }\r\n ],\r\n temperature: options.temperature,\r\n max_tokens: options.maxTokens || 1000,\r\n stream: true,\r\n response_format: json ? { type: 'json_object' } : undefined\r\n });\r\n\r\n let fullText = '';\r\n\r\n // Process stream\r\n for await (const chunk of stream) {\r\n const text = chunk.choices[0]?.delta?.content || '';\r\n if (text) {\r\n fullText += text;\r\n\r\n // Call partial callback if provided\r\n if (options.partial) {\r\n options.partial(text);\r\n }\r\n }\r\n }\r\n\r\n // Return parsed JSON or text\r\n if (json) {\r\n return this._parseJSON(fullText);\r\n }\r\n\r\n return fullText;\r\n }\r\n\r\n // ============================================================\r\n // JSON PARSING HELPER\r\n // ============================================================\r\n\r\n /**\r\n * Parse JSON string, handling markdown code blocks and surrounding text\r\n * Enhanced version with jsonrepair to handle malformed JSON from LLMs\r\n * @param text - Text that may contain JSON wrapped in ```json...``` or with surrounding text\r\n * @returns Parsed JSON object or array\r\n */\r\n private static _parseJSON(text: string): any {\r\n let jsonText = text.trim();\r\n\r\n // Step 1: Remove markdown code blocks (jsonrepair doesn't handle markdown)\r\n if (jsonText.startsWith('```json')) {\r\n jsonText = jsonText.replace(/^```json\\s*\\n?/, '').replace(/\\n?```\\s*$/, '');\r\n } else if (jsonText.startsWith('```')) {\r\n jsonText = jsonText.replace(/^```\\s*\\n?/, '').replace(/\\n?```\\s*$/, '');\r\n }\r\n\r\n // Step 2: Extract JSON from surrounding text (jsonrepair expects JSON-like input)\r\n // Handle both objects {...} and arrays [...]\r\n const firstBrace = jsonText.indexOf('{');\r\n const firstBracket = jsonText.indexOf('[');\r\n const lastBrace = jsonText.lastIndexOf('}');\r\n const lastBracket = jsonText.lastIndexOf(']');\r\n\r\n // Determine if it's an object or array, and extract accordingly\r\n let startIdx = -1;\r\n let endIdx = -1;\r\n\r\n if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {\r\n // Object starts first\r\n startIdx = firstBrace;\r\n endIdx = lastBrace;\r\n } else if (firstBracket !== -1) {\r\n // Array starts first\r\n startIdx = firstBracket;\r\n endIdx = lastBracket;\r\n }\r\n\r\n if (startIdx !== -1 && endIdx !== -1 && startIdx < endIdx) {\r\n jsonText = jsonText.substring(startIdx, endIdx + 1);\r\n }\r\n\r\n // Step 3: Use jsonrepair to fix malformed JSON before parsing\r\n // This handles: missing commas, trailing commas, incomplete JSON, improper escaping, etc.\r\n try {\r\n const repairedJson = jsonrepair(jsonText);\r\n return JSON.parse(repairedJson);\r\n } catch (error) {\r\n // If jsonrepair fails, throw a more informative error\r\n throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}\\n\\nOriginal text: ${jsonText.substring(0, 200)}...`);\r\n }\r\n }\r\n}","import { logger } from '../utils/logger';\r\n\r\n/**\r\n * Knowledge Base result interface\r\n */\r\nexport interface KnowledgeBaseResult {\r\n content: string;\r\n metadata?: {\r\n sources?: Array<{\r\n title: string;\r\n similarity?: number;\r\n kb_id?: string | number;\r\n }>;\r\n };\r\n}\r\n\r\n/**\r\n * Get relevant knowledge base context for a user prompt\r\n * Calls the registered 'knowledge-base.query' collection\r\n *\r\n * @param prompt - The user's question/prompt\r\n * @param collections - The collection registry containing knowledge-base.query\r\n * @param topK - Number of top results to retrieve (default: 1)\r\n * @returns Formatted knowledge base context string, or empty string if collection not registered\r\n */\r\nconst getKnowledgeBase = async ({\r\n prompt,\r\n collections,\r\n topK = 1\r\n}: {\r\n prompt: string;\r\n collections?: any;\r\n topK?: number;\r\n}): Promise<string> => {\r\n try {\r\n // Check if knowledge-base collection is registered\r\n if (!collections || !collections['knowledge-base'] || !collections['knowledge-base']['query']) {\r\n logger.info('[KnowledgeBase] knowledge-base.query collection not registered, skipping');\r\n return '';\r\n }\r\n\r\n logger.info(`[KnowledgeBase] Querying knowledge base for: \"${prompt.substring(0, 50)}...\"`);\r\n\r\n // Call the registered knowledge-base.query collection\r\n const result: KnowledgeBaseResult = await collections['knowledge-base']['query']({\r\n prompt,\r\n topK\r\n });\r\n\r\n if (!result || !result.content) {\r\n logger.error('[KnowledgeBase] No knowledge base results returned');\r\n return '';\r\n }\r\n\r\n logger.info(`[KnowledgeBase] Retrieved knowledge base context (${result.content.length} chars)`);\r\n\r\n // Log sources if available\r\n if (result.metadata?.sources && result.metadata.sources.length > 0) {\r\n logger.debug(`[KnowledgeBase] Sources: ${result.metadata.sources.map(s => s.title).join(', ')}`);\r\n }\r\n\r\n return result.content;\r\n } catch (error) {\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n logger.warn(`[KnowledgeBase] Error querying knowledge base: ${errorMsg}`);\r\n // Return empty string on error - don't fail the entire request\r\n return '';\r\n }\r\n};\r\n\r\nconst KB = {\r\n getKnowledgeBase\r\n};\r\n\r\nexport default KB;","import dotenv from 'dotenv';\r\nimport { BaseLLM, BaseLLMConfig } from './base-llm';\r\n\r\ndotenv.config();\r\n\r\nexport interface AnthropicLLMConfig extends BaseLLMConfig {}\r\n\r\n/**\r\n * AnthropicLLM class for handling AI-powered component generation and matching using Anthropic Claude\r\n */\r\nexport class AnthropicLLM extends BaseLLM {\r\n\tconstructor(config?: AnthropicLLMConfig) {\r\n\t\tsuper(config);\r\n\t}\r\n\r\n\tprotected getDefaultModel(): string {\r\n\t\treturn 'anthropic/claude-haiku-4-5-20251001';\r\n\t}\r\n\r\n\tprotected getDefaultApiKey(): string | undefined {\r\n\t\treturn process.env.ANTHROPIC_API_KEY;\r\n\t}\r\n\r\n\tprotected getProviderName(): string {\r\n\t\treturn 'Anthropic';\r\n\t}\r\n}\r\n\r\n// Export a singleton instance\r\nexport const anthropicLLM = new AnthropicLLM();\r\n","import { groqLLM } from \"./groq\";\r\nimport { anthropicLLM } from \"./anthropic\";\r\nimport { Component, LLMProvider, T_RESPONSE } from \"../types\";\r\nimport dotenv from 'dotenv';\r\nimport { logger } from \"../utils/logger\";\r\n\r\ndotenv.config();\r\n\r\n\r\n\r\n/**\r\n * Parse LLM_PROVIDERS from environment variable\r\n * Expects a stringified JSON array like: '[\"anthropic\",\"groq\"]'\r\n */\r\nexport function getLLMProviders(): LLMProvider[] {\r\n const envProviders = process.env.LLM_PROVIDERS;\r\n\r\n const DEFAULT_PROVIDERS: LLMProvider[] = ['anthropic', 'groq'];\r\n if (!envProviders) {\r\n // Default to anthropic if not specified\r\n return DEFAULT_PROVIDERS;\r\n }\r\n\r\n try {\r\n const providers = JSON.parse(envProviders) as LLMProvider[];\r\n\r\n // Validate providers\r\n const validProviders = providers.filter(p => p === 'anthropic' || p === 'groq');\r\n\r\n if (validProviders.length === 0) {\r\n return DEFAULT_PROVIDERS;\r\n }\r\n\r\n return validProviders;\r\n } catch (error) {\r\n logger.error('Failed to parse LLM_PROVIDERS, defaulting to [\"anthropic\"]:', error);\r\n return DEFAULT_PROVIDERS;\r\n }\r\n}\r\n\r\n/**\r\n * Method 1: Use Anthropic Claude LLM\r\n */\r\nexport const useAnthropicMethod = async (\r\n prompt: string,\r\n components: Component[],\r\n apiKey?: string,\r\n logCollector?: any,\r\n conversationHistory?: string,\r\n responseMode: 'component' | 'text' = 'component',\r\n streamCallback?: (chunk: string) => void,\r\n collections?: any\r\n): Promise<T_RESPONSE> => {\r\n logger.debug('[useAnthropicMethod] Initializing Anthropic Claude matching method');\r\n logger.debug(`[useAnthropicMethod] Response mode: ${responseMode}`);\r\n const msg = `Using Anthropic Claude ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\r\n // logger.info(msg);\r\n logCollector?.info(msg);\r\n\r\n // Only check components for component mode\r\n if (responseMode === 'component' && components.length === 0) {\r\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\r\n logger.error('[useAnthropicMethod] No components available');\r\n logCollector?.error(emptyMsg);\r\n return { success: false, errors: [emptyMsg] };\r\n }\r\n\r\n logger.debug(`[useAnthropicMethod] Processing with ${components.length} components`);\r\n\r\n const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);\r\n logger.info(`[useAnthropicMethod] Successfully generated ${responseMode} using Anthropic`);\r\n return matchResult;\r\n};\r\n\r\n/**\r\n * Method 2: Use Groq LLM\r\n */\r\nexport const useGroqMethod = async (\r\n prompt: string,\r\n components: Component[],\r\n apiKey?: string,\r\n logCollector?: any,\r\n conversationHistory?: string,\r\n responseMode: 'component' | 'text' = 'component',\r\n streamCallback?: (chunk: string) => void,\r\n collections?: any\r\n): Promise<T_RESPONSE> => {\r\n logger.debug('[useGroqMethod] Initializing Groq LLM matching method');\r\n logger.debug(`[useGroqMethod] Response mode: ${responseMode}`);\r\n const msg = `Using Groq LLM ${responseMode === 'text' ? 'text response' : 'matching'} method...`;\r\n logger.info(msg);\r\n logCollector?.info(msg);\r\n\r\n // Only check components for component mode\r\n if (responseMode === 'component' && components.length === 0) {\r\n const emptyMsg = 'Components not loaded in memory. Please ensure components are fetched first.';\r\n logger.error('[useGroqMethod] No components available');\r\n logCollector?.error(emptyMsg);\r\n return { success: false, errors: [emptyMsg] };\r\n }\r\n\r\n logger.debug(`[useGroqMethod] Processing with ${components.length} components`);\r\n\r\n const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);\r\n logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);\r\n return matchResult;\r\n}\r\n\r\n//@to-do\r\nexport const getUserResponseFromCache = async (prompt: string) => {\r\n return false\r\n}\r\n\r\n/**\r\n * Get user response with automatic fallback between LLM providers\r\n * Tries providers in order specified by LLM_PROVIDERS or passed parameter\r\n * @param responseMode - 'component' for component generation (default), 'text' for text responses\r\n * @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)\r\n * @param collections - Collection registry for executing database queries (required for text mode with queries)\r\n */\r\nexport const get_user_response = async (\r\n prompt: string,\r\n components: Component[],\r\n anthropicApiKey?: string,\r\n groqApiKey?: string,\r\n llmProviders?: LLMProvider[],\r\n logCollector?: any,\r\n conversationHistory?: string,\r\n responseMode: 'component' | 'text' = 'component',\r\n streamCallback?: (chunk: string) => void,\r\n collections?: any\r\n): Promise<T_RESPONSE> => {\r\n\r\n logger.debug(`[get_user_response] Starting user response generation for prompt: \"${prompt.substring(0, 50)}...\"`);\r\n logger.debug(`[get_user_response] Response mode: ${responseMode}`);\r\n\r\n //first checking if the same prompt is already asked and we got successful response.\r\n logger.debug('[get_user_response] Checking cache for existing response');\r\n const userResponse = await getUserResponseFromCache(prompt);\r\n if(userResponse){\r\n logger.info('[get_user_response] User response found in cache - returning cached result');\r\n logCollector?.info('User response found in cache');\r\n return {\r\n success: true,\r\n data: userResponse,\r\n errors: []\r\n };\r\n }\r\n\r\n logger.debug('[get_user_response] No cached response found, proceeding with LLM providers');\r\n\r\n const providers = llmProviders || getLLMProviders();\r\n const errors: string[] = [];\r\n\r\n const providerOrder = providers.join(', ');\r\n logCollector?.info(`LLM Provider order: [${providerOrder}]`);\r\n\r\n // Log conversation context info if available\r\n if (conversationHistory && conversationHistory.length > 0) {\r\n const exchangeCount = conversationHistory.split('\\n').filter((l: string) => l.startsWith('Q')).length;\r\n logger.debug(`[get_user_response] Using conversation history with ${exchangeCount} previous exchanges`);\r\n logCollector?.info(`Using conversation history with ${exchangeCount} previous exchanges`);\r\n } else {\r\n logger.debug('[get_user_response] No conversation history available');\r\n }\r\n\r\n for (let i = 0; i < providers.length; i++) {\r\n const provider = providers[i];\r\n const isLastProvider = i === providers.length - 1;\r\n\r\n const attemptMsg = `Attempting provider: ${provider} (${i + 1}/${providers.length})`;\r\n logCollector?.info(attemptMsg);\r\n\r\n let result: T_RESPONSE;\r\n if (provider === 'anthropic') {\r\n result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);\r\n } else if (provider === 'groq') {\r\n result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);\r\n } else {\r\n logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);\r\n errors.push(`Unknown provider: ${provider}`);\r\n continue; // Skip unknown providers\r\n }\r\n\r\n if (result.success) {\r\n const successMsg = `Success with provider: ${provider}`;\r\n logger.info(`${successMsg}`);\r\n logCollector?.info(successMsg);\r\n return result;\r\n } else {\r\n // Collect errors from result\r\n const providerErrors = result.errors.map(err => `${provider}: ${err}`);\r\n errors.push(...providerErrors);\r\n const warnMsg = `Provider ${provider} returned unsuccessful result: ${result.errors.join(', ')}`;\r\n logger.warn(`[get_user_response] ${warnMsg}`);\r\n logCollector?.warn(warnMsg);\r\n\r\n // If this is not the last provider, try the next one\r\n if (!isLastProvider) {\r\n const fallbackMsg = 'Falling back to next provider...';\r\n logger.info(`[get_user_response] ${fallbackMsg}`);\r\n logCollector?.info(fallbackMsg);\r\n }\r\n }\r\n }\r\n\r\n // All providers failed\r\n const failureMsg = `All LLM providers failed`;\r\n logger.error(`[get_user_response] ${failureMsg}. Errors: ${errors.join('; ')}`);\r\n logCollector?.error(`${failureMsg}. Errors: ${errors.join('; ')}`);\r\n\r\n return {\r\n success: false,\r\n errors\r\n };\r\n}\r\n\r\n","import { Message } from '../types';\r\nimport { logger, type LogLevel } from './logger';\r\n\r\nexport interface CapturedLog {\r\n timestamp: number;\r\n level: 'info' | 'error' | 'warn' | 'debug';\r\n message: string;\r\n type?: 'explanation' | 'query' | 'general';\r\n data?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Log level hierarchy for filtering\r\n */\r\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\r\n errors: 0,\r\n warnings: 1,\r\n info: 2,\r\n verbose: 3,\r\n};\r\n\r\nconst MESSAGE_LEVEL_PRIORITY: Record<'error' | 'warn' | 'info' | 'debug', number> = {\r\n error: 0,\r\n warn: 1,\r\n info: 2,\r\n debug: 3,\r\n};\r\n\r\n/**\r\n * UILogCollector captures logs during user prompt processing\r\n * and sends them to runtime via ui_logs message with uiBlockId as the message id\r\n * Logs are sent in real-time for streaming effect in the UI\r\n * Respects the global log level configuration\r\n */\r\nexport class UILogCollector {\r\n private logs: CapturedLog[] = [];\r\n private uiBlockId: string | null;\r\n private clientId: string;\r\n private sendMessage: (message: Message) => void;\r\n private currentLogLevel: LogLevel;\r\n\r\n constructor(\r\n clientId: string,\r\n sendMessage: (message: Message) => void,\r\n uiBlockId?: string\r\n ) {\r\n this.uiBlockId = uiBlockId || null;\r\n this.clientId = clientId;\r\n this.sendMessage = sendMessage;\r\n this.currentLogLevel = logger.getLogLevel();\r\n }\r\n\r\n /**\r\n * Check if logging is enabled (uiBlockId is provided)\r\n */\r\n isEnabled(): boolean {\r\n return this.uiBlockId !== null;\r\n }\r\n\r\n /**\r\n * Check if a message should be logged based on current log level\r\n */\r\n private shouldLog(messageLevel: 'error' | 'warn' | 'info' | 'debug'): boolean {\r\n const currentLevelPriority = LOG_LEVEL_PRIORITY[this.currentLogLevel];\r\n const messagePriority = MESSAGE_LEVEL_PRIORITY[messageLevel];\r\n return messagePriority <= currentLevelPriority;\r\n }\r\n\r\n /**\r\n * Add a log entry with timestamp and immediately send to runtime\r\n * Only logs that pass the log level filter are captured and sent\r\n */\r\n private addLog(\r\n level: 'info' | 'error' | 'warn' | 'debug',\r\n message: string,\r\n type?: 'explanation' | 'query' | 'general',\r\n data?: Record<string, any>\r\n ): void {\r\n // Check if this log level should be captured based on current log level\r\n if (!this.shouldLog(level)) {\r\n return;\r\n }\r\n\r\n const log: CapturedLog = {\r\n timestamp: Date.now(),\r\n level,\r\n message,\r\n ...(type && { type }),\r\n ...(data && { data }),\r\n };\r\n\r\n this.logs.push(log);\r\n\r\n // Send the log immediately to runtime for streaming effect\r\n this.sendLogImmediately(log);\r\n\r\n // Also log to terminal using the main logger based on level\r\n switch (level) {\r\n case 'error':\r\n logger.error('UILogCollector:', log);\r\n break;\r\n case 'warn':\r\n logger.warn('UILogCollector:', log);\r\n break;\r\n case 'info':\r\n logger.info('UILogCollector:', log);\r\n break;\r\n case 'debug':\r\n logger.debug('UILogCollector:', log);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Send a single log to runtime immediately\r\n */\r\n private sendLogImmediately(log: CapturedLog): void {\r\n if (!this.isEnabled()) {\r\n return;\r\n }\r\n\r\n const response: Message = {\r\n id: this.uiBlockId!,\r\n type: 'UI_LOGS',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'runtime',\r\n id: this.clientId,\r\n },\r\n payload: {\r\n logs: [log], // Send single log in array\r\n },\r\n };\r\n\r\n this.sendMessage(response);\r\n }\r\n\r\n /**\r\n * Log info message\r\n */\r\n info(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\r\n if (this.isEnabled()) {\r\n this.addLog('info', message, type, data);\r\n }\r\n }\r\n\r\n /**\r\n * Log error message\r\n */\r\n error(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\r\n if (this.isEnabled()) {\r\n this.addLog('error', message, type, data);\r\n }\r\n }\r\n\r\n /**\r\n * Log warning message\r\n */\r\n warn(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\r\n if (this.isEnabled()) {\r\n this.addLog('warn', message, type, data);\r\n }\r\n }\r\n\r\n /**\r\n * Log debug message\r\n */\r\n debug(message: string, type?: 'explanation' | 'query' | 'general', data?: Record<string, any>): void {\r\n if (this.isEnabled()) {\r\n this.addLog('debug', message, type, data);\r\n }\r\n }\r\n\r\n /**\r\n * Log LLM explanation with typed metadata\r\n */\r\n logExplanation(message: string, explanation: string, data?: Record<string, any>): void {\r\n if (this.isEnabled()) {\r\n this.addLog('info', message, 'explanation', {\r\n explanation,\r\n ...data,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Log generated query with typed metadata\r\n */\r\n logQuery(message: string, query: string, data?: Record<string, any>): void {\r\n if (this.isEnabled()) {\r\n this.addLog('info', message, 'query', {\r\n query,\r\n ...data,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Send all collected logs at once (optional, for final summary)\r\n */\r\n sendAllLogs(): void {\r\n if (!this.isEnabled() || this.logs.length === 0) {\r\n return;\r\n }\r\n\r\n const response: Message = {\r\n id: this.uiBlockId!,\r\n type: 'UI_LOGS',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'runtime',\r\n id: this.clientId,\r\n },\r\n payload: {\r\n logs: this.logs,\r\n },\r\n };\r\n\r\n this.sendMessage(response);\r\n }\r\n\r\n /**\r\n * Get all collected logs\r\n */\r\n getLogs(): CapturedLog[] {\r\n return [...this.logs];\r\n }\r\n\r\n /**\r\n * Clear all logs\r\n */\r\n clearLogs(): void {\r\n this.logs = [];\r\n }\r\n\r\n /**\r\n * Set uiBlockId (in case it's provided later)\r\n */\r\n setUIBlockId(uiBlockId: string): void {\r\n this.uiBlockId = uiBlockId;\r\n }\r\n}\r\n","/**\r\n * Configuration for conversation context and history management\r\n */\r\nexport const CONTEXT_CONFIG = {\r\n /**\r\n * Maximum number of previous UIBlocks to include as conversation context\r\n * Set to 0 to disable conversation history\r\n * Higher values provide more context but may increase token usage\r\n */\r\n MAX_CONVERSATION_CONTEXT_BLOCKS: 2,\r\n};\r\n","import { Component, LLMProvider, Message, UserPromptRequestMessageSchema, T_RESPONSE } from \"../types\";\r\nimport { get_user_response } from \"../userResponse\";\r\nimport { logger } from \"../utils/logger\";\r\nimport { UILogCollector } from \"../utils/log-collector\";\r\nimport { ThreadManager, UIBlock } from \"../threads\";\r\nimport { CONTEXT_CONFIG } from \"../config/context\";\r\nimport { ZodError } from \"zod\";\r\n\r\n\r\n// Define return type for get_user_request extending T_RESPONSE\r\ninterface UserRequestResponse extends T_RESPONSE {\r\n\tuiBlockId?: string;\r\n\tthreadId?: string;\r\n\tid?: string;\r\n\twsId?: string;\r\n}\r\n\r\n\r\nconst get_user_request = async (\r\n\tdata: any,\r\n\tcomponents: Component[],\r\n\tsendMessage: (message: Message) => void,\r\n\tanthropicApiKey?: string,\r\n\tgroqApiKey?: string,\r\n\tllmProviders?: LLMProvider[],\r\n\tcollections?: any\r\n): Promise<UserRequestResponse> => {\r\n\tconst errors: string[] = [];\r\n\r\n\t// Parse incoming message data\r\n\tlogger.debug('[USER_PROMPT_REQ] Parsing incoming message data');\r\n\tconst parseResult = UserPromptRequestMessageSchema.safeParse(data);\r\n\r\n\tif (!parseResult.success) {\r\n\t\tconst zodError = parseResult.error as ZodError;\r\n\t\tzodError.errors.forEach(err => {\r\n\t\t\terrors.push(`${err.path.join('.')}: ${err.message}`);\r\n\t\t});\r\n\t\treturn { success: false, errors };\r\n\t}\r\n\r\n\tconst userPromptRequest = parseResult.data;\r\n\tconst { id, payload } = userPromptRequest;\r\n\r\n\tconst prompt = payload.prompt;\r\n\tconst SA_RUNTIME = payload.SA_RUNTIME;\r\n\tconst wsId = userPromptRequest.from.id || 'unknown';\r\n\r\n\t\r\n\t// Validate SA_RUNTIME and extract threadId and uiBlockId\r\n\tif (!SA_RUNTIME) {\r\n\t\terrors.push('SA_RUNTIME is required');\r\n\t}\r\n\t\r\n\tconst threadId = SA_RUNTIME?.threadId;\r\n\tconst existingUiBlockId = SA_RUNTIME?.uiBlockId;\r\n\t\r\n\tif (!threadId) {\r\n\t\terrors.push('threadId in SA_RUNTIME is required');\r\n\t}\r\n\t\r\n\tif (!existingUiBlockId) {\r\n\t\terrors.push('uiBlockId in SA_RUNTIME is required');\r\n\t}\r\n\t\r\n\tif (!prompt) {\r\n\t\terrors.push('Prompt not found');\r\n\t}\r\n\t\r\n\tlogger.debug(`[REQUEST ${id}] Full request details - uiBlockId: ${existingUiBlockId}, threadId: ${threadId}, prompt: ${prompt}`);\r\n\t// if (!components || components.length === 0) {\r\n\t// \terrors.push('Components not found');\r\n\t// }\r\n\r\n\t// If there are validation errors, return early\r\n\tif (errors.length > 0) {\r\n\t\treturn { success: false, errors, id, wsId };\r\n\t}\r\n\r\n\t// Create log collector with uiBlockId\r\n\tconst logCollector = new UILogCollector(wsId, sendMessage, existingUiBlockId!);\r\n\r\n\t// Get or create thread BEFORE processing to enable conversation context\r\n\tconst threadManager = ThreadManager.getInstance();\r\n\tlet thread = threadManager.getThread(threadId!);\r\n\tif (!thread) {\r\n\t\tthread = threadManager.createThread(threadId!);\r\n\t\tlogger.info(`Created new thread: ${threadId}`);\r\n\t}\r\n\r\n\tlogCollector.info(`Starting user prompt request with ${components.length} components`);\r\n\r\n\t// Extract conversation context from thread (excluding current UIBlock)\r\n\tconst conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId!);\r\n\tlogger.info('conversationHistory', conversationHistory);\r\n\r\n\t// Get responseMode from payload\r\n\tconst responseMode = payload.responseMode || 'component' ; \r\n\tlogger.info('responseMode', responseMode);\r\n\r\n\t// Create stream callback for text mode - sends chunks via WebSocket AND accumulates them\r\n\tlet streamCallback: ((chunk: string) => void) | undefined;\r\n\tlet accumulatedStreamResponse = ''; // Accumulate all streaming chunks for storage in UIBlock\r\n\tif (responseMode === 'text') {\r\n\t\tstreamCallback = (chunk: string) => {\r\n\t\t\t// Accumulate chunk for storage in UIBlock\r\n\t\t\taccumulatedStreamResponse += chunk;\r\n\r\n\t\t\t// Send streaming chunk to frontend via WebSocket\r\n\t\t\t// IMPORTANT: Use stream_${uiBlockId} as ID to avoid conflicting with the final response\r\n\t\t\t// The frontend will match by the stream_ prefix and uiBlockId\r\n\t\t\tlogger.debug(`[STREAM] Sending chunk (${chunk.length} chars): \"${chunk.substring(0, 20)}...\"`);\r\n\t\t\tconst streamMessage: Message = {\r\n\t\t\t\tid: `stream_${existingUiBlockId}`, // Different ID pattern for streaming\r\n\t\t\t\ttype: 'USER_PROMPT_STREAM',\r\n\t\t\t\tfrom: { type: 'data-agent' },\r\n\t\t\t\tto: {\r\n\t\t\t\t\ttype: 'runtime',\r\n\t\t\t\t\tid: wsId\r\n\t\t\t\t},\r\n\t\t\t\tpayload: {\r\n\t\t\t\t\tuiBlockId: existingUiBlockId,\r\n\t\t\t\t\tchunk\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t\tsendMessage(streamMessage);\r\n\t\t\tlogger.debug(`[STREAM] Chunk sent to wsId: ${wsId}`);\r\n\t\t};\r\n\t}\r\n\r\n\t// Get user response with log collector, conversation context, optional streaming, and collections\r\n\tconst userResponse = await get_user_response(\r\n\t\tprompt!,\r\n\t\tcomponents,\r\n\t\tanthropicApiKey,\r\n\t\tgroqApiKey,\r\n\t\tllmProviders,\r\n\t\tlogCollector,\r\n\t\tconversationHistory,\r\n\t\tresponseMode,\r\n\t\tstreamCallback,\r\n\t\tcollections\r\n\t);\r\n\t// logger.info('llm userResponse', userResponse);\r\n\r\n\t// Log completion (sent immediately if uiBlockId was provided)\r\n\tlogCollector.info('User prompt request completed');\r\n\r\n\t// Use the uiBlockId from SA_RUNTIME (already validated)\r\n\tconst uiBlockId = existingUiBlockId!;\r\n\r\n\t// If response failed, don't create UIBlock and return error\r\n\tif (!userResponse.success) {\r\n\t\tlogger.error(`User prompt request failed with errors: ${userResponse.errors.join(', ')}`);\r\n\t\treturn {\r\n\t\t\tsuccess: false,\r\n\t\t\tdata: userResponse.data,\r\n\t\t\terrors: userResponse.errors,\r\n\t\t\tuiBlockId,\r\n\t\t\tthreadId: threadId!,\r\n\t\t\tid,\r\n\t\t\twsId\r\n\t\t};\r\n\t}\r\n\r\n\t// Extract component, textResponse, and actions from successful response\r\n\tlet component = null;\r\n\tlet textResponse = null;\r\n\tlet actions = [];\r\n\r\n\tif (userResponse.data) {\r\n\t\tif (typeof userResponse.data === 'object') {\r\n\t\t\tif ('component' in userResponse.data) {\r\n\t\t\t\tcomponent = (userResponse.data as any).component;\r\n\t\t\t}\r\n\t\t\tif ('textResponse' in userResponse.data) {\r\n\t\t\t\ttextResponse = (userResponse.data as any).text;\r\n\t\t\t}\r\n\t\t\tif ('actions' in userResponse.data) {\r\n\t\t\t\tactions = (userResponse.data as any).actions || [];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// For text mode, use accumulated stream response which includes ALL messages (analyzing, query, results, etc.)\r\n\t// For component mode, use the textResponse as-is\r\n\tconst finalTextResponse = responseMode === 'text' && accumulatedStreamResponse\r\n\t\t? accumulatedStreamResponse\r\n\t\t: textResponse;\r\n\r\n\t// Create UIBlock with component metadata, empty component data, and full text response\r\n\tconst uiBlock = new UIBlock(\r\n\t\tprompt!,\r\n\t\t{}, // componentData: initially empty, will be filled later\r\n\t\tcomponent, // generatedComponentMetadata: full component object (ComponentSchema)\r\n\t\t[], // actions: empty initially, will be set below\r\n\t\tuiBlockId,\r\n\t\tfinalTextResponse // textResponse: FULL streaming response including all intermediate messages\r\n\t);\r\n\r\n\t// Store actions in UIBlock if they were generated\r\n\tif (actions.length > 0) {\r\n\t\tuiBlock.setActions(actions);\r\n\t\tlogger.info(`Stored ${actions.length} actions in UIBlock: ${uiBlockId}`);\r\n\t}\r\n\r\n\t// Add UIBlock to Thread\r\n\tthread.addUIBlock(uiBlock);\r\n\r\n\tlogger.info(`Created UIBlock: ${uiBlockId} in Thread: ${threadId}`);\r\n\r\n\t// Return response with uiBlockId and threadId\r\n\treturn {\r\n\t\tsuccess: userResponse.success,\r\n\t\tdata: userResponse.data,\r\n\t\terrors: userResponse.errors,\r\n\t\tuiBlockId,\r\n\t\tthreadId: threadId!,\r\n\t\tid,\r\n\t\twsId\r\n\t};\r\n}\r\n\r\nexport async function handleUserPromptRequest(\r\n\tdata: any,\r\n\tcomponents: Component[],\r\n\tsendMessage: (message: Message) => void,\r\n\tanthropicApiKey?: string,\r\n\tgroqApiKey?: string,\r\n\tllmProviders?: LLMProvider[],\r\n\tcollections?: any\r\n): Promise<void> {\r\n\tconst response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections);\r\n\r\n\t// Send response using sendDataResponse\r\n\tsendDataResponse(\r\n\t\tresponse.id || data.id,\r\n\t\t{\r\n\t\t\tsuccess: response.success,\r\n\t\t\terrors: response.errors,\r\n\t\t\tdata: response.data,\r\n\t\t\tuiBlockId: response.uiBlockId,\r\n\t\t\tthreadId: response.threadId\r\n\t\t},\r\n\t\tsendMessage,\r\n\t\tresponse.wsId || data.from?.id\r\n\t);\r\n}\r\n\r\n/**\r\n * Send a data_res response message\r\n */\r\nfunction sendDataResponse(\r\n\tid: string,\r\n\tres: T_RESPONSE & { uiBlockId?: string; threadId?: string },\r\n\tsendMessage: (message: Message) => void,\r\n\tclientId?: string,\r\n): void {\r\n\tconst response: Message = {\r\n\t\tid,\r\n\t\ttype: 'USER_PROMPT_RES',\r\n\t\tfrom: { type: 'data-agent' },\r\n\t\tto: {\r\n\t\t\ttype: 'runtime',\r\n\t\t\tid: clientId\r\n\t\t},\r\n\t\tpayload: {\r\n\t\t\t...res,\r\n\t\t}\r\n\t};\r\n\r\n\tlogger.info('sending user prompt response', response);\r\n\tsendMessage(response);\r\n} ","import { Component, Message, UserPromptSuggestionsMessageSchema } from '../types';\r\nimport { logger } from '../utils/logger';\r\n\r\n/**\r\n * Handle user prompt suggestions request\r\n * Searches components based on prompt keywords and returns top matches\r\n */\r\nexport async function handleUserPromptSuggestions(\r\n data: any,\r\n components: Component[],\r\n sendMessage: (message: Message) => void\r\n): Promise<void> {\r\n try {\r\n const request = UserPromptSuggestionsMessageSchema.parse(data);\r\n const { id, payload, from } = request;\r\n\r\n const { prompt, limit = 5 } = payload;\r\n const wsId = from.id;\r\n\r\n // Validate input\r\n if (!prompt || prompt.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Prompt is required and cannot be empty'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n if (!components || components.length === 0) {\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n prompt,\r\n suggestions: [],\r\n count: 0,\r\n message: 'No components available'\r\n }\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n // Search components based on prompt\r\n const suggestions = searchComponents(prompt, components, limit);\r\n\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n prompt,\r\n suggestions,\r\n count: suggestions.length,\r\n message: `Found ${suggestions.length} matching components`\r\n }\r\n }, sendMessage, wsId);\r\n\r\n } catch (error) {\r\n logger.error('Failed to handle user prompt suggestions request:', error);\r\n sendResponse(null, {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error occurred'\r\n }, sendMessage);\r\n }\r\n}\r\n\r\n/**\r\n * Search components based on prompt keywords\r\n * Searches in component name, description, keywords, and category\r\n * @param prompt - Search prompt\r\n * @param components - List of components to search in\r\n * @param limit - Maximum number of results to return\r\n * @returns Matching components sorted by relevance\r\n */\r\nfunction searchComponents(prompt: string, components: Component[], limit: number): Component[] {\r\n const promptLower = prompt.toLowerCase();\r\n const promptTokens = promptLower.split(/\\s+/).filter(token => token.length > 0);\r\n\r\n // Score each component based on keyword matches\r\n const scoredComponents = components.map(component => {\r\n let score = 0;\r\n\r\n const componentName = component.name.toLowerCase();\r\n const componentDesc = component.description.toLowerCase();\r\n const componentKeywords = (component.keywords || []).map(k => k.toLowerCase());\r\n const componentCategory = (component.category || '').toLowerCase();\r\n\r\n // Search in each field with different weights\r\n for (const token of promptTokens) {\r\n // Exact name match (highest weight)\r\n if (componentName === token) {\r\n score += 10;\r\n }\r\n // Name contains token\r\n else if (componentName.includes(token)) {\r\n score += 5;\r\n }\r\n\r\n // Exact keyword match\r\n if (componentKeywords.includes(token)) {\r\n score += 8;\r\n }\r\n // Keywords contain token\r\n else if (componentKeywords.some(k => k.includes(token))) {\r\n score += 4;\r\n }\r\n\r\n // Description contains token\r\n if (componentDesc.includes(token)) {\r\n score += 2;\r\n }\r\n\r\n // Category contains token\r\n if (componentCategory.includes(token)) {\r\n score += 3;\r\n }\r\n }\r\n\r\n return { component, score };\r\n });\r\n\r\n // Filter out components with score 0, sort by score (descending), and take top results\r\n return scoredComponents\r\n .filter(({ score }) => score > 0)\r\n .sort((a, b) => b.score - a.score)\r\n .slice(0, limit)\r\n .map(({ component }) => component);\r\n}\r\n\r\n/**\r\n * Send user prompt suggestions response\r\n */\r\nfunction sendResponse(\r\n id: string | null,\r\n res: { success: boolean; error?: string; data?: any },\r\n sendMessage: (message: Message) => void,\r\n clientId?: string,\r\n): void {\r\n const response: Message = {\r\n id: id || 'unknown',\r\n type: 'USER_PROMPT_SUGGESTIONS_RES',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'runtime',\r\n id: clientId\r\n },\r\n payload: {\r\n ...res,\r\n }\r\n };\r\n\r\n sendMessage(response);\r\n}\r\n","import { anthropicLLM } from './anthropic';\r\nimport { groqLLM } from './groq';\r\nimport { LLMProvider, Component } from '../types';\r\nimport { logger } from '../utils/logger';\r\n\r\n/**\r\n * Generate next questions based on the original user prompt and generated component\r\n * Routes to the appropriate LLM provider (Anthropic or Groq)\r\n * Falls back to next provider if current provider fails or returns empty results\r\n */\r\nexport async function generateNextQuestions(\r\n\toriginalUserPrompt: string,\r\n\tcomponent: Component,\r\n\tcomponentData?: Record<string, unknown>,\r\n\tanthropicApiKey?: string,\r\n\tgroqApiKey?: string,\r\n\tllmProviders?: LLMProvider[],\r\n\tlogCollector?: any,\r\n\tconversationHistory?: string\r\n): Promise<string[]> {\r\n\ttry {\r\n\t\tlogger.debug('[generateNextQuestions] Starting next questions generation');\r\n\t\tlogger.debug(`[generateNextQuestions] User prompt: \"${originalUserPrompt?.substring(0, 50)}...\"`);\r\n\t\tlogger.debug(`[generateNextQuestions] Component: ${component?.name || 'unknown'} (${component?.type || 'unknown'})`);\r\n\t\tlogger.debug(`[generateNextQuestions] Component data available: ${componentData ? 'yes' : 'no'}`);\r\n\r\n\t\t// Determine which providers to use\r\n\t\tconst providers = llmProviders || ['anthropic'];\r\n\t\tlogger.info(`[generateNextQuestions] Using LLM providers: [${providers.join(', ')}]`);\r\n\r\n\t\t// Log conversation context info\r\n\t\tif (conversationHistory && conversationHistory.length > 0) {\r\n\t\t\tconst exchangeCount = conversationHistory.split('\\n').filter((l: string) => l.startsWith('Q')).length;\r\n\t\t\tlogger.debug(`[generateNextQuestions] Using conversation history with ${exchangeCount} previous exchanges`);\r\n\t\t} else {\r\n\t\t\tlogger.debug('[generateNextQuestions] No conversation history available');\r\n\t\t}\r\n\r\n\t\t// Try each provider in order\r\n\t\tfor (let i = 0; i < providers.length; i++) {\r\n\t\t\tconst provider = providers[i];\r\n\t\t\tconst isLastProvider = i === providers.length - 1;\r\n\r\n\t\t\ttry {\r\n\t\t\t\tlogger.info(`[generateNextQuestions] Attempting provider: ${provider} (${i + 1}/${providers.length})`);\r\n\t\t\t\tlogCollector?.info(`Generating questions with ${provider}...`);\r\n\r\n\t\t\t\tlet result: string[] = [];\r\n\r\n\t\t\t\tif (provider === 'groq') {\r\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using Groq LLM for next questions');\r\n\t\t\t\t\tresult = await groqLLM.generateNextQuestions(\r\n\t\t\t\t\t\toriginalUserPrompt,\r\n\t\t\t\t\t\tcomponent,\r\n\t\t\t\t\t\tcomponentData,\r\n\t\t\t\t\t\tgroqApiKey,\r\n\t\t\t\t\t\tlogCollector,\r\n\t\t\t\t\t\tconversationHistory\r\n\t\t\t\t\t);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Default to Anthropic\r\n\t\t\t\t\tlogger.debug('[generateNextQuestions] Using Anthropic LLM for next questions');\r\n\t\t\t\t\tresult = await anthropicLLM.generateNextQuestions(\r\n\t\t\t\t\t\toriginalUserPrompt,\r\n\t\t\t\t\t\tcomponent,\r\n\t\t\t\t\t\tcomponentData,\r\n\t\t\t\t\t\tanthropicApiKey,\r\n\t\t\t\t\t\tlogCollector,\r\n\t\t\t\t\t\tconversationHistory\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// If we got results, return them\r\n\t\t\t\tif (result && result.length > 0) {\r\n\t\t\t\t\tlogger.info(`[generateNextQuestions] Successfully generated ${result.length} questions with ${provider}`);\r\n\t\t\t\t\tlogger.debug(`[generateNextQuestions] Questions: ${JSON.stringify(result)}`);\r\n\t\t\t\t\tlogCollector?.info(`Generated ${result.length} follow-up questions`);\r\n\t\t\t\t\treturn result;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst warnMsg = `No questions generated from ${provider}${!isLastProvider ? ', trying next provider...' : ''}`;\r\n\t\t\t\tlogger.warn(`[generateNextQuestions] ${warnMsg}`);\r\n\t\t\t\tif (!isLastProvider) {\r\n\t\t\t\t\tlogCollector?.warn(warnMsg);\r\n\t\t\t\t}\r\n\t\t\t} catch (providerError) {\r\n\t\t\t\tconst errorMsg = providerError instanceof Error ? providerError.message : String(providerError);\r\n\t\t\t\tlogger.error(`[generateNextQuestions] Provider ${provider} failed: ${errorMsg}`);\r\n\t\t\t\tlogger.debug(`[generateNextQuestions] Provider error details:`, providerError);\r\n\r\n\t\t\t\tif (!isLastProvider) {\r\n\t\t\t\t\tconst fallbackMsg = `Provider ${provider} failed, trying next provider...`;\r\n\t\t\t\t\tlogger.info(`[generateNextQuestions] ${fallbackMsg}`);\r\n\t\t\t\t\tlogCollector?.warn(fallbackMsg);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tlogCollector?.error(`Failed to generate questions with ${provider}`);\r\n\t\t\t\t}\r\n\t\t\t\t// Continue to next provider\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// All providers failed or returned empty results\r\n\t\tlogger.warn('[generateNextQuestions] All providers failed or returned no questions');\r\n\t\tlogCollector?.warn('Unable to generate follow-up questions');\r\n\t\treturn [];\r\n\t} catch (error) {\r\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\tconst errorStack = error instanceof Error ? error.stack : undefined;\r\n\r\n\t\tlogger.error(`[generateNextQuestions] Error generating next questions: ${errorMsg}`);\r\n\t\tlogger.debug('[generateNextQuestions] Error stack trace:', errorStack);\r\n\t\tlogCollector?.error(`Error generating next questions: ${errorMsg}`);\r\n\t\t// Return empty array on error\r\n\t\treturn [];\r\n\t}\r\n}\r\n","import { ActionsRequestMessageSchema, type LLMProvider, type Message } from '../types';\r\nimport { generateNextQuestions } from '../userResponse/next-questions';\r\nimport { logger } from '../utils/logger';\r\nimport { UILogCollector } from '../utils/log-collector';\r\nimport { ThreadManager } from '../threads';\r\nimport { CONTEXT_CONFIG } from '../config/context';\r\n\r\n/**\r\n * Handle incoming actions messages from runtime\r\n * Generates suggested next questions based on the original user prompt and generated component\r\n */\r\nexport async function handleActionsRequest(\r\n data: any,\r\n sendMessage: (message: Message) => void,\r\n anthropicApiKey?: string,\r\n groqApiKey?: string,\r\n llmProviders?: LLMProvider[]\r\n): Promise<void> {\r\n try {\r\n logger.debug('[ACTIONS_REQ] Parsing incoming actions request');\r\n const actionsRequest = ActionsRequestMessageSchema.parse(data);\r\n const { id, payload } = actionsRequest;\r\n const { SA_RUNTIME } = payload;\r\n\r\n const wsId = actionsRequest.from.id || 'unknown';\r\n\r\n logger.info(`[ACTIONS_REQ ${id}] Processing actions request from client: ${wsId}`);\r\n logger.debug(`[ACTIONS_REQ ${id}] Request payload:`, JSON.stringify(payload, null, 2).substring(0, 200));\r\n\r\n // SA_RUNTIME is required to fetch actions from UIBlock\r\n if (!SA_RUNTIME) {\r\n logger.error(`[ACTIONS_REQ ${id}] SA_RUNTIME missing from request`);\r\n sendResponse(id, {\r\n success: false,\r\n error: 'SA_RUNTIME with threadId and uiBlockId is required'\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n const uiBlockId = SA_RUNTIME.uiBlockId;\r\n const threadId = SA_RUNTIME.threadId;\r\n\r\n logger.debug(`[ACTIONS_REQ ${id}] SA_RUNTIME validated - threadId: ${threadId}, uiBlockId: ${uiBlockId}`);\r\n\r\n // Get UIBlock from ThreadManager\r\n const threadManager = ThreadManager.getInstance();\r\n const thread = threadManager.getThread(threadId);\r\n\r\n if (!thread) {\r\n logger.error(`[ACTIONS_REQ ${id}] Thread '${threadId}' not found`);\r\n sendResponse(id, {\r\n success: false,\r\n error: `Thread '${threadId}' not found`\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n logger.debug(`[ACTIONS_REQ ${id}] Thread found with ${thread.getUIBlocks().length} UIBlocks`);\r\n logger.debug(`[ACTIONS_REQ ${id}] Retrieving UIBlock: ${uiBlockId}`);\r\n\r\n const uiBlock = thread.getUIBlock(uiBlockId);\r\n if (!uiBlock) {\r\n logger.error(`[ACTIONS_REQ ${id}] UIBlock '${uiBlockId}' not found in thread '${threadId}'`);\r\n sendResponse(id, {\r\n success: false,\r\n error: `UIBlock '${uiBlockId}' not found in thread '${threadId}'`\r\n }, sendMessage, wsId);\r\n return;\r\n }\r\n\r\n logger.info(`[ACTIONS_REQ ${id}] UIBlock retrieved successfully`);\r\n\r\n // Create log collector with uiBlockId\r\n logger.debug(`[ACTIONS_REQ ${id}] Creating UILogCollector for uiBlockId: ${uiBlockId}`);\r\n const logCollector = new UILogCollector(wsId, sendMessage, uiBlockId);\r\n logger.info(`[ACTIONS_REQ ${id}] UILogCollector initialized`);\r\n\r\n // Extract data from UIBlock\r\n logger.debug(`[ACTIONS_REQ ${id}] Extracting data from UIBlock`);\r\n const userQuestion = uiBlock.getUserQuestion();\r\n const component = uiBlock.getComponentMetadata();\r\n const componentData = uiBlock.getComponentData();\r\n\r\n logger.debug(`[ACTIONS_REQ ${id}] User question: \"${userQuestion?.substring(0, 50)}...\"`);\r\n logger.debug(`[ACTIONS_REQ ${id}] Component: ${component?.name || 'unknown'} (${component?.type || 'unknown'})`);\r\n logger.debug(`[ACTIONS_REQ ${id}] Component data available: ${componentData ? 'yes' : 'no'}`);\r\n\r\n // Extract conversation context from thread (excluding current UIBlock)\r\n logger.debug(`[ACTIONS_REQ ${id}] Extracting conversation history (max ${CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS} blocks)`);\r\n const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, uiBlockId);\r\n const historyLineCount = conversationHistory.split('\\n').filter(l => l.trim()).length;\r\n logger.info(`[ACTIONS_REQ ${id}] Conversation history extracted: ${historyLineCount} lines`);\r\n logger.debug(`[ACTIONS_REQ ${id}] Conversation history preview:\\n${conversationHistory.substring(0, 200)}...`);\r\n\r\n logCollector.info(`Generating actions for UIBlock: ${uiBlockId}`);\r\n logger.info(`[ACTIONS_REQ ${id}] Generating actions for component: ${component?.name || 'unknown'}`);\r\n\r\n // Use getOrFetchActions to manage action state\r\n logger.debug(`[ACTIONS_REQ ${id}] Checking if actions are already cached`);\r\n const startTime = Date.now();\r\n\r\n const actions = await uiBlock.getOrFetchActions(async () => {\r\n logger.info(`[ACTIONS_REQ ${id}] Actions not cached, generating new actions...`);\r\n logCollector.info('Generating follow-up questions...');\r\n\r\n // Generate next questions using extracted data from UIBlock and conversation history\r\n logger.info(`[ACTIONS_REQ ${id}] Starting next questions generation with ${llmProviders?.join(', ') || 'default'} providers`);\r\n const nextQuestions = await generateNextQuestions(\r\n userQuestion,\r\n component as any,\r\n componentData,\r\n anthropicApiKey,\r\n groqApiKey,\r\n llmProviders,\r\n logCollector,\r\n conversationHistory\r\n );\r\n\r\n logger.info(`[ACTIONS_REQ ${id}] Generated ${nextQuestions.length} questions`);\r\n logger.debug(`[ACTIONS_REQ ${id}] Questions: ${JSON.stringify(nextQuestions)}`);\r\n\r\n // Convert questions to actions format\r\n logger.debug(`[ACTIONS_REQ ${id}] Converting questions to actions format`);\r\n const convertedActions = nextQuestions.map((question: string, index: number) => ({\r\n id: `action_${index}_${Date.now()}`,\r\n name: question,\r\n type: 'next_question',\r\n question\r\n }));\r\n\r\n logger.debug(`[ACTIONS_REQ ${id}] Converted ${convertedActions.length} actions`);\r\n return convertedActions;\r\n });\r\n\r\n const processingTime = Date.now() - startTime;\r\n logger.info(`[ACTIONS_REQ ${id}] Actions retrieved in ${processingTime}ms - ${actions.length} actions total`);\r\n\r\n if (actions.length > 0) {\r\n logCollector.info(`Generated ${actions.length} follow-up questions successfully`);\r\n logger.debug(`[ACTIONS_REQ ${id}] Actions: ${actions.map(a => a.name).join(', ')}`);\r\n } else {\r\n logger.warn(`[ACTIONS_REQ ${id}] No actions generated`);\r\n logCollector.warn('No follow-up questions could be generated');\r\n }\r\n\r\n logger.debug(`[ACTIONS_REQ ${id}] Sending successful response to client`);\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n actions,\r\n componentName: component?.name,\r\n componentId: component?.id,\r\n uiBlockId,\r\n threadId\r\n }\r\n }, sendMessage, wsId);\r\n\r\n logger.info(`[ACTIONS_REQ ${id}] ✓ Actions request completed successfully`);\r\n\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\r\n const errorStack = error instanceof Error ? error.stack : undefined;\r\n\r\n logger.error(`[ACTIONS_REQ] Failed to handle actions request: ${errorMessage}`);\r\n logger.debug(`[ACTIONS_REQ] Error stack trace:`, errorStack);\r\n\r\n // Try to send error response\r\n try {\r\n const parsedData = data as any;\r\n if (parsedData?.id && parsedData?.from?.id) {\r\n const logCollector = parsedData?.payload?.SA_RUNTIME?.uiBlockId\r\n ? new UILogCollector(parsedData.from.id, sendMessage, parsedData.payload.SA_RUNTIME.uiBlockId)\r\n : undefined;\r\n\r\n logCollector?.error(`Failed to generate actions: ${errorMessage}`);\r\n }\r\n } catch (logError) {\r\n logger.debug('[ACTIONS_REQ] Failed to send error logs to UI:', logError);\r\n }\r\n\r\n sendResponse(null, {\r\n success: false,\r\n error: errorMessage\r\n }, sendMessage);\r\n\r\n logger.info('[ACTIONS_REQ] ✗ Actions request completed with errors');\r\n }\r\n}\r\n\r\n/**\r\n * Send actions response\r\n */\r\nfunction sendResponse(\r\n id: string | null,\r\n res: { success: boolean; error?: string; data?: any },\r\n sendMessage: (message: Message) => void,\r\n clientId?: string,\r\n): void {\r\n const response: Message = {\r\n id: id || 'unknown',\r\n type: 'ACTIONS_RES',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'runtime',\r\n id: clientId\r\n },\r\n payload: {\r\n ...res,\r\n }\r\n };\r\n\r\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Sending ${res.success ? 'successful' : 'failed'} response to client`);\r\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Response payload size: ${JSON.stringify(response).length} bytes`);\r\n\r\n if (res.data?.actions) {\r\n logger.debug(`[ACTIONS_RES ${id || 'unknown'}] Sending ${res.data.actions.length} actions`);\r\n }\r\n\r\n sendMessage(response);\r\n}\r\n","import { Component, ComponentListResponseMessageSchema, ComponentSchema, ComponentsSchema, Message } from \"../types\";\r\nimport { logger } from \"../utils/logger\";\r\n\r\n\r\nexport async function handleComponentListResponse(\r\n data: any,\r\n storeComponents:(components: Component[])=>void\r\n ): Promise<void> {\r\n try {\r\n const componentListResponse = ComponentListResponseMessageSchema.parse(data);\r\n const { id, payload } = componentListResponse;\r\n \r\n const componentsList = payload.components;\r\n\r\n if(!componentsList){\r\n logger.error('Components list not found in the response');\r\n return;\r\n }\r\n\r\n const components = ComponentsSchema.parse(componentsList);\r\n storeComponents(components);\r\n\r\n return;\r\n } catch (error) {\r\n logger.error('Failed to handle user prompt request:', error);\r\n }\r\n } \r\n\r\n\r\n","import { UsersRequestMessageSchema, Message } from '../types';\r\nimport { getUserManager } from '../auth/user-storage';\r\nimport { logger } from '../utils/logger';\r\n\r\n/**\r\n * Handle unified users management request\r\n * Supports operations: create, update, delete, getAll, getOne\r\n * Only accepts requests from 'admin' type\r\n */\r\nexport async function handleUsersRequest(\r\n data: any,\r\n sendMessage: (message: Message) => void\r\n): Promise<void> {\r\n try {\r\n const request = UsersRequestMessageSchema.parse(data);\r\n const { id, payload, from } = request;\r\n const { operation, data: requestData } = payload;\r\n const username = requestData?.username;\r\n const email = requestData?.email;\r\n const password = requestData?.password;\r\n const fullname = requestData?.fullname;\r\n const role = requestData?.role;\r\n\r\n // Verify request is from admin\r\n if (from.type !== 'admin') {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Unauthorized: Only admin can manage users'\r\n }, sendMessage, from.id);\r\n logger.warn(`Unauthorized user management attempt from: ${from.type}`);\r\n return;\r\n }\r\n\r\n const userManager = getUserManager();\r\n\r\n // Route to appropriate operation handler\r\n switch (operation) {\r\n case 'create':\r\n await handleCreate(id, { username, email, password, fullname, role }, userManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'update':\r\n await handleUpdate(id, { username, email, password, fullname, role }, userManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'delete':\r\n await handleDelete(id, username, userManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'getAll':\r\n await handleGetAll(id, userManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'getOne':\r\n await handleGetOne(id, username, userManager, sendMessage, from.id);\r\n break;\r\n\r\n default:\r\n sendResponse(id, {\r\n success: false,\r\n error: `Unknown operation: ${operation}`\r\n }, sendMessage, from.id);\r\n }\r\n\r\n } catch (error) {\r\n logger.error('Failed to handle users request:', error);\r\n sendResponse(null, {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error occurred'\r\n }, sendMessage);\r\n }\r\n}\r\n\r\n/**\r\n * Handle create user operation\r\n */\r\nasync function handleCreate(\r\n id: string,\r\n userData: {\r\n username?: string;\r\n email?: string;\r\n password?: string;\r\n fullname?: string;\r\n role?: string;\r\n },\r\n userManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n const { username, email, password, fullname, role } = userData;\r\n\r\n // Validate input - username is required\r\n if (!username || username.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Username is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n if (!password || password.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Password is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Validate email format if provided\r\n if (email && email.trim().length > 0) {\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n if (!emailRegex.test(email)) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Invalid email format'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n }\r\n\r\n // Check if user already exists\r\n if (userManager.userExists(username)) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `User '${username}' already exists`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Check if email already exists (if provided)\r\n if (email && userManager.getUserByEmail(email)) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `User with email '${email}' already exists`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Create user object\r\n const newUserData: any = {\r\n username,\r\n password,\r\n };\r\n\r\n if (email && email.trim().length > 0) {\r\n newUserData.email = email.trim();\r\n }\r\n\r\n if (fullname && fullname.trim().length > 0) {\r\n newUserData.fullname = fullname.trim();\r\n }\r\n\r\n if (role && role.trim().length > 0) {\r\n newUserData.role = role.trim();\r\n }\r\n\r\n // Create user (wsIds will be managed in memory, not persisted to file)\r\n const newUser = userManager.createUser(newUserData);\r\n\r\n logger.info(`User created by admin: ${username}${email ? ` (${email})` : ''}`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n username: newUser.username,\r\n email: newUser.email,\r\n fullname: newUser.fullname,\r\n role: newUser.role,\r\n message: `User '${username}' created successfully`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Handle update user operation\r\n */\r\nasync function handleUpdate(\r\n id: string,\r\n userData: {\r\n username?: string;\r\n email?: string;\r\n password?: string;\r\n fullname?: string;\r\n role?: string;\r\n },\r\n userManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n const { username, email, password, fullname, role } = userData;\r\n\r\n // Validate input - username is required to identify which user to update\r\n if (!username || username.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Username is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Check if user exists\r\n if (!userManager.userExists(username)) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `User '${username}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Build update object\r\n const updates: any = {};\r\n\r\n // Validate and add email if provided\r\n if (email !== undefined) {\r\n if (email.trim().length > 0) {\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n if (!emailRegex.test(email)) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Invalid email format'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Check if email is already used by another user\r\n const existingUser = userManager.getUserByEmail(email);\r\n if (existingUser && existingUser.username !== username) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `Email '${email}' is already used by another user`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n updates.email = email.trim();\r\n } else {\r\n // Empty string means remove email\r\n updates.email = undefined;\r\n }\r\n }\r\n\r\n // Update password if provided\r\n if (password !== undefined && password.trim().length > 0) {\r\n updates.password = password.trim();\r\n }\r\n\r\n // Update fullname if provided\r\n if (fullname !== undefined) {\r\n updates.fullname = fullname.trim().length > 0 ? fullname.trim() : undefined;\r\n }\r\n\r\n // Update role if provided\r\n if (role !== undefined) {\r\n updates.role = role.trim().length > 0 ? role.trim() : undefined;\r\n }\r\n\r\n // If nothing to update, return error\r\n if (Object.keys(updates).length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'No fields to update. Please provide at least one field to update.'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Update user\r\n const updatedUser = userManager.updateUser(username, updates);\r\n\r\n logger.info(`User updated by admin: ${username}`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n username: updatedUser.username,\r\n email: updatedUser.email,\r\n fullname: updatedUser.fullname,\r\n role: updatedUser.role,\r\n message: `User '${username}' updated successfully`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Handle delete user operation\r\n */\r\nasync function handleDelete(\r\n id: string,\r\n username: string | undefined,\r\n userManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!username || username.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Username is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Check if user exists\r\n if (!userManager.userExists(username)) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `User '${username}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Delete user\r\n const deleted = userManager.deleteUser(username);\r\n\r\n if (!deleted) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `Failed to delete user '${username}'`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n logger.info(`User deleted by admin: ${username}`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n username: username,\r\n message: `User '${username}' deleted successfully`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Handle get all users operation\r\n */\r\nasync function handleGetAll(\r\n id: string,\r\n userManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n const users = userManager.getAllUsers();\r\n\r\n // Remove sensitive information like passwords\r\n const sanitizedUsers = users.map((user: any) => ({\r\n username: user.username,\r\n email: user.email,\r\n fullname: user.fullname,\r\n role: user.role,\r\n wsIds: user.wsIds || []\r\n }));\r\n\r\n logger.info(`Admin retrieved all users (count: ${sanitizedUsers.length})`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n users: sanitizedUsers,\r\n count: sanitizedUsers.length,\r\n message: `Retrieved ${sanitizedUsers.length} users`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Handle get one user operation\r\n */\r\nasync function handleGetOne(\r\n id: string,\r\n username: string | undefined,\r\n userManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!username || username.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Username is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n // Check if user exists\r\n if (!userManager.userExists(username)) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `User '${username}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n const user = userManager.getUser(username);\r\n\r\n // Remove sensitive information\r\n const sanitizedUser = {\r\n username: user.username,\r\n email: user.email,\r\n fullname: user.fullname,\r\n role: user.role,\r\n wsIds: user.wsIds || []\r\n };\r\n\r\n logger.info(`Admin retrieved user: ${username}`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n user: sanitizedUser,\r\n message: `Retrieved user '${username}'`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Send users response\r\n */\r\nfunction sendResponse(\r\n id: string | null,\r\n res: { success: boolean; error?: string; data?: any },\r\n sendMessage: (message: Message) => void,\r\n clientId?: string,\r\n): void {\r\n const response: Message = {\r\n id: id || 'unknown',\r\n type: 'USERS_RES',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'admin',\r\n id: clientId\r\n },\r\n payload: {\r\n ...res,\r\n }\r\n };\r\n\r\n sendMessage(response);\r\n}\r\n","import { DashboardManager } from './dashboard-manager';\r\nimport { logger } from '../utils/logger';\r\n\r\nlet dashboardManager: DashboardManager | null = null;\r\n\r\n/**\r\n * Set the dashboard manager instance\r\n * @param manager - DashboardManager instance to use\r\n */\r\nexport function setDashboardManager(manager: DashboardManager): void {\r\n dashboardManager = manager;\r\n logger.info('DashboardManager instance set');\r\n}\r\n\r\n/**\r\n * Get the dashboard manager instance\r\n * @throws Error if dashboard manager is not initialized\r\n * @returns DashboardManager instance\r\n */\r\nexport function getDashboardManager(): DashboardManager {\r\n if (!dashboardManager) {\r\n throw new Error('DashboardManager not initialized. Call setDashboardManager first.');\r\n }\r\n return dashboardManager;\r\n}\r\n","import { DashboardsRequestMessageSchema, Message } from '../types';\r\nimport { getDashboardManager } from '../dashboards/dashboard-storage';\r\nimport { logger } from '../utils/logger';\r\n\r\n/**\r\n * Handle unified dashboards management request\r\n * Supports operations: create, update, delete, getAll, getOne\r\n * Only accepts requests from 'admin' type\r\n */\r\nexport async function handleDashboardsRequest(\r\n data: any,\r\n sendMessage: (message: Message) => void\r\n): Promise<void> {\r\n try {\r\n const request = DashboardsRequestMessageSchema.parse(data);\r\n const { id, payload, from } = request;\r\n const { operation, data: requestData } = payload;\r\n const dashboardId = requestData?.dashboardId;\r\n const dashboard = requestData?.dashboard;\r\n\r\n // Verify request is from admin\r\n if (from.type !== 'admin') {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Unauthorized: Only admin can manage dashboards'\r\n }, sendMessage, from.id);\r\n logger.warn(`Unauthorized dashboard management attempt from: ${from.type}`);\r\n return;\r\n }\r\n\r\n const dashboardManager = getDashboardManager();\r\n\r\n // Route to appropriate operation handler\r\n switch (operation) {\r\n case 'create':\r\n await handleCreate(id, dashboardId, dashboard, dashboardManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'update':\r\n await handleUpdate(id, dashboardId, dashboard, dashboardManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'delete':\r\n await handleDelete(id, dashboardId, dashboardManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'getAll':\r\n await handleGetAll(id, dashboardManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'getOne':\r\n await handleGetOne(id, dashboardId, dashboardManager, sendMessage, from.id);\r\n break;\r\n\r\n default:\r\n sendResponse(id, {\r\n success: false,\r\n error: `Unknown operation: ${operation}`\r\n }, sendMessage, from.id);\r\n }\r\n\r\n } catch (error) {\r\n logger.error('Failed to handle dashboards request:', error);\r\n sendResponse(null, {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error occurred'\r\n }, sendMessage);\r\n }\r\n}\r\n\r\n/**\r\n * Handle create dashboard operation\r\n */\r\nasync function handleCreate(\r\n id: string,\r\n dashboardId: string | undefined,\r\n dashboard: any,\r\n dashboardManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!dashboardId || dashboardId.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Dashboard ID is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n if (!dashboard) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Dashboard data is required'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n try {\r\n const createdDashboard = dashboardManager.createDashboard(dashboardId, dashboard);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n dashboardId,\r\n dashboard: createdDashboard,\r\n message: `Dashboard '${dashboardId}' created successfully`\r\n }\r\n }, sendMessage, clientId);\r\n } catch (error) {\r\n sendResponse(id, {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Failed to create dashboard'\r\n }, sendMessage, clientId);\r\n }\r\n}\r\n\r\n/**\r\n * Handle update dashboard operation\r\n */\r\nasync function handleUpdate(\r\n id: string,\r\n dashboardId: string | undefined,\r\n dashboard: any,\r\n dashboardManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!dashboardId || dashboardId.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Dashboard ID is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n if (!dashboard) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Dashboard data is required'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n try {\r\n const updatedDashboard = dashboardManager.updateDashboard(dashboardId, dashboard);\r\n\r\n if (!updatedDashboard) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `Dashboard '${dashboardId}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n dashboardId,\r\n dashboard: updatedDashboard,\r\n message: `Dashboard '${dashboardId}' updated successfully`\r\n }\r\n }, sendMessage, clientId);\r\n } catch (error) {\r\n sendResponse(id, {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Failed to update dashboard'\r\n }, sendMessage, clientId);\r\n }\r\n}\r\n\r\n/**\r\n * Handle delete dashboard operation\r\n */\r\nasync function handleDelete(\r\n id: string,\r\n dashboardId: string | undefined,\r\n dashboardManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!dashboardId || dashboardId.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Dashboard ID is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n const deleted = dashboardManager.deleteDashboard(dashboardId);\r\n\r\n if (!deleted) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `Dashboard '${dashboardId}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n dashboardId,\r\n message: `Dashboard '${dashboardId}' deleted successfully`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Handle get all dashboards operation\r\n */\r\nasync function handleGetAll(\r\n id: string,\r\n dashboardManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n const dashboards = dashboardManager.getAllDashboards();\r\n\r\n logger.info(`Admin retrieved all dashboards (count: ${dashboards.length})`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n dashboards,\r\n count: dashboards.length,\r\n message: `Retrieved ${dashboards.length} dashboards`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Handle get one dashboard operation\r\n */\r\nasync function handleGetOne(\r\n id: string,\r\n dashboardId: string | undefined,\r\n dashboardManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!dashboardId || dashboardId.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Dashboard ID is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n const dashboard = dashboardManager.getDashboard(dashboardId);\r\n\r\n if (!dashboard) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `Dashboard '${dashboardId}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n logger.info(`Admin retrieved dashboard: ${dashboardId}`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n dashboardId,\r\n dashboard,\r\n message: `Retrieved dashboard '${dashboardId}'`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Send dashboards response\r\n */\r\nfunction sendResponse(\r\n id: string | null,\r\n res: { success: boolean; error?: string; data?: any },\r\n sendMessage: (message: Message) => void,\r\n clientId?: string,\r\n): void {\r\n const response: Message = {\r\n id: id || 'unknown',\r\n type: 'DASHBOARDS_RES',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'admin',\r\n id: clientId\r\n },\r\n payload: {\r\n ...res,\r\n }\r\n };\r\n\r\n sendMessage(response);\r\n}\r\n","import { ReportManager } from './report-manager';\r\n\r\n/**\r\n * Global report manager instance\r\n */\r\nlet reportManager: ReportManager | null = null;\r\n\r\n/**\r\n * Get the global report manager instance\r\n * @returns ReportManager instance\r\n * @throws Error if report manager is not initialized\r\n */\r\nexport function getReportManager(): ReportManager {\r\n if (!reportManager) {\r\n throw new Error('Report manager not initialized. Call setReportManager first.');\r\n }\r\n return reportManager;\r\n}\r\n\r\n/**\r\n * Set the global report manager instance\r\n * @param manager - ReportManager instance to set\r\n */\r\nexport function setReportManager(manager: ReportManager): void {\r\n reportManager = manager;\r\n}\r\n","import { ReportsRequestMessageSchema, Message } from '../types';\r\nimport { getReportManager } from '../reports/report-storage';\r\nimport { logger } from '../utils/logger';\r\n\r\n/**\r\n * Handle unified reports management request\r\n * Supports operations: create, update, delete, getAll, getOne\r\n * Only accepts requests from 'admin' type\r\n */\r\nexport async function handleReportsRequest(\r\n data: any,\r\n sendMessage: (message: Message) => void\r\n): Promise<void> {\r\n try {\r\n const request = ReportsRequestMessageSchema.parse(data);\r\n const { id, payload, from } = request;\r\n const { operation, data: requestData } = payload;\r\n const reportId = requestData?.reportId;\r\n const report = requestData?.report;\r\n\r\n // Verify request is from admin\r\n if (from.type !== 'admin') {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Unauthorized: Only admin can manage reports'\r\n }, sendMessage, from.id);\r\n logger.warn(`Unauthorized report management attempt from: ${from.type}`);\r\n return;\r\n }\r\n\r\n const reportManager = getReportManager();\r\n\r\n // Route to appropriate operation handler\r\n switch (operation) {\r\n case 'create':\r\n await handleCreate(id, reportId, report, reportManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'update':\r\n await handleUpdate(id, reportId, report, reportManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'delete':\r\n await handleDelete(id, reportId, reportManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'getAll':\r\n await handleGetAll(id, reportManager, sendMessage, from.id);\r\n break;\r\n\r\n case 'getOne':\r\n await handleGetOne(id, reportId, reportManager, sendMessage, from.id);\r\n break;\r\n\r\n default:\r\n sendResponse(id, {\r\n success: false,\r\n error: `Unknown operation: ${operation}`\r\n }, sendMessage, from.id);\r\n }\r\n\r\n } catch (error) {\r\n logger.error('Failed to handle reports request:', error);\r\n sendResponse(null, {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error occurred'\r\n }, sendMessage);\r\n }\r\n}\r\n\r\n/**\r\n * Handle create report operation\r\n */\r\nasync function handleCreate(\r\n id: string,\r\n reportId: string | undefined,\r\n report: any,\r\n reportManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!reportId || reportId.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Report ID is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n if (!report) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Report data is required'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n try {\r\n const createdReport = reportManager.createReport(reportId, report);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n reportId,\r\n report: createdReport,\r\n message: `Report '${reportId}' created successfully`\r\n }\r\n }, sendMessage, clientId);\r\n } catch (error) {\r\n sendResponse(id, {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Failed to create report'\r\n }, sendMessage, clientId);\r\n }\r\n}\r\n\r\n/**\r\n * Handle update report operation\r\n */\r\nasync function handleUpdate(\r\n id: string,\r\n reportId: string | undefined,\r\n report: any,\r\n reportManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!reportId || reportId.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Report ID is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n if (!report) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Report data is required'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n try {\r\n const updatedReport = reportManager.updateReport(reportId, report);\r\n\r\n if (!updatedReport) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `Report '${reportId}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n reportId,\r\n report: updatedReport,\r\n message: `Report '${reportId}' updated successfully`\r\n }\r\n }, sendMessage, clientId);\r\n } catch (error) {\r\n sendResponse(id, {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Failed to update report'\r\n }, sendMessage, clientId);\r\n }\r\n}\r\n\r\n/**\r\n * Handle delete report operation\r\n */\r\nasync function handleDelete(\r\n id: string,\r\n reportId: string | undefined,\r\n reportManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!reportId || reportId.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Report ID is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n const deleted = reportManager.deleteReport(reportId);\r\n\r\n if (!deleted) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `Report '${reportId}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n reportId,\r\n message: `Report '${reportId}' deleted successfully`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Handle get all reports operation\r\n */\r\nasync function handleGetAll(\r\n id: string,\r\n reportManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n const reports = reportManager.getAllReports();\r\n\r\n logger.info(`Admin retrieved all reports (count: ${reports.length})`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n reports,\r\n count: reports.length,\r\n message: `Retrieved ${reports.length} reports`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Handle get one report operation\r\n */\r\nasync function handleGetOne(\r\n id: string,\r\n reportId: string | undefined,\r\n reportManager: any,\r\n sendMessage: (message: Message) => void,\r\n clientId?: string\r\n): Promise<void> {\r\n // Validate input\r\n if (!reportId || reportId.trim().length === 0) {\r\n sendResponse(id, {\r\n success: false,\r\n error: 'Report ID is required and cannot be empty'\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n const report = reportManager.getReport(reportId);\r\n\r\n if (!report) {\r\n sendResponse(id, {\r\n success: false,\r\n error: `Report '${reportId}' not found`\r\n }, sendMessage, clientId);\r\n return;\r\n }\r\n\r\n logger.info(`Admin retrieved report: ${reportId}`);\r\n\r\n sendResponse(id, {\r\n success: true,\r\n data: {\r\n reportId,\r\n report,\r\n message: `Retrieved report '${reportId}'`\r\n }\r\n }, sendMessage, clientId);\r\n}\r\n\r\n/**\r\n * Send reports response\r\n */\r\nfunction sendResponse(\r\n id: string | null,\r\n res: { success: boolean; error?: string; data?: any },\r\n sendMessage: (message: Message) => void,\r\n clientId?: string,\r\n): void {\r\n const response: Message = {\r\n id: id || 'unknown',\r\n type: 'REPORTS_RES',\r\n from: { type: 'data-agent' },\r\n to: {\r\n type: 'admin',\r\n id: clientId\r\n },\r\n payload: {\r\n ...res,\r\n }\r\n };\r\n\r\n sendMessage(response);\r\n}\r\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { logger } from '../utils/logger';\r\nimport { UserSchema, UsersDataSchema, type User, type UsersData } from '../types';\r\n\r\n/**\r\n * UserManager class to handle CRUD operations on users with file persistence\r\n * and in-memory caching. Changes are synced to file periodically.\r\n */\r\nexport class UserManager {\r\n private users: User[] = [];\r\n private filePath: string;\r\n private hasChanged: boolean = false;\r\n private syncInterval: ReturnType<typeof setInterval> | null = null;\r\n private syncIntervalMs: number;\r\n private isInitialized: boolean = false;\r\n\r\n /**\r\n * Initialize UserManager with file path and sync interval\r\n * @param projectId - Project ID to use in file path (default: 'snowflake-dataset')\r\n * @param syncIntervalMs - Interval in milliseconds to sync changes to file (default: 5000ms)\r\n */\r\n constructor(projectId: string = 'snowflake-dataset', syncIntervalMs: number = 5000) {\r\n this.filePath = path.join(os.homedir(), '.superatom', 'projects', projectId, 'users.json');\r\n this.syncIntervalMs = syncIntervalMs;\r\n }\r\n\r\n /**\r\n * Initialize the UserManager by loading users from file and starting sync interval\r\n */\r\n async init(): Promise<void> {\r\n if (this.isInitialized) {\r\n return;\r\n }\r\n\r\n try {\r\n // Load users from file into memory\r\n await this.loadUsersFromFile();\r\n logger.info(`UserManager initialized with ${this.users.length} users`);\r\n\r\n // Start the sync interval\r\n this.startSyncInterval();\r\n this.isInitialized = true;\r\n } catch (error) {\r\n logger.error('Failed to initialize UserManager:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Load users from the JSON file into memory\r\n */\r\n private async loadUsersFromFile(): Promise<void> {\r\n try {\r\n // Create directory structure if it doesn't exist\r\n const dir = path.dirname(this.filePath);\r\n if (!fs.existsSync(dir)) {\r\n logger.info(`Creating directory structure: ${dir}`);\r\n fs.mkdirSync(dir, { recursive: true });\r\n }\r\n\r\n // Create file with empty users array if it doesn't exist\r\n if (!fs.existsSync(this.filePath)) {\r\n logger.info(`Users file does not exist at ${this.filePath}, creating with empty users`);\r\n const initialData: UsersData = { users: [] };\r\n fs.writeFileSync(this.filePath, JSON.stringify(initialData, null, 4));\r\n this.users = [];\r\n this.hasChanged = false;\r\n return;\r\n }\r\n\r\n const fileContent = fs.readFileSync(this.filePath, 'utf-8');\r\n const rawData = JSON.parse(fileContent);\r\n\r\n // Validate using Zod schema\r\n const validatedData = UsersDataSchema.parse(rawData);\r\n this.users = validatedData.users;\r\n this.hasChanged = false;\r\n logger.debug(`Loaded ${this.users.length} users from file`);\r\n } catch (error) {\r\n logger.error('Failed to load users from file:', error);\r\n throw new Error(`Failed to load users from file: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n }\r\n }\r\n\r\n /**\r\n * Save users from memory to the JSON file\r\n */\r\n private async saveUsersToFile(): Promise<void> {\r\n if (!this.hasChanged) {\r\n return;\r\n }\r\n\r\n try {\r\n // Create directory if it doesn't exist\r\n const dir = path.dirname(this.filePath);\r\n if (!fs.existsSync(dir)) {\r\n fs.mkdirSync(dir, { recursive: true });\r\n }\r\n\r\n // Filter out wsIds before saving to file (wsIds are only stored in memory)\r\n const usersToSave = this.users.map(user => {\r\n const { wsIds, ...userWithoutWsIds } = user;\r\n return userWithoutWsIds;\r\n });\r\n\r\n const data: UsersData = { users: usersToSave };\r\n fs.writeFileSync(this.filePath, JSON.stringify(data, null, 4));\r\n\r\n this.hasChanged = false;\r\n logger.debug(`Synced ${this.users.length} users to file (wsIds excluded)`);\r\n } catch (error) {\r\n logger.error('Failed to save users to file:', error);\r\n throw new Error(`Failed to save users to file: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n }\r\n }\r\n\r\n /**\r\n * Start the periodic sync interval\r\n */\r\n private startSyncInterval(): void {\r\n if (this.syncInterval) {\r\n return;\r\n }\r\n\r\n this.syncInterval = setInterval(async () => {\r\n if (this.hasChanged) {\r\n try {\r\n await this.saveUsersToFile();\r\n logger.debug('Auto-sync: Users saved to file');\r\n } catch (error) {\r\n logger.error('Auto-sync failed:', error);\r\n }\r\n }\r\n }, this.syncIntervalMs);\r\n\r\n logger.debug(`Sync interval started (${this.syncIntervalMs}ms)`);\r\n }\r\n\r\n /**\r\n * Stop the periodic sync interval\r\n */\r\n public stopSyncInterval(): void {\r\n if (this.syncInterval) {\r\n clearInterval(this.syncInterval);\r\n this.syncInterval = null;\r\n logger.debug('Sync interval stopped');\r\n }\r\n }\r\n\r\n /**\r\n * Force sync users to file immediately\r\n */\r\n public async forceSync(): Promise<void> {\r\n await this.saveUsersToFile();\r\n }\r\n\r\n /**\r\n * Create a new user\r\n * @param user - User object to create\r\n * @returns The created user\r\n */\r\n public createUser(user: User): User {\r\n // Validate user data with Zod schema\r\n const validatedUser = UserSchema.parse(user);\r\n\r\n // Check for duplicate username\r\n if (this.users.some(u => u.username === validatedUser.username)) {\r\n throw new Error(`User with username ${validatedUser.username} already exists`);\r\n }\r\n\r\n // Check for duplicate email if email is provided\r\n if (validatedUser.email && this.users.some(u => u.email === validatedUser.email)) {\r\n throw new Error(`User with email ${validatedUser.email} already exists`);\r\n }\r\n\r\n this.users.push(validatedUser);\r\n this.hasChanged = true;\r\n logger.debug(`User created: ${validatedUser.username}`);\r\n\r\n return validatedUser;\r\n }\r\n\r\n /**\r\n * Read a user by username\r\n * @param username - Username to retrieve\r\n * @returns The user if found, undefined otherwise\r\n */\r\n public getUser(username: string): User | undefined {\r\n return this.users.find(u => u.username === username);\r\n }\r\n\r\n /**\r\n * Read a user by email\r\n * @param email - Email to retrieve\r\n * @returns The user if found, undefined otherwise\r\n */\r\n public getUserByEmail(email: string): User | undefined {\r\n return this.users.find(u => u.email === email);\r\n }\r\n\r\n /**\r\n * Find user by username or email\r\n * @param identifier - Username or email to search for\r\n * @returns The user if found, undefined otherwise\r\n */\r\n public getUserByUsernameOrEmail(identifier: string): User | undefined {\r\n return this.users.find(u => u.username === identifier || u.email === identifier);\r\n }\r\n\r\n /**\r\n * Read all users\r\n * @returns Array of all users\r\n */\r\n public getAllUsers(): User[] {\r\n return [...this.users];\r\n }\r\n\r\n /**\r\n * Find users by a predicate function\r\n * @param predicate - Function to filter users\r\n * @returns Array of matching users\r\n */\r\n public findUsers(predicate: (user: User) => boolean): User[] {\r\n return this.users.filter(predicate);\r\n }\r\n\r\n /**\r\n * Update an existing user by username\r\n * @param username - Username of user to update\r\n * @param updates - Partial user object with fields to update\r\n * @returns The updated user\r\n */\r\n public updateUser(username: string, updates: Partial<User>): User {\r\n const userIndex = this.users.findIndex(u => u.username === username);\r\n if (userIndex === -1) {\r\n throw new Error(`User with username ${username} not found`);\r\n }\r\n\r\n const updatedUser = { ...this.users[userIndex], ...updates };\r\n this.users[userIndex] = updatedUser;\r\n this.hasChanged = true;\r\n logger.debug(`User updated: ${username}`);\r\n\r\n return updatedUser;\r\n }\r\n\r\n /**\r\n * Delete a user by username\r\n * @param username - Username of user to delete\r\n * @returns true if user was deleted, false if not found\r\n */\r\n public deleteUser(username: string): boolean {\r\n const initialLength = this.users.length;\r\n this.users = this.users.filter(u => u.username !== username);\r\n\r\n if (this.users.length < initialLength) {\r\n this.hasChanged = true;\r\n logger.debug(`User deleted: ${username}`);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Delete all users\r\n */\r\n public deleteAllUsers(): void {\r\n if (this.users.length > 0) {\r\n this.users = [];\r\n this.hasChanged = true;\r\n logger.debug('All users deleted');\r\n }\r\n }\r\n\r\n /**\r\n * Get the count of users\r\n * @returns Number of users in memory\r\n */\r\n public getUserCount(): number {\r\n return this.users.length;\r\n }\r\n\r\n /**\r\n * Check if a user exists\r\n * @param username - Username to check\r\n * @returns true if user exists, false otherwise\r\n */\r\n public userExists(username: string): boolean {\r\n return this.users.some(u => u.username === username);\r\n }\r\n\r\n /**\r\n * Add a WebSocket ID to a user's wsIds array\r\n * @param username - Username to update\r\n * @param wsId - WebSocket ID to add\r\n * @returns true if successful, false if user not found\r\n */\r\n public addWsId(username: string, wsId: string): boolean {\r\n const user = this.getUser(username);\r\n if (!user) {\r\n return false;\r\n }\r\n\r\n if(!user.wsIds || !Array.isArray(user.wsIds)) {\r\n user.wsIds = [];\r\n }\r\n\r\n if (!user.wsIds.includes(wsId)) {\r\n user.wsIds.push(wsId);\r\n // this.hasChanged = true;\r\n logger.debug(`WebSocket ID added to user ${username}: ${wsId}`);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Remove a WebSocket ID from a user's wsIds array\r\n * @param username - Username to update\r\n * @param wsId - WebSocket ID to remove\r\n * @returns true if successful, false if user not found\r\n */\r\n public removeWsId(username: string, wsId: string): boolean {\r\n const user = this.getUser(username);\r\n if (!user) {\r\n return false;\r\n }\r\n\r\n if(!user.wsIds || !Array.isArray(user.wsIds)) {\r\n return false;\r\n }\r\n\r\n const initialLength = user.wsIds.length;\r\n user.wsIds = user.wsIds.filter(id => id !== wsId);\r\n\r\n if (user.wsIds.length < initialLength) {\r\n // this.hasChanged = true;\r\n logger.debug(`WebSocket ID removed from user ${username}: ${wsId}`);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the change status\r\n * @returns true if there are unsaved changes, false otherwise\r\n */\r\n public hasUnsavedChanges(): boolean {\r\n return this.hasChanged;\r\n }\r\n\r\n /**\r\n * Cleanup resources and stop sync interval\r\n */\r\n public async destroy(): Promise<void> {\r\n this.stopSyncInterval();\r\n // Final sync before cleanup\r\n if (this.hasChanged) {\r\n await this.saveUsersToFile();\r\n }\r\n logger.info('UserManager destroyed');\r\n }\r\n}\r\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { logger } from '../utils/logger';\r\nimport { DSLRendererProps, DSLRendererPropsSchema } from './types';\r\n\r\n/**\r\n * DashboardManager class to handle CRUD operations on dashboards\r\n * All operations read/write directly to files (no in-memory caching)\r\n */\r\nexport class DashboardManager {\r\n private dashboardsBasePath: string;\r\n private projectId: string;\r\n\r\n /**\r\n * Initialize DashboardManager with project ID\r\n * @param projectId - Project ID to use in file path\r\n */\r\n constructor(projectId: string = 'snowflake-dataset') {\r\n this.projectId = projectId;\r\n this.dashboardsBasePath = path.join(\r\n os.homedir(),\r\n '.superatom',\r\n 'projects',\r\n projectId,\r\n 'dashboards'\r\n );\r\n }\r\n\r\n /**\r\n * Get the file path for a specific dashboard\r\n * @param dashboardId - Dashboard ID\r\n * @returns Full path to dashboard data.json file\r\n */\r\n private getDashboardPath(dashboardId: string): string {\r\n return path.join(this.dashboardsBasePath, dashboardId, 'data.json');\r\n }\r\n\r\n /**\r\n * Create a new dashboard\r\n * @param dashboardId - Unique dashboard ID\r\n * @param dashboard - Dashboard data\r\n * @returns Created dashboard with metadata\r\n */\r\n createDashboard(dashboardId: string, dashboard: DSLRendererProps): DSLRendererProps {\r\n const dashboardPath = this.getDashboardPath(dashboardId);\r\n const dashboardDir = path.dirname(dashboardPath);\r\n\r\n // Check if dashboard already exists\r\n if (fs.existsSync(dashboardPath)) {\r\n throw new Error(`Dashboard '${dashboardId}' already exists`);\r\n }\r\n\r\n // Validate dashboard structure\r\n const validated = DSLRendererPropsSchema.parse(dashboard);\r\n\r\n // Create directory structure\r\n fs.mkdirSync(dashboardDir, { recursive: true });\r\n\r\n // Write dashboard to file\r\n fs.writeFileSync(dashboardPath, JSON.stringify(validated, null, 4));\r\n\r\n logger.info(`Dashboard created: ${dashboardId}`);\r\n return validated;\r\n }\r\n\r\n /**\r\n * Get a specific dashboard by ID\r\n * @param dashboardId - Dashboard ID\r\n * @returns Dashboard data or null if not found\r\n */\r\n getDashboard(dashboardId: string): DSLRendererProps | null {\r\n const dashboardPath = this.getDashboardPath(dashboardId);\r\n\r\n if (!fs.existsSync(dashboardPath)) {\r\n logger.warn(`Dashboard not found: ${dashboardId}`);\r\n return null;\r\n }\r\n\r\n try {\r\n const fileContent = fs.readFileSync(dashboardPath, 'utf-8');\r\n const dashboard = JSON.parse(fileContent) as DSLRendererProps;\r\n\r\n // Validate structure\r\n const validated = DSLRendererPropsSchema.parse(dashboard);\r\n return validated;\r\n } catch (error) {\r\n logger.error(`Failed to read dashboard ${dashboardId}:`, error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get all dashboards\r\n * @returns Array of dashboard objects with their IDs\r\n */\r\n getAllDashboards(): Array<{ dashboardId: string; dashboard: DSLRendererProps }> {\r\n // Create base directory if it doesn't exist\r\n if (!fs.existsSync(this.dashboardsBasePath)) {\r\n fs.mkdirSync(this.dashboardsBasePath, { recursive: true });\r\n return [];\r\n }\r\n\r\n const dashboards: Array<{ dashboardId: string; dashboard: DSLRendererProps }> = [];\r\n\r\n try {\r\n const dashboardDirs = fs.readdirSync(this.dashboardsBasePath);\r\n\r\n for (const dashboardId of dashboardDirs) {\r\n const dashboardPath = this.getDashboardPath(dashboardId);\r\n\r\n if (fs.existsSync(dashboardPath)) {\r\n const dashboard = this.getDashboard(dashboardId);\r\n if (dashboard) {\r\n dashboards.push({ dashboardId, dashboard });\r\n }\r\n }\r\n }\r\n\r\n logger.debug(`Retrieved ${dashboards.length} dashboards`);\r\n return dashboards;\r\n } catch (error) {\r\n logger.error('Failed to get all dashboards:', error);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Update an existing dashboard\r\n * @param dashboardId - Dashboard ID\r\n * @param dashboard - Updated dashboard data\r\n * @returns Updated dashboard or null if not found\r\n */\r\n updateDashboard(dashboardId: string, dashboard: DSLRendererProps): DSLRendererProps | null {\r\n const dashboardPath = this.getDashboardPath(dashboardId);\r\n\r\n if (!fs.existsSync(dashboardPath)) {\r\n logger.warn(`Dashboard not found for update: ${dashboardId}`);\r\n return null;\r\n }\r\n\r\n try {\r\n // Validate dashboard structure\r\n const validated = DSLRendererPropsSchema.parse(dashboard);\r\n\r\n // Write updated dashboard to file\r\n fs.writeFileSync(dashboardPath, JSON.stringify(validated, null, 4));\r\n\r\n logger.info(`Dashboard updated: ${dashboardId}`);\r\n return validated;\r\n } catch (error) {\r\n logger.error(`Failed to update dashboard ${dashboardId}:`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Delete a dashboard\r\n * @param dashboardId - Dashboard ID\r\n * @returns True if deleted, false if not found\r\n */\r\n deleteDashboard(dashboardId: string): boolean {\r\n const dashboardPath = this.getDashboardPath(dashboardId);\r\n const dashboardDir = path.dirname(dashboardPath);\r\n\r\n if (!fs.existsSync(dashboardPath)) {\r\n logger.warn(`Dashboard not found for deletion: ${dashboardId}`);\r\n return false;\r\n }\r\n\r\n try {\r\n // Delete the entire dashboard directory\r\n fs.rmSync(dashboardDir, { recursive: true, force: true });\r\n\r\n logger.info(`Dashboard deleted: ${dashboardId}`);\r\n return true;\r\n } catch (error) {\r\n logger.error(`Failed to delete dashboard ${dashboardId}:`, error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Check if a dashboard exists\r\n * @param dashboardId - Dashboard ID\r\n * @returns True if dashboard exists, false otherwise\r\n */\r\n dashboardExists(dashboardId: string): boolean {\r\n const dashboardPath = this.getDashboardPath(dashboardId);\r\n return fs.existsSync(dashboardPath);\r\n }\r\n\r\n /**\r\n * Get dashboard count\r\n * @returns Number of dashboards\r\n */\r\n getDashboardCount(): number {\r\n if (!fs.existsSync(this.dashboardsBasePath)) {\r\n return 0;\r\n }\r\n\r\n try {\r\n const dashboardDirs = fs.readdirSync(this.dashboardsBasePath);\r\n return dashboardDirs.filter((dir) => {\r\n const dashboardPath = this.getDashboardPath(dir);\r\n return fs.existsSync(dashboardPath);\r\n }).length;\r\n } catch (error) {\r\n logger.error('Failed to get dashboard count:', error);\r\n return 0;\r\n }\r\n }\r\n}\r\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { logger } from '../utils/logger';\r\nimport { DSLRendererProps, DSLRendererPropsSchema } from './types';\r\n\r\n/**\r\n * ReportManager class to handle CRUD operations on reports\r\n * All operations read/write directly to files (no in-memory caching)\r\n */\r\nexport class ReportManager {\r\n private reportsBasePath: string;\r\n private projectId: string;\r\n\r\n /**\r\n * Initialize ReportManager with project ID\r\n * @param projectId - Project ID to use in file path\r\n */\r\n constructor(projectId: string = 'snowflake-dataset') {\r\n this.projectId = projectId;\r\n this.reportsBasePath = path.join(\r\n os.homedir(),\r\n '.superatom',\r\n 'projects',\r\n projectId,\r\n 'reports'\r\n );\r\n }\r\n\r\n /**\r\n * Get the file path for a specific report\r\n * @param reportId - Report ID\r\n * @returns Full path to report data.json file\r\n */\r\n private getReportPath(reportId: string): string {\r\n return path.join(this.reportsBasePath, reportId, 'data.json');\r\n }\r\n\r\n /**\r\n * Create a new report\r\n * @param reportId - Unique report ID\r\n * @param report - Report data\r\n * @returns Created report with metadata\r\n */\r\n createReport(reportId: string, report: DSLRendererProps): DSLRendererProps {\r\n const reportPath = this.getReportPath(reportId);\r\n const reportDir = path.dirname(reportPath);\r\n\r\n // Check if report already exists\r\n if (fs.existsSync(reportPath)) {\r\n throw new Error(`Report '${reportId}' already exists`);\r\n }\r\n\r\n // Validate report structure\r\n const validated = DSLRendererPropsSchema.parse(report);\r\n\r\n // Create directory structure\r\n fs.mkdirSync(reportDir, { recursive: true });\r\n\r\n // Write report to file\r\n fs.writeFileSync(reportPath, JSON.stringify(validated, null, 4));\r\n\r\n logger.info(`Report created: ${reportId}`);\r\n return validated;\r\n }\r\n\r\n /**\r\n * Get a specific report by ID\r\n * @param reportId - Report ID\r\n * @returns Report data or null if not found\r\n */\r\n getReport(reportId: string): DSLRendererProps | null {\r\n const reportPath = this.getReportPath(reportId);\r\n\r\n if (!fs.existsSync(reportPath)) {\r\n logger.warn(`Report not found: ${reportId}`);\r\n return null;\r\n }\r\n\r\n try {\r\n const fileContent = fs.readFileSync(reportPath, 'utf-8');\r\n const report = JSON.parse(fileContent) as DSLRendererProps;\r\n\r\n // Validate structure\r\n const validated = DSLRendererPropsSchema.parse(report);\r\n return validated;\r\n } catch (error) {\r\n logger.error(`Failed to read report ${reportId}:`, error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get all reports\r\n * @returns Array of report objects with their IDs\r\n */\r\n getAllReports(): Array<{ reportId: string; report: DSLRendererProps }> {\r\n // Create base directory if it doesn't exist\r\n if (!fs.existsSync(this.reportsBasePath)) {\r\n fs.mkdirSync(this.reportsBasePath, { recursive: true });\r\n return [];\r\n }\r\n\r\n const reports: Array<{ reportId: string; report: DSLRendererProps }> = [];\r\n\r\n try {\r\n const reportDirs = fs.readdirSync(this.reportsBasePath);\r\n\r\n for (const reportId of reportDirs) {\r\n const reportPath = this.getReportPath(reportId);\r\n\r\n if (fs.existsSync(reportPath)) {\r\n const report = this.getReport(reportId);\r\n if (report) {\r\n reports.push({ reportId, report });\r\n }\r\n }\r\n }\r\n\r\n logger.debug(`Retrieved ${reports.length} reports`);\r\n return reports;\r\n } catch (error) {\r\n logger.error('Failed to get all reports:', error);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Update an existing report\r\n * @param reportId - Report ID\r\n * @param report - Updated report data\r\n * @returns Updated report or null if not found\r\n */\r\n updateReport(reportId: string, report: DSLRendererProps): DSLRendererProps | null {\r\n const reportPath = this.getReportPath(reportId);\r\n\r\n if (!fs.existsSync(reportPath)) {\r\n logger.warn(`Report not found for update: ${reportId}`);\r\n return null;\r\n }\r\n\r\n try {\r\n // Validate report structure\r\n const validated = DSLRendererPropsSchema.parse(report);\r\n\r\n // Write updated report to file\r\n fs.writeFileSync(reportPath, JSON.stringify(validated, null, 4));\r\n\r\n logger.info(`Report updated: ${reportId}`);\r\n return validated;\r\n } catch (error) {\r\n logger.error(`Failed to update report ${reportId}:`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Delete a report\r\n * @param reportId - Report ID\r\n * @returns True if deleted, false if not found\r\n */\r\n deleteReport(reportId: string): boolean {\r\n const reportPath = this.getReportPath(reportId);\r\n const reportDir = path.dirname(reportPath);\r\n\r\n if (!fs.existsSync(reportPath)) {\r\n logger.warn(`Report not found for deletion: ${reportId}`);\r\n return false;\r\n }\r\n\r\n try {\r\n // Delete the entire report directory\r\n fs.rmSync(reportDir, { recursive: true, force: true });\r\n\r\n logger.info(`Report deleted: ${reportId}`);\r\n return true;\r\n } catch (error) {\r\n logger.error(`Failed to delete report ${reportId}:`, error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Check if a report exists\r\n * @param reportId - Report ID\r\n * @returns True if report exists, false otherwise\r\n */\r\n reportExists(reportId: string): boolean {\r\n const reportPath = this.getReportPath(reportId);\r\n return fs.existsSync(reportPath);\r\n }\r\n\r\n /**\r\n * Get report count\r\n * @returns Number of reports\r\n */\r\n getReportCount(): number {\r\n if (!fs.existsSync(this.reportsBasePath)) {\r\n return 0;\r\n }\r\n\r\n try {\r\n const reportDirs = fs.readdirSync(this.reportsBasePath);\r\n return reportDirs.filter((dir) => {\r\n const reportPath = this.getReportPath(dir);\r\n return fs.existsSync(reportPath);\r\n }).length;\r\n } catch (error) {\r\n logger.error('Failed to get report count:', error);\r\n return 0;\r\n }\r\n }\r\n}\r\n","import { ThreadManager } from '../threads';\r\nimport { logger } from '../utils/logger';\r\nimport { STORAGE_CONFIG } from '../config/storage';\r\n\r\n/**\r\n * CleanupService handles cleanup of old threads and UIBlocks\r\n * to prevent memory bloat and maintain optimal performance\r\n */\r\nexport class CleanupService {\r\n private static instance: CleanupService;\r\n private cleanupInterval: NodeJS.Timeout | null = null;\r\n\r\n private constructor() {}\r\n\r\n /**\r\n * Get singleton instance of CleanupService\r\n */\r\n static getInstance(): CleanupService {\r\n if (!CleanupService.instance) {\r\n CleanupService.instance = new CleanupService();\r\n }\r\n return CleanupService.instance;\r\n }\r\n\r\n /**\r\n * Clean up old threads based on retention period\r\n * @param retentionDays - Number of days to keep threads (defaults to config)\r\n * @returns Number of threads deleted\r\n */\r\n cleanupOldThreads(retentionDays: number = STORAGE_CONFIG.THREAD_RETENTION_DAYS): number {\r\n const threadManager = ThreadManager.getInstance();\r\n const cutoffDate = new Date();\r\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\r\n\r\n const threads = threadManager.getAllThreads();\r\n let deletedCount = 0;\r\n\r\n for (const thread of threads) {\r\n if (thread.getCreatedAt() < cutoffDate) {\r\n const threadId = thread.getId();\r\n if (threadManager.deleteThread(threadId)) {\r\n deletedCount++;\r\n logger.info(`Deleted old thread: ${threadId} (created: ${thread.getCreatedAt().toISOString()})`);\r\n }\r\n }\r\n }\r\n\r\n if (deletedCount > 0) {\r\n logger.info(`Cleanup: Deleted ${deletedCount} old threads (older than ${retentionDays} days)`);\r\n }\r\n\r\n return deletedCount;\r\n }\r\n\r\n /**\r\n * Clean up old UIBlocks within threads based on retention period\r\n * @param retentionDays - Number of days to keep UIBlocks (defaults to config)\r\n * @returns Object with number of UIBlocks deleted per thread\r\n */\r\n cleanupOldUIBlocks(retentionDays: number = STORAGE_CONFIG.UIBLOCK_RETENTION_DAYS): { [threadId: string]: number } {\r\n const threadManager = ThreadManager.getInstance();\r\n const cutoffDate = new Date();\r\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\r\n\r\n const threads = threadManager.getAllThreads();\r\n const deletionStats: { [threadId: string]: number } = {};\r\n\r\n for (const thread of threads) {\r\n const uiblocks = thread.getUIBlocks();\r\n let deletedInThread = 0;\r\n\r\n for (const uiblock of uiblocks) {\r\n if (uiblock.getCreatedAt() < cutoffDate) {\r\n if (thread.removeUIBlock(uiblock.getId())) {\r\n deletedInThread++;\r\n }\r\n }\r\n }\r\n\r\n if (deletedInThread > 0) {\r\n deletionStats[thread.getId()] = deletedInThread;\r\n logger.info(\r\n `Deleted ${deletedInThread} old UIBlocks from thread ${thread.getId()} (older than ${retentionDays} days)`\r\n );\r\n }\r\n }\r\n\r\n const totalDeleted = Object.values(deletionStats).reduce((sum, count) => sum + count, 0);\r\n if (totalDeleted > 0) {\r\n logger.info(`Cleanup: Deleted ${totalDeleted} old UIBlocks across ${Object.keys(deletionStats).length} threads`);\r\n }\r\n\r\n return deletionStats;\r\n }\r\n\r\n /**\r\n * Clear all component data from UIBlocks to free memory\r\n * Keeps metadata but removes the actual data\r\n * @param retentionDays - Number of days to keep full data (defaults to config)\r\n * @returns Number of UIBlocks whose data was cleared\r\n */\r\n clearOldUIBlockData(retentionDays: number = STORAGE_CONFIG.UIBLOCK_RETENTION_DAYS): number {\r\n const threadManager = ThreadManager.getInstance();\r\n const cutoffDate = new Date();\r\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\r\n\r\n const threads = threadManager.getAllThreads();\r\n let clearedCount = 0;\r\n\r\n for (const thread of threads) {\r\n const uiblocks = thread.getUIBlocks();\r\n\r\n for (const uiblock of uiblocks) {\r\n if (uiblock.getCreatedAt() < cutoffDate) {\r\n const componentData = uiblock.getComponentData();\r\n\r\n // Only clear if data exists\r\n if (componentData && Object.keys(componentData).length > 0) {\r\n // Keep metadata but clear actual data\r\n const metadata = {\r\n dataCleared: true,\r\n clearedAt: new Date().toISOString(),\r\n originalDataInfo: {\r\n totalRows: componentData.totalRows,\r\n storedRows: componentData.storedRows,\r\n isTruncated: componentData.isTruncated,\r\n },\r\n };\r\n\r\n uiblock.setComponentData({ ...metadata, data: null });\r\n clearedCount++;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (clearedCount > 0) {\r\n logger.info(`Cleanup: Cleared data from ${clearedCount} old UIBlocks (older than ${retentionDays} days)`);\r\n }\r\n\r\n return clearedCount;\r\n }\r\n\r\n /**\r\n * Run full cleanup (threads, UIBlocks, and data)\r\n * @returns Cleanup statistics\r\n */\r\n runFullCleanup(): {\r\n threadsDeleted: number;\r\n uiblocksDeleted: { [threadId: string]: number };\r\n dataCleared: number;\r\n } {\r\n logger.info('Starting full cleanup...');\r\n\r\n const stats = {\r\n threadsDeleted: this.cleanupOldThreads(),\r\n uiblocksDeleted: this.cleanupOldUIBlocks(),\r\n dataCleared: this.clearOldUIBlockData(),\r\n };\r\n\r\n const totalUIBlocksDeleted = Object.values(stats.uiblocksDeleted).reduce((sum, count) => sum + count, 0);\r\n\r\n logger.info(\r\n `Full cleanup completed: ${stats.threadsDeleted} threads, ${totalUIBlocksDeleted} UIBlocks deleted, ${stats.dataCleared} UIBlock data cleared`\r\n );\r\n\r\n return stats;\r\n }\r\n\r\n /**\r\n * Start automatic cleanup at regular intervals\r\n * @param intervalHours - Hours between cleanup runs (default: 24)\r\n */\r\n startAutoCleanup(intervalHours: number = 24): void {\r\n if (this.cleanupInterval) {\r\n logger.warn('Auto cleanup is already running');\r\n\r\n //stop this and run with new interval\r\n\r\n \r\n return;\r\n }\r\n\r\n const intervalMs = intervalHours * 60 * 60 * 1000;\r\n\r\n // Run initial cleanup\r\n this.runFullCleanup();\r\n\r\n // Schedule recurring cleanup\r\n this.cleanupInterval = setInterval(() => {\r\n this.runFullCleanup();\r\n }, intervalMs);\r\n\r\n logger.info(`Auto cleanup started: running every ${intervalHours} hours`);\r\n }\r\n\r\n /**\r\n * Stop automatic cleanup\r\n */\r\n stopAutoCleanup(): void {\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n this.cleanupInterval = null;\r\n logger.info('Auto cleanup stopped');\r\n }\r\n }\r\n\r\n /**\r\n * Check if auto cleanup is running\r\n */\r\n isAutoCleanupRunning(): boolean {\r\n return this.cleanupInterval !== null;\r\n }\r\n\r\n /**\r\n * Get current memory usage statistics\r\n */\r\n getMemoryStats(): {\r\n threadCount: number;\r\n totalUIBlocks: number;\r\n avgUIBlocksPerThread: number;\r\n } {\r\n const threadManager = ThreadManager.getInstance();\r\n const threads = threadManager.getAllThreads();\r\n const threadCount = threads.length;\r\n\r\n let totalUIBlocks = 0;\r\n for (const thread of threads) {\r\n totalUIBlocks += thread.getUIBlockCount();\r\n }\r\n\r\n return {\r\n threadCount,\r\n totalUIBlocks,\r\n avgUIBlocksPerThread: threadCount > 0 ? totalUIBlocks / threadCount : 0,\r\n };\r\n }\r\n}\r\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAwHR,MAAM;AAAA;AAAA;AAAA,EAGP;AAAA,EAEA,yBAAyB;AAAA,IACxB,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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","names":["WebSocket","import_zod","import_zod","ExpressionSchema","BindingSchema","ForDirectiveSchema","QuerySpecSchema","UIElementSchema","UIComponentSchema","DSLRendererPropsSchema","DSLRendererPropsSchema","fs","size","import_crypto","result","fs","import_crypto","crypto","sendDataResponse","sendDataResponse","import_fs","path","fs","schema","import_fs","import_path","path","fs","Anthropic","Groq","ensureQueryLimit","result","elapsedTime","dotenv","import_dotenv","dotenv","import_dotenv","dotenv","LOG_LEVEL_PRIORITY","MESSAGE_LEVEL_PRIORITY","sendDataResponse","sendResponse","sendResponse","sendResponse","dashboardManager","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","sendResponse","reportManager","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","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/userResponse/utils.ts","../src/index.ts","../src/websocket.ts","../src/types.ts","../src/dashboards/types.ts","../src/reports/types.ts","../src/utils/logger.ts","../src/threads/uiblock.ts","../src/config/storage.ts","../src/threads/thread.ts","../src/threads/thread-manager.ts","../src/handlers/data-request.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/userResponse/prompt-loader.ts","../src/userResponse/prompts.ts","../src/llm.ts","../src/userResponse/knowledge-base.ts","../src/userResponse/anthropic.ts","../src/userResponse/index.ts","../src/utils/log-collector.ts","../src/config/context.ts","../src/handlers/user-prompt-request.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/auth/user-manager.ts","../src/dashboards/dashboard-manager.ts","../src/reports/report-manager.ts","../src/services/cleanup-service.ts"],"sourcesContent":["import type { Action } from '../threads/action';\n\n/**\n * Converts T-SQL TOP syntax to Snowflake LIMIT syntax\n * Snowflake doesn't support TOP keyword - it must use LIMIT\n * @param query - The SQL query to check\n * @returns The query with TOP converted to LIMIT\n */\nexport function convertTopToLimit(query: string): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\t// Replace \"TOP N\" with nothing (we'll add LIMIT at the end)\n\t// Pattern: SELECT TOP number or SELECT TOP (number)\n\tlet modifiedQuery = query.replace(/\\bSELECT\\s+TOP\\s+(\\d+)\\b/gi, 'SELECT');\n\n\tif (modifiedQuery !== query) {\n\t\tconsole.warn(`⚠️ Query had TOP syntax. Converting to LIMIT for Snowflake compatibility.`);\n\t}\n\n\treturn modifiedQuery;\n}\n\n/**\n * Ensures a SQL query has a LIMIT clause to prevent large result sets\n * Only applies to SELECT queries - leaves INSERT, UPDATE, DELETE, etc. unchanged\n * Also removes any duplicate LIMIT clauses to prevent SQL errors\n * Converts T-SQL TOP syntax to Snowflake LIMIT syntax\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 * @returns The query with a single LIMIT clause (if it's a SELECT query)\n */\nexport function ensureQueryLimit(query: string, defaultLimit: number = 32, maxLimit: number = 32): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\n\n\tlet trimmedQuery = query.trim();\n\n\t// Only apply LIMIT 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// Step 1: Convert TOP syntax to standard format\n\ttrimmedQuery = convertTopToLimit(trimmedQuery);\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\t// Remove any duplicate LIMIT clauses (keep only the last one, or remove all to add a fresh one)\n\t// This regex matches LIMIT followed by a number, case-insensitive\n\tconst limitMatches = trimmedQuery.match(/\\bLIMIT\\s+(\\d+)\\b/gi);\n\n\tif (limitMatches && limitMatches.length > 0) {\n\t\t// If there are multiple LIMIT clauses, remove them all and add a fresh one\n\t\tif (limitMatches.length > 1) {\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\t// If existing limit is less than or equal to maxLimit, keep it\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\t// If existing limit exceeds maxLimit, replace it with maxLimit\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\t// Add back the semicolon if it was there\n\tif (hadSemicolon) {\n\t\ttrimmedQuery += ';';\n\t}\n\n\treturn trimmedQuery;\n}\n\n/**\n * Validates and fixes scalar subqueries to ensure they return exactly one row\n * Adds LIMIT 1 to subqueries used with scalar comparison operators (=, <, >, <=, >=, <>)\n *\n * @param query - The SQL query to validate\n * @returns The query with fixed scalar subqueries\n */\nexport function fixScalarSubqueries(query: string): string {\n\tif (!query || query.trim().length === 0) {\n\t\treturn query;\n\t}\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\t// Check if it already has LIMIT\n\t\tif (/\\bLIMIT\\s+\\d+/i.test(subquery)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Add LIMIT 1 before the closing parenthesis\n\t\tconst fixedSubquery = subquery.trim() + ' LIMIT 1';\n\t\tmodifiedQuery =\n\t\t\tmodifiedQuery.substring(0, startPos) +\n\t\t\tfixedSubquery +\n\t\t\tmodifiedQuery.substring(endPos);\n\n\t\thasChanges = true;\n\t\tconsole.warn(`⚠️ Fixed scalar subquery: added LIMIT 1 to prevent multiple row error`);\n\t}\n\n\tif (hasChanges) {\n\t\tconsole.log('✓ Query validated and fixed for PostgreSQL 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 Component,\n LLMProvider,\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 { 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 anthropicApiKey: string;\n private groqApiKey: string;\n private llmProviders: LLMProvider[];\n private userManager: UserManager;\n private dashboardManager: DashboardManager;\n private reportManager: ReportManager;\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.llmProviders = config.LLM_PROVIDERS || getLLMProviders();\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 await promptLoader.initialize();\n logger.info(`PromptLoader initialized with ${promptLoader.getCacheSize()} prompts from ${promptLoader.getPromptsDir()}`);\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 url.searchParams.set('apiKey', this.apiKey);\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 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 '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, (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, (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.llmProviders, this.collections).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.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)).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)).catch((error) => {\n logger.error('Failed to handle component list request:', error);\n });\n break;\n\n case 'USERS':\n handleUsersRequest(parsed, (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, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle dashboards request:', error);\n });\n break;\n\n case 'REPORTS':\n handleReportsRequest(parsed, (msg) => this.send(msg)).catch((error) => {\n logger.error('Failed to handle reports 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 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 // 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 private storeComponents(components: Component[]){\n this.components = components;\n }\n \n}\n\n// Export types\nexport type { Message, IncomingMessage, SuperatomSDKConfig, CollectionHandler, CollectionOperation, User, UsersData } 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';","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// 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 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});\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 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// Admin User Management Request/Response schemas (Unified)\nexport const UsersRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne']),\n data: z.object({\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 }).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';\n\nimport type { LogLevel } from './utils/logger';\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 ANTHROPIC_API_KEY?: string;\n GROQ_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// Dashboard CRUD request payload\n\nexport const DashboardsRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne']),\n data: z.object({\n dashboardId: z.string().optional(),\n dashboard: DSLRendererPropsSchema.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// Report CRUD request payload\nexport const ReportsRequestPayloadSchema = z.object({\n operation: z.enum(['create', 'update', 'delete', 'getAll', 'getOne']),\n data: z.object({\n reportId: z.string().optional(),\n report: ReportDSLRendererPropsSchema.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// ==================== 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// 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 { 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 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","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 (1MB)\n */\n MAX_SIZE_PER_BLOCK_BYTES: 1 * 1024 * 1024, // 1MB\n\n /**\n * Number of days to keep threads before cleanup\n */\n THREAD_RETENTION_DAYS: 7,\n\n /**\n * Number of days to keep UIBlocks before cleanup\n */\n UIBLOCK_RETENTION_DAYS: 7,\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 { 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 the response\n if (uiBlock) {\n uiBlock.setComponentData(result || {});\n logger.info(`Updated UIBlock ${uiBlockId} with component data from ${collection}.${op}`);\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 * 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\";\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}\n\n/**\n * Validate user credentials against stored user data\n * @param credentials - Login credentials with username/email and password\n * @returns ValidationResult indicating success or failure\n */\nexport function validateUser(credentials: LoginCredentials): 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 // Find user by username or email from in-memory cache\n logger.debug(`[validateUser] Looking up user by identifier: ${identifier}`);\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: ${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 successfully: ${user.username}`);\n logger.debug(`[validateUser] Returning user data for: ${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 UserManager's in-memory cache with automatic file sync\n * @param credentials - Login credentials\n * @param wsId - WebSocket ID to store\n * @returns ValidationResult with authentication status\n */\nexport function authenticateAndStoreWsId(credentials: LoginCredentials, wsId: string): 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 = validateUser(credentials);\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 * @returns ValidationResult indicating if token is valid\n */\nexport function verifyAuthToken(authToken: string): 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 = validateUser(credentials);\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 } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\n\nexport async function handleAuthLoginRequest(\n data: any,\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}`);\n logger.debug(`[AUTH_LOGIN_REQ ${id}] WebSocket ID: ${wsId}`);\n\n // Authenticate user and store wsId\n logger.debug(`[AUTH_LOGIN_REQ ${id}] Calling authenticateAndStoreWsId for user: ${identifier}`);\n const authResult = authenticateAndStoreWsId(\n { username, email, password },\n wsId\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 } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\nexport async function handleAuthVerifyRequest(\n data: any,\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 = verifyAuthToken(token);\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 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 type { Action } from '../threads/action';\nimport KB from './knowledge-base';\n\nexport interface BaseLLMConfig {\n\tmodel?: string;\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 defaultLimit: number;\n\tprotected apiKey?: string;\n\n\tconstructor(config?: BaseLLMConfig) {\n\t\tthis.model = config?.model || this.getDefaultModel();\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\n\t */\n\tprotected abstract getDefaultModel(): 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 * Classify user question to determine the type and required visualizations\n\t */\n\tasync classifyUserQuestion(\n\t\tuserPrompt: string,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<{\n\t\tquestionType: 'analytical' | 'data_modification' | 'general';\n\t\tvisualizations: string[];\n\t\treasoning: string;\n\t\tneedsMultipleComponents: boolean;\n\t}> {\n\t\t\n\t\ttry {\n\t\t\tconst prompts = await promptLoader.loadPrompts('classify', {\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\n\t\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: 800,\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\t// Log the LLM explanation with type\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'User question classified',\n\t\t\t\tresult.reasoning || 'No reasoning provided',\n\t\t\t\t{\n\t\t\t\t\tquestionType: result.questionType || 'general',\n\t\t\t\t\tvisualizations: result.visualizations || [],\n\t\t\t\t\tneedsMultipleComponents: result.needsMultipleComponents || false\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tquestionType: result.questionType || 'general',\n\t\t\t\tvisualizations: result.visualizations || [],\n\t\t\t\treasoning: result.reasoning || 'No reasoning provided',\n\t\t\t\tneedsMultipleComponents: result.needsMultipleComponents || false\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 user question: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Classification error details:`, error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Enhanced function that validates and modifies the entire props object based on user request\n\t * This includes query, title, description, and config properties\n\t */\n\tasync validateAndModifyProps(\n\t\tuserPrompt: string,\n\t\toriginalProps: any,\n\t\tcomponentName: string,\n\t\tcomponentType: string,\n\t\tcomponentDescription?: string,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<{ props: any; isModified: boolean; reasoning: string; modifications: string[] }> {\n\n\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\t\ttry {\n\t\t\tconst prompts = await promptLoader.loadPrompts('modify-props', {\n\t\t\t\tCOMPONENT_NAME: componentName,\n\t\t\t\tCOMPONENT_TYPE: componentType,\n\t\t\t\tCOMPONENT_DESCRIPTION: componentDescription || 'No description',\n\t\t\t\tSCHEMA_DOC: schemaDoc || 'No schema available',\n\t\t\t\tDEFAULT_LIMIT: this.defaultLimit,\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tCURRENT_PROPS: JSON.stringify(originalProps, null, 2),\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\n\t\t\t});\n\n\t\t\tlogger.debug('props-modification: System prompt\\n',prompts.system.substring(0, 100), '\\n\\n\\n', 'User prompt:', prompts.user.substring(0, 50));\t\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: 2500,\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\t// Ensure all queries have a LIMIT clause and fix scalar subqueries\n\t\t\tconst props = result.props || originalProps;\n\t\t\tif (props && props.query) {\n\t\t\t\t// First fix scalar subqueries to prevent PostgreSQL errors\n\t\t\t\tprops.query = fixScalarSubqueries(props.query);\n\t\t\t\t// Then ensure LIMIT clause exists\n\t\t\t\tprops.query = ensureQueryLimit(props.query, this.defaultLimit);\n\t\t\t}\n\n\t\t\t// Log the generated query and explanation with types\n\t\t\tif (props && props.query) {\n\t\t\t\tlogCollector?.logQuery(\n\t\t\t\t\t'Props query modified',\n\t\t\t\t\tprops.query,\n\t\t\t\t\t{\n\t\t\t\t\t\tmodifications: result.modifications || [],\n\t\t\t\t\t\treasoning: result.reasoning || 'No modifications needed'\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (result.reasoning) {\n\t\t\t\tlogCollector?.logExplanation(\n\t\t\t\t\t'Props modification explanation',\n\t\t\t\t\tresult.reasoning,\n\t\t\t\t\t{ modifications: result.modifications || [] }\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tprops: props,\n\t\t\t\tisModified: result.isModified || false,\n\t\t\t\treasoning: result.reasoning || 'No modifications needed',\n\t\t\t\tmodifications: result.modifications || []\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 validating/modifying props: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Props validation error details:`, error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Match and select a component from available components filtered by type\n\t * This picks the best matching component based on user prompt and modifies its props\n\t */\n\tasync generateAnalyticalComponent(\n\t\tuserPrompt: string,\n\t\tcomponents: Component[],\n\t\tpreferredVisualizationType?: string,\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<{\n\t\tcomponent: Component | null;\n\t\treasoning: string;\n\t\tisGenerated: boolean;\n\t}> {\n\t\ttry {\n\t\t\t// Filter components by the preferred visualization type\n\t\t\tconst filteredComponents = preferredVisualizationType\n\t\t\t\t? components.filter(c => c.type === preferredVisualizationType)\n\t\t\t\t: components;\n\n\t\t\tif (filteredComponents.length === 0) {\n\t\t\t\tlogCollector?.warn(\n\t\t\t\t\t`No components found of type ${preferredVisualizationType}`,\n\t\t\t\t\t'explanation',\n\t\t\t\t\t{ reason: 'No matching components available for this visualization type' }\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tcomponent: null,\n\t\t\t\t\treasoning: `No components available of type ${preferredVisualizationType}`,\n\t\t\t\t\tisGenerated: false\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Format filtered components for the prompt\n\t\t\tconst componentsText = filteredComponents\n\t\t\t\t.map((comp, idx) => {\n\t\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\n\t\t\t\t\tconst category = comp.category || 'general';\n\t\t\t\t\tconst propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : 'No props';\n\t\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\n Name: ${comp.name}\n Type: ${comp.type}\n Category: ${category}\n Description: ${comp.description || 'No description'}\n Keywords: ${keywords}\n Props Preview: ${propsPreview}`;\n\t\t\t\t})\n\t\t\t\t.join('\\n\\n');\n\n\t\t\tconst visualizationConstraint = preferredVisualizationType\n\t\t\t\t? `\\n**IMPORTANT: Components are filtered to type ${preferredVisualizationType}. Select the best match.**\\n`\n\t\t\t\t: '';\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('single-component', {\n\t\t\t\tCOMPONENT_TYPE: preferredVisualizationType || 'any',\n\t\t\t\tCOMPONENTS_LIST: componentsText,\n\t\t\t\tVISUALIZATION_CONSTRAINT: visualizationConstraint,\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\n\t\t\t});\n\n\t\t\tlogger.debug('single-component: System prompt\\n',prompts.system.substring(0, 100), '\\n\\n\\n', 'User prompt:', prompts.user.substring(0, 50));\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: 2000,\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.canGenerate || result.confidence < 50) {\n\t\t\t\tlogCollector?.warn(\n\t\t\t\t\t'Cannot match component',\n\t\t\t\t\t'explanation',\n\t\t\t\t\t{ reason: result.reasoning || 'Unable to find matching component for this question' }\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tcomponent: null,\n\t\t\t\t\treasoning: result.reasoning || 'Unable to find matching component for this question',\n\t\t\t\t\tisGenerated: false\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Get the matched component\n\t\t\tconst componentIndex = result.componentIndex;\n\t\t\tconst componentId = result.componentId;\n\t\t\tlet matchedComponent = null;\n\n\t\t\t// Prefer componentId over componentIndex\n\t\t\tif (componentId) {\n\t\t\t\tmatchedComponent = filteredComponents.find(c => c.id === componentId);\n\t\t\t}\n\n\t\t\t// Fallback to componentIndex\n\t\t\tif (!matchedComponent && componentIndex) {\n\t\t\t\tmatchedComponent = filteredComponents[componentIndex - 1];\n\t\t\t}\n\n\t\t\tif (!matchedComponent) {\n\t\t\t\t\n\t\t\t\tlogCollector?.warn('Component not found in filtered list');\n\t\t\t\treturn {\n\t\t\t\t\tcomponent: null,\n\t\t\t\t\treasoning: 'Component not found in filtered list',\n\t\t\t\t\tisGenerated: false\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlogCollector?.info(`Matched component: ${matchedComponent.name} (confidence: ${result.confidence}%)`);\n\n\t\t\t// Now modify the component's props based on user prompt\n\t\t\tconst propsValidation = await this.validateAndModifyProps(\n\t\t\t\tuserPrompt,\n\t\t\t\tmatchedComponent.props,\n\t\t\t\tmatchedComponent.name,\n\t\t\t\tmatchedComponent.type,\n\t\t\t\tmatchedComponent.description,\n\t\t\t\tapiKey,\n\t\t\t\tlogCollector,\n\t\t\t\tconversationHistory\n\t\t\t);\n\n\t\t\t// Create modified component\n\t\t\tconst modifiedComponent: Component = {\n\t\t\t\t...matchedComponent,\n\t\t\t\tprops: propsValidation.props\n\t\t\t};\n\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'Analytical component selected and modified',\n\t\t\t\tresult.reasoning || 'Selected component based on analytical question',\n\t\t\t\t{\n\t\t\t\t\tcomponentName: matchedComponent.name,\n\t\t\t\t\tcomponentType: matchedComponent.type,\n\t\t\t\t\tconfidence: result.confidence,\n\t\t\t\t\tpropsModified: propsValidation.isModified\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tcomponent: modifiedComponent,\n\t\t\t\treasoning: result.reasoning || 'Selected and modified component based on analytical question',\n\t\t\t\tisGenerated: true\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 analytical component: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Analytical component generation error details:`, error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Generate container metadata (title and description) for multi-component dashboard\n\t */\n\tasync generateContainerMetadata(\n\t\tuserPrompt: string,\n\t\tvisualizationTypes: string[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<{\n\t\ttitle: string;\n\t\tdescription: string;\n\t}> {\n\t\ttry {\n\t\t\tconst prompts = await promptLoader.loadPrompts('container-metadata', {\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tVISUALIZATION_TYPES: visualizationTypes.join(', '),\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\n\t\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: 500,\n\t\t\t\t\ttemperature: 0.3,\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'Container metadata generated',\n\t\t\t\t`Generated title and description for multi-component dashboard`,\n\t\t\t\t{\n\t\t\t\t\ttitle: result.title,\n\t\t\t\t\tdescription: result.description,\n\t\t\t\t\tvisualizationTypes\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\ttitle: result.title || `${userPrompt} - Dashboard`,\n\t\t\t\tdescription: result.description || `Multi-component dashboard showing ${visualizationTypes.join(', ')}`\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 container metadata: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Container metadata error details:`, error);\n\t\t\t// Return fallback values\n\t\t\treturn {\n\t\t\t\ttitle: `${userPrompt} - Dashboard`,\n\t\t\t\tdescription: `Multi-component dashboard showing ${visualizationTypes.join(', ')}`\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Match component from a list with enhanced props modification\n\t */\n\tasync matchComponent(\n\t\tuserPrompt: string,\n\t\tcomponents: Component[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<{\n\t\tcomponent: Component | null;\n\t\treasoning: string;\n\t\tqueryModified?: boolean;\n\t\tqueryReasoning?: string;\n\t\tpropsModified?: boolean;\n\t\tpropsModifications?: string[];\n\t\tmethod: string;\n\t\tconfidence?: number;\n\t}> {\n\t\ttry {\n\t\t\t// Step 1: Enhanced component matching with scoring and multiple candidates\n\t\t\tconst componentsText = components\n\t\t\t\t.map((comp, idx) => {\n\t\t\t\t\tconst keywords = comp.keywords ? comp.keywords.join(', ') : '';\n\t\t\t\t\tconst category = comp.category || 'general';\n\t\t\t\t\treturn `${idx + 1}. ID: ${comp.id}\n Name: ${comp.name}\n Type: ${comp.type}\n Category: ${category}\n Description: ${comp.description || 'No description'}\n Keywords: ${keywords}`;\n\t\t\t\t})\n\t\t\t\t.join('\\n\\n');\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('match-component', {\n\t\t\t\tCOMPONENTS_TEXT: componentsText,\n\t\t\t\tUSER_PROMPT: userPrompt,\n\t\t\t\tCONVERSATION_HISTORY: conversationHistory || 'No previous conversation'\n\t\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: 800,\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\tconst componentIndex = result.componentIndex;\n\t\t\tconst componentId = result.componentId;\n\t\t\tconst confidence = result.confidence || 0;\n\n\t\t\t// Prefer componentId over componentIndex for accuracy\n\t\t\tlet component = null;\n\t\t\tif (componentId) {\n\t\t\t\tcomponent = components.find(c => c.id === componentId);\n\t\t\t}\n\n\t\t\t// Fallback to componentIndex if ID not found\n\t\t\tif (!component && componentIndex) {\n\t\t\t\tcomponent = components[componentIndex - 1];\n\t\t\t}\n\n\t\t\tconst matchedMsg = `${this.getProviderName()} matched component: ${component?.name || 'None'}`;\n\t\t\tlogger.info(`[${this.getProviderName()}] ✓ ${matchedMsg}`);\n\t\t\tlogCollector?.info(matchedMsg);\n\n\t\t\tif (result.alternativeMatches && result.alternativeMatches.length > 0) {\n\t\t\t\tlogger.debug(`[${this.getProviderName()}] Alternative matches found: ${result.alternativeMatches.length}`);\n\t\t\t\tconst altMatches = result.alternativeMatches.map((alt: any) =>\n\t\t\t\t\t`${components[alt.index - 1]?.name} (${alt.score}%): ${alt.reason}`\n\t\t\t\t).join(' | ');\n\t\t\t\tlogCollector?.info(`Alternative matches: ${altMatches}`);\n\t\t\t\tresult.alternativeMatches.forEach((alt: any) => {\n\t\t\t\t\tlogger.debug(`[${this.getProviderName()}] - ${components[alt.index - 1]?.name} (${alt.score}%): ${alt.reason}`);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!component) {\n\t\t\t\tconst noMatchMsg = `No matching component found (confidence: ${confidence}%)`;\n\t\t\t\tlogger.warn(`[${this.getProviderName()}] ✗ ${noMatchMsg}`);\n\t\t\t\tlogCollector?.warn(noMatchMsg);\n\t\t\t\tconst genMsg = 'Attempting to match component from analytical question...';\n\t\t\t\tlogger.info(`[${this.getProviderName()}] ✓ ${genMsg}`);\n\t\t\t\tlogCollector?.info(genMsg);\n\n\t\t\t\t// Try to match a component for the analytical question\n\t\t\t\tconst generatedResult = await this.generateAnalyticalComponent(userPrompt, components, undefined, apiKey, logCollector, conversationHistory);\n\n\t\t\t\tif (generatedResult.component) {\n\t\t\t\t\tconst genSuccessMsg = `Successfully matched component: ${generatedResult.component.name}`;\n\t\t\t\t\tlogCollector?.info(genSuccessMsg);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcomponent: generatedResult.component,\n\t\t\t\t\t\treasoning: generatedResult.reasoning,\n\t\t\t\t\t\tmethod: `${this.getProviderName()}-generated`,\n\t\t\t\t\t\tconfidence: 100, // Generated components are considered 100% match to the question\n\t\t\t\t\t\tpropsModified: false,\n\t\t\t\t\t\tqueryModified: false\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// If matching also failed, return null\n\t\t\t\tlogCollector?.error('Failed to match component');\n\t\t\t\treturn {\n\t\t\t\t\tcomponent: null,\n\t\t\t\t\treasoning: result.reasoning || 'No matching component found and unable to match component',\n\t\t\t\t\tmethod: `${this.getProviderName()}-llm`,\n\t\t\t\t\tconfidence\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Step 2: Validate and modify the entire props object based on user request\n\t\t\tlet propsModified = false;\n\t\t\tlet propsModifications: string[] = [];\n\t\t\tlet queryModified = false;\n\t\t\tlet queryReasoning = '';\n\n\t\t\tif (component && component.props) {\n\n\t\t\t\tconst propsValidation = await this.validateAndModifyProps(\n\t\t\t\t\tuserPrompt,\n\t\t\t\t\tcomponent.props,\n\t\t\t\t\tcomponent.name,\n\t\t\t\t\tcomponent.type,\n\t\t\t\t\tcomponent.description,\n\t\t\t\t\tapiKey,\n\t\t\t\t\tlogCollector,\n\t\t\t\t\tconversationHistory\n\t\t\t\t);\n\n\t\t\t\t// Create a new component object with the modified props\n\t\t\t\tconst originalQuery = component.props.query;\n\t\t\t\tconst modifiedQuery = propsValidation.props.query;\n\n\t\t\t\tcomponent = {\n\t\t\t\t\t...component,\n\t\t\t\t\tprops: propsValidation.props\n\t\t\t\t};\n\n\t\t\t\tpropsModified = propsValidation.isModified;\n\t\t\t\tpropsModifications = propsValidation.modifications;\n\t\t\t\tqueryModified = originalQuery !== modifiedQuery;\n\t\t\t\tqueryReasoning = propsValidation.reasoning;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcomponent,\n\t\t\t\treasoning: result.reasoning || 'No reasoning provided',\n\t\t\t\tqueryModified,\n\t\t\t\tqueryReasoning,\n\t\t\t\tpropsModified,\n\t\t\t\tpropsModifications,\n\t\t\t\tmethod: `${this.getProviderName()}-llm`,\n\t\t\t\tconfidence\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 component: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Component matching error details:`, error);\n\t\t\tlogCollector?.error(`Error matching component: ${errorMsg}`);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Match multiple components for analytical questions by visualization types\n\t * This is used when the user needs multiple visualizations\n\t */\n\tasync generateMultipleAnalyticalComponents(\n\t\tuserPrompt: string,\n\t\tavailableComponents: Component[],\n\t\tvisualizationTypes: string[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<{\n\t\tcomponents: Component[];\n\t\treasoning: string;\n\t\tisGenerated: boolean;\n\t}> {\n\t\ttry {\n\t\t\tconsole.log('✓ Matching multiple components:', visualizationTypes);\n\n\t\t\tconst components: Component[] = [];\n\n\t\t\t// Match each component type requested\n\t\t\tfor (const vizType of visualizationTypes) {\n\t\t\t\tconst result = await this.generateAnalyticalComponent(userPrompt, availableComponents, vizType, apiKey, logCollector, conversationHistory);\n\n\t\t\t\tif (result.component) {\n\t\t\t\t\tcomponents.push(result.component);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (components.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcomponents: [],\n\t\t\t\t\treasoning: 'Failed to match any components',\n\t\t\t\t\tisGenerated: false\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcomponents,\n\t\t\t\treasoning: `Matched ${components.length} components: ${visualizationTypes.join(', ')}`,\n\t\t\t\tisGenerated: true\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 multiple analytical components: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Multiple components matching error details:`, error);\n\t\t\treturn {\n\t\t\t\tcomponents: [],\n\t\t\t\treasoning: 'Error occurred while matching components',\n\t\t\t\tisGenerated: false\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Match multiple components and wrap them in a container\n\t */\n\tasync generateMultiComponentResponse(\n\t\tuserPrompt: string,\n\t\tavailableComponents: Component[],\n\t\tvisualizationTypes: string[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<{\n\t\tcontainerComponent: Component | null;\n\t\treasoning: string;\n\t\tisGenerated: boolean;\n\t}> {\n\t\ttry {\n\t\t\t// Match multiple components for each visualization type\n\t\t\tconst matchResult = await this.generateMultipleAnalyticalComponents(\n\t\t\t\tuserPrompt,\n\t\t\t\tavailableComponents,\n\t\t\t\tvisualizationTypes,\n\t\t\t\tapiKey,\n\t\t\t\tlogCollector,\n\t\t\t\tconversationHistory\n\t\t\t);\n\n\t\t\tif (!matchResult.isGenerated || matchResult.components.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcontainerComponent: null,\n\t\t\t\t\treasoning: matchResult.reasoning || 'Unable to match multi-component dashboard',\n\t\t\t\t\tisGenerated: false\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst generatedComponents = matchResult.components;\n\n\t\t\t// Log each generated component's query\n\t\t\tgeneratedComponents.forEach((component, index) => {\n\t\t\t\tif (component.props.query) {\n\t\t\t\t\tlogCollector?.logQuery(\n\t\t\t\t\t\t`Multi-component query generated (${index + 1}/${generatedComponents.length})`,\n\t\t\t\t\t\tcomponent.props.query,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcomponentType: component.type,\n\t\t\t\t\t\t\ttitle: component.props.title,\n\t\t\t\t\t\t\tposition: index + 1,\n\t\t\t\t\t\t\ttotalComponents: generatedComponents.length\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// Generate container title and description\n\t\t\tconst containerTitle = `${userPrompt} - Dashboard`;\n\t\t\tconst containerDescription = `Multi-component dashboard showing ${visualizationTypes.join(', ')}`;\n\n\t\t\t// Log the overall explanation for the multi-component dashboard\n\t\t\tlogCollector?.logExplanation(\n\t\t\t\t'Multi-component dashboard matched',\n\t\t\t\tmatchResult.reasoning || `Matched ${generatedComponents.length} components for comprehensive analysis`,\n\t\t\t\t{\n\t\t\t\t\ttotalComponents: generatedComponents.length,\n\t\t\t\t\tcomponentTypes: generatedComponents.map(c => c.type),\n\t\t\t\t\tcomponentNames: generatedComponents.map(c => c.name),\n\t\t\t\t\tcontainerTitle,\n\t\t\t\t\tcontainerDescription\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t// Create the MultiComponentContainer wrapper\n\t\t\tconst containerComponent: Component = {\n\t\t\t\tid: `multi_container_${Date.now()}`,\n\t\t\t\tname: 'MultiComponentContainer',\n\t\t\t\ttype: 'Container',\n\t\t\t\tdescription: containerDescription,\n\t\t\t\tcategory: 'dynamic',\n\t\t\t\tkeywords: ['multi', 'container', 'dashboard'],\n\t\t\t\tprops: {\n\t\t\t\t\tconfig: {\n\t\t\t\t\t\tcomponents: generatedComponents,\n\t\t\t\t\t\tlayout: 'grid',\n\t\t\t\t\t\tspacing: 24,\n\t\t\t\t\t\ttitle: containerTitle,\n\t\t\t\t\t\tdescription: containerDescription\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tcontainerComponent,\n\t\t\t\treasoning: matchResult.reasoning || `Matched multi-component dashboard with ${generatedComponents.length} components`,\n\t\t\t\tisGenerated: true\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 multi-component response: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Multi-component response error details:`, error);\n\t\t\tthrow error;\n\t\t}\n\t}\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 textResponse - 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 * @returns Object containing matched components, layout title/description, and follow-up actions\n\t */\n\tasync matchComponentsFromTextResponse(\n\t\ttextResponse: string,\n\t\tcomponents: Component[],\n\t\tapiKey?: string,\n\t\tlogCollector?: 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// Get schema documentation for query generation\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\n\n\t\t\tconst prompts = await promptLoader.loadPrompts('match-text-components', {\n\t\t\t\tTEXT_RESPONSE: textResponse,\n\t\t\t\tAVAILABLE_COMPONENTS: availableComponentsText,\n\t\t\t\tSCHEMA_DOC: schemaDoc\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// Let LLM.stream handle JSON parsing automatically\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\tlogger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);\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\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 matched components\n\t\t\tif (matchedComponents.length > 0) {\n\t\t\t\tlogCollector?.info(`Matched ${matchedComponents.length} components for visualization`);\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 * 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 */\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): 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// Get schema documentation\n\t\t\tconst schemaDoc = schema.generateSchemaDocumentation();\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\t// const knowledgeBaseContext = ''\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\tKNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || 'No additional knowledge base context available.'\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 the execute_query tool\n\t\t\tconst tools = [{\n\t\t\t\tname: 'execute_query',\n\t\t\t\tdescription: 'Executes a SQL query against the database and returns the results. Use this when the user asks for data. If the query fails, you will receive the error and can retry with a corrected query.',\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\tquery: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: 'The SQL query to execute. Must be valid SQL syntax using table and column names from the schema.'\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: ['query']\n\t\t\t\t}\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\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 query = toolInput.query;\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\tquery = ensureQueryLimit(query, 32, 32);\n\n\t\t\t\t\t// Track attempts for this query pattern (normalized)\n\t\t\t\t\tconst queryKey = query.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}): ${query.substring(0, 100)}...`);\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\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${query}\\n\\`\\`\\`\\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${query}\\n\\`\\`\\`\\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\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\tquery,\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\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\tconst result = await collections['database']['execute']({ sql: query });\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// 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}\n\n\t\t\t\tthrow new Error(`Unknown tool: ${toolName}`);\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// - 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\t10 // max iterations: allows for 6 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\n\t\t\tif (wrappedStreamCallback && components && components.length > 0) {\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\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 (components && components.length > 0) {\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Matching components from text response...`);\n\t\t\t\tconst matchResult = await this.matchComponentsFromTextResponse(\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);\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\tcontainer_componet = {\n\t\t\t\t\tid: `multi_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\tcategory: 'dynamic',\n\t\t\t\t\tkeywords: ['dashboard', 'layout', 'container'],\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tconfig: {\n\t\t\t\t\t\t\tcomponents: matchedComponents,\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},\n\t\t\t\t\t\tactions: actions\n\t\t\t\t\t}\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\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\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\t/**\n\t * Generate component response for user question\n\t * This provides conversational component suggestions based on user question\n\t * Supports component generation and matching\n\t */\n\tasync generateComponentResponse(\n\t\tuserPrompt: string,\n\t\tcomponents: Component[],\n\t\tapiKey?: string,\n\t\tlogCollector?: any,\n\t\tconversationHistory?: string\n\t): Promise<T_RESPONSE> {\n\t\tconst errors: string[] = [];\n\n\t\ttry {\n\t\t\t// Component mode (default) - existing flow\n\t\t\tlogger.info(`[${this.getProviderName()}] Using component response mode`);\n\n\t\t\t// Step 1: Classify the user's question\n\t\t\tconst classifyMsg = 'Classifying user question...';\n\t\t\tlogCollector?.info(classifyMsg);\n\t\t\tconst classification = await this.classifyUserQuestion(userPrompt, apiKey, logCollector, conversationHistory);\n\t\t\tconst classInfo = `Question type: ${classification.questionType}, Visualizations: ${classification.visualizations.join(', ') || 'None'}, Multiple components: ${classification.needsMultipleComponents}`;\n\t\t\tlogCollector?.info(classInfo);\n\n\t\t// Step 2: Route based on question type\n\t\tif (classification.questionType === 'analytical') {\n\t\t\t// For analytical questions with specific visualization types\n\t\t\tif (classification.visualizations.length > 1) {\n\t\t\t\t// Multiple visualization types - match component for each type\n\t\t\t\tconst multiMsg = `Matching ${classification.visualizations.length} components for types: ${classification.visualizations.join(', ')}`;\n\t\t\t\tlogCollector?.info(multiMsg);\n\n\t\t\t\t// Generate all components in parallel using Promise.allSettled\n\t\t\t\tconst componentPromises = classification.visualizations.map(vizType => {\n\t\t\t\t\tlogCollector?.info(`Matching component for type: ${vizType}`);\n\t\t\t\t\treturn this.generateAnalyticalComponent(\n\t\t\t\t\t\tuserPrompt,\n\t\t\t\t\t\tcomponents,\n\t\t\t\t\t\tvizType,\n\t\t\t\t\t\tapiKey,\n\t\t\t\t\t\tlogCollector,\n\t\t\t\t\t\tconversationHistory\n\t\t\t\t\t).then(result => ({ vizType, result }));\n\t\t\t\t});\n\n\t\t\t\tconst settledResults = await Promise.allSettled(componentPromises);\n\n\t\t\t\t// Extract successfully matched components, skip failed ones\n\t\t\t\tconst matchedComponents: Component[] = [];\n\t\t\t\tfor (const settledResult of settledResults) {\n\t\t\t\t\tif (settledResult.status === 'fulfilled') {\n\t\t\t\t\t\tconst { vizType, result } = settledResult.value;\n\t\t\t\t\t\tif (result.component) {\n\t\t\t\t\t\t\tmatchedComponents.push(result.component);\n\t\t\t\t\t\t\tlogCollector?.info(`Matched: ${result.component.name}`);\n\t\t\t\t\t\t\tlogger.info('Component : ', result.component.name,' props: ', result.component.props);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogCollector?.warn(`Failed to match component for type: ${vizType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Promise rejected - log the error and continue\n\t\t\t\t\t\tlogCollector?.warn(`Error matching component: ${settledResult.reason?.message || 'Unknown error'}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlogger.debug(`[${this.getProviderName()}] Matched ${matchedComponents.length} components for multi-component container`);\n\n\t\t\t\tif (matchedComponents.length === 0) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tcomponent: null,\n\t\t\t\t\t\t\treasoning: 'Failed to match any components for the requested visualization types',\n\t\t\t\t\t\t\tmethod: 'classification-multi-failed',\n\t\t\t\t\t\t\tquestionType: classification.questionType,\n\t\t\t\t\t\t\tneedsMultipleComponents: true,\n\t\t\t\t\t\t\tpropsModified: false,\n\t\t\t\t\t\t\tqueryModified: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\terrors: []\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Generate container metadata from user request\n\t\t\t\tlogCollector?.info('Generating container metadata...');\n\t\t\t\t\n\t\t\t\tconst containerMetadata = await this.generateContainerMetadata(\n\t\t\t\t\tuserPrompt,\n\t\t\t\t\tclassification.visualizations,\n\t\t\t\t\tapiKey,\n\t\t\t\t\tlogCollector,\n\t\t\t\t\tconversationHistory\n\t\t\t\t);\n\n\n\n\t\t\t\tconst containerComponent: Component = {\n\t\t\t\t\tid: `multi_container_${Date.now()}`,\n\t\t\t\t\tname: 'MultiComponentContainer',\n\t\t\t\t\ttype: 'Container',\n\t\t\t\t\tdescription: containerMetadata.description,\n\t\t\t\t\tcategory: 'dynamic',\n\t\t\t\t\tkeywords: ['multi', 'container', 'dashboard'],\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tconfig: {\n\t\t\t\t\t\t\tcomponents: matchedComponents,\n\t\t\t\t\t\t\tlayout: 'grid',\n\t\t\t\t\t\t\tspacing: 24,\n\t\t\t\t\t\t\ttitle: containerMetadata.title,\n\t\t\t\t\t\t\tdescription: containerMetadata.description\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tlogCollector?.info(`Created multi-component container with ${matchedComponents.length} components: \"${containerMetadata.title}\"`);\n\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcomponent: containerComponent,\n\t\t\t\t\t\treasoning: `Matched ${matchedComponents.length} components for visualization types: ${classification.visualizations.join(', ')}`,\n\t\t\t\t\t\tmethod: 'classification-multi-generated',\n\t\t\t\t\t\tquestionType: classification.questionType,\n\t\t\t\t\t\tneedsMultipleComponents: true,\n\t\t\t\t\t\tpropsModified: false,\n\t\t\t\t\t\tqueryModified: false\n\t\t\t\t\t},\n\t\t\t\t\terrors: []\n\t\t\t\t};\n\t\t\t} else if (classification.visualizations.length === 1) {\n\t\t\t\t// Single visualization type - match one component\n\t\t\t\tconst vizType = classification.visualizations[0];\n\t\t\t\tlogCollector?.info(`Matching single component for type: ${vizType}`);\n\t\t\t\tconst result = await this.generateAnalyticalComponent(userPrompt, components, vizType, apiKey, logCollector, conversationHistory);\n\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcomponent: result.component,\n\t\t\t\t\t\treasoning: result.reasoning,\n\t\t\t\t\t\tmethod: 'classification-generated',\n\t\t\t\t\t\tquestionType: classification.questionType,\n\t\t\t\t\t\tneedsMultipleComponents: false,\n\t\t\t\t\t\tpropsModified: false,\n\t\t\t\t\t\tqueryModified: false\n\t\t\t\t\t},\n\t\t\t\t\terrors: []\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\t// No specific visualization type, match from all components\n\t\t\t\tlogCollector?.info('No specific visualization type - matching from all components');\n\t\t\t\tconst result = await this.generateAnalyticalComponent(userPrompt, components, undefined, apiKey, logCollector, conversationHistory);\n\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcomponent: result.component,\n\t\t\t\t\t\treasoning: result.reasoning,\n\t\t\t\t\t\tmethod: 'classification-generated-auto',\n\t\t\t\t\t\tquestionType: classification.questionType,\n\t\t\t\t\t\tneedsMultipleComponents: false,\n\t\t\t\t\t\tpropsModified: false,\n\t\t\t\t\t\tqueryModified: false\n\t\t\t\t\t},\n\t\t\t\t\terrors: []\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (classification.questionType === 'data_modification' || classification.questionType === 'general') {\n\t\t\t// For data modification, use the old component matching flow\n\t\t\tconst matchMsg = 'Using component matching for data modification...';\n\t\t\tlogCollector?.info(matchMsg);\n\t\t\tconst matchResult = await this.matchComponent(userPrompt, components, apiKey, logCollector, conversationHistory);\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tcomponent: matchResult.component,\n\t\t\t\t\treasoning: matchResult.reasoning,\n\t\t\t\t\tmethod: 'classification-matched',\n\t\t\t\t\tquestionType: classification.questionType,\n\t\t\t\t\tneedsMultipleComponents: false,\n\t\t\t\t\tpropsModified: matchResult.propsModified,\n\t\t\t\t\tqueryModified: matchResult.queryModified\n\t\t\t\t},\n\t\t\t\terrors: []\n\t\t\t};\n\t\t} else {\n\t\t\tlogCollector?.info('General question - no component needed');\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tcomponent: null,\n\t\t\t\t\treasoning: 'General question - no component needed',\n\t\t\t\t\tmethod: 'classification-general',\n\t\t\t\t\tquestionType: classification.questionType,\n\t\t\t\t\tneedsMultipleComponents: false,\n\t\t\t\t\tpropsModified: false,\n\t\t\t\t\tqueryModified: false\n\t\t\t\t},\n\t\t\t\terrors: []\n\t\t\t};\n\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 component response: ${errorMsg}`);\n\t\t\tlogger.debug(`[${this.getProviderName()}] Component response generation error details:`, error);\n\t\t\tlogCollector?.error(`Error generating component response: ${errorMsg}`);\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: undefined\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Main orchestration function that classifies question and routes to appropriate handler\n\t * This is the NEW recommended entry point for handling user requests\n\t * Supports both component generation and text response modes\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 */\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' = 'component',\n\t\tstreamCallback?: (chunk: string) => void,\n\t\tcollections?: any\n\t): Promise<T_RESPONSE> {\n\t\tconst startTime = Date.now();\n\t\tlogger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);\n\n\t\t// If text response mode is requested, skip classification and generate text response\n\t\tif (responseMode === 'text') {\n\t\t\tlogger.info(`[${this.getProviderName()}] Using text response mode`);\n\t\t\tlogCollector?.info('Generating text response...');\n\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);\n\n\t\t\t// If text response generation failed, return the error\n\t\t\tif (!textResponse.success) {\n\t\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\t\tlogger.error(`[${this.getProviderName()}] Text response generation failed`);\n\t\t\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\t\t\treturn textResponse;\n\t\t\t}\n\n\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\tlogger.info(`[${this.getProviderName()}] Text response generated successfully`);\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 textResponse\n\t\t}\n\n\t\tconst componentResponse = await this.generateComponentResponse(\n\t\t\tuserPrompt,\n\t\t\tcomponents,\n\t\t\tapiKey,\n\t\t\tlogCollector,\n\t\t\tconversationHistory\n\t\t);\n\n\t\t// If component response generation failed, return the error\n\t\tif (!componentResponse.success) {\n\t\t\tconst elapsedTime = Date.now() - startTime;\n\t\t\tlogger.error(`[${this.getProviderName()}] Component response generation failed`);\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 componentResponse;\n\t\t}\n\n\t\tconst elapsedTime = Date.now() - startTime;\n\t\tlogger.info(`[${this.getProviderName()}] Component response generated successfully`);\n\t\tlogger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\t\tlogCollector?.info(`Total time taken: ${elapsedTime}ms (${(elapsedTime / 1000).toFixed(2)}s)`);\n\n\t\treturn componentResponse\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\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: 800,\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 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 isInitialized: boolean = false;\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 * @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\n\t */\n\tasync loadPrompts(\n\t\tpromptName: string,\n\t\tvariables: Record<string, string | number | boolean | any[]>\n\t): Promise<{ system: string; 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\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> {\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\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","/**\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\t'classify': {\n\t\tsystem: `You are an expert AI that classifies user questions about data and determines the appropriate visualizations needed.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n**Note:** If there is previous conversation history, use it to understand context. For example:\n- If user previously asked about \"sales\" and now asks \"show me trends\", understand it refers to sales trends\n- If user asked for \"revenue by region\" and now says \"make it a pie chart\", understand they want to modify the previous visualization\n- Use the history to resolve ambiguous references like \"that\", \"it\", \"them\", \"the data\"\n\nYour task is to analyze the user's question and determine:\n\n1. **Question Type:**\n - \"analytical\": Questions asking to VIEW, ANALYZE, or VISUALIZE data\n\n - \"data_modification\": Questions asking to CREATE, UPDATE, DELETE, or MODIFY data\n\n - \"general\": General questions, greetings, or requests not related to data\n\n2. **Required Visualizations** (only for analytical questions):\n Determine which visualization type(s) would BEST answer the user's question:\n\n - **KPICard**: Single metric, total, count, average, percentage, or summary number\n\n - **LineChart**: Trends over time, time series, growth/decline patterns\n\n\n - **BarChart**: Comparing categories, rankings, distributions across groups\n\n\n - **PieChart**: Proportions, percentages, composition, market share\n\n\n - **DataTable**: Detailed lists, multiple attributes, when user needs to see records\n\n\n3. **Multiple Visualizations:**\n User may need MULTIPLE visualizations together:\n\n Common combinations:\n - KPICard + LineChart\n - KPICard + BarChart\n - KPICard + DataTable\n - BarChart + PieChart:\n - LineChart + DataTable\n Set needsMultipleComponents to true if user needs multiple views of the data.\n\n**Important Guidelines:**\n- If user explicitly mentions a chart type RESPECT that preference\n- If question is vague or needs both summary and detail, suggest KPICard + DataTable\n- Only return visualizations for \"analytical\" questions\n- For \"data_modification\" or \"general\", return empty array for visualizations\n\n**Output Format:**\n{\n \"questionType\": \"analytical\" | \"data_modification\" | \"general\",\n \"visualizations\": [\"KPICard\", \"LineChart\", ...], // Empty array if not analytical\n \"reasoning\": \"Explanation of classification and visualization choices\",\n \"needsMultipleComponents\": boolean\n}\n`,\n\t\tuser: `{{USER_PROMPT}}\n`\n\t},\n\n\t'match-component': {\n\t\tsystem: `You are an expert AI assistant specialized in matching user requests to the most appropriate data visualization components.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n**Context Instructions:**\n- If there is conversation history, use it to understand what the user is referring to\n- When user says \"show that as a chart\" or \"change it\", they are referring to a previous component\n- If user asks to \"modify\" or \"update\" something, match to the component they previously saw\n- Use context to resolve ambiguous requests like \"show trends for that\" or \"make it interactive\"\n\nYour task is to analyze the user's natural language request and find the BEST matching component from the available list.\n\nAvailable Components:\n{{COMPONENTS_TEXT}}\n\n**Matching Guidelines:**\n\n1. **Understand User Intent:**\n - What type of data visualization do they need? (KPI/metric, chart, table, etc.)\n - What metric or data are they asking about? (revenue, orders, customers, etc.)\n - Are they asking for a summary (KPI), trend (line chart), distribution (bar/pie), or detailed list (table)?\n - Do they want to compare categories, see trends over time, or show proportions?\n\n2. **Component Type Matching:**\n - KPICard: Single metric/number (total, average, count, percentage, rate)\n - LineChart: Trends over time, time series data\n - BarChart: Comparing categories, distributions, rankings\n - PieChart/DonutChart: Proportions, percentages, market share\n - DataTable: Detailed lists, rankings with multiple attributes\n\n3. **Keyword & Semantic Matching:**\n - Match user query terms with component keywords\n - Consider synonyms (e.g., \"sales\" = \"revenue\", \"items\" = \"products\")\n - Look for category matches (financial, orders, customers, products, suppliers, logistics, geographic, operations)\n\n4. **Scoring Criteria:**\n - Exact keyword matches: High priority\n - Component type alignment: High priority\n - Category alignment: Medium priority\n - Semantic similarity: Medium priority\n - Specificity: Prefer more specific components over generic ones\n\n**Output Requirements:**\n\nRespond with a JSON object containing:\n- componentIndex: the 1-based index of the BEST matching component (or null if confidence < 50%)\n- componentId: the ID of the matched component\n- reasoning: detailed explanation of why this component was chosen\n- confidence: confidence score 0-100 (100 = perfect match)\n- alternativeMatches: array of up to 2 alternative component indices with scores (optional)\n\nExample response:\n{\n \"componentIndex\": 5,\n \"componentId\": \"total_revenue_kpi\",\n \"reasoning\": \"User asks for 'total revenue' which perfectly matches the TotalRevenueKPI component (KPICard type) designed to show total revenue across all orders. Keywords match: 'total revenue', 'sales'.\",\n \"confidence\": 95,\n \"alternativeMatches\": [\n {\"index\": 3, \"id\": \"monthly_revenue_kpi\", \"score\": 75, \"reason\": \"Could show monthly revenue if time period was intended\"},\n {\"index\": 8, \"id\": \"revenue_trend_chart\", \"score\": 60, \"reason\": \"Could show revenue trend if historical view was intended\"}\n ]\n}\n\n**Important:**\n- Only return componentIndex if confidence >= 50%\n- Return null if no reasonable match exists\n- Prefer components that exactly match the user's metric over generic ones\n- Consider the full context of the request, not just individual words`,\n\t\tuser: `Current user request: {{USER_PROMPT}}\n\nFind the best matching component considering the conversation history above. Explain your reasoning with a confidence score. Return ONLY valid JSON.`\n\t},\n\n\t'modify-props': {\n\t\tsystem: `You are an AI assistant that validates and modifies component props based on user requests.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\nGiven:\n- A user's natural language request\n- Component name: {{COMPONENT_NAME}}\n- Component type: {{COMPONENT_TYPE}}\n- Component description: {{COMPONENT_DESCRIPTION}}\n\n-\n- Current component props with structure:\n {\n query?: string, // SQL query to fetch data\n title?: string, // Component title\n description?: string, // Component description\n config?: { // Additional configuration\n [key: string]: any\n }\n }\n\n Schema definition for the prop that must be passed to the component\n -{{CURRENT_PROPS}}\n\nDatabase Schema:\n{{SCHEMA_DOC}}\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n**Context Instructions:**\n- Review the conversation history to understand the evolution of the component\n- If user says \"add filter for X\", understand they want to modify the current query\n- If user says \"change to last month\" or \"filter by Y\", apply modifications to existing query\n- Previous questions can clarify what the user means by ambiguous requests like \"change that filter\"\n- Use context to determine appropriate time ranges if user says \"recent\" or \"latest\"\n\nYour task is to intelligently modify the props based on the user's request:\n\n1. **Query Modification**:\n - Modify SQL query if user requests different data, filters, time ranges, limits, or aggregations\n - Use correct table and column names from the schema\n - Ensure valid SQL syntax\n - ALWAYS include a LIMIT clause (default: {{DEFAULT_LIMIT}} rows) to prevent large result sets\n - Preserve the query structure that the component expects (e.g., column aliases)\n\n **CRITICAL - PostgreSQL Query Rules:**\n\n **NO AGGREGATE FUNCTIONS IN WHERE CLAUSE:**\n ❌ WRONG: \\`WHERE COUNT(orders) > 0\\` or \\`WHERE SUM(price) > 100\\`\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\n\n\n **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\n **Subquery Rules:**\n - When using a subquery with scalar comparison operators (=, <, >, <=, >=, <>), the subquery MUST return exactly ONE row\n - ALWAYS add \\`LIMIT 1\\` to scalar subqueries to prevent \"more than one row returned\" errors\n - Example: \\`WHERE location_id = (SELECT store_id FROM orders ORDER BY total_amount DESC LIMIT 1)\\`\n - For multiple values, use \\`IN\\` instead: \\`WHERE location_id IN (SELECT store_id FROM orders)\\`\n - Test your subqueries mentally: if they could return multiple rows, add LIMIT 1 or use IN\n\n2. **Title Modification**:\n - Update title to reflect the user's specific request\n - Keep it concise and descriptive\n - Match the tone of the original title\n\n3. **Description Modification**:\n - Update description to explain what data is shown\n - Be specific about filters, time ranges, or groupings applied\n\n4. **Config Modification** (based on component type):\n - For KPICard: formatter, gradient, icon\n - For Charts: colors, height, xKey, yKey, nameKey, valueKey\n - For Tables: columns, pageSize, formatters\n\n\nRespond with a JSON object:\n{\n \"props\": { /* modified props object with query, title, description, config */ },\n \"isModified\": boolean,\n \"reasoning\": \"brief explanation of changes\",\n \"modifications\": [\"list of specific changes made\"]\n}\n\nIMPORTANT:\n- Return the COMPLETE props object, not just modified fields\n- Preserve the structure expected by the component type\n- Ensure query returns columns with expected aliases\n- Keep config properties that aren't affected by the request`,\n\t\tuser: `{{USER_PROMPT}}`\n\t},\n\n\t'single-component': {\n\t\tsystem: `You are an expert AI assistant specialized in matching user requests to the most appropriate component from a filtered list.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n**Context Instructions:**\n- If there is previous conversation history, use it to understand what the user is referring to\n- When user says \"show trends\", \"add filters\", \"change that\", understand they may be building on previous queries\n- Use previous component types and queries as context to inform your current matching\n\n## Available Components (Type: {{COMPONENT_TYPE}})\nThe following components have been filtered by type {{COMPONENT_TYPE}}. Select the BEST matching one:\n\n{{COMPONENTS_LIST}}\n\n{{VISUALIZATION_CONSTRAINT}}\n\n**Select the BEST matching component** from the available {{COMPONENT_TYPE}} components listed above that would best answer the user's question.\n\n**Matching Guidelines:**\n1. **Semantic Matching:**\n - Match based on component name, description, and keywords\n - Consider what metrics/data the user is asking about\n - Look for semantic similarity (e.g., \"sales\" matches \"revenue\", \"orders\" matches \"purchases\")\n\n2. **Query Relevance:**\n - Consider the component's existing query structure\n - Does it query the right tables/columns for the user's question?\n - Can it be modified to answer the user's specific question?\n\n3. **Scoring Criteria:**\n - Exact keyword matches in name/description: High priority\n - Semantic similarity to user intent: High priority\n - Appropriate aggregation/grouping: Medium priority\n - Category alignment: Medium priority\n\n**Output Requirements:**\n\nRespond with a JSON object:\n{\n \"componentId\": \"matched_component_id\",\n \"componentIndex\": 1, // 1-based index from the filtered list above\n \"reasoning\": \"Detailed explanation of why this component best matches the user's question\",\n \"confidence\": 85, // Confidence score 0-100\n \"canGenerate\": true // false if no suitable component found (confidence < 50)\n}\n\n**Important:**\n- Only set canGenerate to true if confidence >= 50%\n- If no component from the list matches well (all have low relevance), set canGenerate to false\n- Consider the full context of the request and conversation history\n- The component's props (query, title, description, config) will be modified later based on the user's specific request\n- Focus on finding the component that is closest to what the user needs, even if it needs modification`,\n\t\tuser: `{{USER_PROMPT}}\n\n`\n\t},\n\n\t'mutli-component': {\n\t\tsystem: `You are an expert data analyst AI that creates comprehensive multi-component analytical dashboards with aesthetically pleasing and balanced layouts.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\nDatabase Schema:\n{{SCHEMA_DOC}}\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n**Context Instructions:**\n- Review the conversation history to understand what the user has asked before\n- If user is building on previous insights (e.g., \"now show me X and Y\"), use context to inform dashboard design\n- Previous queries can help determine appropriate filters, date ranges, or categories to use\n- If user asks for \"comprehensive view\" or \"dashboard for X\", include complementary components based on context\n\nGiven a user's analytical question and the required visualization types, your task is to:\n\n1. **Determine Container Metadata:**\n - title: Clear, descriptive title for the entire dashboard (2-5 words)\n - description: Brief explanation of what insights this dashboard provides (1-2 sentences)\n\n2. **Generate Props for Each Component:**\n For each visualization type requested, create tailored props:\n\n - **query**: SQL query specific to this visualization using the database schema\n * Use correct table and column names\n * **DO NOT USE TOP keyword - use LIMIT instead (e.g., LIMIT 20, not TOP 20)**\n * ALWAYS include LIMIT clause ONCE at the end (default: {{DEFAULT_LIMIT}})\n * For KPICard: Return single row with column alias \"value\"\n * For Charts: Return appropriate columns (name/label and value, or x and y)\n * For Table: Return relevant columns\n\n - **title**: Specific title for this component (2-4 words)\n\n - **description**: What this specific component shows (1 sentence)\n\n - **config**: Type-specific configuration\n * KPICard: { gradient, formatter, icon }\n * BarChart: { xKey, yKey, colors, height }\n * LineChart: { xKey, yKeys, colors, height }\n * PieChart: { nameKey, valueKey, colors, height }\n * DataTable: { pageSize }\n\n3. **CRITICAL: Component Hierarchy and Ordering:**\n The ORDER of components in the array MUST follow this STRICT hierarchy for proper visual layout:\n\n **HIERARCHY RULES (MUST FOLLOW IN THIS ORDER):**\n 1. KPICards - ALWAYS FIRST (top of dashboard for summary metrics)\n 2. Charts/Graphs - AFTER KPICards (middle of dashboard for visualizations)\n * BarChart, LineChart, PieChart, DonutChart\n 3. DataTable - ALWAYS LAST (bottom of dashboard, full width for detailed data)\n\n **LAYOUT BEHAVIOR (Frontend enforces):**\n - KPICards: Display in responsive grid (3 columns)\n - Single Chart (if only 1 chart): Takes FULL WIDTH\n - Multiple Charts (if 2+ charts): Display in 2-column grid\n - DataTable (if present): Always spans FULL WIDTH at bottom\n\n\n **ABSOLUTELY DO NOT deviate from this hierarchy. Always place:**\n - KPICards first\n - Charts/Graphs second\n - DataTable last (if present)\n\n**Important Guidelines:**\n- Each component should answer a DIFFERENT aspect of the user's question\n- Queries should be complementary, not duplicated\n- If user asks \"Show total revenue and trend\", generate:\n * KPICard: Single total value (FIRST)\n * LineChart: Revenue over time (SECOND)\n- Ensure queries use valid columns from the schema\n- Make titles descriptive and specific to what each component shows\n- **Snowflake Syntax MUST be used:**\n * Use LIMIT (not TOP)\n * Use DATE_TRUNC, DATEDIFF (not DATEPART)\n * Include LIMIT only ONCE per query at the end\n\n**Output Format:**\n{\n \"containerTitle\": \"Dashboard Title\",\n \"containerDescription\": \"Brief description of the dashboard insights\",\n \"components\": [\n {\n \"componentType\": \"KPICard\" | \"BarChart\" | \"LineChart\" | \"PieChart\" | \"DataTable\",\n \"query\": \"SQL query\",\n \"title\": \"Component title\",\n \"description\": \"Component description\",\n \"config\": { /* type-specific config */ }\n },\n ...\n ],\n \"reasoning\": \"Explanation of the dashboard design and component ordering\",\n \"canGenerate\": boolean\n}`,\n\t\tuser: `Current user question: {{USER_PROMPT}}\n\nRequired visualization types: {{VISUALIZATION_TYPES}}\n\nGenerate a complete multi-component dashboard with appropriate container metadata and tailored props for each component. Consider the conversation history above when designing the dashboard. Return ONLY valid JSON.`\n\t},\n\n\t'container-metadata': {\n\t\tsystem: `You are an expert AI assistant that generates titles and descriptions for multi-component dashboards.\n\nCRITICAL: You MUST respond with ONLY valid JSON, no other text before or after.\n\n## Previous Conversation\n{{CONVERSATION_HISTORY}}\n\n**Context Instructions:**\n- If there is previous conversation history, use it to understand what the user is referring to\n- Use context to create relevant titles and descriptions that align with the user's intent\n\nYour task is to generate a concise title and description for a multi-component dashboard that will contain the following visualization types:\n{{VISUALIZATION_TYPES}}\n\n**Guidelines:**\n\n1. **Title:**\n - Should be clear and descriptive (3-8 words)\n - Should reflect what the user is asking about\n - Should NOT include \"Dashboard\" suffix (that will be added automatically)\n\n2. **Description:**\n - Should be a brief summary (1-2 sentences)\n - Should explain what insights the dashboard provides\n\n**Output Requirements:**\n\nRespond with a JSON object:\n{\n \"title\": \"Dashboard title without 'Dashboard' suffix\",\n \"description\": \"Brief description of what this dashboard shows\"\n}\n\n**Important:**\n- Keep the title concise and meaningful\n- Make the description informative but brief\n- Focus on what insights the user will gain\n`,\n\t\tuser: `{{USER_PROMPT}}\n`\n\t},\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.\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## 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## Response Guidelines\n\n- If the question is about data, use the execute_query tool to fetch data and present it\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## Component Suggestions\n\nAfter analyzing the query results, you MUST suggest appropriate dashboard components for displaying the data. Use this format:\n\n<DashboardComponents>\n**Dashboard Components:**\nFormat: \\`{number}.{component_type} : {clear reasoning}\\`\n\n\n**Rules for component suggestions:**\n1. Analyze the query results structure and data type\n2. Suggest components that would best visualize the data\n3. Each component suggestion must be on a new line\n</DashboardComponents>\n\nIMPORTANT: Always wrap component suggestions with <DashboardComponents> tags and include at least one component suggestion when data is returned.\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.\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\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\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\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`,\n\t\tuser: `{{USER_PROMPT}}\n\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. **Parse the component suggestions** from the text response (format: 1:component_type : reasoning)\n2. **Match each suggestion with an actual component** from the available list\n3. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched\n4. **Generate title and description** for the dashboard container\n5. **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- Use the database schema below to write valid SQL\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\n ✅ CORRECT: Use HAVING (with GROUP BY), EXISTS, or subquery\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\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\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## 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\\`\\`\\`json\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 this suggestion\",\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**CRITICAL:**\n- \\`matchedComponents\\` MUST include ALL components suggested in the text response\n- \\`layoutTitle\\` MUST be a clear, concise title (5-10 words) that summarizes what the entire dashboard shows\n - Examples: \"Sales Performance Overview\", \"Customer Metrics Analysis\", \"Product Category Breakdown\"\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 including query, title, description, and config\n\n\n`,\n\t\tuser: `## Text Response\n\n{{TEXT_RESPONSE}}\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","import Anthropic from \"@anthropic-ai/sdk\";\nimport Groq from \"groq-sdk\";\nimport { jsonrepair } from 'jsonrepair';\n\ninterface LLMMessages {\n sys: string;\n user: string;\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 {\n throw new Error(`Unsupported provider: ${provider}. Use \"anthropic\" or \"groq\"`);\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 {\n throw new Error(`Unsupported provider: ${provider}. Use \"anthropic\" or \"groq\"`);\n }\n }\n\n /* Stream response with tool calling support (Anthropic only for now) */\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 throw new Error(`Tool calling is only supported for Anthropic models`);\n }\n\n return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);\n }\n\n // ============================================================\n // PRIVATE HELPER METHODS\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 apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\n const client = new Anthropic({\n apiKey: apiKey,\n });\n\n const response = await client.messages.create({\n model: modelName,\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n system: messages.sys,\n messages: [{\n role: \"user\",\n content: messages.user\n }]\n });\n\n const textBlock = response.content.find(block => block.type === 'text');\n return textBlock?.type === 'text' ? textBlock.text : '';\n }\n\n private static async _anthropicStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || \"\";\n const client = new Anthropic({\n apiKey: apiKey,\n });\n\n const stream = await client.messages.create({\n model: modelName,\n max_tokens: options.maxTokens || 1000,\n temperature: options.temperature,\n system: messages.sys,\n messages: [{\n role: \"user\",\n content: messages.user\n }],\n stream: true,\n });\n\n let fullText = '';\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 }\n }\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\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 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\n while (iterations < maxIterations) {\n iterations++;\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: messages.sys,\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\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 }\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 }\n\n if (chunk.type === 'message_stop') {\n // Message complete\n break;\n }\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 (toolResults.content as any[]).push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: typeof result === 'string' ? result : JSON.stringify(result)\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 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 client = new Groq({\n apiKey: options.apiKey || process.env.GROQ_API_KEY || \"\",\n });\n\n const response = await client.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: messages.sys },\n { role: 'user', content: messages.user }\n ],\n temperature: options.temperature,\n max_tokens: options.maxTokens || 1000,\n });\n\n return response.choices[0]?.message?.content || '';\n }\n\n private static async _groqStream(\n messages: LLMMessages,\n modelName: string,\n options: LLMOptions,\n json?: boolean\n ): Promise<any> {\n const apiKey = options.apiKey || process.env.GROQ_API_KEY || \"\";\n const client = new Groq({\n apiKey: apiKey,\n });\n\n const stream = await client.chat.completions.create({\n model: modelName,\n messages: [\n { role: 'system', content: messages.sys },\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\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 }\n\n // Return parsed JSON or text\n if (json) {\n return this._parseJSON(fullText);\n }\n\n return fullText;\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 (jsonrepair expects JSON-like input)\n // Handle both objects {...} and arrays [...]\n const firstBrace = jsonText.indexOf('{');\n const firstBracket = jsonText.indexOf('[');\n const lastBrace = jsonText.lastIndexOf('}');\n const lastBracket = jsonText.lastIndexOf(']');\n\n // Determine if it's an object or array, and extract accordingly\n let startIdx = -1;\n let endIdx = -1;\n\n if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {\n // Object starts first\n startIdx = firstBrace;\n endIdx = lastBrace;\n } else if (firstBracket !== -1) {\n // Array starts first\n startIdx = firstBracket;\n endIdx = lastBracket;\n }\n\n if (startIdx !== -1 && endIdx !== -1 && startIdx < endIdx) {\n jsonText = jsonText.substring(startIdx, endIdx + 1);\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, throw a more informative error\n throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}\\n\\nOriginal text: ${jsonText.substring(0, 200)}...`);\n }\n }\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 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-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 { groqLLM } from \"./groq\";\nimport { anthropicLLM } from \"./anthropic\";\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', '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');\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): 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);\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): 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);\n logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);\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 */\nexport const get_user_response = async (\n prompt: string,\n components: Component[],\n anthropicApiKey?: string,\n groqApiKey?: string,\n llmProviders?: LLMProvider[],\n logCollector?: any,\n conversationHistory?: string,\n responseMode: 'component' | 'text' = 'component',\n streamCallback?: (chunk: string) => void,\n collections?: any\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);\n } else if (provider === 'groq') {\n result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);\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 { 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","/**\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, LLMProvider, Message, UserPromptRequestMessageSchema, T_RESPONSE } from \"../types\";\nimport { get_user_response } from \"../userResponse\";\nimport { logger } from \"../utils/logger\";\nimport { UILogCollector } from \"../utils/log-collector\";\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\tllmProviders?: LLMProvider[],\n\tcollections?: any\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\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\tlogger.info('conversationHistory', conversationHistory);\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, and collections\n\tconst userResponse = await get_user_response(\n\t\tprompt!,\n\t\tcomponents,\n\t\tanthropicApiKey,\n\t\tgroqApiKey,\n\t\tllmProviders,\n\t\tlogCollector,\n\t\tconversationHistory,\n\t\tresponseMode,\n\t\tstreamCallback,\n\t\tcollections\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\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\tif ('textResponse' in userResponse.data) {\n\t\t\t\ttextResponse = (userResponse.data as any).text;\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// 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\tllmProviders?: LLMProvider[],\n\tcollections?: any\n): Promise<void> {\n\tconst response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections);\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\tlogger.info('sending user prompt response', response);\n\tsendMessage(response);\n} ","import { Component, Message, UserPromptSuggestionsMessageSchema } from '../types';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle user prompt suggestions request\n * Searches components based on prompt keywords and returns top matches\n */\nexport async function handleUserPromptSuggestions(\n data: any,\n components: Component[],\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n const request = UserPromptSuggestionsMessageSchema.parse(data);\n const { id, payload, from } = request;\n\n const { prompt, limit = 5 } = payload;\n const wsId = from.id;\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 if (!components || components.length === 0) {\n sendResponse(id, {\n success: true,\n data: {\n prompt,\n suggestions: [],\n count: 0,\n message: 'No components available'\n }\n }, sendMessage, wsId);\n return;\n }\n\n // Search components based on prompt\n const suggestions = searchComponents(prompt, components, limit);\n\n\n sendResponse(id, {\n success: true,\n data: {\n prompt,\n suggestions,\n count: suggestions.length,\n message: `Found ${suggestions.length} matching components`\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, 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 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 // 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 { 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\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'];\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 {\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 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 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 } from \"../types\";\nimport { logger } from \"../utils/logger\";\n\n\nexport async function handleComponentListResponse(\n data: any,\n storeComponents:(components: Component[])=>void\n ): Promise<void> {\n try {\n const componentListResponse = ComponentListResponseMessageSchema.parse(data);\n const { id, 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 return;\n } catch (error) {\n logger.error('Failed to handle user prompt request:', error);\n }\n } \n\n\n","import { UsersRequestMessageSchema, Message } from '../types';\nimport { getUserManager } from '../auth/user-storage';\nimport { logger } from '../utils/logger';\n\n/**\n * Handle unified users management request\n * Supports operations: create, update, delete, getAll, getOne\n * Only accepts requests from 'admin' type\n */\nexport async function handleUsersRequest(\n data: any,\n sendMessage: (message: Message) => void\n): Promise<void> {\n try {\n const request = UsersRequestMessageSchema.parse(data);\n const { id, payload, from } = request;\n const { operation, data: requestData } = payload;\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\n // Verify request is from admin\n if (from.type !== 'admin') {\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 }, userManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, { username, email, password, fullname, role }, userManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, username, userManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, userManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, username, 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 */\nasync function handleCreate(\n id: string,\n userData: {\n username?: string;\n email?: string;\n password?: string;\n fullname?: string;\n role?: string;\n },\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { username, email, password, fullname, role } = 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 // 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 (wsIds will be managed in memory, not persisted to file)\n const newUser = userManager.createUser(newUserData);\n\n logger.info(`User created by admin: ${username}${email ? ` (${email})` : ''}`);\n\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`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle update user operation\n */\nasync function handleUpdate(\n id: string,\n userData: {\n username?: string;\n email?: string;\n password?: string;\n fullname?: string;\n role?: string;\n },\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const { username, email, password, fullname, role } = userData;\n\n // Validate input - username is required to identify which user to update\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 // 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 // Empty string means remove email\n updates.email = undefined;\n }\n }\n\n // Update password if provided\n if (password !== undefined && password.trim().length > 0) {\n updates.password = password.trim();\n }\n\n // Update fullname if provided\n if (fullname !== undefined) {\n updates.fullname = fullname.trim().length > 0 ? fullname.trim() : undefined;\n }\n\n // Update role if provided\n if (role !== undefined) {\n updates.role = role.trim().length > 0 ? role.trim() : undefined;\n }\n\n // If nothing to update, return error\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 // Update user\n const updatedUser = userManager.updateUser(username, updates);\n\n logger.info(`User updated by admin: ${username}`);\n\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`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle delete user operation\n */\nasync function handleDelete(\n id: string,\n username: string | undefined,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\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 // 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 // Delete user\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(`User deleted by admin: ${username}`);\n\n sendResponse(id, {\n success: true,\n data: {\n username: username,\n message: `User '${username}' deleted successfully`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all users operation\n */\nasync function handleGetAll(\n id: string,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\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(`Admin retrieved all users (count: ${sanitizedUsers.length})`);\n\n sendResponse(id, {\n success: true,\n data: {\n users: sanitizedUsers,\n count: sanitizedUsers.length,\n message: `Retrieved ${sanitizedUsers.length} users`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one user operation\n */\nasync function handleGetOne(\n id: string,\n username: string | undefined,\n userManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n // Validate input\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 // 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(`Admin retrieved user: ${username}`);\n\n sendResponse(id, {\n success: true,\n data: {\n user: sanitizedUser,\n message: `Retrieved user '${username}'`\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 } 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 */\nexport async function handleDashboardsRequest(\n data: any,\n sendMessage: (message: Message) => void\n): Promise<void> {\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\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, dashboardManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, dashboardId, dashboard, dashboardManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, dashboardId, dashboardManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, dashboardManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, dashboardId, 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 */\nasync function handleCreate(\n id: string,\n dashboardId: string | undefined,\n dashboard: 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 (!dashboard) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard data is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const createdDashboard = dashboardManager.createDashboard(dashboardId, dashboard);\n\n sendResponse(id, {\n success: true,\n data: {\n dashboardId,\n dashboard: createdDashboard,\n message: `Dashboard '${dashboardId}' created successfully`\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 */\nasync function handleUpdate(\n id: string,\n dashboardId: string | undefined,\n dashboard: 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 (!dashboard) {\n sendResponse(id, {\n success: false,\n error: 'Dashboard data is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const updatedDashboard = dashboardManager.updateDashboard(dashboardId, dashboard);\n\n if (!updatedDashboard) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${dashboardId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: true,\n data: {\n dashboardId,\n dashboard: updatedDashboard,\n message: `Dashboard '${dashboardId}' updated successfully`\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 */\nasync function handleDelete(\n id: string,\n dashboardId: string | undefined,\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 const deleted = dashboardManager.deleteDashboard(dashboardId);\n\n if (!deleted) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${dashboardId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: true,\n data: {\n dashboardId,\n message: `Dashboard '${dashboardId}' deleted successfully`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all dashboards operation\n */\nasync function handleGetAll(\n id: string,\n dashboardManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const dashboards = dashboardManager.getAllDashboards();\n\n logger.info(`Admin retrieved all dashboards (count: ${dashboards.length})`);\n\n sendResponse(id, {\n success: true,\n data: {\n dashboards,\n count: dashboards.length,\n message: `Retrieved ${dashboards.length} dashboards`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one dashboard operation\n */\nasync function handleGetOne(\n id: string,\n dashboardId: string | undefined,\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 const dashboard = dashboardManager.getDashboard(dashboardId);\n\n if (!dashboard) {\n sendResponse(id, {\n success: false,\n error: `Dashboard '${dashboardId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`Admin retrieved dashboard: ${dashboardId}`);\n\n sendResponse(id, {\n success: true,\n data: {\n dashboardId,\n dashboard,\n message: `Retrieved dashboard '${dashboardId}'`\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 } 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\n * Only accepts requests from 'admin' type\n */\nexport async function handleReportsRequest(\n data: any,\n sendMessage: (message: Message) => void\n): Promise<void> {\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\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, reportManager, sendMessage, from.id);\n break;\n\n case 'update':\n await handleUpdate(id, reportId, report, reportManager, sendMessage, from.id);\n break;\n\n case 'delete':\n await handleDelete(id, reportId, reportManager, sendMessage, from.id);\n break;\n\n case 'getAll':\n await handleGetAll(id, reportManager, sendMessage, from.id);\n break;\n\n case 'getOne':\n await handleGetOne(id, reportId, 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 */\nasync function handleCreate(\n id: string,\n reportId: string | undefined,\n report: 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 (!report) {\n sendResponse(id, {\n success: false,\n error: 'Report data is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const createdReport = reportManager.createReport(reportId, report);\n\n sendResponse(id, {\n success: true,\n data: {\n reportId,\n report: createdReport,\n message: `Report '${reportId}' created successfully`\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 */\nasync function handleUpdate(\n id: string,\n reportId: string | undefined,\n report: 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 (!report) {\n sendResponse(id, {\n success: false,\n error: 'Report data is required'\n }, sendMessage, clientId);\n return;\n }\n\n try {\n const updatedReport = reportManager.updateReport(reportId, report);\n\n if (!updatedReport) {\n sendResponse(id, {\n success: false,\n error: `Report '${reportId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: true,\n data: {\n reportId,\n report: updatedReport,\n message: `Report '${reportId}' updated successfully`\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 */\nasync function handleDelete(\n id: string,\n reportId: string | undefined,\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 const deleted = reportManager.deleteReport(reportId);\n\n if (!deleted) {\n sendResponse(id, {\n success: false,\n error: `Report '${reportId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n sendResponse(id, {\n success: true,\n data: {\n reportId,\n message: `Report '${reportId}' deleted successfully`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get all reports operation\n */\nasync function handleGetAll(\n id: string,\n reportManager: any,\n sendMessage: (message: Message) => void,\n clientId?: string\n): Promise<void> {\n const reports = reportManager.getAllReports();\n\n logger.info(`Admin retrieved all reports (count: ${reports.length})`);\n\n sendResponse(id, {\n success: true,\n data: {\n reports,\n count: reports.length,\n message: `Retrieved ${reports.length} reports`\n }\n }, sendMessage, clientId);\n}\n\n/**\n * Handle get one report operation\n */\nasync function handleGetOne(\n id: string,\n reportId: string | undefined,\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 const report = reportManager.getReport(reportId);\n\n if (!report) {\n sendResponse(id, {\n success: false,\n error: `Report '${reportId}' not found`\n }, sendMessage, clientId);\n return;\n }\n\n logger.info(`Admin retrieved report: ${reportId}`);\n\n sendResponse(id, {\n success: true,\n data: {\n reportId,\n report,\n message: `Retrieved report '${reportId}'`\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 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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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAwHR,MAAM;AAAA;AAAA;AAAA,EAGP;AAAA,EAEA,yBAAyB;AAAA,IACxB,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;AA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","names":["WebSocket","import_zod","import_zod","ExpressionSchema","BindingSchema","ForDirectiveSchema","QuerySpecSchema","UIElementSchema","UIComponentSchema","DSLRendererPropsSchema","DSLRendererPropsSchema","fs","size","import_crypto","result","fs","import_crypto","crypto","sendDataResponse","sendDataResponse","import_fs","path","fs","schema","import_fs","import_path","path","fs","Anthropic","Groq","ensureQueryLimit","result","elapsedTime","dotenv","import_dotenv","dotenv","import_dotenv","dotenv","LOG_LEVEL_PRIORITY","MESSAGE_LEVEL_PRIORITY","sendDataResponse","sendResponse","sendResponse","sendResponse","dashboardManager","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","sendResponse","reportManager","handleCreate","handleUpdate","handleDelete","handleGetAll","handleGetOne","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"]}
|