@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 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 anthropic.ts implementation
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 anthropic.ts implementation
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 the c1:type format
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. **DISCOVER and SELECT the best dashboard layout component** from the available components list
2787
- 2. Parse the component suggestions from the text response
2788
- 3. Match each suggestion with an actual component from the available list
2789
- 4. Generate the RIGHT NUMBER of components to fit the selected layout perfectly (based on the layout component's description)
2790
- 5. Generate proper props to **visualize the analysis results** that were already fetched
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
- - \`selectedLayout\` MUST be the NAME of a layout component from the available components list (must have type "DashboardLayout")
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 its structure (from its description) matches the analysis needs
2975
- - What components it requires based on its description
2976
- - \`matchedComponents\` array length and types MUST match what the selected layout's description specifies
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 response = await client.messages.create({
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
- if (response.stop_reason === "end_turn") {
3302
- const textBlock = response.content.find((block) => block.type === "text");
3303
- if (textBlock && textBlock.type === "text") {
3304
- finalText = textBlock.text;
3305
- if (options.partial) {
3306
- options.partial(finalText);
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 (response.stop_reason === "tool_use") {
3312
- const toolUses = response.content.filter((block) => block.type === "tool_use");
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: response.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
- if (toolUse.type === "tool_use") {
3326
- try {
3327
- const result = await toolHandler(toolUse.name, toolUse.input);
3328
- toolResults.content.push({
3329
- type: "tool_result",
3330
- tool_use_id: toolUse.id,
3331
- content: typeof result === "string" ? result : JSON.stringify(result)
3332
- });
3333
- } catch (error) {
3334
- toolResults.content.push({
3335
- type: "tool_result",
3336
- tool_use_id: toolUse.id,
3337
- content: error instanceof Error ? error.message : String(error),
3338
- is_error: true
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 anthropic.ts implementation
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
- if (firstBrace !== -1 && lastBrace !== -1 && firstBrace < lastBrace) {
3428
- jsonText = jsonText.substring(firstBrace, lastBrace + 1);
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 rawResponse = await LLM.stream(
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
- false
4055
- // Don't parse as JSON yet, get raw response
4120
+ true
4121
+ // Parse as JSON
4056
4122
  );
4057
- logger.debug(`[${this.getProviderName()}] Raw component matching response length: ${rawResponse?.length || 0}`);
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 selectedLayout = result.selectedLayout || "MultiComponentContainer";
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: ${selectedLayout} (ID: ${selectedLayoutId})`);
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 using ${selectedLayout}`);
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 from text response: ${errorMsg}`);
4167
- logger.debug(`[${this.getProviderName()}] Component matching error details:`, error);
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: "Error occurred during component matching",
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
- description: layoutReasoning,
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.host}`);
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;