@superatomai/sdk-node 0.0.10 → 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/README.md +942 -942
- package/dist/index.d.mts +30 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +549 -122
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +549 -122
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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"));
|
|
@@ -1012,6 +1039,7 @@ var Thread = class {
|
|
|
1012
1039
|
let assistantResponse = "";
|
|
1013
1040
|
const hasComponent = metadata && Object.keys(metadata).length > 0 && metadata.type;
|
|
1014
1041
|
const hasTextResponse = textResponse && textResponse.trim().length > 0;
|
|
1042
|
+
const responseParts = [];
|
|
1015
1043
|
if (hasComponent) {
|
|
1016
1044
|
const parts = [];
|
|
1017
1045
|
if (metadata.type) {
|
|
@@ -1020,21 +1048,19 @@ var Thread = class {
|
|
|
1020
1048
|
if (metadata.name) {
|
|
1021
1049
|
parts.push(`Name: ${metadata.name}`);
|
|
1022
1050
|
}
|
|
1023
|
-
if (metadata.
|
|
1024
|
-
parts.push(`
|
|
1025
|
-
}
|
|
1026
|
-
if (metadata.props?.query) {
|
|
1027
|
-
const query = metadata.props.query;
|
|
1028
|
-
const truncatedQuery = query.length > 200 ? query.substring(0, 200) + "..." : query;
|
|
1029
|
-
parts.push(`Query: ${truncatedQuery}`);
|
|
1051
|
+
if (metadata.description) {
|
|
1052
|
+
parts.push(`Description: ${metadata.description}`);
|
|
1030
1053
|
}
|
|
1031
|
-
if (metadata.props
|
|
1032
|
-
|
|
1033
|
-
parts.push(`Multi-component with: ${componentTypes}`);
|
|
1054
|
+
if (metadata.props) {
|
|
1055
|
+
parts.push(`Props: ${JSON.stringify(metadata.props)}`);
|
|
1034
1056
|
}
|
|
1035
|
-
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1057
|
+
responseParts.push(parts.join("\n"));
|
|
1058
|
+
}
|
|
1059
|
+
if (hasTextResponse) {
|
|
1060
|
+
responseParts.push(textResponse);
|
|
1061
|
+
}
|
|
1062
|
+
if (responseParts.length > 0) {
|
|
1063
|
+
assistantResponse = responseParts.join("\n");
|
|
1038
1064
|
} else {
|
|
1039
1065
|
assistantResponse = "No response generated";
|
|
1040
1066
|
}
|
|
@@ -2386,18 +2412,16 @@ Your job is to:
|
|
|
2386
2412
|
1. **Parse the component suggestions** from the text response (format: 1:component_type : reasoning)
|
|
2387
2413
|
2. **Match each suggestion with an actual component** from the available list
|
|
2388
2414
|
3. **Generate proper props** for each matched component to **visualize the analysis results** that were already fetched
|
|
2389
|
-
4. **
|
|
2415
|
+
4. **Generate title and description** for the dashboard container
|
|
2390
2416
|
5. **Generate intelligent follow-up questions (actions)** that the user might naturally ask next based on the data analysis
|
|
2391
2417
|
|
|
2392
2418
|
**CRITICAL GOAL**: Create dashboard components that display the **same data that was already analyzed** - NOT new data. The queries already ran and got results. You're just creating different visualizations of those results.
|
|
2393
2419
|
|
|
2394
|
-
**APPROACH**: First match all the components suggested in the text response, THEN find the layout that best fits those components.
|
|
2395
|
-
|
|
2396
2420
|
## Available Components
|
|
2397
2421
|
|
|
2398
2422
|
{{AVAILABLE_COMPONENTS}}
|
|
2399
2423
|
|
|
2400
|
-
## Component Matching Rules
|
|
2424
|
+
## Component Matching Rules
|
|
2401
2425
|
For each component suggestion (c1, c2, c3, etc.) from the text response:
|
|
2402
2426
|
|
|
2403
2427
|
1. **Match by type**: Find components whose \`type\` matches the suggested component type
|
|
@@ -2406,23 +2430,10 @@ For each component suggestion (c1, c2, c3, etc.) from the text response:
|
|
|
2406
2430
|
- Best fit for the data being visualized
|
|
2407
2431
|
3. **Fallback**: If no exact type match, find the closest alternative
|
|
2408
2432
|
|
|
2409
|
-
##
|
|
2410
|
-
|
|
2411
|
-
**
|
|
2412
|
-
|
|
2413
|
-
1. **Find layout components** by looking for components with \`type: "DashboardLayout"\` in the available components list
|
|
2414
|
-
2. **Read each layout's description** to understand:
|
|
2415
|
-
- What structure it provides
|
|
2416
|
-
- When it's best used (e.g., comprehensive analysis vs focused analysis)
|
|
2417
|
-
- The number and types of components it can accommodate
|
|
2418
|
-
3. **Select the best layout** based on:
|
|
2419
|
-
- Which layout can best display ALL the matched components
|
|
2420
|
-
- The layout's capacity (how many components it supports)
|
|
2421
|
-
- The types of matched components (KPI, charts, tables, etc.)
|
|
2422
|
-
- The user question and data complexity
|
|
2423
|
-
4. **If no specific layout fits**, fall back to "MultiComponentContainer" as the default layout
|
|
2424
|
-
|
|
2425
|
-
**IMPORTANT:** The layout should be chosen to FIT the matched components, not the other way around. Don't force components to fit a layout - find a layout that accommodates your components.
|
|
2433
|
+
## Dashboard Container
|
|
2434
|
+
All matched components will be placed in the default **MultiComponentContainer** layout. Your job is to:
|
|
2435
|
+
1. **Generate a clear title** for the dashboard that summarizes what it shows
|
|
2436
|
+
2. **Generate a brief description** explaining the dashboard's purpose and scope
|
|
2426
2437
|
|
|
2427
2438
|
## Props Generation Rules
|
|
2428
2439
|
|
|
@@ -2536,8 +2547,8 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
2536
2547
|
|
|
2537
2548
|
\`\`\`json
|
|
2538
2549
|
{
|
|
2539
|
-
"
|
|
2540
|
-
"
|
|
2550
|
+
"layoutTitle": "Clear, concise title for the overall dashboard/layout (5-10 words)",
|
|
2551
|
+
"layoutDescription": "Brief description of what the dashboard shows and its purpose (1-2 sentences)",
|
|
2541
2552
|
"matchedComponents": [
|
|
2542
2553
|
{
|
|
2543
2554
|
"componentId": "id_from_available_list",
|
|
@@ -2567,17 +2578,14 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
2567
2578
|
\`\`\`
|
|
2568
2579
|
|
|
2569
2580
|
**CRITICAL:**
|
|
2570
|
-
- \`matchedComponents\` MUST include ALL components suggested in the text response
|
|
2571
|
-
- \`
|
|
2572
|
-
-
|
|
2573
|
-
|
|
2574
|
-
-
|
|
2575
|
-
- Why this layout is the best fit for displaying these specific matched components
|
|
2576
|
-
- What makes this layout appropriate for the component types and count
|
|
2577
|
-
- The layout selection happens AFTER component matching - don't force components to fit a pre-selected layout
|
|
2581
|
+
- \`matchedComponents\` MUST include ALL components suggested in the text response
|
|
2582
|
+
- \`layoutTitle\` MUST be a clear, concise title (5-10 words) that summarizes what the entire dashboard shows
|
|
2583
|
+
- Examples: "Sales Performance Overview", "Customer Metrics Analysis", "Product Category Breakdown"
|
|
2584
|
+
- \`layoutDescription\` MUST be a brief description (1-2 sentences) explaining the purpose and scope of the dashboard
|
|
2585
|
+
- Should describe what insights the dashboard provides and what data it shows
|
|
2578
2586
|
- \`actions\` MUST be an array of 4-5 intelligent follow-up questions based on the analysis
|
|
2579
2587
|
- Return ONLY valid JSON (no markdown code blocks, no text before/after)
|
|
2580
|
-
- Generate complete props for each component
|
|
2588
|
+
- Generate complete props for each component including query, title, description, and config
|
|
2581
2589
|
|
|
2582
2590
|
|
|
2583
2591
|
`,
|
|
@@ -2629,6 +2637,71 @@ Format your response as a JSON object with this structure:
|
|
|
2629
2637
|
}
|
|
2630
2638
|
|
|
2631
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
|
+
`
|
|
2632
2705
|
}
|
|
2633
2706
|
};
|
|
2634
2707
|
|
|
@@ -3673,12 +3746,14 @@ var BaseLLM = class {
|
|
|
3673
3746
|
/**
|
|
3674
3747
|
* Match components from text response suggestions and generate follow-up questions
|
|
3675
3748
|
* Takes a text response with component suggestions (c1:type format) and matches with available components
|
|
3676
|
-
* Also generates intelligent follow-up questions (actions) based on the analysis
|
|
3749
|
+
* Also generates title, description, and intelligent follow-up questions (actions) based on the analysis
|
|
3750
|
+
* All components are placed in a default MultiComponentContainer layout
|
|
3677
3751
|
* @param textResponse - The text response containing component suggestions
|
|
3678
3752
|
* @param components - List of available components
|
|
3679
3753
|
* @param apiKey - Optional API key
|
|
3680
3754
|
* @param logCollector - Optional log collector
|
|
3681
|
-
* @
|
|
3755
|
+
* @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
|
|
3756
|
+
* @returns Object containing matched components, layout title/description, and follow-up actions
|
|
3682
3757
|
*/
|
|
3683
3758
|
async matchComponentsFromTextResponse(textResponse, components, apiKey, logCollector) {
|
|
3684
3759
|
try {
|
|
@@ -3721,24 +3796,17 @@ var BaseLLM = class {
|
|
|
3721
3796
|
);
|
|
3722
3797
|
logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
|
|
3723
3798
|
const matchedComponents = result.matchedComponents || [];
|
|
3724
|
-
const
|
|
3725
|
-
const
|
|
3799
|
+
const layoutTitle = result.layoutTitle || "Dashboard";
|
|
3800
|
+
const layoutDescription = result.layoutDescription || "Multi-component dashboard";
|
|
3726
3801
|
const rawActions = result.actions || [];
|
|
3727
3802
|
const actions = convertQuestionsToActions(rawActions);
|
|
3728
|
-
let selectedLayoutComponent = null;
|
|
3729
|
-
if (selectedLayoutId) {
|
|
3730
|
-
selectedLayoutComponent = components.find((c) => c.id === selectedLayoutId) || null;
|
|
3731
|
-
if (!selectedLayoutComponent) {
|
|
3732
|
-
logger.warn(`[${this.getProviderName()}] Layout component ${selectedLayoutId} not found in available components`);
|
|
3733
|
-
}
|
|
3734
|
-
}
|
|
3735
3803
|
logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
|
|
3736
|
-
logger.info(`[${this.getProviderName()}]
|
|
3737
|
-
logger.info(`[${this.getProviderName()}] Layout
|
|
3804
|
+
logger.info(`[${this.getProviderName()}] Layout title: "${layoutTitle}"`);
|
|
3805
|
+
logger.info(`[${this.getProviderName()}] Layout description: "${layoutDescription}"`);
|
|
3738
3806
|
logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
|
|
3739
3807
|
if (matchedComponents.length > 0) {
|
|
3740
|
-
logCollector?.info(`Matched ${matchedComponents.length} components for visualization
|
|
3741
|
-
logCollector?.info(`
|
|
3808
|
+
logCollector?.info(`Matched ${matchedComponents.length} components for visualization`);
|
|
3809
|
+
logCollector?.info(`Dashboard: "${layoutTitle}"`);
|
|
3742
3810
|
matchedComponents.forEach((comp, idx) => {
|
|
3743
3811
|
logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
|
|
3744
3812
|
if (comp.props?.query) {
|
|
@@ -3772,9 +3840,8 @@ var BaseLLM = class {
|
|
|
3772
3840
|
}).filter(Boolean);
|
|
3773
3841
|
return {
|
|
3774
3842
|
components: finalComponents,
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
layoutReasoning,
|
|
3843
|
+
layoutTitle,
|
|
3844
|
+
layoutDescription,
|
|
3778
3845
|
actions
|
|
3779
3846
|
};
|
|
3780
3847
|
} catch (error) {
|
|
@@ -3783,13 +3850,158 @@ var BaseLLM = class {
|
|
|
3783
3850
|
logCollector?.error(`Failed to match components: ${errorMsg}`);
|
|
3784
3851
|
return {
|
|
3785
3852
|
components: [],
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
layoutReasoning: "Failed to match components due to parsing error",
|
|
3853
|
+
layoutTitle: "Dashboard",
|
|
3854
|
+
layoutDescription: "Failed to generate dashboard",
|
|
3789
3855
|
actions: []
|
|
3790
3856
|
};
|
|
3791
3857
|
}
|
|
3792
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
|
+
}
|
|
3793
4005
|
/**
|
|
3794
4006
|
* Generate text-based response for user question
|
|
3795
4007
|
* This provides conversational text responses instead of component generation
|
|
@@ -3798,12 +4010,40 @@ var BaseLLM = class {
|
|
|
3798
4010
|
* @param streamCallback - Optional callback function to receive text chunks as they stream
|
|
3799
4011
|
* @param collections - Collection registry for executing database queries via database.execute
|
|
3800
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
|
|
3801
4014
|
*/
|
|
3802
|
-
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components) {
|
|
4015
|
+
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools) {
|
|
3803
4016
|
const errors = [];
|
|
3804
4017
|
logger.debug(`[${this.getProviderName()}] Starting text response generation`);
|
|
3805
4018
|
logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
|
|
3806
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
|
+
}
|
|
3807
4047
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
3808
4048
|
const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
|
|
3809
4049
|
prompt: userPrompt,
|
|
@@ -3811,11 +4051,13 @@ var BaseLLM = class {
|
|
|
3811
4051
|
topK: 1
|
|
3812
4052
|
});
|
|
3813
4053
|
logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
|
|
4054
|
+
logger.file("\n=============================\nexternal tool context:", externalToolContext);
|
|
3814
4055
|
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
3815
4056
|
USER_PROMPT: userPrompt,
|
|
3816
4057
|
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
3817
4058
|
SCHEMA_DOC: schemaDoc,
|
|
3818
|
-
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
|
|
3819
4061
|
});
|
|
3820
4062
|
logger.file("\n=============================\nsystem prompt:", prompts.system);
|
|
3821
4063
|
logger.file("\n=============================\nuser prompt:", prompts.user);
|
|
@@ -4029,9 +4271,12 @@ ${errorMsg}
|
|
|
4029
4271
|
textLength: textResponse.length
|
|
4030
4272
|
}
|
|
4031
4273
|
);
|
|
4274
|
+
if (wrappedStreamCallback && components && components.length > 0) {
|
|
4275
|
+
wrappedStreamCallback("__TEXT_COMPLETE__COMPONENT_GENERATION_START__");
|
|
4276
|
+
}
|
|
4032
4277
|
let matchedComponents = [];
|
|
4033
|
-
let
|
|
4034
|
-
let
|
|
4278
|
+
let layoutTitle = "Dashboard";
|
|
4279
|
+
let layoutDescription = "Multi-component dashboard";
|
|
4035
4280
|
let actions = [];
|
|
4036
4281
|
if (components && components.length > 0) {
|
|
4037
4282
|
logger.info(`[${this.getProviderName()}] Matching components from text response...`);
|
|
@@ -4042,46 +4287,30 @@ ${errorMsg}
|
|
|
4042
4287
|
logCollector
|
|
4043
4288
|
);
|
|
4044
4289
|
matchedComponents = matchResult.components;
|
|
4045
|
-
|
|
4046
|
-
|
|
4290
|
+
layoutTitle = matchResult.layoutTitle;
|
|
4291
|
+
layoutDescription = matchResult.layoutDescription;
|
|
4047
4292
|
actions = matchResult.actions;
|
|
4048
4293
|
}
|
|
4049
4294
|
let container_componet = null;
|
|
4050
4295
|
if (matchedComponents.length > 0) {
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
}
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
}
|
|
4068
|
-
|
|
4069
|
-
id: `multi_container_${Date.now()}`,
|
|
4070
|
-
name: "MultiComponentContainer",
|
|
4071
|
-
type: "Container",
|
|
4072
|
-
description: layoutReasoning,
|
|
4073
|
-
category: "dynamic",
|
|
4074
|
-
keywords: ["dashboard", "layout", "container"],
|
|
4075
|
-
props: {
|
|
4076
|
-
config: {
|
|
4077
|
-
components: matchedComponents
|
|
4078
|
-
},
|
|
4079
|
-
actions
|
|
4080
|
-
}
|
|
4081
|
-
};
|
|
4082
|
-
logger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions`);
|
|
4083
|
-
logCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
|
|
4084
|
-
}
|
|
4296
|
+
container_componet = {
|
|
4297
|
+
id: `multi_container_${Date.now()}`,
|
|
4298
|
+
name: "MultiComponentContainer",
|
|
4299
|
+
type: "Container",
|
|
4300
|
+
description: layoutDescription,
|
|
4301
|
+
category: "dynamic",
|
|
4302
|
+
keywords: ["dashboard", "layout", "container"],
|
|
4303
|
+
props: {
|
|
4304
|
+
config: {
|
|
4305
|
+
components: matchedComponents,
|
|
4306
|
+
title: layoutTitle,
|
|
4307
|
+
description: layoutDescription
|
|
4308
|
+
},
|
|
4309
|
+
actions
|
|
4310
|
+
}
|
|
4311
|
+
};
|
|
4312
|
+
logger.info(`[${this.getProviderName()}] Created MultiComponentContainer: "${layoutTitle}" with ${matchedComponents.length} components and ${actions.length} actions`);
|
|
4313
|
+
logCollector?.info(`Created dashboard: "${layoutTitle}" with ${matchedComponents.length} components and ${actions.length} actions`);
|
|
4085
4314
|
}
|
|
4086
4315
|
return {
|
|
4087
4316
|
success: true,
|
|
@@ -4089,7 +4318,6 @@ ${errorMsg}
|
|
|
4089
4318
|
text: textResponse,
|
|
4090
4319
|
matchedComponents,
|
|
4091
4320
|
component: container_componet,
|
|
4092
|
-
layoutReasoning,
|
|
4093
4321
|
actions,
|
|
4094
4322
|
method: `${this.getProviderName()}-text-response`
|
|
4095
4323
|
},
|
|
@@ -4300,8 +4528,9 @@ ${errorMsg}
|
|
|
4300
4528
|
* @param responseMode - 'component' for component generation (default), 'text' for text responses
|
|
4301
4529
|
* @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)
|
|
4302
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)
|
|
4303
4532
|
*/
|
|
4304
|
-
async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) {
|
|
4533
|
+
async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) {
|
|
4305
4534
|
const startTime = Date.now();
|
|
4306
4535
|
logger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);
|
|
4307
4536
|
if (responseMode === "text") {
|
|
@@ -4314,7 +4543,8 @@ ${errorMsg}
|
|
|
4314
4543
|
conversationHistory,
|
|
4315
4544
|
streamCallback,
|
|
4316
4545
|
collections,
|
|
4317
|
-
components
|
|
4546
|
+
components,
|
|
4547
|
+
externalTools
|
|
4318
4548
|
);
|
|
4319
4549
|
if (!textResponse.success) {
|
|
4320
4550
|
const elapsedTime3 = Date.now() - startTime;
|
|
@@ -4460,7 +4690,7 @@ function getLLMProviders() {
|
|
|
4460
4690
|
return DEFAULT_PROVIDERS;
|
|
4461
4691
|
}
|
|
4462
4692
|
}
|
|
4463
|
-
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) => {
|
|
4464
4694
|
logger.debug("[useAnthropicMethod] Initializing Anthropic Claude matching method");
|
|
4465
4695
|
logger.debug(`[useAnthropicMethod] Response mode: ${responseMode}`);
|
|
4466
4696
|
const msg = `Using Anthropic Claude ${responseMode === "text" ? "text response" : "matching"} method...`;
|
|
@@ -4472,11 +4702,11 @@ var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conver
|
|
|
4472
4702
|
return { success: false, errors: [emptyMsg] };
|
|
4473
4703
|
}
|
|
4474
4704
|
logger.debug(`[useAnthropicMethod] Processing with ${components.length} components`);
|
|
4475
|
-
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);
|
|
4476
4706
|
logger.info(`[useAnthropicMethod] Successfully generated ${responseMode} using Anthropic`);
|
|
4477
4707
|
return matchResult;
|
|
4478
4708
|
};
|
|
4479
|
-
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) => {
|
|
4480
4710
|
logger.debug("[useGroqMethod] Initializing Groq LLM matching method");
|
|
4481
4711
|
logger.debug(`[useGroqMethod] Response mode: ${responseMode}`);
|
|
4482
4712
|
const msg = `Using Groq LLM ${responseMode === "text" ? "text response" : "matching"} method...`;
|
|
@@ -4489,14 +4719,14 @@ var useGroqMethod = async (prompt, components, apiKey, logCollector, conversatio
|
|
|
4489
4719
|
return { success: false, errors: [emptyMsg] };
|
|
4490
4720
|
}
|
|
4491
4721
|
logger.debug(`[useGroqMethod] Processing with ${components.length} components`);
|
|
4492
|
-
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);
|
|
4493
4723
|
logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);
|
|
4494
4724
|
return matchResult;
|
|
4495
4725
|
};
|
|
4496
4726
|
var getUserResponseFromCache = async (prompt) => {
|
|
4497
4727
|
return false;
|
|
4498
4728
|
};
|
|
4499
|
-
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) => {
|
|
4500
4730
|
logger.debug(`[get_user_response] Starting user response generation for prompt: "${prompt.substring(0, 50)}..."`);
|
|
4501
4731
|
logger.debug(`[get_user_response] Response mode: ${responseMode}`);
|
|
4502
4732
|
logger.debug("[get_user_response] Checking cache for existing response");
|
|
@@ -4529,9 +4759,9 @@ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey,
|
|
|
4529
4759
|
logCollector?.info(attemptMsg);
|
|
4530
4760
|
let result;
|
|
4531
4761
|
if (provider === "anthropic") {
|
|
4532
|
-
result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
|
|
4762
|
+
result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
|
|
4533
4763
|
} else if (provider === "groq") {
|
|
4534
|
-
result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
|
|
4764
|
+
result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
|
|
4535
4765
|
} else {
|
|
4536
4766
|
logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);
|
|
4537
4767
|
errors.push(`Unknown provider: ${provider}`);
|
|
@@ -4755,11 +4985,11 @@ var CONTEXT_CONFIG = {
|
|
|
4755
4985
|
* Set to 0 to disable conversation history
|
|
4756
4986
|
* Higher values provide more context but may increase token usage
|
|
4757
4987
|
*/
|
|
4758
|
-
MAX_CONVERSATION_CONTEXT_BLOCKS:
|
|
4988
|
+
MAX_CONVERSATION_CONTEXT_BLOCKS: 3
|
|
4759
4989
|
};
|
|
4760
4990
|
|
|
4761
4991
|
// src/handlers/user-prompt-request.ts
|
|
4762
|
-
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) => {
|
|
4763
4993
|
const errors = [];
|
|
4764
4994
|
logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
|
|
4765
4995
|
const parseResult = UserPromptRequestMessageSchema.safeParse(data);
|
|
@@ -4839,7 +5069,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
4839
5069
|
conversationHistory,
|
|
4840
5070
|
responseMode,
|
|
4841
5071
|
streamCallback,
|
|
4842
|
-
collections
|
|
5072
|
+
collections,
|
|
5073
|
+
externalTools
|
|
4843
5074
|
);
|
|
4844
5075
|
logCollector.info("User prompt request completed");
|
|
4845
5076
|
const uiBlockId = existingUiBlockId;
|
|
@@ -4900,8 +5131,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
4900
5131
|
wsId
|
|
4901
5132
|
};
|
|
4902
5133
|
};
|
|
4903
|
-
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections) {
|
|
4904
|
-
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);
|
|
4905
5136
|
sendDataResponse4(
|
|
4906
5137
|
response.id || data.id,
|
|
4907
5138
|
{
|
|
@@ -5975,6 +6206,183 @@ function sendResponse5(id, res, sendMessage, clientId) {
|
|
|
5975
6206
|
sendMessage(response);
|
|
5976
6207
|
}
|
|
5977
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
|
+
|
|
5978
6386
|
// src/auth/user-manager.ts
|
|
5979
6387
|
var import_fs4 = __toESM(require("fs"));
|
|
5980
6388
|
var import_path3 = __toESM(require("path"));
|
|
@@ -6799,6 +7207,7 @@ var SuperatomSDK = class {
|
|
|
6799
7207
|
this.maxReconnectAttempts = 5;
|
|
6800
7208
|
this.collections = {};
|
|
6801
7209
|
this.components = [];
|
|
7210
|
+
this.tools = [];
|
|
6802
7211
|
if (config.logLevel) {
|
|
6803
7212
|
logger.setLogLevel(config.logLevel);
|
|
6804
7213
|
}
|
|
@@ -6954,7 +7363,7 @@ var SuperatomSDK = class {
|
|
|
6954
7363
|
});
|
|
6955
7364
|
break;
|
|
6956
7365
|
case "USER_PROMPT_REQ":
|
|
6957
|
-
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) => {
|
|
6958
7367
|
logger.error("Failed to handle user prompt request:", error);
|
|
6959
7368
|
});
|
|
6960
7369
|
break;
|
|
@@ -6988,6 +7397,11 @@ var SuperatomSDK = class {
|
|
|
6988
7397
|
logger.error("Failed to handle reports request:", error);
|
|
6989
7398
|
});
|
|
6990
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;
|
|
6991
7405
|
default:
|
|
6992
7406
|
const handler = this.messageTypeHandlers.get(message.type);
|
|
6993
7407
|
if (handler) {
|
|
@@ -7094,6 +7508,19 @@ var SuperatomSDK = class {
|
|
|
7094
7508
|
storeComponents(components) {
|
|
7095
7509
|
this.components = components;
|
|
7096
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
|
+
}
|
|
7097
7524
|
};
|
|
7098
7525
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7099
7526
|
0 && (module.exports = {
|