@superatomai/sdk-node 0.0.58 → 0.0.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -2097,7 +2097,7 @@ declare abstract class BaseLLM {
2097
2097
  * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
2098
2098
  * @returns Object containing matched components, layout title/description, and follow-up actions
2099
2099
  */
2100
- matchComponentsFromAnalysis(analysisContent: string, components: Component[], apiKey?: string, logCollector?: any, componentStreamCallback?: (component: Component) => void, deferredTools?: any[], executedTools?: any[]): Promise<{
2100
+ matchComponentsFromAnalysis(analysisContent: string, components: Component[], apiKey?: string, logCollector?: any, componentStreamCallback?: (component: Component) => void, deferredTools?: any[], executedTools?: any[], collections?: any, userId?: string, userPrompt?: string): Promise<{
2101
2101
  components: Component[];
2102
2102
  layoutTitle: string;
2103
2103
  layoutDescription: string;
package/dist/index.d.ts CHANGED
@@ -2097,7 +2097,7 @@ declare abstract class BaseLLM {
2097
2097
  * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
2098
2098
  * @returns Object containing matched components, layout title/description, and follow-up actions
2099
2099
  */
2100
- matchComponentsFromAnalysis(analysisContent: string, components: Component[], apiKey?: string, logCollector?: any, componentStreamCallback?: (component: Component) => void, deferredTools?: any[], executedTools?: any[]): Promise<{
2100
+ matchComponentsFromAnalysis(analysisContent: string, components: Component[], apiKey?: string, logCollector?: any, componentStreamCallback?: (component: Component) => void, deferredTools?: any[], executedTools?: any[], collections?: any, userId?: string, userPrompt?: string): Promise<{
2101
2101
  components: Component[];
2102
2102
  layoutTitle: string;
2103
2103
  layoutDescription: string;
package/dist/index.js CHANGED
@@ -1642,6 +1642,7 @@ __export(utils_exports, {
1642
1642
  fixScalarSubqueries: () => fixScalarSubqueries,
1643
1643
  getDatabaseType: () => getDatabaseType,
1644
1644
  getJsonSizeInBytes: () => getJsonSizeInBytes,
1645
+ validateAndFixSqlQuery: () => validateAndFixSqlQuery,
1645
1646
  validateMessageSize: () => validateMessageSize
1646
1647
  });
1647
1648
  function getDatabaseType() {
@@ -1817,6 +1818,105 @@ function validateMessageSize(message, maxSize = 1048576) {
1817
1818
  maxSize
1818
1819
  };
1819
1820
  }
1821
+ function validateAndFixSqlQuery(query, dbType) {
1822
+ if (!query || query.trim().length === 0) {
1823
+ return { query, fixed: false, fixes: [] };
1824
+ }
1825
+ const databaseType = dbType || getDatabaseType();
1826
+ const _isMssql = databaseType === "mssql";
1827
+ let fixedQuery = query;
1828
+ const fixes = [];
1829
+ const aggregateFunctions = ["SUM", "COUNT", "AVG", "MIN", "MAX"];
1830
+ const aggregateInWherePattern = new RegExp(
1831
+ `\\bWHERE\\b[^]*?\\b(${aggregateFunctions.join("|")})\\s*\\([^)]*\\)\\s*(?:=|>|<|>=|<=|<>|!=)`,
1832
+ "i"
1833
+ );
1834
+ if (aggregateInWherePattern.test(fixedQuery)) {
1835
+ const aggregateConditionPattern = new RegExp(
1836
+ `\\s+(AND|OR)\\s+((?:COALESCE\\s*\\(\\s*)?(?:${aggregateFunctions.join("|")})\\s*\\([^)]+\\)[^)]*(?:\\))?\\s*(?:=|>|<|>=|<=|<>|!=)\\s*[^\\s,)]+)`,
1837
+ "gi"
1838
+ );
1839
+ const aggregateConditions = [];
1840
+ let match;
1841
+ while ((match = aggregateConditionPattern.exec(fixedQuery)) !== null) {
1842
+ aggregateConditions.push(match[2].trim());
1843
+ }
1844
+ if (aggregateConditions.length > 0) {
1845
+ fixedQuery = fixedQuery.replace(aggregateConditionPattern, "");
1846
+ fixedQuery = fixedQuery.replace(/\bWHERE\s+(AND|OR)\s+/gi, "WHERE ");
1847
+ fixedQuery = fixedQuery.replace(/\bWHERE\s+(GROUP\s+BY|ORDER\s+BY|HAVING|$)/gi, "$1");
1848
+ const hasGroupBy = /\bGROUP\s+BY\b/i.test(fixedQuery);
1849
+ if (hasGroupBy) {
1850
+ const hasHaving = /\bHAVING\b/i.test(fixedQuery);
1851
+ const havingClause = aggregateConditions.join(" AND ");
1852
+ if (hasHaving) {
1853
+ fixedQuery = fixedQuery.replace(
1854
+ /\bHAVING\b/i,
1855
+ `HAVING ${havingClause} AND`
1856
+ );
1857
+ } else {
1858
+ const orderByMatch = fixedQuery.match(/(\s+ORDER\s+BY\s+)/i);
1859
+ if (orderByMatch) {
1860
+ fixedQuery = fixedQuery.replace(
1861
+ orderByMatch[1],
1862
+ ` HAVING ${havingClause}${orderByMatch[1]}`
1863
+ );
1864
+ } else {
1865
+ fixedQuery = fixedQuery.trimEnd() + ` HAVING ${havingClause}`;
1866
+ }
1867
+ }
1868
+ fixes.push(`Moved aggregate condition(s) from WHERE to HAVING: ${havingClause}`);
1869
+ }
1870
+ }
1871
+ }
1872
+ let openCount = 0;
1873
+ let closeCount = 0;
1874
+ let inString = false;
1875
+ let stringChar = "";
1876
+ for (let i = 0; i < fixedQuery.length; i++) {
1877
+ const char = fixedQuery[i];
1878
+ const prevChar = i > 0 ? fixedQuery[i - 1] : "";
1879
+ if ((char === "'" || char === '"') && prevChar !== "\\") {
1880
+ if (!inString) {
1881
+ inString = true;
1882
+ stringChar = char;
1883
+ } else if (char === stringChar) {
1884
+ if (i + 1 < fixedQuery.length && fixedQuery[i + 1] === char) {
1885
+ i++;
1886
+ } else {
1887
+ inString = false;
1888
+ }
1889
+ }
1890
+ continue;
1891
+ }
1892
+ if (!inString) {
1893
+ if (char === "(") openCount++;
1894
+ else if (char === ")") closeCount++;
1895
+ }
1896
+ }
1897
+ if (openCount > closeCount) {
1898
+ const missingClose = openCount - closeCount;
1899
+ fixedQuery = fixedQuery.trimEnd();
1900
+ const hasSemicolon = fixedQuery.endsWith(";");
1901
+ if (hasSemicolon) {
1902
+ fixedQuery = fixedQuery.slice(0, -1);
1903
+ }
1904
+ fixedQuery = fixedQuery + ")".repeat(missingClose);
1905
+ if (hasSemicolon) {
1906
+ fixedQuery = fixedQuery + ";";
1907
+ }
1908
+ fixes.push(`Added ${missingClose} missing closing parenthesis(es)`);
1909
+ }
1910
+ const originalLength = fixedQuery.length;
1911
+ fixedQuery = fixedQuery.replace(/\s+/g, " ").trim();
1912
+ if (fixedQuery.length !== originalLength) {
1913
+ }
1914
+ return {
1915
+ query: fixedQuery,
1916
+ fixed: fixes.length > 0,
1917
+ fixes
1918
+ };
1919
+ }
1820
1920
  var init_utils = __esm({
1821
1921
  "src/userResponse/utils.ts"() {
1822
1922
  "use strict";
@@ -5955,7 +6055,7 @@ var BaseLLM = class {
5955
6055
  * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
5956
6056
  * @returns Object containing matched components, layout title/description, and follow-up actions
5957
6057
  */
5958
- async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
6058
+ async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools, collections, userId, userPrompt) {
5959
6059
  const methodStartTime = Date.now();
5960
6060
  const methodName = "matchComponentsFromAnalysis";
5961
6061
  logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("complex")}`);
@@ -6018,6 +6118,16 @@ ${fieldsText}`;
6018
6118
  }
6019
6119
  const schemaDoc = schema.generateSchemaDocumentation();
6020
6120
  const databaseRules = await promptLoader.loadDatabaseRules();
6121
+ let knowledgeBaseContext = "No additional knowledge base context available.";
6122
+ if (collections) {
6123
+ const kbResult = await knowledge_base_default.getAllKnowledgeBase({
6124
+ prompt: userPrompt || analysisContent,
6125
+ collections,
6126
+ userId,
6127
+ topK: 3
6128
+ });
6129
+ knowledgeBaseContext = kbResult.combinedContext || knowledgeBaseContext;
6130
+ }
6021
6131
  const prompts = await promptLoader.loadPrompts("match-text-components", {
6022
6132
  ANALYSIS_CONTENT: analysisContent,
6023
6133
  AVAILABLE_COMPONENTS: availableComponentsText,
@@ -6025,11 +6135,27 @@ ${fieldsText}`;
6025
6135
  DATABASE_RULES: databaseRules,
6026
6136
  DEFERRED_TOOLS: deferredToolsText,
6027
6137
  EXECUTED_TOOLS: executedToolsText,
6138
+ KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext,
6028
6139
  CURRENT_DATETIME: getCurrentDateTimeForPrompt()
6029
6140
  });
6030
6141
  logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
6031
- const systemPromptStr = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
6032
- logger.logLLMPrompt("matchComponentsFromAnalysis", "system", systemPromptStr);
6142
+ const extractPromptText = (content) => {
6143
+ if (typeof content === "string") return content;
6144
+ if (Array.isArray(content)) {
6145
+ return content.map((item) => {
6146
+ if (typeof item === "string") return item;
6147
+ if (item && typeof item.text === "string") return item.text;
6148
+ if (item && item.content && typeof item.content === "string") return item.content;
6149
+ return JSON.stringify(item, null, 2);
6150
+ }).join("\n\n---\n\n");
6151
+ }
6152
+ if (content && typeof content === "object") {
6153
+ if (typeof content.text === "string") return content.text;
6154
+ return JSON.stringify(content, null, 2);
6155
+ }
6156
+ return String(content);
6157
+ };
6158
+ logger.logLLMPrompt("matchComponentsFromAnalysis", "system", extractPromptText(prompts.system));
6033
6159
  logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
6034
6160
  ${analysisContent}
6035
6161
 
@@ -6254,6 +6380,18 @@ ${executedToolsText}`);
6254
6380
  cleanedProps.query = null;
6255
6381
  }
6256
6382
  }
6383
+ if (cleanedProps.query) {
6384
+ const queryStr = typeof cleanedProps.query === "string" ? cleanedProps.query : cleanedProps.query?.sql || "";
6385
+ const { query: fixedQuery, fixed, fixes } = validateAndFixSqlQuery(queryStr);
6386
+ if (fixed) {
6387
+ logger.warn(`[${this.getProviderName()}] SQL fixes applied to component query: ${fixes.join("; ")}`);
6388
+ if (typeof cleanedProps.query === "string") {
6389
+ cleanedProps.query = fixedQuery;
6390
+ } else if (cleanedProps.query?.sql) {
6391
+ cleanedProps.query.sql = fixedQuery;
6392
+ }
6393
+ }
6394
+ }
6257
6395
  if (cleanedProps.query && cleanedProps.externalTool) {
6258
6396
  logger.info(`[${this.getProviderName()}] Both query and externalTool exist, keeping both - frontend will decide`);
6259
6397
  }
@@ -6310,10 +6448,24 @@ ${executedToolsText}`);
6310
6448
  SCHEMA_DOC: schemaDoc || "No database schema available",
6311
6449
  CURRENT_DATETIME: getCurrentDateTimeForPrompt()
6312
6450
  });
6313
- const systemPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
6314
- const userPromptText = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
6315
- logger.logLLMPrompt("classifyQuestionCategory", "system", systemPrompt);
6316
- logger.logLLMPrompt("classifyQuestionCategory", "user", userPromptText);
6451
+ const extractTextContent = (content) => {
6452
+ if (typeof content === "string") return content;
6453
+ if (Array.isArray(content)) {
6454
+ return content.map((item) => {
6455
+ if (typeof item === "string") return item;
6456
+ if (item && typeof item.text === "string") return item.text;
6457
+ if (item && item.content && typeof item.content === "string") return item.content;
6458
+ return JSON.stringify(item, null, 2);
6459
+ }).join("\n\n---\n\n");
6460
+ }
6461
+ if (content && typeof content === "object") {
6462
+ if (typeof content.text === "string") return content.text;
6463
+ return JSON.stringify(content, null, 2);
6464
+ }
6465
+ return String(content);
6466
+ };
6467
+ logger.logLLMPrompt("classifyQuestionCategory", "system", extractTextContent(prompts.system));
6468
+ logger.logLLMPrompt("classifyQuestionCategory", "user", extractTextContent(prompts.user));
6317
6469
  const result = await LLM.stream(
6318
6470
  {
6319
6471
  sys: prompts.system,
@@ -6529,10 +6681,24 @@ ${executedToolsText}`);
6529
6681
  AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc,
6530
6682
  CURRENT_DATETIME: getCurrentDateTimeForPrompt()
6531
6683
  });
6532
- const sysPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
6533
- const usrPrompt = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
6534
- logger.logLLMPrompt("generateTextResponse", "system", sysPrompt);
6535
- logger.logLLMPrompt("generateTextResponse", "user", usrPrompt);
6684
+ const extractText = (content) => {
6685
+ if (typeof content === "string") return content;
6686
+ if (Array.isArray(content)) {
6687
+ return content.map((item) => {
6688
+ if (typeof item === "string") return item;
6689
+ if (item && typeof item.text === "string") return item.text;
6690
+ if (item && item.content && typeof item.content === "string") return item.content;
6691
+ return JSON.stringify(item, null, 2);
6692
+ }).join("\n\n---\n\n");
6693
+ }
6694
+ if (content && typeof content === "object") {
6695
+ if (typeof content.text === "string") return content.text;
6696
+ return JSON.stringify(content, null, 2);
6697
+ }
6698
+ return String(content);
6699
+ };
6700
+ logger.logLLMPrompt("generateTextResponse", "system", extractText(prompts.system));
6701
+ logger.logLLMPrompt("generateTextResponse", "user", extractText(prompts.user));
6536
6702
  logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
6537
6703
  logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
6538
6704
  logCollector?.info("Generating text response with query execution capability...");
@@ -7056,7 +7222,10 @@ ${errorMsg}
7056
7222
  logCollector,
7057
7223
  componentStreamCallback,
7058
7224
  deferredTools,
7059
- executedToolsList
7225
+ executedToolsList,
7226
+ collections,
7227
+ userId,
7228
+ userPrompt
7060
7229
  );
7061
7230
  matchedComponents = matchResult.components;
7062
7231
  layoutTitle = matchResult.layoutTitle;
@@ -7139,7 +7308,6 @@ ${errorMsg}
7139
7308
  logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
7140
7309
  try {
7141
7310
  logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
7142
- logCollector?.info("Step 1: Searching for similar previous conversations...");
7143
7311
  const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
7144
7312
  userPrompt,
7145
7313
  collections,