@superatomai/sdk-node 0.0.26-mds → 0.0.27-mds

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.d.mts CHANGED
@@ -2449,8 +2449,12 @@ declare class OpenAILLM extends BaseLLM {
2449
2449
  declare const openaiLLM: OpenAILLM;
2450
2450
 
2451
2451
  /**
2452
- * Query Cache - Stores query results with configurable TTL
2453
- * Used to avoid re-executing queries that were already validated
2452
+ * Query Cache - Two separate stores with different lifetimes:
2453
+ *
2454
+ * 1. `cache` (query string → result data) — TTL-based, for avoiding re-execution of recently validated queries.
2455
+ * 2. `queryIdCache` (queryId → SQL) — permanent (server lifetime), because queryIds are persisted
2456
+ * in dashboard widgets and must remain resolvable across page reloads and idle periods.
2457
+ * Only the cached *data* inside a queryId entry expires; the SQL mapping itself never does.
2454
2458
  */
2455
2459
  declare class QueryCache {
2456
2460
  private cache;
@@ -2460,7 +2464,7 @@ declare class QueryCache {
2460
2464
  constructor();
2461
2465
  /**
2462
2466
  * Set the cache TTL (Time To Live)
2463
- * @param minutes - TTL in minutes (default: 5)
2467
+ * @param minutes - TTL in minutes (default: 10)
2464
2468
  */
2465
2469
  setTTL(minutes: number): void;
2466
2470
  /**
@@ -2493,10 +2497,13 @@ declare class QueryCache {
2493
2497
  */
2494
2498
  getStats(): {
2495
2499
  size: number;
2500
+ queryIdCount: number;
2496
2501
  oldestEntryAge: number | null;
2497
2502
  };
2498
2503
  /**
2499
- * Start periodic cleanup of expired entries
2504
+ * Start periodic cleanup of expired entries.
2505
+ * Only cleans the data cache — queryIdCache entries are permanent (server lifetime)
2506
+ * because queryIds are persisted in dashboard widgets.
2500
2507
  */
2501
2508
  private startCleanup;
2502
2509
  /**
@@ -2509,7 +2516,9 @@ declare class QueryCache {
2509
2516
  */
2510
2517
  storeQuery(query: any, data?: any): string;
2511
2518
  /**
2512
- * Get a stored query by its ID (not expired)
2519
+ * Get a stored query by its ID.
2520
+ * The SQL mapping never expires (queryIds are persisted in dashboard widgets).
2521
+ * Cached data may be null if it was evicted by the cleanup interval.
2513
2522
  */
2514
2523
  getQuery(queryId: string): {
2515
2524
  query: any;
package/dist/index.d.ts CHANGED
@@ -2449,8 +2449,12 @@ declare class OpenAILLM extends BaseLLM {
2449
2449
  declare const openaiLLM: OpenAILLM;
2450
2450
 
2451
2451
  /**
2452
- * Query Cache - Stores query results with configurable TTL
2453
- * Used to avoid re-executing queries that were already validated
2452
+ * Query Cache - Two separate stores with different lifetimes:
2453
+ *
2454
+ * 1. `cache` (query string → result data) — TTL-based, for avoiding re-execution of recently validated queries.
2455
+ * 2. `queryIdCache` (queryId → SQL) — permanent (server lifetime), because queryIds are persisted
2456
+ * in dashboard widgets and must remain resolvable across page reloads and idle periods.
2457
+ * Only the cached *data* inside a queryId entry expires; the SQL mapping itself never does.
2454
2458
  */
2455
2459
  declare class QueryCache {
2456
2460
  private cache;
@@ -2460,7 +2464,7 @@ declare class QueryCache {
2460
2464
  constructor();
2461
2465
  /**
2462
2466
  * Set the cache TTL (Time To Live)
2463
- * @param minutes - TTL in minutes (default: 5)
2467
+ * @param minutes - TTL in minutes (default: 10)
2464
2468
  */
2465
2469
  setTTL(minutes: number): void;
2466
2470
  /**
@@ -2493,10 +2497,13 @@ declare class QueryCache {
2493
2497
  */
2494
2498
  getStats(): {
2495
2499
  size: number;
2500
+ queryIdCount: number;
2496
2501
  oldestEntryAge: number | null;
2497
2502
  };
2498
2503
  /**
2499
- * Start periodic cleanup of expired entries
2504
+ * Start periodic cleanup of expired entries.
2505
+ * Only cleans the data cache — queryIdCache entries are permanent (server lifetime)
2506
+ * because queryIds are persisted in dashboard widgets.
2500
2507
  */
2501
2508
  private startCleanup;
2502
2509
  /**
@@ -2509,7 +2516,9 @@ declare class QueryCache {
2509
2516
  */
2510
2517
  storeQuery(query: any, data?: any): string;
2511
2518
  /**
2512
- * Get a stored query by its ID (not expired)
2519
+ * Get a stored query by its ID.
2520
+ * The SQL mapping never expires (queryIds are persisted in dashboard widgets).
2521
+ * Cached data may be null if it was evicted by the cleanup interval.
2513
2522
  */
2514
2523
  getQuery(queryId: string): {
2515
2524
  query: any;
package/dist/index.js CHANGED
@@ -1491,14 +1491,14 @@ var QueryCache = class {
1491
1491
  constructor() {
1492
1492
  this.cache = /* @__PURE__ */ new Map();
1493
1493
  this.queryIdCache = /* @__PURE__ */ new Map();
1494
- this.ttlMs = 5 * 60 * 1e3;
1495
- // Default: 5 minutes
1494
+ this.ttlMs = 10 * 60 * 1e3;
1495
+ // Default: 10 minutes (for data cache only)
1496
1496
  this.cleanupInterval = null;
1497
1497
  this.startCleanup();
1498
1498
  }
1499
1499
  /**
1500
1500
  * Set the cache TTL (Time To Live)
1501
- * @param minutes - TTL in minutes (default: 5)
1501
+ * @param minutes - TTL in minutes (default: 10)
1502
1502
  */
1503
1503
  setTTL(minutes) {
1504
1504
  this.ttlMs = minutes * 60 * 1e3;
@@ -1569,11 +1569,14 @@ var QueryCache = class {
1569
1569
  }
1570
1570
  return {
1571
1571
  size: this.cache.size,
1572
+ queryIdCount: this.queryIdCache.size,
1572
1573
  oldestEntryAge: oldestTimestamp ? Date.now() - oldestTimestamp : null
1573
1574
  };
1574
1575
  }
1575
1576
  /**
1576
- * Start periodic cleanup of expired entries
1577
+ * Start periodic cleanup of expired entries.
1578
+ * Only cleans the data cache — queryIdCache entries are permanent (server lifetime)
1579
+ * because queryIds are persisted in dashboard widgets.
1577
1580
  */
1578
1581
  startCleanup() {
1579
1582
  this.cleanupInterval = setInterval(() => {
@@ -1585,14 +1588,13 @@ var QueryCache = class {
1585
1588
  expiredCount++;
1586
1589
  }
1587
1590
  }
1588
- for (const [key, entry] of this.queryIdCache.entries()) {
1589
- if (now - entry.timestamp > this.ttlMs) {
1590
- this.queryIdCache.delete(key);
1591
- expiredCount++;
1591
+ for (const entry of this.queryIdCache.values()) {
1592
+ if (entry.data && now - entry.timestamp > this.ttlMs) {
1593
+ entry.data = null;
1592
1594
  }
1593
1595
  }
1594
1596
  if (expiredCount > 0) {
1595
- logger.debug(`[QueryCache] Cleaned up ${expiredCount} expired entries`);
1597
+ logger.debug(`[QueryCache] Cleaned up ${expiredCount} expired data-cache entries`);
1596
1598
  }
1597
1599
  }, 2 * 60 * 1e3);
1598
1600
  }
@@ -1622,15 +1624,14 @@ var QueryCache = class {
1622
1624
  return queryId;
1623
1625
  }
1624
1626
  /**
1625
- * Get a stored query by its ID (not expired)
1627
+ * Get a stored query by its ID.
1628
+ * The SQL mapping never expires (queryIds are persisted in dashboard widgets).
1629
+ * Cached data may be null if it was evicted by the cleanup interval.
1626
1630
  */
1627
1631
  getQuery(queryId) {
1628
1632
  const entry = this.queryIdCache.get(queryId);
1629
1633
  if (!entry) return null;
1630
- if (Date.now() - entry.timestamp > this.ttlMs) {
1631
- this.queryIdCache.delete(queryId);
1632
- return null;
1633
- }
1634
+ entry.timestamp = Date.now();
1634
1635
  return { query: entry.query, data: entry.data };
1635
1636
  }
1636
1637
  /**
@@ -7946,17 +7947,8 @@ ${executedToolsText}`);
7946
7947
  let matchedComponents = result.matchedComponents || [];
7947
7948
  const layoutTitle = result.layoutTitle || "Dashboard";
7948
7949
  const layoutDescription = result.layoutDescription || "Multi-component dashboard";
7949
- const complexityMatch = analysisContent.match(/\[COMPLEXITY:\s*(simple|medium|complex)\]/i);
7950
- const complexity = complexityMatch ? complexityMatch[1].toLowerCase() : "medium";
7951
- const maxVisualizations = complexity === "simple" ? 1 : complexity === "medium" ? 3 : 5;
7952
- const markdownComps = matchedComponents.filter((mc) => mc.componentName === "DynamicMarkdownBlock");
7953
7950
  const vizComps = matchedComponents.filter((mc) => mc.componentName !== "DynamicMarkdownBlock");
7954
- if (vizComps.length > maxVisualizations) {
7955
- logger.info(`[AgentComponentGen] Trimming ${vizComps.length} visualizations to ${maxVisualizations} (complexity: ${complexity})`);
7956
- matchedComponents = [...vizComps.slice(0, maxVisualizations), ...markdownComps];
7957
- } else {
7958
- logger.info(`[AgentComponentGen] Complexity: ${complexity} | ${vizComps.length} visualizations (limit: ${maxVisualizations})`);
7959
- }
7951
+ logger.info(`[AgentComponentGen] ${vizComps.length} visualizations, ${matchedComponents.length - vizComps.length} markdown blocks`);
7960
7952
  if (result.hasAnswerComponent && result.answerComponent?.componentId) {
7961
7953
  const answer = result.answerComponent;
7962
7954
  const answerSql = answer.props?.externalTool?.parameters?.sql || "";
@@ -14714,8 +14706,15 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
14714
14706
  5
14715
14707
  // max iterations
14716
14708
  );
14717
- const jsonMatch = rawResult.match(/\{[\s\S]*\}/);
14718
- const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
14709
+ const cleaned = rawResult.replace(/```(?:json)?\s*/g, "").replace(/```\s*/g, "");
14710
+ const jsonMatch = cleaned.match(/\{[\s\S]*\}/);
14711
+ const result = jsonMatch ? (() => {
14712
+ try {
14713
+ return JSON.parse(jsonMatch[0]);
14714
+ } catch {
14715
+ return null;
14716
+ }
14717
+ })() : null;
14719
14718
  if (!result) {
14720
14719
  errors.push("Failed to parse LLM response as JSON");
14721
14720
  errors.push(`LLM Response: ${rawResult}`);