@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.d.mts
CHANGED
|
@@ -863,9 +863,9 @@ declare class LLM {
|
|
|
863
863
|
private static _groqStream;
|
|
864
864
|
/**
|
|
865
865
|
* Parse JSON string, handling markdown code blocks and surrounding text
|
|
866
|
-
* Enhanced version from
|
|
866
|
+
* Enhanced version with jsonrepair to handle malformed JSON from LLMs
|
|
867
867
|
* @param text - Text that may contain JSON wrapped in ```json...``` or with surrounding text
|
|
868
|
-
* @returns Parsed JSON object
|
|
868
|
+
* @returns Parsed JSON object or array
|
|
869
869
|
*/
|
|
870
870
|
private static _parseJSON;
|
|
871
871
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -863,9 +863,9 @@ declare class LLM {
|
|
|
863
863
|
private static _groqStream;
|
|
864
864
|
/**
|
|
865
865
|
* Parse JSON string, handling markdown code blocks and surrounding text
|
|
866
|
-
* Enhanced version from
|
|
866
|
+
* Enhanced version with jsonrepair to handle malformed JSON from LLMs
|
|
867
867
|
* @param text - Text that may contain JSON wrapped in ```json...``` or with surrounding text
|
|
868
|
-
* @returns Parsed JSON object
|
|
868
|
+
* @returns Parsed JSON object or array
|
|
869
869
|
*/
|
|
870
870
|
private static _parseJSON;
|
|
871
871
|
}
|
package/dist/index.js
CHANGED
|
@@ -2688,6 +2688,7 @@ When the user asks about data
|
|
|
2688
2688
|
|
|
2689
2689
|
After analyzing the query results, you MUST suggest appropriate dashboard components for displaying the data. Use this format:
|
|
2690
2690
|
|
|
2691
|
+
<DashboardComponents>
|
|
2691
2692
|
**Dashboard Components:**
|
|
2692
2693
|
Format: \`{number}.{component_type} : {clear reasoning}\`
|
|
2693
2694
|
|
|
@@ -2696,9 +2697,9 @@ Format: \`{number}.{component_type} : {clear reasoning}\`
|
|
|
2696
2697
|
1. Analyze the query results structure and data type
|
|
2697
2698
|
2. Suggest components that would best visualize the data
|
|
2698
2699
|
3. Each component suggestion must be on a new line
|
|
2700
|
+
</DashboardComponents>
|
|
2699
2701
|
|
|
2700
|
-
|
|
2701
|
-
IMPORTANT: Always include the **Dashboard Components:** section with at least one component suggestion when data is returned.
|
|
2702
|
+
IMPORTANT: Always wrap component suggestions with <DashboardComponents> tags and include at least one component suggestion when data is returned.
|
|
2702
2703
|
|
|
2703
2704
|
## Output Format
|
|
2704
2705
|
|
|
@@ -2706,7 +2707,7 @@ Respond with plain text that includes:
|
|
|
2706
2707
|
|
|
2707
2708
|
1. **Query Analysis** (if applicable): Brief explanation of what data was fetched
|
|
2708
2709
|
2. **Results Summary**: Present the data in a clear, readable format
|
|
2709
|
-
3. **Dashboard Components**: List suggested components in
|
|
2710
|
+
3. **Dashboard Components**: List suggested components wrapped in <DashboardComponents> tags
|
|
2710
2711
|
|
|
2711
2712
|
|
|
2712
2713
|
**CRITICAL:**
|
|
@@ -2783,39 +2784,22 @@ You will receive a text response containing:
|
|
|
2783
2784
|
3. **Dashboard Components:** suggestions (1:component_type : reasoning format)
|
|
2784
2785
|
|
|
2785
2786
|
Your job is to:
|
|
2786
|
-
1. **
|
|
2787
|
-
2.
|
|
2788
|
-
3.
|
|
2789
|
-
4.
|
|
2790
|
-
5. Generate
|
|
2791
|
-
6. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis
|
|
2787
|
+
1. **Parse the component suggestions** from the text response (format: 1:component_type : reasoning)
|
|
2788
|
+
2. **Match each suggestion with an actual component** from the available list
|
|
2789
|
+
3. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched
|
|
2790
|
+
4. **SELECT the best dashboard layout component** that can accommodate all the matched components
|
|
2791
|
+
5. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis
|
|
2792
2792
|
|
|
2793
2793
|
**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.
|
|
2794
2794
|
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
## Layout Component Discovery
|
|
2798
|
-
**Find layout components** by looking for components with \`type: "DashboardLayout"\`
|
|
2799
|
-
|
|
2800
|
-
## Layout Selection Logic
|
|
2801
|
-
1. **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 exact number and types of components it requires
|
|
2805
|
-
2. **Select the best layout** based on:
|
|
2806
|
-
- Which layout structure best fits the analysis needs
|
|
2807
|
-
- The component suggestions from the text response
|
|
2808
|
-
- The user question and data complexity
|
|
2809
|
-
3. **Generate EXACTLY the components specified** in the selected layout's description
|
|
2810
|
-
|
|
2811
|
-
**IMPORTANT:** Always prefer structured dashboard layouts when available. The layout component's description will tell you exactly what components to generate.
|
|
2795
|
+
**APPROACH**: First match all the components suggested in the text response, THEN find the layout that best fits those components.
|
|
2812
2796
|
|
|
2813
2797
|
## Available Components
|
|
2814
2798
|
|
|
2815
2799
|
{{AVAILABLE_COMPONENTS}}
|
|
2816
2800
|
|
|
2817
|
-
## Component Matching Rules
|
|
2818
|
-
For each component suggestion (c1, c2, c3, etc.):
|
|
2801
|
+
## Component Matching Rules (STEP 1)
|
|
2802
|
+
For each component suggestion (c1, c2, c3, etc.) from the text response:
|
|
2819
2803
|
|
|
2820
2804
|
1. **Match by type**: Find components whose \`type\` matches the suggested component type
|
|
2821
2805
|
2. **Refine by relevance**: If multiple components match, choose based on:
|
|
@@ -2823,6 +2807,24 @@ For each component suggestion (c1, c2, c3, etc.):
|
|
|
2823
2807
|
- Best fit for the data being visualized
|
|
2824
2808
|
3. **Fallback**: If no exact type match, find the closest alternative
|
|
2825
2809
|
|
|
2810
|
+
## Layout Selection Logic (STEP 2 - After Matching Components)
|
|
2811
|
+
|
|
2812
|
+
**After you have matched all components**, select the best dashboard layout:
|
|
2813
|
+
|
|
2814
|
+
1. **Find layout components** by looking for components with \`type: "DashboardLayout"\` in the available components list
|
|
2815
|
+
2. **Read each layout's description** to understand:
|
|
2816
|
+
- What structure it provides
|
|
2817
|
+
- When it's best used (e.g., comprehensive analysis vs focused analysis)
|
|
2818
|
+
- The number and types of components it can accommodate
|
|
2819
|
+
3. **Select the best layout** based on:
|
|
2820
|
+
- Which layout can best display ALL the matched components
|
|
2821
|
+
- The layout's capacity (how many components it supports)
|
|
2822
|
+
- The types of matched components (KPI, charts, tables, etc.)
|
|
2823
|
+
- The user question and data complexity
|
|
2824
|
+
4. **If no specific layout fits**, fall back to "MultiComponentContainer" as the default layout
|
|
2825
|
+
|
|
2826
|
+
**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.
|
|
2827
|
+
|
|
2826
2828
|
## Props Generation Rules
|
|
2827
2829
|
|
|
2828
2830
|
For each matched component, generate complete props:
|
|
@@ -2935,7 +2937,6 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
2935
2937
|
|
|
2936
2938
|
\`\`\`json
|
|
2937
2939
|
{
|
|
2938
|
-
"selectedLayout": "Name of the selected layout component from available components",
|
|
2939
2940
|
"selectedLayoutId": "id_of_the_selected_layout_component",
|
|
2940
2941
|
"layoutReasoning": "Why this layout was selected based on its description and the analysis needs",
|
|
2941
2942
|
"matchedComponents": [
|
|
@@ -2967,13 +2968,14 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
2967
2968
|
\`\`\`
|
|
2968
2969
|
|
|
2969
2970
|
**CRITICAL:**
|
|
2970
|
-
- \`
|
|
2971
|
-
- \`selectedLayoutId\` MUST be the ID of the selected layout component
|
|
2971
|
+
- \`matchedComponents\` MUST include ALL components suggested in the text response (match them first!)
|
|
2972
|
+
- \`selectedLayoutId\` MUST be the ID of the selected layout component (must have type "DashboardLayout")
|
|
2972
2973
|
- \`layoutReasoning\` MUST explain:
|
|
2973
2974
|
- Why you chose this specific layout component
|
|
2974
|
-
- How
|
|
2975
|
-
-
|
|
2976
|
-
-
|
|
2975
|
+
- How many components you matched (e.g., "Matched 3 components: 1 KPI, 1 chart, 1 table")
|
|
2976
|
+
- Why this layout is the best fit for displaying these specific matched components
|
|
2977
|
+
- What makes this layout appropriate for the component types and count
|
|
2978
|
+
- The layout selection happens AFTER component matching - don't force components to fit a pre-selected layout
|
|
2977
2979
|
- \`actions\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis
|
|
2978
2980
|
- Return ONLY valid JSON (no markdown code blocks, no text before/after)
|
|
2979
2981
|
- Generate complete props for each component
|
|
@@ -3169,6 +3171,7 @@ var promptLoader = new PromptLoader({
|
|
|
3169
3171
|
// src/llm.ts
|
|
3170
3172
|
var import_sdk = __toESM(require("@anthropic-ai/sdk"));
|
|
3171
3173
|
var import_groq_sdk = __toESM(require("groq-sdk"));
|
|
3174
|
+
var import_jsonrepair = require("jsonrepair");
|
|
3172
3175
|
var LLM = class {
|
|
3173
3176
|
/* Get a complete text response from an LLM (Anthropic or Groq) */
|
|
3174
3177
|
static async text(messages, options = {}) {
|
|
@@ -3290,65 +3293,110 @@ var LLM = class {
|
|
|
3290
3293
|
let finalText = "";
|
|
3291
3294
|
while (iterations < maxIterations) {
|
|
3292
3295
|
iterations++;
|
|
3293
|
-
const
|
|
3296
|
+
const stream = await client.messages.create({
|
|
3294
3297
|
model: modelName,
|
|
3295
3298
|
max_tokens: options.maxTokens || 4e3,
|
|
3296
3299
|
temperature: options.temperature,
|
|
3297
3300
|
system: messages.sys,
|
|
3298
3301
|
messages: conversationMessages,
|
|
3299
|
-
tools
|
|
3302
|
+
tools,
|
|
3303
|
+
stream: true
|
|
3304
|
+
// Enable streaming
|
|
3300
3305
|
});
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3306
|
+
let stopReason = null;
|
|
3307
|
+
const contentBlocks = [];
|
|
3308
|
+
let currentTextBlock = "";
|
|
3309
|
+
let currentToolUse = null;
|
|
3310
|
+
for await (const chunk of stream) {
|
|
3311
|
+
if (chunk.type === "message_start") {
|
|
3312
|
+
contentBlocks.length = 0;
|
|
3313
|
+
currentTextBlock = "";
|
|
3314
|
+
currentToolUse = null;
|
|
3315
|
+
}
|
|
3316
|
+
if (chunk.type === "content_block_start") {
|
|
3317
|
+
if (chunk.content_block.type === "text") {
|
|
3318
|
+
currentTextBlock = "";
|
|
3319
|
+
} else if (chunk.content_block.type === "tool_use") {
|
|
3320
|
+
currentToolUse = {
|
|
3321
|
+
type: "tool_use",
|
|
3322
|
+
id: chunk.content_block.id,
|
|
3323
|
+
name: chunk.content_block.name,
|
|
3324
|
+
input: {}
|
|
3325
|
+
};
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3328
|
+
if (chunk.type === "content_block_delta") {
|
|
3329
|
+
if (chunk.delta.type === "text_delta") {
|
|
3330
|
+
const text = chunk.delta.text;
|
|
3331
|
+
currentTextBlock += text;
|
|
3332
|
+
if (options.partial) {
|
|
3333
|
+
options.partial(text);
|
|
3334
|
+
}
|
|
3335
|
+
} else if (chunk.delta.type === "input_json_delta" && currentToolUse) {
|
|
3336
|
+
currentToolUse.inputJson = (currentToolUse.inputJson || "") + chunk.delta.partial_json;
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
if (chunk.type === "content_block_stop") {
|
|
3340
|
+
if (currentTextBlock) {
|
|
3341
|
+
contentBlocks.push({
|
|
3342
|
+
type: "text",
|
|
3343
|
+
text: currentTextBlock
|
|
3344
|
+
});
|
|
3345
|
+
finalText = currentTextBlock;
|
|
3346
|
+
currentTextBlock = "";
|
|
3347
|
+
} else if (currentToolUse) {
|
|
3348
|
+
try {
|
|
3349
|
+
currentToolUse.input = currentToolUse.inputJson ? JSON.parse(currentToolUse.inputJson) : {};
|
|
3350
|
+
} catch (error) {
|
|
3351
|
+
currentToolUse.input = {};
|
|
3352
|
+
}
|
|
3353
|
+
delete currentToolUse.inputJson;
|
|
3354
|
+
contentBlocks.push(currentToolUse);
|
|
3355
|
+
currentToolUse = null;
|
|
3307
3356
|
}
|
|
3308
3357
|
}
|
|
3358
|
+
if (chunk.type === "message_delta") {
|
|
3359
|
+
stopReason = chunk.delta.stop_reason || stopReason;
|
|
3360
|
+
}
|
|
3361
|
+
if (chunk.type === "message_stop") {
|
|
3362
|
+
break;
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
if (stopReason === "end_turn") {
|
|
3309
3366
|
break;
|
|
3310
3367
|
}
|
|
3311
|
-
if (
|
|
3312
|
-
const toolUses =
|
|
3368
|
+
if (stopReason === "tool_use") {
|
|
3369
|
+
const toolUses = contentBlocks.filter((block) => block.type === "tool_use");
|
|
3313
3370
|
if (toolUses.length === 0) {
|
|
3314
3371
|
break;
|
|
3315
3372
|
}
|
|
3316
3373
|
conversationMessages.push({
|
|
3317
3374
|
role: "assistant",
|
|
3318
|
-
content:
|
|
3375
|
+
content: contentBlocks
|
|
3319
3376
|
});
|
|
3320
3377
|
const toolResults = {
|
|
3321
3378
|
role: "user",
|
|
3322
3379
|
content: []
|
|
3323
3380
|
};
|
|
3324
3381
|
for (const toolUse of toolUses) {
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
});
|
|
3340
|
-
}
|
|
3382
|
+
try {
|
|
3383
|
+
const result = await toolHandler(toolUse.name, toolUse.input);
|
|
3384
|
+
toolResults.content.push({
|
|
3385
|
+
type: "tool_result",
|
|
3386
|
+
tool_use_id: toolUse.id,
|
|
3387
|
+
content: typeof result === "string" ? result : JSON.stringify(result)
|
|
3388
|
+
});
|
|
3389
|
+
} catch (error) {
|
|
3390
|
+
toolResults.content.push({
|
|
3391
|
+
type: "tool_result",
|
|
3392
|
+
tool_use_id: toolUse.id,
|
|
3393
|
+
content: error instanceof Error ? error.message : String(error),
|
|
3394
|
+
is_error: true
|
|
3395
|
+
});
|
|
3341
3396
|
}
|
|
3342
3397
|
}
|
|
3343
3398
|
conversationMessages.push(toolResults);
|
|
3344
3399
|
} else {
|
|
3345
|
-
const textBlock = response.content.find((block) => block.type === "text");
|
|
3346
|
-
if (textBlock && textBlock.type === "text") {
|
|
3347
|
-
finalText = textBlock.text;
|
|
3348
|
-
if (options.partial) {
|
|
3349
|
-
options.partial(finalText);
|
|
3350
|
-
}
|
|
3351
|
-
}
|
|
3352
3400
|
break;
|
|
3353
3401
|
}
|
|
3354
3402
|
}
|
|
@@ -3411,9 +3459,9 @@ var LLM = class {
|
|
|
3411
3459
|
// ============================================================
|
|
3412
3460
|
/**
|
|
3413
3461
|
* Parse JSON string, handling markdown code blocks and surrounding text
|
|
3414
|
-
* Enhanced version from
|
|
3462
|
+
* Enhanced version with jsonrepair to handle malformed JSON from LLMs
|
|
3415
3463
|
* @param text - Text that may contain JSON wrapped in ```json...``` or with surrounding text
|
|
3416
|
-
* @returns Parsed JSON object
|
|
3464
|
+
* @returns Parsed JSON object or array
|
|
3417
3465
|
*/
|
|
3418
3466
|
static _parseJSON(text) {
|
|
3419
3467
|
let jsonText = text.trim();
|
|
@@ -3423,11 +3471,29 @@ var LLM = class {
|
|
|
3423
3471
|
jsonText = jsonText.replace(/^```\s*\n?/, "").replace(/\n?```\s*$/, "");
|
|
3424
3472
|
}
|
|
3425
3473
|
const firstBrace = jsonText.indexOf("{");
|
|
3474
|
+
const firstBracket = jsonText.indexOf("[");
|
|
3426
3475
|
const lastBrace = jsonText.lastIndexOf("}");
|
|
3427
|
-
|
|
3428
|
-
|
|
3476
|
+
const lastBracket = jsonText.lastIndexOf("]");
|
|
3477
|
+
let startIdx = -1;
|
|
3478
|
+
let endIdx = -1;
|
|
3479
|
+
if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {
|
|
3480
|
+
startIdx = firstBrace;
|
|
3481
|
+
endIdx = lastBrace;
|
|
3482
|
+
} else if (firstBracket !== -1) {
|
|
3483
|
+
startIdx = firstBracket;
|
|
3484
|
+
endIdx = lastBracket;
|
|
3485
|
+
}
|
|
3486
|
+
if (startIdx !== -1 && endIdx !== -1 && startIdx < endIdx) {
|
|
3487
|
+
jsonText = jsonText.substring(startIdx, endIdx + 1);
|
|
3488
|
+
}
|
|
3489
|
+
try {
|
|
3490
|
+
const repairedJson = (0, import_jsonrepair.jsonrepair)(jsonText);
|
|
3491
|
+
return JSON.parse(repairedJson);
|
|
3492
|
+
} catch (error) {
|
|
3493
|
+
throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}
|
|
3494
|
+
|
|
3495
|
+
Original text: ${jsonText.substring(0, 200)}...`);
|
|
3429
3496
|
}
|
|
3430
|
-
return JSON.parse(jsonText);
|
|
3431
3497
|
}
|
|
3432
3498
|
};
|
|
3433
3499
|
|
|
@@ -4040,7 +4106,7 @@ var BaseLLM = class {
|
|
|
4040
4106
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
4041
4107
|
logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
|
|
4042
4108
|
logCollector?.info("Matching components from text response...");
|
|
4043
|
-
const
|
|
4109
|
+
const result = await LLM.stream(
|
|
4044
4110
|
{
|
|
4045
4111
|
sys: prompts.system,
|
|
4046
4112
|
user: prompts.user
|
|
@@ -4051,60 +4117,12 @@ var BaseLLM = class {
|
|
|
4051
4117
|
temperature: 0.2,
|
|
4052
4118
|
apiKey: this.getApiKey(apiKey)
|
|
4053
4119
|
},
|
|
4054
|
-
|
|
4055
|
-
//
|
|
4120
|
+
true
|
|
4121
|
+
// Parse as JSON
|
|
4056
4122
|
);
|
|
4057
|
-
logger.debug(`[${this.getProviderName()}]
|
|
4058
|
-
let result;
|
|
4059
|
-
try {
|
|
4060
|
-
let cleanedResponse = rawResponse || "";
|
|
4061
|
-
cleanedResponse = cleanedResponse.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
4062
|
-
const jsonMatch = cleanedResponse.match(/\{[\s\S]*\}/);
|
|
4063
|
-
if (jsonMatch) {
|
|
4064
|
-
cleanedResponse = jsonMatch[0];
|
|
4065
|
-
}
|
|
4066
|
-
result = JSON.parse(cleanedResponse);
|
|
4067
|
-
} catch (parseError) {
|
|
4068
|
-
logger.error(`[${this.getProviderName()}] Failed to parse component matching JSON response`);
|
|
4069
|
-
const errorMsg = parseError instanceof Error ? parseError.message : String(parseError);
|
|
4070
|
-
const posMatch = errorMsg.match(/position (\d+)/);
|
|
4071
|
-
const errorPos = posMatch ? parseInt(posMatch[1]) : -1;
|
|
4072
|
-
if (errorPos > 0 && rawResponse) {
|
|
4073
|
-
const start = Math.max(0, errorPos - 200);
|
|
4074
|
-
const end = Math.min(rawResponse.length, errorPos + 200);
|
|
4075
|
-
logger.debug(`[${this.getProviderName()}] Error context (position ${errorPos}):`);
|
|
4076
|
-
logger.debug(rawResponse.substring(start, end));
|
|
4077
|
-
logger.debug(" ".repeat(Math.min(200, errorPos - start)) + "^--- Error here");
|
|
4078
|
-
}
|
|
4079
|
-
logger.debug(`[${this.getProviderName()}] Raw response (first 2000 chars):`, rawResponse?.substring(0, 2e3));
|
|
4080
|
-
logger.debug(`[${this.getProviderName()}] Parse error:`, parseError);
|
|
4081
|
-
logCollector?.error(`Failed to parse component matching response: ${errorMsg}`);
|
|
4082
|
-
try {
|
|
4083
|
-
logger.info(`[${this.getProviderName()}] Attempting aggressive JSON cleanup...`);
|
|
4084
|
-
let aggressive = rawResponse || "";
|
|
4085
|
-
aggressive = aggressive.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
4086
|
-
const match = aggressive.match(/\{[\s\S]*\}/);
|
|
4087
|
-
if (match) {
|
|
4088
|
-
aggressive = match[0];
|
|
4089
|
-
}
|
|
4090
|
-
aggressive = aggressive.replace(/,(\s*[}\]])/g, "$1");
|
|
4091
|
-
result = JSON.parse(aggressive);
|
|
4092
|
-
logger.info(`[${this.getProviderName()}] Aggressive cleanup succeeded!`);
|
|
4093
|
-
} catch (secondError) {
|
|
4094
|
-
logger.error(`[${this.getProviderName()}] Aggressive cleanup also failed`);
|
|
4095
|
-
return {
|
|
4096
|
-
components: [],
|
|
4097
|
-
selectedLayout: "MultiComponentContainer",
|
|
4098
|
-
selectedLayoutId: "",
|
|
4099
|
-
selectedLayoutComponent: null,
|
|
4100
|
-
layoutReasoning: "No layout selected",
|
|
4101
|
-
actions: []
|
|
4102
|
-
};
|
|
4103
|
-
}
|
|
4104
|
-
}
|
|
4123
|
+
logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
|
|
4105
4124
|
const matchedComponents = result.matchedComponents || [];
|
|
4106
|
-
const
|
|
4107
|
-
const selectedLayoutId = result.selectedLayoutId || "";
|
|
4125
|
+
const selectedLayoutId = result.selectedLayoutId || "multi-component-container";
|
|
4108
4126
|
const layoutReasoning = result.layoutReasoning || "No layout reasoning provided";
|
|
4109
4127
|
const rawActions = result.actions || [];
|
|
4110
4128
|
const actions = convertQuestionsToActions(rawActions);
|
|
@@ -4116,11 +4134,11 @@ var BaseLLM = class {
|
|
|
4116
4134
|
}
|
|
4117
4135
|
}
|
|
4118
4136
|
logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
|
|
4119
|
-
logger.info(`[${this.getProviderName()}] Selected layout:
|
|
4137
|
+
logger.info(`[${this.getProviderName()}] Selected layout: (ID: ${selectedLayoutId})`);
|
|
4120
4138
|
logger.info(`[${this.getProviderName()}] Layout reasoning: ${layoutReasoning}`);
|
|
4121
4139
|
logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
|
|
4122
4140
|
if (matchedComponents.length > 0) {
|
|
4123
|
-
logCollector?.info(`Matched ${matchedComponents.length} components for visualization
|
|
4141
|
+
logCollector?.info(`Matched ${matchedComponents.length} components for visualization `);
|
|
4124
4142
|
logCollector?.info(`Layout reasoning: ${layoutReasoning}`);
|
|
4125
4143
|
matchedComponents.forEach((comp, idx) => {
|
|
4126
4144
|
logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
|
|
@@ -4155,7 +4173,6 @@ var BaseLLM = class {
|
|
|
4155
4173
|
}).filter(Boolean);
|
|
4156
4174
|
return {
|
|
4157
4175
|
components: finalComponents,
|
|
4158
|
-
selectedLayout,
|
|
4159
4176
|
selectedLayoutId,
|
|
4160
4177
|
selectedLayoutComponent,
|
|
4161
4178
|
layoutReasoning,
|
|
@@ -4163,15 +4180,13 @@ var BaseLLM = class {
|
|
|
4163
4180
|
};
|
|
4164
4181
|
} catch (error) {
|
|
4165
4182
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4166
|
-
logger.error(`[${this.getProviderName()}] Error matching components
|
|
4167
|
-
|
|
4168
|
-
logCollector?.error(`Error matching components: ${errorMsg}`);
|
|
4183
|
+
logger.error(`[${this.getProviderName()}] Error matching components: ${errorMsg}`);
|
|
4184
|
+
logCollector?.error(`Failed to match components: ${errorMsg}`);
|
|
4169
4185
|
return {
|
|
4170
4186
|
components: [],
|
|
4171
|
-
selectedLayout: "MultiComponentContainer",
|
|
4172
4187
|
selectedLayoutId: "",
|
|
4173
4188
|
selectedLayoutComponent: null,
|
|
4174
|
-
layoutReasoning: "
|
|
4189
|
+
layoutReasoning: "Failed to match components due to parsing error",
|
|
4175
4190
|
actions: []
|
|
4176
4191
|
};
|
|
4177
4192
|
}
|
|
@@ -4438,7 +4453,7 @@ ${errorMsg}
|
|
|
4438
4453
|
container_componet = {
|
|
4439
4454
|
...selectedLayoutComponent,
|
|
4440
4455
|
id: `${selectedLayoutComponent.id}_${Date.now()}`,
|
|
4441
|
-
|
|
4456
|
+
// Make ID unique for each instance
|
|
4442
4457
|
props: {
|
|
4443
4458
|
...selectedLayoutComponent.props,
|
|
4444
4459
|
config: {
|
|
@@ -7285,7 +7300,7 @@ var SuperatomSDK = class {
|
|
|
7285
7300
|
url.searchParams.set("projectId", this.projectId);
|
|
7286
7301
|
url.searchParams.set("userId", this.userId);
|
|
7287
7302
|
url.searchParams.set("type", this.type);
|
|
7288
|
-
logger.info(`Connecting to WebSocket: ${url.
|
|
7303
|
+
logger.info(`Connecting to WebSocket: ${url.toString()}`);
|
|
7289
7304
|
this.ws = createWebSocket(url.toString());
|
|
7290
7305
|
this.ws.addEventListener("open", () => {
|
|
7291
7306
|
this.connected = true;
|