@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.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,122 @@ 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 subqueryOrderByPattern = /\(\s*SELECT\s+(?!TOP\s)([^()]*?)\s+ORDER\s+BY\s+[^()]+\)/gi;
|
|
1911
|
+
let subqueryMatch;
|
|
1912
|
+
let subqueryFixed = false;
|
|
1913
|
+
while ((subqueryMatch = subqueryOrderByPattern.exec(fixedQuery)) !== null) {
|
|
1914
|
+
const fullMatch = subqueryMatch[0];
|
|
1915
|
+
if (!/\bTOP\s+\d+/i.test(fullMatch) && !/\bOFFSET\b/i.test(fullMatch)) {
|
|
1916
|
+
const fixedSubquery = fullMatch.replace(
|
|
1917
|
+
/\(\s*SELECT\s+/i,
|
|
1918
|
+
"(SELECT TOP 100 "
|
|
1919
|
+
);
|
|
1920
|
+
fixedQuery = fixedQuery.replace(fullMatch, fixedSubquery);
|
|
1921
|
+
subqueryFixed = true;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
if (subqueryFixed) {
|
|
1925
|
+
fixes.push("Added TOP to subquery with ORDER BY (MSSQL requirement)");
|
|
1926
|
+
}
|
|
1927
|
+
const originalLength = fixedQuery.length;
|
|
1928
|
+
fixedQuery = fixedQuery.replace(/\s+/g, " ").trim();
|
|
1929
|
+
if (fixedQuery.length !== originalLength) {
|
|
1930
|
+
}
|
|
1931
|
+
return {
|
|
1932
|
+
query: fixedQuery,
|
|
1933
|
+
fixed: fixes.length > 0,
|
|
1934
|
+
fixes
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1820
1937
|
var init_utils = __esm({
|
|
1821
1938
|
"src/userResponse/utils.ts"() {
|
|
1822
1939
|
"use strict";
|
|
@@ -5955,7 +6072,7 @@ var BaseLLM = class {
|
|
|
5955
6072
|
* @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
|
|
5956
6073
|
* @returns Object containing matched components, layout title/description, and follow-up actions
|
|
5957
6074
|
*/
|
|
5958
|
-
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
|
|
6075
|
+
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools, collections, userId, userPrompt) {
|
|
5959
6076
|
const methodStartTime = Date.now();
|
|
5960
6077
|
const methodName = "matchComponentsFromAnalysis";
|
|
5961
6078
|
logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("complex")}`);
|
|
@@ -6018,6 +6135,16 @@ ${fieldsText}`;
|
|
|
6018
6135
|
}
|
|
6019
6136
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
6020
6137
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
6138
|
+
let knowledgeBaseContext = "No additional knowledge base context available.";
|
|
6139
|
+
if (collections) {
|
|
6140
|
+
const kbResult = await knowledge_base_default.getAllKnowledgeBase({
|
|
6141
|
+
prompt: userPrompt || analysisContent,
|
|
6142
|
+
collections,
|
|
6143
|
+
userId,
|
|
6144
|
+
topK: 3
|
|
6145
|
+
});
|
|
6146
|
+
knowledgeBaseContext = kbResult.combinedContext || knowledgeBaseContext;
|
|
6147
|
+
}
|
|
6021
6148
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
6022
6149
|
ANALYSIS_CONTENT: analysisContent,
|
|
6023
6150
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -6025,11 +6152,27 @@ ${fieldsText}`;
|
|
|
6025
6152
|
DATABASE_RULES: databaseRules,
|
|
6026
6153
|
DEFERRED_TOOLS: deferredToolsText,
|
|
6027
6154
|
EXECUTED_TOOLS: executedToolsText,
|
|
6155
|
+
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext,
|
|
6028
6156
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
6029
6157
|
});
|
|
6030
6158
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
6031
|
-
const
|
|
6032
|
-
|
|
6159
|
+
const extractPromptText = (content) => {
|
|
6160
|
+
if (typeof content === "string") return content;
|
|
6161
|
+
if (Array.isArray(content)) {
|
|
6162
|
+
return content.map((item) => {
|
|
6163
|
+
if (typeof item === "string") return item;
|
|
6164
|
+
if (item && typeof item.text === "string") return item.text;
|
|
6165
|
+
if (item && item.content && typeof item.content === "string") return item.content;
|
|
6166
|
+
return JSON.stringify(item, null, 2);
|
|
6167
|
+
}).join("\n\n---\n\n");
|
|
6168
|
+
}
|
|
6169
|
+
if (content && typeof content === "object") {
|
|
6170
|
+
if (typeof content.text === "string") return content.text;
|
|
6171
|
+
return JSON.stringify(content, null, 2);
|
|
6172
|
+
}
|
|
6173
|
+
return String(content);
|
|
6174
|
+
};
|
|
6175
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "system", extractPromptText(prompts.system));
|
|
6033
6176
|
logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
|
|
6034
6177
|
${analysisContent}
|
|
6035
6178
|
|
|
@@ -6254,6 +6397,18 @@ ${executedToolsText}`);
|
|
|
6254
6397
|
cleanedProps.query = null;
|
|
6255
6398
|
}
|
|
6256
6399
|
}
|
|
6400
|
+
if (cleanedProps.query) {
|
|
6401
|
+
const queryStr = typeof cleanedProps.query === "string" ? cleanedProps.query : cleanedProps.query?.sql || "";
|
|
6402
|
+
const { query: fixedQuery, fixed, fixes } = validateAndFixSqlQuery(queryStr);
|
|
6403
|
+
if (fixed) {
|
|
6404
|
+
logger.warn(`[${this.getProviderName()}] SQL fixes applied to component query: ${fixes.join("; ")}`);
|
|
6405
|
+
if (typeof cleanedProps.query === "string") {
|
|
6406
|
+
cleanedProps.query = fixedQuery;
|
|
6407
|
+
} else if (cleanedProps.query?.sql) {
|
|
6408
|
+
cleanedProps.query.sql = fixedQuery;
|
|
6409
|
+
}
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6257
6412
|
if (cleanedProps.query && cleanedProps.externalTool) {
|
|
6258
6413
|
logger.info(`[${this.getProviderName()}] Both query and externalTool exist, keeping both - frontend will decide`);
|
|
6259
6414
|
}
|
|
@@ -6310,10 +6465,24 @@ ${executedToolsText}`);
|
|
|
6310
6465
|
SCHEMA_DOC: schemaDoc || "No database schema available",
|
|
6311
6466
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
6312
6467
|
});
|
|
6313
|
-
const
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6468
|
+
const extractTextContent = (content) => {
|
|
6469
|
+
if (typeof content === "string") return content;
|
|
6470
|
+
if (Array.isArray(content)) {
|
|
6471
|
+
return content.map((item) => {
|
|
6472
|
+
if (typeof item === "string") return item;
|
|
6473
|
+
if (item && typeof item.text === "string") return item.text;
|
|
6474
|
+
if (item && item.content && typeof item.content === "string") return item.content;
|
|
6475
|
+
return JSON.stringify(item, null, 2);
|
|
6476
|
+
}).join("\n\n---\n\n");
|
|
6477
|
+
}
|
|
6478
|
+
if (content && typeof content === "object") {
|
|
6479
|
+
if (typeof content.text === "string") return content.text;
|
|
6480
|
+
return JSON.stringify(content, null, 2);
|
|
6481
|
+
}
|
|
6482
|
+
return String(content);
|
|
6483
|
+
};
|
|
6484
|
+
logger.logLLMPrompt("classifyQuestionCategory", "system", extractTextContent(prompts.system));
|
|
6485
|
+
logger.logLLMPrompt("classifyQuestionCategory", "user", extractTextContent(prompts.user));
|
|
6317
6486
|
const result = await LLM.stream(
|
|
6318
6487
|
{
|
|
6319
6488
|
sys: prompts.system,
|
|
@@ -6529,10 +6698,24 @@ ${executedToolsText}`);
|
|
|
6529
6698
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc,
|
|
6530
6699
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
6531
6700
|
});
|
|
6532
|
-
const
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6701
|
+
const extractText = (content) => {
|
|
6702
|
+
if (typeof content === "string") return content;
|
|
6703
|
+
if (Array.isArray(content)) {
|
|
6704
|
+
return content.map((item) => {
|
|
6705
|
+
if (typeof item === "string") return item;
|
|
6706
|
+
if (item && typeof item.text === "string") return item.text;
|
|
6707
|
+
if (item && item.content && typeof item.content === "string") return item.content;
|
|
6708
|
+
return JSON.stringify(item, null, 2);
|
|
6709
|
+
}).join("\n\n---\n\n");
|
|
6710
|
+
}
|
|
6711
|
+
if (content && typeof content === "object") {
|
|
6712
|
+
if (typeof content.text === "string") return content.text;
|
|
6713
|
+
return JSON.stringify(content, null, 2);
|
|
6714
|
+
}
|
|
6715
|
+
return String(content);
|
|
6716
|
+
};
|
|
6717
|
+
logger.logLLMPrompt("generateTextResponse", "system", extractText(prompts.system));
|
|
6718
|
+
logger.logLLMPrompt("generateTextResponse", "user", extractText(prompts.user));
|
|
6536
6719
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6537
6720
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6538
6721
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6565,7 +6748,13 @@ ${executedToolsText}`);
|
|
|
6565
6748
|
(t) => t.executionType === "immediate" || t.executionType === "deferred" && t.userProvidedData
|
|
6566
6749
|
);
|
|
6567
6750
|
logger.info(`[${this.getProviderName()}] Executable tools: ${executableTools.length} of ${externalTools.length} total`);
|
|
6751
|
+
const addedToolIds = /* @__PURE__ */ new Set();
|
|
6568
6752
|
executableTools.forEach((tool) => {
|
|
6753
|
+
if (addedToolIds.has(tool.id)) {
|
|
6754
|
+
logger.info(`[${this.getProviderName()}] Skipping duplicate tool definition: ${tool.id} (already added)`);
|
|
6755
|
+
return;
|
|
6756
|
+
}
|
|
6757
|
+
addedToolIds.add(tool.id);
|
|
6569
6758
|
logger.info(`[${this.getProviderName()}] Processing executable tool:`, JSON.stringify(tool, null, 2));
|
|
6570
6759
|
const properties = {};
|
|
6571
6760
|
const required = [];
|
|
@@ -6635,7 +6824,7 @@ ${executedToolsText}`);
|
|
|
6635
6824
|
input_schema: inputSchema
|
|
6636
6825
|
});
|
|
6637
6826
|
});
|
|
6638
|
-
logger.info(`[${this.getProviderName()}] Added ${
|
|
6827
|
+
logger.info(`[${this.getProviderName()}] Added ${addedToolIds.size} unique tool definitions from ${executableTools.length} tool calls (${externalTools.length - executableTools.length} deferred tools await form input)`);
|
|
6639
6828
|
logger.info(`[${this.getProviderName()}] Complete tools array:`, JSON.stringify(tools, null, 2));
|
|
6640
6829
|
}
|
|
6641
6830
|
const queryAttempts = /* @__PURE__ */ new Map();
|
|
@@ -7056,7 +7245,10 @@ ${errorMsg}
|
|
|
7056
7245
|
logCollector,
|
|
7057
7246
|
componentStreamCallback,
|
|
7058
7247
|
deferredTools,
|
|
7059
|
-
executedToolsList
|
|
7248
|
+
executedToolsList,
|
|
7249
|
+
collections,
|
|
7250
|
+
userId,
|
|
7251
|
+
userPrompt
|
|
7060
7252
|
);
|
|
7061
7253
|
matchedComponents = matchResult.components;
|
|
7062
7254
|
layoutTitle = matchResult.layoutTitle;
|
|
@@ -7139,7 +7331,6 @@ ${errorMsg}
|
|
|
7139
7331
|
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
7140
7332
|
try {
|
|
7141
7333
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
7142
|
-
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
7143
7334
|
const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
|
|
7144
7335
|
userPrompt,
|
|
7145
7336
|
collections,
|