@superatomai/sdk-node 0.0.8 → 0.0.9
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 +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +151 -136
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +151 -136
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -2674,6 +2674,7 @@ When the user asks about data
|
|
|
2674
2674
|
|
|
2675
2675
|
After analyzing the query results, you MUST suggest appropriate dashboard components for displaying the data. Use this format:
|
|
2676
2676
|
|
|
2677
|
+
<DashboardComponents>
|
|
2677
2678
|
**Dashboard Components:**
|
|
2678
2679
|
Format: \`{number}.{component_type} : {clear reasoning}\`
|
|
2679
2680
|
|
|
@@ -2682,9 +2683,9 @@ Format: \`{number}.{component_type} : {clear reasoning}\`
|
|
|
2682
2683
|
1. Analyze the query results structure and data type
|
|
2683
2684
|
2. Suggest components that would best visualize the data
|
|
2684
2685
|
3. Each component suggestion must be on a new line
|
|
2686
|
+
</DashboardComponents>
|
|
2685
2687
|
|
|
2686
|
-
|
|
2687
|
-
IMPORTANT: Always include the **Dashboard Components:** section with at least one component suggestion when data is returned.
|
|
2688
|
+
IMPORTANT: Always wrap component suggestions with <DashboardComponents> tags and include at least one component suggestion when data is returned.
|
|
2688
2689
|
|
|
2689
2690
|
## Output Format
|
|
2690
2691
|
|
|
@@ -2692,7 +2693,7 @@ Respond with plain text that includes:
|
|
|
2692
2693
|
|
|
2693
2694
|
1. **Query Analysis** (if applicable): Brief explanation of what data was fetched
|
|
2694
2695
|
2. **Results Summary**: Present the data in a clear, readable format
|
|
2695
|
-
3. **Dashboard Components**: List suggested components in
|
|
2696
|
+
3. **Dashboard Components**: List suggested components wrapped in <DashboardComponents> tags
|
|
2696
2697
|
|
|
2697
2698
|
|
|
2698
2699
|
**CRITICAL:**
|
|
@@ -2769,39 +2770,22 @@ You will receive a text response containing:
|
|
|
2769
2770
|
3. **Dashboard Components:** suggestions (1:component_type : reasoning format)
|
|
2770
2771
|
|
|
2771
2772
|
Your job is to:
|
|
2772
|
-
1. **
|
|
2773
|
-
2.
|
|
2774
|
-
3.
|
|
2775
|
-
4.
|
|
2776
|
-
5. Generate
|
|
2777
|
-
6. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis
|
|
2773
|
+
1. **Parse the component suggestions** from the text response (format: 1:component_type : reasoning)
|
|
2774
|
+
2. **Match each suggestion with an actual component** from the available list
|
|
2775
|
+
3. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched
|
|
2776
|
+
4. **SELECT the best dashboard layout component** that can accommodate all the matched components
|
|
2777
|
+
5. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis
|
|
2778
2778
|
|
|
2779
2779
|
**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.
|
|
2780
2780
|
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
## Layout Component Discovery
|
|
2784
|
-
**Find layout components** by looking for components with \`type: "DashboardLayout"\`
|
|
2785
|
-
|
|
2786
|
-
## Layout Selection Logic
|
|
2787
|
-
1. **Read each layout's description** to understand:
|
|
2788
|
-
- What structure it provides
|
|
2789
|
-
- When it's best used (e.g., comprehensive analysis vs focused analysis)
|
|
2790
|
-
- The exact number and types of components it requires
|
|
2791
|
-
2. **Select the best layout** based on:
|
|
2792
|
-
- Which layout structure best fits the analysis needs
|
|
2793
|
-
- The component suggestions from the text response
|
|
2794
|
-
- The user question and data complexity
|
|
2795
|
-
3. **Generate EXACTLY the components specified** in the selected layout's description
|
|
2796
|
-
|
|
2797
|
-
**IMPORTANT:** Always prefer structured dashboard layouts when available. The layout component's description will tell you exactly what components to generate.
|
|
2781
|
+
**APPROACH**: First match all the components suggested in the text response, THEN find the layout that best fits those components.
|
|
2798
2782
|
|
|
2799
2783
|
## Available Components
|
|
2800
2784
|
|
|
2801
2785
|
{{AVAILABLE_COMPONENTS}}
|
|
2802
2786
|
|
|
2803
|
-
## Component Matching Rules
|
|
2804
|
-
For each component suggestion (c1, c2, c3, etc.):
|
|
2787
|
+
## Component Matching Rules (STEP 1)
|
|
2788
|
+
For each component suggestion (c1, c2, c3, etc.) from the text response:
|
|
2805
2789
|
|
|
2806
2790
|
1. **Match by type**: Find components whose \`type\` matches the suggested component type
|
|
2807
2791
|
2. **Refine by relevance**: If multiple components match, choose based on:
|
|
@@ -2809,6 +2793,24 @@ For each component suggestion (c1, c2, c3, etc.):
|
|
|
2809
2793
|
- Best fit for the data being visualized
|
|
2810
2794
|
3. **Fallback**: If no exact type match, find the closest alternative
|
|
2811
2795
|
|
|
2796
|
+
## Layout Selection Logic (STEP 2 - After Matching Components)
|
|
2797
|
+
|
|
2798
|
+
**After you have matched all components**, select the best dashboard layout:
|
|
2799
|
+
|
|
2800
|
+
1. **Find layout components** by looking for components with \`type: "DashboardLayout"\` in the available components list
|
|
2801
|
+
2. **Read each layout's description** to understand:
|
|
2802
|
+
- What structure it provides
|
|
2803
|
+
- When it's best used (e.g., comprehensive analysis vs focused analysis)
|
|
2804
|
+
- The number and types of components it can accommodate
|
|
2805
|
+
3. **Select the best layout** based on:
|
|
2806
|
+
- Which layout can best display ALL the matched components
|
|
2807
|
+
- The layout's capacity (how many components it supports)
|
|
2808
|
+
- The types of matched components (KPI, charts, tables, etc.)
|
|
2809
|
+
- The user question and data complexity
|
|
2810
|
+
4. **If no specific layout fits**, fall back to "MultiComponentContainer" as the default layout
|
|
2811
|
+
|
|
2812
|
+
**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.
|
|
2813
|
+
|
|
2812
2814
|
## Props Generation Rules
|
|
2813
2815
|
|
|
2814
2816
|
For each matched component, generate complete props:
|
|
@@ -2921,7 +2923,6 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
2921
2923
|
|
|
2922
2924
|
\`\`\`json
|
|
2923
2925
|
{
|
|
2924
|
-
"selectedLayout": "Name of the selected layout component from available components",
|
|
2925
2926
|
"selectedLayoutId": "id_of_the_selected_layout_component",
|
|
2926
2927
|
"layoutReasoning": "Why this layout was selected based on its description and the analysis needs",
|
|
2927
2928
|
"matchedComponents": [
|
|
@@ -2953,13 +2954,14 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
2953
2954
|
\`\`\`
|
|
2954
2955
|
|
|
2955
2956
|
**CRITICAL:**
|
|
2956
|
-
- \`
|
|
2957
|
-
- \`selectedLayoutId\` MUST be the ID of the selected layout component
|
|
2957
|
+
- \`matchedComponents\` MUST include ALL components suggested in the text response (match them first!)
|
|
2958
|
+
- \`selectedLayoutId\` MUST be the ID of the selected layout component (must have type "DashboardLayout")
|
|
2958
2959
|
- \`layoutReasoning\` MUST explain:
|
|
2959
2960
|
- Why you chose this specific layout component
|
|
2960
|
-
- How
|
|
2961
|
-
-
|
|
2962
|
-
-
|
|
2961
|
+
- How many components you matched (e.g., "Matched 3 components: 1 KPI, 1 chart, 1 table")
|
|
2962
|
+
- Why this layout is the best fit for displaying these specific matched components
|
|
2963
|
+
- What makes this layout appropriate for the component types and count
|
|
2964
|
+
- The layout selection happens AFTER component matching - don't force components to fit a pre-selected layout
|
|
2963
2965
|
- \`actions\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis
|
|
2964
2966
|
- Return ONLY valid JSON (no markdown code blocks, no text before/after)
|
|
2965
2967
|
- Generate complete props for each component
|
|
@@ -3155,6 +3157,7 @@ var promptLoader = new PromptLoader({
|
|
|
3155
3157
|
// src/llm.ts
|
|
3156
3158
|
import Anthropic from "@anthropic-ai/sdk";
|
|
3157
3159
|
import Groq from "groq-sdk";
|
|
3160
|
+
import { jsonrepair } from "jsonrepair";
|
|
3158
3161
|
var LLM = class {
|
|
3159
3162
|
/* Get a complete text response from an LLM (Anthropic or Groq) */
|
|
3160
3163
|
static async text(messages, options = {}) {
|
|
@@ -3276,65 +3279,110 @@ var LLM = class {
|
|
|
3276
3279
|
let finalText = "";
|
|
3277
3280
|
while (iterations < maxIterations) {
|
|
3278
3281
|
iterations++;
|
|
3279
|
-
const
|
|
3282
|
+
const stream = await client.messages.create({
|
|
3280
3283
|
model: modelName,
|
|
3281
3284
|
max_tokens: options.maxTokens || 4e3,
|
|
3282
3285
|
temperature: options.temperature,
|
|
3283
3286
|
system: messages.sys,
|
|
3284
3287
|
messages: conversationMessages,
|
|
3285
|
-
tools
|
|
3288
|
+
tools,
|
|
3289
|
+
stream: true
|
|
3290
|
+
// Enable streaming
|
|
3286
3291
|
});
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3292
|
+
let stopReason = null;
|
|
3293
|
+
const contentBlocks = [];
|
|
3294
|
+
let currentTextBlock = "";
|
|
3295
|
+
let currentToolUse = null;
|
|
3296
|
+
for await (const chunk of stream) {
|
|
3297
|
+
if (chunk.type === "message_start") {
|
|
3298
|
+
contentBlocks.length = 0;
|
|
3299
|
+
currentTextBlock = "";
|
|
3300
|
+
currentToolUse = null;
|
|
3301
|
+
}
|
|
3302
|
+
if (chunk.type === "content_block_start") {
|
|
3303
|
+
if (chunk.content_block.type === "text") {
|
|
3304
|
+
currentTextBlock = "";
|
|
3305
|
+
} else if (chunk.content_block.type === "tool_use") {
|
|
3306
|
+
currentToolUse = {
|
|
3307
|
+
type: "tool_use",
|
|
3308
|
+
id: chunk.content_block.id,
|
|
3309
|
+
name: chunk.content_block.name,
|
|
3310
|
+
input: {}
|
|
3311
|
+
};
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
if (chunk.type === "content_block_delta") {
|
|
3315
|
+
if (chunk.delta.type === "text_delta") {
|
|
3316
|
+
const text = chunk.delta.text;
|
|
3317
|
+
currentTextBlock += text;
|
|
3318
|
+
if (options.partial) {
|
|
3319
|
+
options.partial(text);
|
|
3320
|
+
}
|
|
3321
|
+
} else if (chunk.delta.type === "input_json_delta" && currentToolUse) {
|
|
3322
|
+
currentToolUse.inputJson = (currentToolUse.inputJson || "") + chunk.delta.partial_json;
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
if (chunk.type === "content_block_stop") {
|
|
3326
|
+
if (currentTextBlock) {
|
|
3327
|
+
contentBlocks.push({
|
|
3328
|
+
type: "text",
|
|
3329
|
+
text: currentTextBlock
|
|
3330
|
+
});
|
|
3331
|
+
finalText = currentTextBlock;
|
|
3332
|
+
currentTextBlock = "";
|
|
3333
|
+
} else if (currentToolUse) {
|
|
3334
|
+
try {
|
|
3335
|
+
currentToolUse.input = currentToolUse.inputJson ? JSON.parse(currentToolUse.inputJson) : {};
|
|
3336
|
+
} catch (error) {
|
|
3337
|
+
currentToolUse.input = {};
|
|
3338
|
+
}
|
|
3339
|
+
delete currentToolUse.inputJson;
|
|
3340
|
+
contentBlocks.push(currentToolUse);
|
|
3341
|
+
currentToolUse = null;
|
|
3293
3342
|
}
|
|
3294
3343
|
}
|
|
3344
|
+
if (chunk.type === "message_delta") {
|
|
3345
|
+
stopReason = chunk.delta.stop_reason || stopReason;
|
|
3346
|
+
}
|
|
3347
|
+
if (chunk.type === "message_stop") {
|
|
3348
|
+
break;
|
|
3349
|
+
}
|
|
3350
|
+
}
|
|
3351
|
+
if (stopReason === "end_turn") {
|
|
3295
3352
|
break;
|
|
3296
3353
|
}
|
|
3297
|
-
if (
|
|
3298
|
-
const toolUses =
|
|
3354
|
+
if (stopReason === "tool_use") {
|
|
3355
|
+
const toolUses = contentBlocks.filter((block) => block.type === "tool_use");
|
|
3299
3356
|
if (toolUses.length === 0) {
|
|
3300
3357
|
break;
|
|
3301
3358
|
}
|
|
3302
3359
|
conversationMessages.push({
|
|
3303
3360
|
role: "assistant",
|
|
3304
|
-
content:
|
|
3361
|
+
content: contentBlocks
|
|
3305
3362
|
});
|
|
3306
3363
|
const toolResults = {
|
|
3307
3364
|
role: "user",
|
|
3308
3365
|
content: []
|
|
3309
3366
|
};
|
|
3310
3367
|
for (const toolUse of toolUses) {
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
});
|
|
3326
|
-
}
|
|
3368
|
+
try {
|
|
3369
|
+
const result = await toolHandler(toolUse.name, toolUse.input);
|
|
3370
|
+
toolResults.content.push({
|
|
3371
|
+
type: "tool_result",
|
|
3372
|
+
tool_use_id: toolUse.id,
|
|
3373
|
+
content: typeof result === "string" ? result : JSON.stringify(result)
|
|
3374
|
+
});
|
|
3375
|
+
} catch (error) {
|
|
3376
|
+
toolResults.content.push({
|
|
3377
|
+
type: "tool_result",
|
|
3378
|
+
tool_use_id: toolUse.id,
|
|
3379
|
+
content: error instanceof Error ? error.message : String(error),
|
|
3380
|
+
is_error: true
|
|
3381
|
+
});
|
|
3327
3382
|
}
|
|
3328
3383
|
}
|
|
3329
3384
|
conversationMessages.push(toolResults);
|
|
3330
3385
|
} else {
|
|
3331
|
-
const textBlock = response.content.find((block) => block.type === "text");
|
|
3332
|
-
if (textBlock && textBlock.type === "text") {
|
|
3333
|
-
finalText = textBlock.text;
|
|
3334
|
-
if (options.partial) {
|
|
3335
|
-
options.partial(finalText);
|
|
3336
|
-
}
|
|
3337
|
-
}
|
|
3338
3386
|
break;
|
|
3339
3387
|
}
|
|
3340
3388
|
}
|
|
@@ -3397,9 +3445,9 @@ var LLM = class {
|
|
|
3397
3445
|
// ============================================================
|
|
3398
3446
|
/**
|
|
3399
3447
|
* Parse JSON string, handling markdown code blocks and surrounding text
|
|
3400
|
-
* Enhanced version from
|
|
3448
|
+
* Enhanced version with jsonrepair to handle malformed JSON from LLMs
|
|
3401
3449
|
* @param text - Text that may contain JSON wrapped in ```json...``` or with surrounding text
|
|
3402
|
-
* @returns Parsed JSON object
|
|
3450
|
+
* @returns Parsed JSON object or array
|
|
3403
3451
|
*/
|
|
3404
3452
|
static _parseJSON(text) {
|
|
3405
3453
|
let jsonText = text.trim();
|
|
@@ -3409,11 +3457,29 @@ var LLM = class {
|
|
|
3409
3457
|
jsonText = jsonText.replace(/^```\s*\n?/, "").replace(/\n?```\s*$/, "");
|
|
3410
3458
|
}
|
|
3411
3459
|
const firstBrace = jsonText.indexOf("{");
|
|
3460
|
+
const firstBracket = jsonText.indexOf("[");
|
|
3412
3461
|
const lastBrace = jsonText.lastIndexOf("}");
|
|
3413
|
-
|
|
3414
|
-
|
|
3462
|
+
const lastBracket = jsonText.lastIndexOf("]");
|
|
3463
|
+
let startIdx = -1;
|
|
3464
|
+
let endIdx = -1;
|
|
3465
|
+
if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {
|
|
3466
|
+
startIdx = firstBrace;
|
|
3467
|
+
endIdx = lastBrace;
|
|
3468
|
+
} else if (firstBracket !== -1) {
|
|
3469
|
+
startIdx = firstBracket;
|
|
3470
|
+
endIdx = lastBracket;
|
|
3471
|
+
}
|
|
3472
|
+
if (startIdx !== -1 && endIdx !== -1 && startIdx < endIdx) {
|
|
3473
|
+
jsonText = jsonText.substring(startIdx, endIdx + 1);
|
|
3474
|
+
}
|
|
3475
|
+
try {
|
|
3476
|
+
const repairedJson = jsonrepair(jsonText);
|
|
3477
|
+
return JSON.parse(repairedJson);
|
|
3478
|
+
} catch (error) {
|
|
3479
|
+
throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}
|
|
3480
|
+
|
|
3481
|
+
Original text: ${jsonText.substring(0, 200)}...`);
|
|
3415
3482
|
}
|
|
3416
|
-
return JSON.parse(jsonText);
|
|
3417
3483
|
}
|
|
3418
3484
|
};
|
|
3419
3485
|
|
|
@@ -4026,7 +4092,7 @@ var BaseLLM = class {
|
|
|
4026
4092
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
4027
4093
|
logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
|
|
4028
4094
|
logCollector?.info("Matching components from text response...");
|
|
4029
|
-
const
|
|
4095
|
+
const result = await LLM.stream(
|
|
4030
4096
|
{
|
|
4031
4097
|
sys: prompts.system,
|
|
4032
4098
|
user: prompts.user
|
|
@@ -4037,60 +4103,12 @@ var BaseLLM = class {
|
|
|
4037
4103
|
temperature: 0.2,
|
|
4038
4104
|
apiKey: this.getApiKey(apiKey)
|
|
4039
4105
|
},
|
|
4040
|
-
|
|
4041
|
-
//
|
|
4106
|
+
true
|
|
4107
|
+
// Parse as JSON
|
|
4042
4108
|
);
|
|
4043
|
-
logger.debug(`[${this.getProviderName()}]
|
|
4044
|
-
let result;
|
|
4045
|
-
try {
|
|
4046
|
-
let cleanedResponse = rawResponse || "";
|
|
4047
|
-
cleanedResponse = cleanedResponse.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
4048
|
-
const jsonMatch = cleanedResponse.match(/\{[\s\S]*\}/);
|
|
4049
|
-
if (jsonMatch) {
|
|
4050
|
-
cleanedResponse = jsonMatch[0];
|
|
4051
|
-
}
|
|
4052
|
-
result = JSON.parse(cleanedResponse);
|
|
4053
|
-
} catch (parseError) {
|
|
4054
|
-
logger.error(`[${this.getProviderName()}] Failed to parse component matching JSON response`);
|
|
4055
|
-
const errorMsg = parseError instanceof Error ? parseError.message : String(parseError);
|
|
4056
|
-
const posMatch = errorMsg.match(/position (\d+)/);
|
|
4057
|
-
const errorPos = posMatch ? parseInt(posMatch[1]) : -1;
|
|
4058
|
-
if (errorPos > 0 && rawResponse) {
|
|
4059
|
-
const start = Math.max(0, errorPos - 200);
|
|
4060
|
-
const end = Math.min(rawResponse.length, errorPos + 200);
|
|
4061
|
-
logger.debug(`[${this.getProviderName()}] Error context (position ${errorPos}):`);
|
|
4062
|
-
logger.debug(rawResponse.substring(start, end));
|
|
4063
|
-
logger.debug(" ".repeat(Math.min(200, errorPos - start)) + "^--- Error here");
|
|
4064
|
-
}
|
|
4065
|
-
logger.debug(`[${this.getProviderName()}] Raw response (first 2000 chars):`, rawResponse?.substring(0, 2e3));
|
|
4066
|
-
logger.debug(`[${this.getProviderName()}] Parse error:`, parseError);
|
|
4067
|
-
logCollector?.error(`Failed to parse component matching response: ${errorMsg}`);
|
|
4068
|
-
try {
|
|
4069
|
-
logger.info(`[${this.getProviderName()}] Attempting aggressive JSON cleanup...`);
|
|
4070
|
-
let aggressive = rawResponse || "";
|
|
4071
|
-
aggressive = aggressive.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
4072
|
-
const match = aggressive.match(/\{[\s\S]*\}/);
|
|
4073
|
-
if (match) {
|
|
4074
|
-
aggressive = match[0];
|
|
4075
|
-
}
|
|
4076
|
-
aggressive = aggressive.replace(/,(\s*[}\]])/g, "$1");
|
|
4077
|
-
result = JSON.parse(aggressive);
|
|
4078
|
-
logger.info(`[${this.getProviderName()}] Aggressive cleanup succeeded!`);
|
|
4079
|
-
} catch (secondError) {
|
|
4080
|
-
logger.error(`[${this.getProviderName()}] Aggressive cleanup also failed`);
|
|
4081
|
-
return {
|
|
4082
|
-
components: [],
|
|
4083
|
-
selectedLayout: "MultiComponentContainer",
|
|
4084
|
-
selectedLayoutId: "",
|
|
4085
|
-
selectedLayoutComponent: null,
|
|
4086
|
-
layoutReasoning: "No layout selected",
|
|
4087
|
-
actions: []
|
|
4088
|
-
};
|
|
4089
|
-
}
|
|
4090
|
-
}
|
|
4109
|
+
logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
|
|
4091
4110
|
const matchedComponents = result.matchedComponents || [];
|
|
4092
|
-
const
|
|
4093
|
-
const selectedLayoutId = result.selectedLayoutId || "";
|
|
4111
|
+
const selectedLayoutId = result.selectedLayoutId || "multi-component-container";
|
|
4094
4112
|
const layoutReasoning = result.layoutReasoning || "No layout reasoning provided";
|
|
4095
4113
|
const rawActions = result.actions || [];
|
|
4096
4114
|
const actions = convertQuestionsToActions(rawActions);
|
|
@@ -4102,11 +4120,11 @@ var BaseLLM = class {
|
|
|
4102
4120
|
}
|
|
4103
4121
|
}
|
|
4104
4122
|
logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
|
|
4105
|
-
logger.info(`[${this.getProviderName()}] Selected layout:
|
|
4123
|
+
logger.info(`[${this.getProviderName()}] Selected layout: (ID: ${selectedLayoutId})`);
|
|
4106
4124
|
logger.info(`[${this.getProviderName()}] Layout reasoning: ${layoutReasoning}`);
|
|
4107
4125
|
logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
|
|
4108
4126
|
if (matchedComponents.length > 0) {
|
|
4109
|
-
logCollector?.info(`Matched ${matchedComponents.length} components for visualization
|
|
4127
|
+
logCollector?.info(`Matched ${matchedComponents.length} components for visualization `);
|
|
4110
4128
|
logCollector?.info(`Layout reasoning: ${layoutReasoning}`);
|
|
4111
4129
|
matchedComponents.forEach((comp, idx) => {
|
|
4112
4130
|
logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
|
|
@@ -4141,7 +4159,6 @@ var BaseLLM = class {
|
|
|
4141
4159
|
}).filter(Boolean);
|
|
4142
4160
|
return {
|
|
4143
4161
|
components: finalComponents,
|
|
4144
|
-
selectedLayout,
|
|
4145
4162
|
selectedLayoutId,
|
|
4146
4163
|
selectedLayoutComponent,
|
|
4147
4164
|
layoutReasoning,
|
|
@@ -4149,15 +4166,13 @@ var BaseLLM = class {
|
|
|
4149
4166
|
};
|
|
4150
4167
|
} catch (error) {
|
|
4151
4168
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4152
|
-
logger.error(`[${this.getProviderName()}] Error matching components
|
|
4153
|
-
|
|
4154
|
-
logCollector?.error(`Error matching components: ${errorMsg}`);
|
|
4169
|
+
logger.error(`[${this.getProviderName()}] Error matching components: ${errorMsg}`);
|
|
4170
|
+
logCollector?.error(`Failed to match components: ${errorMsg}`);
|
|
4155
4171
|
return {
|
|
4156
4172
|
components: [],
|
|
4157
|
-
selectedLayout: "MultiComponentContainer",
|
|
4158
4173
|
selectedLayoutId: "",
|
|
4159
4174
|
selectedLayoutComponent: null,
|
|
4160
|
-
layoutReasoning: "
|
|
4175
|
+
layoutReasoning: "Failed to match components due to parsing error",
|
|
4161
4176
|
actions: []
|
|
4162
4177
|
};
|
|
4163
4178
|
}
|
|
@@ -4424,7 +4439,7 @@ ${errorMsg}
|
|
|
4424
4439
|
container_componet = {
|
|
4425
4440
|
...selectedLayoutComponent,
|
|
4426
4441
|
id: `${selectedLayoutComponent.id}_${Date.now()}`,
|
|
4427
|
-
|
|
4442
|
+
// Make ID unique for each instance
|
|
4428
4443
|
props: {
|
|
4429
4444
|
...selectedLayoutComponent.props,
|
|
4430
4445
|
config: {
|
|
@@ -7271,7 +7286,7 @@ var SuperatomSDK = class {
|
|
|
7271
7286
|
url.searchParams.set("projectId", this.projectId);
|
|
7272
7287
|
url.searchParams.set("userId", this.userId);
|
|
7273
7288
|
url.searchParams.set("type", this.type);
|
|
7274
|
-
logger.info(`Connecting to WebSocket: ${url.
|
|
7289
|
+
logger.info(`Connecting to WebSocket: ${url.toString()}`);
|
|
7275
7290
|
this.ws = createWebSocket(url.toString());
|
|
7276
7291
|
this.ws.addEventListener("open", () => {
|
|
7277
7292
|
this.connected = true;
|