@superatomai/sdk-node 0.0.11 → 0.0.13
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.d.mts +30 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +608 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +608 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
|
@@ -3616,13 +3708,14 @@ var BaseLLM = class {
|
|
|
3616
3708
|
* Takes a text response with component suggestions (c1:type format) and matches with available components
|
|
3617
3709
|
* Also generates title, description, and intelligent follow-up questions (actions) based on the analysis
|
|
3618
3710
|
* All components are placed in a default MultiComponentContainer layout
|
|
3619
|
-
* @param
|
|
3711
|
+
* @param analysisContent - The text response containing component suggestions
|
|
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
|
-
async
|
|
3718
|
+
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback) {
|
|
3626
3719
|
try {
|
|
3627
3720
|
logger.debug(`[${this.getProviderName()}] Starting component matching from text response`);
|
|
3628
3721
|
let availableComponentsText = "No components available";
|
|
@@ -3639,14 +3732,94 @@ var BaseLLM = class {
|
|
|
3639
3732
|
}).join("\n\n");
|
|
3640
3733
|
}
|
|
3641
3734
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
3735
|
+
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
3642
3736
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
3643
|
-
|
|
3737
|
+
ANALYSIS_CONTENT: analysisContent,
|
|
3644
3738
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
3645
3739
|
SCHEMA_DOC: schemaDoc
|
|
3646
3740
|
});
|
|
3647
3741
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
3648
3742
|
logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
|
|
3649
3743
|
logCollector?.info("Matching components from text response...");
|
|
3744
|
+
let fullResponseText = "";
|
|
3745
|
+
let answerComponentExtracted = false;
|
|
3746
|
+
const answerCallback = componentStreamCallback;
|
|
3747
|
+
const partialCallback = answerCallback ? (chunk) => {
|
|
3748
|
+
fullResponseText += chunk;
|
|
3749
|
+
if (!answerComponentExtracted && answerCallback) {
|
|
3750
|
+
const hasAnswerComponentMatch = fullResponseText.match(/"hasAnswerComponent"\s*:\s*(true|false)/);
|
|
3751
|
+
if (!hasAnswerComponentMatch || hasAnswerComponentMatch[1] !== "true") {
|
|
3752
|
+
return;
|
|
3753
|
+
}
|
|
3754
|
+
const answerComponentStartMatch = fullResponseText.match(/"answerComponent"\s*:\s*\{/);
|
|
3755
|
+
if (!answerComponentStartMatch) {
|
|
3756
|
+
return;
|
|
3757
|
+
}
|
|
3758
|
+
const startPos = answerComponentStartMatch.index + answerComponentStartMatch[0].length - 1;
|
|
3759
|
+
let braceDepth = 0;
|
|
3760
|
+
let inString = false;
|
|
3761
|
+
let escapeNext = false;
|
|
3762
|
+
let endPos = -1;
|
|
3763
|
+
for (let i = startPos; i < fullResponseText.length; i++) {
|
|
3764
|
+
const char = fullResponseText[i];
|
|
3765
|
+
if (escapeNext) {
|
|
3766
|
+
escapeNext = false;
|
|
3767
|
+
continue;
|
|
3768
|
+
}
|
|
3769
|
+
if (char === "\\") {
|
|
3770
|
+
escapeNext = true;
|
|
3771
|
+
continue;
|
|
3772
|
+
}
|
|
3773
|
+
if (char === '"') {
|
|
3774
|
+
inString = !inString;
|
|
3775
|
+
continue;
|
|
3776
|
+
}
|
|
3777
|
+
if (!inString) {
|
|
3778
|
+
if (char === "{") {
|
|
3779
|
+
braceDepth++;
|
|
3780
|
+
} else if (char === "}") {
|
|
3781
|
+
braceDepth--;
|
|
3782
|
+
if (braceDepth === 0) {
|
|
3783
|
+
endPos = i + 1;
|
|
3784
|
+
break;
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
if (endPos > startPos) {
|
|
3790
|
+
const answerComponentString = fullResponseText.substring(startPos, endPos);
|
|
3791
|
+
try {
|
|
3792
|
+
const answerComponentData = JSON.parse(answerComponentString);
|
|
3793
|
+
if (answerComponentData && answerComponentData.componentId) {
|
|
3794
|
+
const originalComponent = components.find((c) => c.id === answerComponentData.componentId);
|
|
3795
|
+
if (originalComponent) {
|
|
3796
|
+
const answerComponent = {
|
|
3797
|
+
...originalComponent,
|
|
3798
|
+
props: {
|
|
3799
|
+
...originalComponent.props,
|
|
3800
|
+
...answerComponentData.props
|
|
3801
|
+
}
|
|
3802
|
+
};
|
|
3803
|
+
const streamTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
3804
|
+
logger.info(`[${this.getProviderName()}] \u2713 [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type}) - STREAMING TO FRONTEND NOW`);
|
|
3805
|
+
logCollector?.info(`\u2713 Answer component: ${answerComponent.name} (${answerComponent.type}) - streaming to frontend at ${streamTime}`);
|
|
3806
|
+
if (answerComponentData.props?.query) {
|
|
3807
|
+
logCollector?.logQuery(
|
|
3808
|
+
"Answer component query",
|
|
3809
|
+
answerComponentData.props.query,
|
|
3810
|
+
{ componentName: answerComponent.name, componentType: answerComponent.type, reasoning: answerComponentData.reasoning }
|
|
3811
|
+
);
|
|
3812
|
+
}
|
|
3813
|
+
answerCallback(answerComponent);
|
|
3814
|
+
answerComponentExtracted = true;
|
|
3815
|
+
}
|
|
3816
|
+
}
|
|
3817
|
+
} catch (e) {
|
|
3818
|
+
logger.debug(`[${this.getProviderName()}] Partial answerComponent parse failed, waiting for more data...`);
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3822
|
+
} : void 0;
|
|
3650
3823
|
const result = await LLM.stream(
|
|
3651
3824
|
{
|
|
3652
3825
|
sys: prompts.system,
|
|
@@ -3656,23 +3829,54 @@ var BaseLLM = class {
|
|
|
3656
3829
|
model: this.model,
|
|
3657
3830
|
maxTokens: 3e3,
|
|
3658
3831
|
temperature: 0.2,
|
|
3659
|
-
apiKey: this.getApiKey(apiKey)
|
|
3832
|
+
apiKey: this.getApiKey(apiKey),
|
|
3833
|
+
partial: partialCallback
|
|
3660
3834
|
},
|
|
3661
3835
|
true
|
|
3662
3836
|
// Parse as JSON
|
|
3663
3837
|
);
|
|
3664
3838
|
logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
|
|
3839
|
+
const componentSuggestionPattern = /c\d+:(\w+)\s*:\s*(.+)/g;
|
|
3840
|
+
const suggestedComponents = [];
|
|
3841
|
+
let match;
|
|
3842
|
+
while ((match = componentSuggestionPattern.exec(analysisContent)) !== null) {
|
|
3843
|
+
suggestedComponents.push({
|
|
3844
|
+
type: match[1],
|
|
3845
|
+
reasoning: match[2].trim()
|
|
3846
|
+
});
|
|
3847
|
+
}
|
|
3665
3848
|
const matchedComponents = result.matchedComponents || [];
|
|
3666
3849
|
const layoutTitle = result.layoutTitle || "Dashboard";
|
|
3667
3850
|
const layoutDescription = result.layoutDescription || "Multi-component dashboard";
|
|
3851
|
+
logger.info(`[${this.getProviderName()}] \u{1F4CA} Component Suggestions from Text Analysis: ${suggestedComponents.length}`);
|
|
3852
|
+
suggestedComponents.forEach((comp, idx) => {
|
|
3853
|
+
logger.info(`[${this.getProviderName()}] c${idx + 1}: ${comp.type} - ${comp.reasoning}`);
|
|
3854
|
+
});
|
|
3855
|
+
logger.info(`[${this.getProviderName()}] \u{1F4E6} Matched Components from LLM: ${matchedComponents.length}`);
|
|
3856
|
+
matchedComponents.forEach((comp, idx) => {
|
|
3857
|
+
logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
|
|
3858
|
+
});
|
|
3859
|
+
if (suggestedComponents.length !== matchedComponents.length) {
|
|
3860
|
+
logger.warn(`[${this.getProviderName()}] \u26A0\uFE0F MISMATCH: Text suggested ${suggestedComponents.length} components, but LLM matched ${matchedComponents.length}`);
|
|
3861
|
+
}
|
|
3862
|
+
logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
|
|
3668
3863
|
const rawActions = result.actions || [];
|
|
3669
3864
|
const actions = convertQuestionsToActions(rawActions);
|
|
3670
3865
|
logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
|
|
3671
3866
|
logger.info(`[${this.getProviderName()}] Layout title: "${layoutTitle}"`);
|
|
3672
3867
|
logger.info(`[${this.getProviderName()}] Layout description: "${layoutDescription}"`);
|
|
3673
3868
|
logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
|
|
3869
|
+
if (suggestedComponents.length > 0) {
|
|
3870
|
+
logCollector?.info(`\u{1F4DD} Text Analysis suggested ${suggestedComponents.length} dashboard components:`);
|
|
3871
|
+
suggestedComponents.forEach((comp, idx) => {
|
|
3872
|
+
logCollector?.info(` c${idx + 1}: ${comp.type} - ${comp.reasoning}`);
|
|
3873
|
+
});
|
|
3874
|
+
}
|
|
3674
3875
|
if (matchedComponents.length > 0) {
|
|
3675
|
-
logCollector?.info(
|
|
3876
|
+
logCollector?.info(`\u{1F4E6} Matched ${matchedComponents.length} components for dashboard`);
|
|
3877
|
+
if (suggestedComponents.length !== matchedComponents.length) {
|
|
3878
|
+
logCollector?.warn(`\u26A0\uFE0F Component count mismatch: Suggested ${suggestedComponents.length}, but matched ${matchedComponents.length}`);
|
|
3879
|
+
}
|
|
3676
3880
|
logCollector?.info(`Dashboard: "${layoutTitle}"`);
|
|
3677
3881
|
matchedComponents.forEach((comp, idx) => {
|
|
3678
3882
|
logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
|
|
@@ -3723,6 +3927,152 @@ var BaseLLM = class {
|
|
|
3723
3927
|
};
|
|
3724
3928
|
}
|
|
3725
3929
|
}
|
|
3930
|
+
/**
|
|
3931
|
+
* Execute external tools based on user request using agentic LLM tool calling
|
|
3932
|
+
* The LLM can directly call tools and retry on errors
|
|
3933
|
+
* @param userPrompt - The user's question/request
|
|
3934
|
+
* @param availableTools - Array of available external tools
|
|
3935
|
+
* @param apiKey - Optional API key for LLM
|
|
3936
|
+
* @param logCollector - Optional log collector
|
|
3937
|
+
* @returns Object containing tool execution results and summary
|
|
3938
|
+
*/
|
|
3939
|
+
async executeExternalTools(userPrompt, availableTools, apiKey, logCollector) {
|
|
3940
|
+
const MAX_TOOL_ATTEMPTS = 3;
|
|
3941
|
+
const toolResults = [];
|
|
3942
|
+
try {
|
|
3943
|
+
logger.debug(`[${this.getProviderName()}] Starting agentic external tool execution`);
|
|
3944
|
+
logger.debug(`[${this.getProviderName()}] Available tools: ${availableTools.map((t) => t.name).join(", ")}`);
|
|
3945
|
+
const llmTools = availableTools.map((tool) => {
|
|
3946
|
+
const properties = {};
|
|
3947
|
+
const required = [];
|
|
3948
|
+
Object.entries(tool.params || {}).forEach(([key, type]) => {
|
|
3949
|
+
properties[key] = {
|
|
3950
|
+
type: String(type).toLowerCase(),
|
|
3951
|
+
description: `${key} parameter`
|
|
3952
|
+
};
|
|
3953
|
+
required.push(key);
|
|
3954
|
+
});
|
|
3955
|
+
return {
|
|
3956
|
+
name: tool.id,
|
|
3957
|
+
description: tool.description,
|
|
3958
|
+
input_schema: {
|
|
3959
|
+
type: "object",
|
|
3960
|
+
properties,
|
|
3961
|
+
required
|
|
3962
|
+
}
|
|
3963
|
+
};
|
|
3964
|
+
});
|
|
3965
|
+
const toolAttempts = /* @__PURE__ */ new Map();
|
|
3966
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
3967
|
+
const tool = availableTools.find((t) => t.id === toolName);
|
|
3968
|
+
if (!tool) {
|
|
3969
|
+
const errorMsg = `Tool ${toolName} not found in available tools`;
|
|
3970
|
+
logger.error(`[${this.getProviderName()}] ${errorMsg}`);
|
|
3971
|
+
logCollector?.error(errorMsg);
|
|
3972
|
+
throw new Error(errorMsg);
|
|
3973
|
+
}
|
|
3974
|
+
const attempts = (toolAttempts.get(toolName) || 0) + 1;
|
|
3975
|
+
toolAttempts.set(toolName, attempts);
|
|
3976
|
+
logger.info(`[${this.getProviderName()}] Executing tool: ${tool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})`);
|
|
3977
|
+
logCollector?.info(`Executing ${tool.name} (attempt ${attempts}/${MAX_TOOL_ATTEMPTS})...`);
|
|
3978
|
+
if (attempts > MAX_TOOL_ATTEMPTS) {
|
|
3979
|
+
const errorMsg = `Maximum attempts (${MAX_TOOL_ATTEMPTS}) reached for tool: ${tool.name}`;
|
|
3980
|
+
logger.error(`[${this.getProviderName()}] ${errorMsg}`);
|
|
3981
|
+
logCollector?.error(errorMsg);
|
|
3982
|
+
toolResults.push({
|
|
3983
|
+
toolName: tool.name,
|
|
3984
|
+
toolId: tool.id,
|
|
3985
|
+
result: null,
|
|
3986
|
+
error: errorMsg
|
|
3987
|
+
});
|
|
3988
|
+
throw new Error(errorMsg);
|
|
3989
|
+
}
|
|
3990
|
+
try {
|
|
3991
|
+
logger.debug(`[${this.getProviderName()}] Tool ${tool.name} parameters:`, toolInput);
|
|
3992
|
+
const result2 = await tool.fn(toolInput);
|
|
3993
|
+
logger.info(`[${this.getProviderName()}] Tool ${tool.name} executed successfully`);
|
|
3994
|
+
logCollector?.info(`\u2713 ${tool.name} completed successfully`);
|
|
3995
|
+
toolResults.push({
|
|
3996
|
+
toolName: tool.name,
|
|
3997
|
+
toolId: tool.id,
|
|
3998
|
+
result: result2
|
|
3999
|
+
});
|
|
4000
|
+
return JSON.stringify(result2, null, 2);
|
|
4001
|
+
} catch (error) {
|
|
4002
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4003
|
+
logger.error(`[${this.getProviderName()}] Tool ${tool.name} failed (attempt ${attempts}): ${errorMsg}`);
|
|
4004
|
+
logCollector?.error(`\u2717 ${tool.name} failed: ${errorMsg}`);
|
|
4005
|
+
if (attempts >= MAX_TOOL_ATTEMPTS) {
|
|
4006
|
+
toolResults.push({
|
|
4007
|
+
toolName: tool.name,
|
|
4008
|
+
toolId: tool.id,
|
|
4009
|
+
result: null,
|
|
4010
|
+
error: errorMsg
|
|
4011
|
+
});
|
|
4012
|
+
}
|
|
4013
|
+
throw new Error(`Tool execution failed: ${errorMsg}`);
|
|
4014
|
+
}
|
|
4015
|
+
};
|
|
4016
|
+
const prompts = await promptLoader.loadPrompts("execute-tools", {
|
|
4017
|
+
USER_PROMPT: userPrompt,
|
|
4018
|
+
AVAILABLE_TOOLS: availableTools.map((tool, idx) => {
|
|
4019
|
+
const paramsText = Object.entries(tool.params || {}).map(([key, type]) => ` - ${key}: ${type}`).join("\n");
|
|
4020
|
+
return `${idx + 1}. ID: ${tool.id}
|
|
4021
|
+
Name: ${tool.name}
|
|
4022
|
+
Description: ${tool.description}
|
|
4023
|
+
Parameters:
|
|
4024
|
+
${paramsText}`;
|
|
4025
|
+
}).join("\n\n")
|
|
4026
|
+
});
|
|
4027
|
+
logger.debug(`[${this.getProviderName()}] Using agentic tool calling for external tools`);
|
|
4028
|
+
logCollector?.info("Analyzing request and executing external tools...");
|
|
4029
|
+
const result = await LLM.streamWithTools(
|
|
4030
|
+
{
|
|
4031
|
+
sys: prompts.system,
|
|
4032
|
+
user: prompts.user
|
|
4033
|
+
},
|
|
4034
|
+
llmTools,
|
|
4035
|
+
toolHandler,
|
|
4036
|
+
{
|
|
4037
|
+
model: this.model,
|
|
4038
|
+
maxTokens: 2e3,
|
|
4039
|
+
temperature: 0.2,
|
|
4040
|
+
apiKey: this.getApiKey(apiKey)
|
|
4041
|
+
},
|
|
4042
|
+
MAX_TOOL_ATTEMPTS + 2
|
|
4043
|
+
// max iterations: allows for retries + final response
|
|
4044
|
+
);
|
|
4045
|
+
logger.info(`[${this.getProviderName()}] External tool execution completed`);
|
|
4046
|
+
const successfulTools = toolResults.filter((r) => !r.error);
|
|
4047
|
+
const failedTools = toolResults.filter((r) => r.error);
|
|
4048
|
+
let summary = "";
|
|
4049
|
+
if (successfulTools.length > 0) {
|
|
4050
|
+
summary += `Successfully executed ${successfulTools.length} tool(s): ${successfulTools.map((t) => t.toolName).join(", ")}.
|
|
4051
|
+
`;
|
|
4052
|
+
}
|
|
4053
|
+
if (failedTools.length > 0) {
|
|
4054
|
+
summary += `Failed to execute ${failedTools.length} tool(s): ${failedTools.map((t) => t.toolName).join(", ")}.`;
|
|
4055
|
+
}
|
|
4056
|
+
if (toolResults.length === 0) {
|
|
4057
|
+
summary = "No external tools were needed for this request.";
|
|
4058
|
+
}
|
|
4059
|
+
logger.info(`[${this.getProviderName()}] Tool execution summary: ${summary}`);
|
|
4060
|
+
return {
|
|
4061
|
+
toolResults,
|
|
4062
|
+
summary,
|
|
4063
|
+
hasResults: successfulTools.length > 0
|
|
4064
|
+
};
|
|
4065
|
+
} catch (error) {
|
|
4066
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4067
|
+
logger.error(`[${this.getProviderName()}] Error in external tool execution: ${errorMsg}`);
|
|
4068
|
+
logCollector?.error(`Error executing external tools: ${errorMsg}`);
|
|
4069
|
+
return {
|
|
4070
|
+
toolResults,
|
|
4071
|
+
summary: `Error executing external tools: ${errorMsg}`,
|
|
4072
|
+
hasResults: false
|
|
4073
|
+
};
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
3726
4076
|
/**
|
|
3727
4077
|
* Generate text-based response for user question
|
|
3728
4078
|
* This provides conversational text responses instead of component generation
|
|
@@ -3731,12 +4081,40 @@ var BaseLLM = class {
|
|
|
3731
4081
|
* @param streamCallback - Optional callback function to receive text chunks as they stream
|
|
3732
4082
|
* @param collections - Collection registry for executing database queries via database.execute
|
|
3733
4083
|
* @param components - Optional list of available components for matching suggestions
|
|
4084
|
+
* @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called
|
|
3734
4085
|
*/
|
|
3735
|
-
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components) {
|
|
4086
|
+
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools) {
|
|
3736
4087
|
const errors = [];
|
|
3737
4088
|
logger.debug(`[${this.getProviderName()}] Starting text response generation`);
|
|
3738
4089
|
logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
|
|
3739
4090
|
try {
|
|
4091
|
+
let externalToolContext = "No external tools were used for this request.";
|
|
4092
|
+
if (externalTools && externalTools.length > 0) {
|
|
4093
|
+
logger.info(`[${this.getProviderName()}] Executing external tools...`);
|
|
4094
|
+
const toolExecution = await this.executeExternalTools(
|
|
4095
|
+
userPrompt,
|
|
4096
|
+
externalTools,
|
|
4097
|
+
apiKey,
|
|
4098
|
+
logCollector
|
|
4099
|
+
);
|
|
4100
|
+
if (toolExecution.hasResults) {
|
|
4101
|
+
const toolResultsText = toolExecution.toolResults.map((tr) => {
|
|
4102
|
+
if (tr.error) {
|
|
4103
|
+
return `**${tr.toolName}** (Failed): ${tr.error}`;
|
|
4104
|
+
}
|
|
4105
|
+
return `**${tr.toolName}** (Success):
|
|
4106
|
+
${JSON.stringify(tr.result, null, 2)}`;
|
|
4107
|
+
}).join("\n\n");
|
|
4108
|
+
externalToolContext = `## External Tool Results
|
|
4109
|
+
|
|
4110
|
+
${toolExecution.summary}
|
|
4111
|
+
|
|
4112
|
+
${toolResultsText}`;
|
|
4113
|
+
logger.info(`[${this.getProviderName()}] External tools executed, results available`);
|
|
4114
|
+
} else {
|
|
4115
|
+
logger.info(`[${this.getProviderName()}] No external tools were needed`);
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
3740
4118
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
3741
4119
|
const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
|
|
3742
4120
|
prompt: userPrompt,
|
|
@@ -3744,11 +4122,13 @@ var BaseLLM = class {
|
|
|
3744
4122
|
topK: 1
|
|
3745
4123
|
});
|
|
3746
4124
|
logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
|
|
4125
|
+
logger.file("\n=============================\nexternal tool context:", externalToolContext);
|
|
3747
4126
|
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
3748
4127
|
USER_PROMPT: userPrompt,
|
|
3749
4128
|
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
3750
4129
|
SCHEMA_DOC: schemaDoc,
|
|
3751
|
-
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available."
|
|
4130
|
+
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
|
|
4131
|
+
EXTERNAL_TOOL_CONTEXT: externalToolContext
|
|
3752
4132
|
});
|
|
3753
4133
|
logger.file("\n=============================\nsystem prompt:", prompts.system);
|
|
3754
4134
|
logger.file("\n=============================\nuser prompt:", prompts.user);
|
|
@@ -3971,11 +4351,17 @@ ${errorMsg}
|
|
|
3971
4351
|
let actions = [];
|
|
3972
4352
|
if (components && components.length > 0) {
|
|
3973
4353
|
logger.info(`[${this.getProviderName()}] Matching components from text response...`);
|
|
3974
|
-
const
|
|
4354
|
+
const componentStreamCallback = wrappedStreamCallback ? (component) => {
|
|
4355
|
+
const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
|
|
4356
|
+
wrappedStreamCallback(answerMarker);
|
|
4357
|
+
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
4358
|
+
} : void 0;
|
|
4359
|
+
const matchResult = await this.matchComponentsFromAnalysis(
|
|
3975
4360
|
textResponse,
|
|
3976
4361
|
components,
|
|
3977
4362
|
apiKey,
|
|
3978
|
-
logCollector
|
|
4363
|
+
logCollector,
|
|
4364
|
+
componentStreamCallback
|
|
3979
4365
|
);
|
|
3980
4366
|
matchedComponents = matchResult.components;
|
|
3981
4367
|
layoutTitle = matchResult.layoutTitle;
|
|
@@ -4219,8 +4605,9 @@ ${errorMsg}
|
|
|
4219
4605
|
* @param responseMode - 'component' for component generation (default), 'text' for text responses
|
|
4220
4606
|
* @param streamCallback - Optional callback function to receive text chunks as they stream (only for text mode)
|
|
4221
4607
|
* @param collections - Collection registry for executing database queries (required for text mode)
|
|
4608
|
+
* @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called (only for text mode)
|
|
4222
4609
|
*/
|
|
4223
|
-
async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) {
|
|
4610
|
+
async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) {
|
|
4224
4611
|
const startTime = Date.now();
|
|
4225
4612
|
logger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);
|
|
4226
4613
|
if (responseMode === "text") {
|
|
@@ -4233,7 +4620,8 @@ ${errorMsg}
|
|
|
4233
4620
|
conversationHistory,
|
|
4234
4621
|
streamCallback,
|
|
4235
4622
|
collections,
|
|
4236
|
-
components
|
|
4623
|
+
components,
|
|
4624
|
+
externalTools
|
|
4237
4625
|
);
|
|
4238
4626
|
if (!textResponse.success) {
|
|
4239
4627
|
const elapsedTime3 = Date.now() - startTime;
|
|
@@ -4379,7 +4767,7 @@ function getLLMProviders() {
|
|
|
4379
4767
|
return DEFAULT_PROVIDERS;
|
|
4380
4768
|
}
|
|
4381
4769
|
}
|
|
4382
|
-
var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
|
|
4770
|
+
var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
|
|
4383
4771
|
logger.debug("[useAnthropicMethod] Initializing Anthropic Claude matching method");
|
|
4384
4772
|
logger.debug(`[useAnthropicMethod] Response mode: ${responseMode}`);
|
|
4385
4773
|
const msg = `Using Anthropic Claude ${responseMode === "text" ? "text response" : "matching"} method...`;
|
|
@@ -4391,11 +4779,11 @@ var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conver
|
|
|
4391
4779
|
return { success: false, errors: [emptyMsg] };
|
|
4392
4780
|
}
|
|
4393
4781
|
logger.debug(`[useAnthropicMethod] Processing with ${components.length} components`);
|
|
4394
|
-
const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
|
|
4782
|
+
const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
|
|
4395
4783
|
logger.info(`[useAnthropicMethod] Successfully generated ${responseMode} using Anthropic`);
|
|
4396
4784
|
return matchResult;
|
|
4397
4785
|
};
|
|
4398
|
-
var useGroqMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
|
|
4786
|
+
var useGroqMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
|
|
4399
4787
|
logger.debug("[useGroqMethod] Initializing Groq LLM matching method");
|
|
4400
4788
|
logger.debug(`[useGroqMethod] Response mode: ${responseMode}`);
|
|
4401
4789
|
const msg = `Using Groq LLM ${responseMode === "text" ? "text response" : "matching"} method...`;
|
|
@@ -4408,14 +4796,14 @@ var useGroqMethod = async (prompt, components, apiKey, logCollector, conversatio
|
|
|
4408
4796
|
return { success: false, errors: [emptyMsg] };
|
|
4409
4797
|
}
|
|
4410
4798
|
logger.debug(`[useGroqMethod] Processing with ${components.length} components`);
|
|
4411
|
-
const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
|
|
4799
|
+
const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
|
|
4412
4800
|
logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);
|
|
4413
4801
|
return matchResult;
|
|
4414
4802
|
};
|
|
4415
4803
|
var getUserResponseFromCache = async (prompt) => {
|
|
4416
4804
|
return false;
|
|
4417
4805
|
};
|
|
4418
|
-
var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections) => {
|
|
4806
|
+
var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools) => {
|
|
4419
4807
|
logger.debug(`[get_user_response] Starting user response generation for prompt: "${prompt.substring(0, 50)}..."`);
|
|
4420
4808
|
logger.debug(`[get_user_response] Response mode: ${responseMode}`);
|
|
4421
4809
|
logger.debug("[get_user_response] Checking cache for existing response");
|
|
@@ -4448,9 +4836,9 @@ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey,
|
|
|
4448
4836
|
logCollector?.info(attemptMsg);
|
|
4449
4837
|
let result;
|
|
4450
4838
|
if (provider === "anthropic") {
|
|
4451
|
-
result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
|
|
4839
|
+
result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
|
|
4452
4840
|
} else if (provider === "groq") {
|
|
4453
|
-
result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections);
|
|
4841
|
+
result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools);
|
|
4454
4842
|
} else {
|
|
4455
4843
|
logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);
|
|
4456
4844
|
errors.push(`Unknown provider: ${provider}`);
|
|
@@ -4678,7 +5066,7 @@ var CONTEXT_CONFIG = {
|
|
|
4678
5066
|
};
|
|
4679
5067
|
|
|
4680
5068
|
// src/handlers/user-prompt-request.ts
|
|
4681
|
-
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections) => {
|
|
5069
|
+
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools) => {
|
|
4682
5070
|
const errors = [];
|
|
4683
5071
|
logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
|
|
4684
5072
|
const parseResult = UserPromptRequestMessageSchema.safeParse(data);
|
|
@@ -4758,7 +5146,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
4758
5146
|
conversationHistory,
|
|
4759
5147
|
responseMode,
|
|
4760
5148
|
streamCallback,
|
|
4761
|
-
collections
|
|
5149
|
+
collections,
|
|
5150
|
+
externalTools
|
|
4762
5151
|
);
|
|
4763
5152
|
logCollector.info("User prompt request completed");
|
|
4764
5153
|
const uiBlockId = existingUiBlockId;
|
|
@@ -4819,8 +5208,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
4819
5208
|
wsId
|
|
4820
5209
|
};
|
|
4821
5210
|
};
|
|
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);
|
|
5211
|
+
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools) {
|
|
5212
|
+
const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools);
|
|
4824
5213
|
sendDataResponse4(
|
|
4825
5214
|
response.id || data.id,
|
|
4826
5215
|
{
|
|
@@ -4847,7 +5236,6 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
|
4847
5236
|
...res
|
|
4848
5237
|
}
|
|
4849
5238
|
};
|
|
4850
|
-
logger.info("sending user prompt response", response);
|
|
4851
5239
|
sendMessage(response);
|
|
4852
5240
|
}
|
|
4853
5241
|
|
|
@@ -5894,6 +6282,183 @@ function sendResponse5(id, res, sendMessage, clientId) {
|
|
|
5894
6282
|
sendMessage(response);
|
|
5895
6283
|
}
|
|
5896
6284
|
|
|
6285
|
+
// src/handlers/bookmarks.ts
|
|
6286
|
+
async function handleBookmarksRequest(data, collections, sendMessage) {
|
|
6287
|
+
const executeCollection = async (collection, op, params) => {
|
|
6288
|
+
const handler = collections[collection]?.[op];
|
|
6289
|
+
if (!handler) {
|
|
6290
|
+
throw new Error(`Collection operation ${collection}.${op} not found`);
|
|
6291
|
+
}
|
|
6292
|
+
return await handler(params);
|
|
6293
|
+
};
|
|
6294
|
+
try {
|
|
6295
|
+
const request = BookmarksRequestMessageSchema.parse(data);
|
|
6296
|
+
const { id, payload, from } = request;
|
|
6297
|
+
const { operation, data: requestData } = payload;
|
|
6298
|
+
const bookmarkId = requestData?.id;
|
|
6299
|
+
const uiblock = requestData?.uiblock;
|
|
6300
|
+
switch (operation) {
|
|
6301
|
+
case "create":
|
|
6302
|
+
await handleCreate4(id, uiblock, executeCollection, sendMessage, from.id);
|
|
6303
|
+
break;
|
|
6304
|
+
case "update":
|
|
6305
|
+
await handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, from.id);
|
|
6306
|
+
break;
|
|
6307
|
+
case "delete":
|
|
6308
|
+
await handleDelete4(id, bookmarkId, executeCollection, sendMessage, from.id);
|
|
6309
|
+
break;
|
|
6310
|
+
case "getAll":
|
|
6311
|
+
await handleGetAll4(id, executeCollection, sendMessage, from.id);
|
|
6312
|
+
break;
|
|
6313
|
+
case "getOne":
|
|
6314
|
+
await handleGetOne4(id, bookmarkId, executeCollection, sendMessage, from.id);
|
|
6315
|
+
break;
|
|
6316
|
+
default:
|
|
6317
|
+
sendResponse6(id, {
|
|
6318
|
+
success: false,
|
|
6319
|
+
error: `Unknown operation: ${operation}`
|
|
6320
|
+
}, sendMessage, from.id);
|
|
6321
|
+
}
|
|
6322
|
+
} catch (error) {
|
|
6323
|
+
logger.error("Failed to handle bookmarks request:", error);
|
|
6324
|
+
sendResponse6(null, {
|
|
6325
|
+
success: false,
|
|
6326
|
+
error: error instanceof Error ? error.message : "Unknown error occurred"
|
|
6327
|
+
}, sendMessage);
|
|
6328
|
+
}
|
|
6329
|
+
}
|
|
6330
|
+
async function handleCreate4(id, uiblock, executeCollection, sendMessage, clientId) {
|
|
6331
|
+
if (!uiblock) {
|
|
6332
|
+
sendResponse6(id, {
|
|
6333
|
+
success: false,
|
|
6334
|
+
error: "UIBlock data is required"
|
|
6335
|
+
}, sendMessage, clientId);
|
|
6336
|
+
return;
|
|
6337
|
+
}
|
|
6338
|
+
try {
|
|
6339
|
+
const result = await executeCollection("bookmarks", "create", { uiblock });
|
|
6340
|
+
sendResponse6(id, {
|
|
6341
|
+
success: true,
|
|
6342
|
+
data: result.data,
|
|
6343
|
+
message: "Bookmark created successfully"
|
|
6344
|
+
}, sendMessage, clientId);
|
|
6345
|
+
logger.info(`Bookmark created: ID ${result.data.id}`);
|
|
6346
|
+
} catch (error) {
|
|
6347
|
+
sendResponse6(id, {
|
|
6348
|
+
success: false,
|
|
6349
|
+
error: error instanceof Error ? error.message : "Failed to create bookmark"
|
|
6350
|
+
}, sendMessage, clientId);
|
|
6351
|
+
}
|
|
6352
|
+
}
|
|
6353
|
+
async function handleUpdate4(id, bookmarkId, uiblock, executeCollection, sendMessage, clientId) {
|
|
6354
|
+
if (!bookmarkId) {
|
|
6355
|
+
sendResponse6(id, {
|
|
6356
|
+
success: false,
|
|
6357
|
+
error: "Bookmark ID is required"
|
|
6358
|
+
}, sendMessage, clientId);
|
|
6359
|
+
return;
|
|
6360
|
+
}
|
|
6361
|
+
if (!uiblock) {
|
|
6362
|
+
sendResponse6(id, {
|
|
6363
|
+
success: false,
|
|
6364
|
+
error: "UIBlock data is required"
|
|
6365
|
+
}, sendMessage, clientId);
|
|
6366
|
+
return;
|
|
6367
|
+
}
|
|
6368
|
+
try {
|
|
6369
|
+
const result = await executeCollection("bookmarks", "update", { id: bookmarkId, uiblock });
|
|
6370
|
+
sendResponse6(id, {
|
|
6371
|
+
success: true,
|
|
6372
|
+
data: result.data,
|
|
6373
|
+
message: "Bookmark updated successfully"
|
|
6374
|
+
}, sendMessage, clientId);
|
|
6375
|
+
logger.info(`Bookmark updated: ID ${bookmarkId}`);
|
|
6376
|
+
} catch (error) {
|
|
6377
|
+
sendResponse6(id, {
|
|
6378
|
+
success: false,
|
|
6379
|
+
error: error instanceof Error ? error.message : "Failed to update bookmark"
|
|
6380
|
+
}, sendMessage, clientId);
|
|
6381
|
+
}
|
|
6382
|
+
}
|
|
6383
|
+
async function handleDelete4(id, bookmarkId, executeCollection, sendMessage, clientId) {
|
|
6384
|
+
if (!bookmarkId) {
|
|
6385
|
+
sendResponse6(id, {
|
|
6386
|
+
success: false,
|
|
6387
|
+
error: "Bookmark ID is required"
|
|
6388
|
+
}, sendMessage, clientId);
|
|
6389
|
+
return;
|
|
6390
|
+
}
|
|
6391
|
+
try {
|
|
6392
|
+
const result = await executeCollection("bookmarks", "delete", { id: bookmarkId });
|
|
6393
|
+
sendResponse6(id, {
|
|
6394
|
+
success: true,
|
|
6395
|
+
data: result.data,
|
|
6396
|
+
message: "Bookmark deleted successfully"
|
|
6397
|
+
}, sendMessage, clientId);
|
|
6398
|
+
logger.info(`Bookmark deleted: ID ${bookmarkId}`);
|
|
6399
|
+
} catch (error) {
|
|
6400
|
+
sendResponse6(id, {
|
|
6401
|
+
success: false,
|
|
6402
|
+
error: error instanceof Error ? error.message : "Failed to delete bookmark"
|
|
6403
|
+
}, sendMessage, clientId);
|
|
6404
|
+
}
|
|
6405
|
+
}
|
|
6406
|
+
async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
|
|
6407
|
+
try {
|
|
6408
|
+
const result = await executeCollection("bookmarks", "getAll", {});
|
|
6409
|
+
sendResponse6(id, {
|
|
6410
|
+
success: true,
|
|
6411
|
+
data: result.data,
|
|
6412
|
+
count: result.count,
|
|
6413
|
+
message: `Retrieved ${result.count} bookmarks`
|
|
6414
|
+
}, sendMessage, clientId);
|
|
6415
|
+
logger.info(`Retrieved all bookmarks (count: ${result.count})`);
|
|
6416
|
+
} catch (error) {
|
|
6417
|
+
sendResponse6(id, {
|
|
6418
|
+
success: false,
|
|
6419
|
+
error: error instanceof Error ? error.message : "Failed to get bookmarks"
|
|
6420
|
+
}, sendMessage, clientId);
|
|
6421
|
+
}
|
|
6422
|
+
}
|
|
6423
|
+
async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, clientId) {
|
|
6424
|
+
if (!bookmarkId) {
|
|
6425
|
+
sendResponse6(id, {
|
|
6426
|
+
success: false,
|
|
6427
|
+
error: "Bookmark ID is required"
|
|
6428
|
+
}, sendMessage, clientId);
|
|
6429
|
+
return;
|
|
6430
|
+
}
|
|
6431
|
+
try {
|
|
6432
|
+
const result = await executeCollection("bookmarks", "getOne", { id: bookmarkId });
|
|
6433
|
+
sendResponse6(id, {
|
|
6434
|
+
success: true,
|
|
6435
|
+
data: result.data,
|
|
6436
|
+
message: `Retrieved bookmark ID ${bookmarkId}`
|
|
6437
|
+
}, sendMessage, clientId);
|
|
6438
|
+
logger.info(`Retrieved bookmark: ID ${bookmarkId}`);
|
|
6439
|
+
} catch (error) {
|
|
6440
|
+
sendResponse6(id, {
|
|
6441
|
+
success: false,
|
|
6442
|
+
error: error instanceof Error ? error.message : "Failed to get bookmark"
|
|
6443
|
+
}, sendMessage, clientId);
|
|
6444
|
+
}
|
|
6445
|
+
}
|
|
6446
|
+
function sendResponse6(id, res, sendMessage, clientId) {
|
|
6447
|
+
const response = {
|
|
6448
|
+
id: id || "unknown",
|
|
6449
|
+
type: "BOOKMARKS_RES",
|
|
6450
|
+
from: { type: "data-agent" },
|
|
6451
|
+
to: {
|
|
6452
|
+
type: "user",
|
|
6453
|
+
id: clientId
|
|
6454
|
+
},
|
|
6455
|
+
payload: {
|
|
6456
|
+
...res
|
|
6457
|
+
}
|
|
6458
|
+
};
|
|
6459
|
+
sendMessage(response);
|
|
6460
|
+
}
|
|
6461
|
+
|
|
5897
6462
|
// src/auth/user-manager.ts
|
|
5898
6463
|
import fs5 from "fs";
|
|
5899
6464
|
import path4 from "path";
|
|
@@ -6718,6 +7283,7 @@ var SuperatomSDK = class {
|
|
|
6718
7283
|
this.maxReconnectAttempts = 5;
|
|
6719
7284
|
this.collections = {};
|
|
6720
7285
|
this.components = [];
|
|
7286
|
+
this.tools = [];
|
|
6721
7287
|
if (config.logLevel) {
|
|
6722
7288
|
logger.setLogLevel(config.logLevel);
|
|
6723
7289
|
}
|
|
@@ -6873,7 +7439,7 @@ var SuperatomSDK = class {
|
|
|
6873
7439
|
});
|
|
6874
7440
|
break;
|
|
6875
7441
|
case "USER_PROMPT_REQ":
|
|
6876
|
-
handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections).catch((error) => {
|
|
7442
|
+
handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
|
|
6877
7443
|
logger.error("Failed to handle user prompt request:", error);
|
|
6878
7444
|
});
|
|
6879
7445
|
break;
|
|
@@ -6907,6 +7473,11 @@ var SuperatomSDK = class {
|
|
|
6907
7473
|
logger.error("Failed to handle reports request:", error);
|
|
6908
7474
|
});
|
|
6909
7475
|
break;
|
|
7476
|
+
case "BOOKMARKS":
|
|
7477
|
+
handleBookmarksRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
|
|
7478
|
+
logger.error("Failed to handle bookmarks request:", error);
|
|
7479
|
+
});
|
|
7480
|
+
break;
|
|
6910
7481
|
default:
|
|
6911
7482
|
const handler = this.messageTypeHandlers.get(message.type);
|
|
6912
7483
|
if (handler) {
|
|
@@ -7013,6 +7584,19 @@ var SuperatomSDK = class {
|
|
|
7013
7584
|
storeComponents(components) {
|
|
7014
7585
|
this.components = components;
|
|
7015
7586
|
}
|
|
7587
|
+
/**
|
|
7588
|
+
* Set tools for the SDK instance
|
|
7589
|
+
*/
|
|
7590
|
+
setTools(tools) {
|
|
7591
|
+
this.tools = tools;
|
|
7592
|
+
logger.info(`Tools stored in SDK: ${tools.length} tools`);
|
|
7593
|
+
}
|
|
7594
|
+
/**
|
|
7595
|
+
* Get the stored tools
|
|
7596
|
+
*/
|
|
7597
|
+
getTools() {
|
|
7598
|
+
return this.tools;
|
|
7599
|
+
}
|
|
7016
7600
|
};
|
|
7017
7601
|
export {
|
|
7018
7602
|
CONTEXT_CONFIG,
|