@superatomai/sdk-node 0.0.26 → 0.0.28

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
@@ -802,18 +802,22 @@ var STORAGE_CONFIG = {
802
802
  */
803
803
  MAX_ROWS_PER_BLOCK: 10,
804
804
  /**
805
- * Maximum size in bytes per UIBlock (1MB)
805
+ * Maximum size in bytes per UIBlock (500KB - reduced to save memory)
806
806
  */
807
- MAX_SIZE_PER_BLOCK_BYTES: 1 * 1024 * 1024,
808
- // 1MB
807
+ MAX_SIZE_PER_BLOCK_BYTES: 500 * 1024,
808
+ // 500KB
809
809
  /**
810
810
  * Number of days to keep threads before cleanup
811
+ * Note: This is for in-memory storage. Conversations are also persisted to database.
811
812
  */
812
- THREAD_RETENTION_DAYS: 7,
813
+ THREAD_RETENTION_DAYS: 2,
814
+ // Reduced from 7 to 1 day for memory efficiency
813
815
  /**
814
816
  * Number of days to keep UIBlocks before cleanup
817
+ * Note: This is for in-memory storage. Data is also persisted to database.
815
818
  */
816
- UIBLOCK_RETENTION_DAYS: 7
819
+ UIBLOCK_RETENTION_DAYS: 2
820
+ // Reduced from 7 to 1 day for memory efficiency
817
821
  };
818
822
 
819
823
  // src/threads/uiblock.ts
@@ -1333,8 +1337,15 @@ async function handleDataRequest(data, collections, sendMessage) {
1333
1337
  }
1334
1338
  }
1335
1339
  if (uiBlock) {
1336
- uiBlock.setComponentData(result || {});
1337
- logger.info(`Updated UIBlock ${uiBlockId} with component data from ${collection}.${op}`);
1340
+ const dataSummary = {
1341
+ _dataReceived: true,
1342
+ _timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1343
+ _collection: collection,
1344
+ _operation: op,
1345
+ _recordCount: Array.isArray(result) ? result.length : result?.data?.length || result?.contacts?.length || result?.salesorders?.length || "unknown"
1346
+ };
1347
+ uiBlock.setComponentData(dataSummary);
1348
+ logger.info(`Updated UIBlock ${uiBlockId} with data summary from ${collection}.${op} (full data not stored to save memory)`);
1338
1349
  } else {
1339
1350
  logger.warn(`UIBlock ${uiBlockId} not found in threads`);
1340
1351
  }
