@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.mjs CHANGED
@@ -411,7 +411,8 @@ var UserPromptRequestMessageSchema = z3.object({
411
411
  });
412
412
  var UserPromptSuggestionsPayloadSchema = z3.object({
413
413
  prompt: z3.string(),
414
- limit: z3.number().int().positive().default(5)
414
+ limit: z3.number().int().positive().default(5),
415
+ similarityThreshold: z3.number().min(0).max(1).default(0.4)
415
416
  });
416
417
  var UserPromptSuggestionsMessageSchema = z3.object({
417
418
  id: z3.string(),
@@ -498,11 +499,28 @@ var ActionsRequestMessageSchema = z3.object({
498
499
  type: z3.literal("ACTIONS"),
499
500
  payload: ActionsRequestPayloadSchema
500
501
  });
502
+ var DashboardQueryFiltersSchema = z3.object({
503
+ dashboardId: z3.string().optional(),
504
+ projectId: z3.string().optional(),
505
+ createdBy: z3.number().optional(),
506
+ updatedBy: z3.number().optional(),
507
+ name: z3.string().optional()
508
+ });
501
509
  var DashboardsRequestPayloadSchema = z3.object({
502
- operation: z3.enum(["create", "update", "delete", "getAll", "getOne"]),
510
+ operation: z3.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
503
511
  data: z3.object({
512
+ id: z3.number().optional(),
504
513
  dashboardId: z3.string().optional(),
505
- dashboard: DSLRendererPropsSchema.optional()
514
+ projectId: z3.string().optional(),
515
+ name: z3.string().optional(),
516
+ description: z3.string().optional(),
517
+ createdBy: z3.number().optional(),
518
+ updatedBy: z3.number().optional(),
519
+ dashboard: DSLRendererPropsSchema.optional(),
520
+ // Query operation fields
521
+ filters: DashboardQueryFiltersSchema.optional(),
522
+ limit: z3.number().optional(),
523
+ sort: z3.enum(["ASC", "DESC"]).optional()
506
524
  }).optional()
507
525
  });
508
526
  var DashboardsRequestMessageSchema = z3.object({
@@ -511,11 +529,28 @@ var DashboardsRequestMessageSchema = z3.object({
511
529
  type: z3.literal("DASHBOARDS"),
512
530
  payload: DashboardsRequestPayloadSchema
513
531
  });
532
+ var ReportQueryFiltersSchema = z3.object({
533
+ reportId: z3.string().optional(),
534
+ projectId: z3.string().optional(),
535
+ createdBy: z3.number().optional(),
536
+ updatedBy: z3.number().optional(),
537
+ name: z3.string().optional()
538
+ });
514
539
  var ReportsRequestPayloadSchema = z3.object({
515
- operation: z3.enum(["create", "update", "delete", "getAll", "getOne"]),
540
+ operation: z3.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
516
541
  data: z3.object({
542
+ id: z3.number().optional(),
517
543
  reportId: z3.string().optional(),
518
- report: DSLRendererPropsSchema2.optional()
544
+ projectId: z3.string().optional(),
545
+ name: z3.string().optional(),
546
+ description: z3.string().optional(),
547
+ createdBy: z3.number().optional(),
548
+ updatedBy: z3.number().optional(),
549
+ report: DSLRendererPropsSchema2.optional(),
550
+ // Query operation fields
551
+ filters: ReportQueryFiltersSchema.optional(),
552
+ limit: z3.number().optional(),
553
+ sort: z3.enum(["ASC", "DESC"]).optional()
519
554
  }).optional()
520
555
  });
521
556
  var ReportsRequestMessageSchema = z3.object({
@@ -524,6 +559,36 @@ var ReportsRequestMessageSchema = z3.object({
524
559
  type: z3.literal("REPORTS"),
525
560
  payload: ReportsRequestPayloadSchema
526
561
  });
562
+ var UIQueryFiltersSchema = z3.object({
563
+ uiId: z3.string().optional(),
564
+ projectId: z3.string().optional(),
565
+ createdBy: z3.number().optional(),
566
+ updatedBy: z3.number().optional(),
567
+ name: z3.string().optional()
568
+ });
569
+ var UIsRequestPayloadSchema = z3.object({
570
+ operation: z3.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
571
+ data: z3.object({
572
+ id: z3.number().optional(),
573
+ uiId: z3.string().optional(),
574
+ projectId: z3.string().optional(),
575
+ name: z3.string().optional(),
576
+ description: z3.string().optional(),
577
+ createdBy: z3.number().optional(),
578
+ updatedBy: z3.number().optional(),
579
+ ui: DSLRendererPropsSchema.optional(),
580
+ // Query operation fields
581
+ filters: UIQueryFiltersSchema.optional(),
582
+ limit: z3.number().optional(),
583
+ sort: z3.enum(["ASC", "DESC"]).optional()
584
+ }).optional()
585
+ });
586
+ var UIsRequestMessageSchema = z3.object({
587
+ id: z3.string(),
588
+ from: MessageParticipantSchema,
589
+ type: z3.literal("UIS"),
590
+ payload: UIsRequestPayloadSchema
591
+ });
527
592
  var UIBlockSchema = z3.object({
528
593
  id: z3.string().optional(),
529
594
  userQuestion: z3.string().optional(),
@@ -547,10 +612,16 @@ var UIBlockSchema = z3.object({
547
612
  similarity: z3.number().optional()
548
613
  }).optional()
549
614
  });
615
+ var DBUIBlockSchema = z3.object({
616
+ id: z3.string(),
617
+ component: z3.record(z3.string(), z3.any()).nullable(),
618
+ analysis: z3.string().nullable(),
619
+ user_prompt: z3.string()
620
+ });
550
621
  var BookmarkDataSchema = z3.object({
551
622
  id: z3.number().optional(),
552
- uiblock: z3.any(),
553
- // JSON object
623
+ uiblock: DBUIBlockSchema,
624
+ // Typed JSON object
554
625
  created_at: z3.string().optional(),
555
626
  updated_at: z3.string().optional()
556
627
  });
@@ -560,7 +631,9 @@ var BookmarksRequestPayloadSchema = z3.object({
560
631
  id: z3.number().optional(),
561
632
  userId: z3.number().optional(),
562
633
  threadId: z3.string().optional(),
563
- uiblock: z3.any().optional()
634
+ name: z3.string().optional(),
635
+ description: z3.string().optional(),
636
+ uiblock: DBUIBlockSchema.optional()
564
637
  }).optional()
565
638
  });
566
639
  var BookmarksRequestMessageSchema = z3.object({
@@ -2907,6 +2980,8 @@ var promptLoader = new PromptLoader({
2907
2980
  // src/llm.ts
2908
2981
  import Anthropic from "@anthropic-ai/sdk";
2909
2982
  import Groq from "groq-sdk";
2983
+ import { GoogleGenerativeAI, SchemaType } from "@google/generative-ai";
2984
+ import OpenAI from "openai";
2910
2985
  import { jsonrepair } from "jsonrepair";
2911
2986
  var LLM = class {
2912
2987
  /* Get a complete text response from an LLM (Anthropic or Groq) */
@@ -2916,8 +2991,12 @@ var LLM = class {
2916
2991
  return this._anthropicText(messages, modelName, options);
2917
2992
  } else if (provider === "groq") {
2918
2993
  return this._groqText(messages, modelName, options);
2994
+ } else if (provider === "gemini") {
2995
+ return this._geminiText(messages, modelName, options);
2996
+ } else if (provider === "openai") {
2997
+ return this._openaiText(messages, modelName, options);
2919
2998
  } else {
2920
- throw new Error(`Unsupported provider: ${provider}. Use "anthropic" or "groq"`);
2999
+ throw new Error(`Unsupported provider: ${provider}. Use "anthropic", "groq", "gemini", or "openai"`);
2921
3000
  }
2922
3001
  }
2923
3002
  /* Stream response from an LLM (Anthropic or Groq) */
@@ -2927,17 +3006,26 @@ var LLM = class {
2927
3006
  return this._anthropicStream(messages, modelName, options, json);
2928
3007
  } else if (provider === "groq") {
2929
3008
  return this._groqStream(messages, modelName, options, json);
3009
+ } else if (provider === "gemini") {
3010
+ return this._geminiStream(messages, modelName, options, json);
3011
+ } else if (provider === "openai") {
3012
+ return this._openaiStream(messages, modelName, options, json);
2930
3013
  } else {
2931
- throw new Error(`Unsupported provider: ${provider}. Use "anthropic" or "groq"`);
3014
+ throw new Error(`Unsupported provider: ${provider}. Use "anthropic", "groq", "gemini", or "openai"`);
2932
3015
  }
2933
3016
  }
2934
- /* Stream response with tool calling support (Anthropic only for now) */
3017
+ /* Stream response with tool calling support (Anthropic and Gemini) */
2935
3018
  static async streamWithTools(messages, tools, toolHandler, options = {}, maxIterations = 3) {
2936
3019
  const [provider, modelName] = this._parseModel(options.model);
2937
- if (provider !== "anthropic") {
2938
- throw new Error(`Tool calling is only supported for Anthropic models`);
3020
+ if (provider === "anthropic") {
3021
+ return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
3022
+ } else if (provider === "gemini") {
3023
+ return this._geminiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
3024
+ } else if (provider === "openai") {
3025
+ return this._openaiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
3026
+ } else {
3027
+ throw new Error(`Tool calling is only supported for Anthropic, Gemini, and OpenAI models`);
2939
3028
  }
2940
- return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
2941
3029
  }
2942
3030
  // ============================================================
2943
3031
  // PRIVATE HELPER METHODS
@@ -3271,6 +3359,298 @@ var LLM = class {
3271
3359
  return fullText;
3272
3360
  }
3273
3361
  // ============================================================
3362
+ // GEMINI IMPLEMENTATION
3363
+ // ============================================================
3364
+ static async _geminiText(messages, modelName, options) {
3365
+ const apiKey = options.apiKey || process.env.GEMINI_API_KEY || "";
3366
+ const genAI = new GoogleGenerativeAI(apiKey);
3367
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3368
+ const model = genAI.getGenerativeModel({
3369
+ model: modelName,
3370
+ systemInstruction: systemPrompt,
3371
+ generationConfig: {
3372
+ maxOutputTokens: options.maxTokens || 1e3,
3373
+ temperature: options.temperature,
3374
+ topP: options.topP
3375
+ }
3376
+ });
3377
+ const result = await model.generateContent(messages.user);
3378
+ const response = await result.response;
3379
+ return response.text();
3380
+ }
3381
+ static async _geminiStream(messages, modelName, options, json) {
3382
+ const apiKey = options.apiKey || process.env.GEMINI_API_KEY || "";
3383
+ const genAI = new GoogleGenerativeAI(apiKey);
3384
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3385
+ const model = genAI.getGenerativeModel({
3386
+ model: modelName,
3387
+ systemInstruction: systemPrompt,
3388
+ generationConfig: {
3389
+ maxOutputTokens: options.maxTokens || 1e3,
3390
+ temperature: options.temperature,
3391
+ topP: options.topP,
3392
+ responseMimeType: json ? "application/json" : void 0
3393
+ }
3394
+ });
3395
+ const result = await model.generateContentStream(messages.user);
3396
+ let fullText = "";
3397
+ for await (const chunk of result.stream) {
3398
+ const text = chunk.text();
3399
+ if (text) {
3400
+ fullText += text;
3401
+ if (options.partial) {
3402
+ options.partial(text);
3403
+ }
3404
+ }
3405
+ }
3406
+ if (json) {
3407
+ return this._parseJSON(fullText);
3408
+ }
3409
+ return fullText;
3410
+ }
3411
+ static async _geminiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations) {
3412
+ const apiKey = options.apiKey || process.env.GEMINI_API_KEY || "";
3413
+ const genAI = new GoogleGenerativeAI(apiKey);
3414
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3415
+ const functionDeclarations = tools.map((tool) => ({
3416
+ name: tool.name,
3417
+ description: tool.description,
3418
+ parameters: {
3419
+ type: SchemaType.OBJECT,
3420
+ properties: tool.input_schema.properties,
3421
+ required: tool.input_schema.required || []
3422
+ }
3423
+ }));
3424
+ const model = genAI.getGenerativeModel({
3425
+ model: modelName,
3426
+ systemInstruction: systemPrompt,
3427
+ tools: [{ functionDeclarations }],
3428
+ generationConfig: {
3429
+ maxOutputTokens: options.maxTokens || 4e3,
3430
+ temperature: options.temperature,
3431
+ topP: options.topP
3432
+ }
3433
+ });
3434
+ const chat = model.startChat({
3435
+ history: []
3436
+ });
3437
+ let iterations = 0;
3438
+ let finalText = "";
3439
+ let currentUserMessage = messages.user;
3440
+ while (iterations < maxIterations) {
3441
+ iterations++;
3442
+ const result = await chat.sendMessageStream(currentUserMessage);
3443
+ let responseText = "";
3444
+ const functionCalls = [];
3445
+ for await (const chunk of result.stream) {
3446
+ const candidate = chunk.candidates?.[0];
3447
+ if (!candidate) continue;
3448
+ for (const part of candidate.content?.parts || []) {
3449
+ if (part.text) {
3450
+ responseText += part.text;
3451
+ if (options.partial) {
3452
+ options.partial(part.text);
3453
+ }
3454
+ } else if (part.functionCall) {
3455
+ functionCalls.push({
3456
+ name: part.functionCall.name,
3457
+ args: part.functionCall.args
3458
+ });
3459
+ }
3460
+ }
3461
+ }
3462
+ if (functionCalls.length === 0) {
3463
+ finalText = responseText;
3464
+ break;
3465
+ }
3466
+ const functionResponses = [];
3467
+ for (const fc of functionCalls) {
3468
+ try {
3469
+ const result2 = await toolHandler(fc.name, fc.args);
3470
+ functionResponses.push({
3471
+ name: fc.name,
3472
+ response: { result: typeof result2 === "string" ? result2 : JSON.stringify(result2) }
3473
+ });
3474
+ } catch (error) {
3475
+ functionResponses.push({
3476
+ name: fc.name,
3477
+ response: { error: error instanceof Error ? error.message : String(error) }
3478
+ });
3479
+ }
3480
+ }
3481
+ const functionResponseParts = functionResponses.map((fr) => ({
3482
+ functionResponse: {
3483
+ name: fr.name,
3484
+ response: fr.response
3485
+ }
3486
+ }));
3487
+ currentUserMessage = functionResponseParts;
3488
+ }
3489
+ if (iterations >= maxIterations) {
3490
+ throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);
3491
+ }
3492
+ return finalText;
3493
+ }
3494
+ // ============================================================
3495
+ // OPENAI IMPLEMENTATION
3496
+ // ============================================================
3497
+ static async _openaiText(messages, modelName, options) {
3498
+ const apiKey = options.apiKey || process.env.OPENAI_API_KEY || "";
3499
+ const openai = new OpenAI({ apiKey });
3500
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3501
+ const response = await openai.chat.completions.create({
3502
+ model: modelName,
3503
+ messages: [
3504
+ { role: "system", content: systemPrompt },
3505
+ { role: "user", content: messages.user }
3506
+ ],
3507
+ max_tokens: options.maxTokens || 1e3,
3508
+ temperature: options.temperature,
3509
+ top_p: options.topP
3510
+ });
3511
+ return response.choices[0]?.message?.content || "";
3512
+ }
3513
+ static async _openaiStream(messages, modelName, options, json) {
3514
+ const apiKey = options.apiKey || process.env.OPENAI_API_KEY || "";
3515
+ const openai = new OpenAI({ apiKey });
3516
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3517
+ const stream = await openai.chat.completions.create({
3518
+ model: modelName,
3519
+ messages: [
3520
+ { role: "system", content: systemPrompt },
3521
+ { role: "user", content: messages.user }
3522
+ ],
3523
+ max_tokens: options.maxTokens || 1e3,
3524
+ temperature: options.temperature,
3525
+ top_p: options.topP,
3526
+ response_format: json ? { type: "json_object" } : void 0,
3527
+ stream: true
3528
+ });
3529
+ let fullText = "";
3530
+ for await (const chunk of stream) {
3531
+ const content = chunk.choices[0]?.delta?.content || "";
3532
+ if (content) {
3533
+ fullText += content;
3534
+ if (options.partial) {
3535
+ options.partial(content);
3536
+ }
3537
+ }
3538
+ }
3539
+ if (json) {
3540
+ return this._parseJSON(fullText);
3541
+ }
3542
+ return fullText;
3543
+ }
3544
+ static async _openaiStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations) {
3545
+ const apiKey = options.apiKey || process.env.OPENAI_API_KEY || "";
3546
+ const openai = new OpenAI({ apiKey });
3547
+ const systemPrompt = typeof messages.sys === "string" ? messages.sys : messages.sys.map((block) => block.text).join("\n");
3548
+ const openaiTools = tools.map((tool) => ({
3549
+ type: "function",
3550
+ function: {
3551
+ name: tool.name,
3552
+ description: tool.description,
3553
+ parameters: {
3554
+ type: tool.input_schema.type,
3555
+ properties: tool.input_schema.properties,
3556
+ required: tool.input_schema.required || []
3557
+ }
3558
+ }
3559
+ }));
3560
+ const conversationMessages = [
3561
+ { role: "system", content: systemPrompt },
3562
+ { role: "user", content: messages.user }
3563
+ ];
3564
+ let iterations = 0;
3565
+ let finalText = "";
3566
+ while (iterations < maxIterations) {
3567
+ iterations++;
3568
+ const stream = await openai.chat.completions.create({
3569
+ model: modelName,
3570
+ messages: conversationMessages,
3571
+ max_tokens: options.maxTokens || 4e3,
3572
+ temperature: options.temperature,
3573
+ top_p: options.topP,
3574
+ tools: openaiTools,
3575
+ stream: true
3576
+ });
3577
+ let responseText = "";
3578
+ const toolCalls = [];
3579
+ const toolCallsInProgress = /* @__PURE__ */ new Map();
3580
+ for await (const chunk of stream) {
3581
+ const delta = chunk.choices[0]?.delta;
3582
+ if (delta?.content) {
3583
+ responseText += delta.content;
3584
+ if (options.partial) {
3585
+ options.partial(delta.content);
3586
+ }
3587
+ }
3588
+ if (delta?.tool_calls) {
3589
+ for (const toolCallDelta of delta.tool_calls) {
3590
+ const index = toolCallDelta.index;
3591
+ if (!toolCallsInProgress.has(index)) {
3592
+ toolCallsInProgress.set(index, {
3593
+ id: toolCallDelta.id || "",
3594
+ name: toolCallDelta.function?.name || "",
3595
+ arguments: ""
3596
+ });
3597
+ }
3598
+ const tc = toolCallsInProgress.get(index);
3599
+ if (toolCallDelta.id) {
3600
+ tc.id = toolCallDelta.id;
3601
+ }
3602
+ if (toolCallDelta.function?.name) {
3603
+ tc.name = toolCallDelta.function.name;
3604
+ }
3605
+ if (toolCallDelta.function?.arguments) {
3606
+ tc.arguments += toolCallDelta.function.arguments;
3607
+ }
3608
+ }
3609
+ }
3610
+ }
3611
+ for (const tc of toolCallsInProgress.values()) {
3612
+ if (tc.id && tc.name) {
3613
+ toolCalls.push(tc);
3614
+ }
3615
+ }
3616
+ if (toolCalls.length === 0) {
3617
+ finalText = responseText;
3618
+ break;
3619
+ }
3620
+ conversationMessages.push({
3621
+ role: "assistant",
3622
+ content: responseText || null,
3623
+ tool_calls: toolCalls.map((tc) => ({
3624
+ id: tc.id,
3625
+ type: "function",
3626
+ function: {
3627
+ name: tc.name,
3628
+ arguments: tc.arguments
3629
+ }
3630
+ }))
3631
+ });
3632
+ for (const tc of toolCalls) {
3633
+ let result;
3634
+ try {
3635
+ const args = JSON.parse(tc.arguments);
3636
+ const toolResult = await toolHandler(tc.name, args);
3637
+ result = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult);
3638
+ } catch (error) {
3639
+ result = JSON.stringify({ error: error instanceof Error ? error.message : String(error) });
3640
+ }
3641
+ conversationMessages.push({
3642
+ role: "tool",
3643
+ tool_call_id: tc.id,
3644
+ content: result
3645
+ });
3646
+ }
3647
+ }
3648
+ if (iterations >= maxIterations) {
3649
+ throw new Error(`Max iterations (${maxIterations}) reached in tool calling loop`);
3650
+ }
3651
+ return finalText;
3652
+ }
3653
+ // ============================================================
3274
3654
  // JSON PARSING HELPER
3275
3655
  // ============================================================
3276
3656
  /**
@@ -4559,18 +4939,56 @@ var AnthropicLLM = class extends BaseLLM {
4559
4939
  };
4560
4940
  var anthropicLLM = new AnthropicLLM();
4561
4941
 
4562
- // src/userResponse/index.ts
4942
+ // src/userResponse/gemini.ts
4563
4943
  import dotenv3 from "dotenv";
4564
4944
  dotenv3.config();
4945
+ var GeminiLLM = class extends BaseLLM {
4946
+ constructor(config) {
4947
+ super(config);
4948
+ }
4949
+ getDefaultModel() {
4950
+ return "gemini/gemini-2.5-flash";
4951
+ }
4952
+ getDefaultApiKey() {
4953
+ return process.env.GEMINI_API_KEY;
4954
+ }
4955
+ getProviderName() {
4956
+ return "Gemini";
4957
+ }
4958
+ };
4959
+ var geminiLLM = new GeminiLLM();
4960
+
4961
+ // src/userResponse/openai.ts
4962
+ import dotenv4 from "dotenv";
4963
+ dotenv4.config();
4964
+ var OpenAILLM = class extends BaseLLM {
4965
+ constructor(config) {
4966
+ super(config);
4967
+ }
4968
+ getDefaultModel() {
4969
+ return "openai/gpt-4.1";
4970
+ }
4971
+ getDefaultApiKey() {
4972
+ return process.env.OPENAI_API_KEY;
4973
+ }
4974
+ getProviderName() {
4975
+ return "OpenAI";
4976
+ }
4977
+ };
4978
+ var openaiLLM = new OpenAILLM();
4979
+
4980
+ // src/userResponse/index.ts
4981
+ import dotenv5 from "dotenv";
4982
+ dotenv5.config();
4565
4983
  function getLLMProviders() {
4566
4984
  const envProviders = process.env.LLM_PROVIDERS;
4567
- const DEFAULT_PROVIDERS = ["anthropic", "groq"];
4985
+ const DEFAULT_PROVIDERS = ["anthropic", "gemini", "openai", "groq"];
4568
4986
  if (!envProviders) {
4569
4987
  return DEFAULT_PROVIDERS;
4570
4988
  }
4571
4989
  try {
4572
4990
  const providers = JSON.parse(envProviders);
4573
- const validProviders = providers.filter((p) => p === "anthropic" || p === "groq");
4991
+ const validProviders = providers.filter((p) => p === "anthropic" || p === "groq" || p === "gemini" || p === "openai");
4574
4992
  if (validProviders.length === 0) {
4575
4993
  return DEFAULT_PROVIDERS;
4576
4994
  }
@@ -4613,10 +5031,44 @@ var useGroqMethod = async (prompt, components, apiKey, logCollector, conversatio
4613
5031
  logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);
4614
5032
  return matchResult;
4615
5033
  };
5034
+ var useGeminiMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools, userId) => {
5035
+ logger.debug("[useGeminiMethod] Initializing Gemini LLM matching method");
5036
+ logger.debug(`[useGeminiMethod] Response mode: ${responseMode}`);
5037
+ const msg = `Using Gemini LLM ${responseMode === "text" ? "text response" : "matching"} method...`;
5038
+ logger.info(msg);
5039
+ logCollector?.info(msg);
5040
+ if (responseMode === "component" && components.length === 0) {
5041
+ const emptyMsg = "Components not loaded in memory. Please ensure components are fetched first.";
5042
+ logger.error("[useGeminiMethod] No components available");
5043
+ logCollector?.error(emptyMsg);
5044
+ return { success: false, errors: [emptyMsg] };
5045
+ }
5046
+ logger.debug(`[useGeminiMethod] Processing with ${components.length} components`);
5047
+ const matchResult = await geminiLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
5048
+ logger.info(`[useGeminiMethod] Successfully generated ${responseMode} using Gemini`);
5049
+ return matchResult;
5050
+ };
5051
+ var useOpenAIMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools, userId) => {
5052
+ logger.debug("[useOpenAIMethod] Initializing OpenAI GPT matching method");
5053
+ logger.debug(`[useOpenAIMethod] Response mode: ${responseMode}`);
5054
+ const msg = `Using OpenAI GPT ${responseMode === "text" ? "text response" : "matching"} method...`;
5055
+ logger.info(msg);
5056
+ logCollector?.info(msg);
5057
+ if (responseMode === "component" && components.length === 0) {
5058
+ const emptyMsg = "Components not loaded in memory. Please ensure components are fetched first.";
5059
+ logger.error("[useOpenAIMethod] No components available");
5060
+ logCollector?.error(emptyMsg);
5061
+ return { success: false, errors: [emptyMsg] };
5062
+ }
5063
+ logger.debug(`[useOpenAIMethod] Processing with ${components.length} components`);
5064
+ const matchResult = await openaiLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
5065
+ logger.info(`[useOpenAIMethod] Successfully generated ${responseMode} using OpenAI`);
5066
+ return matchResult;
5067
+ };
4616
5068
  var getUserResponseFromCache = async (prompt) => {
4617
5069
  return false;
4618
5070
  };
4619
- var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools, userId) => {
5071
+ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, logCollector, conversationHistory, responseMode = "component", streamCallback, collections, externalTools, userId) => {
4620
5072
  logger.debug(`[get_user_response] Starting user response generation for prompt: "${prompt.substring(0, 50)}..."`);
4621
5073
  logger.debug(`[get_user_response] Response mode: ${responseMode}`);
4622
5074
  logger.debug("[get_user_response] Checking cache for existing response");
@@ -4652,6 +5104,10 @@ var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey,
4652
5104
  result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
4653
5105
  } else if (provider === "groq") {
4654
5106
  result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
5107
+ } else if (provider === "gemini") {
5108
+ result = await useGeminiMethod(prompt, components, geminiApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
5109
+ } else if (provider === "openai") {
5110
+ result = await useOpenAIMethod(prompt, components, openaiApiKey, logCollector, conversationHistory, responseMode, streamCallback, collections, externalTools, userId);
4655
5111
  } else {
4656
5112
  logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);
4657
5113
  errors.push(`Unknown provider: ${provider}`);
@@ -4996,7 +5452,7 @@ var CONTEXT_CONFIG = {
4996
5452
  };
4997
5453
 
4998
5454
  // src/handlers/user-prompt-request.ts
4999
- var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools, userId) => {
5455
+ var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools, userId) => {
5000
5456
  const errors = [];
5001
5457
  logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
5002
5458
  const parseResult = UserPromptRequestMessageSchema.safeParse(data);
@@ -5071,6 +5527,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
5071
5527
  components,
5072
5528
  anthropicApiKey,
5073
5529
  groqApiKey,
5530
+ geminiApiKey,
5531
+ openaiApiKey,
5074
5532
  llmProviders,
5075
5533
  logCollector,
5076
5534
  conversationHistory,
@@ -5169,8 +5627,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
5169
5627
  wsId
5170
5628
  };
5171
5629
  };
5172
- async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools, userId) {
5173
- const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders, collections, externalTools, userId);
5630
+ async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools, userId) {
5631
+ const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools, userId);
5174
5632
  sendDataResponse4(
5175
5633
  response.id || data.id,
5176
5634
  {
@@ -5201,12 +5659,13 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
5201
5659
  }
5202
5660
 
5203
5661
  // src/handlers/user-prompt-suggestions.ts
5204
- async function handleUserPromptSuggestions(data, components, sendMessage) {
5662
+ async function handleUserPromptSuggestions(data, components, sendMessage, collections, userId) {
5205
5663
  try {
5206
5664
  const request = UserPromptSuggestionsMessageSchema.parse(data);
5207
5665
  const { id, payload, from } = request;
5208
- const { prompt, limit = 5 } = payload;
5666
+ const { prompt, limit = 5, similarityThreshold = 0.1 } = payload;
5209
5667
  const wsId = from.id;
5668
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Processing user prompt suggestions: ${prompt}`);
5210
5669
  if (!prompt || prompt.trim().length === 0) {
5211
5670
  sendResponse(id, {
5212
5671
  success: false,
@@ -5214,7 +5673,79 @@ async function handleUserPromptSuggestions(data, components, sendMessage) {
5214
5673
  }, sendMessage, wsId);
5215
5674
  return;
5216
5675
  }
5676
+ const componentSearchHandler = collections?.["components"]?.["search"];
5677
+ const bookmarkSearchHandler = collections?.["bookmarks"]?.["search"];
5678
+ let componentSuggestions = [];
5679
+ let bookmarkSuggestions = [];
5680
+ let useEmbeddingSearch = false;
5681
+ const searchPromises = [];
5682
+ if (componentSearchHandler) {
5683
+ searchPromises.push(
5684
+ (async () => {
5685
+ try {
5686
+ logger.info("Using embedding-based search for components");
5687
+ const result = await componentSearchHandler({ prompt, limit });
5688
+ if (result.success && result.suggestions) {
5689
+ componentSuggestions = result.suggestions.map((s) => ({
5690
+ ...s,
5691
+ suggestionType: "component"
5692
+ }));
5693
+ useEmbeddingSearch = true;
5694
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${componentSuggestions.length} component suggestions`);
5695
+ }
5696
+ } catch (embeddingError) {
5697
+ logger.warn("Component embedding search failed:", embeddingError);
5698
+ }
5699
+ })()
5700
+ );
5701
+ }
5702
+ if (bookmarkSearchHandler && userId && userId !== "anonymous") {
5703
+ searchPromises.push(
5704
+ (async () => {
5705
+ try {
5706
+ logger.info(`Using embedding-based search for bookmarks (user: ${userId})`);
5707
+ const result = await bookmarkSearchHandler({ prompt, userId, limit });
5708
+ if (result.success && result.suggestions) {
5709
+ bookmarkSuggestions = result.suggestions.map((s) => ({
5710
+ ...s,
5711
+ suggestionType: "bookmark"
5712
+ }));
5713
+ useEmbeddingSearch = true;
5714
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Found ${bookmarkSuggestions.length} bookmark suggestions`);
5715
+ }
5716
+ } catch (embeddingError) {
5717
+ logger.warn("Bookmark embedding search failed:", embeddingError);
5718
+ }
5719
+ })()
5720
+ );
5721
+ }
5722
+ if (searchPromises.length > 0) {
5723
+ await Promise.all(searchPromises);
5724
+ }
5725
+ if (useEmbeddingSearch && (componentSuggestions.length > 0 || bookmarkSuggestions.length > 0)) {
5726
+ const filteredComponentSuggestions = componentSuggestions.filter(
5727
+ (s) => (s.similarity || 0) >= similarityThreshold
5728
+ );
5729
+ const filteredBookmarkSuggestions = bookmarkSuggestions.filter(
5730
+ (s) => (s.similarity || 0) >= similarityThreshold
5731
+ );
5732
+ const allSuggestions = [...filteredComponentSuggestions, ...filteredBookmarkSuggestions].sort((a, b) => (b.similarity || 0) - (a.similarity || 0)).slice(0, limit);
5733
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Filtered by threshold ${similarityThreshold}: ${componentSuggestions.length} -> ${filteredComponentSuggestions.length} components, ${bookmarkSuggestions.length} -> ${filteredBookmarkSuggestions.length} bookmarks`);
5734
+ sendResponse(id, {
5735
+ success: true,
5736
+ data: {
5737
+ prompt,
5738
+ suggestions: allSuggestions,
5739
+ count: allSuggestions.length,
5740
+ componentCount: filteredComponentSuggestions.length,
5741
+ bookmarkCount: filteredBookmarkSuggestions.length,
5742
+ message: `Found ${allSuggestions.length} suggestions (${filteredComponentSuggestions.length} components, ${filteredBookmarkSuggestions.length} bookmarks)`
5743
+ }
5744
+ }, sendMessage, wsId);
5745
+ return;
5746
+ }
5217
5747
  const displayComponents = components.filter((c) => c.isDisplayComp === true);
5748
+ logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Using token-based approach. Display components: ${displayComponents.length}`);
5218
5749
  if (!displayComponents || displayComponents.length === 0) {
5219
5750
  sendResponse(id, {
5220
5751
  success: true,
@@ -5297,13 +5828,13 @@ function sendResponse(id, res, sendMessage, clientId) {
5297
5828
  }
5298
5829
 
5299
5830
  // src/userResponse/next-questions.ts
5300
- async function generateNextQuestions(originalUserPrompt, component, componentData, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory) {
5831
+ async function generateNextQuestions(originalUserPrompt, component, componentData, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, logCollector, conversationHistory) {
5301
5832
  try {
5302
5833
  logger.debug("[generateNextQuestions] Starting next questions generation");
5303
5834
  logger.debug(`[generateNextQuestions] User prompt: "${originalUserPrompt?.substring(0, 50)}..."`);
5304
5835
  logger.debug(`[generateNextQuestions] Component: ${component?.name || "unknown"} (${component?.type || "unknown"})`);
5305
5836
  logger.debug(`[generateNextQuestions] Component data available: ${componentData ? "yes" : "no"}`);
5306
- const providers = llmProviders || ["anthropic"];
5837
+ const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
5307
5838
  logger.info(`[generateNextQuestions] Using LLM providers: [${providers.join(", ")}]`);
5308
5839
  if (conversationHistory && conversationHistory.length > 0) {
5309
5840
  const exchangeCount = conversationHistory.split("\n").filter((l) => l.startsWith("Q")).length;
@@ -5328,6 +5859,26 @@ async function generateNextQuestions(originalUserPrompt, component, componentDat
5328
5859
  logCollector,
5329
5860
  conversationHistory
5330
5861
  );
5862
+ } else if (provider === "gemini") {
5863
+ logger.debug("[generateNextQuestions] Using Gemini LLM for next questions");
5864
+ result = await geminiLLM.generateNextQuestions(
5865
+ originalUserPrompt,
5866
+ component,
5867
+ componentData,
5868
+ geminiApiKey,
5869
+ logCollector,
5870
+ conversationHistory
5871
+ );
5872
+ } else if (provider === "openai") {
5873
+ logger.debug("[generateNextQuestions] Using OpenAI LLM for next questions");
5874
+ result = await openaiLLM.generateNextQuestions(
5875
+ originalUserPrompt,
5876
+ component,
5877
+ componentData,
5878
+ openaiApiKey,
5879
+ logCollector,
5880
+ conversationHistory
5881
+ );
5331
5882
  } else {
5332
5883
  logger.debug("[generateNextQuestions] Using Anthropic LLM for next questions");
5333
5884
  result = await anthropicLLM.generateNextQuestions(
@@ -5378,7 +5929,7 @@ async function generateNextQuestions(originalUserPrompt, component, componentDat
5378
5929
  }
5379
5930
 
5380
5931
  // src/handlers/actions-request.ts
5381
- async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiKey, llmProviders) {
5932
+ async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders) {
5382
5933
  try {
5383
5934
  logger.debug("[ACTIONS_REQ] Parsing incoming actions request");
5384
5935
  const actionsRequest = ActionsRequestMessageSchema.parse(data);
@@ -5450,6 +6001,8 @@ ${conversationHistory.substring(0, 200)}...`);
5450
6001
  componentData,
5451
6002
  anthropicApiKey,
5452
6003
  groqApiKey,
6004
+ geminiApiKey,
6005
+ openaiApiKey,
5453
6006
  llmProviders,
5454
6007
  logCollector,
5455
6008
  conversationHistory
@@ -5530,10 +6083,10 @@ function sendResponse2(id, res, sendMessage, clientId) {
5530
6083
  }
5531
6084
 
5532
6085
  // src/handlers/components-list-response.ts
5533
- async function handleComponentListResponse(data, storeComponents) {
6086
+ async function handleComponentListResponse(data, storeComponents, collections) {
5534
6087
  try {
5535
6088
  const componentListResponse = ComponentListResponseMessageSchema.parse(data);
5536
- const { id, payload } = componentListResponse;
6089
+ const { payload } = componentListResponse;
5537
6090
  const componentsList = payload.components;
5538
6091
  if (!componentsList) {
5539
6092
  logger.error("Components list not found in the response");
@@ -5541,6 +6094,20 @@ async function handleComponentListResponse(data, storeComponents) {
5541
6094
  }
5542
6095
  const components = ComponentsSchema.parse(componentsList);
5543
6096
  storeComponents(components);
6097
+ const embedHandler = collections?.["components"]?.["embed"];
6098
+ if (embedHandler) {
6099
+ try {
6100
+ logger.info("Embedding display components for semantic search...");
6101
+ const result = await embedHandler({ components });
6102
+ if (result.success) {
6103
+ logger.info(`Successfully embedded ${result.count} display components`);
6104
+ } else {
6105
+ logger.warn("Failed to embed components:", result.error);
6106
+ }
6107
+ } catch (embedError) {
6108
+ logger.warn("Failed to embed components:", embedError);
6109
+ }
6110
+ }
5544
6111
  return;
5545
6112
  } catch (error) {
5546
6113
  logger.error("Failed to handle user prompt request:", error);
@@ -5558,7 +6125,7 @@ async function handleUsersRequest(data, sendMessage) {
5558
6125
  const password = requestData?.password;
5559
6126
  const fullname = requestData?.fullname;
5560
6127
  const role = requestData?.role;
5561
- if (from.type !== "admin") {
6128
+ if (from.type !== "admin" && operation !== "getOne" && operation !== "getAll") {
5562
6129
  sendResponse3(id, {
5563
6130
  success: false,
5564
6131
  error: "Unauthorized: Only admin can manage users"
@@ -5845,13 +6412,29 @@ function getDashboardManager() {
5845
6412
  }
5846
6413
 
5847
6414
  // src/handlers/dashboards.ts
5848
- async function handleDashboardsRequest(data, sendMessage) {
6415
+ async function handleDashboardsRequest(data, collections, sendMessage) {
6416
+ const executeCollection = async (collection, op, params) => {
6417
+ const handler = collections[collection]?.[op];
6418
+ if (!handler) {
6419
+ return null;
6420
+ }
6421
+ return await handler(params);
6422
+ };
5849
6423
  try {
5850
6424
  const request = DashboardsRequestMessageSchema.parse(data);
5851
6425
  const { id, payload, from } = request;
5852
6426
  const { operation, data: requestData } = payload;
5853
6427
  const dashboardId = requestData?.dashboardId;
5854
6428
  const dashboard = requestData?.dashboard;
6429
+ const projectId = requestData?.projectId;
6430
+ const name = requestData?.name;
6431
+ const description = requestData?.description;
6432
+ const createdBy = requestData?.createdBy;
6433
+ const updatedBy = requestData?.updatedBy;
6434
+ const numericId = requestData?.id;
6435
+ const filters = requestData?.filters;
6436
+ const limit = requestData?.limit;
6437
+ const sort = requestData?.sort;
5855
6438
  if (from.type !== "admin") {
5856
6439
  sendResponse4(id, {
5857
6440
  success: false,
@@ -5863,19 +6446,22 @@ async function handleDashboardsRequest(data, sendMessage) {
5863
6446
  const dashboardManager2 = getDashboardManager();
5864
6447
  switch (operation) {
5865
6448
  case "create":
5866
- await handleCreate2(id, dashboardId, dashboard, dashboardManager2, sendMessage, from.id);
6449
+ await handleCreate2(id, dashboardId, dashboard, projectId, name, description, createdBy, executeCollection, dashboardManager2, sendMessage, from.id);
5867
6450
  break;
5868
6451
  case "update":
5869
- await handleUpdate2(id, dashboardId, dashboard, dashboardManager2, sendMessage, from.id);
6452
+ await handleUpdate2(id, numericId, dashboardId, dashboard, name, description, updatedBy, executeCollection, dashboardManager2, sendMessage, from.id);
5870
6453
  break;
5871
6454
  case "delete":
5872
- await handleDelete2(id, dashboardId, dashboardManager2, sendMessage, from.id);
6455
+ await handleDelete2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, from.id);
5873
6456
  break;
5874
6457
  case "getAll":
5875
- await handleGetAll2(id, dashboardManager2, sendMessage, from.id);
6458
+ await handleGetAll2(id, executeCollection, dashboardManager2, sendMessage, from.id);
5876
6459
  break;
5877
6460
  case "getOne":
5878
- await handleGetOne2(id, dashboardId, dashboardManager2, sendMessage, from.id);
6461
+ await handleGetOne2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, from.id);
6462
+ break;
6463
+ case "query":
6464
+ await handleQuery(id, filters, limit, sort, executeCollection, dashboardManager2, sendMessage, from.id);
5879
6465
  break;
5880
6466
  default:
5881
6467
  sendResponse4(id, {
@@ -5891,7 +6477,7 @@ async function handleDashboardsRequest(data, sendMessage) {
5891
6477
  }, sendMessage);
5892
6478
  }
5893
6479
  }
5894
- async function handleCreate2(id, dashboardId, dashboard, dashboardManager2, sendMessage, clientId) {
6480
+ async function handleCreate2(id, dashboardId, dashboard, projectId, name, description, createdBy, executeCollection, dashboardManager2, sendMessage, clientId) {
5895
6481
  if (!dashboardId || dashboardId.trim().length === 0) {
5896
6482
  sendResponse4(id, {
5897
6483
  success: false,
@@ -5899,21 +6485,50 @@ async function handleCreate2(id, dashboardId, dashboard, dashboardManager2, send
5899
6485
  }, sendMessage, clientId);
5900
6486
  return;
5901
6487
  }
5902
- if (!dashboard) {
6488
+ if (!projectId) {
5903
6489
  sendResponse4(id, {
5904
6490
  success: false,
5905
- error: "Dashboard data is required"
6491
+ error: "Project ID is required"
5906
6492
  }, sendMessage, clientId);
5907
6493
  return;
5908
6494
  }
5909
6495
  try {
6496
+ const result = await executeCollection("dashboards", "create", {
6497
+ dashboardId,
6498
+ projectId,
6499
+ name: name || "",
6500
+ description,
6501
+ dashboard,
6502
+ createdBy
6503
+ });
6504
+ if (result && result.success) {
6505
+ logger.info(`[DB] Dashboard created successfully, ID: ${result.data?.id}`);
6506
+ sendResponse4(id, {
6507
+ success: true,
6508
+ data: {
6509
+ id: result.data?.id,
6510
+ dashboardId: result.data?.dashboardId,
6511
+ dashboard: result.data?.dashboard || dashboard,
6512
+ message: `Dashboard created successfully (DB)`
6513
+ }
6514
+ }, sendMessage, clientId);
6515
+ return;
6516
+ }
6517
+ } catch (dbError) {
6518
+ logger.warn(`[DB] Failed to create dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6519
+ }
6520
+ try {
6521
+ if (!dashboard) {
6522
+ dashboard = {};
6523
+ }
5910
6524
  const createdDashboard = dashboardManager2.createDashboard(dashboardId, dashboard);
6525
+ logger.info(`[FILE] Dashboard '${dashboardId}' created successfully`);
5911
6526
  sendResponse4(id, {
5912
6527
  success: true,
5913
6528
  data: {
5914
6529
  dashboardId,
5915
6530
  dashboard: createdDashboard,
5916
- message: `Dashboard '${dashboardId}' created successfully`
6531
+ message: `Dashboard '${dashboardId}' created successfully (File)`
5917
6532
  }
5918
6533
  }, sendMessage, clientId);
5919
6534
  } catch (error) {
@@ -5923,36 +6538,56 @@ async function handleCreate2(id, dashboardId, dashboard, dashboardManager2, send
5923
6538
  }, sendMessage, clientId);
5924
6539
  }
5925
6540
  }
5926
- async function handleUpdate2(id, dashboardId, dashboard, dashboardManager2, sendMessage, clientId) {
5927
- if (!dashboardId || dashboardId.trim().length === 0) {
5928
- sendResponse4(id, {
5929
- success: false,
5930
- error: "Dashboard ID is required and cannot be empty"
5931
- }, sendMessage, clientId);
5932
- return;
5933
- }
5934
- if (!dashboard) {
6541
+ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, description, updatedBy, executeCollection, dashboardManager2, sendMessage, clientId) {
6542
+ if (!numericId) {
5935
6543
  sendResponse4(id, {
5936
6544
  success: false,
5937
- error: "Dashboard data is required"
6545
+ error: "Dashboard ID is required"
5938
6546
  }, sendMessage, clientId);
5939
6547
  return;
5940
6548
  }
5941
6549
  try {
5942
- const updatedDashboard = dashboardManager2.updateDashboard(dashboardId, dashboard);
6550
+ const result = await executeCollection("dashboards", "update", {
6551
+ id: numericId,
6552
+ name,
6553
+ description,
6554
+ dashboard,
6555
+ updatedBy
6556
+ });
6557
+ if (result && result.success) {
6558
+ logger.info(`[DB] Dashboard updated successfully, ID: ${numericId}`);
6559
+ sendResponse4(id, {
6560
+ success: true,
6561
+ data: {
6562
+ id: numericId,
6563
+ dashboardId: result.data?.dashboardId,
6564
+ dashboard: result.data?.dashboard || dashboard,
6565
+ message: `Dashboard updated successfully (DB)`
6566
+ }
6567
+ }, sendMessage, clientId);
6568
+ return;
6569
+ }
6570
+ } catch (dbError) {
6571
+ logger.warn(`[DB] Failed to update dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6572
+ }
6573
+ const fileStorageId = dashboardId || String(numericId);
6574
+ try {
6575
+ const updatedDashboard = dashboardManager2.updateDashboard(fileStorageId, dashboard);
5943
6576
  if (!updatedDashboard) {
5944
6577
  sendResponse4(id, {
5945
6578
  success: false,
5946
- error: `Dashboard '${dashboardId}' not found`
6579
+ error: `Dashboard '${fileStorageId}' not found`
5947
6580
  }, sendMessage, clientId);
5948
6581
  return;
5949
6582
  }
6583
+ logger.info(`[FILE] Dashboard '${fileStorageId}' updated successfully`);
5950
6584
  sendResponse4(id, {
5951
6585
  success: true,
5952
6586
  data: {
5953
- dashboardId,
6587
+ id: numericId,
6588
+ dashboardId: fileStorageId,
5954
6589
  dashboard: updatedDashboard,
5955
- message: `Dashboard '${dashboardId}' updated successfully`
6590
+ message: `Dashboard '${fileStorageId}' updated successfully (File)`
5956
6591
  }
5957
6592
  }, sendMessage, clientId);
5958
6593
  } catch (error) {
@@ -5962,65 +6597,154 @@ async function handleUpdate2(id, dashboardId, dashboard, dashboardManager2, send
5962
6597
  }, sendMessage, clientId);
5963
6598
  }
5964
6599
  }
5965
- async function handleDelete2(id, dashboardId, dashboardManager2, sendMessage, clientId) {
5966
- if (!dashboardId || dashboardId.trim().length === 0) {
6600
+ async function handleDelete2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, clientId) {
6601
+ if (!numericId) {
5967
6602
  sendResponse4(id, {
5968
6603
  success: false,
5969
- error: "Dashboard ID is required and cannot be empty"
6604
+ error: "Dashboard ID is required"
5970
6605
  }, sendMessage, clientId);
5971
6606
  return;
5972
6607
  }
5973
- const deleted = dashboardManager2.deleteDashboard(dashboardId);
6608
+ try {
6609
+ const result = await executeCollection("dashboards", "delete", { id: numericId });
6610
+ if (result && result.success) {
6611
+ logger.info(`[DB] Dashboard deleted successfully, ID: ${numericId}`);
6612
+ sendResponse4(id, {
6613
+ success: true,
6614
+ data: {
6615
+ id: numericId,
6616
+ message: `Dashboard deleted successfully (DB)`
6617
+ }
6618
+ }, sendMessage, clientId);
6619
+ return;
6620
+ }
6621
+ } catch (dbError) {
6622
+ logger.warn(`[DB] Failed to delete dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6623
+ }
6624
+ const fileStorageId = dashboardId || String(numericId);
6625
+ const deleted = dashboardManager2.deleteDashboard(fileStorageId);
5974
6626
  if (!deleted) {
5975
6627
  sendResponse4(id, {
5976
6628
  success: false,
5977
- error: `Dashboard '${dashboardId}' not found`
6629
+ error: `Dashboard '${fileStorageId}' not found`
5978
6630
  }, sendMessage, clientId);
5979
6631
  return;
5980
6632
  }
6633
+ logger.info(`[FILE] Dashboard '${fileStorageId}' deleted successfully`);
5981
6634
  sendResponse4(id, {
5982
6635
  success: true,
5983
6636
  data: {
5984
- dashboardId,
5985
- message: `Dashboard '${dashboardId}' deleted successfully`
6637
+ id: numericId,
6638
+ dashboardId: fileStorageId,
6639
+ message: `Dashboard '${fileStorageId}' deleted successfully (File)`
5986
6640
  }
5987
6641
  }, sendMessage, clientId);
5988
6642
  }
5989
- async function handleGetAll2(id, dashboardManager2, sendMessage, clientId) {
6643
+ async function handleGetAll2(id, executeCollection, dashboardManager2, sendMessage, clientId) {
6644
+ try {
6645
+ const result = await executeCollection("dashboards", "getAll", {});
6646
+ if (result && result.success) {
6647
+ logger.info(`[DB] Retrieved ${result.count} dashboards`);
6648
+ sendResponse4(id, {
6649
+ success: true,
6650
+ data: {
6651
+ dashboards: result.data,
6652
+ count: result.count,
6653
+ message: `Retrieved ${result.count} dashboards (DB)`
6654
+ }
6655
+ }, sendMessage, clientId);
6656
+ return;
6657
+ }
6658
+ } catch (dbError) {
6659
+ logger.warn(`[DB] Failed to get all dashboards, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6660
+ }
5990
6661
  const dashboards = dashboardManager2.getAllDashboards();
5991
- logger.info(`Admin retrieved all dashboards (count: ${dashboards.length})`);
6662
+ logger.info(`[FILE] Retrieved ${dashboards.length} dashboards`);
5992
6663
  sendResponse4(id, {
5993
6664
  success: true,
5994
6665
  data: {
5995
6666
  dashboards,
5996
6667
  count: dashboards.length,
5997
- message: `Retrieved ${dashboards.length} dashboards`
6668
+ message: `Retrieved ${dashboards.length} dashboards (File)`
5998
6669
  }
5999
6670
  }, sendMessage, clientId);
6000
6671
  }
6001
- async function handleGetOne2(id, dashboardId, dashboardManager2, sendMessage, clientId) {
6002
- if (!dashboardId || dashboardId.trim().length === 0) {
6672
+ async function handleGetOne2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, clientId) {
6673
+ if (!numericId) {
6003
6674
  sendResponse4(id, {
6004
6675
  success: false,
6005
- error: "Dashboard ID is required and cannot be empty"
6676
+ error: "Dashboard ID is required"
6006
6677
  }, sendMessage, clientId);
6007
6678
  return;
6008
6679
  }
6009
- const dashboard = dashboardManager2.getDashboard(dashboardId);
6680
+ try {
6681
+ const result = await executeCollection("dashboards", "getOne", { id: numericId });
6682
+ if (result && result.success) {
6683
+ logger.info(`[DB] Retrieved dashboard ID: ${numericId}`);
6684
+ sendResponse4(id, {
6685
+ success: true,
6686
+ data: {
6687
+ id: numericId,
6688
+ dashboardId: result.data?.dashboardId,
6689
+ dashboard: result.data?.dashboard || result.data,
6690
+ message: `Retrieved dashboard (DB)`
6691
+ }
6692
+ }, sendMessage, clientId);
6693
+ return;
6694
+ }
6695
+ } catch (dbError) {
6696
+ logger.warn(`[DB] Failed to get dashboard, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6697
+ }
6698
+ const fileStorageId = dashboardId || String(numericId);
6699
+ const dashboard = dashboardManager2.getDashboard(fileStorageId);
6010
6700
  if (!dashboard) {
6011
6701
  sendResponse4(id, {
6012
6702
  success: false,
6013
- error: `Dashboard '${dashboardId}' not found`
6703
+ error: `Dashboard '${fileStorageId}' not found`
6014
6704
  }, sendMessage, clientId);
6015
6705
  return;
6016
6706
  }
6017
- logger.info(`Admin retrieved dashboard: ${dashboardId}`);
6707
+ logger.info(`[FILE] Retrieved dashboard: ${fileStorageId}`);
6018
6708
  sendResponse4(id, {
6019
6709
  success: true,
6020
6710
  data: {
6021
- dashboardId,
6711
+ id: numericId,
6712
+ dashboardId: fileStorageId,
6022
6713
  dashboard,
6023
- message: `Retrieved dashboard '${dashboardId}'`
6714
+ message: `Retrieved dashboard '${fileStorageId}' (File)`
6715
+ }
6716
+ }, sendMessage, clientId);
6717
+ }
6718
+ async function handleQuery(id, filters, limit, sort, executeCollection, dashboardManager2, sendMessage, clientId) {
6719
+ try {
6720
+ const result = await executeCollection("dashboards", "query", {
6721
+ filters: filters || {},
6722
+ limit,
6723
+ sort
6724
+ });
6725
+ if (result && result.success) {
6726
+ logger.info(`[DB] Query returned ${result.count} dashboards`);
6727
+ sendResponse4(id, {
6728
+ success: true,
6729
+ data: {
6730
+ dashboards: result.data,
6731
+ count: result.count,
6732
+ message: `Query returned ${result.count} dashboards (DB)`
6733
+ }
6734
+ }, sendMessage, clientId);
6735
+ return;
6736
+ }
6737
+ } catch (dbError) {
6738
+ logger.warn(`[DB] Failed to query dashboards: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6739
+ }
6740
+ const dashboards = dashboardManager2.getAllDashboards();
6741
+ logger.info(`[FILE] Retrieved ${dashboards.length} dashboards (all - no query filter)`);
6742
+ sendResponse4(id, {
6743
+ success: true,
6744
+ data: {
6745
+ dashboards,
6746
+ count: dashboards.length,
6747
+ message: `Retrieved ${dashboards.length} dashboards (File - no query filter)`
6024
6748
  }
6025
6749
  }, sendMessage, clientId);
6026
6750
  }
@@ -6053,13 +6777,29 @@ function setReportManager(manager) {
6053
6777
  }
6054
6778
 
6055
6779
  // src/handlers/reports.ts
6056
- async function handleReportsRequest(data, sendMessage) {
6780
+ async function handleReportsRequest(data, collections, sendMessage) {
6781
+ const executeCollection = async (collection, op, params) => {
6782
+ const handler = collections[collection]?.[op];
6783
+ if (!handler) {
6784
+ return null;
6785
+ }
6786
+ return await handler(params);
6787
+ };
6057
6788
  try {
6058
6789
  const request = ReportsRequestMessageSchema.parse(data);
6059
6790
  const { id, payload, from } = request;
6060
6791
  const { operation, data: requestData } = payload;
6061
6792
  const reportId = requestData?.reportId;
6062
6793
  const report = requestData?.report;
6794
+ const projectId = requestData?.projectId;
6795
+ const name = requestData?.name;
6796
+ const description = requestData?.description;
6797
+ const createdBy = requestData?.createdBy;
6798
+ const updatedBy = requestData?.updatedBy;
6799
+ const numericId = requestData?.id;
6800
+ const filters = requestData?.filters;
6801
+ const limit = requestData?.limit;
6802
+ const sort = requestData?.sort;
6063
6803
  if (from.type !== "admin") {
6064
6804
  sendResponse5(id, {
6065
6805
  success: false,
@@ -6071,19 +6811,22 @@ async function handleReportsRequest(data, sendMessage) {
6071
6811
  const reportManager2 = getReportManager();
6072
6812
  switch (operation) {
6073
6813
  case "create":
6074
- await handleCreate3(id, reportId, report, reportManager2, sendMessage, from.id);
6814
+ await handleCreate3(id, reportId, report, projectId, name, description, createdBy, executeCollection, reportManager2, sendMessage, from.id);
6075
6815
  break;
6076
6816
  case "update":
6077
- await handleUpdate3(id, reportId, report, reportManager2, sendMessage, from.id);
6817
+ await handleUpdate3(id, numericId, reportId, report, name, description, updatedBy, executeCollection, reportManager2, sendMessage, from.id);
6078
6818
  break;
6079
6819
  case "delete":
6080
- await handleDelete3(id, reportId, reportManager2, sendMessage, from.id);
6820
+ await handleDelete3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, from.id);
6081
6821
  break;
6082
6822
  case "getAll":
6083
- await handleGetAll3(id, reportManager2, sendMessage, from.id);
6823
+ await handleGetAll3(id, executeCollection, reportManager2, sendMessage, from.id);
6084
6824
  break;
6085
6825
  case "getOne":
6086
- await handleGetOne3(id, reportId, reportManager2, sendMessage, from.id);
6826
+ await handleGetOne3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, from.id);
6827
+ break;
6828
+ case "query":
6829
+ await handleQuery2(id, filters, limit, sort, executeCollection, reportManager2, sendMessage, from.id);
6087
6830
  break;
6088
6831
  default:
6089
6832
  sendResponse5(id, {
@@ -6099,7 +6842,7 @@ async function handleReportsRequest(data, sendMessage) {
6099
6842
  }, sendMessage);
6100
6843
  }
6101
6844
  }
6102
- async function handleCreate3(id, reportId, report, reportManager2, sendMessage, clientId) {
6845
+ async function handleCreate3(id, reportId, report, projectId, name, description, createdBy, executeCollection, reportManager2, sendMessage, clientId) {
6103
6846
  if (!reportId || reportId.trim().length === 0) {
6104
6847
  sendResponse5(id, {
6105
6848
  success: false,
@@ -6107,21 +6850,50 @@ async function handleCreate3(id, reportId, report, reportManager2, sendMessage,
6107
6850
  }, sendMessage, clientId);
6108
6851
  return;
6109
6852
  }
6110
- if (!report) {
6853
+ if (!projectId) {
6111
6854
  sendResponse5(id, {
6112
6855
  success: false,
6113
- error: "Report data is required"
6856
+ error: "Project ID is required"
6114
6857
  }, sendMessage, clientId);
6115
6858
  return;
6116
6859
  }
6117
6860
  try {
6861
+ const result = await executeCollection("reports", "create", {
6862
+ reportId,
6863
+ projectId,
6864
+ name: name || "",
6865
+ description,
6866
+ report,
6867
+ createdBy
6868
+ });
6869
+ if (result && result.success) {
6870
+ logger.info(`[DB] Report created successfully, ID: ${result.data?.id}`);
6871
+ sendResponse5(id, {
6872
+ success: true,
6873
+ data: {
6874
+ id: result.data?.id,
6875
+ reportId: result.data?.reportId,
6876
+ report: result.data?.report || report,
6877
+ message: `Report created successfully (DB)`
6878
+ }
6879
+ }, sendMessage, clientId);
6880
+ return;
6881
+ }
6882
+ } catch (dbError) {
6883
+ logger.warn(`[DB] Failed to create report, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6884
+ }
6885
+ try {
6886
+ if (!report) {
6887
+ report = {};
6888
+ }
6118
6889
  const createdReport = reportManager2.createReport(reportId, report);
6890
+ logger.info(`[FILE] Report '${reportId}' created successfully`);
6119
6891
  sendResponse5(id, {
6120
6892
  success: true,
6121
6893
  data: {
6122
6894
  reportId,
6123
6895
  report: createdReport,
6124
- message: `Report '${reportId}' created successfully`
6896
+ message: `Report '${reportId}' created successfully (File)`
6125
6897
  }
6126
6898
  }, sendMessage, clientId);
6127
6899
  } catch (error) {
@@ -6131,36 +6903,56 @@ async function handleCreate3(id, reportId, report, reportManager2, sendMessage,
6131
6903
  }, sendMessage, clientId);
6132
6904
  }
6133
6905
  }
6134
- async function handleUpdate3(id, reportId, report, reportManager2, sendMessage, clientId) {
6135
- if (!reportId || reportId.trim().length === 0) {
6906
+ async function handleUpdate3(id, numericId, reportId, report, name, description, updatedBy, executeCollection, reportManager2, sendMessage, clientId) {
6907
+ if (!numericId) {
6136
6908
  sendResponse5(id, {
6137
6909
  success: false,
6138
- error: "Report ID is required and cannot be empty"
6910
+ error: "Report ID is required"
6139
6911
  }, sendMessage, clientId);
6140
6912
  return;
6141
6913
  }
6142
- if (!report) {
6143
- sendResponse5(id, {
6144
- success: false,
6145
- error: "Report data is required"
6146
- }, sendMessage, clientId);
6147
- return;
6914
+ try {
6915
+ const result = await executeCollection("reports", "update", {
6916
+ id: numericId,
6917
+ name,
6918
+ description,
6919
+ report,
6920
+ updatedBy
6921
+ });
6922
+ if (result && result.success) {
6923
+ logger.info(`[DB] Report updated successfully, ID: ${numericId}`);
6924
+ sendResponse5(id, {
6925
+ success: true,
6926
+ data: {
6927
+ id: numericId,
6928
+ reportId: result.data?.reportId,
6929
+ report: result.data?.report || report,
6930
+ message: `Report updated successfully (DB)`
6931
+ }
6932
+ }, sendMessage, clientId);
6933
+ return;
6934
+ }
6935
+ } catch (dbError) {
6936
+ logger.warn(`[DB] Failed to update report, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6148
6937
  }
6938
+ const fileStorageId = reportId || String(numericId);
6149
6939
  try {
6150
- const updatedReport = reportManager2.updateReport(reportId, report);
6940
+ const updatedReport = reportManager2.updateReport(fileStorageId, report);
6151
6941
  if (!updatedReport) {
6152
6942
  sendResponse5(id, {
6153
6943
  success: false,
6154
- error: `Report '${reportId}' not found`
6944
+ error: `Report '${fileStorageId}' not found`
6155
6945
  }, sendMessage, clientId);
6156
6946
  return;
6157
6947
  }
6948
+ logger.info(`[FILE] Report '${fileStorageId}' updated successfully`);
6158
6949
  sendResponse5(id, {
6159
6950
  success: true,
6160
6951
  data: {
6161
- reportId,
6952
+ id: numericId,
6953
+ reportId: fileStorageId,
6162
6954
  report: updatedReport,
6163
- message: `Report '${reportId}' updated successfully`
6955
+ message: `Report '${fileStorageId}' updated successfully (File)`
6164
6956
  }
6165
6957
  }, sendMessage, clientId);
6166
6958
  } catch (error) {
@@ -6170,65 +6962,154 @@ async function handleUpdate3(id, reportId, report, reportManager2, sendMessage,
6170
6962
  }, sendMessage, clientId);
6171
6963
  }
6172
6964
  }
6173
- async function handleDelete3(id, reportId, reportManager2, sendMessage, clientId) {
6174
- if (!reportId || reportId.trim().length === 0) {
6965
+ async function handleDelete3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, clientId) {
6966
+ if (!numericId) {
6175
6967
  sendResponse5(id, {
6176
6968
  success: false,
6177
- error: "Report ID is required and cannot be empty"
6969
+ error: "Report ID is required"
6178
6970
  }, sendMessage, clientId);
6179
6971
  return;
6180
6972
  }
6181
- const deleted = reportManager2.deleteReport(reportId);
6973
+ try {
6974
+ const result = await executeCollection("reports", "delete", { id: numericId });
6975
+ if (result && result.success) {
6976
+ logger.info(`[DB] Report deleted successfully, ID: ${numericId}`);
6977
+ sendResponse5(id, {
6978
+ success: true,
6979
+ data: {
6980
+ id: numericId,
6981
+ message: `Report deleted successfully (DB)`
6982
+ }
6983
+ }, sendMessage, clientId);
6984
+ return;
6985
+ }
6986
+ } catch (dbError) {
6987
+ logger.warn(`[DB] Failed to delete report, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
6988
+ }
6989
+ const fileStorageId = reportId || String(numericId);
6990
+ const deleted = reportManager2.deleteReport(fileStorageId);
6182
6991
  if (!deleted) {
6183
6992
  sendResponse5(id, {
6184
6993
  success: false,
6185
- error: `Report '${reportId}' not found`
6994
+ error: `Report '${fileStorageId}' not found`
6186
6995
  }, sendMessage, clientId);
6187
6996
  return;
6188
6997
  }
6998
+ logger.info(`[FILE] Report '${fileStorageId}' deleted successfully`);
6189
6999
  sendResponse5(id, {
6190
7000
  success: true,
6191
7001
  data: {
6192
- reportId,
6193
- message: `Report '${reportId}' deleted successfully`
7002
+ id: numericId,
7003
+ reportId: fileStorageId,
7004
+ message: `Report '${fileStorageId}' deleted successfully (File)`
6194
7005
  }
6195
7006
  }, sendMessage, clientId);
6196
7007
  }
6197
- async function handleGetAll3(id, reportManager2, sendMessage, clientId) {
7008
+ async function handleGetAll3(id, executeCollection, reportManager2, sendMessage, clientId) {
7009
+ try {
7010
+ const result = await executeCollection("reports", "getAll", {});
7011
+ if (result && result.success) {
7012
+ logger.info(`[DB] Retrieved ${result.count} reports`);
7013
+ sendResponse5(id, {
7014
+ success: true,
7015
+ data: {
7016
+ reports: result.data,
7017
+ count: result.count,
7018
+ message: `Retrieved ${result.count} reports (DB)`
7019
+ }
7020
+ }, sendMessage, clientId);
7021
+ return;
7022
+ }
7023
+ } catch (dbError) {
7024
+ logger.warn(`[DB] Failed to get all reports, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
7025
+ }
6198
7026
  const reports = reportManager2.getAllReports();
6199
- logger.info(`Admin retrieved all reports (count: ${reports.length})`);
7027
+ logger.info(`[FILE] Retrieved ${reports.length} reports`);
6200
7028
  sendResponse5(id, {
6201
7029
  success: true,
6202
7030
  data: {
6203
7031
  reports,
6204
7032
  count: reports.length,
6205
- message: `Retrieved ${reports.length} reports`
7033
+ message: `Retrieved ${reports.length} reports (File)`
6206
7034
  }
6207
7035
  }, sendMessage, clientId);
6208
7036
  }
6209
- async function handleGetOne3(id, reportId, reportManager2, sendMessage, clientId) {
6210
- if (!reportId || reportId.trim().length === 0) {
7037
+ async function handleGetOne3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, clientId) {
7038
+ if (!numericId) {
6211
7039
  sendResponse5(id, {
6212
7040
  success: false,
6213
- error: "Report ID is required and cannot be empty"
7041
+ error: "Report ID is required"
6214
7042
  }, sendMessage, clientId);
6215
7043
  return;
6216
7044
  }
6217
- const report = reportManager2.getReport(reportId);
7045
+ try {
7046
+ const result = await executeCollection("reports", "getOne", { id: numericId });
7047
+ if (result && result.success) {
7048
+ logger.info(`[DB] Retrieved report ID: ${numericId}`);
7049
+ sendResponse5(id, {
7050
+ success: true,
7051
+ data: {
7052
+ id: numericId,
7053
+ reportId: result.data?.reportId,
7054
+ report: result.data?.report || result.data,
7055
+ message: `Retrieved report (DB)`
7056
+ }
7057
+ }, sendMessage, clientId);
7058
+ return;
7059
+ }
7060
+ } catch (dbError) {
7061
+ logger.warn(`[DB] Failed to get report, falling back to file storage: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
7062
+ }
7063
+ const fileStorageId = reportId || String(numericId);
7064
+ const report = reportManager2.getReport(fileStorageId);
6218
7065
  if (!report) {
6219
7066
  sendResponse5(id, {
6220
7067
  success: false,
6221
- error: `Report '${reportId}' not found`
7068
+ error: `Report '${fileStorageId}' not found`
6222
7069
  }, sendMessage, clientId);
6223
7070
  return;
6224
7071
  }
6225
- logger.info(`Admin retrieved report: ${reportId}`);
7072
+ logger.info(`[FILE] Retrieved report: ${fileStorageId}`);
6226
7073
  sendResponse5(id, {
6227
7074
  success: true,
6228
7075
  data: {
6229
- reportId,
7076
+ id: numericId,
7077
+ reportId: fileStorageId,
6230
7078
  report,
6231
- message: `Retrieved report '${reportId}'`
7079
+ message: `Retrieved report '${fileStorageId}' (File)`
7080
+ }
7081
+ }, sendMessage, clientId);
7082
+ }
7083
+ async function handleQuery2(id, filters, limit, sort, executeCollection, reportManager2, sendMessage, clientId) {
7084
+ try {
7085
+ const result = await executeCollection("reports", "query", {
7086
+ filters: filters || {},
7087
+ limit,
7088
+ sort
7089
+ });
7090
+ if (result && result.success) {
7091
+ logger.info(`[DB] Query returned ${result.count} reports`);
7092
+ sendResponse5(id, {
7093
+ success: true,
7094
+ data: {
7095
+ reports: result.data,
7096
+ count: result.count,
7097
+ message: `Query returned ${result.count} reports (DB)`
7098
+ }
7099
+ }, sendMessage, clientId);
7100
+ return;
7101
+ }
7102
+ } catch (dbError) {
7103
+ logger.warn(`[DB] Failed to query reports: ${dbError instanceof Error ? dbError.message : "Unknown error"}`);
7104
+ }
7105
+ const reports = reportManager2.getAllReports();
7106
+ logger.info(`[FILE] Retrieved ${reports.length} reports (all - no query filter)`);
7107
+ sendResponse5(id, {
7108
+ success: true,
7109
+ data: {
7110
+ reports,
7111
+ count: reports.length,
7112
+ message: `Retrieved ${reports.length} reports (File - no query filter)`
6232
7113
  }
6233
7114
  }, sendMessage, clientId);
6234
7115
  }
@@ -6248,6 +7129,297 @@ function sendResponse5(id, res, sendMessage, clientId) {
6248
7129
  sendMessage(response);
6249
7130
  }
6250
7131
 
7132
+ // src/handlers/uis.ts
7133
+ async function handleUIsRequest(data, collections, sendMessage) {
7134
+ const executeCollection = async (collection, op, params) => {
7135
+ const handler = collections[collection]?.[op];
7136
+ if (!handler) {
7137
+ throw new Error(`Collection handler not found: ${collection}.${op}`);
7138
+ }
7139
+ return await handler(params);
7140
+ };
7141
+ try {
7142
+ const request = UIsRequestMessageSchema.parse(data);
7143
+ const { id, payload, from } = request;
7144
+ const { operation, data: requestData } = payload;
7145
+ const uiId = requestData?.uiId;
7146
+ const ui = requestData?.ui;
7147
+ const projectId = requestData?.projectId;
7148
+ const name = requestData?.name;
7149
+ const description = requestData?.description;
7150
+ const createdBy = requestData?.createdBy;
7151
+ const updatedBy = requestData?.updatedBy;
7152
+ const numericId = requestData?.id;
7153
+ const filters = requestData?.filters;
7154
+ const limit = requestData?.limit;
7155
+ const sort = requestData?.sort;
7156
+ if (from.type !== "admin") {
7157
+ sendResponse6(id, {
7158
+ success: false,
7159
+ error: "Unauthorized: Only admin can manage UIs"
7160
+ }, sendMessage, from.id);
7161
+ logger.warn(`Unauthorized UI management attempt from: ${from.type}`);
7162
+ return;
7163
+ }
7164
+ switch (operation) {
7165
+ case "create":
7166
+ await handleCreate4(id, uiId, ui, projectId, name, description, createdBy, executeCollection, sendMessage, from.id);
7167
+ break;
7168
+ case "update":
7169
+ await handleUpdate4(id, numericId, ui, name, description, updatedBy, executeCollection, sendMessage, from.id);
7170
+ break;
7171
+ case "delete":
7172
+ await handleDelete4(id, numericId, executeCollection, sendMessage, from.id);
7173
+ break;
7174
+ case "getAll":
7175
+ await handleGetAll4(id, executeCollection, sendMessage, from.id);
7176
+ break;
7177
+ case "getOne":
7178
+ await handleGetOne4(id, numericId, executeCollection, sendMessage, from.id);
7179
+ break;
7180
+ case "query":
7181
+ await handleQuery3(id, filters, limit, sort, executeCollection, sendMessage, from.id);
7182
+ break;
7183
+ default:
7184
+ sendResponse6(id, {
7185
+ success: false,
7186
+ error: `Unknown operation: ${operation}`
7187
+ }, sendMessage, from.id);
7188
+ }
7189
+ } catch (error) {
7190
+ logger.error("Failed to handle UIs request:", error);
7191
+ sendResponse6(null, {
7192
+ success: false,
7193
+ error: error instanceof Error ? error.message : "Unknown error occurred"
7194
+ }, sendMessage);
7195
+ }
7196
+ }
7197
+ async function handleCreate4(id, uiId, ui, projectId, name, description, createdBy, executeCollection, sendMessage, clientId) {
7198
+ if (!uiId || uiId.trim().length === 0) {
7199
+ sendResponse6(id, {
7200
+ success: false,
7201
+ error: "UI ID is required and cannot be empty"
7202
+ }, sendMessage, clientId);
7203
+ return;
7204
+ }
7205
+ if (!projectId || projectId.trim().length === 0) {
7206
+ sendResponse6(id, {
7207
+ success: false,
7208
+ error: "Project ID is required and cannot be empty"
7209
+ }, sendMessage, clientId);
7210
+ return;
7211
+ }
7212
+ try {
7213
+ const result = await executeCollection("uis", "create", {
7214
+ uiId,
7215
+ projectId,
7216
+ name: name || uiId,
7217
+ description,
7218
+ ui,
7219
+ createdBy
7220
+ });
7221
+ if (result && result.success) {
7222
+ logger.info(`UI created successfully, ID: ${result.data?.id}`);
7223
+ sendResponse6(id, {
7224
+ success: true,
7225
+ data: {
7226
+ id: result.data?.id,
7227
+ uiId: result.data?.uiId || uiId,
7228
+ ui: result.data?.ui || ui,
7229
+ message: `UI created successfully`
7230
+ }
7231
+ }, sendMessage, clientId);
7232
+ } else {
7233
+ sendResponse6(id, {
7234
+ success: false,
7235
+ error: "Failed to create UI"
7236
+ }, sendMessage, clientId);
7237
+ }
7238
+ } catch (error) {
7239
+ sendResponse6(id, {
7240
+ success: false,
7241
+ error: error instanceof Error ? error.message : "Failed to create UI"
7242
+ }, sendMessage, clientId);
7243
+ }
7244
+ }
7245
+ async function handleUpdate4(id, numericId, ui, name, description, updatedBy, executeCollection, sendMessage, clientId) {
7246
+ if (!numericId) {
7247
+ sendResponse6(id, {
7248
+ success: false,
7249
+ error: "UI ID is required"
7250
+ }, sendMessage, clientId);
7251
+ return;
7252
+ }
7253
+ try {
7254
+ const result = await executeCollection("uis", "update", {
7255
+ id: numericId,
7256
+ name,
7257
+ description,
7258
+ ui,
7259
+ updatedBy
7260
+ });
7261
+ if (result && result.success) {
7262
+ logger.info(`UI updated successfully, ID: ${numericId}`);
7263
+ sendResponse6(id, {
7264
+ success: true,
7265
+ data: {
7266
+ id: numericId,
7267
+ uiId: result.data?.uiId,
7268
+ ui: result.data?.ui || ui,
7269
+ message: `UI updated successfully`
7270
+ }
7271
+ }, sendMessage, clientId);
7272
+ } else {
7273
+ sendResponse6(id, {
7274
+ success: false,
7275
+ error: "Failed to update UI"
7276
+ }, sendMessage, clientId);
7277
+ }
7278
+ } catch (error) {
7279
+ sendResponse6(id, {
7280
+ success: false,
7281
+ error: error instanceof Error ? error.message : "Failed to update UI"
7282
+ }, sendMessage, clientId);
7283
+ }
7284
+ }
7285
+ async function handleDelete4(id, numericId, 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", "delete", { id: numericId });
7295
+ if (result && result.success) {
7296
+ logger.info(`UI deleted successfully, ID: ${numericId}`);
7297
+ sendResponse6(id, {
7298
+ success: true,
7299
+ data: {
7300
+ id: numericId,
7301
+ message: `UI deleted successfully`
7302
+ }
7303
+ }, sendMessage, clientId);
7304
+ } else {
7305
+ sendResponse6(id, {
7306
+ success: false,
7307
+ error: "Failed to delete UI"
7308
+ }, sendMessage, clientId);
7309
+ }
7310
+ } catch (error) {
7311
+ sendResponse6(id, {
7312
+ success: false,
7313
+ error: error instanceof Error ? error.message : "Failed to delete UI"
7314
+ }, sendMessage, clientId);
7315
+ }
7316
+ }
7317
+ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
7318
+ try {
7319
+ const result = await executeCollection("uis", "getAll", {});
7320
+ if (result && result.success) {
7321
+ logger.info(`Retrieved ${result.count} UIs`);
7322
+ sendResponse6(id, {
7323
+ success: true,
7324
+ data: {
7325
+ uis: result.data,
7326
+ count: result.count,
7327
+ message: `Retrieved ${result.count} UIs`
7328
+ }
7329
+ }, sendMessage, clientId);
7330
+ } else {
7331
+ sendResponse6(id, {
7332
+ success: false,
7333
+ error: "Failed to get UIs"
7334
+ }, sendMessage, clientId);
7335
+ }
7336
+ } catch (error) {
7337
+ sendResponse6(id, {
7338
+ success: false,
7339
+ error: error instanceof Error ? error.message : "Failed to get UIs"
7340
+ }, sendMessage, clientId);
7341
+ }
7342
+ }
7343
+ async function handleGetOne4(id, numericId, executeCollection, sendMessage, clientId) {
7344
+ if (!numericId) {
7345
+ sendResponse6(id, {
7346
+ success: false,
7347
+ error: "UI ID is required"
7348
+ }, sendMessage, clientId);
7349
+ return;
7350
+ }
7351
+ try {
7352
+ const result = await executeCollection("uis", "getOne", { id: numericId });
7353
+ if (result && result.success) {
7354
+ logger.info(`Retrieved UI ID: ${numericId}`);
7355
+ sendResponse6(id, {
7356
+ success: true,
7357
+ data: {
7358
+ id: numericId,
7359
+ uiId: result.data?.uiId,
7360
+ ui: result.data?.ui || result.data,
7361
+ message: `Retrieved UI`
7362
+ }
7363
+ }, sendMessage, clientId);
7364
+ } else {
7365
+ sendResponse6(id, {
7366
+ success: false,
7367
+ error: `UI not found`
7368
+ }, sendMessage, clientId);
7369
+ }
7370
+ } catch (error) {
7371
+ sendResponse6(id, {
7372
+ success: false,
7373
+ error: error instanceof Error ? error.message : "Failed to get UI"
7374
+ }, sendMessage, clientId);
7375
+ }
7376
+ }
7377
+ async function handleQuery3(id, filters, limit, sort, executeCollection, sendMessage, clientId) {
7378
+ try {
7379
+ const result = await executeCollection("uis", "query", {
7380
+ filters: filters || {},
7381
+ limit,
7382
+ sort
7383
+ });
7384
+ if (result && result.success) {
7385
+ logger.info(`Query returned ${result.count} UIs`);
7386
+ sendResponse6(id, {
7387
+ success: true,
7388
+ data: {
7389
+ uis: result.data,
7390
+ count: result.count,
7391
+ message: `Query returned ${result.count} UIs`
7392
+ }
7393
+ }, sendMessage, clientId);
7394
+ } else {
7395
+ sendResponse6(id, {
7396
+ success: false,
7397
+ error: "Failed to query UIs"
7398
+ }, sendMessage, clientId);
7399
+ }
7400
+ } catch (error) {
7401
+ sendResponse6(id, {
7402
+ success: false,
7403
+ error: error instanceof Error ? error.message : "Failed to query UIs"
7404
+ }, sendMessage, clientId);
7405
+ }
7406
+ }
7407
+ function sendResponse6(id, res, sendMessage, clientId) {
7408
+ const response = {
7409
+ id: id || "unknown",
7410
+ type: "UIS_RES",
7411
+ from: { type: "data-agent" },
7412
+ to: {
7413
+ type: "admin",
7414
+ id: clientId
7415
+ },
7416
+ payload: {
7417
+ ...res
7418
+ }
7419
+ };
7420
+ sendMessage(response);
7421
+ }
7422
+
6251
7423
  // src/handlers/bookmarks.ts
6252
7424
  async function handleBookmarksRequest(data, collections, sendMessage) {
6253
7425
  const executeCollection = async (collection, op, params) => {
@@ -6264,22 +7436,24 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6264
7436
  const bookmarkId = requestData?.id;
6265
7437
  const userId = requestData?.userId;
6266
7438
  const threadId = requestData?.threadId;
7439
+ const name = requestData?.name;
7440
+ const description = requestData?.description;
6267
7441
  const uiblock = requestData?.uiblock;
6268
7442
  switch (operation) {
6269
7443
  case "create":
6270
- await handleCreate4(id, userId, threadId, uiblock, executeCollection, sendMessage, from.id);
7444
+ await handleCreate5(id, userId, threadId, name, description, uiblock, executeCollection, sendMessage, from.id);
6271
7445
  break;
6272
7446
  case "update":
6273
- await handleUpdate4(id, bookmarkId, threadId, uiblock, executeCollection, sendMessage, from.id);
7447
+ await handleUpdate5(id, bookmarkId, threadId, name, description, uiblock, executeCollection, sendMessage, from.id);
6274
7448
  break;
6275
7449
  case "delete":
6276
- await handleDelete4(id, bookmarkId, executeCollection, sendMessage, from.id);
7450
+ await handleDelete5(id, bookmarkId, executeCollection, sendMessage, from.id);
6277
7451
  break;
6278
7452
  case "getAll":
6279
- await handleGetAll4(id, executeCollection, sendMessage, from.id);
7453
+ await handleGetAll5(id, executeCollection, sendMessage, from.id);
6280
7454
  break;
6281
7455
  case "getOne":
6282
- await handleGetOne4(id, bookmarkId, executeCollection, sendMessage, from.id);
7456
+ await handleGetOne5(id, bookmarkId, executeCollection, sendMessage, from.id);
6283
7457
  break;
6284
7458
  case "getByUser":
6285
7459
  await handleGetByUser(id, userId, threadId, executeCollection, sendMessage, from.id);
@@ -6288,82 +7462,75 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
6288
7462
  await handleGetByThread(id, threadId, executeCollection, sendMessage, from.id);
6289
7463
  break;
6290
7464
  default:
6291
- sendResponse6(id, {
7465
+ sendResponse7(id, {
6292
7466
  success: false,
6293
7467
  error: `Unknown operation: ${operation}`
6294
7468
  }, sendMessage, from.id);
6295
7469
  }
6296
7470
  } catch (error) {
6297
7471
  logger.error("Failed to handle bookmarks request:", error);
6298
- sendResponse6(null, {
7472
+ sendResponse7(null, {
6299
7473
  success: false,
6300
7474
  error: error instanceof Error ? error.message : "Unknown error occurred"
6301
7475
  }, sendMessage);
6302
7476
  }
6303
7477
  }
6304
- async function handleCreate4(id, userId, threadId, uiblock, executeCollection, sendMessage, clientId) {
7478
+ async function handleCreate5(id, userId, threadId, name, description, uiblock, executeCollection, sendMessage, clientId) {
6305
7479
  if (!userId) {
6306
- sendResponse6(id, {
7480
+ sendResponse7(id, {
6307
7481
  success: false,
6308
7482
  error: "userId is required"
6309
7483
  }, sendMessage, clientId);
6310
7484
  return;
6311
7485
  }
6312
7486
  if (!uiblock) {
6313
- sendResponse6(id, {
7487
+ sendResponse7(id, {
6314
7488
  success: false,
6315
7489
  error: "UIBlock data is required"
6316
7490
  }, sendMessage, clientId);
6317
7491
  return;
6318
7492
  }
6319
7493
  try {
6320
- const result = await executeCollection("bookmarks", "create", { userId, threadId, uiblock });
6321
- sendResponse6(id, {
7494
+ const result = await executeCollection("bookmarks", "create", { userId, threadId, name, description, uiblock });
7495
+ sendResponse7(id, {
6322
7496
  success: true,
6323
7497
  data: result.data,
6324
7498
  message: "Bookmark created successfully"
6325
7499
  }, sendMessage, clientId);
6326
7500
  logger.info(`Bookmark created: ID ${result.data.id}`);
6327
7501
  } catch (error) {
6328
- sendResponse6(id, {
7502
+ sendResponse7(id, {
6329
7503
  success: false,
6330
7504
  error: error instanceof Error ? error.message : "Failed to create bookmark"
6331
7505
  }, sendMessage, clientId);
6332
7506
  }
6333
7507
  }
6334
- async function handleUpdate4(id, bookmarkId, threadId, uiblock, executeCollection, sendMessage, clientId) {
7508
+ async function handleUpdate5(id, bookmarkId, threadId, name, description, uiblock, executeCollection, sendMessage, clientId) {
6335
7509
  if (!bookmarkId) {
6336
- sendResponse6(id, {
7510
+ sendResponse7(id, {
6337
7511
  success: false,
6338
7512
  error: "Bookmark ID is required"
6339
7513
  }, sendMessage, clientId);
6340
7514
  return;
6341
7515
  }
6342
- if (!uiblock) {
6343
- sendResponse6(id, {
6344
- success: false,
6345
- error: "UIBlock data is required"
6346
- }, sendMessage, clientId);
6347
- return;
6348
- }
6349
7516
  try {
6350
- const result = await executeCollection("bookmarks", "update", { id: bookmarkId, threadId, uiblock });
6351
- sendResponse6(id, {
7517
+ const result = await executeCollection("bookmarks", "update", { id: bookmarkId, threadId, name, description, uiblock });
7518
+ sendResponse7(id, {
6352
7519
  success: true,
6353
7520
  data: result.data,
6354
7521
  message: "Bookmark updated successfully"
6355
7522
  }, sendMessage, clientId);
6356
7523
  logger.info(`Bookmark updated: ID ${bookmarkId}`);
6357
7524
  } catch (error) {
6358
- sendResponse6(id, {
7525
+ sendResponse7(id, {
6359
7526
  success: false,
6360
7527
  error: error instanceof Error ? error.message : "Failed to update bookmark"
6361
7528
  }, sendMessage, clientId);
6362
7529
  }
6363
7530
  }
6364
- async function handleDelete4(id, bookmarkId, executeCollection, sendMessage, clientId) {
7531
+ async function handleDelete5(id, bookmarkId, executeCollection, sendMessage, clientId) {
6365
7532
  if (!bookmarkId) {
6366
- sendResponse6(id, {
7533
+ sendResponse7(id, {
6367
7534
  success: false,
6368
7535
  error: "Bookmark ID is required"
6369
7536
  }, sendMessage, clientId);
@@ -6371,23 +7538,23 @@ async function handleDelete4(id, bookmarkId, executeCollection, sendMessage, cli
6371
7538
  }
6372
7539
  try {
6373
7540
  const result = await executeCollection("bookmarks", "delete", { id: bookmarkId });
6374
- sendResponse6(id, {
7541
+ sendResponse7(id, {
6375
7542
  success: true,
6376
7543
  data: result.data,
6377
7544
  message: "Bookmark deleted successfully"
6378
7545
  }, sendMessage, clientId);
6379
7546
  logger.info(`Bookmark deleted: ID ${bookmarkId}`);
6380
7547
  } catch (error) {
6381
- sendResponse6(id, {
7548
+ sendResponse7(id, {
6382
7549
  success: false,
6383
7550
  error: error instanceof Error ? error.message : "Failed to delete bookmark"
6384
7551
  }, sendMessage, clientId);
6385
7552
  }
6386
7553
  }
6387
- async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
7554
+ async function handleGetAll5(id, executeCollection, sendMessage, clientId) {
6388
7555
  try {
6389
7556
  const result = await executeCollection("bookmarks", "getAll", {});
6390
- sendResponse6(id, {
7557
+ sendResponse7(id, {
6391
7558
  success: true,
6392
7559
  data: result.data,
6393
7560
  count: result.count,
@@ -6395,15 +7562,15 @@ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
6395
7562
  }, sendMessage, clientId);
6396
7563
  logger.info(`Retrieved all bookmarks (count: ${result.count})`);
6397
7564
  } catch (error) {
6398
- sendResponse6(id, {
7565
+ sendResponse7(id, {
6399
7566
  success: false,
6400
7567
  error: error instanceof Error ? error.message : "Failed to get bookmarks"
6401
7568
  }, sendMessage, clientId);
6402
7569
  }
6403
7570
  }
6404
- async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, clientId) {
7571
+ async function handleGetOne5(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,14 +7578,14 @@ async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, cli
6411
7578
  }
6412
7579
  try {
6413
7580
  const result = await executeCollection("bookmarks", "getOne", { id: bookmarkId });
6414
- sendResponse6(id, {
7581
+ sendResponse7(id, {
6415
7582
  success: true,
6416
7583
  data: result.data,
6417
7584
  message: `Retrieved bookmark ID ${bookmarkId}`
6418
7585
  }, sendMessage, clientId);
6419
7586
  logger.info(`Retrieved bookmark: 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 get bookmark"
6424
7591
  }, sendMessage, clientId);
@@ -6426,7 +7593,7 @@ async function handleGetOne4(id, bookmarkId, executeCollection, sendMessage, cli
6426
7593
  }
6427
7594
  async function handleGetByUser(id, userId, threadId, executeCollection, sendMessage, clientId) {
6428
7595
  if (!userId) {
6429
- sendResponse6(id, {
7596
+ sendResponse7(id, {
6430
7597
  success: false,
6431
7598
  error: "userId is required"
6432
7599
  }, sendMessage, clientId);
@@ -6434,7 +7601,7 @@ async function handleGetByUser(id, userId, threadId, executeCollection, sendMess
6434
7601
  }
6435
7602
  try {
6436
7603
  const result = await executeCollection("bookmarks", "getByUser", { userId, threadId });
6437
- sendResponse6(id, {
7604
+ sendResponse7(id, {
6438
7605
  success: true,
6439
7606
  data: result.data,
6440
7607
  count: result.count,
@@ -6442,7 +7609,7 @@ async function handleGetByUser(id, userId, threadId, executeCollection, sendMess
6442
7609
  }, sendMessage, clientId);
6443
7610
  logger.info(`Retrieved bookmarks for user ${userId} (count: ${result.count})`);
6444
7611
  } catch (error) {
6445
- sendResponse6(id, {
7612
+ sendResponse7(id, {
6446
7613
  success: false,
6447
7614
  error: error instanceof Error ? error.message : "Failed to get bookmarks by user"
6448
7615
  }, sendMessage, clientId);
@@ -6450,7 +7617,7 @@ async function handleGetByUser(id, userId, threadId, executeCollection, sendMess
6450
7617
  }
6451
7618
  async function handleGetByThread(id, threadId, executeCollection, sendMessage, clientId) {
6452
7619
  if (!threadId) {
6453
- sendResponse6(id, {
7620
+ sendResponse7(id, {
6454
7621
  success: false,
6455
7622
  error: "threadId is required"
6456
7623
  }, sendMessage, clientId);
@@ -6458,7 +7625,7 @@ async function handleGetByThread(id, threadId, executeCollection, sendMessage, c
6458
7625
  }
6459
7626
  try {
6460
7627
  const result = await executeCollection("bookmarks", "getByThread", { threadId });
6461
- sendResponse6(id, {
7628
+ sendResponse7(id, {
6462
7629
  success: true,
6463
7630
  data: result.data,
6464
7631
  count: result.count,
@@ -6466,13 +7633,13 @@ async function handleGetByThread(id, threadId, executeCollection, sendMessage, c
6466
7633
  }, sendMessage, clientId);
6467
7634
  logger.info(`Retrieved bookmarks for thread ${threadId} (count: ${result.count})`);
6468
7635
  } catch (error) {
6469
- sendResponse6(id, {
7636
+ sendResponse7(id, {
6470
7637
  success: false,
6471
7638
  error: error instanceof Error ? error.message : "Failed to get bookmarks by thread"
6472
7639
  }, sendMessage, clientId);
6473
7640
  }
6474
7641
  }
6475
- function sendResponse6(id, res, sendMessage, clientId) {
7642
+ function sendResponse7(id, res, sendMessage, clientId) {
6476
7643
  const response = {
6477
7644
  id: id || "unknown",
6478
7645
  type: "BOOKMARKS_RES",
@@ -7324,7 +8491,10 @@ var SuperatomSDK = class {
7324
8491
  this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;
7325
8492
  this.anthropicApiKey = config.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY || "";
7326
8493
  this.groqApiKey = config.GROQ_API_KEY || process.env.GROQ_API_KEY || "";
8494
+ this.geminiApiKey = config.GEMINI_API_KEY || process.env.GEMINI_API_KEY || "";
8495
+ this.openaiApiKey = config.OPENAI_API_KEY || process.env.OPENAI_API_KEY || "";
7327
8496
  this.llmProviders = config.LLM_PROVIDERS || getLLMProviders();
8497
+ logger.info(`Initializing Superatom SDK v${SDK_VERSION} for project ${this.projectId}, llm providers: ${this.llmProviders.join(", ")}, config llm providers: ${config.LLM_PROVIDERS}`);
7328
8498
  this.userManager = new UserManager(this.projectId, 5e3);
7329
8499
  this.dashboardManager = new DashboardManager(this.projectId);
7330
8500
  this.reportManager = new ReportManager(this.projectId);
@@ -7409,7 +8579,9 @@ var SuperatomSDK = class {
7409
8579
  return new Promise((resolve, reject) => {
7410
8580
  try {
7411
8581
  const url = new URL(this.url);
7412
- url.searchParams.set("apiKey", this.apiKey);
8582
+ if (this.apiKey) {
8583
+ url.searchParams.set("apiKey", this.apiKey);
8584
+ }
7413
8585
  url.searchParams.set("projectId", this.projectId);
7414
8586
  url.searchParams.set("userId", this.userId);
7415
8587
  url.searchParams.set("type", this.type);
@@ -7468,22 +8640,22 @@ var SuperatomSDK = class {
7468
8640
  });
7469
8641
  break;
7470
8642
  case "USER_PROMPT_REQ":
7471
- handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders, this.collections, this.tools, this.userId).catch((error) => {
8643
+ 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) => {
7472
8644
  logger.error("Failed to handle user prompt request:", error);
7473
8645
  });
7474
8646
  break;
7475
8647
  case "ACTIONS":
7476
- handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.llmProviders).catch((error) => {
8648
+ handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders).catch((error) => {
7477
8649
  logger.error("Failed to handle actions request:", error);
7478
8650
  });
7479
8651
  break;
7480
8652
  case "USER_PROMPT_SUGGESTIONS_REQ":
7481
- handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg)).catch((error) => {
8653
+ handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections, this.userId).catch((error) => {
7482
8654
  logger.error("Failed to handle user prompt suggestions request:", error);
7483
8655
  });
7484
8656
  break;
7485
8657
  case "COMPONENT_LIST_RES":
7486
- handleComponentListResponse(parsed, (com) => this.storeComponents(com)).catch((error) => {
8658
+ handleComponentListResponse(parsed, (com) => this.storeComponents(com), this.collections).catch((error) => {
7487
8659
  logger.error("Failed to handle component list request:", error);
7488
8660
  });
7489
8661
  break;
@@ -7493,15 +8665,20 @@ var SuperatomSDK = class {
7493
8665
  });
7494
8666
  break;
7495
8667
  case "DASHBOARDS":
7496
- handleDashboardsRequest(parsed, (msg) => this.send(msg)).catch((error) => {
8668
+ handleDashboardsRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7497
8669
  logger.error("Failed to handle dashboards request:", error);
7498
8670
  });
7499
8671
  break;
7500
8672
  case "REPORTS":
7501
- handleReportsRequest(parsed, (msg) => this.send(msg)).catch((error) => {
8673
+ handleReportsRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7502
8674
  logger.error("Failed to handle reports request:", error);
7503
8675
  });
7504
8676
  break;
8677
+ case "UIS":
8678
+ handleUIsRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
8679
+ logger.error("Failed to handle UIs request:", error);
8680
+ });
8681
+ break;
7505
8682
  case "BOOKMARKS":
7506
8683
  handleBookmarksRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
7507
8684
  logger.error("Failed to handle bookmarks request:", error);