@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.mjs CHANGED
@@ -1620,6 +1620,7 @@ __export(utils_exports, {
1620
1620
  fixScalarSubqueries: () => fixScalarSubqueries,
1621
1621
  getDatabaseType: () => getDatabaseType,
1622
1622
  getJsonSizeInBytes: () => getJsonSizeInBytes,
1623
+ validateAndFixSqlQuery: () => validateAndFixSqlQuery,
1623
1624
  validateMessageSize: () => validateMessageSize
1624
1625
  });
1625
1626
  function getDatabaseType() {
@@ -1795,6 +1796,105 @@ function validateMessageSize(message, maxSize = 1048576) {
1795
1796
  maxSize
1796
1797
  };
1797
1798
  }
1799
+ function validateAndFixSqlQuery(query, dbType) {
1800
+ if (!query || query.trim().length === 0) {
1801
+ return { query, fixed: false, fixes: [] };
1802
+ }
1803
+ const databaseType = dbType || getDatabaseType();
1804
+ const _isMssql = databaseType === "mssql";
1805
+ let fixedQuery = query;
1806
+ const fixes = [];
1807
+ const aggregateFunctions = ["SUM", "COUNT", "AVG", "MIN", "MAX"];
1808
+ const aggregateInWherePattern = new RegExp(
1809
+ `\\bWHERE\\b[^]*?\\b(${aggregateFunctions.join("|")})\\s*\\([^)]*\\)\\s*(?:=|>|<|>=|<=|<>|!=)`,
1810
+ "i"
1811
+ );
1812
+ if (aggregateInWherePattern.test(fixedQuery)) {
1813
+ const aggregateConditionPattern = new RegExp(
1814
+ `\\s+(AND|OR)\\s+((?:COALESCE\\s*\\(\\s*)?(?:${aggregateFunctions.join("|")})\\s*\\([^)]+\\)[^)]*(?:\\))?\\s*(?:=|>|<|>=|<=|<>|!=)\\s*[^\\s,)]+)`,
1815
+ "gi"
1816
+ );
1817
+ const aggregateConditions = [];
1818
+ let match;
1819
+ while ((match = aggregateConditionPattern.exec(fixedQuery)) !== null) {
1820
+ aggregateConditions.push(match[2].trim());
1821
+ }
1822
+ if (aggregateConditions.length > 0) {
1823
+ fixedQuery = fixedQuery.replace(aggregateConditionPattern, "");
1824
+ fixedQuery = fixedQuery.replace(/\bWHERE\s+(AND|OR)\s+/gi, "WHERE ");
1825
+ fixedQuery = fixedQuery.replace(/\bWHERE\s+(GROUP\s+BY|ORDER\s+BY|HAVING|$)/gi, "$1");
1826
+ const hasGroupBy = /\bGROUP\s+BY\b/i.test(fixedQuery);
1827
+ if (hasGroupBy) {
1828
+ const hasHaving = /\bHAVING\b/i.test(fixedQuery);
1829
+ const havingClause = aggregateConditions.join(" AND ");
1830
+ if (hasHaving) {
1831
+ fixedQuery = fixedQuery.replace(
1832
+ /\bHAVING\b/i,
1833
+ `HAVING ${havingClause} AND`
1834
+ );
1835
+ } else {
1836
+ const orderByMatch = fixedQuery.match(/(\s+ORDER\s+BY\s+)/i);
1837
+ if (orderByMatch) {
1838
+ fixedQuery = fixedQuery.replace(
1839
+ orderByMatch[1],
1840
+ ` HAVING ${havingClause}${orderByMatch[1]}`
1841
+ );
1842
+ } else {
1843
+ fixedQuery = fixedQuery.trimEnd() + ` HAVING ${havingClause}`;
1844
+ }
1845
+ }
1846
+ fixes.push(`Moved aggregate condition(s) from WHERE to HAVING: ${havingClause}`);
1847
+ }
1848
+ }
1849
+ }
1850
+ let openCount = 0;
1851
+ let closeCount = 0;
1852
+ let inString = false;
1853
+ let stringChar = "";
1854
+ for (let i = 0; i < fixedQuery.length; i++) {
1855
+ const char = fixedQuery[i];
1856
+ const prevChar = i > 0 ? fixedQuery[i - 1] : "";
1857
+ if ((char === "'" || char === '"') && prevChar !== "\\") {
1858
+ if (!inString) {
1859
+ inString = true;
1860
+ stringChar = char;
1861
+ } else if (char === stringChar) {
1862
+ if (i + 1 < fixedQuery.length && fixedQuery[i + 1] === char) {
1863
+ i++;
1864
+ } else {
1865
+ inString = false;
1866
+ }
1867
+ }
1868
+ continue;
1869
+ }
1870
+ if (!inString) {
1871
+ if (char === "(") openCount++;
1872
+ else if (char === ")") closeCount++;
1873
+ }
1874
+ }
1875
+ if (openCount > closeCount) {
1876
+ const missingClose = openCount - closeCount;
1877
+ fixedQuery = fixedQuery.trimEnd();
1878
+ const hasSemicolon = fixedQuery.endsWith(";");
1879
+ if (hasSemicolon) {
1880
+ fixedQuery = fixedQuery.slice(0, -1);
1881
+ }
1882
+ fixedQuery = fixedQuery + ")".repeat(missingClose);
1883
+ if (hasSemicolon) {
1884
+ fixedQuery = fixedQuery + ";";
1885
+ }
1886
+ fixes.push(`Added ${missingClose} missing closing parenthesis(es)`);
1887
+ }
1888
+ const originalLength = fixedQuery.length;
1889
+ fixedQuery = fixedQuery.replace(/\s+/g, " ").trim();
1890
+ if (fixedQuery.length !== originalLength) {
1891
+ }
1892
+ return {
1893
+ query: fixedQuery,
1894
+ fixed: fixes.length > 0,
1895
+ fixes
1896
+ };
1897
+ }
1798
1898
  var init_utils = __esm({
1799
1899
  "src/userResponse/utils.ts"() {
1800
1900
  "use strict";
@@ -5905,7 +6005,7 @@ var BaseLLM = class {
5905
6005
  * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
5906
6006
  * @returns Object containing matched components, layout title/description, and follow-up actions
5907
6007
  */
5908
- async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
6008
+ async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools, collections, userId, userPrompt) {
5909
6009
  const methodStartTime = Date.now();
5910
6010
  const methodName = "matchComponentsFromAnalysis";
5911
6011
  logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("complex")}`);
@@ -5968,6 +6068,16 @@ ${fieldsText}`;
5968
6068
  }
5969
6069
  const schemaDoc = schema.generateSchemaDocumentation();
5970
6070
  const databaseRules = await promptLoader.loadDatabaseRules();
6071
+ let knowledgeBaseContext = "No additional knowledge base context available.";
6072
+ if (collections) {
6073
+ const kbResult = await knowledge_base_default.getAllKnowledgeBase({
6074
+ prompt: userPrompt || analysisContent,
6075
+ collections,
6076
+ userId,
6077
+ topK: 3
6078
+ });
6079
+ knowledgeBaseContext = kbResult.combinedContext || knowledgeBaseContext;
6080
+ }
5971
6081
  const prompts = await promptLoader.loadPrompts("match-text-components", {
5972
6082
  ANALYSIS_CONTENT: analysisContent,
5973
6083
  AVAILABLE_COMPONENTS: availableComponentsText,
@@ -5975,11 +6085,27 @@ ${fieldsText}`;
5975
6085
  DATABASE_RULES: databaseRules,
5976
6086
  DEFERRED_TOOLS: deferredToolsText,
5977
6087
  EXECUTED_TOOLS: executedToolsText,
6088
+ KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext,
5978
6089
  CURRENT_DATETIME: getCurrentDateTimeForPrompt()
5979
6090
  });
5980
6091
  logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
5981
- const systemPromptStr = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
5982
- logger.logLLMPrompt("matchComponentsFromAnalysis", "system", systemPromptStr);
6092
+ const extractPromptText = (content) => {
6093
+ if (typeof content === "string") return content;
6094
+ if (Array.isArray(content)) {
6095
+ return content.map((item) => {
6096
+ if (typeof item === "string") return item;
6097
+ if (item && typeof item.text === "string") return item.text;
6098
+ if (item && item.content && typeof item.content === "string") return item.content;
6099
+ return JSON.stringify(item, null, 2);
6100
+ }).join("\n\n---\n\n");
6101
+ }
6102
+ if (content && typeof content === "object") {
6103
+ if (typeof content.text === "string") return content.text;
6104
+ return JSON.stringify(content, null, 2);
6105
+ }
6106
+ return String(content);
6107
+ };
6108
+ logger.logLLMPrompt("matchComponentsFromAnalysis", "system", extractPromptText(prompts.system));
5983
6109
  logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
5984
6110
  ${analysisContent}
5985
6111
 
@@ -6204,6 +6330,18 @@ ${executedToolsText}`);
6204
6330
  cleanedProps.query = null;
6205
6331
  }
6206
6332
  }
6333
+ if (cleanedProps.query) {
6334
+ const queryStr = typeof cleanedProps.query === "string" ? cleanedProps.query : cleanedProps.query?.sql || "";
6335
+ const { query: fixedQuery, fixed, fixes } = validateAndFixSqlQuery(queryStr);
6336
+ if (fixed) {
6337
+ logger.warn(`[${this.getProviderName()}] SQL fixes applied to component query: ${fixes.join("; ")}`);
6338
+ if (typeof cleanedProps.query === "string") {
6339
+ cleanedProps.query = fixedQuery;
6340
+ } else if (cleanedProps.query?.sql) {
6341
+ cleanedProps.query.sql = fixedQuery;
6342
+ }
6343
+ }
6344
+ }
6207
6345
  if (cleanedProps.query && cleanedProps.externalTool) {
6208
6346
  logger.info(`[${this.getProviderName()}] Both query and externalTool exist, keeping both - frontend will decide`);
6209
6347
  }
@@ -6260,10 +6398,24 @@ ${executedToolsText}`);
6260
6398
  SCHEMA_DOC: schemaDoc || "No database schema available",
6261
6399
  CURRENT_DATETIME: getCurrentDateTimeForPrompt()
6262
6400
  });
6263
- const systemPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
6264
- const userPromptText = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
6265
- logger.logLLMPrompt("classifyQuestionCategory", "system", systemPrompt);
6266
- logger.logLLMPrompt("classifyQuestionCategory", "user", userPromptText);
6401
+ const extractTextContent = (content) => {
6402
+ if (typeof content === "string") return content;
6403
+ if (Array.isArray(content)) {
6404
+ return content.map((item) => {
6405
+ if (typeof item === "string") return item;
6406
+ if (item && typeof item.text === "string") return item.text;
6407
+ if (item && item.content && typeof item.content === "string") return item.content;
6408
+ return JSON.stringify(item, null, 2);
6409
+ }).join("\n\n---\n\n");
6410
+ }
6411
+ if (content && typeof content === "object") {
6412
+ if (typeof content.text === "string") return content.text;
6413
+ return JSON.stringify(content, null, 2);
6414
+ }
6415
+ return String(content);
6416
+ };
6417
+ logger.logLLMPrompt("classifyQuestionCategory", "system", extractTextContent(prompts.system));
6418
+ logger.logLLMPrompt("classifyQuestionCategory", "user", extractTextContent(prompts.user));
6267
6419
  const result = await LLM.stream(
6268
6420
  {
6269
6421
  sys: prompts.system,
@@ -6479,10 +6631,24 @@ ${executedToolsText}`);
6479
6631
  AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc,
