@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.mjs CHANGED
@@ -445,6 +445,13 @@ var ComponentListResponseMessageSchema = z3.object({
445
445
  type: z3.literal("COMPONENT_LIST_RES"),
446
446
  payload: ComponentListResponsePayloadSchema
447
447
  });
448
+ var ToolSchema = z3.object({
449
+ id: z3.string(),
450
+ name: z3.string(),
451
+ description: z3.string(),
452
+ params: z3.record(z3.string()),
453
+ fn: z3.function().args(z3.any()).returns(z3.any())
454
+ });
448
455
  var UsersRequestPayloadSchema = z3.object({
449
456
  operation: z3.enum(["create", "update", "delete", "getAll", "getOne"]),
450
457
  data: z3.object({
@@ -515,6 +522,26 @@ var ReportsRequestMessageSchema = z3.object({
515
522
  type: z3.literal("REPORTS"),
516
523
  payload: ReportsRequestPayloadSchema
517
524
  });
525
+ var BookmarkDataSchema = z3.object({
526
+ id: z3.number().optional(),
527
+ uiblock: z3.any(),
528
+ // JSON object
529
+ created_at: z3.string().optional(),
530
+ updated_at: z3.string().optional()
531
+ });
532
+ var BookmarksRequestPayloadSchema = z3.object({
533
+ operation: z3.enum(["create", "update", "delete", "getAll", "getOne"]),
534
+ data: z3.object({
535
+ id: z3.number().optional(),
536
+ uiblock: z3.any().optional()
537
+ }).optional()
538
+ });
539
+ var BookmarksRequestMessageSchema = z3.object({
540
+ id: z3.string(),
541
+ from: MessageParticipantSchema,
542
+ type: z3.literal("BOOKMARKS"),
543
+ payload: BookmarksRequestPayloadSchema
544
+ });
518
545
 
519
546
  // src/utils/logger.ts
520
547
  import fs from "fs";
@@ -2570,6 +2597,71 @@ Format your response as a JSON object with this structure:
2570
2597
  }
2571
2598
 
2572
2599
  Return ONLY valid JSON.`
2600
+ },
2601
+ "execute-tools": {
2602
+ system: `You are an expert AI assistant that executes external tools to fetch data from external services.
2603
+
2604
+ 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.
2605
+
2606
+ ## Available External Tools
2607
+ {{AVAILABLE_TOOLS}}
2608
+
2609
+ ## Your Task
2610
+
2611
+ Analyze the user's request and:
2612
+
2613
+ 1. **Determine if external tools are needed**
2614
+ - Examples that NEED external tools:
2615
+ - "Show me my emails" \u2192 needs email tool
2616
+ - "Get my last 5 Gmail messages" \u2192 needs Gmail tool
2617
+ - "Check my Outlook inbox" \u2192 needs Outlook tool
2618
+
2619
+ - Examples that DON'T need external tools:
2620
+ - "What is the total sales?" \u2192 database query (handled elsewhere)
2621
+ - "Show me revenue trends" \u2192 internal data analysis
2622
+ - "Hello" \u2192 general conversation
2623
+
2624
+ 2. **Call the appropriate tools**
2625
+ - Use the tool calling mechanism to execute external tools
2626
+ - Extract parameters from the user's request
2627
+ - Use sensible defaults when parameters aren't specified:
2628
+ - For email limit: default to 10
2629
+ - For email address: use "me" for the authenticated user if not specified
2630
+
2631
+ 3. **Handle errors and retry**
2632
+ - If a tool call fails, analyze the error message
2633
+ - Retry with corrected parameters if possible
2634
+ - You have up to 3 attempts per tool
2635
+
2636
+ ## Important Guidelines
2637
+
2638
+ - **Only call external tools when necessary** - Don't call tools for database queries or general conversation
2639
+ - **Choose the right tool** - For email requests, select Gmail vs Outlook based on:
2640
+ - Explicit mention (e.g., "Gmail", "Outlook")
2641
+ - Email domain (e.g., @gmail.com \u2192 Gmail, @company.com \u2192 Outlook)
2642
+ - **Extract parameters carefully** - Use the user's exact values when provided
2643
+ - **If no tools are needed** - Simply respond that no external tools are required for this request
2644
+
2645
+ ## Examples
2646
+
2647
+ **Example 1 - Gmail Request:**
2648
+ User: "Show me my last 5 Gmail messages"
2649
+ Action: Call get-gmail-mails tool with parameters: { email: "me", limit: 5 }
2650
+
2651
+ **Example 2 - Outlook Request:**
2652
+ User: "Get emails from john.doe@company.com"
2653
+ Action: Call get-outlook-mails tool with parameters: { email: "john.doe@company.com", limit: 10 }
2654
+
2655
+ **Example 3 - No Tools Needed:**
2656
+ User: "What is the total sales?"
2657
+ Response: This is a database query, not an external tool request. No external tools are needed.
2658
+
2659
+ **Example 4 - Error Retry:**
2660
+ Tool call fails with: "Invalid email parameter"
2661
+ Action: Analyze error, correct the parameter, and retry the tool call
2662
+ `,
2663
+ user: `{{USER_PROMPT}}
2664
+ `
2573
2665
  }
2574
2666
  };
2575
2667
 
@@ -3620,6 +3712,7 @@ var BaseLLM = class {
3620
3712
  * @param components - List of available components
3621
3713
  * @param apiKey - Optional API key
3622
3714
  * @param logCollector - Optional log collector
3715
+ * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
3623
3716
  * @returns Object containing matched components, layout title/description, and follow-up actions
3624
3717
  */
3625
3718
  async matchComponentsFromTextResponse(textResponse, components, apiKey, logCollector) {
@@ -3723,6 +3816,152 @@ var BaseLLM = class {
3723
3816
  };
3724
3817
  }
3725
3818
  }
3819
+ /**
3820
+ * Execute external tools based on user request using agentic LLM tool calling
3821
+ * The LLM can directly call tools and retry on errors
3822
+ * @param userPrompt - The user's question/request
3823
+ * @param availableTools - Array of available external tools
3824
+ * @param apiKey - Optional API key for LLM
3825
+ * @param logCollector - Optional log collector
3826
+ * @returns Object containing tool execution results and summary
3827
+ */
3828
+ async executeExternalTools(userPrompt, availableTools, apiKey, logCollector) {
3829
+ const MAX_TOOL_ATTEMPTS = 3;
3830
+ const toolResults = [];
3831
+ try {
3832
+ logger.debug(`[${this.getProviderName()}] Starting agentic external tool execution`);
3833
+ logger.debug(`[${this.getProviderName()}] Available tools: ${availableTools.map((t) => t.name).join(", ")}`);
3834
+ const llmTools = availableTools.map((tool) => {
3835
+ const properties = {};
3836
+ const required = [];
3837
+ Object.entries(tool.params || {}).forEach(([key, type]) => {
3838
+ properties[key] = {
3839
+ type: String(type).toLowerCase(),
3840
+ description: `${key} parameter`
3841
+ };
3842
+ required.push(key);
3843
+ });
3844
+ return {
3845
+ name: tool.id,
3846
+ description: tool.description,
3847
+ input_schema: {
3848
+ type: "object",
3849
+ properties,
3850
+ required
3851
+ }
3852
+ };
3853
+ });
3854
+ const toolAttempts = /* @__PURE__ */ new Map();
3855
+ const toolHandler = async (toolName, toolInput) => {
3856
+ const tool = availableTools.find((t) => t.id === toolName);
3857
+ if (!tool) {
3858
+ const errorMsg = `Tool ${toolName} not found in available tools`;
3859
+ logger.error(`[${this.getProviderName()}] ${errorMsg}`);
3860
+ logCollector?.error(errorMsg);
3861
+ throw new Error(errorMsg);
3862
+ }
3863
+ const attempts = (toolAttempts.get(toolName) || 0) + 1;
3864
+ toolAttempts.set(toolName, attempts);
3865
+ logger.info(`[${this.getProviderName()}] Executing tool: ${tool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})`);
3866
+ logCollector?.info(`Executing ${tool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})...`);
3867
+ if (attempts > MAX_TOOL_ATTEMPTS) {
3868
+ const errorMsg = `Maximum attempts (${MAX_TOOL_ATTEMPTS}) reached for tool: ${tool.name}`;
3869
+ logger.error(`[${this.getProviderName()}] ${errorMsg}`);
3870
+ logCollector?.error(errorMsg);
3871
+ toolResults.push({
3872
+ toolName: tool.name,
3873
+ toolId: tool.id,
3874
+ result: null,
3875
+ error: errorMsg
3876
+ });
3877
+ throw new Error(errorMsg);
3878
+ }
3879
+ try {
3880
+ logger.debug(`[${this.getProviderName()}] Tool ${tool.name} parameters:`, toolInput);
3881
+ const result2 = await tool.fn(toolInput);
3882
+ logger.info(`[${this.getProviderName()}] Tool ${tool.name} executed successfully`);
3883
+ logCollector?.info(`\u2713 ${tool.name} completed successfully`);
3884
+ toolResults.push({
3885
+ toolName: tool.name,
3886
+ toolId: tool.id,
3887
+ result: result2
3888
+ });
3889
+ return JSON.stringify(result2, null, 2);
3890
+ } catch (error) {
3891
+ const errorMsg = error instanceof Error ? error.message : String(error);
3892
+ logger.error(`[${this.getProviderName()}] Tool ${tool.name} failed (attempt ${attempts}): ${errorMsg}`);
3893
+ logCollector?.error(`\u2717 ${tool.name} failed: ${errorMsg}`);
3894
+ if (attempts >= MAX_TOOL_ATTEMPTS) {
3895
+ toolResults.push({
3896
+ toolName: tool.name,
3897
+ toolId: tool.id,
3898
+ result: null,
3899
+ error: errorMsg
3900
+ });
3901
+ }
3902
+ throw new Error(`Tool execution failed: ${errorMsg}`);
3903
+ }
3904
+ };
3905
+ const prompts = await promptLoader.loadPrompts("execute-tools", {
3906
+ USER_PROMPT: userPrompt,
3907
+ AVAILABLE_TOOLS: availableTools.map((tool, idx) => {
3908
+ const paramsText = Object.entries(tool.params || {}).map(([key, type]) => ` - ${key}: ${type}`).join("\n");
3909
+ return `${idx + 1}. ID: ${tool.id}
3910
+ Name: ${tool.name}
3911
+ Description: ${tool.description}
3912
+ Parameters:
3913
+ ${paramsText}`;
3914
+ }).join("\n\n")
3915
+ });
3916
+ logger.debug(`[${this.getProviderName()}] Using agentic tool calling for external tools`);
3917
+ logCollector?.info("Analyzing request and executing external tools...");
3918
+ const result = await LLM.streamWithTools(
3919
+ {
3920
+ sys: prompts.system,
3921
+ user: prompts.user
3922
+ },
3923
+ llmTools,
3924
+ toolHandler,
3925
+ {
3926
+ model: this.model,
3927
+ maxTokens: 2e3,
3928
+ temperature: 0.2,
3929
+ apiKey: this.getApiKey(apiKey)
3930
+ },
3931
+ MAX_TOOL_ATTEMPTS + 2
3932
+ // max iterations: allows for retries + final response
3933
+ );
3934
+ logger.info(`[${this.getProviderName()}] External tool execution completed`);
3935
+ const successfulTools = toolResults.filter((r) => !r.error);
3936
+ const failedTools = toolResults.filter((r) => r.error);
3937
+ let summary = "";
3938
+ if (successfulTools.length > 0) {
3939
+ summary += `Successfully executed ${successfulTools.length} tool(s): ${successfulTools.map((t) => t.toolName).join(", ")}.
3940
+ `;
3941
+ }
3942
+ if (failedTools.length > 0) {
3943
+ summary += `Failed to execute ${failedTools.length} tool(s): ${failedTools.map((t) => t.toolName).join(", ")}.`;
3944
+ }
3945
+ if (toolResults.length === 0) {
3946
+ summary = "No external tools were needed for this request.";
3947
+ }
3948
+ logger.info(`[${this.getProviderName()}] Tool execution summary: ${summary}`);
3949
+ return {
3950
+ toolResults,
3951
+ summary,
3952
+ hasResults: successfulTools.length > 0
3953
+ };
3954
+ } catch (error) {
3955
+ const errorMsg = error instanceof Error ? error.message : String(error);
3956
+ logger.error(`[${this.getProviderName()}] Error in external tool execution: ${errorMsg}`);
3957
+ logCollector?.error(`Error executing external tools: ${errorMsg}`);
3958
+ return {
3959
+ toolResults,
3960
+ summary: `Error executing external tools: ${errorMsg}`,
3961
+ hasResults: false
3962
+ };
3963
+ }
3964
+ }
3726
3965
  /**
3727
3966
  * Generate text-based response for user question
3728
3967
  * This provides conversational text responses instead of component generation
@@ -3731,12 +3970,40 @@ var BaseLLM = class {
3731
3970
  * @param streamCallback - Optional callback function to receive text chunks as they stream
3732
3971
  * @param collections - Collection registry for executing database queries via database.execute
3733
3972
  * @param components - Optional list of available components for matching suggestions
3973
+ * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called
3734
3974
  */
3735
- async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components) {
3975
+ async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools) {
3736
3976
  const errors = [];
3737
3977
  logger.debug(`[${this.getProviderName()}] Starting text response generation`);
3738
3978
  logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
3739
3979
  try {
3980
+ let externalToolContext = "No external tools were used for this request.";
3981
+ if (externalTools && externalTools.length > 0) {
3982
+ logger.info(`[${this.getProviderName()}] Executing external tools...`);
3983
+ const toolExecution = await this.executeExternalTools(
3984
+ userPrompt,
3985
+ externalTools,
3986
+ apiKey,
3987
+ logCollector
3988
+ );
3989
+ if (toolExecution.hasResults) {
3990
+ const toolResultsText = toolExecution.toolResults.map((tr) => {
3991
+ if (tr.error) {
3992
+ return `**${tr.toolName}** (Failed): ${tr.error}`;
3993
+ }
3994
+ return `**${tr.toolName}** (Success):
3995
+ ${JSON.stringify(tr.result, null, 2)}`;
3996
+ }).join("\n\n");
3997
+ externalToolContext = `## External Tool Results
3998
+
3999
+ ${toolExecution.summary}
4000
+
4001
+ ${toolResultsText}`;
4002
+ logger.info(`[${this.getProviderName()}] External tools executed, results available`);
4003
+ } else {
4004
+ logger.info(`[${this.getProviderName()}] No external tools were needed`);
4005
+ }
4006
+ }
3740
4007
  const schemaDoc = schema.generateSchemaDocumentation();
3741
4008
  const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
3742
4009
  prompt: userPrompt,
@@ -3744,11 +4011,13 @@ var BaseLLM = class {
3744
4011
  topK: 1
3745
4012
  });
3746
4013
  logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
4014
+ logger.file("\n=============================\nexternal tool context:", externalToolContext);
3747
4015
  const prompts = await promptLoader.loadPrompts("text-response", {
3748
4016
  USER_PROMPT: userPrompt,
3749
4017
  CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
3750
4018
  SCHEMA_DOC: schemaDoc,
3751
- KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available."
4019
+ KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
4020
+ EXTERNAL_TOOL_CONTEXT: externalToolContext
3752
4021
  });
3753
4022
  logger.file("\n=============================\nsystem prompt:", prompts.system);
3754
4023
  logger.file("\n=============================\nuser prompt:", prompts.user);
@@ -4219,8 +4488,9 @@ ${errorMsg}
4219
4488
  * @param responseMode - 'component' for component generation (default), 'text' for text responses
4220
4489
  * @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)
4221
4490
  * @param collections - Collection registry for executing database queries (required for text mode)
4491
+ * @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called (only for text mode)
4222
4492
  */
4223
- async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) {
4493
+ async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) {
4224
4494
  const startTime = Date.now();
4225
4495
  logger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);
4226
4496
  if (responseMode === "text") {
@@ -4233,7 +4503,8 @@ ${errorMsg}
4233
4503
  conversationHistory,
4234
4504
  streamCallback,
4235
4505
  collections,
4236
- components
4506
+ components,
4507
+ externalTools
4237
4508
  );
4238
4509
  if (!textResponse.success) {
4239
4510
  const elapsedTime3 = Date.now() - startTime;
@@ -4379,7 +4650,7 @@ function getLLMProviders() {
4379
4650
  return DEFAULT_PROVIDERS;
4380
4651
  }
4381
4652
  }
4382
- var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
4653
+ var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
4383
4654
  logger.debug("[useAnthropicMethod] Initializing Anthropic Claude matching method");
4384
4655
  logger.debug(`[useAnthropicMethod] Response mode: ${responseMode}`);
4385
4656
  const msg = `Using Anthropic Claude ${responseMode === "text" ? "text response" : "matching"} method...`;
@@ -4391,11 +4662,11 @@ var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conver
4391
4662
  return { success: false, errors: [emptyMsg] };
4392
4663
  }
4393
4664
  logger.debug(`[useAnthropicMethod] Processing with ${components.length} components`);
4394
- const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
4665
+ const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
4395
4666
  logger.info(`[useAnthropicMethod] Successfully generated ${responseMode} using Anthropic`);
4396
4667
  return matchResult;
4397
4668
  };
4398
- var useGroqMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
4669
+ var useGroqMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
4399
4670
  logger.debug("[useGroqMethod] Initializing Groq LLM matching method");
4400
4671
  logger.debug(`[useGroqMethod] Response mode: ${responseMode}`);
4401
4672
  const msg = `Using Groq LLM ${responseMode === "text" ? "text response" : "matching"} method...`;
@@ -4408,14 +4679,14 @@ var useGroqMethod = async (prompt, components, apiKey, logCollector, conversatio
4408
4679
  return { success: false, errors: [emptyMsg] };
4409
4680
  }
4410
4681
  logger.debug(`[useGroqMethod] Processing with ${components.length} components`);
4411
- const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
4682
+ const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
4412
4683
  logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);
4413
4684
  return matchResult;
4414
4685
  };
4415
4686
  var getUserResponseFromCache = async (prompt) => {
4416
4687
  return false;
4417
4688
  };
4418
- var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
4689
+ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
4419
4690
  logger.debug(`[get_user_response] Starting user response generation for prompt: "${prompt.substring(0, 50)}..."`);
4420
4691
  logger.debug(`[get_user_response] Response mode: ${responseMode}`);
4421
4692
  logger.debug("[get_user_response] Checking cache for existing response");
@@ -4448,9 +4719,9 @@ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey,
4448
4719
  logCollector?.info(attemptMsg);
4449
4720
  let result;
4450
4721
  if (provider === "anthropic") {
4451
- result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
4722
+ result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
4452
4723
  } else if (provider === "groq") {
4453
- result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
4724
+ result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
4454
4725
  } else {
4455
4726
  logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);
4456
4727
  errors.push(`Unknown provider: ${provider}`);
@@ -4678,7 +4949,7 @@ var CONTEXT_CONFIG = {
4678
4949
  };
4679
4950
 
4680
4951
  // src/handlers/user-prompt-request.ts
4681
- var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections) => {
4952
+ var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools) => {
4682
4953
  const errors = [];
4683
4954
  logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
4684
4955
  const parseResult = UserPromptRequestMessageSchema.safeParse(data);
@@ -4758,7 +5029,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4758
5029
  conversationHistory,
4759
5030
  responseMode,
4760
5031
  streamCallback,
4761
- collections
5032
+ collections,
5033
+ externalTools
4762
5034
  );
4763
5035
  logCollector.info("User prompt request completed");
4764
5036
  const uiBlockId = existingUiBlockId;
@@ -4819,8 +5091,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4819
5091
  wsId
4820
5092
  };
4821
5093
  };
4822
- async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections) {
4823
- const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections);
5094
+ async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools) {
5095
+ const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools);
4824
5096
  sendDataResponse4(
4825
5097
  response.id || data.id,
4826
5098
  {
@@ -5894,6 +6166,183 @@ function sendResponse5(id, res, sendMessage, clientId) {
5894
6166
  sendMessage(response);
5895
6167
  }
5896
6168
 
6169
+ // src/handlers/bookmarks.ts
6170
+ async function handleBookmarksRequest(data, collections, sendMessage) {
6171
+ const executeCollection = async (collection, op, params) => {
6172
+ const handler = collections[collection]?.[op];
6173
+ if (!handler) {
6174
+ throw new Error(`Collection operation ${collection}.${op} not found`);
6175
+ }
6176
+ return await handler(params);
6177
+ };
6178
+ try {
6179
+ const request = BookmarksRequestMessageSchema.parse(data);
6180
+ const { id, payload, from } = request;
6181
+ const { operation, data: requestData } = payload;
6182
+ const bookmarkId = requestData?.id;
6183
+ const uiblock = requestData?.uiblock;
6184
+ switch (operation) {
6185
+ case "create":
6186
+ await handleCreate4(id, uiblock, executeCollection, sendMessage, from.id);
6187
+ break;
6188
+ case "update":
6189
+ await handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, from.id);
6190
+ break;
6191
+ case "delete":
6192
+ await handleDelete4(id, bookmarkId, executeCollection, sendMessage, from.id);
6193
+ break;
6194
+ case "getAll":
6195
+ await handleGetAll4(id, executeCollection, sendMessage, from.id);
6196
+ break;
6197
+ case "getOne":
6198
+ await handleGetOne4(id, bookmarkId, executeCollection, sendMessage, from.id);
6199
+ break;
6200
+ default:
6201
+ sendResponse6(id, {
6202
+ success: false,
6203
+ error: `Unknown operation: ${operation}`
6204
+ }, sendMessage, from.id);
6205
+ }
6206
+ } catch (error) {
6207
+ logger.error("Failed to handle bookmarks request:", error);
6208
+ sendResponse6(null, {
6209
+ success: false,
6210
+ error: error instanceof Error ? error.message : "Unknown error occurred"
6211
+ }, sendMessage);
6212
+ }
6213
+ }
6214
+ async function handleCreate4(id, uiblock, executeCollection, sendMessage, clientId) {
6215
+ if (!uiblock) {
6216
+ sendResponse6(id, {
6217
+ success: false,
6218
+ error: "UIBlock data is required"
6219
+ }, sendMessage, clientId);
6220
+ return;
6221
+ }
6222
+ try {
6223
+ const result = await executeCollection("bookmarks", "create", { uiblock });
6224
+ sendResponse6(id, {
6225
+ success: true,
6226
+ data: result.data,
6227
+ message: "Bookmark created successfully"
6228
+ }, sendMessage, clientId);
6229
+ logger.info(`Bookmark created: ID ${result.data.id}`);
6230
+ } catch (error) {
6231
+ sendResponse6(id, {
6232
+ success: false,
6233
+ error: error instanceof Error ? error.message : "Failed to create bookmark"
6234
+ }, sendMessage, clientId);
6235
+ }
6236
+ }
6237
+ async function handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, clientId) {
6238
+ if (!bookmarkId) {
6239
+ sendResponse6(id, {
6240
+ success: false,
6241
+ error: "Bookmark ID is required"
6242
+ }, sendMessage, clientId);
6243
+ return;
6244
+ }
6245
+ if (!uiblock) {
6246
+ sendResponse6(id, {
6247
+ success: false,
6248
+ error: "UIBlock data is required"
6249
+ }, sendMessage, clientId);
6250
+ return;
6251
+ }
6252
+ try {
6253
+ const result = await executeCollection("bookmarks", "update", { id: bookmarkId, uiblock });
6254
+ sendResponse6(id, {
6255
+ success: true,
6256
+ data: result.data,
6257
+ message: "Bookmark updated successfully"
6258
+ }, sendMessage, clientId);
6259
+ logger.info(`Bookmark updated: ID ${bookmarkId}`);
6260
+ } catch (error) {
6261
+ sendResponse6(id, {
6262
+ success: false,
6263
+ error: error instanceof Error ? error.message : "Failed to update bookmark"
6264
+ }, sendMessage, clientId);
6265
+ }
6266
+ }
6267
+ async function handleDelete4(id, bookmarkId, executeCollection, sendMessage, clientId) {
6268
+ if (!bookmarkId) {
6269
+ sendResponse6(id, {
6270
+ success: false,
6271
+ error: "Bookmark ID is required"
6272
+ }, sendMessage, clientId);
6273
+ return;
6274
+ }
6275
+ try {
6276
+ const result = await executeCollection("bookmarks", "delete", { id: bookmarkId });
6277
+ sendResponse6(id, {
6278
+ success: true,
6279
+ data: result.data,
6280
+ message: "Bookmark deleted successfully"
6281
+ }, sendMessage, clientId);
6282
+ logger.info(`Bookmark deleted: ID ${bookmarkId}`);
6283
+ } catch (error) {
6284
+ sendResponse6(id, {
6285
+ success: false,
6286
+ error: error instanceof Error ? error.message : "Failed to delete bookmark"
6287
+ }, sendMessage, clientId);
6288
+ }
6289
+ }
6290
+ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
6291
+ try {
6292
+ const result = await executeCollection("bookmarks", "getAll", {});
6293
+ sendResponse6(id, {
6294
+ success: true,
6295
+ data: result.data,
6296
+ count: result.count,
6297
+ message: `Retrieved ${result.count} bookmarks`
6298
+ }, sendMessage, clientId);
6299
+ logger.info(`Retrieved all bookmarks (count: ${result.count})`);
6300
+ } catch (error) {
6301
+ sendResponse6(id, {
6302
+ success: false,
6303
+ error: error instanceof Error ? error.message : "Failed to get bookmarks"
6304
+ }, sendMessage, clientId);
6305
+ }
6306
+ }
6307
+ async function handleGetOne4(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", "getOne", { id: bookmarkId });
6317
+ sendResponse6(id, {
6318
+ success: true,
6319
+ data: result.data,
6320
+ message: `Retrieved bookmark ID ${bookmarkId}`
6321
+ }, sendMessage, clientId);
6322
+ logger.info(`Retrieved bookmark: ID ${bookmarkId}`);
6323
+ } catch (error) {
6324
+ sendResponse6(id, {
6325
+ success: false,
6326
+ error: error instanceof Error ? error.message : "Failed to get bookmark"
6327
+ }, sendMessage, clientId);
6328
+ }
6329
+ }
6330
+ function sendResponse6(id, res, sendMessage, clientId) {
6331
+ const response = {
6332
+ id: id || "unknown",
6333
+ type: "BOOKMARKS_RES",
6334
+ from: { type: "data-agent" },
6335
+ to: {
6336
+ type: "user",
6337
+ id: clientId
6338
+ },
6339
+ payload: {
6340
+ ...res
6341
+ }
6342
+ };
6343
+ sendMessage(response);
6344
+ }
6345
+
5897
6346
  // src/auth/user-manager.ts
5898
6347
  import fs5 from "fs";
5899
6348
  import path4 from "path";
@@ -6718,6 +7167,7 @@ var SuperatomSDK = class {
6718
7167
  this.maxReconnectAttempts = 5;
6719
7168
  this.collections = {};
6720
7169
  this.components = [];
7170
+ this.tools = [];
6721
7171
  if (config.logLevel) {
6722
7172
  logger.setLogLevel(config.logLevel);
6723
7173
  }
@@ -6873,7 +7323,7 @@ var SuperatomSDK = class {
6873
7323
  });
6874
7324
  break;
6875
7325
  case "USER_PROMPT_REQ":
6876
- handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections).catch((error) => {
7326
+ handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
6877
7327
  logger.error("Failed to handle user prompt request:", error);
6878
7328
  });
6879
7329
  break;
@@ -6907,6 +7357,11 @@ var SuperatomSDK = class {
6907
7357
  logger.error("Failed to handle reports request:", error);
6908
7358
  });
6909
7359
  break;
7360
+ case "BOOKMARKS":
7361
+ handleBookmarksRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7362
+ logger.error("Failed to handle bookmarks request:", error);
7363
+ });
7364
+ break;
6910
7365
  default:
6911
7366
  const handler = this.messageTypeHandlers.get(message.type);
6912
7367
  if (handler) {
@@ -7013,6 +7468,19 @@ var SuperatomSDK = class {
7013
7468
  storeComponents(components) {
7014
7469
  this.components = components;
7015
7470
  }
7471
+ /**
7472
+ * Set tools for the SDK instance
7473
+ */
7474
+ setTools(tools) {
7475
+ this.tools = tools;
7476
+ logger.info(`Tools stored in SDK: ${tools.length} tools`);
7477
+ }
7478
+ /**
7479
+ * Get the stored tools
7480
+ */
7481
+ getTools() {
7482
+ return this.tools;
7483
+ }
7016
7484
  };
7017
7485
  export {
7018
7486
  CONTEXT_CONFIG,