@superatomai/sdk-node 0.0.77 → 0.0.78

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
@@ -695,6 +695,67 @@ var DashCompRequestMessageSchema = z3.object({
695
695
  type: z3.literal("DASH_COMP_REQ"),
696
696
  payload: DashCompRequestPayloadSchema
697
697
  });
698
+ var SchemaColumnStatisticsSchema = z3.object({
699
+ distinct: z3.number().optional(),
700
+ min: z3.number().optional(),
701
+ max: z3.number().optional()
702
+ });
703
+ var SchemaColumnSchema = z3.object({
704
+ name: z3.string(),
705
+ type: z3.string(),
706
+ nativeType: z3.string(),
707
+ nullable: z3.boolean(),
708
+ description: z3.string(),
709
+ statistics: SchemaColumnStatisticsSchema.optional(),
710
+ cardinality: z3.enum(["unique", "high", "medium", "low"]).optional(),
711
+ sampleValues: z3.array(z3.string()).optional()
712
+ });
713
+ var SchemaTableSchema = z3.object({
714
+ name: z3.string(),
715
+ fullName: z3.string(),
716
+ rowCount: z3.number(),
717
+ description: z3.string(),
718
+ columns: z3.array(SchemaColumnSchema)
719
+ });
720
+ var SchemaRelationshipSchema = z3.object({
721
+ from: z3.string(),
722
+ to: z3.string(),
723
+ type: z3.string(),
724
+ keys: z3.array(z3.string())
725
+ });
726
+ var DatabaseSchemaSchema = z3.object({
727
+ database: z3.string(),
728
+ databaseType: z3.string().optional(),
729
+ schema: z3.string(),
730
+ description: z3.string(),
731
+ tables: z3.array(SchemaTableSchema),
732
+ relationships: z3.array(SchemaRelationshipSchema).optional()
733
+ });
734
+ var SchemaRequestPayloadSchema = z3.object({
735
+ /** If true, returns the formatted documentation string in addition to raw JSON */
736
+ formatted: z3.boolean().optional()
737
+ });
738
+ var SchemaRequestMessageSchema = z3.object({
739
+ id: z3.string(),
740
+ from: MessageParticipantSchema,
741
+ type: z3.literal("SCHEMA_REQ"),
742
+ payload: SchemaRequestPayloadSchema
743
+ });
744
+ var SchemaResponsePayloadSchema = z3.object({
745
+ success: z3.boolean(),
746
+ error: z3.string().optional(),
747
+ data: z3.object({
748
+ schema: DatabaseSchemaSchema,
749
+ /** Formatted schema documentation (only if formatted: true was requested) */
750
+ formatted: z3.string().optional()
751
+ }).optional()
752
+ });
753
+ var SchemaResponseMessageSchema = z3.object({
754
+ id: z3.string(),
755
+ from: MessageParticipantSchema,
756
+ type: z3.literal("SCHEMA_RES"),
757
+ payload: SchemaResponsePayloadSchema
758
+ });
698
759
 
699
760
  // src/utils/logger.ts
700
761
  import fs from "fs";
@@ -3479,6 +3540,7 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
3479
3540
 
3480
3541
  **CRITICAL:**
3481
3542
  - Return ONLY valid JSON (no markdown code blocks, no text before/after)
