@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.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
@@ -4240,13 +4302,13 @@ var PRICING = {
4240
4302
  "gpt-4-turbo": { input: 10, output: 30 },
4241
4303
  "gpt-4": { input: 30, output: 60 },
4242
4304
  "gpt-3.5-turbo": { input: 0.5, output: 1.5 },
4243
- // Google Gemini (December 2025)
4305
+ // Google Gemini (January 2026)
4244
4306
  "gemini-3-pro-preview": { input: 2, output: 12 },
4245
4307
  // New Gemini 3
4246
4308
  "gemini-3-flash-preview": { input: 0.5, output: 3 },
4247
4309
  // For prompts ≤200K tokens, 2x for >200K
4248
- "gemini-2.5-flash": { input: 0.15, output: 0.6 },
4249
- // Standard mode (thinking disabled: $0.60, thinking enabled: $3.50)
4310
+ "gemini-2.5-flash": { input: 0.3, output: 2.5 },
4311
+ // Paid tier: $0.30 input (text/image/video), $2.50 output (includes thinking)
4250
4312
  "gemini-2.5-flash-lite": { input: 0.1, output: 0.4 },
4251
4313
  "gemini-2.0-flash": { input: 0.1, output: 0.4 },
4252
4314
  "gemini-2.0-flash-lite": { input: 0.075, output: 0.3 },
@@ -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;
@@ -7215,8 +7278,15 @@ Please try rephrasing your request or contact support.
7215
7278
  }
7216
7279
  await streamDelay();
7217
7280
  }
7281
+ const cappedToolInput = { ...toolInput };
7282
+ if (cappedToolInput.limit !== void 0 && cappedToolInput.limit > MAX_COMPONENT_QUERY_LIMIT) {
7283
+ logger.info(`[${providerName}] Capping external tool limit from ${cappedToolInput.limit} to ${MAX_COMPONENT_QUERY_LIMIT}`);
7284
+ cappedToolInput.limit = MAX_COMPONENT_QUERY_LIMIT;
7285
+ } else if (cappedToolInput.limit === void 0) {
7286
+ cappedToolInput.limit = MAX_COMPONENT_QUERY_LIMIT;
7287
+ }
7218
7288
  const result = await withProgressHeartbeat(
7219
- () => externalTool.fn(toolInput),
7289
+ () => externalTool.fn(cappedToolInput),
7220
7290
  `Running ${externalTool.name}`,
7221
7291
  streamBuffer
7222
7292
  );
@@ -7230,7 +7300,7 @@ Please try rephrasing your request or contact support.
7230
7300
  this.executedToolsList.push({
7231
7301
  id: externalTool.id,
7232
7302
  name: externalTool.name,
7233
- params: toolInput,
7303
+ params: cappedToolInput,
7234
7304
  result: {
7235
7305
  _totalRecords: formattedForTracking.summary.totalRecords,
7236
7306
  _recordsShown: formattedForTracking.summary.recordsShown,
@@ -8105,8 +8175,12 @@ ${executedToolsText}`);
8105
8175
  if (deferredTools.length > 0) {
8106
8176
  logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools for Form generation`);
8107
8177
  }
8178
+ const sanitizedTextResponse = textResponse.replace(
8179
+ /<DataTable>[\s\S]*?<\/DataTable>/g,
8180
+ "<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>"
8181
+ );
8108
8182
  const matchResult = await this.matchComponentsFromAnalysis(
8109
- textResponse,
8183
+ sanitizedTextResponse,
8110
8184
  components,
8111
8185
  userPrompt,
8112
8186
  apiKey,
@@ -12155,6 +12229,7 @@ function formatComponentsForPrompt(components) {
12155
12229
  if (!components || components.length === 0) {
12156
12230
  return "No components available";
12157
12231
  }
12232
+ components = components.filter((c) => c.name !== "MultiComponentContainer");
12158
12233
  return components.map((comp, idx) => {
12159
12234
  const keywords = comp.keywords ? comp.keywords.join(", ") : "";
12160
12235
  const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
@@ -12201,7 +12276,7 @@ function sendDashCompResponse(id, res, sendMessage, clientId) {
12201
12276
  }
12202
12277
 
12203
12278
  // src/dashComp/pick-component.ts
12204
- 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) {
12205
12280
  const errors = [];
12206
12281
  const availableComponentsText = formatComponentsForPrompt(components);
12207
12282
  const availableToolsText = formatToolsForPrompt(tools);
@@ -12279,12 +12354,14 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12279
12354
  const parsedResult = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
12280
12355
  if (!parsedResult) {
12281
12356
  errors.push("Failed to parse LLM response as JSON");
12357
+ errors.push(`LLM Response: ${result}`);
12282
12358
  return { success: false, errors };
12283
12359
  }
12284
12360
  logger.debug("[DASH_COMP_REQ] LLM response received");
12285
12361
  logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
12286
12362
  if (!parsedResult.componentId || !parsedResult.props) {
12287
12363
  errors.push("Invalid LLM response: missing componentId or props");
12364
+ errors.push(`LLM Response: ${result}`);
12288
12365
  userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
12289
12366
  prompt,
12290
12367
  result: parsedResult,
@@ -12295,6 +12372,7 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12295
12372
  const originalComponent = components.find((c) => c.name === parsedResult.componentName);
12296
12373
  if (!originalComponent) {
12297
12374
  errors.push(`Component ${parsedResult.componentName} not found in available components`);
12375
+ errors.push(`LLM Response: ${result}`);
12298
12376
  userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
12299
12377
  prompt,
12300
12378
  componentName: parsedResult.componentName,
@@ -12302,14 +12380,72 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
12302
12380
  });
12303
12381
  return { success: false, errors };
12304
12382
  }
12305
- const finalComponent = {
12383
+ let finalComponent = {
12306
12384
  ...originalComponent,
12307
12385
  props: {
12308
12386
  ...originalComponent.props,
12309
12387
  ...parsedResult.props
12310
12388
  }
12311
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
+ }
12312
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
+ }
12313
12449
  if (parsedResult.props.query) {
12314
12450
  logger.info(`[DASH_COMP_REQ] Data source: Database query`);
12315
12451
  }
@@ -12419,12 +12555,14 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
12419
12555
  const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
12420
12556
  if (!result) {
12421
12557
  errors.push("Failed to parse LLM response as JSON");
12558
+ errors.push(`LLM Response: ${rawResult}`);
12422
12559
  return { success: false, errors };
12423
12560
  }
12424
12561
  logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
12425
12562
  logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
12426
12563
  if (!result.filterComponent) {
12427
12564
  errors.push("Invalid LLM response: missing filterComponent");
12565
+ errors.push(`LLM Response: ${rawResult}`);
12428
12566
  userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", "Invalid LLM response structure", {
12429
12567
  prompt,
12430
12568
  result,
@@ -12567,6 +12705,64 @@ async function handleDashCompRequest(data, components, sendMessage, anthropicApi
12567
12705
  logger.info(`[DASH_COMP_REQ] Response sent to client ${response.wsId || data.from?.id}`);
12568
12706
  }
12569
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
+
12570
12766
  // src/auth/user-manager.ts
12571
12767
  import fs7 from "fs";
12572
12768
  import path6 from "path";
@@ -13815,6 +14011,11 @@ var SuperatomSDK = class {
13815
14011
  logger.error("Failed to handle dash comp request:", error);
13816
14012
  });
13817
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;
13818
14019
  default:
13819
14020
  const handler = this.messageTypeHandlers.get(message.type);
13820
14021
  if (handler) {