@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.js CHANGED
@@ -164,6 +164,7 @@ var init_utils = __esm({
164
164
  // src/index.ts
165
165
  var index_exports = {};
166
166
  __export(index_exports, {
167
+ BM25L: () => BM25L,
167
168
  CONTEXT_CONFIG: () => CONTEXT_CONFIG,
168
169
  CleanupService: () => CleanupService,
169
170
  LLM: () => LLM,
@@ -175,7 +176,10 @@ __export(index_exports, {
175
176
  UIBlock: () => UIBlock,
176
177
  UILogCollector: () => UILogCollector,
177
178
  UserManager: () => UserManager,
178
- logger: () => logger
179
+ hybridRerank: () => hybridRerank,
180
+ logger: () => logger,
181
+ rerankChromaResults: () => rerankChromaResults,
182
+ rerankConversationResults: () => rerankConversationResults
179
183
  });
180
184
  module.exports = __toCommonJS(index_exports);
181
185
 
@@ -381,6 +385,7 @@ var UserSchema = import_zod3.z.object({
381
385
  password: import_zod3.z.string().min(1, "Password is required"),
382
386
  fullname: import_zod3.z.string().optional(),
383
387
  role: import_zod3.z.string().optional(),
388
+ userInfo: import_zod3.z.record(import_zod3.z.unknown()).optional(),
384
389
  wsIds: import_zod3.z.array(import_zod3.z.string()).optional()
385
390
  // Only in memory, not persisted to file
386
391
  });
@@ -510,6 +515,7 @@ var UsersRequestPayloadSchema = import_zod3.z.object({
510
515
  password: import_zod3.z.string().optional(),
511
516
  fullname: import_zod3.z.string().optional(),
512
517
  role: import_zod3.z.string().optional(),
518
+ userInfo: import_zod3.z.record(import_zod3.z.unknown()).optional(),
513
519
  // Query operation fields
514
520
  filters: UserQueryFiltersSchema.optional(),
515
521
  limit: import_zod3.z.number().optional(),
@@ -555,7 +561,8 @@ var DashboardQueryFiltersSchema = import_zod3.z.object({
555
561
  projectId: import_zod3.z.string().optional(),
556
562
  createdBy: import_zod3.z.number().optional(),
557
563
  updatedBy: import_zod3.z.number().optional(),
558
- name: import_zod3.z.string().optional()
564
+ name: import_zod3.z.string().optional(),
565
+ published: import_zod3.z.boolean().optional()
559
566
  });
560
567
  var DashboardsRequestPayloadSchema = import_zod3.z.object({
561
568
  operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
@@ -565,6 +572,7 @@ var DashboardsRequestPayloadSchema = import_zod3.z.object({
565
572
  projectId: import_zod3.z.string().optional(),
566
573
  name: import_zod3.z.string().optional(),
567
574
  description: import_zod3.z.string().optional(),
575
+ published: import_zod3.z.boolean().optional(),
568
576
  createdBy: import_zod3.z.number().optional(),
569
577
  updatedBy: import_zod3.z.number().optional(),
570
578
  dashboard: DSLRendererPropsSchema.optional(),
@@ -585,7 +593,8 @@ var ReportQueryFiltersSchema = import_zod3.z.object({
585
593
  projectId: import_zod3.z.string().optional(),
586
594
  createdBy: import_zod3.z.number().optional(),
587
595
  updatedBy: import_zod3.z.number().optional(),
588
- name: import_zod3.z.string().optional()
596
+ name: import_zod3.z.string().optional(),
597
+ published: import_zod3.z.boolean().optional()
589
598
  });
590
599
  var ReportsRequestPayloadSchema = import_zod3.z.object({
591
600
  operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
@@ -595,6 +604,7 @@ var ReportsRequestPayloadSchema = import_zod3.z.object({
595
604
  projectId: import_zod3.z.string().optional(),
596
605
  name: import_zod3.z.string().optional(),
597
606
  description: import_zod3.z.string().optional(),
607
+ published: import_zod3.z.boolean().optional(),
598
608
  createdBy: import_zod3.z.number().optional(),
599
609
  updatedBy: import_zod3.z.number().optional(),
600
610
  report: DSLRendererPropsSchema2.optional(),
@@ -3819,6 +3829,166 @@ var KB = {
3819
3829
  };
3820
3830
  var knowledge_base_default = KB;
3821
3831
 
3832
+ // src/utils/bm25l-reranker.ts
3833
+ var BM25L = class {
3834
+ /**
3835
+ * @param documents - Array of raw documents (strings)
3836
+ * @param opts - Optional BM25L parameters
3837
+ */
3838
+ constructor(documents = [], opts = {}) {
3839
+ if (!Array.isArray(documents)) {
3840
+ throw new Error("BM25L: documents must be an array of strings.");
3841
+ }
3842
+ this.k1 = typeof opts.k1 === "number" ? opts.k1 : 1.5;
3843
+ this.b = typeof opts.b === "number" ? opts.b : 0.75;
3844
+ this.delta = typeof opts.delta === "number" ? opts.delta : 0.5;
3845
+ this.documents = documents.map((d) => typeof d === "string" ? this.tokenize(d) : []);
3846
+ this.docLengths = this.documents.map((doc) => doc.length);
3847
+ this.avgDocLength = this.docLengths.reduce((a, b) => a + b, 0) / (this.docLengths.length || 1);
3848
+ this.termDocFreq = {};
3849
+ this.documents.forEach((doc) => {
3850
+ const seen = /* @__PURE__ */ new Set();
3851
+ doc.forEach((term) => {
3852
+ if (!seen.has(term)) {
3853
+ seen.add(term);
3854
+ this.termDocFreq[term] = (this.termDocFreq[term] || 0) + 1;
3855
+ }
3856
+ });
3857
+ });
3858
+ }
3859
+ /**
3860
+ * Tokenize text into lowercase alphanumeric tokens
3861
+ */
3862
+ tokenize(text) {
3863
+ if (typeof text !== "string") return [];
3864
+ return text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter(Boolean);
3865
+ }
3866
+ /**
3867
+ * Compute IDF (Inverse Document Frequency) with smoothing
3868
+ */
3869
+ idf(term) {
3870
+ const df = this.termDocFreq[term] || 0;
3871
+ const N = this.documents.length || 1;
3872
+ return Math.log(1 + (N - df + 0.5) / (df + 0.5));
3873
+ }
3874
+ /**
3875
+ * Compute BM25L score for a single document
3876
+ */
3877
+ score(query, docIndex) {
3878
+ if (typeof query !== "string") return 0;
3879
+ if (docIndex < 0 || docIndex >= this.documents.length) return 0;
3880
+ const tokens = this.tokenize(query);
3881
+ if (tokens.length === 0) return 0;
3882
+ const doc = this.documents[docIndex];
3883
+ const docLength = this.docLengths[docIndex] || 1;
3884
+ const freq = {};
3885
+ for (const t of doc) {
3886
+ freq[t] = (freq[t] || 0) + 1;
3887
+ }
3888
+ let sum = 0;
3889
+ for (const term of tokens) {
3890
+ const tf = freq[term] || 0;
3891
+ if (tf === 0) continue;
3892
+ const idfVal = this.idf(term);
3893
+ let tfL = tf - this.b * (docLength / this.avgDocLength) + this.delta;
3894
+ if (tfL < 0) tfL = 0;
3895
+ sum += idfVal * (tfL / (this.k1 + tfL));
3896
+ }
3897
+ return sum;
3898
+ }
3899
+ /**
3900
+ * Search and rank all documents
3901
+ */
3902
+ search(query) {
3903
+ return this.documents.map((_, i) => ({
3904
+ index: i,
3905
+ score: this.score(query, i)
3906
+ })).sort((a, b) => b.score - a.score);
3907
+ }
3908
+ };
3909
+ function normalizeScores(scores) {
3910
+ if (scores.length === 0) return [];
3911
+ const min = Math.min(...scores);
3912
+ const max = Math.max(...scores);
3913
+ if (max === min) {
3914
+ return scores.map(() => max === 0 ? 0 : 1);
3915
+ }
3916
+ return scores.map((score) => (score - min) / (max - min));
3917
+ }
3918
+ function hybridRerank(query, items, getDocument, getSemanticScore, options = {}) {
3919
+ const {
3920
+ semanticWeight = 0.7,
3921
+ bm25Weight = 0.3,
3922
+ minScore = 0,
3923
+ k1 = 1.5,
3924
+ b = 0.75,
3925
+ delta = 0.5
3926
+ } = options;
3927
+ if (items.length === 0) return [];
3928
+ const documents = items.map(getDocument);
3929
+ const semanticScores = items.map(getSemanticScore);
3930
+ const bm25 = new BM25L(documents, { k1, b, delta });
3931
+ const bm25Scores = items.map((_, i) => bm25.score(query, i));
3932
+ const normalizedSemantic = normalizeScores(semanticScores);
3933
+ const normalizedBM25 = normalizeScores(bm25Scores);
3934
+ const results = items.map((item, i) => {
3935
+ const hybridScore = semanticWeight * normalizedSemantic[i] + bm25Weight * normalizedBM25[i];
3936
+ return {
3937
+ item,
3938
+ originalIndex: i,
3939
+ semanticScore: semanticScores[i],
3940
+ bm25Score: bm25Scores[i],
3941
+ hybridScore
3942
+ };
3943
+ });
3944
+ return results.filter((r) => r.hybridScore >= minScore).sort((a, b2) => b2.hybridScore - a.hybridScore);
3945
+ }
3946
+ function rerankChromaResults(query, chromaResults, options = {}) {
3947
+ const ids = chromaResults.ids[0] || [];
3948
+ const documents = chromaResults.documents[0] || [];
3949
+ const metadatas = chromaResults.metadatas[0] || [];
3950
+ const distances = chromaResults.distances[0] || [];
3951
+ if (ids.length === 0) return [];
3952
+ const items = ids.map((id, i) => ({
3953
+ id,
3954
+ document: documents[i],
3955
+ metadata: metadatas[i],
3956
+ distance: distances[i]
3957
+ }));
3958
+ const reranked = hybridRerank(
3959
+ query,
3960
+ items,
3961
+ (item) => item.document || "",
3962
+ // Convert L2 distance to similarity score
3963
+ (item) => 1 / (1 + item.distance),
3964
+ options
3965
+ );
3966
+ return reranked.map((r) => ({
3967
+ id: r.item.id,
3968
+ document: r.item.document,
3969
+ metadata: r.item.metadata,
3970
+ distance: r.item.distance,
3971
+ semanticScore: r.semanticScore,
3972
+ bm25Score: r.bm25Score,
3973
+ hybridScore: r.hybridScore
3974
+ }));
3975
+ }
3976
+ function rerankConversationResults(query, results, options = {}) {
3977
+ if (results.length === 0) return [];
3978
+ const reranked = hybridRerank(
3979
+ query,
3980
+ results,
3981
+ (item) => item.userPrompt || "",
3982
+ (item) => item.similarity || 0,
3983
+ options
3984
+ );
3985
+ return reranked.map((r) => ({
3986
+ ...r.item,
3987
+ hybridScore: r.hybridScore,
3988
+ bm25Score: r.bm25Score
3989
+ }));
3990
+ }
3991
+
3822
3992
  // src/userResponse/conversation-search.ts
3823
3993
  var searchConversations = async ({
3824
3994
  userPrompt,
@@ -3865,8 +4035,93 @@ var searchConversations = async ({
3865
4035
  return null;
3866
4036
  }
3867
4037
  };
4038
+ var searchConversationsWithReranking = async (options) => {
4039
+ const {
4040
+ userPrompt,
4041
+ collections,
4042
+ userId,
4043
+ similarityThreshold = 0.6,
4044
+ rerankCandidates = 50,
4045
+ // Fetch more candidates for better reranking
4046
+ hybridOptions = {
4047
+ semanticWeight: 0.7,
4048
+ bm25Weight: 0.3
4049
+ }
4050
+ } = options;
4051
+ try {
4052
+ if (!collections || !collections["conversation-history"]) {
4053
+ logger.info("[ConversationSearch] conversation-history collection not registered, skipping");
4054
+ return null;
4055
+ }
4056
+ if (!collections["conversation-history"]["searchMultiple"]) {
4057
+ logger.info("[ConversationSearch] searchMultiple not available, falling back to standard search");
4058
+ return searchConversations({
4059
+ userPrompt,
4060
+ collections,
4061
+ userId,
4062
+ similarityThreshold
4063
+ });
4064
+ }
4065
+ logger.info(`[ConversationSearch] Hybrid search for: "${userPrompt.substring(0, 50)}..."`);
4066
+ logger.info(`[ConversationSearch] Fetching ${rerankCandidates} candidates for reranking`);
4067
+ logger.info(`[ConversationSearch] Weights - Semantic: ${hybridOptions.semanticWeight}, BM25: ${hybridOptions.bm25Weight}`);
4068
+ const results = await collections["conversation-history"]["searchMultiple"]({
4069
+ userPrompt,
4070
+ userId,
4071
+ limit: rerankCandidates,
4072
+ threshold: 0
4073
+ // No threshold - get all candidates for reranking
4074
+ });
4075
+ if (!results || results.length === 0) {
4076
+ logger.info("[ConversationSearch] No conversations found in database");
4077
+ return null;
4078
+ }
4079
+ logger.info(`[ConversationSearch] Retrieved ${results.length} candidates for reranking`);
4080
+ const candidatesForReranking = results.map((r) => ({
4081
+ ...r,
4082
+ userPrompt: r.metadata?.userPrompt || ""
4083
+ }));
4084
+ const reranked = rerankConversationResults(userPrompt, candidatesForReranking, hybridOptions);
4085
+ if (reranked.length === 0) {
4086
+ logger.info("[ConversationSearch] No results after reranking");
4087
+ return null;
4088
+ }
4089
+ const best = reranked[0];
4090
+ const hybridScore = best.hybridScore;
4091
+ const semanticScore = best.similarity || 0;
4092
+ const matchedUserPrompt = best.userPrompt || best.metadata?.userPrompt || "";
4093
+ logger.info(`[ConversationSearch] Best match after reranking:`);
4094
+ logger.info(` - Hybrid score: ${(hybridScore * 100).toFixed(2)}%`);
4095
+ logger.info(` - Semantic score: ${(semanticScore * 100).toFixed(2)}%`);
4096
+ logger.info(` - BM25L score: ${best.bm25Score.toFixed(4)}`);
4097
+ logger.info(` - Matched prompt: "${matchedUserPrompt}"`);
4098
+ logger.info(` - Query prompt: "${userPrompt}"`);
4099
+ if (semanticScore < similarityThreshold) {
4100
+ logger.info(
4101
+ `[ConversationSearch] Semantic score ${(semanticScore * 100).toFixed(2)}% below threshold ${(similarityThreshold * 100).toFixed(2)}% - rejecting match`
4102
+ );
4103
+ return null;
4104
+ }
4105
+ logger.info(
4106
+ `[ConversationSearch] \u2713 Found match with semantic score ${(semanticScore * 100).toFixed(2)}%`
4107
+ );
4108
+ logger.info(` - Returning cached result for: "${matchedUserPrompt}"`);
4109
+ return {
4110
+ uiBlock: best.uiBlock,
4111
+ similarity: semanticScore,
4112
+ hybridScore,
4113
+ bm25Score: best.bm25Score,
4114
+ metadata: best.metadata
4115
+ };
4116
+ } catch (error) {
4117
+ const errorMsg = error instanceof Error ? error.message : String(error);
4118
+ logger.warn(`[ConversationSearch] Error in hybrid search: ${errorMsg}`);
4119
+ return null;
4120
+ }
4121
+ };
3868
4122
  var ConversationSearch = {
3869
- searchConversations
4123
+ searchConversations,
4124
+ searchConversationsWithReranking
3870
4125
  };
3871
4126
  var conversation_search_default = ConversationSearch;
3872
4127
 
@@ -3915,7 +4170,7 @@ var BaseLLM = class {
3915
4170
  * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
3916
4171
  * @returns Object containing matched components, layout title/description, and follow-up actions
3917
4172
  */
3918
- async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback) {
4173
+ async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
3919
4174
  try {
3920
4175
  logger.debug(`[${this.getProviderName()}] Starting component matching from text response`);
3921
4176
  let availableComponentsText = "No components available";
@@ -3931,12 +4186,44 @@ var BaseLLM = class {
3931
4186
  Props Structure: ${propsPreview}`;
3932
4187
  }).join("\n\n");
3933
4188
  }
4189
+ let deferredToolsText = "No deferred external tools for this request.";
4190
+ if (deferredTools && deferredTools.length > 0) {
4191
+ logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools to component matching`);
4192
+ 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) => {
4193
+ return `${idx + 1}. **${tool.name}**
4194
+ toolId: "${tool.id}" (USE THIS EXACT VALUE - do not modify!)
4195
+ toolName: "${tool.name}"
4196
+ parameters: ${JSON.stringify(tool.params || {})}
4197
+ requiredFields:
4198
+ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
4199
+ }).join("\n\n");
4200
+ }
4201
+ let executedToolsText = "No external tools were executed for data fetching.";
4202
+ if (executedTools && executedTools.length > 0) {
4203
+ logger.info(`[${this.getProviderName()}] Passing ${executedTools.length} executed tools to component matching`);
4204
+ 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) => {
4205
+ let resultPreview = "No result data";
4206
+ if (tool.result) {
4207
+ const resultStr = typeof tool.result === "string" ? tool.result : JSON.stringify(tool.result, null, 2);
4208
+ resultPreview = resultStr.length > 2e3 ? resultStr.substring(0, 2e3) + "\n... (truncated)" : resultStr;
4209
+ }
4210
+ return `${idx + 1}. **${tool.name}**
4211
+ toolId: "${tool.id}" (USE THIS EXACT VALUE for externalTool.toolId)
4212
+ toolName: "${tool.name}" (USE THIS EXACT VALUE for externalTool.toolName)
4213
+ parameters: ${JSON.stringify(tool.params || {})} (USE THESE for externalTool.parameters)
4214
+ result: ${resultPreview}`;
4215
+ }).join("\n\n");
4216
+ }
3934
4217
  const schemaDoc = schema.generateSchemaDocumentation();
3935
4218
  logger.file("\n=============================\nText analysis response:", analysisContent);
4219
+ logger.file("\n=============================\nDeferred tools:", deferredToolsText);
4220
+ logger.file("\n=============================\nExecuted tools:", executedToolsText);
3936
4221
  const prompts = await promptLoader.loadPrompts("match-text-components", {
3937
4222
  ANALYSIS_CONTENT: analysisContent,
3938
4223
  AVAILABLE_COMPONENTS: availableComponentsText,
3939
- SCHEMA_DOC: schemaDoc
4224
+ SCHEMA_DOC: schemaDoc,
4225
+ DEFERRED_TOOLS: deferredToolsText,
4226
+ EXECUTED_TOOLS: executedToolsText
3940
4227
  });
3941
4228
  logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
3942
4229
  logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
@@ -4056,9 +4343,6 @@ var BaseLLM = class {
4056
4343
  matchedComponents.forEach((comp, idx) => {
4057
4344
  logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
4058
4345
  });
4059
- if (suggestedComponents.length !== matchedComponents.length) {
4060
- logger.warn(`[${this.getProviderName()}] \u26A0\uFE0F MISMATCH: Text suggested ${suggestedComponents.length} components, but LLM matched ${matchedComponents.length}`);
4061
- }
4062
4346
  logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
4063
4347
  const rawActions = result.actions || [];
4064
4348
  const actions = convertQuestionsToActions(rawActions);
@@ -4133,6 +4417,7 @@ var BaseLLM = class {
4133
4417
  */
4134
4418
  async classifyQuestionCategory(userPrompt, apiKey, logCollector, conversationHistory, externalTools) {
4135
4419
  try {
4420
+ const schemaDoc = schema.generateSchemaDocumentation();
4136
4421
  const availableToolsDoc = externalTools && externalTools.length > 0 ? externalTools.map((tool) => {
4137
4422
  const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
4138
4423
  return `- **${tool.name}** (id: ${tool.id})
@@ -4142,7 +4427,8 @@ var BaseLLM = class {
4142
4427
  const prompts = await promptLoader.loadPrompts("category-classification", {
4143
4428
  USER_PROMPT: userPrompt,
4144
4429
  CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
4145
- AVAILABLE_TOOLS: availableToolsDoc
4430
+ AVAILABLE_TOOLS: availableToolsDoc,
4431
+ SCHEMA_DOC: schemaDoc || "No database schema available"
4146
4432
  });
4147
4433
  const result = await LLM.stream(
4148
4434
  {
@@ -4280,21 +4566,44 @@ var BaseLLM = class {
4280
4566
  let availableToolsDoc = "No external tools are available for this request.";
4281
4567
  if (externalTools && externalTools.length > 0) {
4282
4568
  logger.info(`[${this.getProviderName()}] External tools available: ${externalTools.map((t) => t.name).join(", ")}`);
4283
- 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) => {
4284
- const paramsText = Object.entries(tool.params || {}).map(([key, value]) => {
4285
- const valueType = typeof value;
4286
- if (valueType === "string" && ["string", "number", "integer", "boolean", "array", "object"].includes(String(value).toLowerCase())) {
4287
- return `- ${key}: ${value}`;
4288
- } else {
4289
- return `- ${key}: ${JSON.stringify(value)} (default value - use this)`;
4569
+ const immediateTools = externalTools.filter((t) => t.executionType === "immediate" || t.executionType === "deferred" && t.userProvidedData);
4570
+ const deferredTools = externalTools.filter((t) => t.executionType === "deferred" && !t.userProvidedData);
4571
+ let toolsDocParts = [];
4572
+ if (immediateTools.length > 0) {
4573
+ const immediateDoc = "## IMMEDIATE EXECUTION TOOLS\nExecute these tools right away:\n\n" + immediateTools.map((tool, idx) => {
4574
+ const paramsText = Object.entries(tool.params || {}).map(([key, value]) => {
4575
+ const valueType = typeof value;
4576
+ if (valueType === "string" && ["string", "number", "integer", "boolean", "array", "object"].includes(String(value).toLowerCase())) {
4577
+ return `- ${key}: ${value}`;
4578
+ } else {
4579
+ return `- ${key}: ${JSON.stringify(value)} (default value - use this)`;
4580
+ }
4581
+ }).join("\n ");
4582
+ let userDataText = "";
4583
+ if (tool.userProvidedData) {
4584
+ userDataText = "\n **User Provided Data** (use these values):\n " + Object.entries(tool.userProvidedData).map(([key, value]) => `- ${key}: ${JSON.stringify(value)}`).join("\n ");
4290
4585
  }
4291
- }).join("\n ");
4292
- return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
4586
+ return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
4587
+ Execution Type: IMMEDIATE
4293
4588
  Description: ${tool.description}
4294
- **ACTION REQUIRED**: Call this tool with the parameters below
4295
4589
  Parameters:
4296
- ${paramsText}`;
4297
- }).join("\n\n");
4590
+ ${paramsText}${userDataText}`;
4591
+ }).join("\n\n");
4592
+ toolsDocParts.push(immediateDoc);
4593
+ }
4594
+ if (deferredTools.length > 0) {
4595
+ 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) => {
4596
+ const requiredFieldsText = (tool.requiredFields || []).map((f) => `- ${f.label || f.name} (${f.type})${f.required ? " *required*" : ""}`).join("\n ");
4597
+ return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
4598
+ Execution Type: DEFERRED (needs form input)
4599
+ Description: ${tool.description}
4600
+ Reason: ${tool.executionReason || "Write operation requires user confirmation"}
4601
+ Required Fields:
4602
+ ${requiredFieldsText || "(fields will be determined by form)"}`;
4603
+ }).join("\n\n");
4604
+ toolsDocParts.push(deferredDoc);
4605
+ }
4606
+ availableToolsDoc = toolsDocParts.join("\n\n---\n\n");
4298
4607
  }
4299
4608
  const schemaDoc = schema.generateSchemaDocumentation();
4300
4609
  const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
@@ -4335,8 +4644,12 @@ var BaseLLM = class {
4335
4644
  }
4336
4645
  }];
4337
4646
  if (externalTools && externalTools.length > 0) {
4338
- externalTools.forEach((tool) => {
4339
- logger.info(`[${this.getProviderName()}] Processing external tool:`, JSON.stringify(tool, null, 2));
4647
+ const executableTools = externalTools.filter(
4648
+ (t) => t.executionType === "immediate" || t.executionType === "deferred" && t.userProvidedData
4649
+ );
4650
+ logger.info(`[${this.getProviderName()}] Executable tools: ${executableTools.length} of ${externalTools.length} total`);
4651
+ executableTools.forEach((tool) => {
4652
+ logger.info(`[${this.getProviderName()}] Processing executable tool:`, JSON.stringify(tool, null, 2));
4340
4653
  const properties = {};
4341
4654
  const required = [];
4342
4655
  Object.entries(tool.params || {}).forEach(([key, typeOrValue]) => {
@@ -4405,13 +4718,14 @@ var BaseLLM = class {
4405
4718
  input_schema: inputSchema
4406
4719
  });
4407
4720
  });
4408
- logger.info(`[${this.getProviderName()}] Added ${externalTools.length} external tools to tool calling capability`);
4721
+ logger.info(`[${this.getProviderName()}] Added ${executableTools.length} executable tools to tool calling capability (${externalTools.length - executableTools.length} deferred tools await form input)`);
4409
4722
  logger.info(`[${this.getProviderName()}] Complete tools array:`, JSON.stringify(tools, null, 2));
4410
4723
  }
4411
4724
  const queryAttempts = /* @__PURE__ */ new Map();
4412
4725
  const MAX_QUERY_ATTEMPTS = 6;
4413
4726
  const toolAttempts = /* @__PURE__ */ new Map();
4414
4727
  const MAX_TOOL_ATTEMPTS = 3;
4728
+ const executedToolsList = [];
4415
4729
  let maxAttemptsReached = false;
4416
4730
  let fullStreamedText = "";
4417
4731
  const wrappedStreamCallback = streamCallback ? (chunk) => {
@@ -4594,6 +4908,17 @@ Please try rephrasing your request or contact support.
4594
4908
  const result2 = await externalTool.fn(toolInput);
4595
4909
  logger.info(`[${this.getProviderName()}] External tool ${externalTool.name} executed successfully`);
4596
4910
  logCollector?.info(`\u2713 ${externalTool.name} executed successfully`);
4911
+ if (!executedToolsList.find((t) => t.id === externalTool.id)) {
4912
+ executedToolsList.push({
4913
+ id: externalTool.id,
4914
+ name: externalTool.name,
4915
+ params: toolInput,
4916
+ // The actual parameters used in this execution
4917
+ result: result2
4918
+ // Store the actual result data for populating deferred tool params
4919
+ });
4920
+ logger.info(`[${this.getProviderName()}] Tracked executed tool: ${externalTool.name} with params: ${JSON.stringify(toolInput)}`);
4921
+ }
4597
4922
  if (wrappedStreamCallback) {
4598
4923
  wrappedStreamCallback(`\u2705 **${externalTool.name} completed successfully**
4599
4924
 
@@ -4683,12 +5008,31 @@ ${errorMsg}
4683
5008
  wrappedStreamCallback(answerMarker);
4684
5009
  logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
4685
5010
  } : void 0;
5011
+ const deferredTools = externalTools?.filter((t) => {
5012
+ if (t.executionType === "deferred" && !t.userProvidedData) return true;
5013
+ if (category === "data_modification" && !t.userProvidedData) {
5014
+ const name = (t.name || t.id || "").toLowerCase();
5015
+ const isWriteOperation = /create|add|insert|new|update|edit|modify|delete|remove|send/.test(name);
5016
+ if (isWriteOperation) {
5017
+ logger.info(`[${this.getProviderName()}] Inferred deferred execution for tool: ${t.name}`);
5018
+ return true;
5019
+ }
5020
+ }
5021
+ return false;
5022
+ }) || [];
5023
+ if (deferredTools.length > 0) {
5024
+ logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools for Form generation`);
5025
+ }
5026
+ logger.info(`[${this.getProviderName()}] passing deferred tools to the matching function: ${JSON.stringify(deferredTools, null, 2)}`);
5027
+ logger.info(`[${this.getProviderName()}] passing executed tools to the matching function: ${JSON.stringify(executedToolsList, null, 2)}`);
4686
5028
  const matchResult = await this.matchComponentsFromAnalysis(
4687
5029
  textResponse,
4688
5030
  components,
4689
5031
  apiKey,
4690
5032
  logCollector,
4691
- componentStreamCallback
5033
+ componentStreamCallback,
5034
+ deferredTools,
5035
+ executedToolsList
4692
5036
  );
4693
5037
  matchedComponents = matchResult.components;
4694
5038
  layoutTitle = matchResult.layoutTitle;
@@ -4757,23 +5101,20 @@ ${errorMsg}
4757
5101
  */
4758
5102
  async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "text", streamCallback, collections, externalTools, userId) {
4759
5103
  const startTime = Date.now();
4760
- logger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);
5104
+ logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
4761
5105
  logCollector?.info(`Starting request processing with mode: ${responseMode}`);
4762
5106
  try {
4763
5107
  logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
4764
5108
  logCollector?.info("Step 1: Searching for similar previous conversations...");
4765
- const conversationMatch = await conversation_search_default.searchConversations({
5109
+ const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
4766
5110
  userPrompt,
4767
5111
  collections,
4768
5112
  userId,
4769
5113
  similarityThreshold: 0.6
4770
5114
  // 60% threshold
4771
5115
  });
4772
- logger.info("conversationMatch:", conversationMatch);
4773
5116
  if (conversationMatch) {
4774
- logger.info(
4775
- `[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`
4776
- );
5117
+ logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
4777
5118
  logCollector?.info(
4778
5119
  `\u2713 Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`
4779
5120
  );
@@ -4781,7 +5122,6 @@ ${errorMsg}
4781
5122
  const isValidComponent = rawComponent && typeof rawComponent === "object" && Object.keys(rawComponent).length > 0;
4782
5123
  const component = isValidComponent ? rawComponent : null;
4783
5124
  const cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || "";
4784
- logger.debug(`[${this.getProviderName()}] Cached component: ${component ? "present" : "null"}, cachedTextResponse: ${cachedTextResponse ? cachedTextResponse.substring(0, 50) + "..." : "empty"}`);
4785
5125
  if (this.containsFormComponent(component)) {
4786
5126
  logger.info(`[${this.getProviderName()}] Skipping cached result - Form components contain stale defaultValues, fetching fresh data`);
4787
5127
  logCollector?.info("Skipping cache for form - fetching current values from database...");
@@ -4879,22 +5219,31 @@ ${errorMsg}
4879
5219
  if (categoryClassification.externalTools && categoryClassification.externalTools.length > 0) {
4880
5220
  logger.info(`[${this.getProviderName()}] Identified ${categoryClassification.externalTools.length} external tools needed`);
4881
5221
  logCollector?.info(`Identified external tools: ${categoryClassification.externalTools.map((t) => t.name || t.type).join(", ")}`);
4882
- toolsToUse = categoryClassification.externalTools?.map((t) => ({
4883
- id: t.type,
4884
- name: t.name,
4885
- description: t.description,
4886
- params: t.parameters || {},
4887
- fn: (() => {
4888
- const realTool = externalTools?.find((tool) => tool.id === t.type);
4889
- if (realTool) {
4890
- logger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);
4891
- return realTool.fn;
4892
- } else {
4893
- logger.warn(`[${this.getProviderName()}] Tool ${t.type} not found in registered tools`);
4894
- return async () => ({ success: false, message: `Tool ${t.name || t.type} not registered` });
4895
- }
4896
- })()
4897
- })) || [];
5222
+ logger.info(`[${this.getProviderName()}] Raw external tools from classification: ${JSON.stringify(categoryClassification.externalTools, null, 2)}`);
5223
+ toolsToUse = categoryClassification.externalTools?.map((t) => {
5224
+ const realTool = externalTools?.find((tool) => tool.id === t.type);
5225
+ logger.info(`[${this.getProviderName()}] Tool ${t.name}: executionType=${t.executionType}, userProvidedData=${t.userProvidedData ? "present" : "null"}`);
5226
+ return {
5227
+ id: t.type,
5228
+ name: t.name,
5229
+ description: t.description,
5230
+ params: t.parameters || {},
5231
+ // NEW: Include execution type info from category classification
5232
+ executionType: t.executionType || "immediate",
5233
+ executionReason: t.executionReason || "",
5234
+ requiredFields: t.requiredFields || [],
5235
+ userProvidedData: t.userProvidedData || null,
5236
+ fn: (() => {
5237
+ if (realTool) {
5238
+ logger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);
5239
+ return realTool.fn;
5240
+ } else {
5241
+ logger.warn(`[${this.getProviderName()}] Tool ${t.type} not found in registered tools`);
5242
+ return async () => ({ success: false, message: `Tool ${t.name || t.type} not registered` });
5243
+ }
5244
+ })()
5245
+ };
5246
+ }) || [];
4898
5247
  }
4899
5248
  if (categoryClassification.category === "general") {
4900
5249
  logger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);
@@ -5585,7 +5934,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
5585
5934
  }
5586
5935
  logCollector.info(`Starting user prompt request with ${components.length} components`);
5587
5936
  const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId);
5588
- logger.info("conversationHistory", conversationHistory);
5589
5937
  const responseMode = payload.responseMode || "component";
5590
5938
  logger.info("responseMode", responseMode);
5591
5939
  let streamCallback;
@@ -6195,6 +6543,7 @@ async function handleUsersRequest(data, collections, sendMessage) {
6195
6543
  const password = requestData?.password;
6196
6544
  const fullname = requestData?.fullname;
6197
6545
  const role = requestData?.role;
6546
+ const userInfo = requestData?.userInfo;
6198
6547
  const filters = requestData?.filters;
6199
6548
  const limit = requestData?.limit;
6200
6549
  const sort = requestData?.sort;
@@ -6209,10 +6558,10 @@ async function handleUsersRequest(data, collections, sendMessage) {
6209
6558
  const userManager = getUserManager();
6210
6559
  switch (operation) {
6211
6560
  case "create":
6212
- await handleCreate(id, { username, email, password, fullname, role }, executeCollection, userManager, sendMessage, from.id);
6561
+ await handleCreate(id, { username, email, password, fullname, role, userInfo }, executeCollection, userManager, sendMessage, from.id);
6213
6562
  break;
6214
6563
  case "update":
6215
- await handleUpdate(id, numericId, { username, email, password, fullname, role }, executeCollection, userManager, sendMessage, from.id);
6564
+ await handleUpdate(id, numericId, { username, email, password, fullname, role, userInfo }, executeCollection, userManager, sendMessage, from.id);
6216
6565
  break;
6217
6566
  case "delete":
6218
6567
  await handleDelete(id, numericId, username, executeCollection, userManager, sendMessage, from.id);
@@ -6241,7 +6590,7 @@ async function handleUsersRequest(data, collections, sendMessage) {
6241
6590
  }
6242
6591
  }
6243
6592
  async function handleCreate(id, userData, executeCollection, userManager, sendMessage, clientId) {
6244
- const { username, email, password, fullname, role } = userData;
6593
+ const { username, email, password, fullname, role, userInfo } = userData;
6245
6594
  if (!username || username.trim().length === 0) {
6246
6595
  sendResponse3(id, {
6247
6596
  success: false,
@@ -6272,7 +6621,8 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
6272
6621
  email: email || void 0,
6273
6622
  password,
6274
6623
  fullname: fullname || void 0,
6275
- role: role || void 0
6624
+ role: role || void 0,
6625
+ userInfo: userInfo || void 0
6276
6626
  });
6277
6627
  if (result && result.success) {
6278
6628
  logger.info(`[DB] User created successfully: ${username}`);
@@ -6340,7 +6690,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
6340
6690
  }
6341
6691
  }
6342
6692
  async function handleUpdate(id, numericId, userData, executeCollection, userManager, sendMessage, clientId) {
6343
- const { username, email, password, fullname, role } = userData;
6693
+ const { username, email, password, fullname, role, userInfo } = userData;
6344
6694
  if (!numericId && !username) {
6345
6695
  sendResponse3(id, {
6346
6696
  success: false,
@@ -6356,7 +6706,8 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
6356
6706
  email,
6357
6707
  password,
6358
6708
  fullname,
6359
- role
6709
+ role,
6710
+ userInfo
6360
6711
  });
6361
6712
  if (result && result.success) {
6362
6713
  logger.info(`[DB] User updated successfully, ID: ${numericId}`);
@@ -6716,6 +7067,7 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
6716
7067
  const projectId = requestData?.projectId;
6717
7068
  const name = requestData?.name;
6718
7069
  const description = requestData?.description;
7070
+ const published = requestData?.published;
6719
7071
  const createdBy = requestData?.createdBy;
6720
7072
  const updatedBy = requestData?.updatedBy;
6721
7073
  const numericId = requestData?.id;
@@ -6733,10 +7085,10 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
6733
7085
  const dashboardManager2 = getDashboardManager();
6734
7086
  switch (operation) {
6735
7087
  case "create":
6736
- await handleCreate2(id, dashboardId, dashboard, projectId, name, description, createdBy, executeCollection, dashboardManager2, sendMessage, from.id);
7088
+ await handleCreate2(id, dashboardId, dashboard, projectId, name, description, published, createdBy, executeCollection, dashboardManager2, sendMessage, from.id);
6737
7089
  break;
6738
7090
  case "update":
6739
- await handleUpdate2(id, numericId, dashboardId, dashboard, name, description, updatedBy, executeCollection, dashboardManager2, sendMessage, from.id);
7091
+ await handleUpdate2(id, numericId, dashboardId, dashboard, name, description, published, updatedBy, executeCollection, dashboardManager2, sendMessage, from.id);
6740
7092
  break;
6741
7093
  case "delete":
6742
7094
  await handleDelete2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, from.id);
@@ -6764,7 +7116,7 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
6764
7116
  }, sendMessage);
6765
7117
  }
6766
7118
  }
6767
- async function handleCreate2(id, dashboardId, dashboard, projectId, name, description, createdBy, executeCollection, dashboardManager2, sendMessage, clientId) {
7119
+ async function handleCreate2(id, dashboardId, dashboard, projectId, name, description, published, createdBy, executeCollection, dashboardManager2, sendMessage, clientId) {
6768
7120
  if (!dashboardId || dashboardId.trim().length === 0) {
6769
7121
  sendResponse4(id, {
6770
7122
  success: false,
@@ -6786,6 +7138,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
6786
7138
  name: name || "",
6787
7139
  description,
6788
7140
  dashboard,
7141
+ published,
6789
7142
  createdBy
6790
7143
  });
6791
7144
  if (result && result.success) {
@@ -6825,7 +7178,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
6825
7178
  }, sendMessage, clientId);
6826
7179
  }
6827
7180
  }
6828
- async function handleUpdate2(id, numericId, dashboardId, dashboard, name, description, updatedBy, executeCollection, dashboardManager2, sendMessage, clientId) {
7181
+ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, description, published, updatedBy, executeCollection, dashboardManager2, sendMessage, clientId) {
6829
7182
  if (!numericId) {
6830
7183
  sendResponse4(id, {
6831
7184
  success: false,
@@ -6839,6 +7192,7 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
6839
7192
  name,
6840
7193
  description,
6841
7194
  dashboard,
7195
+ published,
6842
7196
  updatedBy
6843
7197
  });
6844
7198
  if (result && result.success) {
@@ -7081,6 +7435,7 @@ async function handleReportsRequest(data, collections, sendMessage) {
7081
7435
  const projectId = requestData?.projectId;
7082
7436
  const name = requestData?.name;
7083
7437
  const description = requestData?.description;
7438
+ const published = requestData?.published;
7084
7439
  const createdBy = requestData?.createdBy;
7085
7440
  const updatedBy = requestData?.updatedBy;
7086
7441
  const numericId = requestData?.id;
@@ -7098,10 +7453,10 @@ async function handleReportsRequest(data, collections, sendMessage) {
7098
7453
  const reportManager2 = getReportManager();
7099
7454
  switch (operation) {
7100
7455
  case "create":
7101
- await handleCreate3(id, reportId, report, projectId, name, description, createdBy, executeCollection, reportManager2, sendMessage, from.id);
7456
+ await handleCreate3(id, reportId, report, projectId, name, description, published, createdBy, executeCollection, reportManager2, sendMessage, from.id);
7102
7457
  break;
7103
7458
  case "update":
7104
- await handleUpdate3(id, numericId, reportId, report, name, description, updatedBy, executeCollection, reportManager2, sendMessage, from.id);
7459
+ await handleUpdate3(id, numericId, reportId, report, name, description, published, updatedBy, executeCollection, reportManager2, sendMessage, from.id);
7105
7460
  break;
7106
7461
  case "delete":
7107
7462
  await handleDelete3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, from.id);
@@ -7129,7 +7484,7 @@ async function handleReportsRequest(data, collections, sendMessage) {
7129
7484
  }, sendMessage);
7130
7485
  }
7131
7486
  }
7132
- async function handleCreate3(id, reportId, report, projectId, name, description, createdBy, executeCollection, reportManager2, sendMessage, clientId) {
7487
+ async function handleCreate3(id, reportId, report, projectId, name, description, published, createdBy, executeCollection, reportManager2, sendMessage, clientId) {
7133
7488
  if (!reportId || reportId.trim().length === 0) {
7134
7489
  sendResponse5(id, {
7135
7490
  success: false,
@@ -7151,6 +7506,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
7151
7506
  name: name || "",
7152
7507
  description,
7153
7508
  report,
7509
+ published,
7154
7510
  createdBy
7155
7511
  });
7156
7512
  if (result && result.success) {
@@ -7190,7 +7546,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
7190
7546
  }, sendMessage, clientId);
7191
7547
  }
7192
7548
  }
7193
- async function handleUpdate3(id, numericId, reportId, report, name, description, updatedBy, executeCollection, reportManager2, sendMessage, clientId) {
7549
+ async function handleUpdate3(id, numericId, reportId, report, name, description, published, updatedBy, executeCollection, reportManager2, sendMessage, clientId) {
7194
7550
  if (!numericId) {
7195
7551
  sendResponse5(id, {
7196
7552
  success: false,
@@ -7204,6 +7560,7 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
7204
7560
  name,
7205
7561
  description,
7206
7562
  report,
7563
+ published,
7207
7564
  updatedBy
7208
7565
  });
7209
7566
  if (result && result.success) {
@@ -9523,6 +9880,7 @@ var SuperatomSDK = class {
9523
9880
  };
9524
9881
  // Annotate the CommonJS export names for ESM import in node:
9525
9882
  0 && (module.exports = {
9883
+ BM25L,
9526
9884
  CONTEXT_CONFIG,
9527
9885
  CleanupService,
9528
9886
  LLM,
@@ -9534,6 +9892,9 @@ var SuperatomSDK = class {
9534
9892
  UIBlock,
9535
9893
  UILogCollector,
9536
9894
  UserManager,
9537
- logger
9895
+ hybridRerank,
9896
+ logger,
9897
+ rerankChromaResults,
9898
+ rerankConversationResults
9538
9899
  });
9539
9900
  //# sourceMappingURL=index.js.map