3543
+ -\`componentName\`: MUST be the EXACT \`name\` field from the Available Components list. Never use a title or description as componentName.
3482
3544
  - \`componentId\`: For new components, MUST match an ID from the available components list. For updates, preserve the existing component's ID
3483
3545
  - \`isUpdate\`: Set to \`true\` if updating an existing component, \`false\` if creating new
3484
3546
  - \`dataSourceType\` indicates whether data comes from database or external tool
@@ -6476,6 +6538,7 @@ var STREAM_PREVIEW_MAX_CHARS = 200;
6476
6538
  var TOOL_TRACKING_MAX_ROWS = 5;
6477
6539
  var TOOL_TRACKING_MAX_CHARS = 200;
6478
6540
  var TOOL_TRACKING_SAMPLE_ROWS = 3;
6541
+ var DEFAULT_QUERY_LIMIT = 10;
6479
6542
  var MAX_COMPONENT_QUERY_LIMIT = 10;
6480
6543
  var EXACT_MATCH_SIMILARITY_THRESHOLD = 0.99;
6481
6544
  var DEFAULT_CONVERSATION_SIMILARITY_THRESHOLD = 0.8;
@@ -12166,6 +12229,7 @@ function formatComponentsForPrompt(components) {
12166
12229
  if (!components || components.length === 0) {
12167
12230
  return "No components available";
12168
12231
  }
12232
+ components = components.filter((c) => c.name !== "MultiComponentContainer");
12169
12233
  return components.map((comp, idx) => {
12170
12234
  const keywords = comp.keywords ? comp.keywords.join(", ") : "";
12171
12235
  const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
@@ -12212,7 +12276,7 @@ function sendDashCompResponse(id, res, sendMessage, clientId) {
12212
12276
  }
12213
12277
 
12214
12278
  // src/dashComp/pick-component.ts
12215
- async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, _collections, tools, dashCompModels) {
12279
+ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, dashCompModels) {
12216
12280
  const errors = [];
12217
12281
  const availableComponentsText = formatComponentsForPrompt(components);
12218
12282
  const availableToolsText = formatToolsForPrompt(tools);
@@ -12290,12 +12354,14 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12290
12354
  const parsedResult = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
12291
12355
  if (!parsedResult) {
12292
12356
  errors.push("Failed to parse LLM response as JSON");
12357
+ errors.push(`LLM Response: ${result}`);
12293
12358
  return { success: false, errors };
12294
12359
  }
12295
12360
  logger.debug("[DASH_COMP_REQ] LLM response received");
12296
12361
  logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
12297
12362
  if (!parsedResult.componentId || !parsedResult.props) {
12298
12363
  errors.push("Invalid LLM response: missing componentId or props");
12364
+ errors.push(`LLM Response: ${result}`);
12299
12365
  userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
12300
12366
  prompt,
12301
12367
  result: parsedResult,
@@ -12306,6 +12372,7 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12306
12372
  const originalComponent = components.find((c) => c.name === parsedResult.componentName);
12307
12373
  if (!originalComponent) {
12308
12374
  errors.push(`Component ${parsedResult.componentName} not found in available components`);
12375
+ errors.push(`LLM Response: ${result}`);
12309
12376
  userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
12310
12377
  prompt,
12311
12378
  componentName: parsedResult.componentName,
@@ -12313,14 +12380,72 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12313
12380
  });
12314
12381
  return { success: false, errors };
12315
12382
  }
12316
- const finalComponent = {
12383
+ let finalComponent = {
12317
12384
  ...originalComponent,
12318
12385
  props: {
12319
12386
  ...originalComponent.props,
12320
12387
  ...parsedResult.props
12321
12388
  }
12322
12389
  };
12390
+ if (finalComponent.props?.query) {
12391
+ const query = finalComponent.props.query;
12392
+ if (typeof query === "string") {
12393
+ finalComponent.props.query = ensureQueryLimit(query, DEFAULT_QUERY_LIMIT, MAX_COMPONENT_QUERY_LIMIT);
12394
+ } else if (query?.sql) {
12395
+ finalComponent.props.query = {
12396
+ ...query,
12397
+ sql: ensureQueryLimit(query.sql, DEFAULT_QUERY_LIMIT, MAX_COMPONENT_QUERY_LIMIT)
12398
+ };
12399
+ }
12400
+ }
12323
12401
  logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
12402
+ if (finalComponent.props?.query && collections?.["database"]?.["execute"]) {
12403
+ logger.info(`[DASH_COMP_REQ] Validating query for component: ${finalComponent.name}`);
12404
+ const queryService = new QueryExecutionService({
12405
+ defaultLimit: DEFAULT_QUERY_LIMIT,
12406
+ getModelForTask: () => model,
12407
+ // Use the same model for query fixes
12408
+ getApiKey: () => apiKey,
12409
+ providerName: "DASH_COMP_REQ"
12410
+ });
12411
+ try {
12412
+ const validationResult = await queryService.validateSingleQuery(
12413
+ finalComponent,
12414
+ collections,
12415
+ apiKey
12416
+ );
12417
+ if (!validationResult.validated) {
12418
+ logger.error(`[DASH_COMP_REQ] Query validation failed for component: ${finalComponent.name}`);
12419
+ errors.push(`Query validation failed for component ${finalComponent.name}. The generated SQL query could not be executed.`);
12420
+ return {
12421
+ success: false,
12422
+ errors,
12423
+ data: {
12424
+ reasoning: parsedResult.reasoning || "Component selected but query validation failed",
12425
+ rawResponse: parsedResult
12426
+ }
12427
+ };
12428
+ }
12429
+ if (validationResult.component) {
12430
+ finalComponent = validationResult.component;
12431
+ }
12432
+ logger.info(`[DASH_COMP_REQ] Query validated successfully for component: ${finalComponent.name}`);
12433
+ } catch (validationError) {
12434
+ const validationErrorMsg = validationError instanceof Error ? validationError.message : String(validationError);
12435
+ logger.error(`[DASH_COMP_REQ] Query validation error: ${validationErrorMsg}`);
12436
+ errors.push(`Query validation error: ${validationErrorMsg}`);
12437
+ return {
12438
+ success: false,
12439
+ errors,
12440
+ data: {
12441
+ reasoning: parsedResult.reasoning || "Component selected but query validation encountered an error",
12442
+ rawResponse: parsedResult
12443
+ }
12444
+ };
12445
+ }
12446
+ } else if (finalComponent.props?.query && !collections?.["database"]?.["execute"]) {
12447
+ logger.warn(`[DASH_COMP_REQ] Skipping query validation - database execute function not available`);
12448
+ }
12324
12449
  if (parsedResult.props.query) {
12325
12450
  logger.info(`[DASH_COMP_REQ] Data source: Database query`);
12326
12451
  }
@@ -12430,12 +12555,14 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
12430
12555
  const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
12431
12556
  if (!result) {
12432
12557
  errors.push("Failed to parse LLM response as JSON");
12558
+ errors.push(`LLM Response: ${rawResult}`);
12433
12559
  return { success: false, errors };
12434
12560
  }
12435
12561
  logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
12436
12562
  logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
12437
12563
  if (!result.filterComponent) {
12438
12564
  errors.push("Invalid LLM response: missing filterComponent");
12565
+ errors.push(`LLM Response: ${rawResult}`);
12439
12566
  userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", "Invalid LLM response structure", {
12440
12567
  prompt,
12441
12568
  result,
@@ -12578,6 +12705,64 @@ async function handleDashCompRequest(data, components, sendMessage, anthropicApi
12578
12705
  logger.info(`[DASH_COMP_REQ] Response sent to client ${response.wsId || data.from?.id}`);
12579
12706
  }
12580
12707
 
12708
+ // src/handlers/schema-request.ts
12709
+ async function handleSchemaRequest(message, sendMessage) {
12710
+ const startTime = Date.now();
12711
+ try {
12712
+ const payload = message.payload;
12713
+ const formatted = payload?.formatted ?? false;
12714
+ logger.info(`[SchemaRequest] Processing schema request (formatted: ${formatted})`);
12715
+ const schemaData = schema.getSchema();
12716
+ if (!schemaData) {
12717
+ const response2 = {
12718
+ id: message.id,
12719
+ type: "SCHEMA_RES",
12720
+ from: { type: "data-agent" },
12721
+ to: message.from,
12722
+ payload: {
12723
+ success: false,
12724
+ error: "Schema not found or failed to load"
12725
+ }
12726
+ };
12727
+ sendMessage(response2);
12728
+ return;
12729
+ }
12730
+ const responseData = {
12731
+ schema: schemaData
12732
+ };
12733
+ if (formatted) {
12734
+ responseData.formatted = schema.generateSchemaDocumentation();
12735
+ }
12736
+ const executionMs = Date.now() - startTime;
12737
+ logger.info(`[SchemaRequest] Schema retrieved successfully in ${executionMs}ms`);
12738
+ const response = {
12739
+ id: message.id,
12740
+ type: "SCHEMA_RES",
12741
+ from: { type: "data-agent" },
12742
+ to: message.from,
12743
+ payload: {
12744
+ success: true,
12745
+ data: responseData
12746
+ }
12747
+ };
12748
+ sendMessage(response);
12749
+ } catch (error) {
12750
+ const errorMsg = error instanceof Error ? error.message : String(error);
12751
+ logger.error(`[SchemaRequest] Error: ${errorMsg}`);
12752
+ const response = {
12753
+ id: message.id,
12754
+ type: "SCHEMA_RES",
12755
+ from: { type: "data-agent" },
12756
+ to: message.from,
12757
+ payload: {
12758
+ success: false,
12759
+ error: errorMsg
12760
+ }
12761
+ };
12762
+ sendMessage(response);
12763
+ }
12764
+ }
12765
+
12581
12766
  // src/auth/user-manager.ts
12582
12767
  import fs7 from "fs";
12583
12768
  import path6 from "path";
@@ -13826,6 +14011,11 @@ var SuperatomSDK = class {
13826
14011
  logger.error("Failed to handle dash comp request:", error);
13827
14012
  });
13828
14013
  break;
14014
+ case "SCHEMA_REQ":
14015
+ handleSchemaRequest(parsed, (msg) => this.send(msg)).catch((error) => {
14016
+ logger.error("Failed to handle schema request:", error);
14017
+ });
14018
+ break;
13829
14019
  default:
13830
14020
  const handler = this.messageTypeHandlers.get(message.type);
13831
14021
  if (handler) {