@superatomai/sdk-node 0.0.10 → 0.0.11

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
@@ -972,6 +972,7 @@ var Thread = class {
972
972
  let assistantResponse = "";
973
973
  const hasComponent = metadata && Object.keys(metadata).length > 0 && metadata.type;
974
974
  const hasTextResponse = textResponse && textResponse.trim().length > 0;
975
+ const responseParts = [];
975
976
  if (hasComponent) {
976
977
  const parts = [];
977
978
  if (metadata.type) {
@@ -980,21 +981,19 @@ var Thread = class {
980
981
  if (metadata.name) {
981
982
  parts.push(`Name: ${metadata.name}`);
982
983
  }
983
- if (metadata.props?.title) {
984
- parts.push(`Title: "${metadata.props.title}"`);
984
+ if (metadata.description) {
985
+ parts.push(`Description: ${metadata.description}`);
985
986
  }
986
- if (metadata.props?.query) {
987
- const query = metadata.props.query;
988
- const truncatedQuery = query.length > 200 ? query.substring(0, 200) + "..." : query;
989
- parts.push(`Query: ${truncatedQuery}`);
987
+ if (metadata.props) {
988
+ parts.push(`Props: ${JSON.stringify(metadata.props)}`);
990
989
  }
991
- if (metadata.props?.config?.components && Array.isArray(metadata.props.config.components)) {
992
- const componentTypes = metadata.props.config.components.map((c) => c.type).join(", ");
993
- parts.push(`Multi-component with: ${componentTypes}`);
994
- }
995
- assistantResponse = parts.join(", ");
996
- } else if (hasTextResponse) {
997
- assistantResponse = textResponse;
990
+ responseParts.push(parts.join("\n"));
991
+ }
992
+ if (hasTextResponse) {
993
+ responseParts.push(textResponse);
994
+ }
995
+ if (responseParts.length > 0) {
996
+ assistantResponse = responseParts.join("\n");
998
997
  } else {
999
998
  assistantResponse = "No response generated";
1000
999
  }
@@ -2346,18 +2345,16 @@ Your job is to:
2346
2345
  1. **Parse the component suggestions** from the text response (format: 1:component_type : reasoning)
2347
2346
  2. **Match each suggestion with an actual component** from the available list
2348
2347
  3. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched
2349
- 4. **SELECT the best dashboard layout component** that can accommodate all the matched components
2348
+ 4. **Generate title and description** for the dashboard container
2350
2349
  5. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis
2351
2350
 
2352
2351
  **CRITICAL GOAL**: Create dashboard components that display the **same data that was already analyzed** - NOT new data. The queries already ran and got results. You're just creating different visualizations of those results.
2353
2352
 
2354
- **APPROACH**: First match all the components suggested in the text response, THEN find the layout that best fits those components.
2355
-
2356
2353
  ## Available Components
2357
2354
 
2358
2355
  {{AVAILABLE_COMPONENTS}}
2359
2356
 
2360
- ## Component Matching Rules (STEP 1)
2357
+ ## Component Matching Rules
2361
2358
  For each component suggestion (c1, c2, c3, etc.) from the text response:
2362
2359
 
2363
2360
  1. **Match by type**: Find components whose \`type\` matches the suggested component type
@@ -2366,23 +2363,10 @@ For each component suggestion (c1, c2, c3, etc.) from the text response:
2366
2363
  - Best fit for the data being visualized
2367
2364
  3. **Fallback**: If no exact type match, find the closest alternative
2368
2365
 
2369
- ## Layout Selection Logic (STEP 2 - After Matching Components)
2370
-
2371
- **After you have matched all components**, select the best dashboard layout:
2372
-
2373
- 1. **Find layout components** by looking for components with \`type: "DashboardLayout"\` in the available components list
2374
- 2. **Read each layout's description** to understand:
2375
- - What structure it provides
2376
- - When it's best used (e.g., comprehensive analysis vs focused analysis)
2377
- - The number and types of components it can accommodate
2378
- 3. **Select the best layout** based on:
2379
- - Which layout can best display ALL the matched components
2380
- - The layout's capacity (how many components it supports)
2381
- - The types of matched components (KPI, charts, tables, etc.)
2382
- - The user question and data complexity
2383
- 4. **If no specific layout fits**, fall back to "MultiComponentContainer" as the default layout
2384
-
2385
- **IMPORTANT:** The layout should be chosen to FIT the matched components, not the other way around. Don't force components to fit a layout - find a layout that accommodates your components.
2366
+ ## Dashboard Container
2367
+ All matched components will be placed in the default **MultiComponentContainer** layout. Your job is to:
2368
+ 1. **Generate a clear title** for the dashboard that summarizes what it shows
2369
+ 2. **Generate a brief description** explaining the dashboard's purpose and scope
2386
2370
 
2387
2371
  ## Props Generation Rules
2388
2372
 
@@ -2496,8 +2480,8 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
2496
2480
 
2497
2481
  \`\`\`json
2498
2482
  {
2499
- "selectedLayoutId": "id_of_the_selected_layout_component",
2500
- "layoutReasoning": "Why this layout was selected based on its description and the analysis needs",
2483
+ "layoutTitle": "Clear, concise title for the overall dashboard/layout (5-10 words)",
2484
+ "layoutDescription": "Brief description of what the dashboard shows and its purpose (1-2 sentences)",
2501
2485
  "matchedComponents": [
2502
2486
  {
2503
2487
  "componentId": "id_from_available_list",
@@ -2527,17 +2511,14 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
2527
2511
  \`\`\`
2528
2512
 
2529
2513
  **CRITICAL:**
2530
- - \`matchedComponents\` MUST include ALL components suggested in the text response (match them first!)
2531
- - \`selectedLayoutId\` MUST be the ID of the selected layout component (must have type "DashboardLayout")
2532
- - \`layoutReasoning\` MUST explain:
2533
- - Why you chose this specific layout component
2534
- - How many components you matched (e.g., "Matched 3 components: 1 KPI, 1 chart, 1 table")
2535
- - Why this layout is the best fit for displaying these specific matched components
2536
- - What makes this layout appropriate for the component types and count
2537
- - The layout selection happens AFTER component matching - don't force components to fit a pre-selected layout
2514
+ - \`matchedComponents\` MUST include ALL components suggested in the text response
2515
+ - \`layoutTitle\` MUST be a clear, concise title (5-10 words) that summarizes what the entire dashboard shows
2516
+ - Examples: "Sales Performance Overview", "Customer Metrics Analysis", "Product Category Breakdown"
2517
+ - \`layoutDescription\` MUST be a brief description (1-2 sentences) explaining the purpose and scope of the dashboard
2518
+ - Should describe what insights the dashboard provides and what data it shows
2538
2519
  - \`actions\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis
2539
2520
  - Return ONLY valid JSON (no markdown code blocks, no text before/after)
2540
- - Generate complete props for each component
2521
+ - Generate complete props for each component including query, title, description, and config
2541
2522
 
2542
2523
 
2543
2524
  `,
@@ -3633,12 +3614,13 @@ var BaseLLM = class {
3633
3614
  /**
3634
3615
  * Match components from text response suggestions and generate follow-up questions
3635
3616
  * Takes a text response with component suggestions (c1:type format) and matches with available components
3636
- * Also generates intelligent follow-up questions (actions) based on the analysis
3617
+ * Also generates title, description, and intelligent follow-up questions (actions) based on the analysis
3618
+ * All components are placed in a default MultiComponentContainer layout
3637
3619
  * @param textResponse - The text response containing component suggestions
3638
3620
  * @param components - List of available components
3639
3621
  * @param apiKey - Optional API key
3640
3622
  * @param logCollector - Optional log collector
3641
- * @returns Object containing matched components, selected layout, reasoning, and follow-up actions
3623
+ * @returns Object containing matched components, layout title/description, and follow-up actions
3642
3624
  */
3643
3625
  async matchComponentsFromTextResponse(textResponse, components, apiKey, logCollector) {
3644
3626
  try {
@@ -3681,24 +3663,17 @@ var BaseLLM = class {
3681
3663
  );
3682
3664
  logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
3683
3665
  const matchedComponents = result.matchedComponents || [];
3684
- const selectedLayoutId = result.selectedLayoutId || "multi-component-container";
3685
- const layoutReasoning = result.layoutReasoning || "No layout reasoning provided";
3666
+ const layoutTitle = result.layoutTitle || "Dashboard";
3667
+ const layoutDescription = result.layoutDescription || "Multi-component dashboard";
3686
3668
  const rawActions = result.actions || [];
3687
3669
  const actions = convertQuestionsToActions(rawActions);
3688
- let selectedLayoutComponent = null;
3689
- if (selectedLayoutId) {
3690
- selectedLayoutComponent = components.find((c) => c.id === selectedLayoutId) || null;
3691
- if (!selectedLayoutComponent) {
3692
- logger.warn(`[${this.getProviderName()}] Layout component ${selectedLayoutId} not found in available components`);
3693
- }
3694
- }
3695
3670
  logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
3696
- logger.info(`[${this.getProviderName()}] Selected layout: (ID: ${selectedLayoutId})`);
3697
- logger.info(`[${this.getProviderName()}] Layout reasoning: ${layoutReasoning}`);
3671
+ logger.info(`[${this.getProviderName()}] Layout title: "${layoutTitle}"`);
3672
+ logger.info(`[${this.getProviderName()}] Layout description: "${layoutDescription}"`);
3698
3673
  logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
3699
3674
  if (matchedComponents.length > 0) {
3700
- logCollector?.info(`Matched ${matchedComponents.length} components for visualization `);
3701
- logCollector?.info(`Layout reasoning: ${layoutReasoning}`);
3675
+ logCollector?.info(`Matched ${matchedComponents.length} components for visualization`);
3676
+ logCollector?.info(`Dashboard: "${layoutTitle}"`);
3702
3677
  matchedComponents.forEach((comp, idx) => {
3703
3678
  logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
3704
3679
  if (comp.props?.query) {
@@ -3732,9 +3707,8 @@ var BaseLLM = class {
3732
3707
  }).filter(Boolean);
3733
3708
  return {
3734
3709
  components: finalComponents,
3735
- selectedLayoutId,
3736
- selectedLayoutComponent,
3737
- layoutReasoning,
3710
+ layoutTitle,
3711
+ layoutDescription,
3738
3712
  actions
3739
3713
  };
3740
3714
  } catch (error) {
@@ -3743,9 +3717,8 @@ var BaseLLM = class {
3743
3717
  logCollector?.error(`Failed to match components: ${errorMsg}`);
3744
3718
  return {
3745
3719
  components: [],
3746
- selectedLayoutId: "",
3747
- selectedLayoutComponent: null,
3748
- layoutReasoning: "Failed to match components due to parsing error",
3720
+ layoutTitle: "Dashboard",
3721
+ layoutDescription: "Failed to generate dashboard",
3749
3722
  actions: []
3750
3723
  };
3751
3724
  }
@@ -3989,9 +3962,12 @@ ${errorMsg}
3989
3962
  textLength: textResponse.length
3990
3963
  }
3991
3964
  );
3965
+ if (wrappedStreamCallback && components && components.length > 0) {
3966
+ wrappedStreamCallback("__TEXT_COMPLETE__COMPONENT_GENERATION_START__");
3967
+ }
3992
3968
  let matchedComponents = [];
3993
- let selectedLayoutComponent = null;
3994
- let layoutReasoning = "No layout selected";
3969
+ let layoutTitle = "Dashboard";
3970
+ let layoutDescription = "Multi-component dashboard";
3995
3971
  let actions = [];
3996
3972
  if (components && components.length > 0) {
3997
3973
  logger.info(`[${this.getProviderName()}] Matching components from text response...`);
@@ -4002,46 +3978,30 @@ ${errorMsg}
4002
3978
  logCollector
4003
3979
  );
4004
3980
  matchedComponents = matchResult.components;
4005
- selectedLayoutComponent = matchResult.selectedLayoutComponent;
4006
- layoutReasoning = matchResult.layoutReasoning;
3981
+ layoutTitle = matchResult.layoutTitle;
3982
+ layoutDescription = matchResult.layoutDescription;
4007
3983
  actions = matchResult.actions;
4008
3984
  }
4009
3985
  let container_componet = null;
4010
3986
  if (matchedComponents.length > 0) {
4011
- if (selectedLayoutComponent) {
4012
- container_componet = {
4013
- ...selectedLayoutComponent,
4014
- id: `${selectedLayoutComponent.id}_${Date.now()}`,
4015
- // Make ID unique for each instance
4016
- props: {
4017
- ...selectedLayoutComponent.props,
4018
- config: {
4019
- ...selectedLayoutComponent.props?.config || {},
4020
- components: matchedComponents
4021
- },
4022
- actions
4023
- }
4024
- };
4025
- logger.info(`[${this.getProviderName()}] Created ${selectedLayoutComponent.name} (${selectedLayoutComponent.type}) container with ${matchedComponents.length} components and ${actions.length} actions`);
4026
- logCollector?.info(`Created ${selectedLayoutComponent.name} with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
4027
- } else {
4028
- container_componet = {
4029
- id: `multi_container_${Date.now()}`,
4030
- name: "MultiComponentContainer",
4031
- type: "Container",
4032
- description: layoutReasoning,
4033
- category: "dynamic",
4034
- keywords: ["dashboard", "layout", "container"],
4035
- props: {
4036
- config: {
4037
- components: matchedComponents
4038
- },
4039
- actions
4040
- }
4041
- };
4042
- logger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions`);
4043
- logCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
4044
- }
3987
+ container_componet = {
3988
+ id: `multi_container_${Date.now()}`,
3989
+ name: "MultiComponentContainer",
3990
+ type: "Container",
3991
+ description: layoutDescription,
3992
+ category: "dynamic",
3993
+ keywords: ["dashboard", "layout", "container"],
3994
+ props: {
3995
+ config: {
3996
+ components: matchedComponents,
3997
+ title: layoutTitle,
3998
+ description: layoutDescription
3999
+ },
4000
+ actions
4001
+ }
4002
+ };
4003
+ logger.info(`[${this.getProviderName()}] Created MultiComponentContainer: "${layoutTitle}" with ${matchedComponents.length} components and ${actions.length} actions`);
4004
+ logCollector?.info(`Created dashboard: "${layoutTitle}" with ${matchedComponents.length} components and ${actions.length} actions`);
4045
4005
  }
4046
4006
  return {
4047
4007
  success: true,
@@ -4049,7 +4009,6 @@ ${errorMsg}
4049
4009
  text: textResponse,
4050
4010
  matchedComponents,
4051
4011
  component: container_componet,
4052
- layoutReasoning,
4053
4012
  actions,
4054
4013
  method: `${this.getProviderName()}-text-response`
4055
4014
  },
@@ -4715,7 +4674,7 @@ var CONTEXT_CONFIG = {
4715
4674
  * Set to 0 to disable conversation history
4716
4675
  * Higher values provide more context but may increase token usage
4717
4676
  */
4718
- MAX_CONVERSATION_CONTEXT_BLOCKS: 2
4677
+ MAX_CONVERSATION_CONTEXT_BLOCKS: 3
4719
4678
  };
4720
4679
 
4721
4680
  // src/handlers/user-prompt-request.ts