@superatomai/sdk-node 0.0.9 → 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
@@ -1,439 +1,12 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
- }) : x)(function(x) {
10
- if (typeof require !== "undefined") return require.apply(this, arguments);
11
- throw Error('Dynamic require of "' + x + '" is not supported');
12
- });
13
3
  var __esm = (fn, res) => function __init() {
14
4
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
5
  };
16
- var __commonJS = (cb, mod) => function __require2() {
17
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
- };
19
6
  var __export = (target, all) => {
20
7
  for (var name in all)
21
8
  __defProp(target, name, { get: all[name], enumerable: true });
22
9
  };
23
- var __copyProps = (to, from, except, desc) => {
24
- if (from && typeof from === "object" || typeof from === "function") {
25
- for (let key of __getOwnPropNames(from))
26
- if (!__hasOwnProp.call(to, key) && key !== except)
27
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
28
- }
29
- return to;
30
- };
31
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
32
- // If the importer is in node compatibility mode or this is not an ESM
33
- // file that has been converted to a CommonJS file using a Babel-
34
- // compatible transform (i.e. "__esModule" has not been set), then set
35
- // "default" to the CommonJS "module.exports" for node compatibility.
36
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
37
- mod
38
- ));
39
-
40
- // node_modules/dotenv/package.json
41
- var require_package = __commonJS({
42
- "node_modules/dotenv/package.json"(exports, module) {
43
- module.exports = {
44
- name: "dotenv",
45
- version: "17.2.3",
46
- description: "Loads environment variables from .env file",
47
- main: "lib/main.js",
48
- types: "lib/main.d.ts",
49
- exports: {
50
- ".": {
51
- types: "./lib/main.d.ts",
52
- require: "./lib/main.js",
53
- default: "./lib/main.js"
54
- },
55
- "./config": "./config.js",
56
- "./config.js": "./config.js",
57
- "./lib/env-options": "./lib/env-options.js",
58
- "./lib/env-options.js": "./lib/env-options.js",
59
- "./lib/cli-options": "./lib/cli-options.js",
60
- "./lib/cli-options.js": "./lib/cli-options.js",
61
- "./package.json": "./package.json"
62
- },
63
- scripts: {
64
- "dts-check": "tsc --project tests/types/tsconfig.json",
65
- lint: "standard",
66
- pretest: "npm run lint && npm run dts-check",
67
- test: "tap run tests/**/*.js --allow-empty-coverage --disable-coverage --timeout=60000",
68
- "test:coverage": "tap run tests/**/*.js --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
69
- prerelease: "npm test",
70
- release: "standard-version"
71
- },
72
- repository: {
73
- type: "git",
74
- url: "git://github.com/motdotla/dotenv.git"
75
- },
76
- homepage: "https://github.com/motdotla/dotenv#readme",
77
- funding: "https://dotenvx.com",
78
- keywords: [
79
- "dotenv",
80
- "env",
81
- ".env",
82
- "environment",
83
- "variables",
84
- "config",
85
- "settings"
86
- ],
87
- readmeFilename: "README.md",
88
- license: "BSD-2-Clause",
89
- devDependencies: {
90
- "@types/node": "^18.11.3",
91
- decache: "^4.6.2",
92
- sinon: "^14.0.1",
93
- standard: "^17.0.0",
94
- "standard-version": "^9.5.0",
95
- tap: "^19.2.0",
96
- typescript: "^4.8.4"
97
- },
98
- engines: {
99
- node: ">=12"
100
- },
101
- browser: {
102
- fs: false
103
- }
104
- };
105
- }
106
- });
107
-
108
- // node_modules/dotenv/lib/main.js
109
- var require_main = __commonJS({
110
- "node_modules/dotenv/lib/main.js"(exports, module) {
111
- "use strict";
112
- var fs8 = __require("fs");
113
- var path7 = __require("path");
114
- var os4 = __require("os");
115
- var crypto2 = __require("crypto");
116
- var packageJson = require_package();
117
- var version = packageJson.version;
118
- var TIPS = [
119
- "\u{1F510} encrypt with Dotenvx: https://dotenvx.com",
120
- "\u{1F510} prevent committing .env to code: https://dotenvx.com/precommit",
121
- "\u{1F510} prevent building .env in docker: https://dotenvx.com/prebuild",
122
- "\u{1F4E1} add observability to secrets: https://dotenvx.com/ops",
123
- "\u{1F465} sync secrets across teammates & machines: https://dotenvx.com/ops",
124
- "\u{1F5C2}\uFE0F backup and recover secrets: https://dotenvx.com/ops",
125
- "\u2705 audit secrets and track compliance: https://dotenvx.com/ops",
126
- "\u{1F504} add secrets lifecycle management: https://dotenvx.com/ops",
127
- "\u{1F511} add access controls to secrets: https://dotenvx.com/ops",
128
- "\u{1F6E0}\uFE0F run anywhere with `dotenvx run -- yourcommand`",
129
- "\u2699\uFE0F specify custom .env file path with { path: '/custom/path/.env' }",
130
- "\u2699\uFE0F enable debug logging with { debug: true }",
131
- "\u2699\uFE0F override existing env vars with { override: true }",
132
- "\u2699\uFE0F suppress all logs with { quiet: true }",
133
- "\u2699\uFE0F write to custom object with { processEnv: myObject }",
134
- "\u2699\uFE0F load multiple .env files with { path: ['.env.local', '.env'] }"
135
- ];
136
- function _getRandomTip() {
137
- return TIPS[Math.floor(Math.random() * TIPS.length)];
138
- }
139
- function parseBoolean(value) {
140
- if (typeof value === "string") {
141
- return !["false", "0", "no", "off", ""].includes(value.toLowerCase());
142
- }
143
- return Boolean(value);
144
- }
145
- function supportsAnsi() {
146
- return process.stdout.isTTY;
147
- }
148
- function dim(text) {
149
- return supportsAnsi() ? `\x1B[2m${text}\x1B[0m` : text;
150
- }
151
- var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
152
- function parse(src) {
153
- const obj = {};
154
- let lines = src.toString();
155
- lines = lines.replace(/\r\n?/mg, "\n");
156
- let match;
157
- while ((match = LINE.exec(lines)) != null) {
158
- const key = match[1];
159
- let value = match[2] || "";
160
- value = value.trim();
161
- const maybeQuote = value[0];
162
- value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
163
- if (maybeQuote === '"') {
164
- value = value.replace(/\\n/g, "\n");
165
- value = value.replace(/\\r/g, "\r");
166
- }
167
- obj[key] = value;
168
- }
169
- return obj;
170
- }
171
- function _parseVault(options) {
172
- options = options || {};
173
- const vaultPath = _vaultPath(options);
174
- options.path = vaultPath;
175
- const result = DotenvModule.configDotenv(options);
176
- if (!result.parsed) {
177
- const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
178
- err.code = "MISSING_DATA";
179
- throw err;
180
- }
181
- const keys = _dotenvKey(options).split(",");
182
- const length = keys.length;
183
- let decrypted;
184
- for (let i = 0; i < length; i++) {
185
- try {
186
- const key = keys[i].trim();
187
- const attrs = _instructions(result, key);
188
- decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
189
- break;
190
- } catch (error) {
191
- if (i + 1 >= length) {
192
- throw error;
193
- }
194
- }
195
- }
196
- return DotenvModule.parse(decrypted);
197
- }
198
- function _warn(message) {
199
- console.error(`[dotenv@${version}][WARN] ${message}`);
200
- }
201
- function _debug(message) {
202
- console.log(`[dotenv@${version}][DEBUG] ${message}`);
203
- }
204
- function _log(message) {
205
- console.log(`[dotenv@${version}] ${message}`);
206
- }
207
- function _dotenvKey(options) {
208
- if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
209
- return options.DOTENV_KEY;
210
- }
211
- if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
212
- return process.env.DOTENV_KEY;
213
- }
214
- return "";
215
- }
216
- function _instructions(result, dotenvKey) {
217
- let uri;
218
- try {
219
- uri = new URL(dotenvKey);
220
- } catch (error) {
221
- if (error.code === "ERR_INVALID_URL") {
222
- const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
223
- err.code = "INVALID_DOTENV_KEY";
224
- throw err;
225
- }
226
- throw error;
227
- }
228
- const key = uri.password;
229
- if (!key) {
230
- const err = new Error("INVALID_DOTENV_KEY: Missing key part");
231
- err.code = "INVALID_DOTENV_KEY";
232
- throw err;
233
- }
234
- const environment = uri.searchParams.get("environment");
235
- if (!environment) {
236
- const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
237
- err.code = "INVALID_DOTENV_KEY";
238
- throw err;
239
- }
240
- const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
241
- const ciphertext = result.parsed[environmentKey];
242
- if (!ciphertext) {
243
- const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
244
- err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
245
- throw err;
246
- }
247
- return { ciphertext, key };
248
- }
249
- function _vaultPath(options) {
250
- let possibleVaultPath = null;
251
- if (options && options.path && options.path.length > 0) {
252
- if (Array.isArray(options.path)) {
253
- for (const filepath of options.path) {
254
- if (fs8.existsSync(filepath)) {
255
- possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
256
- }
257
- }
258
- } else {
259
- possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
260
- }
261
- } else {
262
- possibleVaultPath = path7.resolve(process.cwd(), ".env.vault");
263
- }
264
- if (fs8.existsSync(possibleVaultPath)) {
265
- return possibleVaultPath;
266
- }
267
- return null;
268
- }
269
- function _resolveHome(envPath) {
270
- return envPath[0] === "~" ? path7.join(os4.homedir(), envPath.slice(1)) : envPath;
271
- }
272
- function _configVault(options) {
273
- const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
274
- const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
275
- if (debug || !quiet) {
276
- _log("Loading env from encrypted .env.vault");
277
- }
278
- const parsed = DotenvModule._parseVault(options);
279
- let processEnv = process.env;
280
- if (options && options.processEnv != null) {
281
- processEnv = options.processEnv;
282
- }
283
- DotenvModule.populate(processEnv, parsed, options);
284
- return { parsed };
285
- }
286
- function configDotenv(options) {
287
- const dotenvPath = path7.resolve(process.cwd(), ".env");
288
- let encoding = "utf8";
289
- let processEnv = process.env;
290
- if (options && options.processEnv != null) {
291
- processEnv = options.processEnv;
292
- }
293
- let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
294
- let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
295
- if (options && options.encoding) {
296
- encoding = options.encoding;
297
- } else {
298
- if (debug) {
299
- _debug("No encoding is specified. UTF-8 is used by default");
300
- }
301
- }
302
- let optionPaths = [dotenvPath];
303
- if (options && options.path) {
304
- if (!Array.isArray(options.path)) {
305
- optionPaths = [_resolveHome(options.path)];
306
- } else {
307
- optionPaths = [];
308
- for (const filepath of options.path) {
309
- optionPaths.push(_resolveHome(filepath));
310
- }
311
- }
312
- }
313
- let lastError;
314
- const parsedAll = {};
315
- for (const path8 of optionPaths) {
316
- try {
317
- const parsed = DotenvModule.parse(fs8.readFileSync(path8, { encoding }));
318
- DotenvModule.populate(parsedAll, parsed, options);
319
- } catch (e) {
320
- if (debug) {
321
- _debug(`Failed to load ${path8} ${e.message}`);
322
- }
323
- lastError = e;
324
- }
325
- }
326
- const populated = DotenvModule.populate(processEnv, parsedAll, options);
327
- debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
328
- quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
329
- if (debug || !quiet) {
330
- const keysCount = Object.keys(populated).length;
331
- const shortPaths = [];
332
- for (const filePath of optionPaths) {
333
- try {
334
- const relative = path7.relative(process.cwd(), filePath);
335
- shortPaths.push(relative);
336
- } catch (e) {
337
- if (debug) {
338
- _debug(`Failed to load ${filePath} ${e.message}`);
339
- }
340
- lastError = e;
341
- }
342
- }
343
- _log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
344
- }
345
- if (lastError) {
346
- return { parsed: parsedAll, error: lastError };
347
- } else {
348
- return { parsed: parsedAll };
349
- }
350
- }
351
- function config(options) {
352
- if (_dotenvKey(options).length === 0) {
353
- return DotenvModule.configDotenv(options);
354
- }
355
- const vaultPath = _vaultPath(options);
356
- if (!vaultPath) {
357
- _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
358
- return DotenvModule.configDotenv(options);
359
- }
360
- return DotenvModule._configVault(options);
361
- }
362
- function decrypt(encrypted, keyStr) {
363
- const key = Buffer.from(keyStr.slice(-64), "hex");
364
- let ciphertext = Buffer.from(encrypted, "base64");
365
- const nonce = ciphertext.subarray(0, 12);
366
- const authTag = ciphertext.subarray(-16);
367
- ciphertext = ciphertext.subarray(12, -16);
368
- try {
369
- const aesgcm = crypto2.createDecipheriv("aes-256-gcm", key, nonce);
370
- aesgcm.setAuthTag(authTag);
371
- return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
372
- } catch (error) {
373
- const isRange = error instanceof RangeError;
374
- const invalidKeyLength = error.message === "Invalid key length";
375
- const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
376
- if (isRange || invalidKeyLength) {
377
- const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
378
- err.code = "INVALID_DOTENV_KEY";
379
- throw err;
380
- } else if (decryptionFailed) {
381
- const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
382
- err.code = "DECRYPTION_FAILED";
383
- throw err;
384
- } else {
385
- throw error;
386
- }
387
- }
388
- }
389
- function populate(processEnv, parsed, options = {}) {
390
- const debug = Boolean(options && options.debug);
391
- const override = Boolean(options && options.override);
392
- const populated = {};
393
- if (typeof parsed !== "object") {
394
- const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
395
- err.code = "OBJECT_REQUIRED";
396
- throw err;
397
- }
398
- for (const key of Object.keys(parsed)) {
399
- if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
400
- if (override === true) {
401
- processEnv[key] = parsed[key];
402
- populated[key] = parsed[key];
403
- }
404
- if (debug) {
405
- if (override === true) {
406
- _debug(`"${key}" is already defined and WAS overwritten`);
407
- } else {
408
- _debug(`"${key}" is already defined and was NOT overwritten`);
409
- }
410
- }
411
- } else {
412
- processEnv[key] = parsed[key];
413
- populated[key] = parsed[key];
414
- }
415
- }
416
- return populated;
417
- }
418
- var DotenvModule = {
419
- configDotenv,
420
- _configVault,
421
- _parseVault,
422
- config,
423
- decrypt,
424
- parse,
425
- populate
426
- };
427
- module.exports.configDotenv = DotenvModule.configDotenv;
428
- module.exports._configVault = DotenvModule._configVault;
429
- module.exports._parseVault = DotenvModule._parseVault;
430
- module.exports.config = DotenvModule.config;
431
- module.exports.decrypt = DotenvModule.decrypt;
432
- module.exports.parse = DotenvModule.parse;
433
- module.exports.populate = DotenvModule.populate;
434
- module.exports = DotenvModule;
435
- }
436
- });
437
10
 
