@superatomai/sdk-node 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -565,10 +565,14 @@ var ReportsRequestMessageSchema = import_zod3.z.object({
565
565
  var UIBlockSchema = import_zod3.z.object({
566
566
  id: import_zod3.z.string().optional(),
567
567
  userQuestion: import_zod3.z.string().optional(),
568
+ user_prompt: import_zod3.z.string().optional(),
569
+ // DB field name
568
570
  text: import_zod3.z.string().optional(),
569
571
  textResponse: import_zod3.z.string().optional(),
572
+ analysis: import_zod3.z.string().optional(),
573
+ // DB field name for textResponse
570
574
  component: ComponentSchema.optional(),
571
- // Legacy field
575
+ // DB field name / Legacy field
572
576
  generatedComponentMetadata: ComponentSchema.optional(),
573
577
  // Actual field used by UIBlock class
574
578
  componentData: import_zod3.z.record(import_zod3.z.any()).optional(),
@@ -589,9 +593,11 @@ var BookmarkDataSchema = import_zod3.z.object({
589
593
  updated_at: import_zod3.z.string().optional()
590
594
  });
591
595
  var BookmarksRequestPayloadSchema = import_zod3.z.object({
592
- operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne"]),
596
+ operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne", "getByUser", "getByThread"]),
593
597
  data: import_zod3.z.object({
594
598
  id: import_zod3.z.number().optional(),
599
+ userId: import_zod3.z.number().optional(),
600
+ threadId: import_zod3.z.string().optional(),
595
601
  uiblock: import_zod3.z.any().optional()
596
602
  }).optional()
597
603
  });
@@ -1419,7 +1425,7 @@ async function cleanupUserStorage() {
1419
1425
  }
1420
1426
 
1421
1427
  // src/auth/validator.ts
1422
- function validateUser(credentials) {
1428
+ async function validateUser(credentials, collections) {
1423
1429
  const { username, email, password } = credentials;
1424
1430
  const identifier = username || email;
1425
1431
  logger.debug("[validateUser] Starting user validation");
@@ -1431,7 +1437,39 @@ function validateUser(credentials) {
1431
1437
  error: "Username or email and password are required"
1432
1438
  };
1433
1439
  }
1434
- logger.debug(`[validateUser] Looking up user by identifier: ${identifier}`);
1440
+ if (collections && collections["users"] && collections["users"]["authenticate"]) {
1441
+ logger.debug(`[validateUser] Attempting database authentication for: ${identifier}`);
1442
+ try {
1443
+ const dbResult = await collections["users"]["authenticate"]({
1444
+ identifier,
1445
+ password
1446
+ });
1447
+ logger.info("[validateUser] Database authentication attempt completed", dbResult);
1448
+ if (dbResult && dbResult.success && dbResult.data) {
1449
+ logger.info(`[validateUser] \u2713 User authenticated via database: ${dbResult.data.username}`);
1450
+ return {
1451
+ success: true,
1452
+ data: dbResult.data.username,
1453
+ username: dbResult.data.username,
1454
+ userId: dbResult.data.id
1455
+ };
1456
+ } else {
1457
+ logger.debug(`[validateUser] Database auth failed for ${identifier}: ${dbResult?.error || "Invalid credentials"}`);
1458
+ if (dbResult && dbResult.error === "Invalid credentials") {
1459
+ return {
1460
+ success: false,
1461
+ error: "Invalid credentials"
1462
+ };
1463
+ }
1464
+ }
1465
+ } catch (error) {
1466
+ const errorMsg = error instanceof Error ? error.message : String(error);
1467
+ logger.debug(`[validateUser] Database lookup error: ${errorMsg}, falling back to file storage`);
1468
+ }
1469
+ } else {
1470
+ logger.debug("[validateUser] No users collection available, using file storage only");
1471
+ }
1472
+ logger.info(`[validateUser] Attempting file-based validation for: ${identifier}`);
1435
1473
  const user = findUserByUsernameOrEmail(identifier);
1436
1474
  if (!user) {
1437
1475
  logger.warn(`[validateUser] Validation failed: User not found - ${identifier}`);
@@ -1440,7 +1478,7 @@ function validateUser(credentials) {
1440
1478
  error: "Invalid username or email"
1441
1479
  };
1442
1480
  }
1443
- logger.debug(`[validateUser] User found: ${user.username}, verifying password`);
1481
+ logger.debug(`[validateUser] User found in file storage: ${user.username}, verifying password`);
1444
1482
  const hashedPassword = hashPassword(user.password);
1445
1483
  if (hashedPassword !== password) {
1446
1484
  logger.warn(`[validateUser] Validation failed: Invalid password for user - ${user.username}`);
@@ -1450,19 +1488,18 @@ function validateUser(credentials) {
1450
1488
  error: "Invalid password"
1451
1489
  };
1452
1490
  }
1453
- logger.info(`[validateUser] \u2713 User validated successfully: ${user.username}`);
1454
- logger.debug(`[validateUser] Returning user data for: ${user.username}`);
1491
+ logger.info(`[validateUser] \u2713 User validated via file storage: ${user.username}`);
1455
1492
  return {
1456
1493
  success: true,
1457
1494
  data: user.username,
1458
1495
  username: user.username
1459
1496
  };
1460
1497
  }
1461
- function authenticateAndStoreWsId(credentials, wsId) {
1498
+ async function authenticateAndStoreWsId(credentials, wsId, collections) {
1462
1499
  const identifier = credentials.username || credentials.email;
1463
1500
  logger.debug("[authenticateAndStoreWsId] Starting authentication and WebSocket ID storage");
1464
1501
  logger.debug("[authenticateAndStoreWsId] Validating user credentials");
1465
- const validationResult = validateUser(credentials);
1502
+ const validationResult = await validateUser(credentials, collections);
1466
1503
  if (!validationResult.success) {
1467
1504
  logger.warn(`[authenticateAndStoreWsId] User validation failed for: ${identifier}`);
1468
1505
  return validationResult;
@@ -1474,7 +1511,7 @@ function authenticateAndStoreWsId(credentials, wsId) {
1474
1511
  logger.debug(`[authenticateAndStoreWsId] WebSocket ID ${wsId} associated with user ${username}`);
1475
1512
  return validationResult;
1476
1513
  }
1477
- function verifyAuthToken(authToken) {
1514
+ async function verifyAuthToken(authToken, collections) {
1478
1515
  try {
1479
1516
  logger.debug("[verifyAuthToken] Starting token verification");
1480
1517
  logger.debug("[verifyAuthToken] Decoding base64 token");
@@ -1484,7 +1521,7 @@ function verifyAuthToken(authToken) {
1484
1521
  logger.debug("[verifyAuthToken] Token decoded and parsed successfully");
1485
1522
  logger.debug(`[verifyAuthToken] Token contains username: ${credentials.username ? "\u2713" : "\u2717"}`);
1486
1523
  logger.debug("[verifyAuthToken] Validating credentials from token");
1487
- const result = validateUser(credentials);
1524
+ const result = await validateUser(credentials, collections);
1488
1525
  if (result.success) {
1489
1526
  logger.info(`[verifyAuthToken] \u2713 Token verified successfully for user: ${credentials.username || "unknown"}`);
1490
1527
  } else {
@@ -1503,7 +1540,7 @@ function verifyAuthToken(authToken) {
1503
1540
  }
1504
1541
 
1505
1542
  // src/handlers/auth-login-requests.ts
1506
- async function handleAuthLoginRequest(data, sendMessage) {
1543
+ async function handleAuthLoginRequest(data, collections, sendMessage) {
1507
1544
  try {
1508
1545
  logger.debug("[AUTH_LOGIN_REQ] Parsing incoming auth login request");
1509
1546
  const authRequest = AuthLoginRequestMessageSchema.parse(data);
@@ -1562,12 +1599,12 @@ async function handleAuthLoginRequest(data, sendMessage) {
1562
1599
  }, sendMessage, wsId);
1563
1600
  return;
1564
1601
  }
1565
- logger.info(`[AUTH_LOGIN_REQ ${id}] Credentials validated, authenticating user: ${identifier}`);
1566
- logger.debug(`[AUTH_LOGIN_REQ ${id}] WebSocket ID: ${wsId}`);
1602
+ logger.info(`[AUTH_LOGIN_REQ ${id}] Credentials validated, authenticating user: ${identifier} username: ${username} email: ${email} password: ${password}`);
1567
1603
  logger.debug(`[AUTH_LOGIN_REQ ${id}] Calling authenticateAndStoreWsId for user: ${identifier}`);
1568
- const authResult = authenticateAndStoreWsId(
1604
+ const authResult = await authenticateAndStoreWsId(
1569
1605
  { username, email, password },
1570
- wsId
1606
+ wsId,
1607
+ collections
1571
1608
  );
1572
1609
  logger.info(`[AUTH_LOGIN_REQ ${id}] Authentication result for ${identifier}: ${authResult.success ? "success" : "failed"}`);
1573
1610
  if (!authResult.success) {
@@ -1619,7 +1656,7 @@ function sendDataResponse2(id, res, sendMessage, clientId) {
1619
1656
  }
1620
1657
 
1621
1658
  // src/handlers/auth-verify-request.ts
1622
- async function handleAuthVerifyRequest(data, sendMessage) {
1659
+ async function handleAuthVerifyRequest(data, collections, sendMessage) {
1623
1660
  try {
1624
1661
  logger.debug("[AUTH_VERIFY_REQ] Parsing incoming auth verify request");
1625
1662
  const authRequest = AuthVerifyRequestMessageSchema.parse(data);
@@ -1649,7 +1686,7 @@ async function handleAuthVerifyRequest(data, sendMessage) {
1649
1686
  logger.debug(`[AUTH_VERIFY_REQ ${id}] WebSocket ID: ${wsId}`);
1650
1687
  logger.debug(`[AUTH_VERIFY_REQ ${id}] Calling verifyAuthToken`);
1651
1688
  const startTime = Date.now();
1652
- const authResult = verifyAuthToken(token);
1689
+ const authResult = await verifyAuthToken(token, collections);
1653
1690
  const verificationTime = Date.now() - startTime;
1654
1691
  logger.info(`[AUTH_VERIFY_REQ ${id}] Token verification completed in ${verificationTime}ms - ${authResult.success ? "valid" : "invalid"}`);
1655
1692
  if (!authResult.success) {
@@ -3699,13 +3736,13 @@ var BaseLLM = class {
3699
3736
  */
3700
3737
  async adaptUIBlockParameters(currentUserPrompt, originalUserPrompt, matchedUIBlock, apiKey, logCollector) {
3701
3738
  try {
3702
- if (!matchedUIBlock || !matchedUIBlock.generatedComponentMetadata) {
3739
+ const component = matchedUIBlock?.generatedComponentMetadata || matchedUIBlock?.component;
3740
+ if (!matchedUIBlock || !component) {
3703
3741
  return {
3704
3742
  success: false,
3705
3743
  explanation: "No component found in matched UI block"
3706
3744
  };
3707
3745
  }
3708
- const component = matchedUIBlock.generatedComponentMetadata;
3709
3746
  const schemaDoc = schema.generateSchemaDocumentation();
3710
3747
  const prompts = await promptLoader.loadPrompts("adapt-ui-block-params", {
3711
3748
  ORIGINAL_USER_PROMPT: originalUserPrompt,
@@ -3781,8 +3818,9 @@ var BaseLLM = class {
3781
3818
  * @param collections - Collection registry for executing database queries via database.execute
3782
3819
  * @param components - Optional list of available components for matching suggestions
3783
3820
  * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called
3821
+ * @param category - Question category ('data_analysis' | 'data_modification' | 'general'). For data_modification, answer component streaming is skipped. For general, component generation is skipped entirely.
3784
3822
  */
3785
- async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools) {
3823
+ async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools, category) {
3786
3824
  const errors = [];
3787
3825
  logger.debug(`[${this.getProviderName()}] Starting text response generation`);
3788
3826
  logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
@@ -4176,16 +4214,19 @@ ${errorMsg}
4176
4214
  textLength: textResponse.length
4177
4215
  }
4178
4216
  );
4179
- if (wrappedStreamCallback && components && components.length > 0) {
4217
+ if (wrappedStreamCallback && components && components.length > 0 && category !== "general") {
4180
4218
  wrappedStreamCallback("__TEXT_COMPLETE__COMPONENT_GENERATION_START__");
4181
4219
  }
4182
4220
  let matchedComponents = [];
4183
4221
  let layoutTitle = "Dashboard";
4184
4222
  let layoutDescription = "Multi-component dashboard";
4185
4223
  let actions = [];
4186
- if (components && components.length > 0) {
4224
+ if (category === "general") {
4225
+ logger.info(`[${this.getProviderName()}] Skipping component generation for general/conversational question`);
4226
+ logCollector?.info("Skipping component generation for general question");
4227
+ } else if (components && components.length > 0) {
4187
4228
  logger.info(`[${this.getProviderName()}] Matching components from text response...`);
4188
- const componentStreamCallback = wrappedStreamCallback ? (component) => {
4229
+ const componentStreamCallback = wrappedStreamCallback && category !== "data_modification" ? (component) => {
4189
4230
  const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
4190
4231
  wrappedStreamCallback(answerMarker);
4191
4232
  logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
@@ -4284,52 +4325,78 @@ ${errorMsg}
4284
4325
  logCollector?.info(
4285
4326
  `\u2713 Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`
4286
4327
  );
4287
- if (conversationMatch.similarity >= 0.99) {
4288
- const elapsedTime2 = Date.now() - startTime;
4289
- logger.info(`[${this.getProviderName()}] \u2713 100% match - returning UI block directly without adaptation`);
4290
- logCollector?.info(`\u2713 Exact match (${(conversationMatch.similarity * 100).toFixed(2)}%) - returning cached result`);
4291
- logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4292
- const component = conversationMatch.uiBlock?.generatedComponentMetadata || conversationMatch.uiBlock?.component;
4293
- return {
4294
- success: true,
4295
- data: {
4296
- component,
4297
- reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
4298
- method: `${this.getProviderName()}-semantic-match-exact`,
4299
- semanticSimilarity: conversationMatch.similarity
4300
- },
4301
- errors: []
4302
- };
4303
- }
4304
- logCollector?.info(`Adapting parameters for similar question...`);
4305
- const originalPrompt = conversationMatch.metadata?.userPrompt || "Previous question";
4306
- const adaptResult = await this.adaptUIBlockParameters(
4307
- userPrompt,
4308
- originalPrompt,
4309
- conversationMatch.uiBlock,
4310
- apiKey,
4311
- logCollector
4312
- );
4313
- if (adaptResult.success && adaptResult.adaptedComponent) {
4314
- const elapsedTime2 = Date.now() - startTime;
4315
- logger.info(`[${this.getProviderName()}] \u2713 Successfully adapted UI block parameters`);
4316
- logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4317
- logCollector?.info(`\u2713 UI block adapted successfully`);
4318
- logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4319
- return {
4320
- success: true,
4321
- data: {
4322
- component: adaptResult.adaptedComponent,
4323
- reasoning: `Adapted from previous conversation: ${originalPrompt}`,
4324
- method: `${this.getProviderName()}-semantic-match`,
4325
- semanticSimilarity: conversationMatch.similarity,
4326
- parametersChanged: adaptResult.parametersChanged
4327
- },
4328
- errors: []
4329
- };
4328
+ const component = conversationMatch.uiBlock?.component || conversationMatch.uiBlock?.generatedComponentMetadata;
4329
+ const cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || "";
4330
+ if (!component) {
4331
+ if (conversationMatch.similarity >= 0.99) {
4332
+ const elapsedTime2 = Date.now() - startTime;
4333
+ logger.info(`[${this.getProviderName()}] \u2713 Exact match for general question - returning cached text response`);
4334
+ logCollector?.info(`\u2713 Exact match for general question - returning cached response`);
4335
+ logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4336
+ return {
4337
+ success: true,
4338
+ data: {
4339
+ text: cachedTextResponse,
4340
+ component: null,
4341
+ matchedComponents: [],
4342
+ actions: conversationMatch.uiBlock?.actions || [],
4343
+ reasoning: `Exact match from previous general conversation`,
4344
+ method: `${this.getProviderName()}-semantic-match-general`,
4345
+ semanticSimilarity: conversationMatch.similarity
4346
+ },
4347
+ errors: []
4348
+ };
4349
+ } else {
4350
+ logger.info(`[${this.getProviderName()}] Similar match but no component (general question) - processing fresh`);
4351
+ logCollector?.info("Similar match found but was a general conversation - processing as new question");
4352
+ }
4330
4353
  } else {
4331
- logger.info(`[${this.getProviderName()}] Could not adapt matched conversation, continuing to category classification`);
4332
- logCollector?.warn(`Could not adapt matched conversation: ${adaptResult.explanation}`);
4354
+ if (conversationMatch.similarity >= 0.99) {
4355
+ const elapsedTime2 = Date.now() - startTime;
4356
+ logger.info(`[${this.getProviderName()}] \u2713 100% match - returning UI block directly without adaptation`);
4357
+ logCollector?.info(`\u2713 Exact match (${(conversationMatch.similarity * 100).toFixed(2)}%) - returning cached result`);
4358
+ logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4359
+ return {
4360
+ success: true,
4361
+ data: {
4362
+ component,
4363
+ reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
4364
+ method: `${this.getProviderName()}-semantic-match-exact`,
4365
+ semanticSimilarity: conversationMatch.similarity
4366
+ },
4367
+ errors: []
4368
+ };
4369
+ }
4370
+ logCollector?.info(`Adapting parameters for similar question...`);
4371
+ const originalPrompt = conversationMatch.metadata?.userPrompt || "Previous question";
4372
+ const adaptResult = await this.adaptUIBlockParameters(
4373
+ userPrompt,
4374
+ originalPrompt,
4375
+ conversationMatch.uiBlock,
4376
+ apiKey,
4377
+ logCollector
4378
+ );
4379
+ if (adaptResult.success && adaptResult.adaptedComponent) {
4380
+ const elapsedTime2 = Date.now() - startTime;
4381
+ logger.info(`[${this.getProviderName()}] \u2713 Successfully adapted UI block parameters`);
4382
+ logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4383
+ logCollector?.info(`\u2713 UI block adapted successfully`);
4384
+ logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4385
+ return {
4386
+ success: true,
4387
+ data: {
4388
+ component: adaptResult.adaptedComponent,
4389
+ reasoning: `Adapted from previous conversation: ${originalPrompt}`,
4390
+ method: `${this.getProviderName()}-semantic-match`,
4391
+ semanticSimilarity: conversationMatch.similarity,
4392
+ parametersChanged: adaptResult.parametersChanged
4393
+ },
4394
+ errors: []
4395
+ };
4396
+ } else {
4397
+ logger.info(`[${this.getProviderName()}] Could not adapt matched conversation, continuing to category classification`);
4398
+ logCollector?.warn(`Could not adapt matched conversation: ${adaptResult.explanation}`);
4399
+ }
4333
4400
  }
4334
4401
  } else {
4335
4402
  logger.info(`[${this.getProviderName()}] No matching previous conversations found, proceeding to category classification`);
@@ -4371,7 +4438,10 @@ ${errorMsg}
4371
4438
  })()
4372
4439
  })) || [];
4373
4440
  }
4374
- if (categoryClassification.category === "data_analysis") {
4441
+ if (categoryClassification.category === "general") {
4442
+ logger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);
4443
+ logCollector?.info("Routing to general conversation...");
4444
+ } else if (categoryClassification.category === "data_analysis") {
4375
4445
  logger.info(`[${this.getProviderName()}] Routing to data analysis (SELECT operations)`);
4376
4446
  logCollector?.info("Routing to data analysis...");
4377
4447
  } else if (categoryClassification.category === "data_modification") {
@@ -4386,7 +4456,8 @@ ${errorMsg}
4386
4456
  streamCallback,
4387
4457
  collections,
4388
4458
  components,
4389
- toolsToUse
4459
+ toolsToUse,
4460
+ categoryClassification.category
4390
4461
  );
4391
4462
  const elapsedTime = Date.now() - startTime;
4392
4463
  logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1e3).toFixed(2)}s)`);
@@ -4810,6 +4881,15 @@ var UILogCollector = class {
4810
4881
  };
4811
4882
 
4812
4883
  // src/utils/conversation-saver.ts
4884
+ function transformUIBlockForDB(uiblock, userPrompt, uiBlockId) {
4885
+ const component = uiblock?.generatedComponentMetadata && Object.keys(uiblock.generatedComponentMetadata).length > 0 ? uiblock.generatedComponentMetadata : null;
4886
+ return {
4887
+ id: uiBlockId || uiblock?.id || "",
4888
+ component,
4889
+ analysis: uiblock?.textResponse || null,
4890
+ user_prompt: userPrompt || uiblock?.userQuestion || ""
4891
+ };
4892
+ }
4813
4893
  async function saveConversation(params) {
4814
4894
  const { userId, userPrompt, uiblock, uiBlockId, threadId, collections } = params;
4815
4895
  if (!userId) {
@@ -4864,10 +4944,12 @@ async function saveConversation(params) {
4864
4944
  error: `Invalid userId: ${userId} (not a valid number)`
4865
4945
  };
4866
4946
  }
4947
+ const dbUIBlock = transformUIBlockForDB(uiblock, userPrompt, uiBlockId);
4948
+ logger.debug(`[CONVERSATION_SAVER] Transformed UIBlock for DB: ${JSON.stringify(dbUIBlock)}`);
4867
4949
  const saveResult = await collections["user-conversations"]["create"]({
4868
4950
  userId: userIdNumber,
4869
4951
  userPrompt,
4870
- uiblock,
4952
+ uiblock: dbUIBlock,
4871
4953
  threadId
4872
4954
  });
4873
4955
  if (!saveResult?.success) {
@@ -4884,7 +4966,8 @@ async function saveConversation(params) {
4884
4966
  const embedResult = await collections["conversation-history"]["embed"]({
4885
4967
  uiBlockId,
4886
4968
  userPrompt,
4887
- uiBlock: uiblock,
4969
+ uiBlock: dbUIBlock,
4970
+ // Use the transformed UIBlock
4888
4971
  userId: userIdNumber
4889
4972
  });
4890
4973
  if (embedResult?.success) {
@@ -5031,8 +5114,10 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
5031
5114
  if ("component" in userResponse.data) {
5032
5115
  component = userResponse.data.component;
5033
5116
  }
5034
- if ("textResponse" in userResponse.data) {
5117
+ if ("text" in userResponse.data) {
5035
5118
  textResponse = userResponse.data.text;
5119
+ } else if ("textResponse" in userResponse.data) {
5120
+ textResponse = userResponse.data.textResponse;
5036
5121
  }
5037
5122
  if ("actions" in userResponse.data) {
5038
5123
  actions = userResponse.data.actions || [];
@@ -6184,13 +6269,15 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6184
6269
  const { id, payload, from } = request;
6185
6270
  const { operation, data: requestData } = payload;
6186
6271
  const bookmarkId = requestData?.id;
6272
+ const userId = requestData?.userId;
6273
+ const threadId = requestData?.threadId;
6187
6274
  const uiblock = requestData?.uiblock;
6188
6275
  switch (operation) {
6189
6276
  case "create":
6190
- await handleCreate4(id, uiblock, executeCollection, sendMessage, from.id);
6277
+ await handleCreate4(id, userId, threadId, uiblock, executeCollection, sendMessage, from.id);
6191
6278
  break;
6192
6279
  case "update":
6193
- await handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, from.id);
6280
+ await handleUpdate4(id, bookmarkId, threadId, uiblock, executeCollection, sendMessage, from.id);
6194
6281
  break;
6195
6282
  case "delete":
6196
6283
  await handleDelete4(id, bookmarkId, executeCollection, sendMessage, from.id);
@@ -6201,6 +6288,12 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6201
6288
  case "getOne":
6202
6289
  await handleGetOne4(id, bookmarkId, executeCollection, sendMessage, from.id);
6203
6290
  break;
6291
+ case "getByUser":
6292
+ await handleGetByUser(id, userId, threadId, executeCollection, sendMessage, from.id);
6293
+ break;
6294
+ case "getByThread":
6295
+ await handleGetByThread(id, threadId, executeCollection, sendMessage, from.id);
6296
+ break;
6204
6297
  default:
6205
6298
  sendResponse6(id, {
6206
6299
  success: false,
@@ -6215,7 +6308,14 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6215
6308
  }, sendMessage);
6216
6309
  }
6217
6310
  }
6218
- async function handleCreate4(id, uiblock, executeCollection, sendMessage, clientId) {
6311
+ async function handleCreate4(id, userId, threadId, uiblock, executeCollection, sendMessage, clientId) {
6312
+ if (!userId) {
6313
+ sendResponse6(id, {
6314
+ success: false,
6315
+ error: "userId is required"
6316
+ }, sendMessage, clientId);
6317
+ return;
6318
+ }
6219
6319
  if (!uiblock) {
6220
6320
  sendResponse6(id, {
6221
6321
  success: false,
@@ -6224,7 +6324,7 @@ async function handleCreate4(id, uiblock, executeCollection, sendMessage, client
6224
6324
  return;
6225
6325
  }
6226
6326
  try {
6227
- const result = await executeCollection("bookmarks", "create", { uiblock });
6327
+ const result = await executeCollection("bookmarks", "create", { userId, threadId, uiblock });
6228
6328
  sendResponse6(id, {
6229
6329
  success: true,
6230
6330
  data: result.data,
@@ -6238,7 +6338,7 @@ async function handleCreate4(id, uiblock, executeCollection, sendMessage, client
6238
6338
  }, sendMessage, clientId);
6239
6339
  }
6240
6340
  }
6241
- async function handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, clientId) {
6341
+ async function handleUpdate4(id, bookmarkId, threadId, uiblock, executeCollection, sendMessage, clientId) {
6242
6342
  if (!bookmarkId) {
6243
6343
  sendResponse6(id, {
6244
6344
  success: false,
@@ -6254,7 +6354,7 @@ async function handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMes
6254
6354
  return;
6255
6355
  }
6256
6356
  try {
6257
- const result = await executeCollection("bookmarks", "update", { id: bookmarkId, uiblock });
6357
+ const result = await executeCollection("bookmarks", "update", { id: bookmarkId, threadId, uiblock });
6258
6358
  sendResponse6(id, {
6259
6359
  success: true,
6260
6360
  data: result.data,
@@ -6331,6 +6431,54 @@ async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, cli
6331
6431
  }, sendMessage, clientId);
6332
6432
  }
6333
6433
  }
6434
+ async function handleGetByUser(id, userId, threadId, executeCollection, sendMessage, clientId) {
6435
+ if (!userId) {
6436
+ sendResponse6(id, {
6437
+ success: false,
6438
+ error: "userId is required"
6439
+ }, sendMessage, clientId);
6440
+ return;
6441
+ }
6442
+ try {
6443
+ const result = await executeCollection("bookmarks", "getByUser", { userId, threadId });
6444
+ sendResponse6(id, {
6445
+ success: true,
6446
+ data: result.data,
6447
+ count: result.count,
6448
+ message: `Retrieved ${result.count} bookmarks for user ${userId}`
6449
+ }, sendMessage, clientId);
6450
+ logger.info(`Retrieved bookmarks for user ${userId} (count: ${result.count})`);
6451
+ } catch (error) {
6452
+ sendResponse6(id, {
6453
+ success: false,
6454
+ error: error instanceof Error ? error.message : "Failed to get bookmarks by user"
6455
+ }, sendMessage, clientId);
6456
+ }
6457
+ }
6458
+ async function handleGetByThread(id, threadId, executeCollection, sendMessage, clientId) {
6459
+ if (!threadId) {
6460
+ sendResponse6(id, {
6461
+ success: false,
6462
+ error: "threadId is required"
6463
+ }, sendMessage, clientId);
6464
+ return;
6465
+ }
6466
+ try {
6467
+ const result = await executeCollection("bookmarks", "getByThread", { threadId });
6468
+ sendResponse6(id, {
6469
+ success: true,
6470
+ data: result.data,
6471
+ count: result.count,
6472
+ message: `Retrieved ${result.count} bookmarks for thread ${threadId}`
6473
+ }, sendMessage, clientId);
6474
+ logger.info(`Retrieved bookmarks for thread ${threadId} (count: ${result.count})`);
6475
+ } catch (error) {
6476
+ sendResponse6(id, {
6477
+ success: false,
6478
+ error: error instanceof Error ? error.message : "Failed to get bookmarks by thread"
6479
+ }, sendMessage, clientId);
6480
+ }
6481
+ }
6334
6482
  function sendResponse6(id, res, sendMessage, clientId) {
6335
6483
  const response = {
6336
6484
  id: id || "unknown",
@@ -7317,12 +7465,12 @@ var SuperatomSDK = class {
7317
7465
  });
7318
7466
  break;
7319
7467
  case "AUTH_LOGIN_REQ":
7320
- handleAuthLoginRequest(parsed, (msg) => this.send(msg)).catch((error) => {
7468
+ handleAuthLoginRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7321
7469
  logger.error("Failed to handle auth login request:", error);
7322
7470
  });
7323
7471
  break;
7324
7472
  case "AUTH_VERIFY_REQ":
7325
- handleAuthVerifyRequest(parsed, (msg) => this.send(msg)).catch((error) => {
7473
+ handleAuthVerifyRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7326
7474
  logger.error("Failed to handle auth verify request:", error);
7327
7475
  });
7328
7476
  break;