@@ -2881,7 +2892,9 @@ If adaptation is not possible or would fundamentally change the component:
2881
2892
  var PromptLoader = class {
2882
2893
  constructor(config) {
2883
2894
  this.promptCache = /* @__PURE__ */ new Map();
2895
+ this.databaseRulesCache = /* @__PURE__ */ new Map();
2884
2896
  this.isInitialized = false;
2897
+ this.databaseType = "postgresql";
2885
2898
  logger.debug("Initializing PromptLoader...");
2886
2899
  this.promptsDir = config?.promptsDir || path3.join(process.cwd(), ".prompts");
2887
2900
  logger.debug(`Prompts directory set to: ${this.promptsDir}`);
@@ -3027,6 +3040,76 @@ var PromptLoader = class {
3027
3040
  getCacheSize() {
3028
3041
  return this.promptCache.size;
3029
3042
  }
3043
+ /**
3044
+ * Set the database type for SQL rules loading
3045
+ * @param type - Database type ('postgresql' | 'mssql')
3046
+ */
3047
+ setDatabaseType(type) {
3048
+ this.databaseType = type;
3049
+ this.databaseRulesCache.clear();
3050
+ logger.debug(`Database type set to: ${type}`);
3051
+ }
3052
+ /**
3053
+ * Get current database type
3054
+ * @returns Database type string
3055
+ */
3056
+ getDatabaseType() {
3057
+ return this.databaseType;
3058
+ }
3059
+ /**
3060
+ * Load database-specific SQL rules from file system
3061
+ * Falls back to minimal default rules if file not found
3062
+ * @returns Database rules as a string
3063
+ */
3064
+ async loadDatabaseRules() {
3065
+ if (this.databaseRulesCache.has(this.databaseType)) {
3066
+ logger.debug(`\u2713 Database rules for '${this.databaseType}' loaded from cache`);
3067
+ return this.databaseRulesCache.get(this.databaseType);
3068
+ }
3069
+ const rulesPath = path3.join(this.promptsDir, "database-rules", `${this.databaseType}.md`);
3070
+ try {
3071
+ if (fs4.existsSync(rulesPath)) {
3072
+ const rules = fs4.readFileSync(rulesPath, "utf-8");
3073
+ this.databaseRulesCache.set(this.databaseType, rules);
3074
+ logger.info(`\u2713 Loaded database rules for '${this.databaseType}' from ${rulesPath}`);
3075
+ return rules;
3076
+ }
3077
+ } catch (error) {
3078
+ logger.warn(`Could not load database rules for '${this.databaseType}' from file system: ${error}`);
3079
+ }
3080
+ const defaultRules = this.getDefaultDatabaseRules();
3081
+ this.databaseRulesCache.set(this.databaseType, defaultRules);
3082
+ logger.warn(`Using default database rules for '${this.databaseType}' (file not found at ${rulesPath})`);
3083
+ return defaultRules;
3084
+ }
3085
+ /**
3086
+ * Get default database rules as fallback
3087
+ * @returns Minimal database rules
3088
+ */
3089
+ getDefaultDatabaseRules() {
3090
+ if (this.databaseType === "mssql") {
3091
+ return `**Database Type: Microsoft SQL Server**
3092
+
3093
+ **SQL Query Rules:**
3094
+ - Use \`TOP N\` for row limiting (e.g., \`SELECT TOP 32 * FROM table\`)
3095
+ - Use \`1\` for true, \`0\` for false (no native boolean)
3096
+ - Use \`+\` or \`CONCAT()\` for string concatenation
3097
+ - Use \`GETDATE()\` for current timestamp
3098
+ - Use \`CAST()\` or \`CONVERT()\` for type casting
3099
+ - Use \`OUTPUT INSERTED.*\` instead of \`RETURNING\`
3100
+ - NULL values: Use \`NULL\` keyword without quotes`;
3101
+ }
3102
+ return `**Database Type: PostgreSQL**
3103
+
3104
+ **SQL Query Rules:**
3105
+ - Use \`LIMIT N\` for row limiting (e.g., \`SELECT * FROM table LIMIT 32\`)
3106
+ - Use \`true\` / \`false\` for boolean values
3107
+ - Use \`||\` for string concatenation
3108
+ - Use \`NOW()\` for current timestamp
3109
+ - Use \`::TYPE\` or \`CAST()\` for type casting
3110
+ - Use \`RETURNING\` clause for mutations
3111
+ - NULL values: Use \`NULL\` keyword without quotes`;
3112
+ }
3030
3113
  };
3031
3114
  var defaultPromptsPath = process.env.PROMPTS_DIR || path3.join(process.cwd(), ".prompts");
3032
3115
  var promptLoader = new PromptLoader({
@@ -3341,10 +3424,15 @@ var LLM = class {
3341
3424
  for (const toolUse of toolUses) {
3342
3425
  try {
3343
3426
  const result = await toolHandler(toolUse.name, toolUse.input);
3427
+ let resultContent = typeof result === "string" ? result : JSON.stringify(result);
3428
+ const MAX_RESULT_LENGTH = 5e4;
3429
+ if (resultContent.length > MAX_RESULT_LENGTH) {
3430
+ resultContent = resultContent.substring(0, MAX_RESULT_LENGTH) + "\n\n... [Result truncated - showing first 50000 characters of " + resultContent.length + " total]";
3431
+ }
3344
3432
  toolResults.content.push({
3345
3433
  type: "tool_result",
3346
3434
  tool_use_id: toolUse.id,
3347
- content: typeof result === "string" ? result : JSON.stringify(result)
3435
+ content: resultContent
3348
3436
  });
3349
3437
  } catch (error) {
3350
3438
  toolResults.content.push({
@@ -3523,9 +3611,14 @@ var LLM = class {
3523
3611
  for (const fc of functionCalls) {
3524
3612
  try {
3525
3613
  const result2 = await toolHandler(fc.name, fc.args);
3614
+ let resultContent = typeof result2 === "string" ? result2 : JSON.stringify(result2);
3615
+ const MAX_RESULT_LENGTH = 5e4;
3616
+ if (resultContent.length > MAX_RESULT_LENGTH) {
3617
+ resultContent = resultContent.substring(0, MAX_RESULT_LENGTH) + "\n\n... [Result truncated - showing first 50000 characters of " + resultContent.length + " total]";
3618
+ }
3526
3619
  functionResponses.push({
3527
3620
  name: fc.name,
3528
- response: { result: typeof result2 === "string" ? result2 : JSON.stringify(result2) }
3621
+ response: { result: resultContent }
3529
3622
  });
3530
3623
  } catch (error) {
3531
3624
  functionResponses.push({
@@ -3691,6 +3784,10 @@ var LLM = class {
3691
3784
  const args = JSON.parse(tc.arguments);
3692
3785
  const toolResult = await toolHandler(tc.name, args);
3693
3786
  result = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult);
3787
+ const MAX_RESULT_LENGTH = 5e4;
3788
+ if (result.length > MAX_RESULT_LENGTH) {
3789
+ result = result.substring(0, MAX_RESULT_LENGTH) + "\n\n... [Result truncated - showing first 50000 characters of " + result.length + " total]";
3790
+ }
3694
3791
  } catch (error) {
3695
3792
  result = JSON.stringify({ error: error instanceof Error ? error.message : String(error) });
3696
3793
  }
@@ -4171,6 +4268,7 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
4171
4268
  }).join("\n\n");
4172
4269
  }
4173
4270
  const schemaDoc = schema.generateSchemaDocumentation();
4271
+ const databaseRules = await promptLoader.loadDatabaseRules();
4174
4272
  logger.file("\n=============================\nText analysis response:", analysisContent);
4175
4273
  logger.file("\n=============================\nDeferred tools:", deferredToolsText);
4176
4274
  logger.file("\n=============================\nExecuted tools:", executedToolsText);
@@ -4178,6 +4276,7 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
4178
4276
  ANALYSIS_CONTENT: analysisContent,
4179
4277
  AVAILABLE_COMPONENTS: availableComponentsText,
4180
4278
  SCHEMA_DOC: schemaDoc,
4279
+ DATABASE_RULES: databaseRules,
4181
4280
  DEFERRED_TOOLS: deferredToolsText,
4182
4281
  EXECUTED_TOOLS: executedToolsText
4183
4282
  });
@@ -4438,12 +4537,14 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
4438
4537
  };
4439
4538
  }
4440
4539
  const schemaDoc = schema.generateSchemaDocumentation();
4540
+ const databaseRules = await promptLoader.loadDatabaseRules();
4441
4541
  const prompts = await promptLoader.loadPrompts("adapt-ui-block-params", {
4442
4542
  ORIGINAL_USER_PROMPT: originalUserPrompt,
4443
4543
  CURRENT_USER_PROMPT: currentUserPrompt,
4444
4544
  MATCHED_UI_BLOCK_COMPONENT: JSON.stringify(component, null, 2),
4445
4545
  COMPONENT_PROPS: JSON.stringify(component.props, null, 2),
4446
- SCHEMA_DOC: schemaDoc || "No schema available"
4546
+ SCHEMA_DOC: schemaDoc || "No schema available",
4547
+ DATABASE_RULES: databaseRules
4447
4548
  });
4448
4549
  const result = await LLM.stream(
4449
4550
  {
@@ -4562,6 +4663,7 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
4562
4663
  availableToolsDoc = toolsDocParts.join("\n\n---\n\n");
4563
4664
  }
4564
4665
  const schemaDoc = schema.generateSchemaDocumentation();
4666
+ const databaseRules = await promptLoader.loadDatabaseRules();
4565
4667
  const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
4566
4668
  prompt: userPrompt,
4567
4669
  collections,
@@ -4572,6 +4674,7 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
4572
4674
  USER_PROMPT: userPrompt,
4573
4675
  CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
4574
4676
  SCHEMA_DOC: schemaDoc,
4677
+ DATABASE_RULES: databaseRules,
4575
4678
  KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
4576
4679
  AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc
4577
4680
  });
@@ -4865,13 +4968,26 @@ Please try rephrasing your request or contact support.
4865
4968
  logger.info(`[${this.getProviderName()}] External tool ${externalTool.name} executed successfully`);
4866
4969
  logCollector?.info(`\u2713 ${externalTool.name} executed successfully`);
4867
4970
  if (!executedToolsList.find((t) => t.id === externalTool.id)) {
4971
+ let resultSummary = null;
4972
+ if (result2) {
4973
+ const resultStr = typeof result2 === "string" ? result2 : JSON.stringify(result2);
4974
+ if (resultStr.length > 1e3) {
4975
+ resultSummary = {
4976
+ _preview: resultStr.substring(0, 1e3) + "... (truncated)",
4977
+ _totalLength: resultStr.length,
4978
+ _recordCount: Array.isArray(result2) ? result2.length : result2?.data?.length || result2?.contacts?.length || result2?.salesorders?.length || "unknown"
4979
+ };
4980
+ } else {
4981
+ resultSummary = result2;
4982
+ }
4983
+ }
4868
4984
  executedToolsList.push({
4869
4985
  id: externalTool.id,
4870
4986
  name: externalTool.name,
4871
4987
  params: toolInput,
4872
4988
  // The actual parameters used in this execution
4873
- result: result2
4874
- // Store the actual result data for populating deferred tool params
4989
+ result: resultSummary
4990
+ // Store summary instead of full result to save memory
4875
4991
  });
4876
4992
  logger.info(`[${this.getProviderName()}] Tracked executed tool: ${externalTool.name} with params: ${JSON.stringify(toolInput)}`);
4877
4993
  }
@@ -4979,8 +5095,6 @@ ${errorMsg}
4979
5095
  if (deferredTools.length > 0) {
4980
5096
  logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools for Form generation`);
4981
5097
  }
4982
- logger.info(`[${this.getProviderName()}] passing deferred tools to the matching function: ${JSON.stringify(deferredTools, null, 2)}`);
4983
- logger.info(`[${this.getProviderName()}] passing executed tools to the matching function: ${JSON.stringify(executedToolsList, null, 2)}`);
4984
5098
  const matchResult = await this.matchComponentsFromAnalysis(
4985
5099
  textResponse,
4986
5100
  components,
@@ -9519,7 +9633,8 @@ var SuperatomSDK = class {
9519
9633
  this.geminiApiKey = config.GEMINI_API_KEY || process.env.GEMINI_API_KEY || "";
9520
9634
  this.openaiApiKey = config.OPENAI_API_KEY || process.env.OPENAI_API_KEY || "";
9521
9635
  this.llmProviders = config.LLM_PROVIDERS || getLLMProviders();
9522
- logger.info(`Initializing Superatom SDK v${SDK_VERSION} for project ${this.projectId}, llm providers: ${this.llmProviders.join(", ")}, config llm providers: ${config.LLM_PROVIDERS}`);
9636
+ this.databaseType = config.databaseType || "postgresql";
9637
+ logger.info(`Initializing Superatom SDK v${SDK_VERSION} for project ${this.projectId}, llm providers: ${this.llmProviders.join(", ")}, database type: ${this.databaseType}`);
9523
9638
  this.userManager = new UserManager(this.projectId, 5e3);
9524
9639
  this.dashboardManager = new DashboardManager(this.projectId);
9525
9640
  this.reportManager = new ReportManager(this.projectId);
@@ -9541,8 +9656,9 @@ var SuperatomSDK = class {
9541
9656
  if (promptsDir) {
9542
9657
  promptLoader.setPromptsDir(promptsDir);
9543
9658
  }
9659
+ promptLoader.setDatabaseType(this.databaseType);
9544
9660
  await promptLoader.initialize();
9545
- logger.info(`PromptLoader initialized with ${promptLoader.getCacheSize()} prompts from ${promptLoader.getPromptsDir()}`);
9661
+ logger.info(`PromptLoader initialized with ${promptLoader.getCacheSize()} prompts from ${promptLoader.getPromptsDir()}, database type: ${this.databaseType}`);
9546
9662
  } catch (error) {
9547
9663
  logger.error("Failed to initialize PromptLoader:", error);
9548
9664
  throw error;