@axiom-lattice/core 2.1.33 → 2.1.35

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
@@ -338,7 +338,7 @@ var ModelLattice = class extends BaseChatModel {
338
338
  streaming: config.streaming
339
339
  });
340
340
  } else if (config.provider === "deepseek") {
341
- return new ChatDeepSeek({
341
+ const deepseek = new ChatDeepSeek({
342
342
  model: config.model,
343
343
  temperature: config.temperature || 0,
344
344
  maxTokens: config.maxTokens,
@@ -346,10 +346,12 @@ var ModelLattice = class extends BaseChatModel {
346
346
  maxRetries: config.maxRetries || 2,
347
347
  apiKey: config.apiKey || process.env[config.apiKeyEnvName || "DEEPSEEK_API_KEY"],
348
348
  streaming: config.streaming,
349
+ enable_thinking: true,
349
350
  configuration: {
350
351
  baseURL: config.baseURL
351
352
  }
352
353
  });
354
+ return deepseek;
353
355
  } else if (config.provider === "siliconcloud") {
354
356
  return new ChatOpenAI({
355
357
  model: config.model,
@@ -1432,6 +1434,37 @@ ${databaseKeys.map(
1432
1434
  );
1433
1435
  };
1434
1436
 
1437
+ // src/tool_lattice/metrics/utils.ts
1438
+ function getTenantIdFromConfig2(exeConfig, getTenantId) {
1439
+ const runConfig = exeConfig?.configurable?.runConfig || {};
1440
+ return runConfig.tenantId || (getTenantId ? getTenantId() : "default");
1441
+ }
1442
+ function filterServerKeysByTenant(serverKeys, tenantId, manager = metricsServerManager) {
1443
+ return serverKeys.filter((key) => {
1444
+ return manager.hasServer(tenantId, key);
1445
+ });
1446
+ }
1447
+ function arrayRowsToObjectRows(rows, columns) {
1448
+ if (!rows || rows.length === 0) {
1449
+ return [];
1450
+ }
1451
+ return rows.map((row) => {
1452
+ const obj = {};
1453
+ columns.forEach((col, index) => {
1454
+ obj[col.name] = row[index];
1455
+ });
1456
+ return obj;
1457
+ });
1458
+ }
1459
+ function objectRowsToArrayRows(rows, columns) {
1460
+ if (!rows || rows.length === 0) {
1461
+ return [];
1462
+ }
1463
+ return rows.map(
1464
+ (row) => columns.map((col) => row[col])
1465
+ );
1466
+ }
1467
+
1435
1468
  // src/tool_lattice/metrics/SemanticMetricsClient.ts
1436
1469
  var SemanticMetricsClient = class {
1437
1470
  constructor(config) {
@@ -1561,15 +1594,34 @@ var SemanticMetricsClient = class {
1561
1594
  limit: 1e3
1562
1595
  };
1563
1596
  const result = await this.semanticQuery(request);
1564
- const metricResult = result.results.find((r) => r.metricName === metricName);
1565
- const dataPoints = metricResult?.rows.map((row, index) => ({
1566
- timestamp: index * 1e3,
1567
- // Use index as timestamp if not provided
1568
- value: typeof row.value === "number" ? row.value : 0,
1569
- labels: Object.fromEntries(
1570
- Object.entries(row).map(([k, v]) => [k, String(v)])
1571
- )
1572
- })) || [];
1597
+ const dataPoints = [];
1598
+ if (result.rows && result.rows.length > 0) {
1599
+ const columnNames = result.columns.map((col) => col.name);
1600
+ result.rows.forEach((row, index) => {
1601
+ const rowObj = {};
1602
+ columnNames.forEach((colName, colIndex) => {
1603
+ rowObj[colName] = row[colIndex];
1604
+ });
1605
+ dataPoints.push({
1606
+ timestamp: index * 1e3,
1607
+ // Use index as timestamp if not provided
1608
+ value: typeof rowObj[metricName] === "number" ? rowObj[metricName] : 0,
1609
+ labels: Object.fromEntries(
1610
+ Object.entries(rowObj).map(([k, v]) => [k, String(v)])
1611
+ )
1612
+ });
1613
+ });
1614
+ } else if (result.rowsObject && result.rowsObject.length > 0) {
1615
+ result.rowsObject.forEach((row, index) => {
1616
+ dataPoints.push({
1617
+ timestamp: index * 1e3,
1618
+ value: typeof row[metricName] === "number" ? row[metricName] : 0,
1619
+ labels: Object.fromEntries(
1620
+ Object.entries(row).map(([k, v]) => [k, String(v)])
1621
+ )
1622
+ });
1623
+ });
1624
+ }
1573
1625
  return {
1574
1626
  metricName,
1575
1627
  dataPoints,
@@ -1630,30 +1682,92 @@ var SemanticMetricsClient = class {
1630
1682
  /**
1631
1683
  * Execute a semantic metrics query
1632
1684
  * POST /metrics/query
1685
+ *
1686
+ * @param request - Query request with optional format parameter
1687
+ * @returns Standardized query response based on format specification
1633
1688
  */
1634
1689
  async semanticQuery(request) {
1690
+ const format = request.format ?? "array";
1635
1691
  const response = await fetch(`${this.baseUrl}/metrics/query`, {
1636
1692
  method: "POST",
1637
1693
  headers: {
1638
1694
  ...this.getHeaders(),
1639
1695
  "Content-Type": "application/json"
1640
1696
  },
1641
- body: JSON.stringify(request)
1697
+ body: JSON.stringify({ ...request, debug: true })
1642
1698
  });
1643
1699
  if (!response.ok) {
1644
1700
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1645
1701
  }
1646
- const data = await response.json();
1647
- if (data.code !== 200) {
1648
- throw new Error(`API error: ${data.message}`);
1702
+ const apiResponse = await response.json();
1703
+ if (apiResponse.code !== 200) {
1704
+ throw new Error(`API error: ${apiResponse.message}`);
1649
1705
  }
1650
- return data.data;
1706
+ const data = apiResponse.data;
1707
+ const result = {
1708
+ semanticModel: data.semanticModel,
1709
+ columns: data.columns,
1710
+ rowCount: data.rows?.length ?? 0
1711
+ };
1712
+ if (format === "array" || format === "both") {
1713
+ result.rows = data.rows;
1714
+ }
1715
+ if (format === "object" || format === "both") {
1716
+ result.rowsObject = arrayRowsToObjectRows(data.rows, data.columns);
1717
+ }
1718
+ return result;
1719
+ }
1720
+ /**
1721
+ * Execute a table query
1722
+ * GET /api/metrics/table/{tableName}
1723
+ *
1724
+ * @param request - Table query request with optional format parameter
1725
+ * @returns Standardized table query response based on format specification
1726
+ */
1727
+ async tableQuery(request) {
1728
+ const format = request.format ?? "object";
1729
+ const { tableName, limit = 20 } = request;
1730
+ const queryParams = new URLSearchParams();
1731
+ queryParams.append("limit", limit.toString());
1732
+ const response = await fetch(
1733
+ `${this.baseUrl}/api/metrics/table/${encodeURIComponent(tableName)}?${queryParams}`,
1734
+ {
1735
+ method: "GET",
1736
+ headers: this.getHeaders()
1737
+ }
1738
+ );
1739
+ if (!response.ok) {
1740
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1741
+ }
1742
+ const apiResponse = await response.json();
1743
+ if (apiResponse.code !== 200) {
1744
+ throw new Error(`API error: ${apiResponse.message}`);
1745
+ }
1746
+ const data = apiResponse.data;
1747
+ const result = {
1748
+ tableName: data.tableName,
1749
+ columns: data.columns,
1750
+ rowCount: data.rowCount,
1751
+ executionTimeMs: data.executionTimeMs,
1752
+ executedSql: data.executedSql
1753
+ };
1754
+ if (format === "object" || format === "both") {
1755
+ result.rowsObject = data.rows;
1756
+ }
1757
+ if (format === "array" || format === "both") {
1758
+ result.rows = objectRowsToArrayRows(data.rows, data.columns);
1759
+ }
1760
+ return result;
1651
1761
  }
1652
1762
  /**
1653
1763
  * Execute a custom SQL query
1654
1764
  * POST /metrics/query
1765
+ *
1766
+ * @param request - SQL query request with optional format parameter
1767
+ * @returns Standardized query response based on format specification
1655
1768
  */
1656
1769
  async executeSqlQuery(request) {
1770
+ const format = request.format ?? "object";
1657
1771
  const response = await fetch(`${this.baseUrl}/metrics/query`, {
1658
1772
  method: "POST",
1659
1773
  headers: {
@@ -1665,11 +1779,27 @@ var SemanticMetricsClient = class {
1665
1779
  if (!response.ok) {
1666
1780
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1667
1781
  }
1668
- const data = await response.json();
1669
- if (data.code !== 200) {
1670
- throw new Error(`API error: ${data.message}`);
1782
+ const apiResponse = await response.json();
1783
+ if (apiResponse.code !== 200) {
1784
+ throw new Error(`API error: ${apiResponse.message}`);
1785
+ }
1786
+ const data = apiResponse.data;
1787
+ const result = {
1788
+ datasourceId: data.datasourceId,
1789
+ datasourceName: data.datasourceName,
1790
+ tableName: data.tableName,
1791
+ columns: data.columns,
1792
+ rowCount: data.rowCount,
1793
+ executionTimeMs: data.executionTimeMs,
1794
+ executedSql: data.executedSql
1795
+ };
1796
+ if (format === "object" || format === "both") {
1797
+ result.rowsObject = data.rows;
1671
1798
  }
1672
- return data.data;
1799
+ if (format === "array" || format === "both") {
1800
+ result.rows = objectRowsToArrayRows(data.rows, data.columns);
1801
+ }
1802
+ return result;
1673
1803
  }
1674
1804
  /**
1675
1805
  * Get selected data sources for this configuration
@@ -2158,19 +2288,6 @@ var metricsServerManager = MetricsServerManager.getInstance();
2158
2288
  // src/tool_lattice/metrics/list_metrics_servers.ts
2159
2289
  import z7 from "zod";
2160
2290
  import { tool as tool6 } from "langchain";
2161
-
2162
- // src/tool_lattice/metrics/utils.ts
2163
- function getTenantIdFromConfig2(exeConfig, getTenantId) {
2164
- const runConfig = exeConfig?.configurable?.runConfig || {};
2165
- return runConfig.tenantId || (getTenantId ? getTenantId() : "default");
2166
- }
2167
- function filterServerKeysByTenant(serverKeys, tenantId, manager = metricsServerManager) {
2168
- return serverKeys.filter((key) => {
2169
- return manager.hasServer(tenantId, key);
2170
- });
2171
- }
2172
-
2173
- // src/tool_lattice/metrics/list_metrics_servers.ts
2174
2291
  var LIST_METRICS_SERVERS_DESCRIPTION = `List all registered metrics servers. Returns a list of available metrics servers with their keys and types. Use this tool first to understand what metrics servers are available.`;
2175
2292
  var createListMetricsServersTool = ({ serverKeys, serverDescriptions, getTenantId }) => {
2176
2293
  const availableServersText = serverKeys.length > 0 ? `
@@ -2545,176 +2662,7 @@ ${serverKeys.map(
2545
2662
  if (!foundDetail) {
2546
2663
  return `Metric "${metricName}" not found in the specified data sources.`;
2547
2664
  }
2548
- const lines = [];
2549
- lines.push(`# ${foundDetail.displayName} (${foundDetail.metricName})`);
2550
- lines.push("");
2551
- lines.push(`## Basic Information`);
2552
- lines.push("");
2553
- lines.push(`- **Metric Name**: ${foundDetail.metricName}`);
2554
- lines.push(`- **Display Name**: ${foundDetail.displayName}`);
2555
- lines.push(`- **Domain**: ${foundDetail.domain}`);
2556
- lines.push(`- **Data Type**: ${foundDetail.dataType}`);
2557
- lines.push(`- **Format**: ${foundDetail.format}`);
2558
- if (foundDatasourceId) {
2559
- lines.push(`- **Data Source ID**: ${foundDatasourceId}`);
2560
- }
2561
- lines.push("");
2562
- lines.push(`## Description`);
2563
- lines.push("");
2564
- lines.push(foundDetail.description);
2565
- lines.push("");
2566
- if (foundDetail.defaultTimeContext) {
2567
- const dtc = foundDetail.defaultTimeContext;
2568
- lines.push(`## Time Context`);
2569
- lines.push("");
2570
- if (dtc.timeDimension) {
2571
- lines.push(`- **Time Dimension**: ${dtc.timeDimension}${dtc.label ? ` (${dtc.label})` : ""}`);
2572
- }
2573
- if (dtc.granularity) {
2574
- lines.push(`- **Default Granularity**: ${dtc.granularity}`);
2575
- }
2576
- if (dtc.window) {
2577
- lines.push(`- **Default Window**: ${dtc.window}`);
2578
- }
2579
- const grains = dtc.supportedGrains;
2580
- lines.push(`- **Supported Grains**: ${Array.isArray(grains) && grains.length > 0 ? grains.join(", ") : "Not configured"}`);
2581
- lines.push("");
2582
- }
2583
- if (foundDetail.supportedDimensions && foundDetail.supportedDimensions.length > 0) {
2584
- const categoricalDims = foundDetail.supportedDimensions.filter((d) => d.type === "categorical");
2585
- const datetimeDims = foundDetail.supportedDimensions.filter((d) => d.type === "datetime");
2586
- const timeDimension = foundDetail.defaultTimeContext?.timeDimension;
2587
- lines.push(`## Supported Dimensions`);
2588
- lines.push("");
2589
- if (categoricalDims.length > 0) {
2590
- lines.push(`### Categorical Dimensions - ${categoricalDims.length}`);
2591
- lines.push("Supports IN (multiple), EQ (single) operators");
2592
- lines.push("");
2593
- const examples = categoricalDims.slice(0, 2);
2594
- for (const dim of examples) {
2595
- lines.push(`**${dim.dim_id}** (${dim.field_name})`);
2596
- lines.push("```json");
2597
- lines.push(`// Grouping example`);
2598
- lines.push(`"groupBy": ["${dim.dim_id}"]`);
2599
- lines.push("");
2600
- lines.push(`// Filter example`);
2601
- lines.push(`{"dimension": "${dim.dim_id}", "operator": "IN", "values": ["value1", "value2"]}`);
2602
- lines.push("```");
2603
- lines.push("");
2604
- }
2605
- if (categoricalDims.length > 2) {
2606
- const others = categoricalDims.slice(2).map((d) => d.dim_id).join(", ");
2607
- lines.push(`**Other ${categoricalDims.length - 2} dimensions**: ${others}`);
2608
- lines.push("");
2609
- }
2610
- }
2611
- if (datetimeDims.length > 0) {
2612
- lines.push(`### Datetime Dimensions - ${datetimeDims.length}`);
2613
- lines.push("Supports BETWEEN (range), GT/GTE/LT/LTE (comparison) operators");
2614
- lines.push("");
2615
- const primaryDim = datetimeDims.find((d) => d.dim_id === timeDimension) || datetimeDims[0];
2616
- lines.push(`**${primaryDim.dim_id}** (${primaryDim.field_name})`);
2617
- lines.push("```json");
2618
- lines.push(`// Group by time grain`);
2619
- lines.push(`"groupBy": ["${primaryDim.dim_id}__month"] // Options: day, week, month, year`);
2620
- lines.push("");
2621
- lines.push(`// Time range filter`);
2622
- lines.push(`{"dimension": "${primaryDim.dim_id}", "operator": "BETWEEN", "values": ["2025-01-01", "2025-12-31"]}`);
2623
- lines.push("```");
2624
- lines.push("");
2625
- if (datetimeDims.length > 1) {
2626
- const others = datetimeDims.filter((d) => d.dim_id !== primaryDim.dim_id).map((d) => d.dim_id).join(", ");
2627
- lines.push(`**Other time dimensions**: ${others}`);
2628
- lines.push("");
2629
- }
2630
- }
2631
- lines.push("### Quick Reference");
2632
- lines.push("");
2633
- lines.push("**Time grouping format**: `{timeDimension}__{grain}`");
2634
- lines.push("- By day: `DocDate__day`");
2635
- lines.push("- By week: `DocDate__week`");
2636
- lines.push("- By month: `DocDate__month`");
2637
- lines.push("- By year: `DocDate__year`");
2638
- lines.push("");
2639
- }
2640
- if (foundDetail.aiAgentContext) {
2641
- const aiContext = foundDetail.aiAgentContext;
2642
- lines.push(`## AI Analysis Context`);
2643
- lines.push("");
2644
- if (aiContext.polarity) {
2645
- lines.push(`### Metric Polarity`);
2646
- lines.push("");
2647
- lines.push(aiContext.polarity === "positive" ? "Positive metric (higher is better)" : "Negative metric (lower is better)");
2648
- lines.push("");
2649
- }
2650
- if (aiContext.synonyms && aiContext.synonyms.length > 0) {
2651
- lines.push(`### Synonyms/Aliases`);
2652
- lines.push("");
2653
- lines.push(aiContext.synonyms.join(", "));
2654
- lines.push("");
2655
- }
2656
- if (aiContext.thresholds && aiContext.thresholds.length > 0) {
2657
- lines.push(`### Alert Thresholds`);
2658
- lines.push("");
2659
- lines.push("| Metric | Operator | Threshold | Level |");
2660
- lines.push("|--------|----------|-----------|-------|");
2661
- for (const t of aiContext.thresholds) {
2662
- lines.push(`| ${t.metric} | ${t.operator} | ${t.value} | ${t.level} |`);
2663
- }
2664
- lines.push("");
2665
- }
2666
- if (aiContext.diagnosticWorkflow) {
2667
- lines.push(`### Diagnostic Workflow`);
2668
- lines.push("");
2669
- if (aiContext.diagnosticWorkflow.trigger && aiContext.diagnosticWorkflow.trigger.any_of) {
2670
- lines.push(`**Trigger Conditions** (satisfy any):`);
2671
- for (const trigger of aiContext.diagnosticWorkflow.trigger.any_of) {
2672
- if (trigger.metric && trigger.operator) {
2673
- lines.push(`- ${trigger.metric} ${trigger.operator} ${trigger.value ?? "N/A"}`);
2674
- }
2675
- }
2676
- lines.push("");
2677
- }
2678
- if (aiContext.diagnosticWorkflow.actions && aiContext.diagnosticWorkflow.actions.length > 0) {
2679
- lines.push(`**Analysis Actions**:`);
2680
- for (let i = 0; i < aiContext.diagnosticWorkflow.actions.length; i++) {
2681
- const action = aiContext.diagnosticWorkflow.actions[i];
2682
- if (!action) continue;
2683
- lines.push(`${i + 1}. **${action.type ?? "Unnamed Action"}**`);
2684
- if (action.metric) {
2685
- lines.push(` - Comparison Metric: ${action.metric}`);
2686
- }
2687
- if (action.dimensions && action.dimensions.length > 0) {
2688
- lines.push(` - Drill-down Dimensions: ${action.dimensions.join(", ")}`);
2689
- }
2690
- if (action.intent) {
2691
- lines.push(` - Intent: ${action.intent}`);
2692
- }
2693
- }
2694
- lines.push("");
2695
- }
2696
- if (aiContext.diagnosticWorkflow.analysis_logic) {
2697
- lines.push(`**Analysis Logic**: ${aiContext.diagnosticWorkflow.analysis_logic}`);
2698
- lines.push("");
2699
- }
2700
- }
2701
- if (aiContext.humanReadableExplanation) {
2702
- lines.push(`### System Recommendations`);
2703
- lines.push("");
2704
- lines.push(aiContext.humanReadableExplanation);
2705
- lines.push("");
2706
- }
2707
- }
2708
- lines.push(`---`);
2709
- lines.push("");
2710
- lines.push(`## Usage Example`);
2711
- lines.push("");
2712
- lines.push(`To query this metric, use the query_semantic_metric_data tool with parameters:`);
2713
- lines.push(`- **metricName**: "${foundDetail.metricName}"`);
2714
- if (foundDatasourceId) {
2715
- lines.push(`- **datasourceId**: "${foundDatasourceId}"`);
2716
- }
2717
- return lines.join("\n");
2665
+ return JSON.stringify(foundDetail, null, 2);
2718
2666
  } catch (error) {
2719
2667
  return `Error querying metric definition: ${error instanceof Error ? error.message : String(error)}`;
2720
2668
  }
@@ -2752,11 +2700,19 @@ Skip using this tool when:
2752
2700
  Prerequisites - MUST Complete First
2753
2701
  1. Call query_metrics_list to discover available metrics
2754
2702
  2. Call query_metric_definition(metricName) to get:
2755
- - defaultTimeContext.timeDimension (e.g., "DocDate")
2703
+ - defaultTimeContext.timeDimension (e.g., "DocDate","date")
2756
2704
  - defaultTimeContext.supportedGrains (e.g., ["day", "week", "month", "year"])
2757
2705
  - supportedDimensions[].dim_id (use these for groupBy and filters)
2758
2706
  - supportedDimensions[].filter_operators (allowed operators per dimension)
2759
2707
 
2708
+ **Rules**:
2709
+ - To filter by date: Copy the pattern and replace values
2710
+ \`\`\`json
2711
+ {"dimension": "DocDate", "operator": "BETWEEN", "values": ["2025-01-01", "2025-12-31"]}
2712
+ \`\`\`
2713
+ - To group by time: Use \`"{timeDimension}__{supportedGrain}"\` format (e.g., \`"date__month"\`)
2714
+
2715
+
2760
2716
  The Five Query Patterns
2761
2717
 
2762
2718
  Pattern A - Time Trend (most common first query)
@@ -2764,8 +2720,8 @@ Goal: Show how a metric changes over time within a period
2764
2720
  {
2765
2721
  "metrics": ["order_amt_tax_inc"],
2766
2722
  "groupBy": ["DocDate__month"],
2767
- "filters": [{ "dimension": "DocDate", "operator": "BETWEEN", "values": ["2025-01-01", "2025-12-31"] }],
2768
- "orderBy": [{ "field": "DocDate__month", "direction": "ASC" }]
2723
+ "filters": [{ "dimension": "date", "operator": "BETWEEN", "values": ["2025-01-01", "2025-12-31"] }],
2724
+ "orderBy": [{ "field": "date__month", "direction": "ASC" }]
2769
2725
  }
2770
2726
 
2771
2727
  Pattern B - Dimension Breakdown (who/what is top or bottom)
@@ -2830,82 +2786,50 @@ Common Mistakes to Avoid
2830
2786
  - Omitting date filter entirely - ALWAYS include at least one DocDate filter
2831
2787
  - Querying a metric by an unsupported dimension - only use dim_id from supportedDimensions
2832
2788
  - Putting display name in orderBy.field - must match exactly what's in groupBy
2833
-
2834
- Recommended Analysis Flow
2835
- User question
2836
- |
2837
- \u25BC
2838
- Step 1: query_metrics_list - find matching metric(s)
2839
- |
2840
- \u25BC
2841
- Step 2: query_metric_definition - read defaultTimeContext + supportedDimensions
2842
- |
2843
- \u25BC
2844
- Step 3a: Pattern A (time trend) - get the big picture
2845
- |
2846
- \u251C\u2500 anomaly found? \u2500\u2500\u25BA Step 3c: Pattern C (drill down)
2847
- \u251C\u2500 user asks "who"? \u2500\u2500\u25BA Step 3b: Pattern B (dimension breakdown)
2848
- \u2514\u2500 user asks "compare X and Y"? \u2500\u2500\u25BA Step 3d: Pattern D (multi-metric)
2849
-
2850
- Debug Mode
2851
- Set "debug": true to receive executedSqls in the response to verify generated SQL.`;
2852
- function formatSemanticQueryResult(datasourceId, datasourceName, results) {
2853
- if (results.length === 0) {
2789
+ `;
2790
+ function formatSemanticQueryResult(result) {
2791
+ const { semanticModel, columns, rowCount } = result;
2792
+ if (!columns || columns.length === 0 || rowCount === 0) {
2854
2793
  return `No data found for the specified query.
2855
- Data Source: ${datasourceId}${datasourceName ? ` (${datasourceName})` : ""}`;
2794
+ Semantic Model: ${semanticModel}`;
2856
2795
  }
2857
2796
  const lines = [];
2858
2797
  lines.push(`# Metric Query Results`);
2859
2798
  lines.push(`
2860
- **Data Source**: ${datasourceId}${datasourceName ? ` (${datasourceName})` : ""}`);
2861
- lines.push(`**Metrics Count**: ${results.length}`);
2799
+ **Semantic Model**: ${semanticModel}`);
2800
+ lines.push(`**Columns**: ${columns.length}`);
2801
+ lines.push(`**Rows**: ${rowCount}`);
2862
2802
  lines.push(`
2863
2803
  ---
2864
2804
  `);
2865
- for (const metric of results) {
2866
- lines.push(`## ${metric.displayName} (${metric.metricName})`);
2867
- lines.push(`
2868
- - **Data Type**: ${metric.dataType}`);
2869
- lines.push(`- **Format**: ${metric.format}`);
2870
- lines.push(`- **Polarity**: ${metric.polarity}`);
2871
- lines.push(`- **Execution Time**: ${metric.executionTimeMs}ms`);
2872
- lines.push(`- **Rows Returned**: ${metric.rowCount}`);
2873
- if (metric.columns.length > 0 && metric.rows.length > 0) {
2874
- lines.push(`
2875
- ### Data
2805
+ const rows = result.rowsObject ?? result.rows ?? [];
2806
+ if (rows.length === 0) {
2807
+ lines.push(`*No data rows returned*
2876
2808
  `);
2877
- lines.push(`| ${metric.columns.join(" | ")} |`);
2878
- lines.push(`|${metric.columns.map(() => "---").join("|")}|`);
2879
- for (const row of metric.rows) {
2880
- const rowValues = metric.columns.map((col) => {
2881
- const val = row[col];
2882
- return val !== void 0 ? String(val) : "";
2883
- });
2884
- lines.push(`| ${rowValues.join(" | ")} |`);
2885
- }
2886
- }
2887
- if (metric.aiHints) {
2888
- lines.push(`
2889
- ### AI Analysis Suggestions
2809
+ return lines.join("\n");
2810
+ }
2811
+ const columnNames = columns.map((col) => col.name);
2812
+ lines.push(`## Data
2890
2813
  `);
2891
- lines.push(`- **Value Interpretation**: ${metric.aiHints.valueInterpretation}`);
2892
- if (metric.aiHints.thresholds && metric.aiHints.thresholds.length > 0) {
2893
- lines.push(`- **Alert Thresholds**:`);
2894
- for (const t of metric.aiHints.thresholds) {
2895
- lines.push(` - ${t.metric} ${t.operator} ${t.value} (${t.level})`);
2896
- }
2897
- }
2898
- if (metric.aiHints.suggestedFollowup && metric.aiHints.suggestedFollowup.length > 0) {
2899
- lines.push(`- **Suggested Follow-up Analysis**:`);
2900
- for (const suggestion of metric.aiHints.suggestedFollowup) {
2901
- lines.push(` - ${suggestion}`);
2902
- }
2903
- }
2814
+ lines.push(`| ${columnNames.join(" | ")} |`);
2815
+ lines.push(`|${columnNames.map(() => "---").join("|")}|`);
2816
+ if (result.rowsObject) {
2817
+ for (const row of result.rowsObject) {
2818
+ const rowValues = columnNames.map((col) => {
2819
+ const val = row[col];
2820
+ return val !== void 0 && val !== null ? String(val) : "";
2821
+ });
2822
+ lines.push(`| ${rowValues.join(" | ")} |`);
2904
2823
  }
2905
- lines.push(`
2824
+ } else if (result.rows) {
2825
+ for (const row of result.rows) {
2826
+ const rowValues = row.map((val) => val !== void 0 && val !== null ? String(val) : "");
2827
+ lines.push(`| ${rowValues.join(" | ")} |`);
2828
+ }
2829
+ }
2830
+ lines.push(`
2906
2831
  ---
2907
2832
  `);
2908
- }
2909
2833
  return lines.join("\n");
2910
2834
  }
2911
2835
  var createQuerySemanticMetricDataTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
@@ -2965,11 +2889,7 @@ ${serverKeys.map(
2965
2889
  filters: semanticFilters,
2966
2890
  limit: limit || 1e3
2967
2891
  });
2968
- return formatSemanticQueryResult(
2969
- result.datasourceId,
2970
- result.datasourceName,
2971
- result.results
2972
- );
2892
+ return formatSemanticQueryResult(result);
2973
2893
  } catch (error) {
2974
2894
  return `Error querying semantic metric data: ${error instanceof Error ? error.message : String(error)}`;
2975
2895
  }
@@ -3288,7 +3208,7 @@ ${serverKeys.map(
3288
3208
  params,
3289
3209
  limit: limit || 100
3290
3210
  });
3291
- const rows = result.result?.rows || [];
3211
+ const rows = result.rowsObject ?? result.rows ?? [];
3292
3212
  return "query_result:\n" + JSON.stringify(rows, null, 2);
3293
3213
  } catch (error) {
3294
3214
  return `Error executing SQL query: ${error instanceof Error ? error.message : String(error)}`;
@@ -8313,7 +8233,7 @@ var ReActAgentGraphBuilder = class {
8313
8233
  let workingDirectory = "/";
8314
8234
  if (workspaceId && projectId) {
8315
8235
  if (tenantId) {
8316
- workingDirectory = `/tenants/${tenantId}/${workspaceId}/${projectId}`;
8236
+ workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
8317
8237
  } else {
8318
8238
  workingDirectory = `/${workspaceId}/${projectId}`;
8319
8239
  }
@@ -8715,6 +8635,7 @@ async function executeNode(state) {
8715
8635
  const { assistant_id, thread_id, input, command2, runConfig } = state;
8716
8636
  const callParams = {
8717
8637
  assistant_id,
8638
+ "x-tenant-id": runConfig?.tenantId,
8718
8639
  thread_id,
8719
8640
  input,
8720
8641
  command: command2,
@@ -8971,7 +8892,9 @@ function getSubagents(options) {
8971
8892
  model: defaultModel,
8972
8893
  systemPrompt: DEFAULT_SUBAGENT_PROMPT,
8973
8894
  tools: defaultTools,
8974
- middleware: generalPurposeMiddleware
8895
+ middleware: generalPurposeMiddleware,
8896
+ checkpointer: getCheckpointSaver("default"),
8897
+ name: "general-purpose"
8975
8898
  });
8976
8899
  agents["general-purpose"] = generalPurposeSubagent;
8977
8900
  subagentDescriptions.push(
@@ -8993,7 +8916,8 @@ function getSubagents(options) {
8993
8916
  model: agentParams.model ?? defaultModel,
8994
8917
  systemPrompt: agentParams.systemPrompt,
8995
8918
  tools: agentParams.tools ?? defaultTools,
8996
- middleware
8919
+ middleware,
8920
+ checkpointer: getCheckpointSaver("default")
8997
8921
  });
8998
8922
  }
8999
8923
  }
@@ -9021,6 +8945,24 @@ function createTaskTool(options) {
9021
8945
  return tool44(
9022
8946
  async (input, config) => {
9023
8947
  const { description, subagent_type } = input;
8948
+ let assistant_id = subagent_type;
8949
+ if (subagent_type === "general-purpose") {
8950
+ assistant_id = config.configurable?.runConfig?.assistant_id + "-general-purpose";
8951
+ const hasAgentLattice = agentLatticeManager.hasAgentLatticeWithTenant(config.configurable?.runConfig?.tenantId, assistant_id);
8952
+ if (!hasAgentLattice) {
8953
+ const client = subagentGraphs["general-purpose"];
8954
+ agentLatticeManager.registerWithTenant(config.configurable?.runConfig?.tenantId, assistant_id, {
8955
+ config: {
8956
+ key: assistant_id,
8957
+ name: "general-purpose",
8958
+ description: DEFAULT_GENERAL_PURPOSE_DESCRIPTION,
8959
+ type: AgentType.REACT,
8960
+ prompt: DEFAULT_SUBAGENT_PROMPT
8961
+ },
8962
+ client
8963
+ });
8964
+ }
8965
+ }
9024
8966
  try {
9025
8967
  if (!(subagent_type in subagentGraphs)) {
9026
8968
  const allowedTypes = Object.keys(subagentGraphs).map((k) => `\`${k}\``).join(", ");
@@ -9028,19 +8970,18 @@ function createTaskTool(options) {
9028
8970
  `Error: invoked agent of type ${subagent_type}, the only allowed types are ${allowedTypes}`
9029
8971
  );
9030
8972
  }
9031
- const subagent = subagentGraphs[subagent_type];
9032
8973
  const currentState = getCurrentTaskInput2();
9033
8974
  const subagentState = filterStateForSubagent(currentState);
9034
8975
  subagentState.messages = [new HumanMessage({ content: description })];
9035
- const subagent_thread_id = config.configurable?.thread_id + "____" + subagent_type + "_" + config.toolCall.id;
8976
+ const subagent_thread_id = config.configurable?.thread_id + "____" + assistant_id + "_" + config.toolCall.id;
9036
8977
  console.log(subagent_thread_id);
9037
8978
  const workerResult = await agentWorkerGraph.invoke({
9038
- assistant_id: subagent_type,
8979
+ assistant_id,
9039
8980
  thread_id: subagent_thread_id,
9040
8981
  input: { ...subagentState, message: description },
9041
8982
  runConfig: {
9042
8983
  ...config.configurable?.runConfig,
9043
- assistant_id: subagent_type,
8984
+ assistant_id,
9044
8985
  thread_id: subagent_thread_id
9045
8986
  }
9046
8987
  });
@@ -10580,11 +10521,12 @@ ${BASE_PROMPT}` : BASE_PROMPT;
10580
10521
  unsupportedModelBehavior: "ignore"
10581
10522
  }),
10582
10523
  // Subagent middleware: Patches tool calls for compatibility
10583
- createPatchToolCallsMiddleware()
10524
+ createPatchToolCallsMiddleware(),
10525
+ ...customMiddleware
10584
10526
  ],
10585
10527
  defaultInterruptOn: interruptOn,
10586
10528
  subagents,
10587
- generalPurposeAgent: false
10529
+ generalPurposeAgent: true
10588
10530
  }),
10589
10531
  // Automatically summarizes conversation history when token limits are approached
10590
10532
  summarizationMiddleware({
@@ -11565,14 +11507,19 @@ You have access to these tools:
11565
11507
  middleware: [...teamMiddleware ?? [], ...spec.middleware ?? []],
11566
11508
  checkpointer: getCheckpointSaver("default")
11567
11509
  });
11568
- registerTeammateAgent(assistantId, agent);
11510
+ registerTeammateAgent(assistantId, agent, ctx.tenantId);
11569
11511
  const teammateThreadId = ctx.parentThreadId ? `${ctx.parentThreadId}____${ctx.teamId}_${spec.name}` : `standalone_${ctx.teamId}_${spec.name}`;
11570
11512
  const startMessage = "Start working";
11571
11513
  try {
11572
11514
  await agentWorkerGraph.invoke({
11573
11515
  assistant_id: assistantId,
11574
11516
  thread_id: teammateThreadId,
11575
- input: { message: startMessage, messages: [{ role: "human", content: startMessage }] }
11517
+ input: { message: startMessage, messages: [{ role: "human", content: startMessage }] },
11518
+ runConfig: {
11519
+ tenantId: ctx.tenantId,
11520
+ workspaceId: ctx.workspaceId,
11521
+ projectId: ctx.projectId
11522
+ }
11576
11523
  });
11577
11524
  } catch (err) {
11578
11525
  const errorMsg = err instanceof Error ? err.message : "Unknown error during teammate execution";
@@ -11596,7 +11543,10 @@ async function spawnTeammate(options) {
11596
11543
  defaultModel,
11597
11544
  parentThreadId = "",
11598
11545
  teamTools,
11599
- teamMiddleware
11546
+ teamMiddleware,
11547
+ tenantId,
11548
+ workspaceId,
11549
+ projectId
11600
11550
  } = options;
11601
11551
  const ctx = {
11602
11552
  teamId,
@@ -11608,12 +11558,15 @@ async function spawnTeammate(options) {
11608
11558
  defaultModel,
11609
11559
  pollIntervalMs: DEFAULT_POLL_INTERVAL_MS,
11610
11560
  scheduleLatticeKey: DEFAULT_SCHEDULE_LATTICE_KEY,
11611
- agentCache: /* @__PURE__ */ new Map()
11561
+ agentCache: /* @__PURE__ */ new Map(),
11562
+ tenantId,
11563
+ workspaceId,
11564
+ projectId
11612
11565
  };
11613
11566
  await getOrCreateTeammateAgent(ctx, spec, teamTools, teamMiddleware);
11614
11567
  }
11615
11568
  function createTeamMiddleware(options) {
11616
- const { teamConfig, taskListStore, mailboxStore } = options;
11569
+ const { teamConfig, taskListStore, mailboxStore, tenantId } = options;
11617
11570
  const defaultModel = teamConfig.model ?? "claude-sonnet-4-5-20250929";
11618
11571
  const createTeamTool = tool47(
11619
11572
  async (input, config) => {
@@ -11660,6 +11613,7 @@ function createTeamMiddleware(options) {
11660
11613
  await mailboxStore.registerAgent(teamId, spec.name);
11661
11614
  }
11662
11615
  const parentThreadId = config.configurable?.thread_id ?? "";
11616
+ const runConfig = config.configurable?.runConfig;
11663
11617
  matchedSpecs.forEach((spec) => {
11664
11618
  void spawnTeammate({
11665
11619
  teamId,
@@ -11670,7 +11624,10 @@ function createTeamMiddleware(options) {
11670
11624
  defaultModel,
11671
11625
  parentThreadId,
11672
11626
  teamTools: teamConfig.tools,
11673
- teamMiddleware: teamConfig.middleware
11627
+ teamMiddleware: teamConfig.middleware,
11628
+ tenantId,
11629
+ workspaceId: runConfig?.workspaceId,
11630
+ projectId: runConfig?.projectId
11674
11631
  });
11675
11632
  });
11676
11633
  const teamJson = JSON.stringify({
@@ -12240,7 +12197,8 @@ function createAgentTeam(config) {
12240
12197
  const teamMiddleware = createTeamMiddleware({
12241
12198
  teamConfig: teamConfigWithFs,
12242
12199
  taskListStore,
12243
- mailboxStore
12200
+ mailboxStore,
12201
+ tenantId: config.tenantId
12244
12202
  });
12245
12203
  const middleware = [
12246
12204
  teamMiddleware,
@@ -12307,7 +12265,8 @@ var TeamAgentGraphBuilder = class {
12307
12265
  scheduleLatticeKey: config.scheduleLatticeKey,
12308
12266
  pollIntervalMs: config.pollIntervalMs,
12309
12267
  backend: filesystemBackend,
12310
- middleware: middlewares
12268
+ middleware: middlewares,
12269
+ tenantId: params.tenantId
12311
12270
  };
12312
12271
  const teamLead = createAgentTeam(teamConfig);
12313
12272
  return teamLead;
@@ -12671,8 +12630,9 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
12671
12630
  *
12672
12631
  * @param key Unique key (e.g. `team:${teamId}:${agentName}`)
12673
12632
  * @param client Pre-built AgentClient (ReactAgent or CompiledGraph)
12633
+ * @param tenantId Tenant ID (required)
12674
12634
  */
12675
- registerTeammateAgent(key, client) {
12635
+ registerTeammateAgent(key, client, tenantId) {
12676
12636
  const agentLattice = {
12677
12637
  config: {
12678
12638
  key,
@@ -12682,7 +12642,7 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
12682
12642
  },
12683
12643
  client
12684
12644
  };
12685
- this.register(key, agentLattice);
12645
+ this.registerWithTenant(tenantId, key, agentLattice);
12686
12646
  }
12687
12647
  /**
12688
12648
  * Unregister a teammate agent. Call when a team is done to clean up.
@@ -12802,7 +12762,11 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
12802
12762
  this.initializeClient(tenantId, key);
12803
12763
  return this.getAgentLatticeWithTenant(tenantId, key);
12804
12764
  });
12805
- return paramsBuilder.buildParams(agentLattice, options);
12765
+ const params = paramsBuilder.buildParams(agentLattice, options);
12766
+ return {
12767
+ ...params,
12768
+ tenantId
12769
+ };
12806
12770
  }
12807
12771
  /**
12808
12772
  * Create an AgentClient from AgentLattice config
@@ -12886,7 +12850,7 @@ var registerAgentLattices = (tenantId, configs) => {
12886
12850
  var getAgentConfig = (key) => agentLatticeManager.getAgentConfig(key);
12887
12851
  var getAllAgentConfigs = () => agentLatticeManager.getAllAgentConfigs();
12888
12852
  var validateAgentInput = (key, input) => agentLatticeManager.validateAgentInput(key, input);
12889
- var registerTeammateAgent = (key, client) => agentLatticeManager.registerTeammateAgent(key, client);
12853
+ var registerTeammateAgent = (key, client, tenantId) => agentLatticeManager.registerTeammateAgent(key, client, tenantId);
12890
12854
  var unregisterTeammateAgent = (key) => agentLatticeManager.unregisterTeammateAgent(key);
12891
12855
  var getAgentClient = (tenantId, key, options) => agentLatticeManager.initializeClient(tenantId, key, options);
12892
12856
  var createAgentClientFromAgentLattice = async (agentLattice, options) => await agentLatticeManager.createAgentClientFromConfig(agentLattice, options);