@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.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
- 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)}`;
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
- \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"}`;
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
- toolId: "${tool.id}"
6355
- toolName: "${tool.name}"
6356
- parameters: ${JSON.stringify(tool.params || {})}
6357
- recordCount: ${recordCount} rows returned
6358
- outputSchema: ${outputSchemaText}${fieldNamesList}`;
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}) - STREAMING TO FRONTEND NOW`);
6468
- logCollector?.info(`\u2713 Answer component: ${answerComponent.name} (${answerComponent.type}) - streaming to frontend at ${streamTime}`);
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
- answerCallback(answerComponent);
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) {