@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.mjs CHANGED
@@ -525,10 +525,14 @@ var ReportsRequestMessageSchema = z3.object({
525
525
  var UIBlockSchema = z3.object({
526
526
  id: z3.string().optional(),
527
527
  userQuestion: z3.string().optional(),
528
+ user_prompt: z3.string().optional(),
529
+ // DB field name
528
530
  text: z3.string().optional(),
529
531
  textResponse: z3.string().optional(),
532
+ analysis: z3.string().optional(),
533
+ // DB field name for textResponse
530
534
  component: ComponentSchema.optional(),
531
- // Legacy field
535
+ // DB field name / Legacy field
532
536
  generatedComponentMetadata: ComponentSchema.optional(),
533
537
  // Actual field used by UIBlock class
534
538
  componentData: z3.record(z3.any()).optional(),
@@ -549,9 +553,11 @@ var BookmarkDataSchema = z3.object({
549
553
  updated_at: z3.string().optional()
550
554
  });
551
555
  var BookmarksRequestPayloadSchema = z3.object({
552
- operation: z3.enum(["create", "update", "delete", "getAll", "getOne"]),
556
+ operation: z3.enum(["create", "update", "delete", "getAll", "getOne", "getByUser", "getByThread"]),
553
557
  data: z3.object({
554
558
  id: z3.number().optional(),
559
+ userId: z3.number().optional(),
560
+ threadId: z3.string().optional(),
555
561
  uiblock: z3.any().optional()
556
562
  }).optional()
557
563
  });
@@ -1379,7 +1385,7 @@ async function cleanupUserStorage() {
1379
1385
  }
1380
1386
 
1381
1387
  // src/auth/validator.ts
1382
- function validateUser(credentials) {
1388
+ async function validateUser(credentials, collections) {
1383
1389
  const { username, email, password } = credentials;
1384
1390
  const identifier = username || email;
1385
1391
  logger.debug("[validateUser] Starting user validation");
@@ -1391,7 +1397,39 @@ function validateUser(credentials) {
1391
1397
  error: "Username or email and password are required"
1392
1398
  };
1393
1399
  }
1394
- logger.debug(`[validateUser] Looking up user by identifier: ${identifier}`);
1400
+ if (collections && collections["users"] && collections["users"]["authenticate"]) {
1401
+ logger.debug(`[validateUser] Attempting database authentication for: ${identifier}`);
1402
+ try {
1403
+ const dbResult = await collections["users"]["authenticate"]({
1404
+ identifier,
1405
+ password
1406
+ });
1407
+ logger.info("[validateUser] Database authentication attempt completed", dbResult);
1408
+ if (dbResult && dbResult.success && dbResult.data) {
1409
+ logger.info(`[validateUser] \u2713 User authenticated via database: ${dbResult.data.username}`);
1410
+ return {
1411
+ success: true,
1412
+ data: dbResult.data.username,
1413
+ username: dbResult.data.username,
1414
+ userId: dbResult.data.id
1415
+ };
1416
+ } else {
1417
+ logger.debug(`[validateUser] Database auth failed for ${identifier}: ${dbResult?.error || "Invalid credentials"}`);
1418
+ if (dbResult && dbResult.error === "Invalid credentials") {
1419
+ return {
1420
+ success: false,
1421
+ error: "Invalid credentials"
1422
+ };
1423
+ }
1424
+ }
1425
+ } catch (error) {
1426
+ const errorMsg = error instanceof Error ? error.message : String(error);
1427
+ logger.debug(`[validateUser] Database lookup error: ${errorMsg}, falling back to file storage`);
1428
+ }
1429
+ } else {
1430
+ logger.debug("[validateUser] No users collection available, using file storage only");
1431
+ }
1432
+ logger.info(`[validateUser] Attempting file-based validation for: ${identifier}`);
1395
1433
  const user = findUserByUsernameOrEmail(identifier);
1396
1434
  if (!user) {
1397
1435
  logger.warn(`[validateUser] Validation failed: User not found - ${identifier}`);
@@ -1400,7 +1438,7 @@ function validateUser(credentials) {
1400
1438
  error: "Invalid username or email"
1401
1439
  };
1402
1440
  }
1403
- logger.debug(`[validateUser] User found: ${user.username}, verifying password`);
1441
+ logger.debug(`[validateUser] User found in file storage: ${user.username}, verifying password`);
1404
1442
  const hashedPassword = hashPassword(user.password);
1405
1443
  if (hashedPassword !== password) {
1406
1444
  logger.warn(`[validateUser] Validation failed: Invalid password for user - ${user.username}`);
@@ -1410,19 +1448,18 @@ function validateUser(credentials) {
1410
1448
  error: "Invalid password"
1411
1449
  };
1412
1450
  }
1413
- logger.info(`[validateUser] \u2713 User validated successfully: ${user.username}`);
1414
- logger.debug(`[validateUser] Returning user data for: ${user.username}`);
1451
+ logger.info(`[validateUser] \u2713 User validated via file storage: ${user.username}`);
1415
1452
  return {
1416
1453
  success: true,
1417
1454
  data: user.username,
1418
1455
  username: user.username
1419
1456
  };
1420
1457
  }
1421
- function authenticateAndStoreWsId(credentials, wsId) {
1458
+ async function authenticateAndStoreWsId(credentials, wsId, collections) {
1422
1459
  const identifier = credentials.username || credentials.email;
1423
1460
  logger.debug("[authenticateAndStoreWsId] Starting authentication and WebSocket ID storage");
1424
1461
  logger.debug("[authenticateAndStoreWsId] Validating user credentials");
1425
- const validationResult = validateUser(credentials);
1462
+ const validationResult = await validateUser(credentials, collections);
1426
1463
  if (!validationResult.success) {
1427
1464
  logger.warn(`[authenticateAndStoreWsId] User validation failed for: ${identifier}`);
1428
1465
  return validationResult;
@@ -1434,7 +1471,7 @@ function authenticateAndStoreWsId(credentials, wsId) {
1434
1471
  logger.debug(`[authenticateAndStoreWsId] WebSocket ID ${wsId} associated with user ${username}`);
1435
1472
  return validationResult;
1436
1473
  }
1437
- function verifyAuthToken(authToken) {
1474
+ async function verifyAuthToken(authToken, collections) {
1438
1475
  try {
1439
1476
  logger.debug("[verifyAuthToken] Starting token verification");
1440
1477
  logger.debug("[verifyAuthToken] Decoding base64 token");
@@ -1444,7 +1481,7 @@ function verifyAuthToken(authToken) {
1444
1481
  logger.debug("[verifyAuthToken] Token decoded and parsed successfully");
1445
1482
  logger.debug(`[verifyAuthToken] Token contains username: ${credentials.username ? "\u2713" : "\u2717"}`);
1446
1483
  logger.debug("[verifyAuthToken] Validating credentials from token");
1447
- const result = validateUser(credentials);
1484
+ const result = await validateUser(credentials, collections);
1448
1485
  if (result.success) {
1449
1486
  logger.info(`[verifyAuthToken] \u2713 Token verified successfully for user: ${credentials.username || "unknown"}`);
1450
1487
  } else {
@@ -1463,7 +1500,7 @@ function verifyAuthToken(authToken) {
1463
1500
  }
1464
1501
 
1465
1502
  // src/handlers/auth-login-requests.ts
1466
- async function handleAuthLoginRequest(data, sendMessage) {
1503
+ async function handleAuthLoginRequest(data, collections, sendMessage) {
1467
1504
  try {
1468
1505
  logger.debug("[AUTH_LOGIN_REQ] Parsing incoming auth login request");
1469
1506
  const authRequest = AuthLoginRequestMessageSchema.parse(data);
@@ -1522,12 +1559,12 @@ async function handleAuthLoginRequest(data, sendMessage) {
1522
1559
  }, sendMessage, wsId);
1523
1560
  return;
1524
1561
  }
1525
- logger.info(`[AUTH_LOGIN_REQ ${id}] Credentials validated, authenticating user: ${identifier}`);
1526
- logger.debug(`[AUTH_LOGIN_REQ ${id}] WebSocket ID: ${wsId}`);
1562
+ logger.info(`[AUTH_LOGIN_REQ ${id}] Credentials validated, authenticating user: ${identifier} username: ${username} email: ${email} password: ${password}`);
1527
1563
  logger.debug(`[AUTH_LOGIN_REQ ${id}] Calling authenticateAndStoreWsId for user: ${identifier}`);
1528
- const authResult = authenticateAndStoreWsId(
1564
+ const authResult = await authenticateAndStoreWsId(
1529
1565
  { username, email, password },
1530
- wsId
1566
+ wsId,
1567
+ collections
1531
1568
  );
1532
1569
  logger.info(`[AUTH_LOGIN_REQ ${id}] Authentication result for ${identifier}: ${authResult.success ? "success" : "failed"}`);
1533
1570
  if (!authResult.success) {
@@ -1579,7 +1616,7 @@ function sendDataResponse2(id, res, sendMessage, clientId) {
1579
1616
  }
1580
1617
 
1581
1618
  // src/handlers/auth-verify-request.ts
1582
- async function handleAuthVerifyRequest(data, sendMessage) {
1619
+ async function handleAuthVerifyRequest(data, collections, sendMessage) {
1583
1620
  try {
1584
1621
  logger.debug("[AUTH_VERIFY_REQ] Parsing incoming auth verify request");
1585
1622
  const authRequest = AuthVerifyRequestMessageSchema.parse(data);
@@ -1609,7 +1646,7 @@ async function handleAuthVerifyRequest(data, sendMessage) {
1609
1646
  logger.debug(`[AUTH_VERIFY_REQ ${id}] WebSocket ID: ${wsId}`);
1610
1647
  logger.debug(`[AUTH_VERIFY_REQ ${id}] Calling verifyAuthToken`);
1611
1648
  const startTime = Date.now();
1612
- const authResult = verifyAuthToken(token);
1649
+ const authResult = await verifyAuthToken(token, collections);
1613
1650
  const verificationTime = Date.now() - startTime;
1614
1651
  logger.info(`[AUTH_VERIFY_REQ ${id}] Token verification completed in ${verificationTime}ms - ${authResult.success ? "valid" : "invalid"}`);
1615
1652
  if (!authResult.success) {
@@ -3659,13 +3696,13 @@ var BaseLLM = class {
3659
3696
  */
3660
3697
  async adaptUIBlockParameters(currentUserPrompt, originalUserPrompt, matchedUIBlock, apiKey, logCollector) {
3661
3698
  try {
3662
- if (!matchedUIBlock || !matchedUIBlock.generatedComponentMetadata) {
3699
+ const component = matchedUIBlock?.generatedComponentMetadata || matchedUIBlock?.component;
3700
+ if (!matchedUIBlock || !component) {
3663
3701
  return {
3664
3702
  success: false,
3665
3703
  explanation: "No component found in matched UI block"
3666
3704
  };
3667
3705
  }
3668
- const component = matchedUIBlock.generatedComponentMetadata;
3669
3706
  const schemaDoc = schema.generateSchemaDocumentation();
3670
3707
  const prompts = await promptLoader.loadPrompts("adapt-ui-block-params", {
3671
3708
  ORIGINAL_USER_PROMPT: originalUserPrompt,
@@ -3741,8 +3778,9 @@ var BaseLLM = class {
3741
3778
  * @param collections - Collection registry for executing database queries via database.execute
3742
3779
  * @param components - Optional list of available components for matching suggestions
3743
3780
  * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called
3781
+ * @param category - Question category ('data_analysis' | 'data_modification' | 'general'). For data_modification, answer component streaming is skipped. For general, component generation is skipped entirely.
3744
3782
  */
3745
- async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools) {
3783
+ async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools, category) {
3746
3784
  const errors = [];
3747
3785
  logger.debug(`[${this.getProviderName()}] Starting text response generation`);
3748
3786
  logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
@@ -4136,16 +4174,19 @@ ${errorMsg}
4136
4174
  textLength: textResponse.length
4137
4175
  }
4138
4176
  );
4139
- if (wrappedStreamCallback && components && components.length > 0) {
4177
+ if (wrappedStreamCallback && components && components.length > 0 && category !== "general") {
4140
4178
  wrappedStreamCallback("__TEXT_COMPLETE__COMPONENT_GENERATION_START__");
4141
4179
  }
4142
4180
  let matchedComponents = [];
4143
4181
  let layoutTitle = "Dashboard";
4144
4182
  let layoutDescription = "Multi-component dashboard";
4145
4183
  let actions = [];
4146
- if (components && components.length > 0) {
4184
+ if (category === "general") {
4185
+ logger.info(`[${this.getProviderName()}] Skipping component generation for general/conversational question`);
4186
+ logCollector?.info("Skipping component generation for general question");
4187
+ } else if (components && components.length > 0) {
4147
4188
  logger.info(`[${this.getProviderName()}] Matching components from text response...`);
4148
- const componentStreamCallback = wrappedStreamCallback ? (component) => {
4189
+ const componentStreamCallback = wrappedStreamCallback && category !== "data_modification" ? (component) => {
4149
4190
  const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
4150
4191
  wrappedStreamCallback(answerMarker);
4151
4192
  logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
@@ -4244,52 +4285,78 @@ ${errorMsg}
4244
4285
  logCollector?.info(
4245
4286
  `\u2713 Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`
4246
4287
  );
4247
- if (conversationMatch.similarity >= 0.99) {
4248
- const elapsedTime2 = Date.now() - startTime;
4249
- logger.info(`[${this.getProviderName()}] \u2713 100% match - returning UI block directly without adaptation`);
4250
- logCollector?.info(`\u2713 Exact match (${(conversationMatch.similarity * 100).toFixed(2)}%) - returning cached result`);
4251
- logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4252
- const component = conversationMatch.uiBlock?.generatedComponentMetadata || conversationMatch.uiBlock?.component;
4253
- return {
4254
- success: true,
4255
- data: {
4256
- component,
4257
- reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
4258
- method: `${this.getProviderName()}-semantic-match-exact`,
4259
- semanticSimilarity: conversationMatch.similarity
4260
- },
4261
- errors: []
4262
- };
4263
- }
4264
- logCollector?.info(`Adapting parameters for similar question...`);
4265
- const originalPrompt = conversationMatch.metadata?.userPrompt || "Previous question";
4266
- const adaptResult = await this.adaptUIBlockParameters(
4267
- userPrompt,
4268
- originalPrompt,
4269
- conversationMatch.uiBlock,
4270
- apiKey,
4271
- logCollector
4272
- );
4273
- if (adaptResult.success && adaptResult.adaptedComponent) {
4274
- const elapsedTime2 = Date.now() - startTime;
4275
- logger.info(`[${this.getProviderName()}] \u2713 Successfully adapted UI block parameters`);
4276
- logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4277
- logCollector?.info(`\u2713 UI block adapted successfully`);
4278
- logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4279
- return {
4280
- success: true,
4281
- data: {
4282
- component: adaptResult.adaptedComponent,
4283
- reasoning: `Adapted from previous conversation: ${originalPrompt}`,
4284
- method: `${this.getProviderName()}-semantic-match`,
4285
- semanticSimilarity: conversationMatch.similarity,
4286
- parametersChanged: adaptResult.parametersChanged
4287
- },
4288
- errors: []
4289
- };
4288
+ const component = conversationMatch.uiBlock?.component || conversationMatch.uiBlock?.generatedComponentMetadata;
4289
+ const cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || "";
4290
+ if (!component) {
4291
+ if (conversationMatch.similarity >= 0.99) {
4292
+ const elapsedTime2 = Date.now() - startTime;
4293
+ logger.info(`[${this.getProviderName()}] \u2713 Exact match for general question - returning cached text response`);
4294
+ logCollector?.info(`\u2713 Exact match for general question - returning cached response`);
4295
+ logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4296
+ return {
4297
+ success: true,
4298
+ data: {
4299
+ text: cachedTextResponse,
4300
+ component: null,
4301
+ matchedComponents: [],
4302
+ actions: conversationMatch.uiBlock?.actions || [],
4303
+ reasoning: `Exact match from previous general conversation`,
4304
+ method: `${this.getProviderName()}-semantic-match-general`,
4305
+ semanticSimilarity: conversationMatch.similarity
4306
+ },
4307
+ errors: []
4308
+ };
4309
+ } else {
4310
+ logger.info(`[${this.getProviderName()}] Similar match but no component (general question) - processing fresh`);
4311
+ logCollector?.info("Similar match found but was a general conversation - processing as new question");
4312
+ }
4290
4313
  } else {
4291
- logger.info(`[${this.getProviderName()}] Could not adapt matched conversation, continuing to category classification`);
4292
- logCollector?.warn(`Could not adapt matched conversation: ${adaptResult.explanation}`);
4314
+ if (conversationMatch.similarity >= 0.99) {
4315
+ const elapsedTime2 = Date.now() - startTime;
4316
+ logger.info(`[${this.getProviderName()}] \u2713 100% match - returning UI block directly without adaptation`);
4317
+ logCollector?.info(`\u2713 Exact match (${(conversationMatch.similarity * 100).toFixed(2)}%) - returning cached result`);
4318
+ logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4319
+ return {
4320
+ success: true,
4321
+ data: {
4322
+ component,
4323
+ reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
4324
+ method: `${this.getProviderName()}-semantic-match-exact`,
4325
+ semanticSimilarity: conversationMatch.similarity
4326
+ },
4327
+ errors: []
4328
+ };
4329
+ }
4330
+ logCollector?.info(`Adapting parameters for similar question...`);
4331
+ const originalPrompt = conversationMatch.metadata?.userPrompt || "Previous question";
4332
+ const adaptResult = await this.adaptUIBlockParameters(
4333
+ userPrompt,
4334
+ originalPrompt,
4335
+ conversationMatch.uiBlock,
4336
+ apiKey,
4337
+ logCollector
4338
+ );
4339
+ if (adaptResult.success && adaptResult.adaptedComponent) {
4340
+ const elapsedTime2 = Date.now() - startTime;
4341
+ logger.info(`[${this.getProviderName()}] \u2713 Successfully adapted UI block parameters`);
4342
+ logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4343
+ logCollector?.info(`\u2713 UI block adapted successfully`);
4344
+ logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
4345
+ return {
4346
+ success: true,
4347
+ data: {
4348
+ component: adaptResult.adaptedComponent,
4349
+ reasoning: `Adapted from previous conversation: ${originalPrompt}`,
4350
+ method: `${this.getProviderName()}-semantic-match`,
4351
+ semanticSimilarity: conversationMatch.similarity,
4352
+ parametersChanged: adaptResult.parametersChanged
4353
+ },
4354
+ errors: []
4355
+ };
4356
+ } else {
4357
+ logger.info(`[${this.getProviderName()}] Could not adapt matched conversation, continuing to category classification`);
4358
+ logCollector?.warn(`Could not adapt matched conversation: ${adaptResult.explanation}`);
4359
+ }
4293
4360
  }
4294
4361
  } else {
4295
4362
  logger.info(`[${this.getProviderName()}] No matching previous conversations found, proceeding to category classification`);
@@ -4331,7 +4398,10 @@ ${errorMsg}
4331
4398
  })()
4332
4399
  })) || [];
4333
4400
  }
4334
- if (categoryClassification.category === "data_analysis") {
4401
+ if (categoryClassification.category === "general") {
4402
+ logger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);
4403
+ logCollector?.info("Routing to general conversation...");
4404
+ } else if (categoryClassification.category === "data_analysis") {
4335
4405
  logger.info(`[${this.getProviderName()}] Routing to data analysis (SELECT operations)`);
4336
4406
  logCollector?.info("Routing to data analysis...");
4337
4407
  } else if (categoryClassification.category === "data_modification") {
@@ -4346,7 +4416,8 @@ ${errorMsg}
4346
4416
  streamCallback,
4347
4417
  collections,
4348
4418
  components,
4349
- toolsToUse
4419
+ toolsToUse,
4420
+ categoryClassification.category
4350
4421
  );
4351
4422
  const elapsedTime = Date.now() - startTime;
4352
4423
  logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1e3).toFixed(2)}s)`);
@@ -4770,6 +4841,15 @@ var UILogCollector = class {
4770
4841
  };
4771
4842
 
4772
4843
  // src/utils/conversation-saver.ts
4844
+ function transformUIBlockForDB(uiblock, userPrompt, uiBlockId) {
4845
+ const component = uiblock?.generatedComponentMetadata && Object.keys(uiblock.generatedComponentMetadata).length > 0 ? uiblock.generatedComponentMetadata : null;
4846
+ return {
4847
+ id: uiBlockId || uiblock?.id || "",
4848
+ component,
4849
+ analysis: uiblock?.textResponse || null,
4850
+ user_prompt: userPrompt || uiblock?.userQuestion || ""
4851
+ };
4852
+ }
4773
4853
  async function saveConversation(params) {
4774
4854
  const { userId, userPrompt, uiblock, uiBlockId, threadId, collections } = params;
4775
4855
  if (!userId) {
@@ -4824,10 +4904,12 @@ async function saveConversation(params) {
4824
4904
  error: `Invalid userId: ${userId} (not a valid number)`
4825
4905
  };
4826
4906
  }
4907
+ const dbUIBlock = transformUIBlockForDB(uiblock, userPrompt, uiBlockId);
4908
+ logger.debug(`[CONVERSATION_SAVER] Transformed UIBlock for DB: ${JSON.stringify(dbUIBlock)}`);
4827
4909
  const saveResult = await collections["user-conversations"]["create"]({
4828
4910
  userId: userIdNumber,
4829
4911
  userPrompt,
4830
- uiblock,
4912
+ uiblock: dbUIBlock,
4831
4913
  threadId
4832
4914
  });
4833
4915
  if (!saveResult?.success) {
@@ -4844,7 +4926,8 @@ async function saveConversation(params) {
4844
4926
  const embedResult = await collections["conversation-history"]["embed"]({
4845
4927
  uiBlockId,
4846
4928
  userPrompt,
4847
- uiBlock: uiblock,
4929
+ uiBlock: dbUIBlock,
4930
+ // Use the transformed UIBlock
4848
4931
  userId: userIdNumber
4849
4932
  });
4850
4933
  if (embedResult?.success) {
@@ -4991,8 +5074,10 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4991
5074
  if ("component" in userResponse.data) {
4992
5075
  component = userResponse.data.component;
4993
5076
  }
4994
- if ("textResponse" in userResponse.data) {
5077
+ if ("text" in userResponse.data) {
4995
5078
  textResponse = userResponse.data.text;
5079
+ } else if ("textResponse" in userResponse.data) {
5080
+ textResponse = userResponse.data.textResponse;
4996
5081
  }
4997
5082
  if ("actions" in userResponse.data) {
4998
5083
  actions = userResponse.data.actions || [];
@@ -6144,13 +6229,15 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6144
6229
  const { id, payload, from } = request;
6145
6230
  const { operation, data: requestData } = payload;
6146
6231
  const bookmarkId = requestData?.id;
6232
+ const userId = requestData?.userId;
6233
+ const threadId = requestData?.threadId;
6147
6234
  const uiblock = requestData?.uiblock;
6148
6235
  switch (operation) {
6149
6236
  case "create":
6150
- await handleCreate4(id, uiblock, executeCollection, sendMessage, from.id);
6237
+ await handleCreate4(id, userId, threadId, uiblock, executeCollection, sendMessage, from.id);
6151
6238
  break;
6152
6239
  case "update":
6153
- await handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, from.id);
6240
+ await handleUpdate4(id, bookmarkId, threadId, uiblock, executeCollection, sendMessage, from.id);
6154
6241
  break;
6155
6242
  case "delete":
6156
6243
  await handleDelete4(id, bookmarkId, executeCollection, sendMessage, from.id);
@@ -6161,6 +6248,12 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6161
6248
  case "getOne":
6162
6249
  await handleGetOne4(id, bookmarkId, executeCollection, sendMessage, from.id);
6163
6250
  break;
6251
+ case "getByUser":
6252
+ await handleGetByUser(id, userId, threadId, executeCollection, sendMessage, from.id);
6253
+ break;
6254
+ case "getByThread":
6255
+ await handleGetByThread(id, threadId, executeCollection, sendMessage, from.id);
6256
+ break;
6164
6257
  default:
6165
6258
  sendResponse6(id, {
6166
6259
  success: false,
@@ -6175,7 +6268,14 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6175
6268
  }, sendMessage);
6176
6269
  }
6177
6270
  }
6178
- async function handleCreate4(id, uiblock, executeCollection, sendMessage, clientId) {
6271
+ async function handleCreate4(id, userId, threadId, uiblock, executeCollection, sendMessage, clientId) {
6272
+ if (!userId) {
6273
+ sendResponse6(id, {
6274
+ success: false,
6275
+ error: "userId is required"
6276
+ }, sendMessage, clientId);
6277
+ return;
6278
+ }
6179
6279
  if (!uiblock) {
6180
6280
  sendResponse6(id, {
6181
6281
  success: false,
@@ -6184,7 +6284,7 @@ async function handleCreate4(id, uiblock, executeCollection, sendMessage, client
6184
6284
  return;
6185
6285
  }
6186
6286
  try {
6187
- const result = await executeCollection("bookmarks", "create", { uiblock });
6287
+ const result = await executeCollection("bookmarks", "create", { userId, threadId, uiblock });
6188
6288
  sendResponse6(id, {
6189
6289
  success: true,
6190
6290
  data: result.data,
@@ -6198,7 +6298,7 @@ async function handleCreate4(id, uiblock, executeCollection, sendMessage, client
6198
6298
  }, sendMessage, clientId);
6199
6299
  }
6200
6300
  }
6201
- async function handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, clientId) {
6301
+ async function handleUpdate4(id, bookmarkId, threadId, uiblock, executeCollection, sendMessage, clientId) {
6202
6302
  if (!bookmarkId) {
6203
6303
  sendResponse6(id, {
6204
6304
  success: false,
@@ -6214,7 +6314,7 @@ async function handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMes
6214
6314
  return;
6215
6315
  }
6216
6316
  try {
6217
- const result = await executeCollection("bookmarks", "update", { id: bookmarkId, uiblock });
6317
+ const result = await executeCollection("bookmarks", "update", { id: bookmarkId, threadId, uiblock });
6218
6318
  sendResponse6(id, {
6219
6319
  success: true,
6220
6320
  data: result.data,
@@ -6291,6 +6391,54 @@ async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, cli
6291
6391
  }, sendMessage, clientId);
6292
6392
  }
6293
6393
  }
6394
+ async function handleGetByUser(id, userId, threadId, executeCollection, sendMessage, clientId) {
6395
+ if (!userId) {
6396
+ sendResponse6(id, {
6397
+ success: false,
6398
+ error: "userId is required"
6399
+ }, sendMessage, clientId);
6400
+ return;
6401
+ }
6402
+ try {
6403
+ const result = await executeCollection("bookmarks", "getByUser", { userId, threadId });
6404
+ sendResponse6(id, {
6405
+ success: true,
6406
+ data: result.data,
6407
+ count: result.count,
6408
+ message: `Retrieved ${result.count} bookmarks for user ${userId}`
6409
+ }, sendMessage, clientId);
6410
+ logger.info(`Retrieved bookmarks for user ${userId} (count: ${result.count})`);
6411
+ } catch (error) {
6412
+ sendResponse6(id, {
6413
+ success: false,
6414
+ error: error instanceof Error ? error.message : "Failed to get bookmarks by user"
6415
+ }, sendMessage, clientId);
6416
+ }
6417
+ }
6418
+ async function handleGetByThread(id, threadId, executeCollection, sendMessage, clientId) {
6419
+ if (!threadId) {
6420
+ sendResponse6(id, {
6421
+ success: false,
6422
+ error: "threadId is required"
6423
+ }, sendMessage, clientId);
6424
+ return;
6425
+ }
6426
+ try {
6427
+ const result = await executeCollection("bookmarks", "getByThread", { threadId });
6428
+ sendResponse6(id, {
6429
+ success: true,
6430
+ data: result.data,
6431
+ count: result.count,
6432
+ message: `Retrieved ${result.count} bookmarks for thread ${threadId}`
6433
+ }, sendMessage, clientId);
6434
+ logger.info(`Retrieved bookmarks for thread ${threadId} (count: ${result.count})`);
6435
+ } catch (error) {
6436
+ sendResponse6(id, {
6437
+ success: false,
6438
+ error: error instanceof Error ? error.message : "Failed to get bookmarks by thread"
6439
+ }, sendMessage, clientId);
6440
+ }
6441
+ }
6294
6442
  function sendResponse6(id, res, sendMessage, clientId) {
6295
6443
  const response = {
6296
6444
  id: id || "unknown",
@@ -7277,12 +7425,12 @@ var SuperatomSDK = class {
7277
7425
  });
7278
7426
  break;
7279
7427
  case "AUTH_LOGIN_REQ":
7280
- handleAuthLoginRequest(parsed, (msg) => this.send(msg)).catch((error) => {
7428
+ handleAuthLoginRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7281
7429
  logger.error("Failed to handle auth login request:", error);
7282
7430
  });
7283
7431
  break;
7284
7432
  case "AUTH_VERIFY_REQ":
7285
- handleAuthVerifyRequest(parsed, (msg) => this.send(msg)).catch((error) => {
7433
+ handleAuthVerifyRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7286
7434
  logger.error("Failed to handle auth verify request:", error);
7287
7435
  });
7288
7436
  break;