6480
6632
  CURRENT_DATETIME: getCurrentDateTimeForPrompt()
6481
6633
  });
6482
- const sysPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
6483
- const usrPrompt = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
6484
- logger.logLLMPrompt("generateTextResponse", "system", sysPrompt);
6485
- logger.logLLMPrompt("generateTextResponse", "user", usrPrompt);
6634
+ const extractText = (content) => {
6635
+ if (typeof content === "string") return content;
6636
+ if (Array.isArray(content)) {
6637
+ return content.map((item) => {
6638
+ if (typeof item === "string") return item;
6639
+ if (item && typeof item.text === "string") return item.text;
6640
+ if (item && item.content && typeof item.content === "string") return item.content;
6641
+ return JSON.stringify(item, null, 2);
6642
+ }).join("\n\n---\n\n");
6643
+ }
6644
+ if (content && typeof content === "object") {
6645
+ if (typeof content.text === "string") return content.text;
6646
+ return JSON.stringify(content, null, 2);
6647
+ }
6648
+ return String(content);
6649
+ };
6650
+ logger.logLLMPrompt("generateTextResponse", "system", extractText(prompts.system));
6651
+ logger.logLLMPrompt("generateTextResponse", "user", extractText(prompts.user));
6486
6652
  logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
6487
6653
  logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
6488
6654
  logCollector?.info("Generating text response with query execution capability...");
@@ -7006,7 +7172,10 @@ ${errorMsg}
7006
7172
  logCollector,
7007
7173
  componentStreamCallback,
7008
7174
  deferredTools,
7009
- executedToolsList
7175
+ executedToolsList,
7176
+ collections,
7177
+ userId,
7178
+ userPrompt
7010
7179
  );
7011
7180
  matchedComponents = matchResult.components;
7012
7181
  layoutTitle = matchResult.layoutTitle;
@@ -7089,7 +7258,6 @@ ${errorMsg}
7089
7258
  logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
7090
7259
  try {
7091
7260
  logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
7092
- logCollector?.info("Step 1: Searching for similar previous conversations...");
7093
7261
  const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
7094
7262
  userPrompt,
7095
7263
  collections,