@superatomai/sdk-node 0.0.76 → 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.js CHANGED
@@ -752,6 +752,67 @@ var DashCompRequestMessageSchema = import_zod3.z.object({
752
752
  type: import_zod3.z.literal("DASH_COMP_REQ"),
753
753
  payload: DashCompRequestPayloadSchema
754
754
  });
755
+ var SchemaColumnStatisticsSchema = import_zod3.z.object({
756
+ distinct: import_zod3.z.number().optional(),
757
+ min: import_zod3.z.number().optional(),
758
+ max: import_zod3.z.number().optional()
759
+ });
760
+ var SchemaColumnSchema = import_zod3.z.object({
761
+ name: import_zod3.z.string(),
762
+ type: import_zod3.z.string(),
763
+ nativeType: import_zod3.z.string(),
764
+ nullable: import_zod3.z.boolean(),
765
+ description: import_zod3.z.string(),
766
+ statistics: SchemaColumnStatisticsSchema.optional(),
767
+ cardinality: import_zod3.z.enum(["unique", "high", "medium", "low"]).optional(),
768
+ sampleValues: import_zod3.z.array(import_zod3.z.string()).optional()
769
+ });
770
+ var SchemaTableSchema = import_zod3.z.object({
771
+ name: import_zod3.z.string(),
772
+ fullName: import_zod3.z.string(),
773
+ rowCount: import_zod3.z.number(),
774
+ description: import_zod3.z.string(),
775
+ columns: import_zod3.z.array(SchemaColumnSchema)
776
+ });
777
+ var SchemaRelationshipSchema = import_zod3.z.object({
778
+ from: import_zod3.z.string(),
779
+ to: import_zod3.z.string(),
780
+ type: import_zod3.z.string(),
781
+ keys: import_zod3.z.array(import_zod3.z.string())
782
+ });
783
+ var DatabaseSchemaSchema = import_zod3.z.object({
784
+ database: import_zod3.z.string(),
785
+ databaseType: import_zod3.z.string().optional(),
786
+ schema: import_zod3.z.string(),
787
+ description: import_zod3.z.string(),
788
+ tables: import_zod3.z.array(SchemaTableSchema),
789
+ relationships: import_zod3.z.array(SchemaRelationshipSchema).optional()
790
+ });
791
+ var SchemaRequestPayloadSchema = import_zod3.z.object({
792
+ /** If true, returns the formatted documentation string in addition to raw JSON */
793
+ formatted: import_zod3.z.boolean().optional()
794
+ });
795
+ var SchemaRequestMessageSchema = import_zod3.z.object({
796
+ id: import_zod3.z.string(),
797
+ from: MessageParticipantSchema,
798
+ type: import_zod3.z.literal("SCHEMA_REQ"),
799
+ payload: SchemaRequestPayloadSchema
800
+ });
801
+ var SchemaResponsePayloadSchema = import_zod3.z.object({
802
+ success: import_zod3.z.boolean(),
803
+ error: import_zod3.z.string().optional(),
804
+ data: import_zod3.z.object({
805
+ schema: DatabaseSchemaSchema,
806
+ /** Formatted schema documentation (only if formatted: true was requested) */
807
+ formatted: import_zod3.z.string().optional()
808
+ }).optional()
809
+ });
810
+ var SchemaResponseMessageSchema = import_zod3.z.object({
811
+ id: import_zod3.z.string(),
812
+ from: MessageParticipantSchema,
813
+ type: import_zod3.z.literal("SCHEMA_RES"),
814
+ payload: SchemaResponsePayloadSchema
815
+ });
755
816
 
756
817
  // src/utils/logger.ts
757
818
  var import_fs = __toESM(require("fs"));
@@ -3536,6 +3597,7 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
3536
3597
 
3537
3598
  **CRITICAL:**
3538
3599
  - Return ONLY valid JSON (no markdown code blocks, no text before/after)
