@superatomai/sdk-node 0.0.57 → 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 +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +265 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +265 -26
- 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,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";
|
|
@@ -2409,8 +2509,14 @@ var BookmarksRequestMessageSchema = import_zod3.z.object({
|
|
|
2409
2509
|
type: import_zod3.z.literal("BOOKMARKS"),
|
|
2410
2510
|
payload: BookmarksRequestPayloadSchema
|
|
2411
2511
|
});
|
|
2512
|
+
var ArtifactsQueryFiltersSchema = import_zod3.z.object({
|
|
2513
|
+
createdBy: import_zod3.z.number().optional(),
|
|
2514
|
+
status: import_zod3.z.string().optional(),
|
|
2515
|
+
name: import_zod3.z.string().optional(),
|
|
2516
|
+
deleted: import_zod3.z.boolean().optional()
|
|
2517
|
+
});
|
|
2412
2518
|
var ArtifactsRequestPayloadSchema = import_zod3.z.object({
|
|
2413
|
-
operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne"]),
|
|
2519
|
+
operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
|
|
2414
2520
|
data: import_zod3.z.object({
|
|
2415
2521
|
id: import_zod3.z.number().optional(),
|
|
2416
2522
|
name: import_zod3.z.string().optional(),
|
|
@@ -2418,7 +2524,10 @@ var ArtifactsRequestPayloadSchema = import_zod3.z.object({
|
|
|
2418
2524
|
dsl: import_zod3.z.record(import_zod3.z.any()).optional(),
|
|
2419
2525
|
status: import_zod3.z.string().optional(),
|
|
2420
2526
|
deleted: import_zod3.z.boolean().optional(),
|
|
2421
|
-
limit: import_zod3.z.number().optional()
|
|
2527
|
+
limit: import_zod3.z.number().optional(),
|
|
2528
|
+
// Query operation fields
|
|
2529
|
+
filters: ArtifactsQueryFiltersSchema.optional(),
|
|
2530
|
+
sort: import_zod3.z.enum(["ASC", "DESC"]).optional()
|
|
2422
2531
|
}).optional()
|
|
2423
2532
|
});
|
|
2424
2533
|
var ArtifactsRequestMessageSchema = import_zod3.z.object({
|
|
@@ -5946,7 +6055,10 @@ var BaseLLM = class {
|
|
|
5946
6055
|
* @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
|
|
5947
6056
|
* @returns Object containing matched components, layout title/description, and follow-up actions
|
|
5948
6057
|
*/
|
|
5949
|
-
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
|
|
6058
|
+
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools, collections, userId, userPrompt) {
|
|
6059
|
+
const methodStartTime = Date.now();
|
|
6060
|
+
const methodName = "matchComponentsFromAnalysis";
|
|
6061
|
+
logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("complex")}`);
|
|
5950
6062
|
try {
|
|
5951
6063
|
logger.debug(`[${this.getProviderName()}] Starting component matching from text response`);
|
|
5952
6064
|
let availableComponentsText = "No components available";
|
|
@@ -6006,6 +6118,16 @@ ${fieldsText}`;
|
|
|
6006
6118
|
}
|
|
6007
6119
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
6008
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
|
+
}
|
|
6009
6131
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
6010
6132
|
ANALYSIS_CONTENT: analysisContent,
|
|
6011
6133
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -6013,11 +6135,27 @@ ${fieldsText}`;
|
|
|
6013
6135
|
DATABASE_RULES: databaseRules,
|
|
6014
6136
|
DEFERRED_TOOLS: deferredToolsText,
|
|
6015
6137
|
EXECUTED_TOOLS: executedToolsText,
|
|
6138
|
+
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext,
|
|
6016
6139
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
6017
6140
|
});
|
|
6018
6141
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
6019
|
-
const
|
|
6020
|
-
|
|
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));
|
|
6021
6159
|
logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
|
|
6022
6160
|
${analysisContent}
|
|
6023
6161
|
|
|
@@ -6242,6 +6380,18 @@ ${executedToolsText}`);
|
|
|
6242
6380
|
cleanedProps.query = null;
|
|
6243
6381
|
}
|
|
6244
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
|
+
}
|
|
6245
6395
|
if (cleanedProps.query && cleanedProps.externalTool) {
|
|
6246
6396
|
logger.info(`[${this.getProviderName()}] Both query and externalTool exist, keeping both - frontend will decide`);
|
|
6247
6397
|
}
|
|
@@ -6253,6 +6403,8 @@ ${executedToolsText}`);
|
|
|
6253
6403
|
}
|
|
6254
6404
|
};
|
|
6255
6405
|
}).filter(Boolean);
|
|
6406
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
6407
|
+
logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | components: ${finalComponents.length} | actions: ${actions.length}`);
|
|
6256
6408
|
return {
|
|
6257
6409
|
components: finalComponents,
|
|
6258
6410
|
layoutTitle,
|
|
@@ -6260,8 +6412,9 @@ ${executedToolsText}`);
|
|
|
6260
6412
|
actions
|
|
6261
6413
|
};
|
|
6262
6414
|
} catch (error) {
|
|
6415
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
6263
6416
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
6264
|
-
logger.error(`[${this.getProviderName()}]
|
|
6417
|
+
logger.error(`[${this.getProviderName()}] [TIMING] FAILED ${methodName} in ${methodDuration}ms | error: ${errorMsg}`);
|
|
6265
6418
|
logCollector?.error(`Failed to match components: ${errorMsg}`);
|
|
6266
6419
|
return {
|
|
6267
6420
|
components: [],
|
|
@@ -6276,6 +6429,10 @@ ${executedToolsText}`);
|
|
|
6276
6429
|
* Determines if question is for data analysis, requires external tools, or needs text response
|
|
6277
6430
|
*/
|
|
6278
6431
|
async classifyQuestionCategory(userPrompt, apiKey, logCollector, conversationHistory, externalTools) {
|
|
6432
|
+
const methodStartTime = Date.now();
|
|
6433
|
+
const methodName = "classifyQuestionCategory";
|
|
6434
|
+
const promptPreview = userPrompt.substring(0, 50) + (userPrompt.length > 50 ? "..." : "");
|
|
6435
|
+
logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("simple")} | prompt: "${promptPreview}"`);
|
|
6279
6436
|
try {
|
|
6280
6437
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
6281
6438
|
const availableToolsDoc = externalTools && externalTools.length > 0 ? externalTools.map((tool) => {
|
|
@@ -6291,10 +6448,24 @@ ${executedToolsText}`);
|
|
|
6291
6448
|
SCHEMA_DOC: schemaDoc || "No database schema available",
|
|
6292
6449
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
6293
6450
|
});
|
|
6294
|
-
const
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
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));
|
|
6298
6469
|
const result = await LLM.stream(
|
|
6299
6470
|
{
|
|
6300
6471
|
sys: prompts.system,
|
|
@@ -6319,6 +6490,8 @@ ${executedToolsText}`);
|
|
|
6319
6490
|
confidence: result.confidence
|
|
6320
6491
|
}
|
|
6321
6492
|
);
|
|
6493
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
6494
|
+
logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | category: ${result.category} | confidence: ${result.confidence}% | tools: ${(result.externalTools || []).length}`);
|
|
6322
6495
|
return {
|
|
6323
6496
|
category: result.category || "data_analysis",
|
|
6324
6497
|
externalTools: result.externalTools || [],
|
|
@@ -6327,8 +6500,9 @@ ${executedToolsText}`);
|
|
|
6327
6500
|
confidence: result.confidence || 0
|
|
6328
6501
|
};
|
|
6329
6502
|
} catch (error) {
|
|
6503
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
6330
6504
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
6331
|
-
logger.error(`[${this.getProviderName()}]
|
|
6505
|
+
logger.error(`[${this.getProviderName()}] [TIMING] FAILED ${methodName} in ${methodDuration}ms | error: ${errorMsg}`);
|
|
6332
6506
|
logger.debug(`[${this.getProviderName()}] Category classification error details:`, error);
|
|
6333
6507
|
throw error;
|
|
6334
6508
|
}
|
|
@@ -6339,9 +6513,15 @@ ${executedToolsText}`);
|
|
|
6339
6513
|
* Also adapts the cached text response to match the new question
|
|
6340
6514
|
*/
|
|
6341
6515
|
async adaptUIBlockParameters(currentUserPrompt, originalUserPrompt, matchedUIBlock, apiKey, logCollector, cachedTextResponse) {
|
|
6516
|
+
const methodStartTime = Date.now();
|
|
6517
|
+
const methodName = "adaptUIBlockParameters";
|
|
6518
|
+
const promptPreview = currentUserPrompt.substring(0, 50) + (currentUserPrompt.length > 50 ? "..." : "");
|
|
6519
|
+
logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("complex")} | prompt: "${promptPreview}"`);
|
|
6342
6520
|
try {
|
|
6343
6521
|
const component = matchedUIBlock?.generatedComponentMetadata || matchedUIBlock?.component;
|
|
6344
6522
|
if (!matchedUIBlock || !component) {
|
|
6523
|
+
const methodDuration2 = Date.now() - methodStartTime;
|
|
6524
|
+
logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration2}ms | result: no component found`);
|
|
6345
6525
|
return {
|
|
6346
6526
|
success: false,
|
|
6347
6527
|
explanation: "No component found in matched UI block"
|
|
@@ -6374,9 +6554,8 @@ ${executedToolsText}`);
|
|
|
6374
6554
|
// Parse as JSON
|
|
6375
6555
|
);
|
|
6376
6556
|
if (!result.success) {
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
);
|
|
6557
|
+
const methodDuration2 = Date.now() - methodStartTime;
|
|
6558
|
+
logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration2}ms | result: adaptation failed - ${result.reason}`);
|
|
6380
6559
|
logCollector?.warn(
|
|
6381
6560
|
"Could not adapt matched UI block",
|
|
6382
6561
|
"explanation",
|
|
@@ -6401,6 +6580,8 @@ ${executedToolsText}`);
|
|
|
6401
6580
|
componentType: result.adaptedComponent?.type
|
|
6402
6581
|
}
|
|
6403
6582
|
);
|
|
6583
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
6584
|
+
logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | result: success | changes: ${(result.parametersChanged || []).length}`);
|
|
6404
6585
|
return {
|
|
6405
6586
|
success: true,
|
|
6406
6587
|
adaptedComponent: result.adaptedComponent,
|
|
@@ -6409,8 +6590,9 @@ ${executedToolsText}`);
|
|
|
6409
6590
|
explanation: result.explanation || "Parameters adapted successfully"
|
|
6410
6591
|
};
|
|
6411
6592
|
} catch (error) {
|
|
6593
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
6412
6594
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
6413
|
-
logger.error(`[${this.getProviderName()}]
|
|
6595
|
+
logger.error(`[${this.getProviderName()}] [TIMING] FAILED ${methodName} in ${methodDuration}ms | error: ${errorMsg}`);
|
|
6414
6596
|
logger.debug(`[${this.getProviderName()}] Adaptation error details:`, error);
|
|
6415
6597
|
return {
|
|
6416
6598
|
success: false,
|
|
@@ -6431,6 +6613,10 @@ ${executedToolsText}`);
|
|
|
6431
6613
|
* @param userId - Optional user ID for fetching user-specific knowledge base nodes
|
|
6432
6614
|
*/
|
|
6433
6615
|
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools, category, userId) {
|
|
6616
|
+
const methodStartTime = Date.now();
|
|
6617
|
+
const methodName = "generateTextResponse";
|
|
6618
|
+
const promptPreview = userPrompt.substring(0, 50) + (userPrompt.length > 50 ? "..." : "");
|
|
6619
|
+
logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("complex")} | category: ${category} | prompt: "${promptPreview}"`);
|
|
6434
6620
|
const errors = [];
|
|
6435
6621
|
logger.debug(`[${this.getProviderName()}] Starting text response generation`);
|
|
6436
6622
|
logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
|
|
@@ -6495,10 +6681,24 @@ ${executedToolsText}`);
|
|
|
6495
6681
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc,
|
|
6496
6682
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
6497
6683
|
});
|
|
6498
|
-
const
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
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));
|
|
6502
6702
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6503
6703
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6504
6704
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6944,7 +7144,8 @@ ${errorMsg}
|
|
|
6944
7144
|
logger.info(`[${this.getProviderName()}] Text response stream completed`);
|
|
6945
7145
|
const textResponse = fullStreamedText || result || "I apologize, but I was unable to generate a response.";
|
|
6946
7146
|
if (maxAttemptsReached) {
|
|
6947
|
-
|
|
7147
|
+
const methodDuration2 = Date.now() - methodStartTime;
|
|
7148
|
+
logger.warn(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration2}ms | result: max attempts reached`);
|
|
6948
7149
|
logCollector?.error("Failed to generate valid query after maximum attempts");
|
|
6949
7150
|
return {
|
|
6950
7151
|
success: false,
|
|
@@ -7021,7 +7222,10 @@ ${errorMsg}
|
|
|
7021
7222
|
logCollector,
|
|
7022
7223
|
componentStreamCallback,
|
|
7023
7224
|
deferredTools,
|
|
7024
|
-
executedToolsList
|
|
7225
|
+
executedToolsList,
|
|
7226
|
+
collections,
|
|
7227
|
+
userId,
|
|
7228
|
+
userPrompt
|
|
7025
7229
|
);
|
|
7026
7230
|
matchedComponents = matchResult.components;
|
|
7027
7231
|
layoutTitle = matchResult.layoutTitle;
|
|
@@ -7047,6 +7251,8 @@ ${errorMsg}
|
|
|
7047
7251
|
}
|
|
7048
7252
|
};
|
|
7049
7253
|
}
|
|
7254
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
7255
|
+
logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | result: success | components: ${matchedComponents.length} | actions: ${actions.length}`);
|
|
7050
7256
|
return {
|
|
7051
7257
|
success: true,
|
|
7052
7258
|
data: {
|
|
@@ -7058,8 +7264,9 @@ ${errorMsg}
|
|
|
7058
7264
|
errors: []
|
|
7059
7265
|
};
|
|
7060
7266
|
} catch (error) {
|
|
7267
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
7061
7268
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
7062
|
-
logger.error(`[${this.getProviderName()}]
|
|
7269
|
+
logger.error(`[${this.getProviderName()}] [TIMING] FAILED ${methodName} in ${methodDuration}ms | error: ${errorMsg}`);
|
|
7063
7270
|
logCollector?.error(`Error generating text response: ${errorMsg}`);
|
|
7064
7271
|
userPromptErrorLogger.logLlmError(
|
|
7065
7272
|
this.getProviderName(),
|
|
@@ -7101,7 +7308,6 @@ ${errorMsg}
|
|
|
7101
7308
|
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
7102
7309
|
try {
|
|
7103
7310
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
7104
|
-
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
7105
7311
|
const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
|
|
7106
7312
|
userPrompt,
|
|
7107
7313
|
collections,
|
|
@@ -7313,6 +7519,10 @@ ${errorMsg}
|
|
|
7313
7519
|
* For general/conversational questions without components, pass textResponse instead
|
|
7314
7520
|
*/
|
|
7315
7521
|
async generateNextQuestions(originalUserPrompt, component, componentData, apiKey, logCollector, conversationHistory, textResponse) {
|
|
7522
|
+
const methodStartTime = Date.now();
|
|
7523
|
+
const methodName = "generateNextQuestions";
|
|
7524
|
+
const promptPreview = originalUserPrompt.substring(0, 50) + (originalUserPrompt.length > 50 ? "..." : "");
|
|
7525
|
+
logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("simple")} | prompt: "${promptPreview}"`);
|
|
7316
7526
|
try {
|
|
7317
7527
|
let component_info;
|
|
7318
7528
|
if (component) {
|
|
@@ -7361,10 +7571,13 @@ ${errorMsg}
|
|
|
7361
7571
|
questions: nextQuestions
|
|
7362
7572
|
}
|
|
7363
7573
|
);
|
|
7574
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
7575
|
+
logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | questions: ${nextQuestions.length}`);
|
|
7364
7576
|
return nextQuestions;
|
|
7365
7577
|
} catch (error) {
|
|
7578
|
+
const methodDuration = Date.now() - methodStartTime;
|
|
7366
7579
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
7367
|
-
logger.error(`[${this.getProviderName()}]
|
|
7580
|
+
logger.error(`[${this.getProviderName()}] [TIMING] FAILED ${methodName} in ${methodDuration}ms | error: ${errorMsg}`);
|
|
7368
7581
|
logger.debug(`[${this.getProviderName()}] Next questions generation error details:`, error);
|
|
7369
7582
|
logCollector?.error(`Error generating next questions: ${errorMsg}`);
|
|
7370
7583
|
return [];
|
|
@@ -10372,6 +10585,8 @@ async function handleArtifactsRequest(data, collections, sendMessage) {
|
|
|
10372
10585
|
const status = requestData?.status;
|
|
10373
10586
|
const deleted = requestData?.deleted;
|
|
10374
10587
|
const limit = requestData?.limit;
|
|
10588
|
+
const filters = requestData?.filters;
|
|
10589
|
+
const sort = requestData?.sort;
|
|
10375
10590
|
switch (operation) {
|
|
10376
10591
|
case "create":
|
|
10377
10592
|
await handleCreate6(id, name, createdBy, dsl, status, executeCollection, sendMessage, from.id);
|
|
@@ -10388,6 +10603,9 @@ async function handleArtifactsRequest(data, collections, sendMessage) {
|
|
|
10388
10603
|
case "getOne":
|
|
10389
10604
|
await handleGetOne6(id, artifactId, executeCollection, sendMessage, from.id);
|
|
10390
10605
|
break;
|
|
10606
|
+
case "query":
|
|
10607
|
+
await handleQuery6(id, { filters, limit, sort }, executeCollection, sendMessage, from.id);
|
|
10608
|
+
break;
|
|
10391
10609
|
default:
|
|
10392
10610
|
sendResponse8(id, {
|
|
10393
10611
|
success: false,
|
|
@@ -10511,6 +10729,27 @@ async function handleGetOne6(id, artifactId, executeCollection, sendMessage, cli
|
|
|
10511
10729
|
}, sendMessage, clientId);
|
|
10512
10730
|
}
|
|
10513
10731
|
}
|
|
10732
|
+
async function handleQuery6(id, queryParams, executeCollection, sendMessage, clientId) {
|
|
10733
|
+
try {
|
|
10734
|
+
const result = await executeCollection("artifacts", "query", {
|
|
10735
|
+
filters: queryParams.filters,
|
|
10736
|
+
limit: queryParams.limit || 50,
|
|
10737
|
+
sort: queryParams.sort || "DESC"
|
|
10738
|
+
});
|
|
10739
|
+
sendResponse8(id, {
|
|
10740
|
+
success: true,
|
|
10741
|
+
data: result.data,
|
|
10742
|
+
count: result.count,
|
|
10743
|
+
message: `Query returned ${result.count} artifacts`
|
|
10744
|
+
}, sendMessage, clientId);
|
|
10745
|
+
logger.info(`Query artifacts (count: ${result.count})`);
|
|
10746
|
+
} catch (error) {
|
|
10747
|
+
sendResponse8(id, {
|
|
10748
|
+
success: false,
|
|
10749
|
+
error: error instanceof Error ? error.message : "Failed to query artifacts"
|
|
10750
|
+
}, sendMessage, clientId);
|
|
10751
|
+
}
|
|
10752
|
+
}
|
|
10514
10753
|
function sendResponse8(id, res, sendMessage, clientId) {
|
|
10515
10754
|
const response = {
|
|
10516
10755
|
id: id || "unknown",
|
|
@@ -11037,7 +11276,7 @@ async function handleMenusRequest(data, collections, sendMessage) {
|
|
|
11037
11276
|
await handleGetHierarchy(id, executeCollection, sendMessage, from.id);
|
|
11038
11277
|
break;
|
|
11039
11278
|
case "query":
|
|
11040
|
-
await
|
|
11279
|
+
await handleQuery7(id, filters, limit, sort, executeCollection, sendMessage, from.id);
|
|
11041
11280
|
break;
|
|
11042
11281
|
case "reorder":
|
|
11043
11282
|
await handleReorder(id, items, executeCollection, sendMessage, from.id);
|
|
@@ -11249,7 +11488,7 @@ async function handleGetHierarchy(id, executeCollection, sendMessage, clientId)
|
|
|
11249
11488
|
}, sendMessage, clientId);
|
|
11250
11489
|
}
|
|
11251
11490
|
}
|
|
11252
|
-
async function
|
|
11491
|
+
async function handleQuery7(id, filters, limit, sort, executeCollection, sendMessage, clientId) {
|
|
11253
11492
|
try {
|
|
11254
11493
|
const result = await executeCollection("menus", "query", {
|
|
11255
11494
|
filters: filters || {},
|