438
11
  // src/userResponse/utils.ts
439
12
  var utils_exports = {};
@@ -847,7 +420,7 @@ var UserPromptSuggestionsMessageSchema = z3.object({
847
420
  payload: UserPromptSuggestionsPayloadSchema
848
421
  });
849
422
  var ComponentPropsSchema = z3.object({
850
- query: z3.string().optional(),
423
+ query: z3.string().or(z3.object({})).optional(),
851
424
  title: z3.string().optional(),
852
425
  description: z3.string().optional(),
853
426
  config: z3.record(z3.unknown()).optional(),
@@ -1399,6 +972,7 @@ var Thread = class {
1399
972
  let assistantResponse = "";
1400
973
  const hasComponent = metadata && Object.keys(metadata).length > 0 && metadata.type;
1401
974
  const hasTextResponse = textResponse && textResponse.trim().length > 0;
975
+ const responseParts = [];
1402
976
  if (hasComponent) {
1403
977
  const parts = [];
1404
978
  if (metadata.type) {
@@ -1407,21 +981,19 @@ var Thread = class {
1407
981
  if (metadata.name) {
1408
982
  parts.push(`Name: ${metadata.name}`);
1409
983
  }
1410
- if (metadata.props?.title) {
1411
- parts.push(`Title: "${metadata.props.title}"`);
1412
- }
1413
- if (metadata.props?.query) {
1414
- const query = metadata.props.query;
1415
- const truncatedQuery = query.length > 200 ? query.substring(0, 200) + "..." : query;
1416
- parts.push(`Query: ${truncatedQuery}`);
984
+ if (metadata.description) {
985
+ parts.push(`Description: ${metadata.description}`);
1417
986
  }
1418
- if (metadata.props?.config?.components && Array.isArray(metadata.props.config.components)) {
1419
- const componentTypes = metadata.props.config.components.map((c) => c.type).join(", ");
1420
- parts.push(`Multi-component with: ${componentTypes}`);
987
+ if (metadata.props) {
988
+ parts.push(`Props: ${JSON.stringify(metadata.props)}`);
1421
989
  }
1422
- assistantResponse = parts.join(", ");
1423
- } else if (hasTextResponse) {
1424
- 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");
1425
997
  } else {
1426
998
  assistantResponse = "No response generated";
1427
999
  }
@@ -2046,7 +1618,7 @@ function sendDataResponse3(id, res, sendMessage, clientId) {
2046
1618
  }
2047
1619
 
2048
1620
  // src/userResponse/groq.ts
2049
- var import_dotenv = __toESM(require_main());
1621
+ import dotenv from "dotenv";
2050
1622
 
2051
1623
  // src/userResponse/base-llm.ts
2052
1624
  init_utils();
@@ -2773,18 +2345,16 @@ Your job is to:
2773
2345
  1. **Parse the component suggestions** from the text response (format: 1:component_type : reasoning)
2774
2346
  2. **Match each suggestion with an actual component** from the available list
2775
2347
  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
2348
+ 4. **Generate title and description** for the dashboard container
2777
2349
  5. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis
2778
2350
 
2779
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.
2780
2352
 
2781
- **APPROACH**: First match all the components suggested in the text response, THEN find the layout that best fits those components.
2782
-
2783
2353
  ## Available Components
2784
2354
 
2785
2355
  {{AVAILABLE_COMPONENTS}}
2786
2356
 
2787
- ## Component Matching Rules (STEP 1)
2357
+ ## Component Matching Rules
2788
2358
  For each component suggestion (c1, c2, c3, etc.) from the text response:
2789
2359
 
2790
2360
  1. **Match by type**: Find components whose \`type\` matches the suggested component type
@@ -2793,23 +2363,10 @@ For each component suggestion (c1, c2, c3, etc.) from the text response:
2793
2363
  - Best fit for the data being visualized
2794
2364
  3. **Fallback**: If no exact type match, find the closest alternative
2795
2365
 
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.
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
2813
2370
 
2814
2371
  ## Props Generation Rules
2815
2372
 
@@ -2923,8 +2480,8 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
2923
2480
 
2924
2481
  \`\`\`json
2925
2482
  {
2926
- "selectedLayoutId": "id_of_the_selected_layout_component",
2927
- "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)",
2928
2485
  "matchedComponents": [
2929
2486
  {
2930
2487
  "componentId": "id_from_available_list",
@@ -2954,17 +2511,14 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
2954
2511
  \`\`\`
2955
2512
 
2956
2513
  **CRITICAL:**
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")
2959
- - \`layoutReasoning\` MUST explain:
2960
- - Why you chose this specific layout component
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
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
2965
2519
  - \`actions\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis
2966
2520
  - Return ONLY valid JSON (no markdown code blocks, no text before/after)
2967
- - Generate complete props for each component
2521
+ - Generate complete props for each component including query, title, description, and config
2968
2522
 
2969
2523
 
2970
2524
  `,
@@ -4060,12 +3614,13 @@ var BaseLLM = class {
4060
3614
  /**
4061
3615
  * Match components from text response suggestions and generate follow-up questions
4062
3616
  * Takes a text response with component suggestions (c1:type format) and matches with available components
4063
- * 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
4064
3619
  * @param textResponse - The text response containing component suggestions
4065
3620
  * @param components - List of available components
4066
3621
  * @param apiKey - Optional API key
4067
3622
  * @param logCollector - Optional log collector
4068
- * @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
4069
3624
  */
4070
3625
  async matchComponentsFromTextResponse(textResponse, components, apiKey, logCollector) {
4071
3626
  try {
@@ -4108,24 +3663,17 @@ var BaseLLM = class {
4108
3663
  );
4109
3664
  logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
4110
3665
  const matchedComponents = result.matchedComponents || [];
4111
- const selectedLayoutId = result.selectedLayoutId || "multi-component-container";
4112
- const layoutReasoning = result.layoutReasoning || "No layout reasoning provided";
3666
+ const layoutTitle = result.layoutTitle || "Dashboard";
3667
+ const layoutDescription = result.layoutDescription || "Multi-component dashboard";
4113
3668
  const rawActions = result.actions || [];
4114
3669
  const actions = convertQuestionsToActions(rawActions);
4115
- let selectedLayoutComponent = null;
4116
- if (selectedLayoutId) {
4117
- selectedLayoutComponent = components.find((c) => c.id === selectedLayoutId) || null;
4118
- if (!selectedLayoutComponent) {
4119
- logger.warn(`[${this.getProviderName()}] Layout component ${selectedLayoutId} not found in available components`);
4120
- }
4121
- }
4122
3670
  logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
4123
- logger.info(`[${this.getProviderName()}] Selected layout: (ID: ${selectedLayoutId})`);
4124
- logger.info(`[${this.getProviderName()}] Layout reasoning: ${layoutReasoning}`);
3671
+ logger.info(`[${this.getProviderName()}] Layout title: "${layoutTitle}"`);
3672
+ logger.info(`[${this.getProviderName()}] Layout description: "${layoutDescription}"`);
4125
3673
  logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
4126
3674
  if (matchedComponents.length > 0) {
4127
- logCollector?.info(`Matched ${matchedComponents.length} components for visualization `);
4128
- logCollector?.info(`Layout reasoning: ${layoutReasoning}`);
3675
+ logCollector?.info(`Matched ${matchedComponents.length} components for visualization`);
3676
+ logCollector?.info(`Dashboard: "${layoutTitle}"`);
4129
3677
  matchedComponents.forEach((comp, idx) => {
4130
3678
  logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
4131
3679
  if (comp.props?.query) {
@@ -4159,9 +3707,8 @@ var BaseLLM = class {
4159
3707
  }).filter(Boolean);
4160
3708
  return {
4161
3709
  components: finalComponents,
4162
- selectedLayoutId,
4163
- selectedLayoutComponent,
4164
- layoutReasoning,
3710
+ layoutTitle,
3711
+ layoutDescription,
4165
3712
  actions
4166
3713
  };
4167
3714
  } catch (error) {
@@ -4170,9 +3717,8 @@ var BaseLLM = class {
4170
3717
  logCollector?.error(`Failed to match components: ${errorMsg}`);
4171
3718
  return {
4172
3719
  components: [],
4173
- selectedLayoutId: "",
4174
- selectedLayoutComponent: null,
4175
- layoutReasoning: "Failed to match components due to parsing error",
3720
+ layoutTitle: "Dashboard",
3721
+ layoutDescription: "Failed to generate dashboard",
4176
3722
  actions: []
4177
3723
  };
4178
3724
  }
@@ -4416,9 +3962,12 @@ ${errorMsg}
4416
3962
  textLength: textResponse.length
4417
3963
  }
4418
3964
  );
3965
+ if (wrappedStreamCallback && components && components.length > 0) {
3966
+ wrappedStreamCallback("__TEXT_COMPLETE__COMPONENT_GENERATION_START__");
3967
+ }
4419
3968
  let matchedComponents = [];
4420
- let selectedLayoutComponent = null;
4421
- let layoutReasoning = "No layout selected";
3969
+ let layoutTitle = "Dashboard";
3970
+ let layoutDescription = "Multi-component dashboard";
4422
3971
  let actions = [];
4423
3972
  if (components && components.length > 0) {
4424
3973
  logger.info(`[${this.getProviderName()}] Matching components from text response...`);
@@ -4429,46 +3978,30 @@ ${errorMsg}
4429
3978
  logCollector
4430
3979
  );
4431
3980
  matchedComponents = matchResult.components;
4432
- selectedLayoutComponent = matchResult.selectedLayoutComponent;
4433
- layoutReasoning = matchResult.layoutReasoning;
3981
+ layoutTitle = matchResult.layoutTitle;
3982
+ layoutDescription = matchResult.layoutDescription;
4434
3983
  actions = matchResult.actions;
4435
3984
  }
4436
3985
  let container_componet = null;
4437
3986
  if (matchedComponents.length > 0) {
4438
- if (selectedLayoutComponent) {
4439
- container_componet = {
4440
- ...selectedLayoutComponent,
4441
- id: `${selectedLayoutComponent.id}_${Date.now()}`,
4442
- // Make ID unique for each instance
4443
- props: {
4444
- ...selectedLayoutComponent.props,
4445
- config: {
4446
- ...selectedLayoutComponent.props?.config || {},
4447
- components: matchedComponents
4448
- },
4449
- actions
4450
- }
4451
- };
4452
- logger.info(`[${this.getProviderName()}] Created ${selectedLayoutComponent.name} (${selectedLayoutComponent.type}) container with ${matchedComponents.length} components and ${actions.length} actions`);
4453
- logCollector?.info(`Created ${selectedLayoutComponent.name} with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
4454
- } else {
4455
- container_componet = {
4456
- id: `multi_container_${Date.now()}`,
4457
- name: "MultiComponentContainer",
4458
- type: "Container",
4459
- description: layoutReasoning,
4460
- category: "dynamic",
4461
- keywords: ["dashboard", "layout", "container"],
4462
- props: {
4463
- config: {
4464
- components: matchedComponents
4465
- },
4466
- actions
4467
- }
4468
- };
4469
- logger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions`);
4470
- logCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
4471
- }
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`);
4472
4005
  }
4473
4006
  return {
4474
4007
  success: true,
@@ -4476,7 +4009,6 @@ ${errorMsg}
4476
4009
  text: textResponse,
4477
4010
  matchedComponents,
4478
4011
  component: container_componet,
4479
- layoutReasoning,
4480
4012
  actions,
4481
4013
  method: `${this.getProviderName()}-text-response`
4482
4014
  },
@@ -4790,7 +4322,7 @@ ${errorMsg}
4790
4322
  };
4791
4323
 
4792
4324
  // src/userResponse/groq.ts
4793
- import_dotenv.default.config();
4325
+ dotenv.config();
4794
4326
  var GroqLLM = class extends BaseLLM {
4795
4327
  constructor(config) {
4796
4328
  super(config);
@@ -4808,8 +4340,8 @@ var GroqLLM = class extends BaseLLM {
4808
4340
  var groqLLM = new GroqLLM();
4809
4341
 
4810
4342
  // src/userResponse/anthropic.ts
4811
- var import_dotenv2 = __toESM(require_main());
4812
- import_dotenv2.default.config();
4343
+ import dotenv2 from "dotenv";
4344
+ dotenv2.config();
4813
4345
  var AnthropicLLM = class extends BaseLLM {
4814
4346
  constructor(config) {
4815
4347
  super(config);
@@ -4827,8 +4359,8 @@ var AnthropicLLM = class extends BaseLLM {
4827
4359
  var anthropicLLM = new AnthropicLLM();
4828
4360
 
4829
4361
  // src/userResponse/index.ts
4830
- var import_dotenv3 = __toESM(require_main());
4831
- import_dotenv3.default.config();
4362
+ import dotenv3 from "dotenv";
4363
+ dotenv3.config();
4832
4364
  function getLLMProviders() {
4833
4365
  const envProviders = process.env.LLM_PROVIDERS;
4834
4366
  const DEFAULT_PROVIDERS = ["anthropic", "groq"];
@@ -5142,7 +4674,7 @@ var CONTEXT_CONFIG = {
5142
4674
  * Set to 0 to disable conversation history
5143
4675
  * Higher values provide more context but may increase token usage
5144
4676
  */
5145
- MAX_CONVERSATION_CONTEXT_BLOCKS: 2
4677
+ MAX_CONVERSATION_CONTEXT_BLOCKS: 3
5146
4678
  };
5147
4679
 
5148
4680
  // src/handlers/user-prompt-request.ts