@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.js CHANGED
@@ -1012,6 +1012,7 @@ var Thread = class {
1012
1012
  let assistantResponse = "";
1013
1013
  const hasComponent = metadata && Object.keys(metadata).length > 0 && metadata.type;
1014
1014
  const hasTextResponse = textResponse && textResponse.trim().length > 0;
1015
+ const responseParts = [];
1015
1016
  if (hasComponent) {
1016
1017
  const parts = [];
1017
1018
  if (metadata.type) {
@@ -1020,21 +1021,19 @@ var Thread = class {
1020
1021
  if (metadata.name) {
1021
1022
  parts.push(`Name: ${metadata.name}`);
1022
1023
  }
1023
- if (metadata.props?.title) {
1024
- parts.push(`Title: "${metadata.props.title}"`);
1024
+ if (metadata.description) {
1025
+ parts.push(`Description: ${metadata.description}`);
1025
1026
  }
1026
- if (metadata.props?.query) {
1027
- const query = metadata.props.query;
1028
- const truncatedQuery = query.length > 200 ? query.substring(0, 200) + "..." : query;
1029
- parts.push(`Query: ${truncatedQuery}`);
1027
+ if (metadata.props) {
1028
+ parts.push(`Props: ${JSON.stringify(metadata.props)}`);
1030
1029
  }
1031
- if (metadata.props?.config?.components && Array.isArray(metadata.props.config.components)) {
1032
- const componentTypes = metadata.props.config.components.map((c) => c.type).join(", ");
1033
- parts.push(`Multi-component with: ${componentTypes}`);
1034
- }
1035
- assistantResponse = parts.join(", ");
1036
- } else if (hasTextResponse) {
1037
- assistantResponse = textResponse;
1030
+ responseParts.push(parts.join("\n"));
1031
+ }
1032
+ if (hasTextResponse) {
1033
+ responseParts.push(textResponse);
1034
+ }
1035
+ if (responseParts.length > 0) {
1036
+ assistantResponse = responseParts.join("\n");
1038
1037
  } else {
1039
1038
  assistantResponse = "No response generated";
1040
1039
  }
@@ -2386,18 +2385,16 @@ Your job is to:
2386
2385
  1. **Parse the component suggestions** from the text response (format: 1:component_type : reasoning)
2387
2386
  2. **Match each suggestion with an actual component** from the available list
2388
2387
  3. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched
2389
- 4. **SELECT the best dashboard layout component** that can accommodate all the matched components
2388
+ 4. **Generate title and description** for the dashboard container
2390
2389
  5. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis
2391
2390
 
2392
2391
  **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.
2393
2392
 
2394
- **APPROACH**: First match all the components suggested in the text response, THEN find the layout that best fits those components.
2395
-
2396
2393
  ## Available Components
2397
2394
 
2398
2395
  {{AVAILABLE_COMPONENTS}}
2399
2396
 
2400
- ## Component Matching Rules (STEP 1)
2397
+ ## Component Matching Rules
2401
2398
  For each component suggestion (c1, c2, c3, etc.) from the text response:
2402
2399
 
2403
2400
  1. **Match by type**: Find components whose \`type\` matches the suggested component type
@@ -2406,23 +2403,10 @@ For each component suggestion (c1, c2, c3, etc.) from the text response:
2406
2403
  - Best fit for the data being visualized
2407
2404
  3. **Fallback**: If no exact type match, find the closest alternative
2408
2405
 
2409
- ## Layout Selection Logic (STEP 2 - After Matching Components)
2410
-
2411
- **After you have matched all components**, select the best dashboard layout:
2412
-
2413
- 1. **Find layout components** by looking for components with \`type: "DashboardLayout"\` in the available components list
2414
- 2. **Read each layout's description** to understand:
2415
- - What structure it provides
2416
- - When it's best used (e.g., comprehensive analysis vs focused analysis)
2417
- - The number and types of components it can accommodate
2418
- 3. **Select the best layout** based on:
2419
- - Which layout can best display ALL the matched components
2420
- - The layout's capacity (how many components it supports)
2421
- - The types of matched components (KPI, charts, tables, etc.)
2422
- - The user question and data complexity
2423
- 4. **If no specific layout fits**, fall back to "MultiComponentContainer" as the default layout
2424
-
2425
- **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.
2406
+ ## Dashboard Container
2407
+ All matched components will be placed in the default **MultiComponentContainer** layout. Your job is to:
2408
+ 1. **Generate a clear title** for the dashboard that summarizes what it shows
2409
+ 2. **Generate a brief description** explaining the dashboard's purpose and scope
2426
2410
 
2427
2411
  ## Props Generation Rules
2428
2412
 
@@ -2536,8 +2520,8 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
2536
2520
 
2537
2521
  \`\`\`json
2538
2522
  {
2539
- "selectedLayoutId": "id_of_the_selected_layout_component",
2540
- "layoutReasoning": "Why this layout was selected based on its description and the analysis needs",
2523
+ "layoutTitle": "Clear, concise title for the overall dashboard/layout (5-10 words)",
2524
+ "layoutDescription": "Brief description of what the dashboard shows and its purpose (1-2 sentences)",
2541
2525
  "matchedComponents": [
2542
2526
  {
2543
2527
  "componentId": "id_from_available_list",
@@ -2567,17 +2551,14 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
2567
2551
  \`\`\`
2568
2552
 
2569
2553
  **CRITICAL:**
2570
- - \`matchedComponents\` MUST include ALL components suggested in the text response (match them first!)
2571
- - \`selectedLayoutId\` MUST be the ID of the selected layout component (must have type "DashboardLayout")
2572
- - \`layoutReasoning\` MUST explain:
2573
- - Why you chose this specific layout component
2574
- - How many components you matched (e.g., "Matched 3 components: 1 KPI, 1 chart, 1 table")
2575
- - Why this layout is the best fit for displaying these specific matched components
2576
- - What makes this layout appropriate for the component types and count
2577
- - The layout selection happens AFTER component matching - don't force components to fit a pre-selected layout
2554
+ - \`matchedComponents\` MUST include ALL components suggested in the text response
2555
+ - \`layoutTitle\` MUST be a clear, concise title (5-10 words) that summarizes what the entire dashboard shows
2556
+ - Examples: "Sales Performance Overview", "Customer Metrics Analysis", "Product Category Breakdown"
2557
+ - \`layoutDescription\` MUST be a brief description (1-2 sentences) explaining the purpose and scope of the dashboard
2558
+ - Should describe what insights the dashboard provides and what data it shows
2578
2559
  - \`actions\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis
2579
2560
  - Return ONLY valid JSON (no markdown code blocks, no text before/after)
2580
- - Generate complete props for each component
2561
+ - Generate complete props for each component including query, title, description, and config
2581
2562
 
2582
2563
 
2583
2564
  `,
@@ -3673,12 +3654,13 @@ var BaseLLM = class {
3673
3654
  /**
3674
3655
  * Match components from text response suggestions and generate follow-up questions
3675
3656
  * Takes a text response with component suggestions (c1:type format) and matches with available components
3676
- * Also generates intelligent follow-up questions (actions) based on the analysis
3657
+ * Also generates title, description, and intelligent follow-up questions (actions) based on the analysis
3658
+ * All components are placed in a default MultiComponentContainer layout
3677
3659
  * @param textResponse - The text response containing component suggestions
3678
3660
  * @param components - List of available components
3679
3661
  * @param apiKey - Optional API key
3680
3662
  * @param logCollector - Optional log collector
3681
- * @returns Object containing matched components, selected layout, reasoning, and follow-up actions
3663
+ * @returns Object containing matched components, layout title/description, and follow-up actions
3682
3664
  */
3683
3665
  async matchComponentsFromTextResponse(textResponse, components, apiKey, logCollector) {
3684
3666
  try {
@@ -3721,24 +3703,17 @@ var BaseLLM = class {
3721
3703
  );
3722
3704
  logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
3723
3705
  const matchedComponents = result.matchedComponents || [];
3724
- const selectedLayoutId = result.selectedLayoutId || "multi-component-container";
3725
- const layoutReasoning = result.layoutReasoning || "No layout reasoning provided";
3706
+ const layoutTitle = result.layoutTitle || "Dashboard";
3707
+ const layoutDescription = result.layoutDescription || "Multi-component dashboard";
3726
3708
  const rawActions = result.actions || [];
3727
3709
  const actions = convertQuestionsToActions(rawActions);
3728
- let selectedLayoutComponent = null;
3729
- if (selectedLayoutId) {
3730
- selectedLayoutComponent = components.find((c) => c.id === selectedLayoutId) || null;
3731
- if (!selectedLayoutComponent) {
3732
- logger.warn(`[${this.getProviderName()}] Layout component ${selectedLayoutId} not found in available components`);
3733
- }
3734
- }
3735
3710
  logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
3736
- logger.info(`[${this.getProviderName()}] Selected layout: (ID: ${selectedLayoutId})`);
3737
- logger.info(`[${this.getProviderName()}] Layout reasoning: ${layoutReasoning}`);
3711
+ logger.info(`[${this.getProviderName()}] Layout title: "${layoutTitle}"`);
3712
+ logger.info(`[${this.getProviderName()}] Layout description: "${layoutDescription}"`);
3738
3713
  logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
3739
3714
  if (matchedComponents.length > 0) {
3740
- logCollector?.info(`Matched ${matchedComponents.length} components for visualization `);
3741
- logCollector?.info(`Layout reasoning: ${layoutReasoning}`);
3715
+ logCollector?.info(`Matched ${matchedComponents.length} components for visualization`);
3716
+ logCollector?.info(`Dashboard: "${layoutTitle}"`);
3742
3717
  matchedComponents.forEach((comp, idx) => {
3743
3718
  logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
3744
3719
  if (comp.props?.query) {
@@ -3772,9 +3747,8 @@ var BaseLLM = class {
3772
3747
  }).filter(Boolean);
3773
3748
  return {
3774
3749
  components: finalComponents,
3775
- selectedLayoutId,
3776
- selectedLayoutComponent,
3777
- layoutReasoning,
3750
+ layoutTitle,
3751
+ layoutDescription,
3778
3752
  actions
3779
3753
  };
3780
3754
  } catch (error) {
@@ -3783,9 +3757,8 @@ var BaseLLM = class {
3783
3757
  logCollector?.error(`Failed to match components: ${errorMsg}`);
3784
3758
  return {
3785
3759
  components: [],
3786
- selectedLayoutId: "",
3787
- selectedLayoutComponent: null,
3788
- layoutReasoning: "Failed to match components due to parsing error",
3760
+ layoutTitle: "Dashboard",
3761
+ layoutDescription: "Failed to generate dashboard",
3789
3762
  actions: []
3790
3763
  };
3791
3764
  }
@@ -4029,9 +4002,12 @@ ${errorMsg}
4029
4002
  textLength: textResponse.length
4030
4003
  }
4031
4004
  );
4005
+ if (wrappedStreamCallback && components && components.length > 0) {
4006
+ wrappedStreamCallback("__TEXT_COMPLETE__COMPONENT_GENERATION_START__");
4007
+ }
4032
4008
  let matchedComponents = [];
4033
- let selectedLayoutComponent = null;
4034
- let layoutReasoning = "No layout selected";
4009
+ let layoutTitle = "Dashboard";
4010
+ let layoutDescription = "Multi-component dashboard";
4035
4011
  let actions = [];
4036
4012
  if (components && components.length > 0) {
4037
4013
  logger.info(`[${this.getProviderName()}] Matching components from text response...`);
@@ -4042,46 +4018,30 @@ ${errorMsg}
4042
4018
  logCollector
4043
4019
  );
4044
4020
  matchedComponents = matchResult.components;
4045
- selectedLayoutComponent = matchResult.selectedLayoutComponent;
4046
- layoutReasoning = matchResult.layoutReasoning;
4021
+ layoutTitle = matchResult.layoutTitle;
4022
+ layoutDescription = matchResult.layoutDescription;
4047
4023
  actions = matchResult.actions;
4048
4024
  }
4049
4025
  let container_componet = null;
4050
4026
  if (matchedComponents.length > 0) {
4051
- if (selectedLayoutComponent) {
4052
- container_componet = {
4053
- ...selectedLayoutComponent,
4054
- id: `${selectedLayoutComponent.id}_${Date.now()}`,
4055
- // Make ID unique for each instance
4056
- props: {
4057
- ...selectedLayoutComponent.props,
4058
- config: {
4059
- ...selectedLayoutComponent.props?.config || {},
4060
- components: matchedComponents
4061
- },
4062
- actions
4063
- }
4064
- };
4065
- logger.info(`[${this.getProviderName()}] Created ${selectedLayoutComponent.name} (${selectedLayoutComponent.type}) container with ${matchedComponents.length} components and ${actions.length} actions`);
4066
- logCollector?.info(`Created ${selectedLayoutComponent.name} with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
4067
- } else {
4068
- container_componet = {
4069
- id: `multi_container_${Date.now()}`,
4070
- name: "MultiComponentContainer",
4071
- type: "Container",
4072
- description: layoutReasoning,
4073
- category: "dynamic",
4074
- keywords: ["dashboard", "layout", "container"],
4075
- props: {
4076
- config: {
4077
- components: matchedComponents
4078
- },
4079
- actions
4080
- }
4081
- };
4082
- logger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions`);
4083
- logCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
4084
- }
4027
+ container_componet = {
4028
+ id: `multi_container_${Date.now()}`,
4029
+ name: "MultiComponentContainer",
4030
+ type: "Container",
4031
+ description: layoutDescription,
4032
+ category: "dynamic",
4033
+ keywords: ["dashboard", "layout", "container"],
4034
+ props: {
4035
+ config: {
4036
+ components: matchedComponents,
4037
+ title: layoutTitle,
4038
+ description: layoutDescription
4039
+ },
4040
+ actions
4041
+ }
4042
+ };
4043
+ logger.info(`[${this.getProviderName()}] Created MultiComponentContainer: "${layoutTitle}" with ${matchedComponents.length} components and ${actions.length} actions`);
4044
+ logCollector?.info(`Created dashboard: "${layoutTitle}" with ${matchedComponents.length} components and ${actions.length} actions`);
4085
4045
  }
4086
4046
  return {
4087
4047
  success: true,
@@ -4089,7 +4049,6 @@ ${errorMsg}
4089
4049
  text: textResponse,
4090
4050
  matchedComponents,
4091
4051
  component: container_componet,
4092
- layoutReasoning,
4093
4052
  actions,
4094
4053
  method: `${this.getProviderName()}-text-response`
4095
4054
  },
@@ -4755,7 +4714,7 @@ var CONTEXT_CONFIG = {
4755
4714
  * Set to 0 to disable conversation history
4756
4715
  * Higher values provide more context but may increase token usage
4757
4716
  */
4758
- MAX_CONVERSATION_CONTEXT_BLOCKS: 2
4717
+ MAX_CONVERSATION_CONTEXT_BLOCKS: 3
4759
4718
  };
4760
4719
 
4761
4720
  // src/handlers/user-prompt-request.ts