@superatomai/sdk-node 0.0.11 → 0.0.12

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
@@ -485,6 +485,13 @@ var ComponentListResponseMessageSchema = import_zod3.z.object({
485
485
  type: import_zod3.z.literal("COMPONENT_LIST_RES"),
486
486
  payload: ComponentListResponsePayloadSchema
487
487
  });
488
+ var ToolSchema = import_zod3.z.object({
489
+ id: import_zod3.z.string(),
490
+ name: import_zod3.z.string(),
491
+ description: import_zod3.z.string(),
492
+ params: import_zod3.z.record(import_zod3.z.string()),
493
+ fn: import_zod3.z.function().args(import_zod3.z.any()).returns(import_zod3.z.any())
494
+ });
488
495
  var UsersRequestPayloadSchema = import_zod3.z.object({
489
496
  operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne"]),
490
497
  data: import_zod3.z.object({
@@ -555,6 +562,26 @@ var ReportsRequestMessageSchema = import_zod3.z.object({
555
562
  type: import_zod3.z.literal("REPORTS"),
556
563
  payload: ReportsRequestPayloadSchema
557
564
  });
565
+ var BookmarkDataSchema = import_zod3.z.object({
566
+ id: import_zod3.z.number().optional(),
567
+ uiblock: import_zod3.z.any(),
568
+ // JSON object
569
+ created_at: import_zod3.z.string().optional(),
570
+ updated_at: import_zod3.z.string().optional()
571
+ });
572
+ var BookmarksRequestPayloadSchema = import_zod3.z.object({
573
+ operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne"]),
574
+ data: import_zod3.z.object({
575
+ id: import_zod3.z.number().optional(),
576
+ uiblock: import_zod3.z.any().optional()
577
+ }).optional()
578
+ });
579
+ var BookmarksRequestMessageSchema = import_zod3.z.object({
580
+ id: import_zod3.z.string(),
581
+ from: MessageParticipantSchema,
582
+ type: import_zod3.z.literal("BOOKMARKS"),
583
+ payload: BookmarksRequestPayloadSchema
584
+ });
558
585
 
559
586
  // src/utils/logger.ts
560
587
  var import_fs = __toESM(require("fs"));
@@ -2610,6 +2637,71 @@ Format your response as a JSON object with this structure:
2610
2637
  }
2611
2638
 
2612
2639
  Return ONLY valid JSON.`
2640
+ },
2641
+ "execute-tools": {
2642
+ system: `You are an expert AI assistant that executes external tools to fetch data from external services.
2643
+
2644
+ You have access to external tools that can retrieve information like emails, calendar events, and other external data. When the user requests this information, you should call the appropriate tools.
2645
+
2646
+ ## Available External Tools
2647
+ {{AVAILABLE_TOOLS}}
2648
+
2649
+ ## Your Task
2650
+
2651
+ Analyze the user's request and:
2652
+
2653
+ 1. **Determine if external tools are needed**
2654
+ - Examples that NEED external tools:
2655
+ - "Show me my emails" \u2192 needs email tool
2656
+ - "Get my last 5 Gmail messages" \u2192 needs Gmail tool
2657
+ - "Check my Outlook inbox" \u2192 needs Outlook tool
2658
+
2659
+ - Examples that DON'T need external tools:
2660
+ - "What is the total sales?" \u2192 database query (handled elsewhere)
2661
+ - "Show me revenue trends" \u2192 internal data analysis
2662
+ - "Hello" \u2192 general conversation
2663
+
2664
+ 2. **Call the appropriate tools**
2665
+ - Use the tool calling mechanism to execute external tools
2666
+ - Extract parameters from the user's request
2667
+ - Use sensible defaults when parameters aren't specified:
2668
+ - For email limit: default to 10
2669
+ - For email address: use "me" for the authenticated user if not specified
2670
+
2671
+ 3. **Handle errors and retry**
2672
+ - If a tool call fails, analyze the error message
2673
+ - Retry with corrected parameters if possible
2674
+ - You have up to 3 attempts per tool
2675
+
2676
+ ## Important Guidelines
2677
+
2678
+ - **Only call external tools when necessary** - Don't call tools for database queries or general conversation
2679
+ - **Choose the right tool** - For email requests, select Gmail vs Outlook based on:
2680
+ - Explicit mention (e.g., "Gmail", "Outlook")
2681
+ - Email domain (e.g., @gmail.com \u2192 Gmail, @company.com \u2192 Outlook)
2682
+ - **Extract parameters carefully** - Use the user's exact values when provided
2683
+ - **If no tools are needed** - Simply respond that no external tools are required for this request
2684
+
2685
+ ## Examples
2686
+
2687
+ **Example 1 - Gmail Request:**
2688
+ User: "Show me my last 5 Gmail messages"
2689
+ Action: Call get-gmail-mails tool with parameters: { email: "me", limit: 5 }
2690
+
2691
+ **Example 2 - Outlook Request:**
2692
+ User: "Get emails from john.doe@company.com"
2693
+ Action: Call get-outlook-mails tool with parameters: { email: "john.doe@company.com", limit: 10 }
2694
+
2695
+ **Example 3 - No Tools Needed:**
2696
+ User: "What is the total sales?"
2697
+ Response: This is a database query, not an external tool request. No external tools are needed.
2698
+
2699
+ **Example 4 - Error Retry:**
2700
+ Tool call fails with: "Invalid email parameter"
2701
+ Action: Analyze error, correct the parameter, and retry the tool call
2702
+ `,
2703
+ user: `{{USER_PROMPT}}
2704
+ `
2613
2705
  }
2614
2706
  };
2615
2707
 
@@ -3660,6 +3752,7 @@ var BaseLLM = class {
3660
3752
  * @param components - List of available components
3661
3753
  * @param apiKey - Optional API key
3662
3754
  * @param logCollector - Optional log collector
3755
+ * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
3663
3756
  * @returns Object containing matched components, layout title/description, and follow-up actions
3664
3757
  */
3665
3758
  async matchComponentsFromTextResponse(textResponse, components, apiKey, logCollector) {
@@ -3763,6 +3856,152 @@ var BaseLLM = class {
3763
3856
  };
3764
3857
  }
3765
3858
  }
3859
+ /**
3860
+ * Execute external tools based on user request using agentic LLM tool calling
3861
+ * The LLM can directly call tools and retry on errors
3862
+ * @param userPrompt - The user's question/request
3863
+ * @param availableTools - Array of available external tools
3864
+ * @param apiKey - Optional API key for LLM
3865
+ * @param logCollector - Optional log collector
3866
+ * @returns Object containing tool execution results and summary
3867
+ */
3868
+ async executeExternalTools(userPrompt, availableTools, apiKey, logCollector) {
3869
+ const MAX_TOOL_ATTEMPTS = 3;
3870
+ const toolResults = [];
3871
+ try {
3872
+ logger.debug(`[${this.getProviderName()}] Starting agentic external tool execution`);
3873
+ logger.debug(`[${this.getProviderName()}] Available tools: ${availableTools.map((t) => t.name).join(", ")}`);
3874
+ const llmTools = availableTools.map((tool) => {
3875
+ const properties = {};
3876
+ const required = [];
3877
+ Object.entries(tool.params || {}).forEach(([key, type]) => {
3878
+ properties[key] = {
3879
+ type: String(type).toLowerCase(),
3880
+ description: `${key} parameter`
3881
+ };
3882
+ required.push(key);
3883
+ });
3884
+ return {
3885
+ name: tool.id,
3886
+ description: tool.description,
3887
+ input_schema: {
3888
+ type: "object",
3889
+ properties,
3890
+ required
3891
+ }
3892
+ };
3893
+ });
3894
+ const toolAttempts = /* @__PURE__ */ new Map();
3895
+ const toolHandler = async (toolName, toolInput) => {
3896
+ const tool = availableTools.find((t) => t.id === toolName);
3897
+ if (!tool) {
3898
+ const errorMsg = `Tool ${toolName} not found in available tools`;
3899
+ logger.error(`[${this.getProviderName()}] ${errorMsg}`);
3900
+ logCollector?.error(errorMsg);
3901
+ throw new Error(errorMsg);
3902
+ }
3903
+ const attempts = (toolAttempts.get(toolName) || 0) + 1;
3904
+ toolAttempts.set(toolName, attempts);
3905
+ logger.info(`[${this.getProviderName()}] Executing tool: ${tool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})`);
3906
+ logCollector?.info(`Executing ${tool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})...`);
3907
+ if (attempts > MAX_TOOL_ATTEMPTS) {
3908
+ const errorMsg = `Maximum attempts (${MAX_TOOL_ATTEMPTS}) reached for tool: ${tool.name}`;
3909
+ logger.error(`[${this.getProviderName()}] ${errorMsg}`);
3910
+ logCollector?.error(errorMsg);
3911
+ toolResults.push({
3912
+ toolName: tool.name,
3913
+ toolId: tool.id,
3914
+ result: null,
3915
+ error: errorMsg
3916
+ });
3917
+ throw new Error(errorMsg);
3918
+ }
3919
+ try {
3920
+ logger.debug(`[${this.getProviderName()}] Tool ${tool.name} parameters:`, toolInput);
3921
+ const result2 = await tool.fn(toolInput);
3922
+ logger.info(`[${this.getProviderName()}] Tool ${tool.name} executed successfully`);
3923
+ logCollector?.info(`\u2713 ${tool.name} completed successfully`);
3924
+ toolResults.push({
3925
+ toolName: tool.name,
3926
+ toolId: tool.id,
3927
+ result: result2
3928
+ });
3929
+ return JSON.stringify(result2, null, 2);
3930
+ } catch (error) {
3931
+ const errorMsg = error instanceof Error ? error.message : String(error);
3932
+ logger.error(`[${this.getProviderName()}] Tool ${tool.name} failed (attempt ${attempts}): ${errorMsg}`);
3933
+ logCollector?.error(`\u2717 ${tool.name} failed: ${errorMsg}`);
3934
+ if (attempts >= MAX_TOOL_ATTEMPTS) {
3935
+ toolResults.push({
3936
+ toolName: tool.name,
3937
+ toolId: tool.id,
3938
+ result: null,
3939
+ error: errorMsg
3940
+ });
3941
+ }
3942
+ throw new Error(`Tool execution failed: ${errorMsg}`);
3943
+ }
3944
+ };
3945
+ const prompts = await promptLoader.loadPrompts("execute-tools", {
3946
+ USER_PROMPT: userPrompt,
3947
+ AVAILABLE_TOOLS: availableTools.map((tool, idx) => {
3948
+ const paramsText = Object.entries(tool.params || {}).map(([key, type]) => ` - ${key}: ${type}`).join("\n");
3949
+ return `${idx + 1}. ID: ${tool.id}
3950
+ Name: ${tool.name}
3951
+ Description: ${tool.description}
3952
+ Parameters:
3953
+ ${paramsText}`;
3954
+ }).join("\n\n")
3955
+ });
3956
+ logger.debug(`[${this.getProviderName()}] Using agentic tool calling for external tools`);
3957
+ logCollector?.info("Analyzing request and executing external tools...");
3958
+ const result = await LLM.streamWithTools(
3959
+ {
3960
+ sys: prompts.system,
3961
+ user: prompts.user
3962
+ },
3963
+ llmTools,
3964
+ toolHandler,
3965
+ {
3966
+ model: this.model,
3967
+ maxTokens: 2e3,
3968
+ temperature: 0.2,
3969
+ apiKey: this.getApiKey(apiKey)
3970
+ },
3971
+ MAX_TOOL_ATTEMPTS + 2
3972
+ // max iterations: allows for retries + final response
3973
+ );
3974
+ logger.info(`[${this.getProviderName()}] External tool execution completed`);
3975
+ const successfulTools = toolResults.filter((r) => !r.error);
3976
+ const failedTools = toolResults.filter((r) => r.error);
3977
+ let summary = "";
3978
+ if (successfulTools.length > 0) {
3979
+ summary += `Successfully executed ${successfulTools.length} tool(s): ${successfulTools.map((t) => t.toolName).join(", ")}.
3980
+ `;
3981
+ }
3982
+ if (failedTools.length > 0) {
3983
+ summary += `Failed to execute ${failedTools.length} tool(s): ${failedTools.map((t) => t.toolName).join(", ")}.`;
3984
+ }
3985
+ if (toolResults.length === 0) {
3986
+ summary = "No external tools were needed for this request.";
3987
+ }
3988
+ logger.info(`[${this.getProviderName()}] Tool execution summary: ${summary}`);
3989
+ return {
3990
+ toolResults,
3991
+ summary,
3992
+ hasResults: successfulTools.length > 0
3993
+ };
3994
+ } catch (error) {
3995
+ const errorMsg = error instanceof Error ? error.message : String(error);
3996
+ logger.error(`[${this.getProviderName()}] Error in external tool execution: ${errorMsg}`);
3997
+ logCollector?.error(`Error executing external tools: ${errorMsg}`);
3998
+ return {
3999
+ toolResults,
4000
+ summary: `Error executing external tools: ${errorMsg}`,
4001
+ hasResults: false
4002
+ };
4003
+ }
4004
+ }
3766
4005
  /**
3767
4006
  * Generate text-based response for user question
3768
4007
  * This provides conversational text responses instead of component generation
@@ -3771,12 +4010,40 @@ var BaseLLM = class {
3771
4010
  * @param streamCallback - Optional callback function to receive text chunks as they stream
3772
4011
  * @param collections - Collection registry for executing database queries via database.execute
3773
4012
  * @param components - Optional list of available components for matching suggestions
4013
+ * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called
3774
4014
  */
3775
- async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components) {
4015
+ async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools) {
3776
4016
  const errors = [];
3777
4017
  logger.debug(`[${this.getProviderName()}] Starting text response generation`);
3778
4018
  logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
3779
4019
  try {
4020
+ let externalToolContext = "No external tools were used for this request.";
4021
+ if (externalTools && externalTools.length > 0) {
4022
+ logger.info(`[${this.getProviderName()}] Executing external tools...`);
4023
+ const toolExecution = await this.executeExternalTools(
4024
+ userPrompt,
4025
+ externalTools,
4026
+ apiKey,
4027
+ logCollector
4028
+ );
4029
+ if (toolExecution.hasResults) {
4030
+ const toolResultsText = toolExecution.toolResults.map((tr) => {
4031
+ if (tr.error) {
4032
+ return `**${tr.toolName}** (Failed): ${tr.error}`;
4033
+ }
4034
+ return `**${tr.toolName}** (Success):
4035
+ ${JSON.stringify(tr.result, null, 2)}`;
4036
+ }).join("\n\n");
4037
+ externalToolContext = `## External Tool Results
4038
+
4039
+ ${toolExecution.summary}
4040
+
4041
+ ${toolResultsText}`;
4042
+ logger.info(`[${this.getProviderName()}] External tools executed, results available`);
4043
+ } else {
4044
+ logger.info(`[${this.getProviderName()}] No external tools were needed`);
4045
+ }
4046
+ }
3780
4047
  const schemaDoc = schema.generateSchemaDocumentation();
3781
4048
  const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
3782
4049
  prompt: userPrompt,
@@ -3784,11 +4051,13 @@ var BaseLLM = class {
3784
4051
  topK: 1
3785
4052
  });
3786
4053
  logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
4054
+ logger.file("\n=============================\nexternal tool context:", externalToolContext);
3787
4055
  const prompts = await promptLoader.loadPrompts("text-response", {
3788
4056
  USER_PROMPT: userPrompt,
3789
4057
  CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
3790
4058
  SCHEMA_DOC: schemaDoc,
3791
- KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available."
4059
+ KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
4060
+ EXTERNAL_TOOL_CONTEXT: externalToolContext
3792
4061
  });
3793
4062
  logger.file("\n=============================\nsystem prompt:", prompts.system);
3794
4063
  logger.file("\n=============================\nuser prompt:", prompts.user);
@@ -4259,8 +4528,9 @@ ${errorMsg}
4259
4528
  * @param responseMode - 'component' for component generation (default), 'text' for text responses
4260
4529
  * @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)
4261
4530
  * @param collections - Collection registry for executing database queries (required for text mode)
4531
+ * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called (only for text mode)
4262
4532
  */
4263
- async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) {
4533
+ async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) {
4264
4534
  const startTime = Date.now();
4265
4535
  logger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);
4266
4536
  if (responseMode === "text") {
@@ -4273,7 +4543,8 @@ ${errorMsg}
4273
4543
  conversationHistory,
4274
4544
  streamCallback,
4275
4545
  collections,
4276
- components
4546
+ components,
4547
+ externalTools
4277
4548
  );
4278
4549
  if (!textResponse.success) {
4279
4550
  const elapsedTime3 = Date.now() - startTime;
@@ -4419,7 +4690,7 @@ function getLLMProviders() {
4419
4690
  return DEFAULT_PROVIDERS;
4420
4691
  }
4421
4692
  }
4422
- var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
4693
+ var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
4423
4694
  logger.debug("[useAnthropicMethod] Initializing Anthropic Claude matching method");
4424
4695
  logger.debug(`[useAnthropicMethod] Response mode: ${responseMode}`);
4425
4696
  const msg = `Using Anthropic Claude ${responseMode === "text" ? "text response" : "matching"} method...`;
@@ -4431,11 +4702,11 @@ var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conver
4431
4702
  return { success: false, errors: [emptyMsg] };
4432
4703
  }
4433
4704
  logger.debug(`[useAnthropicMethod] Processing with ${components.length} components`);
4434
- const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
4705
+ const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
4435
4706
  logger.info(`[useAnthropicMethod] Successfully generated ${responseMode} using Anthropic`);
4436
4707
  return matchResult;
4437
4708
  };
4438
- var useGroqMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
4709
+ var useGroqMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
4439
4710
  logger.debug("[useGroqMethod] Initializing Groq LLM matching method");
4440
4711
  logger.debug(`[useGroqMethod] Response mode: ${responseMode}`);
4441
4712
  const msg = `Using Groq LLM ${responseMode === "text" ? "text response" : "matching"} method...`;
@@ -4448,14 +4719,14 @@ var useGroqMethod = async (prompt, components, apiKey, logCollector, conversatio
4448
4719
  return { success: false, errors: [emptyMsg] };
4449
4720
  }
4450
4721
  logger.debug(`[useGroqMethod] Processing with ${components.length} components`);
4451
- const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
4722
+ const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
4452
4723
  logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);
4453
4724
  return matchResult;
4454
4725
  };
4455
4726
  var getUserResponseFromCache = async (prompt) => {
4456
4727
  return false;
4457
4728
  };
4458
- var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
4729
+ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
4459
4730
  logger.debug(`[get_user_response] Starting user response generation for prompt: "${prompt.substring(0, 50)}..."`);
4460
4731
  logger.debug(`[get_user_response] Response mode: ${responseMode}`);
4461
4732
  logger.debug("[get_user_response] Checking cache for existing response");
@@ -4488,9 +4759,9 @@ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey,
4488
4759
  logCollector?.info(attemptMsg);
4489
4760
  let result;
4490
4761
  if (provider === "anthropic") {
4491
- result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
4762
+ result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
4492
4763
  } else if (provider === "groq") {
4493
- result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
4764
+ result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
4494
4765
  } else {
4495
4766
  logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);
4496
4767
  errors.push(`Unknown provider: ${provider}`);
@@ -4718,7 +4989,7 @@ var CONTEXT_CONFIG = {
4718
4989
  };
4719
4990
 
4720
4991
  // src/handlers/user-prompt-request.ts
4721
- var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections) => {
4992
+ var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools) => {
4722
4993
  const errors = [];
4723
4994
  logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
4724
4995
  const parseResult = UserPromptRequestMessageSchema.safeParse(data);
@@ -4798,7 +5069,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4798
5069
  conversationHistory,
4799
5070
  responseMode,
4800
5071
  streamCallback,
4801
- collections
5072
+ collections,
5073
+ externalTools
4802
5074
  );
4803
5075
  logCollector.info("User prompt request completed");
4804
5076
  const uiBlockId = existingUiBlockId;
@@ -4859,8 +5131,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4859
5131
  wsId
4860
5132
  };
4861
5133
  };
4862
- async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections) {
4863
- const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections);
5134
+ async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools) {
5135
+ const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools);
4864
5136
  sendDataResponse4(
4865
5137
  response.id || data.id,
4866
5138
  {
@@ -5934,6 +6206,183 @@ function sendResponse5(id, res, sendMessage, clientId) {
5934
6206
  sendMessage(response);
5935
6207
  }
5936
6208
 
6209
+ // src/handlers/bookmarks.ts
6210
+ async function handleBookmarksRequest(data, collections, sendMessage) {
6211
+ const executeCollection = async (collection, op, params) => {
6212
+ const handler = collections[collection]?.[op];
6213
+ if (!handler) {
6214
+ throw new Error(`Collection operation ${collection}.${op} not found`);
6215
+ }
6216
+ return await handler(params);
6217
+ };
6218
+ try {
6219
+ const request = BookmarksRequestMessageSchema.parse(data);
6220
+ const { id, payload, from } = request;
6221
+ const { operation, data: requestData } = payload;
6222
+ const bookmarkId = requestData?.id;
6223
+ const uiblock = requestData?.uiblock;
6224
+ switch (operation) {
6225
+ case "create":
6226
+ await handleCreate4(id, uiblock, executeCollection, sendMessage, from.id);
6227
+ break;
6228
+ case "update":
6229
+ await handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, from.id);
6230
+ break;
6231
+ case "delete":
6232
+ await handleDelete4(id, bookmarkId, executeCollection, sendMessage, from.id);
6233
+ break;
6234
+ case "getAll":
6235
+ await handleGetAll4(id, executeCollection, sendMessage, from.id);
6236
+ break;
6237
+ case "getOne":
6238
+ await handleGetOne4(id, bookmarkId, executeCollection, sendMessage, from.id);
6239
+ break;
6240
+ default:
6241
+ sendResponse6(id, {
6242
+ success: false,
6243
+ error: `Unknown operation: ${operation}`
6244
+ }, sendMessage, from.id);
6245
+ }
6246
+ } catch (error) {
6247
+ logger.error("Failed to handle bookmarks request:", error);
6248
+ sendResponse6(null, {
6249
+ success: false,
6250
+ error: error instanceof Error ? error.message : "Unknown error occurred"
6251
+ }, sendMessage);
6252
+ }
6253
+ }
6254
+ async function handleCreate4(id, uiblock, executeCollection, sendMessage, clientId) {
6255
+ if (!uiblock) {
6256
+ sendResponse6(id, {
6257
+ success: false,
6258
+ error: "UIBlock data is required"
6259
+ }, sendMessage, clientId);
6260
+ return;
6261
+ }
6262
+ try {
6263
+ const result = await executeCollection("bookmarks", "create", { uiblock });
6264
+ sendResponse6(id, {
6265
+ success: true,
6266
+ data: result.data,
6267
+ message: "Bookmark created successfully"
6268
+ }, sendMessage, clientId);
6269
+ logger.info(`Bookmark created: ID ${result.data.id}`);
6270
+ } catch (error) {
6271
+ sendResponse6(id, {
6272
+ success: false,
6273
+ error: error instanceof Error ? error.message : "Failed to create bookmark"
6274
+ }, sendMessage, clientId);
6275
+ }
6276
+ }
6277
+ async function handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, clientId) {
6278
+ if (!bookmarkId) {
6279
+ sendResponse6(id, {
6280
+ success: false,
6281
+ error: "Bookmark ID is required"
6282
+ }, sendMessage, clientId);
6283
+ return;
6284
+ }
6285
+ if (!uiblock) {
6286
+ sendResponse6(id, {
6287
+ success: false,
6288
+ error: "UIBlock data is required"
6289
+ }, sendMessage, clientId);
6290
+ return;
6291
+ }
6292
+ try {
6293
+ const result = await executeCollection("bookmarks", "update", { id: bookmarkId, uiblock });
6294
+ sendResponse6(id, {
6295
+ success: true,
6296
+ data: result.data,
6297
+ message: "Bookmark updated successfully"
6298
+ }, sendMessage, clientId);
6299
+ logger.info(`Bookmark updated: ID ${bookmarkId}`);
6300
+ } catch (error) {
6301
+ sendResponse6(id, {
6302
+ success: false,
6303
+ error: error instanceof Error ? error.message : "Failed to update bookmark"
6304
+ }, sendMessage, clientId);
6305
+ }
6306
+ }
6307
+ async function handleDelete4(id, bookmarkId, executeCollection, sendMessage, clientId) {
6308
+ if (!bookmarkId) {
6309
+ sendResponse6(id, {
6310
+ success: false,
6311
+ error: "Bookmark ID is required"
6312
+ }, sendMessage, clientId);
6313
+ return;
6314
+ }
6315
+ try {
6316
+ const result = await executeCollection("bookmarks", "delete", { id: bookmarkId });
6317
+ sendResponse6(id, {
6318
+ success: true,
6319
+ data: result.data,
6320
+ message: "Bookmark deleted successfully"
6321
+ }, sendMessage, clientId);
6322
+ logger.info(`Bookmark deleted: ID ${bookmarkId}`);
6323
+ } catch (error) {
6324
+ sendResponse6(id, {
6325
+ success: false,
6326
+ error: error instanceof Error ? error.message : "Failed to delete bookmark"
6327
+ }, sendMessage, clientId);
6328
+ }
6329
+ }
6330
+ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
6331
+ try {
6332
+ const result = await executeCollection("bookmarks", "getAll", {});
6333
+ sendResponse6(id, {
6334
+ success: true,
6335
+ data: result.data,
6336
+ count: result.count,
6337
+ message: `Retrieved ${result.count} bookmarks`
6338
+ }, sendMessage, clientId);
6339
+ logger.info(`Retrieved all bookmarks (count: ${result.count})`);
6340
+ } catch (error) {
6341
+ sendResponse6(id, {
6342
+ success: false,
6343
+ error: error instanceof Error ? error.message : "Failed to get bookmarks"
6344
+ }, sendMessage, clientId);
6345
+ }
6346
+ }
6347
+ async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, clientId) {
6348
+ if (!bookmarkId) {
6349
+ sendResponse6(id, {
6350
+ success: false,
6351
+ error: "Bookmark ID is required"
6352
+ }, sendMessage, clientId);
6353
+ return;
6354
+ }
6355
+ try {
6356
+ const result = await executeCollection("bookmarks", "getOne", { id: bookmarkId });
6357
+ sendResponse6(id, {
6358
+ success: true,
6359
+ data: result.data,
6360
+ message: `Retrieved bookmark ID ${bookmarkId}`
6361
+ }, sendMessage, clientId);
6362
+ logger.info(`Retrieved bookmark: ID ${bookmarkId}`);
6363
+ } catch (error) {
6364
+ sendResponse6(id, {
6365
+ success: false,
6366
+ error: error instanceof Error ? error.message : "Failed to get bookmark"
6367
+ }, sendMessage, clientId);
6368
+ }
6369
+ }
6370
+ function sendResponse6(id, res, sendMessage, clientId) {
6371
+ const response = {
6372
+ id: id || "unknown",
6373
+ type: "BOOKMARKS_RES",
6374
+ from: { type: "data-agent" },
6375
+ to: {
6376
+ type: "user",
6377
+ id: clientId
6378
+ },
6379
+ payload: {
6380
+ ...res
6381
+ }
6382
+ };
6383
+ sendMessage(response);
6384
+ }
6385
+
5937
6386
  // src/auth/user-manager.ts
5938
6387
  var import_fs4 = __toESM(require("fs"));
5939
6388
  var import_path3 = __toESM(require("path"));
@@ -6758,6 +7207,7 @@ var SuperatomSDK = class {
6758
7207
  this.maxReconnectAttempts = 5;
6759
7208
  this.collections = {};
6760
7209
  this.components = [];
7210
+ this.tools = [];
6761
7211
  if (config.logLevel) {
6762
7212
  logger.setLogLevel(config.logLevel);
6763
7213
  }
@@ -6913,7 +7363,7 @@ var SuperatomSDK = class {
6913
7363
  });
6914
7364
  break;
6915
7365
  case "USER_PROMPT_REQ":
6916
- handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections).catch((error) => {
7366
+ handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
6917
7367
  logger.error("Failed to handle user prompt request:", error);
6918
7368
  });
6919
7369
  break;
@@ -6947,6 +7397,11 @@ var SuperatomSDK = class {
6947
7397
  logger.error("Failed to handle reports request:", error);
6948
7398
  });
6949
7399
  break;
7400
+ case "BOOKMARKS":
7401
+ handleBookmarksRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7402
+ logger.error("Failed to handle bookmarks request:", error);
7403
+ });
7404
+ break;
6950
7405
  default:
6951
7406
  const handler = this.messageTypeHandlers.get(message.type);
6952
7407
  if (handler) {
@@ -7053,6 +7508,19 @@ var SuperatomSDK = class {
7053
7508
  storeComponents(components) {
7054
7509
  this.components = components;
7055
7510
  }
7511
+ /**
7512
+ * Set tools for the SDK instance
7513
+ */
7514
+ setTools(tools) {
7515
+ this.tools = tools;
7516
+ logger.info(`Tools stored in SDK: ${tools.length} tools`);
7517
+ }
7518
+ /**
7519
+ * Get the stored tools
7520
+ */
7521
+ getTools() {
7522
+ return this.tools;
7523
+ }
7056
7524
  };
7057
7525
  // Annotate the CommonJS export names for ESM import in node:
7058
7526
  0 && (module.exports = {