3600
+ -\`componentName\`: MUST be the EXACT \`name\` field from the Available Components list. Never use a title or description as componentName.
3539
3601
  - \`componentId\`: For new components, MUST match an ID from the available components list. For updates, preserve the existing component's ID
3540
3602
  - \`isUpdate\`: Set to \`true\` if updating an existing component, \`false\` if creating new
3541
3603
  - \`dataSourceType\` indicates whether data comes from database or external tool
@@ -4297,13 +4359,13 @@ var PRICING = {
4297
4359
  "gpt-4-turbo": { input: 10, output: 30 },
4298
4360
  "gpt-4": { input: 30, output: 60 },
4299
4361
  "gpt-3.5-turbo": { input: 0.5, output: 1.5 },
4300
- // Google Gemini (December 2025)
4362
+ // Google Gemini (January 2026)
4301
4363
  "gemini-3-pro-preview": { input: 2, output: 12 },
4302
4364
  // New Gemini 3
4303
4365
  "gemini-3-flash-preview": { input: 0.5, output: 3 },
4304
4366
  // For prompts ≤200K tokens, 2x for >200K
4305
- "gemini-2.5-flash": { input: 0.15, output: 0.6 },
4306
- // Standard mode (thinking disabled: $0.60, thinking enabled: $3.50)
4367
+ "gemini-2.5-flash": { input: 0.3, output: 2.5 },
4368
+ // Paid tier: $0.30 input (text/image/video), $2.50 output (includes thinking)
4307
4369
  "gemini-2.5-flash-lite": { input: 0.1, output: 0.4 },
4308
4370
  "gemini-2.0-flash": { input: 0.1, output: 0.4 },
4309
4371
  "gemini-2.0-flash-lite": { input: 0.075, output: 0.3 },
@@ -6533,6 +6595,7 @@ var STREAM_PREVIEW_MAX_CHARS = 200;
6533
6595
  var TOOL_TRACKING_MAX_ROWS = 5;
6534
6596
  var TOOL_TRACKING_MAX_CHARS = 200;
6535
6597
  var TOOL_TRACKING_SAMPLE_ROWS = 3;
6598
+ var DEFAULT_QUERY_LIMIT = 10;
6536
6599
  var MAX_COMPONENT_QUERY_LIMIT = 10;
6537
6600
  var EXACT_MATCH_SIMILARITY_THRESHOLD = 0.99;
6538
6601
  var DEFAULT_CONVERSATION_SIMILARITY_THRESHOLD = 0.8;
@@ -7272,8 +7335,15 @@ Please try rephrasing your request or contact support.
7272
7335
  }
7273
7336
  await streamDelay();
7274
7337
  }
7338
+ const cappedToolInput = { ...toolInput };
7339
+ if (cappedToolInput.limit !== void 0 && cappedToolInput.limit > MAX_COMPONENT_QUERY_LIMIT) {
7340
+ logger.info(`[${providerName}] Capping external tool limit from ${cappedToolInput.limit} to ${MAX_COMPONENT_QUERY_LIMIT}`);
7341
+ cappedToolInput.limit = MAX_COMPONENT_QUERY_LIMIT;
7342
+ } else if (cappedToolInput.limit === void 0) {
7343
+ cappedToolInput.limit = MAX_COMPONENT_QUERY_LIMIT;
7344
+ }
7275
7345
  const result = await withProgressHeartbeat(
7276
- () => externalTool.fn(toolInput),
7346
+ () => externalTool.fn(cappedToolInput),
7277
7347
  `Running ${externalTool.name}`,
7278
7348
  streamBuffer
7279
7349
  );
@@ -7287,7 +7357,7 @@ Please try rephrasing your request or contact support.
7287
7357
  this.executedToolsList.push({
7288
7358
  id: externalTool.id,
7289
7359
  name: externalTool.name,
7290
- params: toolInput,
7360
+ params: cappedToolInput,
7291
7361
  result: {
7292
7362
  _totalRecords: formattedForTracking.summary.totalRecords,
7293
7363
  _recordsShown: formattedForTracking.summary.recordsShown,
@@ -8162,8 +8232,12 @@ ${executedToolsText}`);
8162
8232
  if (deferredTools.length > 0) {
8163
8233
  logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools for Form generation`);
8164
8234
  }
8235
+ const sanitizedTextResponse = textResponse.replace(
8236
+ /<DataTable>[\s\S]*?<\/DataTable>/g,
8237
+ "<DataTable>[Data preview removed - for table components, REUSE the exact SQL query shown above (the one that returned these results). Do NOT write a new query or embed data in props.]</DataTable>"
8238
+ );
8165
8239
  const matchResult = await this.matchComponentsFromAnalysis(
8166
- textResponse,
8240
+ sanitizedTextResponse,
8167
8241
  components,
8168
8242
  userPrompt,
8169
8243
  apiKey,
@@ -12212,6 +12286,7 @@ function formatComponentsForPrompt(components) {
12212
12286
  if (!components || components.length === 0) {
12213
12287
  return "No components available";
12214
12288
  }
12289
+ components = components.filter((c) => c.name !== "MultiComponentContainer");
12215
12290
  return components.map((comp, idx) => {
12216
12291
  const keywords = comp.keywords ? comp.keywords.join(", ") : "";
12217
12292
  const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
@@ -12258,7 +12333,7 @@ function sendDashCompResponse(id, res, sendMessage, clientId) {
12258
12333
  }
12259
12334
 
12260
12335
  // src/dashComp/pick-component.ts
12261
- async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, _collections, tools, dashCompModels) {
12336
+ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, dashCompModels) {
12262
12337
  const errors = [];
12263
12338
  const availableComponentsText = formatComponentsForPrompt(components);
12264
12339
  const availableToolsText = formatToolsForPrompt(tools);
@@ -12336,12 +12411,14 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12336
12411
  const parsedResult = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
12337
12412
  if (!parsedResult) {
12338
12413
  errors.push("Failed to parse LLM response as JSON");
12414
+ errors.push(`LLM Response: ${result}`);
12339
12415
  return { success: false, errors };
12340
12416
  }
12341
12417
  logger.debug("[DASH_COMP_REQ] LLM response received");
12342
12418
  logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
12343
12419
  if (!parsedResult.componentId || !parsedResult.props) {
12344
12420
  errors.push("Invalid LLM response: missing componentId or props");
12421
+ errors.push(`LLM Response: ${result}`);
12345
12422
  userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
12346
12423
  prompt,
12347
12424
  result: parsedResult,
@@ -12352,6 +12429,7 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12352
12429
  const originalComponent = components.find((c) => c.name === parsedResult.componentName);
12353
12430
  if (!originalComponent) {
12354
12431
  errors.push(`Component ${parsedResult.componentName} not found in available components`);
12432
+ errors.push(`LLM Response: ${result}`);
12355
12433
  userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
12356
12434
  prompt,
12357
12435
  componentName: parsedResult.componentName,
@@ -12359,14 +12437,72 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12359
12437
  });
12360
12438
  return { success: false, errors };
12361
12439
  }
12362
- const finalComponent = {
12440
+ let finalComponent = {
12363
12441
  ...originalComponent,
12364
12442
  props: {
12365
12443
  ...originalComponent.props,
12366
12444
  ...parsedResult.props
12367
12445
  }
12368
12446
  };
12447
+ if (finalComponent.props?.query) {
12448
+ const query = finalComponent.props.query;
12449
+ if (typeof query === "string") {
12450
+ finalComponent.props.query = ensureQueryLimit(query, DEFAULT_QUERY_LIMIT, MAX_COMPONENT_QUERY_LIMIT);
12451
+ } else if (query?.sql) {
12452
+ finalComponent.props.query = {
12453
+ ...query,
12454
+ sql: ensureQueryLimit(query.sql, DEFAULT_QUERY_LIMIT, MAX_COMPONENT_QUERY_LIMIT)
12455
+ };
12456
+ }
12457
+ }
12369
12458
  logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
12459
+ if (finalComponent.props?.query && collections?.["database"]?.["execute"]) {
12460
+ logger.info(`[DASH_COMP_REQ] Validating query for component: ${finalComponent.name}`);
12461
+ const queryService = new QueryExecutionService({
12462
+ defaultLimit: DEFAULT_QUERY_LIMIT,
12463
+ getModelForTask: () => model,
12464
+ // Use the same model for query fixes
12465
+ getApiKey: () => apiKey,
12466
+ providerName: "DASH_COMP_REQ"
12467
+ });
12468
+ try {
12469
+ const validationResult = await queryService.validateSingleQuery(
12470
+ finalComponent,
12471
+ collections,
12472
+ apiKey
12473
+ );
12474
+ if (!validationResult.validated) {
12475
+ logger.error(`[DASH_COMP_REQ] Query validation failed for component: ${finalComponent.name}`);
12476
+ errors.push(`Query validation failed for component ${finalComponent.name}. The generated SQL query could not be executed.`);
12477
+ return {
12478
+ success: false,
12479
+ errors,
12480
+ data: {
12481
+ reasoning: parsedResult.reasoning || "Component selected but query validation failed",
12482
+ rawResponse: parsedResult
12483
+ }
12484
+ };
12485
+ }
12486
+ if (validationResult.component) {
12487
+ finalComponent = validationResult.component;
12488
+ }
12489
+ logger.info(`[DASH_COMP_REQ] Query validated successfully for component: ${finalComponent.name}`);
12490
+ } catch (validationError) {
12491
+ const validationErrorMsg = validationError instanceof Error ? validationError.message : String(validationError);
12492
+ logger.error(`[DASH_COMP_REQ] Query validation error: ${validationErrorMsg}`);
12493
+ errors.push(`Query validation error: ${validationErrorMsg}`);
12494
+ return {
12495
+ success: false,
12496
+ errors,
12497
+ data: {
12498
+ reasoning: parsedResult.reasoning || "Component selected but query validation encountered an error",
12499
+ rawResponse: parsedResult
12500
+ }
12501
+ };
12502
+ }
12503
+ } else if (finalComponent.props?.query && !collections?.["database"]?.["execute"]) {
12504
+ logger.warn(`[DASH_COMP_REQ] Skipping query validation - database execute function not available`);
12505
+ }
12370
12506
  if (parsedResult.props.query) {
12371
12507
  logger.info(`[DASH_COMP_REQ] Data source: Database query`);
12372
12508
  }
@@ -12476,12 +12612,14 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
12476
12612
  const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
12477
12613
  if (!result) {
12478
12614
  errors.push("Failed to parse LLM response as JSON");
12615
+ errors.push(`LLM Response: ${rawResult}`);
12479
12616
  return { success: false, errors };
12480
12617
  }
12481
12618
  logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
12482
12619
  logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
12483
12620
  if (!result.filterComponent) {
12484
12621
  errors.push("Invalid LLM response: missing filterComponent");
12622
+ errors.push(`LLM Response: ${rawResult}`);
12485
12623
  userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", "Invalid LLM response structure", {
12486
12624
  prompt,
12487
12625
  result,
@@ -12624,6 +12762,64 @@ async function handleDashCompRequest(data, components, sendMessage, anthropicApi
12624
12762
  logger.info(`[DASH_COMP_REQ] Response sent to client ${response.wsId || data.from?.id}`);
12625
12763
  }
12626
12764
 
12765
+ // src/handlers/schema-request.ts
12766
+ async function handleSchemaRequest(message, sendMessage) {
12767
+ const startTime = Date.now();
12768
+ try {
12769
+ const payload = message.payload;
12770
+ const formatted = payload?.formatted ?? false;
12771
+ logger.info(`[SchemaRequest] Processing schema request (formatted: ${formatted})`);
12772
+ const schemaData = schema.getSchema();
12773
+ if (!schemaData) {
12774
+ const response2 = {
12775
+ id: message.id,
12776
+ type: "SCHEMA_RES",
12777
+ from: { type: "data-agent" },
12778
+ to: message.from,
12779
+ payload: {
12780
+ success: false,
12781
+ error: "Schema not found or failed to load"
12782
+ }
12783
+ };
12784
+ sendMessage(response2);
12785
+ return;
12786
+ }
12787
+ const responseData = {
12788
+ schema: schemaData
12789
+ };
12790
+ if (formatted) {
12791
+ responseData.formatted = schema.generateSchemaDocumentation();
12792
+ }
12793
+ const executionMs = Date.now() - startTime;
12794
+ logger.info(`[SchemaRequest] Schema retrieved successfully in ${executionMs}ms`);
12795
+ const response = {
12796
+ id: message.id,
12797
+ type: "SCHEMA_RES",
12798
+ from: { type: "data-agent" },
12799
+ to: message.from,
12800
+ payload: {
12801
+ success: true,
12802
+ data: responseData
12803
+ }
12804
+ };
12805
+ sendMessage(response);
12806
+ } catch (error) {
12807
+ const errorMsg = error instanceof Error ? error.message : String(error);
12808
+ logger.error(`[SchemaRequest] Error: ${errorMsg}`);
12809
+ const response = {
12810
+ id: message.id,
12811
+ type: "SCHEMA_RES",
12812
+ from: { type: "data-agent" },
12813
+ to: message.from,
12814
+ payload: {
12815
+ success: false,
12816
+ error: errorMsg
12817
+ }
12818
+ };
12819
+ sendMessage(response);
12820
+ }
12821
+ }
12822
+
12627
12823
  // src/auth/user-manager.ts
12628
12824
  var import_fs6 = __toESM(require("fs"));
12629
12825
  var import_path5 = __toESM(require("path"));
@@ -13872,6 +14068,11 @@ var SuperatomSDK = class {
13872
14068
  logger.error("Failed to handle dash comp request:", error);
13873
14069
  });
13874
14070
  break;
14071
+ case "SCHEMA_REQ":
14072
+ handleSchemaRequest(parsed, (msg) => this.send(msg)).catch((error) => {
14073
+ logger.error("Failed to handle schema request:", error);
14074
+ });
14075
+ break;
13875
14076
  default:
13876
14077
  const handler = this.messageTypeHandlers.get(message.type);
13877
14078
  if (handler) {