@superatomai/sdk-node 0.0.63 → 0.0.64
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.js +95 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +95 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6321,11 +6321,11 @@ Fixed SQL query:`;
|
|
|
6321
6321
|
logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools to component matching`);
|
|
6322
6322
|
deferredToolsText = "The following external tools need user input via a Form component.\n**IMPORTANT: Use these EXACT values when generating Form externalTool prop.**\n\n" + deferredTools.map((tool, idx) => {
|
|
6323
6323
|
return `${idx + 1}. **${tool.name}**
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
6324
|
+
toolId: "${tool.id}" (USE THIS EXACT VALUE - do not modify!)
|
|
6325
|
+
toolName: "${tool.name}"
|
|
6326
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
6327
|
+
requiredFields:
|
|
6328
|
+
${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
6329
6329
|
}).join("\n\n");
|
|
6330
6330
|
}
|
|
6331
6331
|
let executedToolsText = "No external tools were executed for data fetching.";
|
|
@@ -6341,8 +6341,8 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
|
6341
6341
|
const numericFields = fields.filter((f) => f.type === "number").map((f) => f.name);
|
|
6342
6342
|
const stringFields = fields.filter((f) => f.type === "string").map((f) => f.name);
|
|
6343
6343
|
fieldNamesList = `
|
|
6344
|
-
|
|
6345
|
-
|
|
6344
|
+
\u{1F4CA} NUMERIC FIELDS (use for yAxisKey, valueKey, aggregationField): ${numericFields.join(", ") || "none"}
|
|
6345
|
+
\u{1F4DD} STRING FIELDS (use for xAxisKey, groupBy, nameKey): ${stringFields.join(", ") || "none"}`;
|
|
6346
6346
|
const fieldsText = fields.map(
|
|
6347
6347
|
(f) => ` "${f.name}" (${f.type}): ${f.description}`
|
|
6348
6348
|
).join("\n");
|
|
@@ -6351,11 +6351,11 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
|
6351
6351
|
${fieldsText}`;
|
|
6352
6352
|
}
|
|
6353
6353
|
return `${idx + 1}. **${tool.name}**
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6354
|
+
toolId: "${tool.id}"
|
|
6355
|
+
toolName: "${tool.name}"
|
|
6356
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
6357
|
+
recordCount: ${recordCount} rows returned
|
|
6358
|
+
outputSchema: ${outputSchemaText}${fieldNamesList}`;
|
|
6359
6359
|
}).join("\n\n");
|
|
6360
6360
|
}
|
|
6361
6361
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
@@ -6406,6 +6406,7 @@ ${executedToolsText}`);
|
|
|
6406
6406
|
logCollector?.info("Matching components from text response...");
|
|
6407
6407
|
let fullResponseText = "";
|
|
6408
6408
|
let answerComponentExtracted = false;
|
|
6409
|
+
let validatedAnswerComponent = null;
|
|
6409
6410
|
const answerCallback = componentStreamCallback;
|
|
6410
6411
|
const partialCallback = answerCallback ? (chunk) => {
|
|
6411
6412
|
fullResponseText += chunk;
|
|
@@ -6464,8 +6465,8 @@ ${executedToolsText}`);
|
|
|
6464
6465
|
}
|
|
6465
6466
|
};
|
|
6466
6467
|
const streamTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
6467
|
-
logger.info(`[${this.getProviderName()}] \u2713 [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type})
|
|
6468
|
-
logCollector?.info(`\u2713 Answer component: ${answerComponent.name} (${answerComponent.type}) -
|
|
6468
|
+
logger.info(`[${this.getProviderName()}] \u2713 [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type})`);
|
|
6469
|
+
logCollector?.info(`\u2713 Answer component: ${answerComponent.name} (${answerComponent.type}) - detected at ${streamTime}`);
|
|
6469
6470
|
if (answerComponentData.props?.query) {
|
|
6470
6471
|
logCollector?.logQuery(
|
|
6471
6472
|
"Answer component query",
|
|
@@ -6473,7 +6474,79 @@ ${executedToolsText}`);
|
|
|
6473
6474
|
{ componentName: answerComponent.name, componentType: answerComponent.type, reasoning: answerComponentData.reasoning }
|
|
6474
6475
|
);
|
|
6475
6476
|
}
|
|
6476
|
-
|
|
6477
|
+
const answerQuery = answerComponent.props?.query;
|
|
6478
|
+
logger.info(`[${this.getProviderName()}] Answer component detected: ${answerComponent.name} (${answerComponent.type}), hasQuery: ${!!answerQuery}, hasDbExecute: ${!!collections?.["database"]?.["execute"]}`);
|
|
6479
|
+
if (answerQuery && collections?.["database"]?.["execute"]) {
|
|
6480
|
+
(async () => {
|
|
6481
|
+
const MAX_RETRIES = 3;
|
|
6482
|
+
let attempts = 0;
|
|
6483
|
+
let validated = false;
|
|
6484
|
+
let currentQuery = answerQuery;
|
|
6485
|
+
let currentQueryStr = typeof answerQuery === "string" ? answerQuery : answerQuery?.sql || "";
|
|
6486
|
+
let lastError = "";
|
|
6487
|
+
logger.info(`[${this.getProviderName()}] Validating answer component query before streaming...`);
|
|
6488
|
+
while (attempts < MAX_RETRIES && !validated) {
|
|
6489
|
+
attempts++;
|
|
6490
|
+
try {
|
|
6491
|
+
const cacheKey = this.getQueryCacheKey(currentQuery);
|
|
6492
|
+
if (cacheKey) {
|
|
6493
|
+
logger.debug(`[${this.getProviderName()}] Answer component query validation attempt ${attempts}/${MAX_RETRIES}`);
|
|
6494
|
+
const result2 = await collections["database"]["execute"]({ sql: cacheKey });
|
|
6495
|
+
queryCache.set(cacheKey, result2);
|
|
6496
|
+
validated = true;
|
|
6497
|
+
if (currentQuery !== answerQuery) {
|
|
6498
|
+
answerComponent.props.query = currentQuery;
|
|
6499
|
+
}
|
|
6500
|
+
validatedAnswerComponent = {
|
|
6501
|
+
componentId: answerComponentData.componentId,
|
|
6502
|
+
validatedQuery: currentQuery
|
|
6503
|
+
};
|
|
6504
|
+
logger.info(`[${this.getProviderName()}] \u2713 Answer component query validated (attempt ${attempts}) - STREAMING TO FRONTEND NOW`);
|
|
6505
|
+
logCollector?.info(`\u2713 Answer component query validated - streaming to frontend`);
|
|
6506
|
+
logger.info(`[${this.getProviderName()}] Calling answerCallback for: ${answerComponent.name}`);
|
|
6507
|
+
answerCallback(answerComponent);
|
|
6508
|
+
logger.info(`[${this.getProviderName()}] answerCallback completed for: ${answerComponent.name}`);
|
|
6509
|
+
}
|
|
6510
|
+
} catch (validationError) {
|
|
6511
|
+
lastError = validationError instanceof Error ? validationError.message : String(validationError);
|
|
6512
|
+
logger.warn(`[${this.getProviderName()}] Answer component query validation failed (attempt ${attempts}/${MAX_RETRIES}): ${lastError}`);
|
|
6513
|
+
if (attempts < MAX_RETRIES) {
|
|
6514
|
+
try {
|
|
6515
|
+
logger.info(`[${this.getProviderName()}] Requesting LLM to fix answer component query...`);
|
|
6516
|
+
const fixedQueryStr = await this.requestQueryFix(
|
|
6517
|
+
currentQueryStr,
|
|
6518
|
+
lastError,
|
|
6519
|
+
{
|
|
6520
|
+
name: answerComponent.name,
|
|
6521
|
+
type: answerComponent.type,
|
|
6522
|
+
title: answerComponent.props?.title
|
|
6523
|
+
},
|
|
6524
|
+
apiKey
|
|
6525
|
+
);
|
|
6526
|
+
if (typeof currentQuery === "string") {
|
|
6527
|
+
currentQuery = fixedQueryStr;
|
|
6528
|
+
} else {
|
|
6529
|
+
currentQuery = { ...currentQuery, sql: fixedQueryStr };
|
|
6530
|
+
}
|
|
6531
|
+
currentQueryStr = fixedQueryStr;
|
|
6532
|
+
logger.info(`[${this.getProviderName()}] LLM provided fixed query for answer component, retrying...`);
|
|
6533
|
+
} catch (fixError) {
|
|
6534
|
+
const fixErrorMsg = fixError instanceof Error ? fixError.message : String(fixError);
|
|
6535
|
+
logger.error(`[${this.getProviderName()}] Failed to get LLM query fix for answer component: ${fixErrorMsg}`);
|
|
6536
|
+
break;
|
|
6537
|
+
}
|
|
6538
|
+
}
|
|
6539
|
+
}
|
|
6540
|
+
}
|
|
6541
|
+
if (!validated) {
|
|
6542
|
+
logger.warn(`[${this.getProviderName()}] Answer component query validation failed after ${attempts} attempts - skipping early stream`);
|
|
6543
|
+
logCollector?.warn(`Answer component query validation failed: ${lastError} - will be handled in batch validation`);
|
|
6544
|
+
}
|
|
6545
|
+
})();
|
|
6546
|
+
} else {
|
|
6547
|
+
logger.info(`[${this.getProviderName()}] Answer component has no query - STREAMING TO FRONTEND NOW`);
|
|
6548
|
+
answerCallback(answerComponent);
|
|
6549
|
+
}
|
|
6477
6550
|
answerComponentExtracted = true;
|
|
6478
6551
|
}
|
|
6479
6552
|
}
|
|
@@ -6527,6 +6600,10 @@ ${executedToolsText}`);
|
|
|
6527
6600
|
return null;
|
|
6528
6601
|
}
|
|
6529
6602
|
let cleanedProps = { ...mc.props };
|
|
6603
|
+
if (validatedAnswerComponent && mc.componentId === validatedAnswerComponent.componentId) {
|
|
6604
|
+
logger.info(`[${this.getProviderName()}] Using pre-validated query for answer component: ${mc.componentId}`);
|
|
6605
|
+
cleanedProps.query = validatedAnswerComponent.validatedQuery;
|
|
6606
|
+
}
|
|
6530
6607
|
if (cleanedProps.externalTool) {
|
|
6531
6608
|
const toolId = cleanedProps.externalTool.toolId;
|
|
6532
6609
|
const validToolIds = (executedTools || []).map((t) => t.id);
|
|
@@ -7572,11 +7649,14 @@ ${errorMsg}
|
|
|
7572
7649
|
logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions for general question`);
|
|
7573
7650
|
} else if (components && components.length > 0) {
|
|
7574
7651
|
logger.info(`[${this.getProviderName()}] Matching components from text response...`);
|
|
7652
|
+
logger.info(`[${this.getProviderName()}] componentStreamCallback setup: wrappedStreamCallback=${!!wrappedStreamCallback}, category=${category}`);
|
|
7575
7653
|
const componentStreamCallback = wrappedStreamCallback && category !== "data_modification" ? (component) => {
|
|
7654
|
+
logger.info(`[${this.getProviderName()}] componentStreamCallback INVOKED for: ${component.name} (${component.type})`);
|
|
7576
7655
|
const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
|
|
7577
7656
|
wrappedStreamCallback(answerMarker);
|
|
7578
7657
|
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
7579
7658
|
} : void 0;
|
|
7659
|
+
logger.info(`[${this.getProviderName()}] componentStreamCallback created: ${!!componentStreamCallback}`);
|
|
7580
7660
|
const deferredTools = externalTools?.filter((t) => {
|
|
7581
7661
|
if (t.executionType === "deferred" && !t.userProvidedData) return true;
|
|
7582
7662
|
if (category === "data_modification" && !t.userProvidedData) {
|