@superatomai/sdk-node 0.0.18 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -451,7 +451,8 @@ var UserPromptRequestMessageSchema = import_zod3.z.object({
451
451
  });
452
452
  var UserPromptSuggestionsPayloadSchema = import_zod3.z.object({
453
453
  prompt: import_zod3.z.string(),
454
- limit: import_zod3.z.number().int().positive().default(5)
454
+ limit: import_zod3.z.number().int().positive().default(5),
455
+ similarityThreshold: import_zod3.z.number().min(0).max(1).default(0.4)
455
456
  });
456
457
  var UserPromptSuggestionsMessageSchema = import_zod3.z.object({
457
458
  id: import_zod3.z.string(),
@@ -538,11 +539,28 @@ var ActionsRequestMessageSchema = import_zod3.z.object({
538
539
  type: import_zod3.z.literal("ACTIONS"),
539
540
  payload: ActionsRequestPayloadSchema
540
541
  });
542
+ var DashboardQueryFiltersSchema = import_zod3.z.object({
543
+ dashboardId: import_zod3.z.string().optional(),
544
+ projectId: import_zod3.z.string().optional(),
545
+ createdBy: import_zod3.z.number().optional(),
546
+ updatedBy: import_zod3.z.number().optional(),
547
+ name: import_zod3.z.string().optional()
548
+ });
541
549
  var DashboardsRequestPayloadSchema = import_zod3.z.object({
542
- operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne"]),
550
+ operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
543
551
  data: import_zod3.z.object({
552
+ id: import_zod3.z.number().optional(),
544
553
  dashboardId: import_zod3.z.string().optional(),
545
- dashboard: DSLRendererPropsSchema.optional()
554
+ projectId: import_zod3.z.string().optional(),
555
+ name: import_zod3.z.string().optional(),
556
+ description: import_zod3.z.string().optional(),
557
+ createdBy: import_zod3.z.number().optional(),
558
+ updatedBy: import_zod3.z.number().optional(),
559
+ dashboard: DSLRendererPropsSchema.optional(),
560
+ // Query operation fields
561
+ filters: DashboardQueryFiltersSchema.optional(),
562
+ limit: import_zod3.z.number().optional(),
563
+ sort: import_zod3.z.enum(["ASC", "DESC"]).optional()
546
564
  }).optional()
547
565
  });
548
566
  var DashboardsRequestMessageSchema = import_zod3.z.object({
@@ -551,11 +569,28 @@ var DashboardsRequestMessageSchema = import_zod3.z.object({
551
569
  type: import_zod3.z.literal("DASHBOARDS"),
552
570
  payload: DashboardsRequestPayloadSchema
553
571
  });
572
+ var ReportQueryFiltersSchema = import_zod3.z.object({
573
+ reportId: import_zod3.z.string().optional(),
574
+ projectId: import_zod3.z.string().optional(),
575
+ createdBy: import_zod3.z.number().optional(),
576
+ updatedBy: import_zod3.z.number().optional(),
577
+ name: import_zod3.z.string().optional()
578
+ });
554
579
  var ReportsRequestPayloadSchema = import_zod3.z.object({
555
- operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne"]),
580
+ operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
556
581
  data: import_zod3.z.object({
582
+ id: import_zod3.z.number().optional(),
557
583
  reportId: import_zod3.z.string().optional(),
558
- report: DSLRendererPropsSchema2.optional()
584
+ projectId: import_zod3.z.string().optional(),
585
+ name: import_zod3.z.string().optional(),
586
+ description: import_zod3.z.string().optional(),
587
+ createdBy: import_zod3.z.number().optional(),
588
+ updatedBy: import_zod3.z.number().optional(),
589
+ report: DSLRendererPropsSchema2.optional(),
590
+ // Query operation fields
591
+ filters: ReportQueryFiltersSchema.optional(),
592
+ limit: import_zod3.z.number().optional(),
593
+ sort: import_zod3.z.enum(["ASC", "DESC"]).optional()
559
594
  }).optional()
560
595
  });
561
596
  var ReportsRequestMessageSchema = import_zod3.z.object({
@@ -564,6 +599,36 @@ var ReportsRequestMessageSchema = import_zod3.z.object({
564
599
  type: import_zod3.z.literal("REPORTS"),
565
600
  payload: ReportsRequestPayloadSchema
566
601
  });
602
+ var UIQueryFiltersSchema = import_zod3.z.object({
603
+ uiId: import_zod3.z.string().optional(),
604
+ projectId: import_zod3.z.string().optional(),
605
+ createdBy: import_zod3.z.number().optional(),
606
+ updatedBy: import_zod3.z.number().optional(),
607
+ name: import_zod3.z.string().optional()
608
+ });
609
+ var UIsRequestPayloadSchema = import_zod3.z.object({
610
+ operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
611
+ data: import_zod3.z.object({
612
+ id: import_zod3.z.number().optional(),
613
+ uiId: import_zod3.z.string().optional(),
614
+ projectId: import_zod3.z.string().optional(),
615
+ name: import_zod3.z.string().optional(),
616
+ description: import_zod3.z.string().optional(),
617
+ createdBy: import_zod3.z.number().optional(),
618
+ updatedBy: import_zod3.z.number().optional(),
619
+ ui: DSLRendererPropsSchema.optional(),
620
+ // Query operation fields
621
+ filters: UIQueryFiltersSchema.optional(),
622
+ limit: import_zod3.z.number().optional(),
623
+ sort: import_zod3.z.enum(["ASC", "DESC"]).optional()
624
+ }).optional()
625
+ });
626
+ var UIsRequestMessageSchema = import_zod3.z.object({
627
+ id: import_zod3.z.string(),
628
+ from: MessageParticipantSchema,
629
+ type: import_zod3.z.literal("UIS"),
630
+ payload: UIsRequestPayloadSchema
631
+ });
567
632
  var UIBlockSchema = import_zod3.z.object({
568
633
  id: import_zod3.z.string().optional(),
569
634
  userQuestion: import_zod3.z.string().optional(),
@@ -587,10 +652,16 @@ var UIBlockSchema = import_zod3.z.object({
587
652
  similarity: import_zod3.z.number().optional()
588
653
  }).optional()
589
654
  });
655
+ var DBUIBlockSchema = import_zod3.z.object({
656
+ id: import_zod3.z.string(),
657
+ component: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.any()).nullable(),
658
+ analysis: import_zod3.z.string().nullable(),
659
+ user_prompt: import_zod3.z.string()
660
+ });
590
661
  var BookmarkDataSchema = import_zod3.z.object({
591
662
  id: import_zod3.z.number().optional(),
592
- uiblock: import_zod3.z.any(),
593
- // JSON object
663
+ uiblock: DBUIBlockSchema,
664
+ // Typed JSON object
594
665
  created_at: import_zod3.z.string().optional(),
595
666
  updated_at: import_zod3.z.string().optional()
596
667
  });
@@ -600,7 +671,9 @@ var BookmarksRequestPayloadSchema = import_zod3.z.object({
600
671
  id: import_zod3.z.number().optional(),
601
672
  userId: import_zod3.z.number().optional(),
602
673
  threadId: import_zod3.z.string().optional(),
603
- uiblock: import_zod3.z.any().optional()
674
+ name: import_zod3.z.string().optional(),
675
+ description: import_zod3.z.string().optional(),
676
+ uiblock: DBUIBlockSchema.optional()
604
677
  }).optional()
605
678
  });
606
679
  var BookmarksRequestMessageSchema = import_zod3.z.object({
@@ -2947,6 +3020,8 @@ var promptLoader = new PromptLoader({
2947
3020
  // src/llm.ts
2948
3021
  var import_sdk = __toESM(require("@anthropic-ai/sdk"));
2949
3022
  var import_groq_sdk = __toESM(require("groq-sdk"));
3023
+ var import_generative_ai = require("@google/generative-ai");
3024
+ var import_openai = __toESM(require("openai"));
2950
3025
  var import_jsonrepair = require("jsonrepair");
2951
3026
  var LLM = class {
2952
3027
  /* Get a complete text response from an LLM (Anthropic or Groq) */
@@ -2956,8 +3031,12 @@ var LLM = class {
2956
3031
  return this._anthropicText(messages, modelName, options);
2957
3032
  } else if (provider === "groq") {
2958
3033
  return this._groqText(messages, modelName, options);
3034
+ } else if (provider === "gemini") {
3035
+ return this._geminiText(messages, modelName, options);
3036
+ } else if (provider === "openai") {
3037
+ return this._openaiText(messages, modelName, options);
2959
3038
  } else {
2960
- throw new Error(`Unsupported provider: ${provider}. Use "anthropic" or "groq"`);
3039
+ throw new Error(`Unsupported provider: ${provider}. Use "anthropic", "groq", "gemini", or "openai"`);
2961
3040
  }
2962
3041
  }
2963
3042
  /* Stream response from an LLM (Anthropic or Groq) */
@@ -2967,17 +3046,26 @@ var LLM = class {
2967
3046
  return this._anthropicStream(messages, modelName, options, json);
2968
3047
  } else if (provider === "groq") {
2969
3048
  return this._groqStream(messages, modelName, options, json);
3049
+ } else if (provider === "gemini") {
3050
+ return this._geminiStream(messages, modelName, options, json);
3051
+ } else if (provider === "openai") {
3052
+ return this._openaiStream(messages, modelName, options, json);
2970
3053
  } else {
2971
- throw new Error(`Unsupported provider: ${provider}. Use "anthropic" or "groq"`);
3054
+ throw new Error(`Unsupported provider: ${provider}. Use "anthropic", "groq", "gemini", or "openai"`);
2972
3055
  }
2973
3056
  }
2974
- /* Stream response with tool calling support (Anthropic only for now) */
3057
+ /* Stream response with tool calling support (Anthropic and Gemini) */
2975
3058
  static async streamWithTools(messages, tools, toolHandler, options = {}, maxIterations = 3) {
2976
3059
  const [provider, modelName] = this._parseModel(options.model);
2977
- if (provider !== "anthropic") {
2978
- throw new Error(`Tool calling is only supported for Anthropic models`);
3060
+ if (provider === "anthropic") {
3061
+ return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
3062
+ } else if (provider === "gemini") {
3063
+ return this._geminiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
3064
+ } else if (provider === "openai") {
3065
+ return this._openaiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
3066
+ } else {
3067
+ throw new Error(`Tool calling is only supported for Anthropic, Gemini, and OpenAI models`);
2979
3068
  }
2980
- return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
2981
3069
  }
2982
3070
  // ============================================================
2983
3071
  // PRIVATE HELPER METHODS
@@ -3311,6 +3399,298 @@ var LLM = class {
3311
3399
  return fullText;
3312
3400
  }
3313
3401
  // ============================================================
3402
+ // GEMINI IMPLEMENTATION
3403
+ // ============================================================
3404
+ static async _geminiText(messages, modelName, options) {
3405
+ const apiKey = options.apiKey || process.env.GEMINI_API_KEY || "";
3406
+ const genAI = new import_generative_ai.GoogleGenerativeAI(apiKey);
3407
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3408
+ const model = genAI.getGenerativeModel({
3409
+ model: modelName,
3410
+ systemInstruction: systemPrompt,
3411
+ generationConfig: {
3412
+ maxOutputTokens: options.maxTokens || 1e3,
3413
+ temperature: options.temperature,
3414
+ topP: options.topP
3415
+ }
3416
+ });
3417
+ const result = await model.generateContent(messages.user);
3418
+ const response = await result.response;
3419
+ return response.text();
3420
+ }
3421
+ static async _geminiStream(messages, modelName, options, json) {
3422
+ const apiKey = options.apiKey || process.env.GEMINI_API_KEY || "";
3423
+ const genAI = new import_generative_ai.GoogleGenerativeAI(apiKey);
3424
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3425
+ const model = genAI.getGenerativeModel({
3426
+ model: modelName,
3427
+ systemInstruction: systemPrompt,
3428
+ generationConfig: {
3429
+ maxOutputTokens: options.maxTokens || 1e3,
3430
+ temperature: options.temperature,
3431
+ topP: options.topP,
3432
+ responseMimeType: json ? "application/json" : void 0
3433
+ }
3434
+ });
3435
+ const result = await model.generateContentStream(messages.user);
3436
+ let fullText = "";
3437
+ for await (const chunk of result.stream) {
3438
+ const text = chunk.text();
3439
+ if (text) {
3440
+ fullText += text;
3441
+ if (options.partial) {
3442
+ options.partial(text);
3443
+ }
3444
+ }
3445
+ }
3446
+ if (json) {
3447
+ return this._parseJSON(fullText);
3448
+ }
3449
+ return fullText;
3450
+ }
3451
+ static async _geminiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations) {
3452
+ const apiKey = options.apiKey || process.env.GEMINI_API_KEY || "";
3453
+ const genAI = new import_generative_ai.GoogleGenerativeAI(apiKey);
3454
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3455
+ const functionDeclarations = tools.map((tool) => ({
3456
+ name: tool.name,
3457
+ description: tool.description,
3458
+ parameters: {
3459
+ type: import_generative_ai.SchemaType.OBJECT,
3460
+ properties: tool.input_schema.properties,
3461
+ required: tool.input_schema.required || []
3462
+ }
3463
+ }));
3464
+ const model = genAI.getGenerativeModel({
3465
+ model: modelName,
3466
+ systemInstruction: systemPrompt,
3467
+ tools: [{ functionDeclarations }],
3468
+ generationConfig: {
3469
+ maxOutputTokens: options.maxTokens || 4e3,
3470
+ temperature: options.temperature,
3471
+ topP: options.topP
3472
+ }
3473
+ });
3474
+ const chat = model.startChat({
3475
+ history: []
3476
+ });
3477
+ let iterations = 0;
3478
+ let finalText = "";
3479
+ let currentUserMessage = messages.user;
3480
+ while (iterations < maxIterations) {
3481
+ iterations++;
3482
+ const result = await chat.sendMessageStream(currentUserMessage);
3483
+ let responseText = "";
3484
+ const functionCalls = [];
3485
+ for await (const chunk of result.stream) {
3486
+ const candidate = chunk.candidates?.[0];
3487
+ if (!candidate) continue;
3488
+ for (const part of candidate.content?.parts || []) {
3489
+ if (part.text) {
3490
+ responseText += part.text;
3491
+ if (options.partial) {
3492
+ options.partial(part.text);
3493
+ }
3494
+ } else if (part.functionCall) {
3495
+ functionCalls.push({
3496
+ name: part.functionCall.name,
3497
+ args: part.functionCall.args
3498
+ });
3499
+ }
3500
+ }
3501
+ }
3502
+ if (functionCalls.length === 0) {
3503
+ finalText = responseText;
3504
+ break;
3505
+ }
3506
+ const functionResponses = [];
3507
+ for (const fc of functionCalls) {
3508
+ try {
3509
+ const result2 = await toolHandler(fc.name, fc.args);
3510
+ functionResponses.push({
3511
+ name: fc.name,
3512
+ response: { result: typeof result2 === "string" ? result2 : JSON.stringify(result2) }
3513
+ });
3514
+ } catch (error) {
3515
+ functionResponses.push({
3516
+ name: fc.name,
3517
+ response: { error: error instanceof Error ? error.message : String(error) }
3518
+ });
3519
+ }
3520
+ }
3521
+ const functionResponseParts = functionResponses.map((fr) => ({
3522
+ functionResponse: {
3523
+ name: fr.name,
3524
+ response: fr.response
3525
+ }
3526
+ }));
3527
+ currentUserMessage = functionResponseParts;
3528
+ }
3529
+ if (iterations >= maxIterations) {
3530
+ throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);
3531
+ }
3532
+ return finalText;
3533
+ }
3534
+ // ============================================================
3535
+ // OPENAI IMPLEMENTATION
3536
+ // ============================================================
3537
+ static async _openaiText(messages, modelName, options) {
3538
+ const apiKey = options.apiKey || process.env.OPENAI_API_KEY || "";
3539
+ const openai = new import_openai.default({ apiKey });
3540
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3541
+ const response = await openai.chat.completions.create({
3542
+ model: modelName,
3543
+ messages: [
3544
+ { role: "system", content: systemPrompt },
3545
+ { role: "user", content: messages.user }
3546
+ ],
3547
+ max_tokens: options.maxTokens || 1e3,
3548
+ temperature: options.temperature,
3549
+ top_p: options.topP
3550
+ });
3551
+ return response.choices[0]?.message?.content || "";
3552
+ }
3553
+ static async _openaiStream(messages, modelName, options, json) {
3554
+ const apiKey = options.apiKey || process.env.OPENAI_API_KEY || "";
3555
+ const openai = new import_openai.default({ apiKey });
3556
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3557
+ const stream = await openai.chat.completions.create({
3558
+ model: modelName,
3559
+ messages: [
3560
+ { role: "system", content: systemPrompt },
3561
+ { role: "user", content: messages.user }
3562
+ ],
3563
+ max_tokens: options.maxTokens || 1e3,
3564
+ temperature: options.temperature,
3565
+ top_p: options.topP,
3566
+ response_format: json ? { type: "json_object" } : void 0,
3567
+ stream: true
3568
+ });
3569
+ let fullText = "";
3570
+ for await (const chunk of stream) {
3571
+ const content = chunk.choices[0]?.delta?.content || "";
3572
+ if (content) {
3573
+ fullText += content;
3574
+ if (options.partial) {
3575
+ options.partial(content);
3576
+ }
3577
+ }
3578
+ }
3579
+ if (json) {
3580
+ return this._parseJSON(fullText);
3581
+ }
3582
+ return fullText;
3583
+ }
3584
+ static async _openaiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations) {
3585
+ const apiKey = options.apiKey || process.env.OPENAI_API_KEY || "";
3586
+ const openai = new import_openai.default({ apiKey });
3587
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3588
+ const openaiTools = tools.map((tool) => ({
3589
+ type: "function",
3590
+ function: {
3591
+ name: tool.name,
3592
+ description: tool.description,
3593
+ parameters: {
3594
+ type: tool.input_schema.type,
3595
+ properties: tool.input_schema.properties,
3596
+ required: tool.input_schema.required || []
3597
+ }
3598
+ }
3599
+ }));
3600
+ const conversationMessages = [
3601
+ { role: "system", content: systemPrompt },
3602
+ { role: "user", content: messages.user }
3603
+ ];
3604
+ let iterations = 0;
3605
+ let finalText = "";
3606
+ while (iterations < maxIterations) {
3607
+ iterations++;
3608
+ const stream = await openai.chat.completions.create({
3609
+ model: modelName,
3610
+ messages: conversationMessages,
3611
+ max_tokens: options.maxTokens || 4e3,
3612
+ temperature: options.temperature,
3613
+ top_p: options.topP,
3614
+ tools: openaiTools,
3615
+ stream: true
3616
+ });
3617
+ let responseText = "";
3618
+ const toolCalls = [];
3619
+ const toolCallsInProgress = /* @__PURE__ */ new Map();
3620
+ for await (const chunk of stream) {
3621
+ const delta = chunk.choices[0]?.delta;
3622
+ if (delta?.content) {
3623
+ responseText += delta.content;
3624
+ if (options.partial) {
3625
+ options.partial(delta.content);
3626
+ }
3627
+ }
3628
+ if (delta?.tool_calls) {
3629
+ for (const toolCallDelta of delta.tool_calls) {
3630
+ const index = toolCallDelta.index;
3631
+ if (!toolCallsInProgress.has(index)) {
3632
+ toolCallsInProgress.set(index, {
3633
+ id: toolCallDelta.id || "",
3634
+ name: toolCallDelta.function?.name || "",
3635
+ arguments: ""
3636
+ });
3637
+ }
3638
+ const tc = toolCallsInProgress.get(index);
3639
+ if (toolCallDelta.id) {
3640
+ tc.id = toolCallDelta.id;
3641
+ }
3642
+ if (toolCallDelta.function?.name) {
3643
+ tc.name = toolCallDelta.function.name;
3644
+ }
3645
+ if (toolCallDelta.function?.arguments) {
3646
+ tc.arguments += toolCallDelta.function.arguments;
3647
+ }
3648
+ }
3649
+ }
3650
+ }
3651
+ for (const tc of toolCallsInProgress.values()) {
3652
+ if (tc.id && tc.name) {
3653
+ toolCalls.push(tc);
3654
+ }
3655
+ }
3656
+ if (toolCalls.length === 0) {
3657
+ finalText = responseText;
3658
+ break;
3659
+ }
3660
+ conversationMessages.push({
3661
+ role: "assistant",
3662
+ content: responseText || null,
3663
+ tool_calls: toolCalls.map((tc) => ({
3664
+ id: tc.id,
3665
+ type: "function",
3666
+ function: {
3667
+ name: tc.name,
3668
+ arguments: tc.arguments
3669
+ }
3670
+ }))
3671
+ });
3672
+ for (const tc of toolCalls) {
3673
+ let result;
3674
+ try {
3675
+ const args = JSON.parse(tc.arguments);
3676
+ const toolResult = await toolHandler(tc.name, args);
3677
+ result = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult);
3678
+ } catch (error) {
3679
+ result = JSON.stringify({ error: error instanceof Error ? error.message : String(error) });
3680
+ }
3681
+ conversationMessages.push({
3682
+ role: "tool",
3683
+ tool_call_id: tc.id,
3684
+ content: result
3685
+ });
3686
+ }
3687
+ }
3688
+ if (iterations >= maxIterations) {
3689
+ throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);
3690
+ }
3691
+ return finalText;
3692
+ }
3693
+ // ============================================================
3314
3694
  // JSON PARSING HELPER
3315
3695
  // ============================================================
3316
3696
  /**
@@ -4599,18 +4979,56 @@ var AnthropicLLM = class extends BaseLLM {
4599
4979
  };
4600
4980
  var anthropicLLM = new AnthropicLLM();
4601
4981
 
4602
- // src/userResponse/index.ts
4982
+ // src/userResponse/gemini.ts
4603
4983
  var import_dotenv3 = __toESM(require("dotenv"));
4604
4984
  import_dotenv3.default.config();
4985
+ var GeminiLLM = class extends BaseLLM {
4986
+ constructor(config) {
4987
+ super(config);
4988
+ }
4989
+ getDefaultModel() {
4990
+ return "gemini/gemini-2.5-flash";
4991
+ }
4992
+ getDefaultApiKey() {
4993
+ return process.env.GEMINI_API_KEY;
4994
+ }
4995
+ getProviderName() {
4996
+ return "Gemini";
4997
+ }
4998
+ };
4999
+ var geminiLLM = new GeminiLLM();
5000
+
5001
+ // src/userResponse/openai.ts
5002
+ var import_dotenv4 = __toESM(require("dotenv"));
5003
+ import_dotenv4.default.config();
5004
+ var OpenAILLM = class extends BaseLLM {
5005
+ constructor(config) {
5006
+ super(config);
5007
+ }
5008
+ getDefaultModel() {
5009
+ return "openai/gpt-4.1";
5010
+ }
5011
+ getDefaultApiKey() {
5012
+ return process.env.OPENAI_API_KEY;
5013
+ }
5014
+ getProviderName() {
5015
+ return "OpenAI";
5016
+ }
5017
+ };
5018
+ var openaiLLM = new OpenAILLM();
5019
+
5020
+ // src/userResponse/index.ts
5021
+ var import_dotenv5 = __toESM(require("dotenv"));
5022
+ import_dotenv5.default.config();
4605
5023
  function getLLMProviders() {
4606
5024
  const envProviders = process.env.LLM_PROVIDERS;
4607
- const DEFAULT_PROVIDERS = ["anthropic", "groq"];
5025
+ const DEFAULT_PROVIDERS = ["anthropic", "gemini", "openai", "groq"];
4608
5026
  if (!envProviders) {
4609
5027
  return DEFAULT_PROVIDERS;
4610
5028
  }
4611
5029
  try {
4612
5030
  const providers = JSON.parse(envProviders);
4613
- const validProviders = providers.filter((p) => p === "anthropic" || p === "groq");
5031
+ const validProviders = providers.filter((p) => p === "anthropic" || p === "groq" || p === "gemini" || p === "openai");
4614
5032
  if (validProviders.length === 0) {
4615
5033
  return DEFAULT_PROVIDERS;
4616
5034
  }
@@ -4653,10 +5071,44 @@ var useGroqMethod = async (prompt, components, apiKey, logCollector, conversatio
4653
5071
  logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);
4654
5072
  return matchResult;
4655
5073
  };
5074
+ var useGeminiMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools, userId) => {
5075
+ logger.debug("[useGeminiMethod] Initializing Gemini LLM matching method");
5076
+ logger.debug(`[useGeminiMethod] Response mode: ${responseMode}`);
5077
+ const msg = `Using Gemini LLM ${responseMode === "text" ? "text response" : "matching"} method...`;
5078
+ logger.info(msg);
5079
+ logCollector?.info(msg);
5080
+ if (responseMode === "component" && components.length === 0) {
5081
+ const emptyMsg = "Components not loaded in memory. Please ensure components are fetched first.";
5082
+ logger.error("[useGeminiMethod] No components available");
5083
+ logCollector?.error(emptyMsg);
5084
+ return { success: false, errors: [emptyMsg] };
5085
+ }
5086
+ logger.debug(`[useGeminiMethod] Processing with ${components.length} components`);
5087
+ const matchResult = await geminiLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
5088
+ logger.info(`[useGeminiMethod] Successfully generated ${responseMode} using Gemini`);
5089
+ return matchResult;
5090
+ };
5091
+ var useOpenAIMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools, userId) => {
5092
+ logger.debug("[useOpenAIMethod] Initializing OpenAI GPT matching method");
5093
+ logger.debug(`[useOpenAIMethod] Response mode: ${responseMode}`);
5094
+ const msg = `Using OpenAI GPT ${responseMode === "text" ? "text response" : "matching"} method...`;
5095
+ logger.info(msg);
5096
+ logCollector?.info(msg);
5097
+ if (responseMode === "component" && components.length === 0) {
5098
+ const emptyMsg = "Components not loaded in memory. Please ensure components are fetched first.";
5099
+ logger.error("[useOpenAIMethod] No components available");
5100
+ logCollector?.error(emptyMsg);
5101
+ return { success: false, errors: [emptyMsg] };
5102
+ }
5103
+ logger.debug(`[useOpenAIMethod] Processing with ${components.length} components`);
5104
+ const matchResult = await openaiLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
5105
+ logger.info(`[useOpenAIMethod] Successfully generated ${responseMode} using OpenAI`);
5106
+ return matchResult;
5107
+ };
4656
5108
  var getUserResponseFromCache = async (prompt) => {
4657
5109
  return false;
4658
5110
  };
4659
- var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools, userId) => {
5111
+ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools, userId) => {
4660
5112
  logger.debug(`[get_user_response] Starting user response generation for prompt: "${prompt.substring(0, 50)}..."`);
4661
5113
  logger.debug(`[get_user_response] Response mode: ${responseMode}`);
4662
5114
  logger.debug("[get_user_response] Checking cache for existing response");
@@ -4692,6 +5144,10 @@ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey,
4692
5144
  result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
4693
5145
  } else if (provider === "groq") {
4694
5146
  result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
5147
+ } else if (provider === "gemini") {
5148
+ result = await useGeminiMethod(prompt, components, geminiApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
5149
+ } else if (provider === "openai") {
5150
+ result = await useOpenAIMethod(prompt, components, openaiApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
4695
5151
  } else {
4696
5152
  logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);
4697
5153
  errors.push(`Unknown provider: ${provider}`);
@@ -5036,7 +5492,7 @@ var CONTEXT_CONFIG = {
5036
5492
  };
5037
5493
 
5038
5494
  // src/handlers/user-prompt-request.ts
5039
- var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools, userId) => {
5495
+ var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools, userId) => {
5040
5496
  const errors = [];
5041
5497
  logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
5042
5498
  const parseResult = UserPromptRequestMessageSchema.safeParse(data);
@@ -5111,6 +5567,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
5111
5567
  components,
5112
5568
  anthropicApiKey,
5113
5569
  groqApiKey,
5570
+ geminiApiKey,
5571
+ openaiApiKey,
5114
5572
  llmProviders,
5115
5573
  logCollector,
5116
5574
  conversationHistory,
@@ -5209,8 +5667,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
5209
5667
  wsId
5210
5668
  };
5211
5669
  };
5212
- async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools, userId) {
5213
- const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools, userId);
5670
+ async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools, userId) {
5671
+ const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools, userId);
5214
5672
  sendDataResponse4(
5215
5673
  response.id || data.id,
5216
5674
  {
@@ -5241,12 +5699,13 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
5241
5699
  }
5242
5700
 
5243
5701
  // src/handlers/user-prompt-suggestions.ts
5244
- async function handleUserPromptSuggestions(data, components, sendMessage) {
5702
+ async function handleUserPromptSuggestions(data, components, sendMessage, collections, userId) {
5245
5703
  try {
5246
5704
  const request = UserPromptSuggestionsMessageSchema.parse(data);
5247
5705
  const { id, payload, from } = request;
5248
- const { prompt, limit = 5 } = payload;
5706
+ const { prompt, limit = 5, similarityThreshold = 0.1 } = payload;
5249
5707
  const wsId = from.id;
5708
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Processing user prompt suggestions: ${prompt}`);
5250
5709
  if (!prompt || prompt.trim().length === 0) {
5251
5710
  sendResponse(id, {
5252
5711
  success: false,
@@ -5254,7 +5713,79 @@ async function handleUserPromptSuggestions(data, components, sendMessage) {
5254
5713
  }, sendMessage, wsId);
5255
5714
  return;
5256
5715
  }
5716
+ const componentSearchHandler = collections?.["components"]?.["search"];
5717
+ const bookmarkSearchHandler = collections?.["bookmarks"]?.["search"];
5718
+ let componentSuggestions = [];
5719
+ let bookmarkSuggestions = [];
5720
+ let useEmbeddingSearch = false;
5721
+ const searchPromises = [];
5722
+ if (componentSearchHandler) {
5723
+ searchPromises.push(
5724
+ (async () => {
5725
+ try {
5726
+ logger.info("Using embedding-based search for components");
5727
+ const result = await componentSearchHandler({ prompt, limit });
5728
+ if (result.success && result.suggestions) {
5729
+ componentSuggestions = result.suggestions.map((s) => ({
5730
+ ...s,
5731
+ suggestionType: "component"
5732
+ }));
5733
+ useEmbeddingSearch = true;
5734
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${componentSuggestions.length} component suggestions`);
5735
+ }
5736
+ } catch (embeddingError) {
5737
+ logger.warn("Component embedding search failed:", embeddingError);
5738
+ }
5739
+ })()
5740
+ );
5741
+ }
5742
+ if (bookmarkSearchHandler && userId && userId !== "anonymous") {
5743
+ searchPromises.push(
5744
+ (async () => {
5745
+ try {
5746
+ logger.info(`Using embedding-based search for bookmarks (user: ${userId})`);
5747
+ const result = await bookmarkSearchHandler({ prompt, userId, limit });
5748
+ if (result.success && result.suggestions) {
5749
+ bookmarkSuggestions = result.suggestions.map((s) => ({
5750
+ ...s,
5751
+ suggestionType: "bookmark"
5752
+ }));
5753
+ useEmbeddingSearch = true;
5754
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${bookmarkSuggestions.length} bookmark suggestions`);
5755
+ }
5756
+ } catch (embeddingError) {
5757
+ logger.warn("Bookmark embedding search failed:", embeddingError);
5758
+ }
5759
+ })()
5760
+ );
5761
+ }
5762
+ if (searchPromises.length > 0) {
5763
+ await Promise.all(searchPromises);
5764
+ }
5765
+ if (useEmbeddingSearch && (componentSuggestions.length > 0 || bookmarkSuggestions.length > 0)) {
5766
+ const filteredComponentSuggestions = componentSuggestions.filter(
5767
+ (s) => (s.similarity || 0) >= similarityThreshold
5768
+ );
5769
+ const filteredBookmarkSuggestions = bookmarkSuggestions.filter(
5770
+ (s) => (s.similarity || 0) >= similarityThreshold
5771
+ );
5772
+ const allSuggestions = [...filteredComponentSuggestions, ...filteredBookmarkSuggestions].sort((a, b) => (b.similarity || 0) - (a.similarity || 0)).slice(0, limit);
5773
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Filtered by threshold ${similarityThreshold}: ${componentSuggestions.length} -> ${filteredComponentSuggestions.length} components, ${bookmarkSuggestions.length} -> ${filteredBookmarkSuggestions.length} bookmarks`);
5774
+ sendResponse(id, {
5775
+ success: true,
5776
+ data: {
5777
+ prompt,
5778
+ suggestions: allSuggestions,
5779
+ count: allSuggestions.length,
5780
+ componentCount: filteredComponentSuggestions.length,
5781
+ bookmarkCount: filteredBookmarkSuggestions.length,
5782
+ message: `Found ${allSuggestions.length} suggestions (${filteredComponentSuggestions.length} components, ${filteredBookmarkSuggestions.length} bookmarks)`
5783
+ }
5784
+ }, sendMessage, wsId);
5785
+ return;
5786
+ }
5257
5787
  const displayComponents = components.filter((c) => c.isDisplayComp === true);
5788
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Using token-based approach. Display components: ${displayComponents.length}`);
5258
5789
  if (!displayComponents || displayComponents.length === 0) {
5259
5790
  sendResponse(id, {
5260
5791
  success: true,
@@ -5337,13 +5868,13 @@ function sendResponse(id, res, sendMessage, clientId) {
5337
5868
  }
5338
5869
 
5339
5870
  // src/userResponse/next-questions.ts
5340
- async function generateNextQuestions(originalUserPrompt, component, componentData, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory) {
5871
+ async function generateNextQuestions(originalUserPrompt, component, componentData, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, logCollector, conversationHistory) {
5341
5872
  try {
5342
5873
  logger.debug("[generateNextQuestions] Starting next questions generation");
5343
5874
  logger.debug(`[generateNextQuestions] User prompt: "${originalUserPrompt?.substring(0, 50)}..."`);
5344
5875
  logger.debug(`[generateNextQuestions] Component: ${component?.name || "unknown"} (${component?.type || "unknown"})`);
5345
5876
  logger.debug(`[generateNextQuestions] Component data available: ${componentData ? "yes" : "no"}`);
5346
- const providers = llmProviders || ["anthropic"];
5877
+ const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
5347
5878
  logger.info(`[generateNextQuestions] Using LLM providers: [${providers.join(", ")}]`);
5348
5879
  if (conversationHistory && conversationHistory.length > 0) {
5349
5880
  const exchangeCount = conversationHistory.split("\n").filter((l) => l.startsWith("Q")).length;
@@ -5368,6 +5899,26 @@ async function generateNextQuestions(originalUserPrompt, component, componentDat
5368
5899
  logCollector,
5369
5900
  conversationHistory
5370
5901
  );
5902
+ } else if (provider === "gemini") {
5903
+ logger.debug("[generateNextQuestions] Using Gemini LLM for next questions");
5904
+ result = await geminiLLM.generateNextQuestions(
5905
+ originalUserPrompt,
5906
+ component,
5907
+ componentData,
5908
+ geminiApiKey,
5909
+ logCollector,
5910
+ conversationHistory
5911
+ );
5912
+ } else if (provider === "openai") {
5913
+ logger.debug("[generateNextQuestions] Using OpenAI LLM for next questions");
5914
+ result = await openaiLLM.generateNextQuestions(
5915
+ originalUserPrompt,
5916
+ component,
5917
+ componentData,
5918
+ openaiApiKey,
5919
+ logCollector,
5920
+ conversationHistory
5921
+ );
5371
5922
  } else {
5372
5923
  logger.debug("[generateNextQuestions] Using Anthropic LLM for next questions");
5373
5924
  result = await anthropicLLM.generateNextQuestions(
@@ -5418,7 +5969,7 @@ async function generateNextQuestions(originalUserPrompt, component, componentDat
5418
5969
  }
5419
5970
 
5420
5971
  // src/handlers/actions-request.ts
5421
- async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiKey, llmProviders) {
5972
+ async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders) {
5422
5973
  try {
5423
5974
  logger.debug("[ACTIONS_REQ] Parsing incoming actions request");
5424
5975
  const actionsRequest = ActionsRequestMessageSchema.parse(data);
@@ -5490,6 +6041,8 @@ ${conversationHistory.substring(0, 200)}...`);
5490
6041
  componentData,
5491
6042
  anthropicApiKey,
5492
6043
  groqApiKey,
6044
+ geminiApiKey,
6045
+ openaiApiKey,
5493
6046
  llmProviders,
5494
6047
  logCollector,
5495
6048
  conversationHistory
@@ -5570,10 +6123,10 @@ function sendResponse2(id, res, sendMessage, clientId) {
5570
6123
  }
5571
6124
 
5572
6125
  // src/handlers/components-list-response.ts
5573
- async function handleComponentListResponse(data, storeComponents) {
6126
+ async function handleComponentListResponse(data, storeComponents, collections) {
5574
6127
  try {
5575
6128
  const componentListResponse = ComponentListResponseMessageSchema.parse(data);
5576
- const { id, payload } = componentListResponse;
6129
+ const { payload } = componentListResponse;
5577
6130
  const componentsList = payload.components;
5578
6131
  if (!componentsList) {
5579
6132
  logger.error("Components list not found in the response");
@@ -5581,6 +6134,20 @@ async function handleComponentListResponse(data, storeComponents) {
5581
6134
  }
5582
6135
  const components = ComponentsSchema.parse(componentsList);
5583
6136
  storeComponents(components);
6137
+ const embedHandler = collections?.["components"]?.["embed"];
6138
+ if (embedHandler) {
6139
+ try {
6140
+ logger.info("Embedding display components for semantic search...");
6141
+ const result = await embedHandler({ components });
6142
+ if (result.success) {
6143
+ logger.info(`Successfully embedded ${result.count} display components`);
6144
+ } else {
6145
+ logger.warn("Failed to embed components:", result.error);
6146
+ }
6147
+ } catch (embedError) {
6148
+ logger.warn("Failed to embed components:", embedError);
6149
+ }
6150
+ }
5584
6151
  return;
5585
6152
  } catch (error) {
5586
6153
  logger.error("Failed to handle user prompt request:", error);
@@ -5598,7 +6165,7 @@ async function handleUsersRequest(data, sendMessage) {
5598
6165
  const password = requestData?.password;
5599
6166
  const fullname = requestData?.fullname;
5600
6167
  const role = requestData?.role;
5601
- if (from.type !== "admin") {
6168
+ if (from.type !== "admin" && operation !== "getOne" && operation !== "getAll") {
5602
6169
  sendResponse3(id, {
5603
6170
  success: false,
5604
6171
  error: "Unauthorized: Only admin can manage users"
@@ -5885,13 +6452,29 @@ function getDashboardManager() {
5885
6452
  }
5886
6453
 
5887
6454
  // src/handlers/dashboards.ts
5888
- async function handleDashboardsRequest(data, sendMessage) {
6455
+ async function handleDashboardsRequest(data, collections, sendMessage) {
6456
+ const executeCollection = async (collection, op, params) => {
6457
+ const handler = collections[collection]?.[op];
6458
+ if (!handler) {
6459
+ return null;
6460
+ }
6461
+ return await handler(params);
6462
+ };
5889
6463
  try {
5890
6464
  const request = DashboardsRequestMessageSchema.parse(data);
5891
6465
  const { id, payload, from } = request;
5892
6466
  const { operation, data: requestData } = payload;
5893
6467
  const dashboardId = requestData?.dashboardId;
5894
6468
  const dashboard = requestData?.dashboard;
6469
+ const projectId = requestData?.projectId;
6470
+ const name = requestData?.name;
6471
+ const description = requestData?.description;
6472
+ const createdBy = requestData?.createdBy;
6473
+ const updatedBy = requestData?.updatedBy;
6474
+ const numericId = requestData?.id;
6475
+ const filters = requestData?.filters;
6476
+ const limit = requestData?.limit;
6477
+ const sort = requestData?.sort;
5895
6478
  if (from.type !== "admin") {
5896
6479
  sendResponse4(id, {
5897
6480
  success: false,
@@ -5903,19 +6486,22 @@ async function handleDashboardsRequest(data, sendMessage) {
5903
6486
  const dashboardManager2 = getDashboardManager();
5904
6487
  switch (operation) {
5905
6488
  case "create":
5906
- await handleCreate2(id, dashboardId, dashboard, dashboardManager2, sendMessage, from.id);
6489
+ await handleCreate2(id, dashboardId, dashboard, projectId, name, description, createdBy, executeCollection, dashboardManager2, sendMessage, from.id);
5907
6490
  break;
5908
6491
  case "update":
5909
- await handleUpdate2(id, dashboardId, dashboard, dashboardManager2, sendMessage, from.id);
6492
+ await handleUpdate2(id, numericId, dashboardId, dashboard, name, description, updatedBy, executeCollection, dashboardManager2, sendMessage, from.id);
5910
6493
  break;
5911
6494
  case "delete":
5912
- await handleDelete2(id, dashboardId, dashboardManager2, sendMessage, from.id);
6495
+ await handleDelete2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, from.id);
5913
6496
  break;
5914
6497
  case "getAll":
5915
- await handleGetAll2(id, dashboardManager2, sendMessage, from.id);
6498
+ await handleGetAll2(id, executeCollection, dashboardManager2, sendMessage, from.id);
5916
6499
  break;
5917
6500
  case "getOne":
5918
- await handleGetOne2(id, dashboardId, dashboardManager2, sendMessage, from.id);
6501
+ await handleGetOne2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, from.id);
6502
+ break;
6503
+ case "query":
6504
+ await handleQuery(id, filters, limit, sort, executeCollection, dashboardManager2, sendMessage, from.id);
5919
6505
  break;
5920
6506
  default:
5921
6507
  sendResponse4(id, {
@@ -5931,7 +6517,7 @@ async function handleDashboardsRequest(data, sendMessage) {
5931
6517
  }, sendMessage);
5932
6518
  }
5933
6519
  }
5934
- async function handleCreate2(id, dashboardId, dashboard, dashboardManager2, sendMessage, clientId) {
6520
+ async function handleCreate2(id, dashboardId, dashboard, projectId, name, description, createdBy, executeCollection, dashboardManager2, sendMessage, clientId) {
5935
6521
  if (!dashboardId || dashboardId.trim().length === 0) {
5936
6522
  sendResponse4(id, {
5937
6523
  success: false,
@@ -5939,21 +6525,50 @@ async function handleCreate2(id, dashboardId, dashboard, dashboardManager2, send
5939
6525
  }, sendMessage, clientId);
5940
6526
  return;
5941
6527
  }
5942
- if (!dashboard) {
6528
+ if (!projectId) {
5943
6529
  sendResponse4(id, {
5944
6530
  success: false,
5945
- error: "Dashboard data is required"
6531
+ error: "Project ID is required"
5946
6532
  }, sendMessage, clientId);
5947
6533
  return;
5948
6534
  }
5949
6535
  try {
6536
+ const result = await executeCollection("dashboards", "create", {
6537
+ dashboardId,
6538
+ projectId,
6539
+ name: name || "",
6540
+ description,
6541
+ dashboard,
6542
+ createdBy
6543
+ });
6544
+ if (result && result.success) {
6545
+ logger.info(`[DB] Dashboard created successfully, ID: ${result.data?.id}`);
6546
+ sendResponse4(id, {
6547
+ success: true,
6548
+ data: {
6549
+ id: result.data?.id,
6550
+ dashboardId: result.data?.dashboardId,
6551
+ dashboard: result.data?.dashboard || dashboard,
6552
+ message: `Dashboard created successfully (DB)`
6553
+ }
6554
+ }, sendMessage, clientId);
6555
+ return;
6556
+ }
6557
+ } catch (dbError) {
6558
+ logger.warn(`[DB] Failed to create dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6559
+ }
6560
+ try {
6561
+ if (!dashboard) {
6562
+ dashboard = {};
6563
+ }
5950
6564
  const createdDashboard = dashboardManager2.createDashboard(dashboardId, dashboard);
6565
+ logger.info(`[FILE] Dashboard '${dashboardId}' created successfully`);
5951
6566
  sendResponse4(id, {
5952
6567
  success: true,
5953
6568
  data: {
5954
6569
  dashboardId,
5955
6570
  dashboard: createdDashboard,
5956
- message: `Dashboard '${dashboardId}' created successfully`
6571
+ message: `Dashboard '${dashboardId}' created successfully (File)`
5957
6572
  }
5958
6573
  }, sendMessage, clientId);
5959
6574
  } catch (error) {
@@ -5963,36 +6578,56 @@ async function handleCreate2(id, dashboardId, dashboard, dashboardManager2, send
5963
6578
  }, sendMessage, clientId);
5964
6579
  }
5965
6580
  }
5966
- async function handleUpdate2(id, dashboardId, dashboard, dashboardManager2, sendMessage, clientId) {
5967
- if (!dashboardId || dashboardId.trim().length === 0) {
5968
- sendResponse4(id, {
5969
- success: false,
5970
- error: "Dashboard ID is required and cannot be empty"
5971
- }, sendMessage, clientId);
5972
- return;
5973
- }
5974
- if (!dashboard) {
6581
+ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, description, updatedBy, executeCollection, dashboardManager2, sendMessage, clientId) {
6582
+ if (!numericId) {
5975
6583
  sendResponse4(id, {
5976
6584
  success: false,
5977
- error: "Dashboard data is required"
6585
+ error: "Dashboard ID is required"
5978
6586
  }, sendMessage, clientId);
5979
6587
  return;
5980
6588
  }
5981
6589
  try {
5982
- const updatedDashboard = dashboardManager2.updateDashboard(dashboardId, dashboard);
6590
+ const result = await executeCollection("dashboards", "update", {
6591
+ id: numericId,
6592
+ name,
6593
+ description,
6594
+ dashboard,
6595
+ updatedBy
6596
+ });
6597
+ if (result && result.success) {
6598
+ logger.info(`[DB] Dashboard updated successfully, ID: ${numericId}`);
6599
+ sendResponse4(id, {
6600
+ success: true,
6601
+ data: {
6602
+ id: numericId,
6603
+ dashboardId: result.data?.dashboardId,
6604
+ dashboard: result.data?.dashboard || dashboard,
6605
+ message: `Dashboard updated successfully (DB)`
6606
+ }
6607
+ }, sendMessage, clientId);
6608
+ return;
6609
+ }
6610
+ } catch (dbError) {
6611
+ logger.warn(`[DB] Failed to update dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6612
+ }
6613
+ const fileStorageId = dashboardId || String(numericId);
6614
+ try {
6615
+ const updatedDashboard = dashboardManager2.updateDashboard(fileStorageId, dashboard);
5983
6616
  if (!updatedDashboard) {
5984
6617
  sendResponse4(id, {
5985
6618
  success: false,
5986
- error: `Dashboard '${dashboardId}' not found`
6619
+ error: `Dashboard '${fileStorageId}' not found`
5987
6620
  }, sendMessage, clientId);
5988
6621
  return;
5989
6622
  }
6623
+ logger.info(`[FILE] Dashboard '${fileStorageId}' updated successfully`);
5990
6624
  sendResponse4(id, {
5991
6625
  success: true,
5992
6626
  data: {
5993
- dashboardId,
6627
+ id: numericId,
6628
+ dashboardId: fileStorageId,
5994
6629
  dashboard: updatedDashboard,
5995
- message: `Dashboard '${dashboardId}' updated successfully`
6630
+ message: `Dashboard '${fileStorageId}' updated successfully (File)`
5996
6631
  }
5997
6632
  }, sendMessage, clientId);
5998
6633
  } catch (error) {
@@ -6002,65 +6637,154 @@ async function handleUpdate2(id, dashboardId, dashboard, dashboardManager2, send
6002
6637
  }, sendMessage, clientId);
6003
6638
  }
6004
6639
  }
6005
- async function handleDelete2(id, dashboardId, dashboardManager2, sendMessage, clientId) {
6006
- if (!dashboardId || dashboardId.trim().length === 0) {
6640
+ async function handleDelete2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, clientId) {
6641
+ if (!numericId) {
6007
6642
  sendResponse4(id, {
6008
6643
  success: false,
6009
- error: "Dashboard ID is required and cannot be empty"
6644
+ error: "Dashboard ID is required"
6010
6645
  }, sendMessage, clientId);
6011
6646
  return;
6012
6647
  }
6013
- const deleted = dashboardManager2.deleteDashboard(dashboardId);
6648
+ try {
6649
+ const result = await executeCollection("dashboards", "delete", { id: numericId });
6650
+ if (result && result.success) {
6651
+ logger.info(`[DB] Dashboard deleted successfully, ID: ${numericId}`);
6652
+ sendResponse4(id, {
6653
+ success: true,
6654
+ data: {
6655
+ id: numericId,
6656
+ message: `Dashboard deleted successfully (DB)`
6657
+ }
6658
+ }, sendMessage, clientId);
6659
+ return;
6660
+ }
6661
+ } catch (dbError) {
6662
+ logger.warn(`[DB] Failed to delete dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6663
+ }
6664
+ const fileStorageId = dashboardId || String(numericId);
6665
+ const deleted = dashboardManager2.deleteDashboard(fileStorageId);
6014
6666
  if (!deleted) {
6015
6667
  sendResponse4(id, {
6016
6668
  success: false,
6017
- error: `Dashboard '${dashboardId}' not found`
6669
+ error: `Dashboard '${fileStorageId}' not found`
6018
6670
  }, sendMessage, clientId);
6019
6671
  return;
6020
6672
  }
6673
+ logger.info(`[FILE] Dashboard '${fileStorageId}' deleted successfully`);
6021
6674
  sendResponse4(id, {
6022
6675
  success: true,
6023
6676
  data: {
6024
- dashboardId,
6025
- message: `Dashboard '${dashboardId}' deleted successfully`
6677
+ id: numericId,
6678
+ dashboardId: fileStorageId,
6679
+ message: `Dashboard '${fileStorageId}' deleted successfully (File)`
6026
6680
  }
6027
6681
  }, sendMessage, clientId);
6028
6682
  }
6029
- async function handleGetAll2(id, dashboardManager2, sendMessage, clientId) {
6683
+ async function handleGetAll2(id, executeCollection, dashboardManager2, sendMessage, clientId) {
6684
+ try {
6685
+ const result = await executeCollection("dashboards", "getAll", {});
6686
+ if (result && result.success) {
6687
+ logger.info(`[DB] Retrieved ${result.count} dashboards`);
6688
+ sendResponse4(id, {
6689
+ success: true,
6690
+ data: {
6691
+ dashboards: result.data,
6692
+ count: result.count,
6693
+ message: `Retrieved ${result.count} dashboards (DB)`
6694
+ }
6695
+ }, sendMessage, clientId);
6696
+ return;
6697
+ }
6698
+ } catch (dbError) {
6699
+ logger.warn(`[DB] Failed to get all dashboards, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6700
+ }
6030
6701
  const dashboards = dashboardManager2.getAllDashboards();
6031
- logger.info(`Admin retrieved all dashboards (count: ${dashboards.length})`);
6702
+ logger.info(`[FILE] Retrieved ${dashboards.length} dashboards`);
6032
6703
  sendResponse4(id, {
6033
6704
  success: true,
6034
6705
  data: {
6035
6706
  dashboards,
6036
6707
  count: dashboards.length,
6037
- message: `Retrieved ${dashboards.length} dashboards`
6708
+ message: `Retrieved ${dashboards.length} dashboards (File)`
6038
6709
  }
6039
6710
  }, sendMessage, clientId);
6040
6711
  }
6041
- async function handleGetOne2(id, dashboardId, dashboardManager2, sendMessage, clientId) {
6042
- if (!dashboardId || dashboardId.trim().length === 0) {
6712
+ async function handleGetOne2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, clientId) {
6713
+ if (!numericId) {
6043
6714
  sendResponse4(id, {
6044
6715
  success: false,
6045
- error: "Dashboard ID is required and cannot be empty"
6716
+ error: "Dashboard ID is required"
6046
6717
  }, sendMessage, clientId);
6047
6718
  return;
6048
6719
  }
6049
- const dashboard = dashboardManager2.getDashboard(dashboardId);
6720
+ try {
6721
+ const result = await executeCollection("dashboards", "getOne", { id: numericId });
6722
+ if (result && result.success) {
6723
+ logger.info(`[DB] Retrieved dashboard ID: ${numericId}`);
6724
+ sendResponse4(id, {
6725
+ success: true,
6726
+ data: {
6727
+ id: numericId,
6728
+ dashboardId: result.data?.dashboardId,
6729
+ dashboard: result.data?.dashboard || result.data,
6730
+ message: `Retrieved dashboard (DB)`
6731
+ }
6732
+ }, sendMessage, clientId);
6733
+ return;
6734
+ }
6735
+ } catch (dbError) {
6736
+ logger.warn(`[DB] Failed to get dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6737
+ }
6738
+ const fileStorageId = dashboardId || String(numericId);
6739
+ const dashboard = dashboardManager2.getDashboard(fileStorageId);
6050
6740
  if (!dashboard) {
6051
6741
  sendResponse4(id, {
6052
6742
  success: false,
6053
- error: `Dashboard '${dashboardId}' not found`
6743
+ error: `Dashboard '${fileStorageId}' not found`
6054
6744
  }, sendMessage, clientId);
6055
6745
  return;
6056
6746
  }
6057
- logger.info(`Admin retrieved dashboard: ${dashboardId}`);
6747
+ logger.info(`[FILE] Retrieved dashboard: ${fileStorageId}`);
6058
6748
  sendResponse4(id, {
6059
6749
  success: true,
6060
6750
  data: {
6061
- dashboardId,
6751
+ id: numericId,
6752
+ dashboardId: fileStorageId,
6062
6753
  dashboard,
6063
- message: `Retrieved dashboard '${dashboardId}'`
6754
+ message: `Retrieved dashboard '${fileStorageId}' (File)`
6755
+ }
6756
+ }, sendMessage, clientId);
6757
+ }
6758
+ async function handleQuery(id, filters, limit, sort, executeCollection, dashboardManager2, sendMessage, clientId) {
6759
+ try {
6760
+ const result = await executeCollection("dashboards", "query", {
6761
+ filters: filters || {},
6762
+ limit,
6763
+ sort
6764
+ });
6765
+ if (result && result.success) {
6766
+ logger.info(`[DB] Query returned ${result.count} dashboards`);
6767
+ sendResponse4(id, {
6768
+ success: true,
6769
+ data: {
6770
+ dashboards: result.data,
6771
+ count: result.count,
6772
+ message: `Query returned ${result.count} dashboards (DB)`
6773
+ }
6774
+ }, sendMessage, clientId);
6775
+ return;
6776
+ }
6777
+ } catch (dbError) {
6778
+ logger.warn(`[DB] Failed to query dashboards: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6779
+ }
6780
+ const dashboards = dashboardManager2.getAllDashboards();
6781
+ logger.info(`[FILE] Retrieved ${dashboards.length} dashboards (all - no query filter)`);
6782
+ sendResponse4(id, {
6783
+ success: true,
6784
+ data: {
6785
+ dashboards,
6786
+ count: dashboards.length,
6787
+ message: `Retrieved ${dashboards.length} dashboards (File - no query filter)`
6064
6788
  }
6065
6789
  }, sendMessage, clientId);
6066
6790
  }
@@ -6093,13 +6817,29 @@ function setReportManager(manager) {
6093
6817
  }
6094
6818
 
6095
6819
  // src/handlers/reports.ts
6096
- async function handleReportsRequest(data, sendMessage) {
6820
+ async function handleReportsRequest(data, collections, sendMessage) {
6821
+ const executeCollection = async (collection, op, params) => {
6822
+ const handler = collections[collection]?.[op];
6823
+ if (!handler) {
6824
+ return null;
6825
+ }
6826
+ return await handler(params);
6827
+ };
6097
6828
  try {
6098
6829
  const request = ReportsRequestMessageSchema.parse(data);
6099
6830
  const { id, payload, from } = request;
6100
6831
  const { operation, data: requestData } = payload;
6101
6832
  const reportId = requestData?.reportId;
6102
6833
  const report = requestData?.report;
6834
+ const projectId = requestData?.projectId;
6835
+ const name = requestData?.name;
6836
+ const description = requestData?.description;
6837
+ const createdBy = requestData?.createdBy;
6838
+ const updatedBy = requestData?.updatedBy;
6839
+ const numericId = requestData?.id;
6840
+ const filters = requestData?.filters;
6841
+ const limit = requestData?.limit;
6842
+ const sort = requestData?.sort;
6103
6843
  if (from.type !== "admin") {
6104
6844
  sendResponse5(id, {
6105
6845
  success: false,
@@ -6111,19 +6851,22 @@ async function handleReportsRequest(data, sendMessage) {
6111
6851
  const reportManager2 = getReportManager();
6112
6852
  switch (operation) {
6113
6853
  case "create":
6114
- await handleCreate3(id, reportId, report, reportManager2, sendMessage, from.id);
6854
+ await handleCreate3(id, reportId, report, projectId, name, description, createdBy, executeCollection, reportManager2, sendMessage, from.id);
6115
6855
  break;
6116
6856
  case "update":
6117
- await handleUpdate3(id, reportId, report, reportManager2, sendMessage, from.id);
6857
+ await handleUpdate3(id, numericId, reportId, report, name, description, updatedBy, executeCollection, reportManager2, sendMessage, from.id);
6118
6858
  break;
6119
6859
  case "delete":
6120
- await handleDelete3(id, reportId, reportManager2, sendMessage, from.id);
6860
+ await handleDelete3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, from.id);
6121
6861
  break;
6122
6862
  case "getAll":
6123
- await handleGetAll3(id, reportManager2, sendMessage, from.id);
6863
+ await handleGetAll3(id, executeCollection, reportManager2, sendMessage, from.id);
6124
6864
  break;
6125
6865
  case "getOne":
6126
- await handleGetOne3(id, reportId, reportManager2, sendMessage, from.id);
6866
+ await handleGetOne3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, from.id);
6867
+ break;
6868
+ case "query":
6869
+ await handleQuery2(id, filters, limit, sort, executeCollection, reportManager2, sendMessage, from.id);
6127
6870
  break;
6128
6871
  default:
6129
6872
  sendResponse5(id, {
@@ -6139,7 +6882,7 @@ async function handleReportsRequest(data, sendMessage) {
6139
6882
  }, sendMessage);
6140
6883
  }
6141
6884
  }
6142
- async function handleCreate3(id, reportId, report, reportManager2, sendMessage, clientId) {
6885
+ async function handleCreate3(id, reportId, report, projectId, name, description, createdBy, executeCollection, reportManager2, sendMessage, clientId) {
6143
6886
  if (!reportId || reportId.trim().length === 0) {
6144
6887
  sendResponse5(id, {
6145
6888
  success: false,
@@ -6147,21 +6890,50 @@ async function handleCreate3(id, reportId, report, reportManager2, sendMessage,
6147
6890
  }, sendMessage, clientId);
6148
6891
  return;
6149
6892
  }
6150
- if (!report) {
6893
+ if (!projectId) {
6151
6894
  sendResponse5(id, {
6152
6895
  success: false,
6153
- error: "Report data is required"
6896
+ error: "Project ID is required"
6154
6897
  }, sendMessage, clientId);
6155
6898
  return;
6156
6899
  }
6157
6900
  try {
6901
+ const result = await executeCollection("reports", "create", {
6902
+ reportId,
6903
+ projectId,
6904
+ name: name || "",
6905
+ description,
6906
+ report,
6907
+ createdBy
6908
+ });
6909
+ if (result && result.success) {
6910
+ logger.info(`[DB] Report created successfully, ID: ${result.data?.id}`);
6911
+ sendResponse5(id, {
6912
+ success: true,
6913
+ data: {
6914
+ id: result.data?.id,
6915
+ reportId: result.data?.reportId,
6916
+ report: result.data?.report || report,
6917
+ message: `Report created successfully (DB)`
6918
+ }
6919
+ }, sendMessage, clientId);
6920
+ return;
6921
+ }
6922
+ } catch (dbError) {
6923
+ logger.warn(`[DB] Failed to create report, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6924
+ }
6925
+ try {
6926
+ if (!report) {
6927
+ report = {};
6928
+ }
6158
6929
  const createdReport = reportManager2.createReport(reportId, report);
6930
+ logger.info(`[FILE] Report '${reportId}' created successfully`);
6159
6931
  sendResponse5(id, {
6160
6932
  success: true,
6161
6933
  data: {
6162
6934
  reportId,
6163
6935
  report: createdReport,
6164
- message: `Report '${reportId}' created successfully`
6936
+ message: `Report '${reportId}' created successfully (File)`
6165
6937
  }
6166
6938
  }, sendMessage, clientId);
6167
6939
  } catch (error) {
@@ -6171,36 +6943,56 @@ async function handleCreate3(id, reportId, report, reportManager2, sendMessage,
6171
6943
  }, sendMessage, clientId);
6172
6944
  }
6173
6945
  }
6174
- async function handleUpdate3(id, reportId, report, reportManager2, sendMessage, clientId) {
6175
- if (!reportId || reportId.trim().length === 0) {
6946
+ async function handleUpdate3(id, numericId, reportId, report, name, description, updatedBy, executeCollection, reportManager2, sendMessage, clientId) {
6947
+ if (!numericId) {
6176
6948
  sendResponse5(id, {
6177
6949
  success: false,
6178
- error: "Report ID is required and cannot be empty"
6950
+ error: "Report ID is required"
6179
6951
  }, sendMessage, clientId);
6180
6952
  return;
6181
6953
  }
6182
- if (!report) {
6183
- sendResponse5(id, {
6184
- success: false,
6185
- error: "Report data is required"
6186
- }, sendMessage, clientId);
6187
- return;
6954
+ try {
6955
+ const result = await executeCollection("reports", "update", {
6956
+ id: numericId,
6957
+ name,
6958
+ description,
6959
+ report,
6960
+ updatedBy
6961
+ });
6962
+ if (result && result.success) {
6963
+ logger.info(`[DB] Report updated successfully, ID: ${numericId}`);
6964
+ sendResponse5(id, {
6965
+ success: true,
6966
+ data: {
6967
+ id: numericId,
6968
+ reportId: result.data?.reportId,
6969
+ report: result.data?.report || report,
6970
+ message: `Report updated successfully (DB)`
6971
+ }
6972
+ }, sendMessage, clientId);
6973
+ return;
6974
+ }
6975
+ } catch (dbError) {
6976
+ logger.warn(`[DB] Failed to update report, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6188
6977
  }
6978
+ const fileStorageId = reportId || String(numericId);
6189
6979
  try {
6190
- const updatedReport = reportManager2.updateReport(reportId, report);
6980
+ const updatedReport = reportManager2.updateReport(fileStorageId, report);
6191
6981
  if (!updatedReport) {
6192
6982
  sendResponse5(id, {
6193
6983
  success: false,
6194
- error: `Report '${reportId}' not found`
6984
+ error: `Report '${fileStorageId}' not found`
6195
6985
  }, sendMessage, clientId);
6196
6986
  return;
6197
6987
  }
6988
+ logger.info(`[FILE] Report '${fileStorageId}' updated successfully`);
6198
6989
  sendResponse5(id, {
6199
6990
  success: true,
6200
6991
  data: {
6201
- reportId,
6992
+ id: numericId,
6993
+ reportId: fileStorageId,
6202
6994
  report: updatedReport,
6203
- message: `Report '${reportId}' updated successfully`
6995
+ message: `Report '${fileStorageId}' updated successfully (File)`
6204
6996
  }
6205
6997
  }, sendMessage, clientId);
6206
6998
  } catch (error) {
@@ -6210,65 +7002,154 @@ async function handleUpdate3(id, reportId, report, reportManager2, sendMessage,
6210
7002
  }, sendMessage, clientId);
6211
7003
  }
6212
7004
  }
6213
- async function handleDelete3(id, reportId, reportManager2, sendMessage, clientId) {
6214
- if (!reportId || reportId.trim().length === 0) {
7005
+ async function handleDelete3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, clientId) {
7006
+ if (!numericId) {
6215
7007
  sendResponse5(id, {
6216
7008
  success: false,
6217
- error: "Report ID is required and cannot be empty"
7009
+ error: "Report ID is required"
6218
7010
  }, sendMessage, clientId);
6219
7011
  return;
6220
7012
  }
6221
- const deleted = reportManager2.deleteReport(reportId);
7013
+ try {
7014
+ const result = await executeCollection("reports", "delete", { id: numericId });
7015
+ if (result && result.success) {
7016
+ logger.info(`[DB] Report deleted successfully, ID: ${numericId}`);
7017
+ sendResponse5(id, {
7018
+ success: true,
7019
+ data: {
7020
+ id: numericId,
7021
+ message: `Report deleted successfully (DB)`
7022
+ }
7023
+ }, sendMessage, clientId);
7024
+ return;
7025
+ }
7026
+ } catch (dbError) {
7027
+ logger.warn(`[DB] Failed to delete report, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
7028
+ }
7029
+ const fileStorageId = reportId || String(numericId);
7030
+ const deleted = reportManager2.deleteReport(fileStorageId);
6222
7031
  if (!deleted) {
6223
7032
  sendResponse5(id, {
6224
7033
  success: false,
6225
- error: `Report '${reportId}' not found`
7034
+ error: `Report '${fileStorageId}' not found`
6226
7035
  }, sendMessage, clientId);
6227
7036
  return;
6228
7037
  }
7038
+ logger.info(`[FILE] Report '${fileStorageId}' deleted successfully`);
6229
7039
  sendResponse5(id, {
6230
7040
  success: true,
6231
7041
  data: {
6232
- reportId,
6233
- message: `Report '${reportId}' deleted successfully`
7042
+ id: numericId,
7043
+ reportId: fileStorageId,
7044
+ message: `Report '${fileStorageId}' deleted successfully (File)`
6234
7045
  }
6235
7046
  }, sendMessage, clientId);
6236
7047
  }
6237
- async function handleGetAll3(id, reportManager2, sendMessage, clientId) {
7048
+ async function handleGetAll3(id, executeCollection, reportManager2, sendMessage, clientId) {
7049
+ try {
7050
+ const result = await executeCollection("reports", "getAll", {});
7051
+ if (result && result.success) {
7052
+ logger.info(`[DB] Retrieved ${result.count} reports`);
7053
+ sendResponse5(id, {
7054
+ success: true,
7055
+ data: {
7056
+ reports: result.data,
7057
+ count: result.count,
7058
+ message: `Retrieved ${result.count} reports (DB)`
7059
+ }
7060
+ }, sendMessage, clientId);
7061
+ return;
7062
+ }
7063
+ } catch (dbError) {
7064
+ logger.warn(`[DB] Failed to get all reports, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
7065
+ }
6238
7066
  const reports = reportManager2.getAllReports();
6239
- logger.info(`Admin retrieved all reports (count: ${reports.length})`);
7067
+ logger.info(`[FILE] Retrieved ${reports.length} reports`);
6240
7068
  sendResponse5(id, {
6241
7069
  success: true,
6242
7070
  data: {
6243
7071
  reports,
6244
7072
  count: reports.length,
6245
- message: `Retrieved ${reports.length} reports`
7073
+ message: `Retrieved ${reports.length} reports (File)`
6246
7074
  }
6247
7075
  }, sendMessage, clientId);
6248
7076
  }
6249
- async function handleGetOne3(id, reportId, reportManager2, sendMessage, clientId) {
6250
- if (!reportId || reportId.trim().length === 0) {
7077
+ async function handleGetOne3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, clientId) {
7078
+ if (!numericId) {
6251
7079
  sendResponse5(id, {
6252
7080
  success: false,
6253
- error: "Report ID is required and cannot be empty"
7081
+ error: "Report ID is required"
6254
7082
  }, sendMessage, clientId);
6255
7083
  return;
6256
7084
  }
6257
- const report = reportManager2.getReport(reportId);
7085
+ try {
7086
+ const result = await executeCollection("reports", "getOne", { id: numericId });
7087
+ if (result && result.success) {
7088
+ logger.info(`[DB] Retrieved report ID: ${numericId}`);
7089
+ sendResponse5(id, {
7090
+ success: true,
7091
+ data: {
7092
+ id: numericId,
7093
+ reportId: result.data?.reportId,
7094
+ report: result.data?.report || result.data,
7095
+ message: `Retrieved report (DB)`
7096
+ }
7097
+ }, sendMessage, clientId);
7098
+ return;
7099
+ }
7100
+ } catch (dbError) {
7101
+ logger.warn(`[DB] Failed to get report, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
7102
+ }
7103
+ const fileStorageId = reportId || String(numericId);
7104
+ const report = reportManager2.getReport(fileStorageId);
6258
7105
  if (!report) {
6259
7106
  sendResponse5(id, {
6260
7107
  success: false,
6261
- error: `Report '${reportId}' not found`
7108
+ error: `Report '${fileStorageId}' not found`
6262
7109
  }, sendMessage, clientId);
6263
7110
  return;
6264
7111
  }
6265
- logger.info(`Admin retrieved report: ${reportId}`);
7112
+ logger.info(`[FILE] Retrieved report: ${fileStorageId}`);
6266
7113
  sendResponse5(id, {
6267
7114
  success: true,
6268
7115
  data: {
6269
- reportId,
7116
+ id: numericId,
7117
+ reportId: fileStorageId,
6270
7118
  report,
6271
- message: `Retrieved report '${reportId}'`
7119
+ message: `Retrieved report '${fileStorageId}' (File)`
7120
+ }
7121
+ }, sendMessage, clientId);
7122
+ }
7123
+ async function handleQuery2(id, filters, limit, sort, executeCollection, reportManager2, sendMessage, clientId) {
7124
+ try {
7125
+ const result = await executeCollection("reports", "query", {
7126
+ filters: filters || {},
7127
+ limit,
7128
+ sort
7129
+ });
7130
+ if (result && result.success) {
7131
+ logger.info(`[DB] Query returned ${result.count} reports`);
7132
+ sendResponse5(id, {
7133
+ success: true,
7134
+ data: {
7135
+ reports: result.data,
7136
+ count: result.count,
7137
+ message: `Query returned ${result.count} reports (DB)`
7138
+ }
7139
+ }, sendMessage, clientId);
7140
+ return;
7141
+ }
7142
+ } catch (dbError) {
7143
+ logger.warn(`[DB] Failed to query reports: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
7144
+ }
7145
+ const reports = reportManager2.getAllReports();
7146
+ logger.info(`[FILE] Retrieved ${reports.length} reports (all - no query filter)`);
7147
+ sendResponse5(id, {
7148
+ success: true,
7149
+ data: {
7150
+ reports,
7151
+ count: reports.length,
7152
+ message: `Retrieved ${reports.length} reports (File - no query filter)`
6272
7153
  }
6273
7154
  }, sendMessage, clientId);
6274
7155
  }
@@ -6288,6 +7169,297 @@ function sendResponse5(id, res, sendMessage, clientId) {
6288
7169
  sendMessage(response);
6289
7170
  }
6290
7171
 
7172
+ // src/handlers/uis.ts
7173
+ async function handleUIsRequest(data, collections, sendMessage) {
7174
+ const executeCollection = async (collection, op, params) => {
7175
+ const handler = collections[collection]?.[op];
7176
+ if (!handler) {
7177
+ throw new Error(`Collection handler not found: ${collection}.${op}`);
7178
+ }
7179
+ return await handler(params);
7180
+ };
7181
+ try {
7182
+ const request = UIsRequestMessageSchema.parse(data);
7183
+ const { id, payload, from } = request;
7184
+ const { operation, data: requestData } = payload;
7185
+ const uiId = requestData?.uiId;
7186
+ const ui = requestData?.ui;
7187
+ const projectId = requestData?.projectId;
7188
+ const name = requestData?.name;
7189
+ const description = requestData?.description;
7190
+ const createdBy = requestData?.createdBy;
7191
+ const updatedBy = requestData?.updatedBy;
7192
+ const numericId = requestData?.id;
7193
+ const filters = requestData?.filters;
7194
+ const limit = requestData?.limit;
7195
+ const sort = requestData?.sort;
7196
+ if (from.type !== "admin") {
7197
+ sendResponse6(id, {
7198
+ success: false,
7199
+ error: "Unauthorized: Only admin can manage UIs"
7200
+ }, sendMessage, from.id);
7201
+ logger.warn(`Unauthorized UI management attempt from: ${from.type}`);
7202
+ return;
7203
+ }
7204
+ switch (operation) {
7205
+ case "create":
7206
+ await handleCreate4(id, uiId, ui, projectId, name, description, createdBy, executeCollection, sendMessage, from.id);
7207
+ break;
7208
+ case "update":
7209
+ await handleUpdate4(id, numericId, ui, name, description, updatedBy, executeCollection, sendMessage, from.id);
7210
+ break;
7211
+ case "delete":
7212
+ await handleDelete4(id, numericId, executeCollection, sendMessage, from.id);
7213
+ break;
7214
+ case "getAll":
7215
+ await handleGetAll4(id, executeCollection, sendMessage, from.id);
7216
+ break;
7217
+ case "getOne":
7218
+ await handleGetOne4(id, numericId, executeCollection, sendMessage, from.id);
7219
+ break;
7220
+ case "query":
7221
+ await handleQuery3(id, filters, limit, sort, executeCollection, sendMessage, from.id);
7222
+ break;
7223
+ default:
7224
+ sendResponse6(id, {
7225
+ success: false,
7226
+ error: `Unknown operation: ${operation}`
7227
+ }, sendMessage, from.id);
7228
+ }
7229
+ } catch (error) {
7230
+ logger.error("Failed to handle UIs request:", error);
7231
+ sendResponse6(null, {
7232
+ success: false,
7233
+ error: error instanceof Error ? error.message : "Unknown error occurred"
7234
+ }, sendMessage);
7235
+ }
7236
+ }
7237
+ async function handleCreate4(id, uiId, ui, projectId, name, description, createdBy, executeCollection, sendMessage, clientId) {
7238
+ if (!uiId || uiId.trim().length === 0) {
7239
+ sendResponse6(id, {
7240
+ success: false,
7241
+ error: "UI ID is required and cannot be empty"
7242
+ }, sendMessage, clientId);
7243
+ return;
7244
+ }
7245
+ if (!projectId || projectId.trim().length === 0) {
7246
+ sendResponse6(id, {
7247
+ success: false,
7248
+ error: "Project ID is required and cannot be empty"
7249
+ }, sendMessage, clientId);
7250
+ return;
7251
+ }
7252
+ try {
7253
+ const result = await executeCollection("uis", "create", {
7254
+ uiId,
7255
+ projectId,
7256
+ name: name || uiId,
7257
+ description,
7258
+ ui,
7259
+ createdBy
7260
+ });
7261
+ if (result && result.success) {
7262
+ logger.info(`UI created successfully, ID: ${result.data?.id}`);
7263
+ sendResponse6(id, {
7264
+ success: true,
7265
+ data: {
7266
+ id: result.data?.id,
7267
+ uiId: result.data?.uiId || uiId,
7268
+ ui: result.data?.ui || ui,
7269
+ message: `UI created successfully`
7270
+ }
7271
+ }, sendMessage, clientId);
7272
+ } else {
7273
+ sendResponse6(id, {
7274
+ success: false,
7275
+ error: "Failed to create UI"
7276
+ }, sendMessage, clientId);
7277
+ }
7278
+ } catch (error) {
7279
+ sendResponse6(id, {
7280
+ success: false,
7281
+ error: error instanceof Error ? error.message : "Failed to create UI"
7282
+ }, sendMessage, clientId);
7283
+ }
7284
+ }
7285
+ async function handleUpdate4(id, numericId, ui, name, description, updatedBy, executeCollection, sendMessage, clientId) {
7286
+ if (!numericId) {
7287
+ sendResponse6(id, {
7288
+ success: false,
7289
+ error: "UI ID is required"
7290
+ }, sendMessage, clientId);
7291
+ return;
7292
+ }
7293
+ try {
7294
+ const result = await executeCollection("uis", "update", {
7295
+ id: numericId,
7296
+ name,
7297
+ description,
7298
+ ui,
7299
+ updatedBy
7300
+ });
7301
+ if (result && result.success) {
7302
+ logger.info(`UI updated successfully, ID: ${numericId}`);
7303
+ sendResponse6(id, {
7304
+ success: true,
7305
+ data: {
7306
+ id: numericId,
7307
+ uiId: result.data?.uiId,
7308
+ ui: result.data?.ui || ui,
7309
+ message: `UI updated successfully`
7310
+ }
7311
+ }, sendMessage, clientId);
7312
+ } else {
7313
+ sendResponse6(id, {
7314
+ success: false,
7315
+ error: "Failed to update UI"
7316
+ }, sendMessage, clientId);
7317
+ }
7318
+ } catch (error) {
7319
+ sendResponse6(id, {
7320
+ success: false,
7321
+ error: error instanceof Error ? error.message : "Failed to update UI"
7322
+ }, sendMessage, clientId);
7323
+ }
7324
+ }
7325
+ async function handleDelete4(id, numericId, executeCollection, sendMessage, clientId) {
7326
+ if (!numericId) {
7327
+ sendResponse6(id, {
7328
+ success: false,
7329
+ error: "UI ID is required"
7330
+ }, sendMessage, clientId);
7331
+ return;
7332
+ }
7333
+ try {
7334
+ const result = await executeCollection("uis", "delete", { id: numericId });
7335
+ if (result && result.success) {
7336
+ logger.info(`UI deleted successfully, ID: ${numericId}`);
7337
+ sendResponse6(id, {
7338
+ success: true,
7339
+ data: {
7340
+ id: numericId,
7341
+ message: `UI deleted successfully`
7342
+ }
7343
+ }, sendMessage, clientId);
7344
+ } else {
7345
+ sendResponse6(id, {
7346
+ success: false,
7347
+ error: "Failed to delete UI"
7348
+ }, sendMessage, clientId);
7349
+ }
7350
+ } catch (error) {
7351
+ sendResponse6(id, {
7352
+ success: false,
7353
+ error: error instanceof Error ? error.message : "Failed to delete UI"
7354
+ }, sendMessage, clientId);
7355
+ }
7356
+ }
7357
+ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
7358
+ try {
7359
+ const result = await executeCollection("uis", "getAll", {});
7360
+ if (result && result.success) {
7361
+ logger.info(`Retrieved ${result.count} UIs`);
7362
+ sendResponse6(id, {
7363
+ success: true,
7364
+ data: {
7365
+ uis: result.data,
7366
+ count: result.count,
7367
+ message: `Retrieved ${result.count} UIs`
7368
+ }
7369
+ }, sendMessage, clientId);
7370
+ } else {
7371
+ sendResponse6(id, {
7372
+ success: false,
7373
+ error: "Failed to get UIs"
7374
+ }, sendMessage, clientId);
7375
+ }
7376
+ } catch (error) {
7377
+ sendResponse6(id, {
7378
+ success: false,
7379
+ error: error instanceof Error ? error.message : "Failed to get UIs"
7380
+ }, sendMessage, clientId);
7381
+ }
7382
+ }
7383
+ async function handleGetOne4(id, numericId, executeCollection, sendMessage, clientId) {
7384
+ if (!numericId) {
7385
+ sendResponse6(id, {
7386
+ success: false,
7387
+ error: "UI ID is required"
7388
+ }, sendMessage, clientId);
7389
+ return;
7390
+ }
7391
+ try {
7392
+ const result = await executeCollection("uis", "getOne", { id: numericId });
7393
+ if (result && result.success) {
7394
+ logger.info(`Retrieved UI ID: ${numericId}`);
7395
+ sendResponse6(id, {
7396
+ success: true,
7397
+ data: {
7398
+ id: numericId,
7399
+ uiId: result.data?.uiId,
7400
+ ui: result.data?.ui || result.data,
7401
+ message: `Retrieved UI`
7402
+ }
7403
+ }, sendMessage, clientId);
7404
+ } else {
7405
+ sendResponse6(id, {
7406
+ success: false,
7407
+ error: `UI not found`
7408
+ }, sendMessage, clientId);
7409
+ }
7410
+ } catch (error) {
7411
+ sendResponse6(id, {
7412
+ success: false,
7413
+ error: error instanceof Error ? error.message : "Failed to get UI"
7414
+ }, sendMessage, clientId);
7415
+ }
7416
+ }
7417
+ async function handleQuery3(id, filters, limit, sort, executeCollection, sendMessage, clientId) {
7418
+ try {
7419
+ const result = await executeCollection("uis", "query", {
7420
+ filters: filters || {},
7421
+ limit,
7422
+ sort
7423
+ });
7424
+ if (result && result.success) {
7425
+ logger.info(`Query returned ${result.count} UIs`);
7426
+ sendResponse6(id, {
7427
+ success: true,
7428
+ data: {
7429
+ uis: result.data,
7430
+ count: result.count,
7431
+ message: `Query returned ${result.count} UIs`
7432
+ }
7433
+ }, sendMessage, clientId);
7434
+ } else {
7435
+ sendResponse6(id, {
7436
+ success: false,
7437
+ error: "Failed to query UIs"
7438
+ }, sendMessage, clientId);
7439
+ }
7440
+ } catch (error) {
7441
+ sendResponse6(id, {
7442
+ success: false,
7443
+ error: error instanceof Error ? error.message : "Failed to query UIs"
7444
+ }, sendMessage, clientId);
7445
+ }
7446
+ }
7447
+ function sendResponse6(id, res, sendMessage, clientId) {
7448
+ const response = {
7449
+ id: id || "unknown",
7450
+ type: "UIS_RES",
7451
+ from: { type: "data-agent" },
7452
+ to: {
7453
+ type: "admin",
7454
+ id: clientId
7455
+ },
7456
+ payload: {
7457
+ ...res
7458
+ }
7459
+ };
7460
+ sendMessage(response);
7461
+ }
7462
+
6291
7463
  // src/handlers/bookmarks.ts
6292
7464
  async function handleBookmarksRequest(data, collections, sendMessage) {
6293
7465
  const executeCollection = async (collection, op, params) => {
@@ -6304,22 +7476,24 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6304
7476
  const bookmarkId = requestData?.id;
6305
7477
  const userId = requestData?.userId;
6306
7478
  const threadId = requestData?.threadId;
7479
+ const name = requestData?.name;
7480
+ const description = requestData?.description;
6307
7481
  const uiblock = requestData?.uiblock;
6308
7482
  switch (operation) {
6309
7483
  case "create":
6310
- await handleCreate4(id, userId, threadId, uiblock, executeCollection, sendMessage, from.id);
7484
+ await handleCreate5(id, userId, threadId, name, description, uiblock, executeCollection, sendMessage, from.id);
6311
7485
  break;
6312
7486
  case "update":
6313
- await handleUpdate4(id, bookmarkId, threadId, uiblock, executeCollection, sendMessage, from.id);
7487
+ await handleUpdate5(id, bookmarkId, threadId, name, description, uiblock, executeCollection, sendMessage, from.id);
6314
7488
  break;
6315
7489
  case "delete":
6316
- await handleDelete4(id, bookmarkId, executeCollection, sendMessage, from.id);
7490
+ await handleDelete5(id, bookmarkId, executeCollection, sendMessage, from.id);
6317
7491
  break;
6318
7492
  case "getAll":
6319
- await handleGetAll4(id, executeCollection, sendMessage, from.id);
7493
+ await handleGetAll5(id, executeCollection, sendMessage, from.id);
6320
7494
  break;
6321
7495
  case "getOne":
6322
- await handleGetOne4(id, bookmarkId, executeCollection, sendMessage, from.id);
7496
+ await handleGetOne5(id, bookmarkId, executeCollection, sendMessage, from.id);
6323
7497
  break;
6324
7498
  case "getByUser":
6325
7499
  await handleGetByUser(id, userId, threadId, executeCollection, sendMessage, from.id);
@@ -6328,82 +7502,75 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6328
7502
  await handleGetByThread(id, threadId, executeCollection, sendMessage, from.id);
6329
7503
  break;
6330
7504
  default:
6331
- sendResponse6(id, {
7505
+ sendResponse7(id, {
6332
7506
  success: false,
6333
7507
  error: `Unknown operation: ${operation}`
6334
7508
  }, sendMessage, from.id);
6335
7509
  }
6336
7510
  } catch (error) {
6337
7511
  logger.error("Failed to handle bookmarks request:", error);
6338
- sendResponse6(null, {
7512
+ sendResponse7(null, {
6339
7513
  success: false,
6340
7514
  error: error instanceof Error ? error.message : "Unknown error occurred"
6341
7515
  }, sendMessage);
6342
7516
  }
6343
7517
  }
6344
- async function handleCreate4(id, userId, threadId, uiblock, executeCollection, sendMessage, clientId) {
7518
+ async function handleCreate5(id, userId, threadId, name, description, uiblock, executeCollection, sendMessage, clientId) {
6345
7519
  if (!userId) {
6346
- sendResponse6(id, {
7520
+ sendResponse7(id, {
6347
7521
  success: false,
6348
7522
  error: "userId is required"
6349
7523
  }, sendMessage, clientId);
6350
7524
  return;
6351
7525
  }
6352
7526
  if (!uiblock) {
6353
- sendResponse6(id, {
7527
+ sendResponse7(id, {
6354
7528
  success: false,
6355
7529
  error: "UIBlock data is required"
6356
7530
  }, sendMessage, clientId);
6357
7531
  return;
6358
7532
  }
6359
7533
  try {
6360
- const result = await executeCollection("bookmarks", "create", { userId, threadId, uiblock });
6361
- sendResponse6(id, {
7534
+ const result = await executeCollection("bookmarks", "create", { userId, threadId, name, description, uiblock });
7535
+ sendResponse7(id, {
6362
7536
  success: true,
6363
7537
  data: result.data,
6364
7538
  message: "Bookmark created successfully"
6365
7539
  }, sendMessage, clientId);
6366
7540
  logger.info(`Bookmark created: ID ${result.data.id}`);
6367
7541
  } catch (error) {
6368
- sendResponse6(id, {
7542
+ sendResponse7(id, {
6369
7543
  success: false,
6370
7544
  error: error instanceof Error ? error.message : "Failed to create bookmark"
6371
7545
  }, sendMessage, clientId);
6372
7546
  }
6373
7547
  }
6374
- async function handleUpdate4(id, bookmarkId, threadId, uiblock, executeCollection, sendMessage, clientId) {
7548
+ async function handleUpdate5(id, bookmarkId, threadId, name, description, uiblock, executeCollection, sendMessage, clientId) {
6375
7549
  if (!bookmarkId) {
6376
- sendResponse6(id, {
7550
+ sendResponse7(id, {
6377
7551
  success: false,
6378
7552
  error: "Bookmark ID is required"
6379
7553
  }, sendMessage, clientId);
6380
7554
  return;
6381
7555
  }
6382
- if (!uiblock) {
6383
- sendResponse6(id, {
6384
- success: false,
6385
- error: "UIBlock data is required"
6386
- }, sendMessage, clientId);
6387
- return;
6388
- }
6389
7556
  try {
6390
- const result = await executeCollection("bookmarks", "update", { id: bookmarkId, threadId, uiblock });
6391
- sendResponse6(id, {
7557
+ const result = await executeCollection("bookmarks", "update", { id: bookmarkId, threadId, name, description, uiblock });
7558
+ sendResponse7(id, {
6392
7559
  success: true,
6393
7560
  data: result.data,
6394
7561
  message: "Bookmark updated successfully"
6395
7562
  }, sendMessage, clientId);
6396
7563
  logger.info(`Bookmark updated: ID ${bookmarkId}`);
6397
7564
  } catch (error) {
6398
- sendResponse6(id, {
7565
+ sendResponse7(id, {
6399
7566
  success: false,
6400
7567
  error: error instanceof Error ? error.message : "Failed to update bookmark"
6401
7568
  }, sendMessage, clientId);
6402
7569
  }
6403
7570
  }
6404
- async function handleDelete4(id, bookmarkId, executeCollection, sendMessage, clientId) {
7571
+ async function handleDelete5(id, bookmarkId, executeCollection, sendMessage, clientId) {
6405
7572
  if (!bookmarkId) {
6406
- sendResponse6(id, {
7573
+ sendResponse7(id, {
6407
7574
  success: false,
6408
7575
  error: "Bookmark ID is required"
6409
7576
  }, sendMessage, clientId);
@@ -6411,23 +7578,23 @@ async function handleDelete4(id, bookmarkId, executeCollection, sendMessage, cli
6411
7578
  }
6412
7579
  try {
6413
7580
  const result = await executeCollection("bookmarks", "delete", { id: bookmarkId });
6414
- sendResponse6(id, {
7581
+ sendResponse7(id, {
6415
7582
  success: true,
6416
7583
  data: result.data,
6417
7584
  message: "Bookmark deleted successfully"
6418
7585
  }, sendMessage, clientId);
6419
7586
  logger.info(`Bookmark deleted: ID ${bookmarkId}`);
6420
7587
  } catch (error) {
6421
- sendResponse6(id, {
7588
+ sendResponse7(id, {
6422
7589
  success: false,
6423
7590
  error: error instanceof Error ? error.message : "Failed to delete bookmark"
6424
7591
  }, sendMessage, clientId);
6425
7592
  }
6426
7593
  }
6427
- async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
7594
+ async function handleGetAll5(id, executeCollection, sendMessage, clientId) {
6428
7595
  try {
6429
7596
  const result = await executeCollection("bookmarks", "getAll", {});
6430
- sendResponse6(id, {
7597
+ sendResponse7(id, {
6431
7598
  success: true,
6432
7599
  data: result.data,
6433
7600
  count: result.count,
@@ -6435,15 +7602,15 @@ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
6435
7602
  }, sendMessage, clientId);
6436
7603
  logger.info(`Retrieved all bookmarks (count: ${result.count})`);
6437
7604
  } catch (error) {
6438
- sendResponse6(id, {
7605
+ sendResponse7(id, {
6439
7606
  success: false,
6440
7607
  error: error instanceof Error ? error.message : "Failed to get bookmarks"
6441
7608
  }, sendMessage, clientId);
6442
7609
  }
6443
7610
  }
6444
- async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, clientId) {
7611
+ async function handleGetOne5(id, bookmarkId, executeCollection, sendMessage, clientId) {
6445
7612
  if (!bookmarkId) {
6446
- sendResponse6(id, {
7613
+ sendResponse7(id, {
6447
7614
  success: false,
6448
7615
  error: "Bookmark ID is required"
6449
7616
  }, sendMessage, clientId);
@@ -6451,14 +7618,14 @@ async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, cli
6451
7618
  }
6452
7619
  try {
6453
7620
  const result = await executeCollection("bookmarks", "getOne", { id: bookmarkId });
6454
- sendResponse6(id, {
7621
+ sendResponse7(id, {
6455
7622
  success: true,
6456
7623
  data: result.data,
6457
7624
  message: `Retrieved bookmark ID ${bookmarkId}`
6458
7625
  }, sendMessage, clientId);
6459
7626
  logger.info(`Retrieved bookmark: ID ${bookmarkId}`);
6460
7627
  } catch (error) {
6461
- sendResponse6(id, {
7628
+ sendResponse7(id, {
6462
7629
  success: false,
6463
7630
  error: error instanceof Error ? error.message : "Failed to get bookmark"
6464
7631
  }, sendMessage, clientId);
@@ -6466,7 +7633,7 @@ async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, cli
6466
7633
  }
6467
7634
  async function handleGetByUser(id, userId, threadId, executeCollection, sendMessage, clientId) {
6468
7635
  if (!userId) {
6469
- sendResponse6(id, {
7636
+ sendResponse7(id, {
6470
7637
  success: false,
6471
7638
  error: "userId is required"
6472
7639
  }, sendMessage, clientId);
@@ -6474,7 +7641,7 @@ async function handleGetByUser(id, userId, threadId, executeCollection, sendMess
6474
7641
  }
6475
7642
  try {
6476
7643
  const result = await executeCollection("bookmarks", "getByUser", { userId, threadId });
6477
- sendResponse6(id, {
7644
+ sendResponse7(id, {
6478
7645
  success: true,
6479
7646
  data: result.data,
6480
7647
  count: result.count,
@@ -6482,7 +7649,7 @@ async function handleGetByUser(id, userId, threadId, executeCollection, sendMess
6482
7649
  }, sendMessage, clientId);
6483
7650
  logger.info(`Retrieved bookmarks for user ${userId} (count: ${result.count})`);
6484
7651
  } catch (error) {
6485
- sendResponse6(id, {
7652
+ sendResponse7(id, {
6486
7653
  success: false,
6487
7654
  error: error instanceof Error ? error.message : "Failed to get bookmarks by user"
6488
7655
  }, sendMessage, clientId);
@@ -6490,7 +7657,7 @@ async function handleGetByUser(id, userId, threadId, executeCollection, sendMess
6490
7657
  }
6491
7658
  async function handleGetByThread(id, threadId, executeCollection, sendMessage, clientId) {
6492
7659
  if (!threadId) {
6493
- sendResponse6(id, {
7660
+ sendResponse7(id, {
6494
7661
  success: false,
6495
7662
  error: "threadId is required"
6496
7663
  }, sendMessage, clientId);
@@ -6498,7 +7665,7 @@ async function handleGetByThread(id, threadId, executeCollection, sendMessage, c
6498
7665
  }
6499
7666
  try {
6500
7667
  const result = await executeCollection("bookmarks", "getByThread", { threadId });
6501
- sendResponse6(id, {
7668
+ sendResponse7(id, {
6502
7669
  success: true,
6503
7670
  data: result.data,
6504
7671
  count: result.count,
@@ -6506,13 +7673,13 @@ async function handleGetByThread(id, threadId, executeCollection, sendMessage, c
6506
7673
  }, sendMessage, clientId);
6507
7674
  logger.info(`Retrieved bookmarks for thread ${threadId} (count: ${result.count})`);
6508
7675
  } catch (error) {
6509
- sendResponse6(id, {
7676
+ sendResponse7(id, {
6510
7677
  success: false,
6511
7678
  error: error instanceof Error ? error.message : "Failed to get bookmarks by thread"
6512
7679
  }, sendMessage, clientId);
6513
7680
  }
6514
7681
  }
6515
- function sendResponse6(id, res, sendMessage, clientId) {
7682
+ function sendResponse7(id, res, sendMessage, clientId) {
6516
7683
  const response = {
6517
7684
  id: id || "unknown",
6518
7685
  type: "BOOKMARKS_RES",
@@ -7364,7 +8531,10 @@ var SuperatomSDK = class {
7364
8531
  this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;
7365
8532
  this.anthropicApiKey = config.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY || "";
7366
8533
  this.groqApiKey = config.GROQ_API_KEY || process.env.GROQ_API_KEY || "";
8534
+ this.geminiApiKey = config.GEMINI_API_KEY || process.env.GEMINI_API_KEY || "";
8535
+ this.openaiApiKey = config.OPENAI_API_KEY || process.env.OPENAI_API_KEY || "";
7367
8536
  this.llmProviders = config.LLM_PROVIDERS || getLLMProviders();
8537
+ logger.info(`Initializing Superatom SDK v${SDK_VERSION} for project ${this.projectId}, llm providers: ${this.llmProviders.join(", ")}, config llm providers: ${config.LLM_PROVIDERS}`);
7368
8538
  this.userManager = new UserManager(this.projectId, 5e3);
7369
8539
  this.dashboardManager = new DashboardManager(this.projectId);
7370
8540
  this.reportManager = new ReportManager(this.projectId);
@@ -7449,7 +8619,9 @@ var SuperatomSDK = class {
7449
8619
  return new Promise((resolve, reject) => {
7450
8620
  try {
7451
8621
  const url = new URL(this.url);
7452
- url.searchParams.set("apiKey", this.apiKey);
8622
+ if (this.apiKey) {
8623
+ url.searchParams.set("apiKey", this.apiKey);
8624
+ }
7453
8625
  url.searchParams.set("projectId", this.projectId);
7454
8626
  url.searchParams.set("userId", this.userId);
7455
8627
  url.searchParams.set("type", this.type);
@@ -7508,22 +8680,22 @@ var SuperatomSDK = class {
7508
8680
  });
7509
8681
  break;
7510
8682
  case "USER_PROMPT_REQ":
7511
- handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections, this.tools, this.userId).catch((error) => {
8683
+ handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools, this.userId).catch((error) => {
7512
8684
  logger.error("Failed to handle user prompt request:", error);
7513
8685
  });
7514
8686
  break;
7515
8687
  case "ACTIONS":
7516
- handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders).catch((error) => {
8688
+ handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders).catch((error) => {
7517
8689
  logger.error("Failed to handle actions request:", error);
7518
8690
  });
7519
8691
  break;
7520
8692
  case "USER_PROMPT_SUGGESTIONS_REQ":
7521
- handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg)).catch((error) => {
8693
+ handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections, this.userId).catch((error) => {
7522
8694
  logger.error("Failed to handle user prompt suggestions request:", error);
7523
8695
  });
7524
8696
  break;
7525
8697
  case "COMPONENT_LIST_RES":
7526
- handleComponentListResponse(parsed, (com) => this.storeComponents(com)).catch((error) => {
8698
+ handleComponentListResponse(parsed, (com) => this.storeComponents(com), this.collections).catch((error) => {
7527
8699
  logger.error("Failed to handle component list request:", error);
7528
8700
  });
7529
8701
  break;
@@ -7533,15 +8705,20 @@ var SuperatomSDK = class {
7533
8705
  });
7534
8706
  break;
7535
8707
  case "DASHBOARDS":
7536
- handleDashboardsRequest(parsed, (msg) => this.send(msg)).catch((error) => {
8708
+ handleDashboardsRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7537
8709
  logger.error("Failed to handle dashboards request:", error);
7538
8710
  });
7539
8711
  break;
7540
8712
  case "REPORTS":
7541
- handleReportsRequest(parsed, (msg) => this.send(msg)).catch((error) => {
8713
+ handleReportsRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7542
8714
  logger.error("Failed to handle reports request:", error);
7543
8715
  });
7544
8716
  break;
8717
+ case "UIS":
8718
+ handleUIsRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
8719
+ logger.error("Failed to handle UIs request:", error);
8720
+ });
8721
+ break;
7545
8722
  case "BOOKMARKS":
7546
8723
  handleBookmarksRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7547
8724
  logger.error("Failed to handle bookmarks request:", error);