@superatomai/sdk-node 0.0.58 → 0.0.60
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.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +205 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +205 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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,122 @@ 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 subqueryOrderByPattern = /\(\s*SELECT\s+(?!TOP\s)([^()]*?)\s+ORDER\s+BY\s+[^()]+\)/gi;
|
|
1889
|
+
let subqueryMatch;
|
|
1890
|
+
let subqueryFixed = false;
|
|
1891
|
+
while ((subqueryMatch = subqueryOrderByPattern.exec(fixedQuery)) !== null) {
|
|
1892
|
+
const fullMatch = subqueryMatch[0];
|
|
1893
|
+
if (!/\bTOP\s+\d+/i.test(fullMatch) && !/\bOFFSET\b/i.test(fullMatch)) {
|
|
1894
|
+
const fixedSubquery = fullMatch.replace(
|
|
1895
|
+
/\(\s*SELECT\s+/i,
|
|
1896
|
+
"(SELECT TOP 100 "
|
|
1897
|
+
);
|
|
1898
|
+
fixedQuery = fixedQuery.replace(fullMatch, fixedSubquery);
|
|
1899
|
+
subqueryFixed = true;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
if (subqueryFixed) {
|
|
1903
|
+
fixes.push("Added TOP to subquery with ORDER BY (MSSQL requirement)");
|
|
1904
|
+
}
|
|
1905
|
+
const originalLength = fixedQuery.length;
|
|
1906
|
+
fixedQuery = fixedQuery.replace(/\s+/g, " ").trim();
|
|
1907
|
+
if (fixedQuery.length !== originalLength) {
|
|
1908
|
+
}
|
|
1909
|
+
return {
|
|
1910
|
+
query: fixedQuery,
|
|
1911
|
+
fixed: fixes.length > 0,
|
|
1912
|
+
fixes
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1798
1915
|
var init_utils = __esm({
|
|
1799
1916
|
"src/userResponse/utils.ts"() {
|
|
1800
1917
|
"use strict";
|
|
@@ -5905,7 +6022,7 @@ var BaseLLM = class {
|
|
|
5905
6022
|
* @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
|
|
5906
6023
|
* @returns Object containing matched components, layout title/description, and follow-up actions
|
|
5907
6024
|
*/
|
|
5908
|
-
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
|
|
6025
|
+
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools, collections, userId, userPrompt) {
|
|
5909
6026
|
const methodStartTime = Date.now();
|
|
5910
6027
|
const methodName = "matchComponentsFromAnalysis";
|
|
5911
6028
|
logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("complex")}`);
|
|
@@ -5968,6 +6085,16 @@ ${fieldsText}`;
|
|
|
5968
6085
|
}
|
|
5969
6086
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
5970
6087
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
6088
|
+
let knowledgeBaseContext = "No additional knowledge base context available.";
|
|
6089
|
+
if (collections) {
|
|
6090
|
+
const kbResult = await knowledge_base_default.getAllKnowledgeBase({
|
|
6091
|
+
prompt: userPrompt || analysisContent,
|
|
6092
|
+
collections,
|
|
6093
|
+
userId,
|
|
6094
|
+
topK: 3
|
|
6095
|
+
});
|
|
6096
|
+
knowledgeBaseContext = kbResult.combinedContext || knowledgeBaseContext;
|
|
6097
|
+
}
|
|
5971
6098
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
5972
6099
|
ANALYSIS_CONTENT: analysisContent,
|
|
5973
6100
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -5975,11 +6102,27 @@ ${fieldsText}`;
|
|
|
5975
6102
|
DATABASE_RULES: databaseRules,
|
|
5976
6103
|
DEFERRED_TOOLS: deferredToolsText,
|
|
5977
6104
|
EXECUTED_TOOLS: executedToolsText,
|
|
6105
|
+
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext,
|
|
5978
6106
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
5979
6107
|
});
|
|
5980
6108
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
5981
|
-
const
|
|
5982
|
-
|
|
6109
|
+
const extractPromptText = (content) => {
|
|
6110
|
+
if (typeof content === "string") return content;
|
|
6111
|
+
if (Array.isArray(content)) {
|
|
6112
|
+
return content.map((item) => {
|
|
6113
|
+
if (typeof item === "string") return item;
|
|
6114
|
+
if (item && typeof item.text === "string") return item.text;
|
|
6115
|
+
if (item && item.content && typeof item.content === "string") return item.content;
|
|
6116
|
+
return JSON.stringify(item, null, 2);
|
|
6117
|
+
}).join("\n\n---\n\n");
|
|
6118
|
+
}
|
|
6119
|
+
if (content && typeof content === "object") {
|
|
6120
|
+
if (typeof content.text === "string") return content.text;
|
|
6121
|
+
return JSON.stringify(content, null, 2);
|
|
6122
|
+
}
|
|
6123
|
+
return String(content);
|
|
6124
|
+
};
|
|
6125
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "system", extractPromptText(prompts.system));
|
|
5983
6126
|
logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
|
|
5984
6127
|
${analysisContent}
|
|
5985
6128
|
|
|
@@ -6204,6 +6347,18 @@ ${executedToolsText}`);
|
|
|
6204
6347
|
cleanedProps.query = null;
|
|
6205
6348
|
}
|
|
6206
6349
|
}
|
|
6350
|
+
if (cleanedProps.query) {
|
|
6351
|
+
const queryStr = typeof cleanedProps.query === "string" ? cleanedProps.query : cleanedProps.query?.sql || "";
|
|
6352
|
+
const { query: fixedQuery, fixed, fixes } = validateAndFixSqlQuery(queryStr);
|
|
6353
|
+
if (fixed) {
|
|
6354
|
+
logger.warn(`[${this.getProviderName()}] SQL fixes applied to component query: ${fixes.join("; ")}`);
|
|
6355
|
+
if (typeof cleanedProps.query === "string") {
|
|
6356
|
+
cleanedProps.query = fixedQuery;
|
|
6357
|
+
} else if (cleanedProps.query?.sql) {
|
|
6358
|
+
cleanedProps.query.sql = fixedQuery;
|
|
6359
|
+
}
|
|
6360
|
+
}
|
|
6361
|
+
}
|
|
6207
6362
|
if (cleanedProps.query && cleanedProps.externalTool) {
|
|
6208
6363
|
logger.info(`[${this.getProviderName()}] Both query and externalTool exist, keeping both - frontend will decide`);
|
|
6209
6364
|
}
|
|
@@ -6260,10 +6415,24 @@ ${executedToolsText}`);
|
|
|
6260
6415
|
SCHEMA_DOC: schemaDoc || "No database schema available",
|
|
6261
6416
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
6262
6417
|
});
|
|
6263
|
-
const
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6418
|
+
const extractTextContent = (content) => {
|
|
6419
|
+
if (typeof content === "string") return content;
|
|
6420
|
+
if (Array.isArray(content)) {
|
|
6421
|
+
return content.map((item) => {
|
|
6422
|
+
if (typeof item === "string") return item;
|
|
6423
|
+
if (item && typeof item.text === "string") return item.text;
|
|
6424
|
+
if (item && item.content && typeof item.content === "string") return item.content;
|
|
6425
|
+
return JSON.stringify(item, null, 2);
|
|
6426
|
+
}).join("\n\n---\n\n");
|
|
6427
|
+
}
|
|
6428
|
+
if (content && typeof content === "object") {
|
|
6429
|
+
if (typeof content.text === "string") return content.text;
|
|
6430
|
+
return JSON.stringify(content, null, 2);
|
|
6431
|
+
}
|
|
6432
|
+
return String(content);
|
|
6433
|
+
};
|
|
6434
|
+
logger.logLLMPrompt("classifyQuestionCategory", "system", extractTextContent(prompts.system));
|
|
6435
|
+
logger.logLLMPrompt("classifyQuestionCategory", "user", extractTextContent(prompts.user));
|
|
6267
6436
|
const result = await LLM.stream(
|
|
6268
6437
|
{
|
|
6269
6438
|
sys: prompts.system,
|
|
@@ -6479,10 +6648,24 @@ ${executedToolsText}`);
|
|
|
6479
6648
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc,
|
|
6480
6649
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
6481
6650
|
});
|
|
6482
|
-
const
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6651
|
+
const extractText = (content) => {
|
|
6652
|
+
if (typeof content === "string") return content;
|
|
6653
|
+
if (Array.isArray(content)) {
|
|
6654
|
+
return content.map((item) => {
|
|
6655
|
+
if (typeof item === "string") return item;
|
|
6656
|
+
if (item && typeof item.text === "string") return item.text;
|
|
6657
|
+
if (item && item.content && typeof item.content === "string") return item.content;
|
|
6658
|
+
return JSON.stringify(item, null, 2);
|
|
6659
|
+
}).join("\n\n---\n\n");
|
|
6660
|
+
}
|
|
6661
|
+
if (content && typeof content === "object") {
|
|
6662
|
+
if (typeof content.text === "string") return content.text;
|
|
6663
|
+
return JSON.stringify(content, null, 2);
|
|
6664
|
+
}
|
|
6665
|
+
return String(content);
|
|
6666
|
+
};
|
|
6667
|
+
logger.logLLMPrompt("generateTextResponse", "system", extractText(prompts.system));
|
|
6668
|
+
logger.logLLMPrompt("generateTextResponse", "user", extractText(prompts.user));
|
|
6486
6669
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6487
6670
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6488
6671
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6515,7 +6698,13 @@ ${executedToolsText}`);
|
|
|
6515
6698
|
(t) => t.executionType === "immediate" || t.executionType === "deferred" && t.userProvidedData
|
|
6516
6699
|
);
|
|
6517
6700
|
logger.info(`[${this.getProviderName()}] Executable tools: ${executableTools.length} of ${externalTools.length} total`);
|
|
6701
|
+
const addedToolIds = /* @__PURE__ */ new Set();
|
|
6518
6702
|
executableTools.forEach((tool) => {
|
|
6703
|
+
if (addedToolIds.has(tool.id)) {
|
|
6704
|
+
logger.info(`[${this.getProviderName()}] Skipping duplicate tool definition: ${tool.id} (already added)`);
|
|
6705
|
+
return;
|
|
6706
|
+
}
|
|
6707
|
+
addedToolIds.add(tool.id);
|
|
6519
6708
|
logger.info(`[${this.getProviderName()}] Processing executable tool:`, JSON.stringify(tool, null, 2));
|
|
6520
6709
|
const properties = {};
|
|
6521
6710
|
const required = [];
|
|
@@ -6585,7 +6774,7 @@ ${executedToolsText}`);
|
|
|
6585
6774
|
input_schema: inputSchema
|
|
6586
6775
|
});
|
|
6587
6776
|
});
|
|
6588
|
-
logger.info(`[${this.getProviderName()}] Added ${
|
|
6777
|
+
logger.info(`[${this.getProviderName()}] Added ${addedToolIds.size} unique tool definitions from ${executableTools.length} tool calls (${externalTools.length - executableTools.length} deferred tools await form input)`);
|
|
6589
6778
|
logger.info(`[${this.getProviderName()}] Complete tools array:`, JSON.stringify(tools, null, 2));
|
|
6590
6779
|
}
|
|
6591
6780
|
const queryAttempts = /* @__PURE__ */ new Map();
|
|
@@ -7006,7 +7195,10 @@ ${errorMsg}
|
|
|
7006
7195
|
logCollector,
|
|
7007
7196
|
componentStreamCallback,
|
|
7008
7197
|
deferredTools,
|
|
7009
|
-
executedToolsList
|
|
7198
|
+
executedToolsList,
|
|
7199
|
+
collections,
|
|
7200
|
+
userId,
|
|
7201
|
+
userPrompt
|
|
7010
7202
|
);
|
|
7011
7203
|
matchedComponents = matchResult.components;
|
|
7012
7204
|
layoutTitle = matchResult.layoutTitle;
|
|
@@ -7089,7 +7281,6 @@ ${errorMsg}
|
|
|
7089
7281
|
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
7090
7282
|
try {
|
|
7091
7283
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
7092
|
-
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
7093
7284
|
const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
|
|
7094
7285
|
userPrompt,
|
|
7095
7286
|
collections,
|