@superatomai/sdk-node 0.0.24 → 0.0.26

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
@@ -341,6 +341,7 @@ var UserSchema = z3.object({
341
341
  password: z3.string().min(1, "Password is required"),
342
342
  fullname: z3.string().optional(),
343
343
  role: z3.string().optional(),
344
+ userInfo: z3.record(z3.unknown()).optional(),
344
345
  wsIds: z3.array(z3.string()).optional()
345
346
  // Only in memory, not persisted to file
346
347
  });
@@ -470,6 +471,7 @@ var UsersRequestPayloadSchema = z3.object({
470
471
  password: z3.string().optional(),
471
472
  fullname: z3.string().optional(),
472
473
  role: z3.string().optional(),
474
+ userInfo: z3.record(z3.unknown()).optional(),
473
475
  // Query operation fields
474
476
  filters: UserQueryFiltersSchema.optional(),
475
477
  limit: z3.number().optional(),
@@ -515,7 +517,8 @@ var DashboardQueryFiltersSchema = z3.object({
515
517
  projectId: z3.string().optional(),
516
518
  createdBy: z3.number().optional(),
517
519
  updatedBy: z3.number().optional(),
518
- name: z3.string().optional()
520
+ name: z3.string().optional(),
521
+ published: z3.boolean().optional()
519
522
  });
520
523
  var DashboardsRequestPayloadSchema = z3.object({
521
524
  operation: z3.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
@@ -525,6 +528,7 @@ var DashboardsRequestPayloadSchema = z3.object({
525
528
  projectId: z3.string().optional(),
526
529
  name: z3.string().optional(),
527
530
  description: z3.string().optional(),
531
+ published: z3.boolean().optional(),
528
532
  createdBy: z3.number().optional(),
529
533
  updatedBy: z3.number().optional(),
530
534
  dashboard: DSLRendererPropsSchema.optional(),
@@ -545,7 +549,8 @@ var ReportQueryFiltersSchema = z3.object({
545
549
  projectId: z3.string().optional(),
546
550
  createdBy: z3.number().optional(),
547
551
  updatedBy: z3.number().optional(),
548
- name: z3.string().optional()
552
+ name: z3.string().optional(),
553
+ published: z3.boolean().optional()
549
554
  });
550
555
  var ReportsRequestPayloadSchema = z3.object({
551
556
  operation: z3.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
@@ -555,6 +560,7 @@ var ReportsRequestPayloadSchema = z3.object({
555
560
  projectId: z3.string().optional(),
556
561
  name: z3.string().optional(),
557
562
  description: z3.string().optional(),
563
+ published: z3.boolean().optional(),
558
564
  createdBy: z3.number().optional(),
559
565
  updatedBy: z3.number().optional(),
560
566
  report: DSLRendererPropsSchema2.optional(),
@@ -3779,6 +3785,166 @@ var KB = {
3779
3785
  };
3780
3786
  var knowledge_base_default = KB;
3781
3787
 
3788
+ // src/utils/bm25l-reranker.ts
3789
+ var BM25L = class {
3790
+ /**
3791
+ * @param documents - Array of raw documents (strings)
3792
+ * @param opts - Optional BM25L parameters
3793
+ */
3794
+ constructor(documents = [], opts = {}) {
3795
+ if (!Array.isArray(documents)) {
3796
+ throw new Error("BM25L: documents must be an array of strings.");
3797
+ }
3798
+ this.k1 = typeof opts.k1 === "number" ? opts.k1 : 1.5;
3799
+ this.b = typeof opts.b === "number" ? opts.b : 0.75;
3800
+ this.delta = typeof opts.delta === "number" ? opts.delta : 0.5;
3801
+ this.documents = documents.map((d) => typeof d === "string" ? this.tokenize(d) : []);
3802
+ this.docLengths = this.documents.map((doc) => doc.length);
3803
+ this.avgDocLength = this.docLengths.reduce((a, b) => a + b, 0) / (this.docLengths.length || 1);
3804
+ this.termDocFreq = {};
3805
+ this.documents.forEach((doc) => {
3806
+ const seen = /* @__PURE__ */ new Set();
3807
+ doc.forEach((term) => {
3808
+ if (!seen.has(term)) {
3809
+ seen.add(term);
3810
+ this.termDocFreq[term] = (this.termDocFreq[term] || 0) + 1;
3811
+ }
3812
+ });
3813
+ });
3814
+ }
3815
+ /**
3816
+ * Tokenize text into lowercase alphanumeric tokens
3817
+ */
3818
+ tokenize(text) {
3819
+ if (typeof text !== "string") return [];
3820
+ return text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter(Boolean);
3821
+ }
3822
+ /**
3823
+ * Compute IDF (Inverse Document Frequency) with smoothing
3824
+ */
3825
+ idf(term) {
3826
+ const df = this.termDocFreq[term] || 0;
3827
+ const N = this.documents.length || 1;
3828
+ return Math.log(1 + (N - df + 0.5) / (df + 0.5));
3829
+ }
3830
+ /**
3831
+ * Compute BM25L score for a single document
3832
+ */
3833
+ score(query, docIndex) {
3834
+ if (typeof query !== "string") return 0;
3835
+ if (docIndex < 0 || docIndex >= this.documents.length) return 0;
3836
+ const tokens = this.tokenize(query);
3837
+ if (tokens.length === 0) return 0;
3838
+ const doc = this.documents[docIndex];
3839
+ const docLength = this.docLengths[docIndex] || 1;
3840
+ const freq = {};
3841
+ for (const t of doc) {
3842
+ freq[t] = (freq[t] || 0) + 1;
3843
+ }
3844
+ let sum = 0;
3845
+ for (const term of tokens) {
3846
+ const tf = freq[term] || 0;
3847
+ if (tf === 0) continue;
3848
+ const idfVal = this.idf(term);
3849
+ let tfL = tf - this.b * (docLength / this.avgDocLength) + this.delta;
3850
+ if (tfL < 0) tfL = 0;
3851
+ sum += idfVal * (tfL / (this.k1 + tfL));
3852
+ }
3853
+ return sum;
3854
+ }
3855
+ /**
3856
+ * Search and rank all documents
3857
+ */
3858
+ search(query) {
3859
+ return this.documents.map((_, i) => ({
3860
+ index: i,
3861
+ score: this.score(query, i)
3862
+ })).sort((a, b) => b.score - a.score);
3863
+ }
3864
+ };
3865
+ function normalizeScores(scores) {
3866
+ if (scores.length === 0) return [];
3867
+ const min = Math.min(...scores);
3868
+ const max = Math.max(...scores);
3869
+ if (max === min) {
3870
+ return scores.map(() => max === 0 ? 0 : 1);
3871
+ }
3872
+ return scores.map((score) => (score - min) / (max - min));
3873
+ }
3874
+ function hybridRerank(query, items, getDocument, getSemanticScore, options = {}) {
3875
+ const {
3876
+ semanticWeight = 0.7,
3877
+ bm25Weight = 0.3,
3878
+ minScore = 0,
3879
+ k1 = 1.5,
3880
+ b = 0.75,
3881
+ delta = 0.5
3882
+ } = options;
3883
+ if (items.length === 0) return [];
3884
+ const documents = items.map(getDocument);
3885
+ const semanticScores = items.map(getSemanticScore);
3886
+ const bm25 = new BM25L(documents, { k1, b, delta });
3887
+ const bm25Scores = items.map((_, i) => bm25.score(query, i));
3888
+ const normalizedSemantic = normalizeScores(semanticScores);
3889
+ const normalizedBM25 = normalizeScores(bm25Scores);
3890
+ const results = items.map((item, i) => {
3891
+ const hybridScore = semanticWeight * normalizedSemantic[i] + bm25Weight * normalizedBM25[i];
3892
+ return {
3893
+ item,
3894
+ originalIndex: i,
3895
+ semanticScore: semanticScores[i],
3896
+ bm25Score: bm25Scores[i],
3897
+ hybridScore
3898
+ };
3899
+ });
3900
+ return results.filter((r) => r.hybridScore >= minScore).sort((a, b2) => b2.hybridScore - a.hybridScore);
3901
+ }
3902
+ function rerankChromaResults(query, chromaResults, options = {}) {
3903
+ const ids = chromaResults.ids[0] || [];
3904
+ const documents = chromaResults.documents[0] || [];
3905
+ const metadatas = chromaResults.metadatas[0] || [];
3906
+ const distances = chromaResults.distances[0] || [];
3907
+ if (ids.length === 0) return [];
3908
+ const items = ids.map((id, i) => ({
3909
+ id,
3910
+ document: documents[i],
3911
+ metadata: metadatas[i],
3912
+ distance: distances[i]
3913
+ }));
3914
+ const reranked = hybridRerank(
3915
+ query,
3916
+ items,
3917
+ (item) => item.document || "",
3918
+ // Convert L2 distance to similarity score
3919
+ (item) => 1 / (1 + item.distance),
3920
+ options
3921
+ );
3922
+ return reranked.map((r) => ({
3923
+ id: r.item.id,
3924
+ document: r.item.document,
3925
+ metadata: r.item.metadata,
3926
+ distance: r.item.distance,
3927
+ semanticScore: r.semanticScore,
3928
+ bm25Score: r.bm25Score,
3929
+ hybridScore: r.hybridScore
3930
+ }));
3931
+ }
3932
+ function rerankConversationResults(query, results, options = {}) {
3933
+ if (results.length === 0) return [];
3934
+ const reranked = hybridRerank(
3935
+ query,
3936
+ results,
3937
+ (item) => item.userPrompt || "",
3938
+ (item) => item.similarity || 0,
3939
+ options
3940
+ );
3941
+ return reranked.map((r) => ({
3942
+ ...r.item,
3943
+ hybridScore: r.hybridScore,
3944
+ bm25Score: r.bm25Score
3945
+ }));
3946
+ }
3947
+
3782
3948
  // src/userResponse/conversation-search.ts
3783
3949
  var searchConversations = async ({
3784
3950
  userPrompt,
@@ -3825,8 +3991,93 @@ var searchConversations = async ({
3825
3991
  return null;
3826
3992
  }
3827
3993
  };
3994
+ var searchConversationsWithReranking = async (options) => {
3995
+ const {
3996
+ userPrompt,
3997
+ collections,
3998
+ userId,
3999
+ similarityThreshold = 0.6,
4000
+ rerankCandidates = 50,
4001
+ // Fetch more candidates for better reranking
4002
+ hybridOptions = {
4003
+ semanticWeight: 0.7,
4004
+ bm25Weight: 0.3
4005
+ }
4006
+ } = options;
4007
+ try {
4008
+ if (!collections || !collections["conversation-history"]) {
4009
+ logger.info("[ConversationSearch] conversation-history collection not registered, skipping");
4010
+ return null;
4011
+ }
4012
+ if (!collections["conversation-history"]["searchMultiple"]) {
4013
+ logger.info("[ConversationSearch] searchMultiple not available, falling back to standard search");
4014
+ return searchConversations({
4015
+ userPrompt,
4016
+ collections,
4017
+ userId,
4018
+ similarityThreshold
4019
+ });
4020
+ }
4021
+ logger.info(`[ConversationSearch] Hybrid search for: "${userPrompt.substring(0, 50)}..."`);
4022
+ logger.info(`[ConversationSearch] Fetching ${rerankCandidates} candidates for reranking`);
4023
+ logger.info(`[ConversationSearch] Weights - Semantic: ${hybridOptions.semanticWeight}, BM25: ${hybridOptions.bm25Weight}`);
4024
+ const results = await collections["conversation-history"]["searchMultiple"]({
4025
+ userPrompt,
4026
+ userId,
4027
+ limit: rerankCandidates,
4028
+ threshold: 0
4029
+ // No threshold - get all candidates for reranking
4030
+ });
4031
+ if (!results || results.length === 0) {
4032
+ logger.info("[ConversationSearch] No conversations found in database");
4033
+ return null;
4034
+ }
4035
+ logger.info(`[ConversationSearch] Retrieved ${results.length} candidates for reranking`);
4036
+ const candidatesForReranking = results.map((r) => ({
4037
+ ...r,
4038
+ userPrompt: r.metadata?.userPrompt || ""
4039
+ }));
4040
+ const reranked = rerankConversationResults(userPrompt, candidatesForReranking, hybridOptions);
4041
+ if (reranked.length === 0) {
4042
+ logger.info("[ConversationSearch] No results after reranking");
4043
+ return null;
4044
+ }
4045
+ const best = reranked[0];
4046
+ const hybridScore = best.hybridScore;
4047
+ const semanticScore = best.similarity || 0;
4048
+ const matchedUserPrompt = best.userPrompt || best.metadata?.userPrompt || "";
4049
+ logger.info(`[ConversationSearch] Best match after reranking:`);
4050
+ logger.info(` - Hybrid score: ${(hybridScore * 100).toFixed(2)}%`);
4051
+ logger.info(` - Semantic score: ${(semanticScore * 100).toFixed(2)}%`);
4052
+ logger.info(` - BM25L score: ${best.bm25Score.toFixed(4)}`);
4053
+ logger.info(` - Matched prompt: "${matchedUserPrompt}"`);
4054
+ logger.info(` - Query prompt: "${userPrompt}"`);
4055
+ if (semanticScore < similarityThreshold) {
4056
+ logger.info(
4057
+ `[ConversationSearch] Semantic score ${(semanticScore * 100).toFixed(2)}% below threshold ${(similarityThreshold * 100).toFixed(2)}% - rejecting match`
4058
+ );
4059
+ return null;
4060
+ }
4061
+ logger.info(
4062
+ `[ConversationSearch] \u2713 Found match with semantic score ${(semanticScore * 100).toFixed(2)}%`
4063
+ );
4064
+ logger.info(` - Returning cached result for: "${matchedUserPrompt}"`);
4065
+ return {
4066
+ uiBlock: best.uiBlock,
4067
+ similarity: semanticScore,
4068
+ hybridScore,
4069
+ bm25Score: best.bm25Score,
4070
+ metadata: best.metadata
4071
+ };
4072
+ } catch (error) {
4073
+ const errorMsg = error instanceof Error ? error.message : String(error);
4074
+ logger.warn(`[ConversationSearch] Error in hybrid search: ${errorMsg}`);
4075
+ return null;
4076
+ }
4077
+ };
3828
4078
  var ConversationSearch = {
3829
- searchConversations
4079
+ searchConversations,
4080
+ searchConversationsWithReranking
3830
4081
  };
3831
4082
  var conversation_search_default = ConversationSearch;
3832
4083
 
@@ -3875,7 +4126,7 @@ var BaseLLM = class {
3875
4126
  * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
3876
4127
  * @returns Object containing matched components, layout title/description, and follow-up actions
3877
4128
  */
3878
- async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback) {
4129
+ async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
3879
4130
  try {
3880
4131
  logger.debug(`[${this.getProviderName()}] Starting component matching from text response`);
3881
4132
  let availableComponentsText = "No components available";
@@ -3891,12 +4142,44 @@ var BaseLLM = class {
3891
4142
  Props Structure: ${propsPreview}`;
3892
4143
  }).join("\n\n");
3893
4144
  }
4145
+ let deferredToolsText = "No deferred external tools for this request.";
4146
+ if (deferredTools && deferredTools.length > 0) {
4147
+ logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools to component matching`);
4148
+ deferredToolsText = "The following external tools need user input via a Form component.\n**IMPORTANT: Use these EXACT values when generating Form externalTool prop.**\n\n" + deferredTools.map((tool, idx) => {
4149
+ return `${idx + 1}. **${tool.name}**
4150
+ toolId: "${tool.id}" (USE THIS EXACT VALUE - do not modify!)
4151
+ toolName: "${tool.name}"
4152
+ parameters: ${JSON.stringify(tool.params || {})}
4153
+ requiredFields:
4154
+ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
4155
+ }).join("\n\n");
4156
+ }
4157
+ let executedToolsText = "No external tools were executed for data fetching.";
4158
+ if (executedTools && executedTools.length > 0) {
4159
+ logger.info(`[${this.getProviderName()}] Passing ${executedTools.length} executed tools to component matching`);
4160
+ executedToolsText = "The following external tools were executed to fetch data.\n**IMPORTANT: For components displaying this data, use externalTool prop instead of query.**\n**IMPORTANT: Use the result data to populate deferred tool parameters when applicable.**\n\n" + executedTools.map((tool, idx) => {
4161
+ let resultPreview = "No result data";
4162
+ if (tool.result) {
4163
+ const resultStr = typeof tool.result === "string" ? tool.result : JSON.stringify(tool.result, null, 2);
4164
+ resultPreview = resultStr.length > 2e3 ? resultStr.substring(0, 2e3) + "\n... (truncated)" : resultStr;
4165
+ }
4166
+ return `${idx + 1}. **${tool.name}**
4167
+ toolId: "${tool.id}" (USE THIS EXACT VALUE for externalTool.toolId)
4168
+ toolName: "${tool.name}" (USE THIS EXACT VALUE for externalTool.toolName)
4169
+ parameters: ${JSON.stringify(tool.params || {})} (USE THESE for externalTool.parameters)
4170
+ result: ${resultPreview}`;
4171
+ }).join("\n\n");
4172
+ }
3894
4173
  const schemaDoc = schema.generateSchemaDocumentation();
3895
4174
  logger.file("\n=============================\nText analysis response:", analysisContent);
4175
+ logger.file("\n=============================\nDeferred tools:", deferredToolsText);
4176
+ logger.file("\n=============================\nExecuted tools:", executedToolsText);
3896
4177
  const prompts = await promptLoader.loadPrompts("match-text-components", {
3897
4178
  ANALYSIS_CONTENT: analysisContent,
3898
4179
  AVAILABLE_COMPONENTS: availableComponentsText,
3899
- SCHEMA_DOC: schemaDoc
4180
+ SCHEMA_DOC: schemaDoc,
4181
+ DEFERRED_TOOLS: deferredToolsText,
4182
+ EXECUTED_TOOLS: executedToolsText
3900
4183
  });
3901
4184
  logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
3902
4185
  logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
@@ -4016,9 +4299,6 @@ var BaseLLM = class {
4016
4299
  matchedComponents.forEach((comp, idx) => {
4017
4300
  logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
4018
4301
  });
4019
- if (suggestedComponents.length !== matchedComponents.length) {
4020
- logger.warn(`[${this.getProviderName()}] \u26A0\uFE0F MISMATCH: Text suggested ${suggestedComponents.length} components, but LLM matched ${matchedComponents.length}`);
4021
- }
4022
4302
  logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
4023
4303
  const rawActions = result.actions || [];
4024
4304
  const actions = convertQuestionsToActions(rawActions);
@@ -4093,6 +4373,7 @@ var BaseLLM = class {
4093
4373
  */
4094
4374
  async classifyQuestionCategory(userPrompt, apiKey, logCollector, conversationHistory, externalTools) {
4095
4375
  try {
4376
+ const schemaDoc = schema.generateSchemaDocumentation();
4096
4377
  const availableToolsDoc = externalTools && externalTools.length > 0 ? externalTools.map((tool) => {
4097
4378
  const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
4098
4379
  return `- **${tool.name}** (id: ${tool.id})
@@ -4102,7 +4383,8 @@ var BaseLLM = class {
4102
4383
  const prompts = await promptLoader.loadPrompts("category-classification", {
4103
4384
  USER_PROMPT: userPrompt,
4104
4385
  CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
4105
- AVAILABLE_TOOLS: availableToolsDoc
4386
+ AVAILABLE_TOOLS: availableToolsDoc,
4387
+ SCHEMA_DOC: schemaDoc || "No database schema available"
4106
4388
  });
4107
4389
  const result = await LLM.stream(
4108
4390
  {
@@ -4240,21 +4522,44 @@ var BaseLLM = class {
4240
4522
  let availableToolsDoc = "No external tools are available for this request.";
4241
4523
  if (externalTools && externalTools.length > 0) {
4242
4524
  logger.info(`[${this.getProviderName()}] External tools available: ${externalTools.map((t) => t.name).join(", ")}`);
4243
- availableToolsDoc = "\u26A0\uFE0F **EXECUTE THESE TOOLS IMMEDIATELY** \u26A0\uFE0F\n\nThe following external tools have been identified as necessary for this request. You MUST call them:\n\n" + externalTools.map((tool, idx) => {
4244
- const paramsText = Object.entries(tool.params || {}).map(([key, value]) => {
4245
- const valueType = typeof value;
4246
- if (valueType === "string" && ["string", "number", "integer", "boolean", "array", "object"].includes(String(value).toLowerCase())) {
4247
- return `- ${key}: ${value}`;
4248
- } else {
4249
- return `- ${key}: ${JSON.stringify(value)} (default value - use this)`;
4525
+ const immediateTools = externalTools.filter((t) => t.executionType === "immediate" || t.executionType === "deferred" && t.userProvidedData);
4526
+ const deferredTools = externalTools.filter((t) => t.executionType === "deferred" && !t.userProvidedData);
4527
+ let toolsDocParts = [];
4528
+ if (immediateTools.length > 0) {
4529
+ const immediateDoc = "## IMMEDIATE EXECUTION TOOLS\nExecute these tools right away:\n\n" + immediateTools.map((tool, idx) => {
4530
+ const paramsText = Object.entries(tool.params || {}).map(([key, value]) => {
4531
+ const valueType = typeof value;
4532
+ if (valueType === "string" && ["string", "number", "integer", "boolean", "array", "object"].includes(String(value).toLowerCase())) {
4533
+ return `- ${key}: ${value}`;
4534
+ } else {
4535
+ return `- ${key}: ${JSON.stringify(value)} (default value - use this)`;
4536
+ }
4537
+ }).join("\n ");
4538
+ let userDataText = "";
4539
+ if (tool.userProvidedData) {
4540
+ userDataText = "\n **User Provided Data** (use these values):\n " + Object.entries(tool.userProvidedData).map(([key, value]) => `- ${key}: ${JSON.stringify(value)}`).join("\n ");
4250
4541
  }
4251
- }).join("\n ");
4252
- return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
4542
+ return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
4543
+ Execution Type: IMMEDIATE
4253
4544
  Description: ${tool.description}
4254
- **ACTION REQUIRED**: Call this tool with the parameters below
4255
4545
  Parameters:
4256
- ${paramsText}`;
4257
- }).join("\n\n");
4546
+ ${paramsText}${userDataText}`;
4547
+ }).join("\n\n");
4548
+ toolsDocParts.push(immediateDoc);
4549
+ }
4550
+ if (deferredTools.length > 0) {
4551
+ const deferredDoc = "## DEFERRED TOOLS (DO NOT EXECUTE)\nThese tools need user input. A Form component will be generated to collect the data.\n**DO NOT call these tools.** Instead, acknowledge the request and inform user that a form will be shown.\n\n" + deferredTools.map((tool, idx) => {
4552
+ const requiredFieldsText = (tool.requiredFields || []).map((f) => `- ${f.label || f.name} (${f.type})${f.required ? " *required*" : ""}`).join("\n ");
4553
+ return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
4554
+ Execution Type: DEFERRED (needs form input)
4555
+ Description: ${tool.description}
4556
+ Reason: ${tool.executionReason || "Write operation requires user confirmation"}
4557
+ Required Fields:
4558
+ ${requiredFieldsText || "(fields will be determined by form)"}`;
4559
+ }).join("\n\n");
4560
+ toolsDocParts.push(deferredDoc);
4561
+ }
4562
+ availableToolsDoc = toolsDocParts.join("\n\n---\n\n");
4258
4563
  }
4259
4564
  const schemaDoc = schema.generateSchemaDocumentation();
4260
4565
  const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
@@ -4295,8 +4600,12 @@ var BaseLLM = class {
4295
4600
  }
4296
4601
  }];
4297
4602
  if (externalTools && externalTools.length > 0) {
4298
- externalTools.forEach((tool) => {
4299
- logger.info(`[${this.getProviderName()}] Processing external tool:`, JSON.stringify(tool, null, 2));
4603
+ const executableTools = externalTools.filter(
4604
+ (t) => t.executionType === "immediate" || t.executionType === "deferred" && t.userProvidedData
4605
+ );
4606
+ logger.info(`[${this.getProviderName()}] Executable tools: ${executableTools.length} of ${externalTools.length} total`);
4607
+ executableTools.forEach((tool) => {
4608
+ logger.info(`[${this.getProviderName()}] Processing executable tool:`, JSON.stringify(tool, null, 2));
4300
4609
  const properties = {};
4301
4610
  const required = [];
4302
4611
  Object.entries(tool.params || {}).forEach(([key, typeOrValue]) => {
@@ -4365,13 +4674,14 @@ var BaseLLM = class {
4365
4674
  input_schema: inputSchema
4366
4675
  });
4367
4676
  });
4368
- logger.info(`[${this.getProviderName()}] Added ${externalTools.length} external tools to tool calling capability`);
4677
+ logger.info(`[${this.getProviderName()}] Added ${executableTools.length} executable tools to tool calling capability (${externalTools.length - executableTools.length} deferred tools await form input)`);
4369
4678
  logger.info(`[${this.getProviderName()}] Complete tools array:`, JSON.stringify(tools, null, 2));
4370
4679
  }
4371
4680
  const queryAttempts = /* @__PURE__ */ new Map();
4372
4681
  const MAX_QUERY_ATTEMPTS = 6;
4373
4682
  const toolAttempts = /* @__PURE__ */ new Map();
4374
4683
  const MAX_TOOL_ATTEMPTS = 3;
4684
+ const executedToolsList = [];
4375
4685
  let maxAttemptsReached = false;
4376
4686
  let fullStreamedText = "";
4377
4687
  const wrappedStreamCallback = streamCallback ? (chunk) => {
@@ -4554,6 +4864,17 @@ Please try rephrasing your request or contact support.
4554
4864
  const result2 = await externalTool.fn(toolInput);
4555
4865
  logger.info(`[${this.getProviderName()}] External tool ${externalTool.name} executed successfully`);
4556
4866
  logCollector?.info(`\u2713 ${externalTool.name} executed successfully`);
4867
+ if (!executedToolsList.find((t) => t.id === externalTool.id)) {
4868
+ executedToolsList.push({
4869
+ id: externalTool.id,
4870
+ name: externalTool.name,
4871
+ params: toolInput,
4872
+ // The actual parameters used in this execution
4873
+ result: result2
4874
+ // Store the actual result data for populating deferred tool params
4875
+ });
4876
+ logger.info(`[${this.getProviderName()}] Tracked executed tool: ${externalTool.name} with params: ${JSON.stringify(toolInput)}`);
4877
+ }
4557
4878
  if (wrappedStreamCallback) {
4558
4879
  wrappedStreamCallback(`\u2705 **${externalTool.name} completed successfully**
4559
4880
 
@@ -4643,12 +4964,31 @@ ${errorMsg}
4643
4964
  wrappedStreamCallback(answerMarker);
4644
4965
  logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
4645
4966
  } : void 0;
4967
+ const deferredTools = externalTools?.filter((t) => {
4968
+ if (t.executionType === "deferred" && !t.userProvidedData) return true;
4969
+ if (category === "data_modification" && !t.userProvidedData) {
4970
+ const name = (t.name || t.id || "").toLowerCase();
4971
+ const isWriteOperation = /create|add|insert|new|update|edit|modify|delete|remove|send/.test(name);
4972
+ if (isWriteOperation) {
4973
+ logger.info(`[${this.getProviderName()}] Inferred deferred execution for tool: ${t.name}`);
4974
+ return true;
4975
+ }
4976
+ }
4977
+ return false;
4978
+ }) || [];
4979
+ if (deferredTools.length > 0) {
4980
+ logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools for Form generation`);
4981
+ }
4982
+ logger.info(`[${this.getProviderName()}] passing deferred tools to the matching function: ${JSON.stringify(deferredTools, null, 2)}`);
4983
+ logger.info(`[${this.getProviderName()}] passing executed tools to the matching function: ${JSON.stringify(executedToolsList, null, 2)}`);
4646
4984
  const matchResult = await this.matchComponentsFromAnalysis(
4647
4985
  textResponse,
4648
4986
  components,
4649
4987
  apiKey,
4650
4988
  logCollector,
4651
- componentStreamCallback
4989
+ componentStreamCallback,
4990
+ deferredTools,
4991
+ executedToolsList
4652
4992
  );
4653
4993
  matchedComponents = matchResult.components;
4654
4994
  layoutTitle = matchResult.layoutTitle;
@@ -4717,23 +5057,20 @@ ${errorMsg}
4717
5057
  */
4718
5058
  async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "text", streamCallback, collections, externalTools, userId) {
4719
5059
  const startTime = Date.now();
4720
- logger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);
5060
+ logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
4721
5061
  logCollector?.info(`Starting request processing with mode: ${responseMode}`);
4722
5062
  try {
4723
5063
  logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
4724
5064
  logCollector?.info("Step 1: Searching for similar previous conversations...");
4725
- const conversationMatch = await conversation_search_default.searchConversations({
5065
+ const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
4726
5066
  userPrompt,
4727
5067
  collections,
4728
5068
  userId,
4729
5069
  similarityThreshold: 0.6
4730
5070
  // 60% threshold
4731
5071
  });
4732
- logger.info("conversationMatch:", conversationMatch);
4733
5072
  if (conversationMatch) {
4734
- logger.info(
4735
- `[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`
4736
- );
5073
+ logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
4737
5074
  logCollector?.info(
4738
5075
  `\u2713 Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`
4739
5076
  );
@@ -4741,7 +5078,6 @@ ${errorMsg}
4741
5078
  const isValidComponent = rawComponent && typeof rawComponent === "object" && Object.keys(rawComponent).length > 0;
4742
5079
  const component = isValidComponent ? rawComponent : null;
4743
5080
  const cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || "";
4744
- logger.debug(`[${this.getProviderName()}] Cached component: ${component ? "present" : "null"}, cachedTextResponse: ${cachedTextResponse ? cachedTextResponse.substring(0, 50) + "..." : "empty"}`);
4745
5081
  if (this.containsFormComponent(component)) {
4746
5082
  logger.info(`[${this.getProviderName()}] Skipping cached result - Form components contain stale defaultValues, fetching fresh data`);
4747
5083
  logCollector?.info("Skipping cache for form - fetching current values from database...");
@@ -4839,22 +5175,31 @@ ${errorMsg}
4839
5175
  if (categoryClassification.externalTools && categoryClassification.externalTools.length > 0) {
4840
5176
  logger.info(`[${this.getProviderName()}] Identified ${categoryClassification.externalTools.length} external tools needed`);
4841
5177
  logCollector?.info(`Identified external tools: ${categoryClassification.externalTools.map((t) => t.name || t.type).join(", ")}`);
4842
- toolsToUse = categoryClassification.externalTools?.map((t) => ({
4843
- id: t.type,
4844
- name: t.name,
4845
- description: t.description,
4846
- params: t.parameters || {},
4847
- fn: (() => {
4848
- const realTool = externalTools?.find((tool) => tool.id === t.type);
4849
- if (realTool) {
4850
- logger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);
4851
- return realTool.fn;
4852
- } else {
4853
- logger.warn(`[${this.getProviderName()}] Tool ${t.type} not found in registered tools`);
4854
- return async () => ({ success: false, message: `Tool ${t.name || t.type} not registered` });
4855
- }
4856
- })()
4857
- })) || [];
5178
+ logger.info(`[${this.getProviderName()}] Raw external tools from classification: ${JSON.stringify(categoryClassification.externalTools, null, 2)}`);
5179
+ toolsToUse = categoryClassification.externalTools?.map((t) => {
5180
+ const realTool = externalTools?.find((tool) => tool.id === t.type);
5181
+ logger.info(`[${this.getProviderName()}] Tool ${t.name}: executionType=${t.executionType}, userProvidedData=${t.userProvidedData ? "present" : "null"}`);
5182
+ return {
5183
+ id: t.type,
5184
+ name: t.name,
5185
+ description: t.description,
5186
+ params: t.parameters || {},
5187
+ // NEW: Include execution type info from category classification
5188
+ executionType: t.executionType || "immediate",
5189
+ executionReason: t.executionReason || "",
5190
+ requiredFields: t.requiredFields || [],
5191
+ userProvidedData: t.userProvidedData || null,
5192
+ fn: (() => {
5193
+ if (realTool) {
5194
+ logger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);
5195
+ return realTool.fn;
5196
+ } else {
5197
+ logger.warn(`[${this.getProviderName()}] Tool ${t.type} not found in registered tools`);
5198
+ return async () => ({ success: false, message: `Tool ${t.name || t.type} not registered` });
5199
+ }
5200
+ })()
5201
+ };
5202
+ }) || [];
4858
5203
  }
4859
5204
  if (categoryClassification.category === "general") {
4860
5205
  logger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);
@@ -5545,7 +5890,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
5545
5890
  }
5546
5891
  logCollector.info(`Starting user prompt request with ${components.length} components`);
5547
5892
  const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId);
5548
- logger.info("conversationHistory", conversationHistory);
5549
5893
  const responseMode = payload.responseMode || "component";
5550
5894
  logger.info("responseMode", responseMode);
5551
5895
  let streamCallback;
@@ -6155,6 +6499,7 @@ async function handleUsersRequest(data, collections, sendMessage) {
6155
6499
  const password = requestData?.password;
6156
6500
  const fullname = requestData?.fullname;
6157
6501
  const role = requestData?.role;
6502
+ const userInfo = requestData?.userInfo;
6158
6503
  const filters = requestData?.filters;
6159
6504
  const limit = requestData?.limit;
6160
6505
  const sort = requestData?.sort;
@@ -6169,10 +6514,10 @@ async function handleUsersRequest(data, collections, sendMessage) {
6169
6514
  const userManager = getUserManager();
6170
6515
  switch (operation) {
6171
6516
  case "create":
6172
- await handleCreate(id, { username, email, password, fullname, role }, executeCollection, userManager, sendMessage, from.id);
6517
+ await handleCreate(id, { username, email, password, fullname, role, userInfo }, executeCollection, userManager, sendMessage, from.id);
6173
6518
  break;
6174
6519
  case "update":
6175
- await handleUpdate(id, numericId, { username, email, password, fullname, role }, executeCollection, userManager, sendMessage, from.id);
6520
+ await handleUpdate(id, numericId, { username, email, password, fullname, role, userInfo }, executeCollection, userManager, sendMessage, from.id);
6176
6521
  break;
6177
6522
  case "delete":
6178
6523
  await handleDelete(id, numericId, username, executeCollection, userManager, sendMessage, from.id);
@@ -6201,7 +6546,7 @@ async function handleUsersRequest(data, collections, sendMessage) {
6201
6546
  }
6202
6547
  }
6203
6548
  async function handleCreate(id, userData, executeCollection, userManager, sendMessage, clientId) {
6204
- const { username, email, password, fullname, role } = userData;
6549
+ const { username, email, password, fullname, role, userInfo } = userData;
6205
6550
  if (!username || username.trim().length === 0) {
6206
6551
  sendResponse3(id, {
6207
6552
  success: false,
@@ -6232,7 +6577,8 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
6232
6577
  email: email || void 0,
6233
6578
  password,
6234
6579
  fullname: fullname || void 0,
6235
- role: role || void 0
6580
+ role: role || void 0,
6581
+ userInfo: userInfo || void 0
6236
6582
  });
6237
6583
  if (result && result.success) {
6238
6584
  logger.info(`[DB] User created successfully: ${username}`);
@@ -6300,7 +6646,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
6300
6646
  }
6301
6647
  }
6302
6648
  async function handleUpdate(id, numericId, userData, executeCollection, userManager, sendMessage, clientId) {
6303
- const { username, email, password, fullname, role } = userData;
6649
+ const { username, email, password, fullname, role, userInfo } = userData;
6304
6650
  if (!numericId && !username) {
6305
6651
  sendResponse3(id, {
6306
6652
  success: false,
@@ -6316,7 +6662,8 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
6316
6662
  email,
6317
6663
  password,
6318
6664
  fullname,
6319
- role
6665
+ role,
6666
+ userInfo
6320
6667
  });
6321
6668
  if (result && result.success) {
6322
6669
  logger.info(`[DB] User updated successfully, ID: ${numericId}`);
@@ -6676,6 +7023,7 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
6676
7023
  const projectId = requestData?.projectId;
6677
7024
  const name = requestData?.name;
6678
7025
  const description = requestData?.description;
7026
+ const published = requestData?.published;
6679
7027
  const createdBy = requestData?.createdBy;
6680
7028
  const updatedBy = requestData?.updatedBy;
6681
7029
  const numericId = requestData?.id;
@@ -6693,10 +7041,10 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
6693
7041
  const dashboardManager2 = getDashboardManager();
6694
7042
  switch (operation) {
6695
7043
  case "create":
6696
- await handleCreate2(id, dashboardId, dashboard, projectId, name, description, createdBy, executeCollection, dashboardManager2, sendMessage, from.id);
7044
+ await handleCreate2(id, dashboardId, dashboard, projectId, name, description, published, createdBy, executeCollection, dashboardManager2, sendMessage, from.id);
6697
7045
  break;
6698
7046
  case "update":
6699
- await handleUpdate2(id, numericId, dashboardId, dashboard, name, description, updatedBy, executeCollection, dashboardManager2, sendMessage, from.id);
7047
+ await handleUpdate2(id, numericId, dashboardId, dashboard, name, description, published, updatedBy, executeCollection, dashboardManager2, sendMessage, from.id);
6700
7048
  break;
6701
7049
  case "delete":
6702
7050
  await handleDelete2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, from.id);
@@ -6724,7 +7072,7 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
6724
7072
  }, sendMessage);
6725
7073
  }
6726
7074
  }
6727
- async function handleCreate2(id, dashboardId, dashboard, projectId, name, description, createdBy, executeCollection, dashboardManager2, sendMessage, clientId) {
7075
+ async function handleCreate2(id, dashboardId, dashboard, projectId, name, description, published, createdBy, executeCollection, dashboardManager2, sendMessage, clientId) {
6728
7076
  if (!dashboardId || dashboardId.trim().length === 0) {
6729
7077
  sendResponse4(id, {
6730
7078
  success: false,
@@ -6746,6 +7094,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
6746
7094
  name: name || "",
6747
7095
  description,
6748
7096
  dashboard,
7097
+ published,
6749
7098
  createdBy
6750
7099
  });
6751
7100
  if (result && result.success) {
@@ -6785,7 +7134,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
6785
7134
  }, sendMessage, clientId);
6786
7135
  }
6787
7136
  }
6788
- async function handleUpdate2(id, numericId, dashboardId, dashboard, name, description, updatedBy, executeCollection, dashboardManager2, sendMessage, clientId) {
7137
+ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, description, published, updatedBy, executeCollection, dashboardManager2, sendMessage, clientId) {
6789
7138
  if (!numericId) {
6790
7139
  sendResponse4(id, {
6791
7140
  success: false,
@@ -6799,6 +7148,7 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
6799
7148
  name,
6800
7149
  description,
6801
7150
  dashboard,
7151
+ published,
6802
7152
  updatedBy
6803
7153
  });
6804
7154
  if (result && result.success) {
@@ -7041,6 +7391,7 @@ async function handleReportsRequest(data, collections, sendMessage) {
7041
7391
  const projectId = requestData?.projectId;
7042
7392
  const name = requestData?.name;
7043
7393
  const description = requestData?.description;
7394
+ const published = requestData?.published;
7044
7395
  const createdBy = requestData?.createdBy;
7045
7396
  const updatedBy = requestData?.updatedBy;
7046
7397
  const numericId = requestData?.id;
@@ -7058,10 +7409,10 @@ async function handleReportsRequest(data, collections, sendMessage) {
7058
7409
  const reportManager2 = getReportManager();
7059
7410
  switch (operation) {
7060
7411
  case "create":
7061
- await handleCreate3(id, reportId, report, projectId, name, description, createdBy, executeCollection, reportManager2, sendMessage, from.id);
7412
+ await handleCreate3(id, reportId, report, projectId, name, description, published, createdBy, executeCollection, reportManager2, sendMessage, from.id);
7062
7413
  break;
7063
7414
  case "update":
7064
- await handleUpdate3(id, numericId, reportId, report, name, description, updatedBy, executeCollection, reportManager2, sendMessage, from.id);
7415
+ await handleUpdate3(id, numericId, reportId, report, name, description, published, updatedBy, executeCollection, reportManager2, sendMessage, from.id);
7065
7416
  break;
7066
7417
  case "delete":
7067
7418
  await handleDelete3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, from.id);
@@ -7089,7 +7440,7 @@ async function handleReportsRequest(data, collections, sendMessage) {
7089
7440
  }, sendMessage);
7090
7441
  }
7091
7442
  }
7092
- async function handleCreate3(id, reportId, report, projectId, name, description, createdBy, executeCollection, reportManager2, sendMessage, clientId) {
7443
+ async function handleCreate3(id, reportId, report, projectId, name, description, published, createdBy, executeCollection, reportManager2, sendMessage, clientId) {
7093
7444
  if (!reportId || reportId.trim().length === 0) {
7094
7445
  sendResponse5(id, {
7095
7446
  success: false,
@@ -7111,6 +7462,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
7111
7462
  name: name || "",
7112
7463
  description,
7113
7464
  report,
7465
+ published,
7114
7466
  createdBy
7115
7467
  });
7116
7468
  if (result && result.success) {
@@ -7150,7 +7502,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
7150
7502
  }, sendMessage, clientId);
7151
7503
  }
7152
7504
  }
7153
- async function handleUpdate3(id, numericId, reportId, report, name, description, updatedBy, executeCollection, reportManager2, sendMessage, clientId) {
7505
+ async function handleUpdate3(id, numericId, reportId, report, name, description, published, updatedBy, executeCollection, reportManager2, sendMessage, clientId) {
7154
7506
  if (!numericId) {
7155
7507
  sendResponse5(id, {
7156
7508
  success: false,
@@ -7164,6 +7516,7 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
7164
7516
  name,
7165
7517
  description,
7166
7518
  report,
7519
+ published,
7167
7520
  updatedBy
7168
7521
  });
7169
7522
  if (result && result.success) {
@@ -9482,6 +9835,7 @@ var SuperatomSDK = class {
9482
9835
  }
9483
9836
  };
9484
9837
  export {
9838
+ BM25L,
9485
9839
  CONTEXT_CONFIG,
9486
9840
  CleanupService,
9487
9841
  LLM,
@@ -9493,6 +9847,9 @@ export {
9493
9847
  UIBlock,
9494
9848
  UILogCollector,
9495
9849
  UserManager,
9496
- logger
9850
+ hybridRerank,
9851
+ logger,
9852
+ rerankChromaResults,
9853
+ rerankConversationResults
9497
9854
  };
9498
9855
  //# sourceMappingURL=index.mjs.map