@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.js
CHANGED
|
@@ -6372,11 +6372,11 @@ Fixed SQL query:`;
|
|
|
6372
6372
|
logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools to component matching`);
|
|
6373
6373
|
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) => {
|
|
6374
6374
|
return `${idx + 1}. **${tool.name}**
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
6375
|
+
toolId: "${tool.id}" (USE THIS EXACT VALUE - do not modify!)
|
|
6376
|
+
toolName: "${tool.name}"
|
|
6377
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
6378
|
+
requiredFields:
|
|
6379
|
+
${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
6380
6380
|
}).join("\n\n");
|
|
6381
6381
|
}
|
|
6382
6382
|
let executedToolsText = "No external tools were executed for data fetching.";
|
|
@@ -6392,8 +6392,8 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
|
6392
6392
|
const numericFields = fields.filter((f) => f.type === "number").map((f) => f.name);
|
|
6393
6393
|
const stringFields = fields.filter((f) => f.type === "string").map((f) => f.name);
|
|
6394
6394
|
fieldNamesList = `
|
|
6395
|
-
|
|
6396
|
-
|
|
6395
|
+
\u{1F4CA} NUMERIC FIELDS (use for yAxisKey, valueKey, aggregationField): ${numericFields.join(", ") || "none"}
|
|
6396
|
+
\u{1F4DD} STRING FIELDS (use for xAxisKey, groupBy, nameKey): ${stringFields.join(", ") || "none"}`;
|
|
6397
6397
|
const fieldsText = fields.map(
|
|
6398
6398
|
(f) => ` "${f.name}" (${f.type}): ${f.description}`
|
|
6399
6399
|
).join("\n");
|
|
@@ -6402,11 +6402,11 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
|
6402
6402
|
${fieldsText}`;
|
|
6403
6403
|
}
|
|
6404
6404
|
return `${idx + 1}. **${tool.name}**
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6405
|
+
toolId: "${tool.id}"
|
|
6406
|
+
toolName: "${tool.name}"
|
|
6407
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
6408
|
+
recordCount: ${recordCount} rows returned
|
|
6409
|
+
outputSchema: ${outputSchemaText}${fieldNamesList}`;
|
|
6410
6410
|
}).join("\n\n");
|
|
6411
6411
|
}
|
|
6412
6412
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
@@ -6457,6 +6457,7 @@ ${executedToolsText}`);
|
|
|
6457
6457
|
logCollector?.info("Matching components from text response...");
|
|
6458
6458
|
let fullResponseText = "";
|
|
6459
6459
|
let answerComponentExtracted = false;
|
|
6460
|
+
let validatedAnswerComponent = null;
|
|
6460
6461
|
const answerCallback = componentStreamCallback;
|
|
6461
6462
|
const partialCallback = answerCallback ? (chunk) => {
|
|
6462
6463
|
fullResponseText += chunk;
|
|
@@ -6515,8 +6516,8 @@ ${executedToolsText}`);
|
|
|
6515
6516
|
}
|
|
6516
6517
|
};
|
|
6517
6518
|
const streamTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
6518
|
-
logger.info(`[${this.getProviderName()}] \u2713 [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type})
|
|
6519
|
-
logCollector?.info(`\u2713 Answer component: ${answerComponent.name} (${answerComponent.type}) -
|
|
6519
|
+
logger.info(`[${this.getProviderName()}] \u2713 [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type})`);
|
|
6520
|
+
logCollector?.info(`\u2713 Answer component: ${answerComponent.name} (${answerComponent.type}) - detected at ${streamTime}`);
|
|
6520
6521
|
if (answerComponentData.props?.query) {
|
|
6521
6522
|
logCollector?.logQuery(
|
|
6522
6523
|
"Answer component query",
|
|
@@ -6524,7 +6525,79 @@ ${executedToolsText}`);
|
|
|
6524
6525
|
{ componentName: answerComponent.name, componentType: answerComponent.type, reasoning: answerComponentData.reasoning }
|
|
6525
6526
|
);
|
|
6526
6527
|
}
|
|
6527
|
-
|
|
6528
|
+
const answerQuery = answerComponent.props?.query;
|
|
6529
|
+
logger.info(`[${this.getProviderName()}] Answer component detected: ${answerComponent.name} (${answerComponent.type}), hasQuery: ${!!answerQuery}, hasDbExecute: ${!!collections?.["database"]?.["execute"]}`);
|
|
6530
|
+
if (answerQuery && collections?.["database"]?.["execute"]) {
|
|
6531
|
+
(async () => {
|
|
6532
|
+
const MAX_RETRIES = 3;
|
|
6533
|
+
let attempts = 0;
|
|
6534
|
+
let validated = false;
|
|
6535
|
+
let currentQuery = answerQuery;
|
|
6536
|
+
let currentQueryStr = typeof answerQuery === "string" ? answerQuery : answerQuery?.sql || "";
|
|
6537
|
+
let lastError = "";
|
|
6538
|
+
logger.info(`[${this.getProviderName()}] Validating answer component query before streaming...`);
|
|
6539
|
+
while (attempts < MAX_RETRIES && !validated) {
|
|
6540
|
+
attempts++;
|
|
6541
|
+
try {
|
|
6542
|
+
const cacheKey = this.getQueryCacheKey(currentQuery);
|
|
6543
|
+
if (cacheKey) {
|
|
6544
|
+
logger.debug(`[${this.getProviderName()}] Answer component query validation attempt ${attempts}/${MAX_RETRIES}`);
|
|
6545
|
+
const result2 = await collections["database"]["execute"]({ sql: cacheKey });
|
|
6546
|
+
queryCache.set(cacheKey, result2);
|
|
6547
|
+
validated = true;
|
|
6548
|
+
if (currentQuery !== answerQuery) {
|
|
6549
|
+
answerComponent.props.query = currentQuery;
|
|
6550
|
+
}
|
|
6551
|
+
validatedAnswerComponent = {
|
|
6552
|
+
componentId: answerComponentData.componentId,
|
|
6553
|
+
validatedQuery: currentQuery
|
|
6554
|
+
};
|
|
6555
|
+
logger.info(`[${this.getProviderName()}] \u2713 Answer component query validated (attempt ${attempts}) - STREAMING TO FRONTEND NOW`);
|
|
6556
|
+
logCollector?.info(`\u2713 Answer component query validated - streaming to frontend`);
|
|
6557
|
+
logger.info(`[${this.getProviderName()}] Calling answerCallback for: ${answerComponent.name}`);
|
|
6558
|
+
answerCallback(answerComponent);
|
|
6559
|
+
logger.info(`[${this.getProviderName()}] answerCallback completed for: ${answerComponent.name}`);
|
|
6560
|
+
}
|
|
6561
|
+
} catch (validationError) {
|
|
6562
|
+
lastError = validationError instanceof Error ? validationError.message : String(validationError);
|
|
6563
|
+
logger.warn(`[${this.getProviderName()}] Answer component query validation failed (attempt ${attempts}/${MAX_RETRIES}): ${lastError}`);
|
|
6564
|
+
if (attempts < MAX_RETRIES) {
|
|
6565
|
+
try {
|
|
6566
|
+
logger.info(`[${this.getProviderName()}] Requesting LLM to fix answer component query...`);
|
|
6567
|
+
const fixedQueryStr = await this.requestQueryFix(
|
|
6568
|
+
currentQueryStr,
|
|
6569
|
+
lastError,
|
|
6570
|
+
{
|
|
6571
|
+
name: answerComponent.name,
|
|
6572
|
+
type: answerComponent.type,
|
|
6573
|
+
title: answerComponent.props?.title
|
|
6574
|
+
},
|
|
6575
|
+
apiKey
|
|
6576
|
+
);
|
|
6577
|
+
if (typeof currentQuery === "string") {
|
|
6578
|
+
currentQuery = fixedQueryStr;
|
|
6579
|
+
} else {
|
|
6580
|
+
currentQuery = { ...currentQuery, sql: fixedQueryStr };
|
|
6581
|
+
}
|
|
6582
|
+
currentQueryStr = fixedQueryStr;
|
|
6583
|
+
logger.info(`[${this.getProviderName()}] LLM provided fixed query for answer component, retrying...`);
|
|
6584
|
+
} catch (fixError) {
|
|
6585
|
+
const fixErrorMsg = fixError instanceof Error ? fixError.message : String(fixError);
|
|
6586
|
+
logger.error(`[${this.getProviderName()}] Failed to get LLM query fix for answer component: ${fixErrorMsg}`);
|
|
6587
|
+
break;
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
}
|
|
6591
|
+
}
|
|
6592
|
+
if (!validated) {
|
|
6593
|
+
logger.warn(`[${this.getProviderName()}] Answer component query validation failed after ${attempts} attempts - skipping early stream`);
|
|
6594
|
+
logCollector?.warn(`Answer component query validation failed: ${lastError} - will be handled in batch validation`);
|
|
6595
|
+
}
|
|
6596
|
+
})();
|
|
6597
|
+
} else {
|
|
6598
|
+
logger.info(`[${this.getProviderName()}] Answer component has no query - STREAMING TO FRONTEND NOW`);
|
|
6599
|
+
answerCallback(answerComponent);
|
|
6600
|
+
}
|
|
6528
6601
|
answerComponentExtracted = true;
|
|
6529
6602
|
}
|
|
6530
6603
|
}
|
|
@@ -6578,6 +6651,10 @@ ${executedToolsText}`);
|
|
|
6578
6651
|
return null;
|
|
6579
6652
|
}
|
|
6580
6653
|
let cleanedProps = { ...mc.props };
|
|
6654
|
+
if (validatedAnswerComponent && mc.componentId === validatedAnswerComponent.componentId) {
|
|
6655
|
+
logger.info(`[${this.getProviderName()}] Using pre-validated query for answer component: ${mc.componentId}`);
|
|
6656
|
+
cleanedProps.query = validatedAnswerComponent.validatedQuery;
|
|
6657
|
+
}
|
|
6581
6658
|
if (cleanedProps.externalTool) {
|
|
6582
6659
|
const toolId = cleanedProps.externalTool.toolId;
|
|
6583
6660
|
const validToolIds = (executedTools || []).map((t) => t.id);
|
|
@@ -7623,11 +7700,14 @@ ${errorMsg}
|
|
|
7623
7700
|
logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions for general question`);
|
|
7624
7701
|
} else if (components && components.length > 0) {
|
|
7625
7702
|
logger.info(`[${this.getProviderName()}] Matching components from text response...`);
|
|
7703
|
+
logger.info(`[${this.getProviderName()}] componentStreamCallback setup: wrappedStreamCallback=${!!wrappedStreamCallback}, category=${category}`);
|
|
7626
7704
|
const componentStreamCallback = wrappedStreamCallback && category !== "data_modification" ? (component) => {
|
|
7705
|
+
logger.info(`[${this.getProviderName()}] componentStreamCallback INVOKED for: ${component.name} (${component.type})`);
|
|
7627
7706
|
const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
|
|
7628
7707
|
wrappedStreamCallback(answerMarker);
|
|
7629
7708
|
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
7630
7709
|
} : void 0;
|
|
7710
|
+
logger.info(`[${this.getProviderName()}] componentStreamCallback created: ${!!componentStreamCallback}`);
|
|
7631
7711
|
const deferredTools = externalTools?.filter((t) => {
|
|
7632
7712
|
if (t.executionType === "deferred" && !t.userProvidedData) return true;
|
|
7633
7713
|
if (category === "data_modification" && !t.userProvidedData) {
|