@superatomai/sdk-node 0.0.24 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +129 -1
- package/dist/index.d.ts +129 -1
- package/dist/index.js +392 -48
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +387 -47
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3779,6 +3779,166 @@ var KB = {
|
|
|
3779
3779
|
};
|
|
3780
3780
|
var knowledge_base_default = KB;
|
|
3781
3781
|
|
|
3782
|
+
// src/utils/bm25l-reranker.ts
|
|
3783
|
+
var BM25L = class {
|
|
3784
|
+
/**
|
|
3785
|
+
* @param documents - Array of raw documents (strings)
|
|
3786
|
+
* @param opts - Optional BM25L parameters
|
|
3787
|
+
*/
|
|
3788
|
+
constructor(documents = [], opts = {}) {
|
|
3789
|
+
if (!Array.isArray(documents)) {
|
|
3790
|
+
throw new Error("BM25L: documents must be an array of strings.");
|
|
3791
|
+
}
|
|
3792
|
+
this.k1 = typeof opts.k1 === "number" ? opts.k1 : 1.5;
|
|
3793
|
+
this.b = typeof opts.b === "number" ? opts.b : 0.75;
|
|
3794
|
+
this.delta = typeof opts.delta === "number" ? opts.delta : 0.5;
|
|
3795
|
+
this.documents = documents.map((d) => typeof d === "string" ? this.tokenize(d) : []);
|
|
3796
|
+
this.docLengths = this.documents.map((doc) => doc.length);
|
|
3797
|
+
this.avgDocLength = this.docLengths.reduce((a, b) => a + b, 0) / (this.docLengths.length || 1);
|
|
3798
|
+
this.termDocFreq = {};
|
|
3799
|
+
this.documents.forEach((doc) => {
|
|
3800
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3801
|
+
doc.forEach((term) => {
|
|
3802
|
+
if (!seen.has(term)) {
|
|
3803
|
+
seen.add(term);
|
|
3804
|
+
this.termDocFreq[term] = (this.termDocFreq[term] || 0) + 1;
|
|
3805
|
+
}
|
|
3806
|
+
});
|
|
3807
|
+
});
|
|
3808
|
+
}
|
|
3809
|
+
/**
|
|
3810
|
+
* Tokenize text into lowercase alphanumeric tokens
|
|
3811
|
+
*/
|
|
3812
|
+
tokenize(text) {
|
|
3813
|
+
if (typeof text !== "string") return [];
|
|
3814
|
+
return text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter(Boolean);
|
|
3815
|
+
}
|
|
3816
|
+
/**
|
|
3817
|
+
* Compute IDF (Inverse Document Frequency) with smoothing
|
|
3818
|
+
*/
|
|
3819
|
+
idf(term) {
|
|
3820
|
+
const df = this.termDocFreq[term] || 0;
|
|
3821
|
+
const N = this.documents.length || 1;
|
|
3822
|
+
return Math.log(1 + (N - df + 0.5) / (df + 0.5));
|
|
3823
|
+
}
|
|
3824
|
+
/**
|
|
3825
|
+
* Compute BM25L score for a single document
|
|
3826
|
+
*/
|
|
3827
|
+
score(query, docIndex) {
|
|
3828
|
+
if (typeof query !== "string") return 0;
|
|
3829
|
+
if (docIndex < 0 || docIndex >= this.documents.length) return 0;
|
|
3830
|
+
const tokens = this.tokenize(query);
|
|
3831
|
+
if (tokens.length === 0) return 0;
|
|
3832
|
+
const doc = this.documents[docIndex];
|
|
3833
|
+
const docLength = this.docLengths[docIndex] || 1;
|
|
3834
|
+
const freq = {};
|
|
3835
|
+
for (const t of doc) {
|
|
3836
|
+
freq[t] = (freq[t] || 0) + 1;
|
|
3837
|
+
}
|
|
3838
|
+
let sum = 0;
|
|
3839
|
+
for (const term of tokens) {
|
|
3840
|
+
const tf = freq[term] || 0;
|
|
3841
|
+
if (tf === 0) continue;
|
|
3842
|
+
const idfVal = this.idf(term);
|
|
3843
|
+
let tfL = tf - this.b * (docLength / this.avgDocLength) + this.delta;
|
|
3844
|
+
if (tfL < 0) tfL = 0;
|
|
3845
|
+
sum += idfVal * (tfL / (this.k1 + tfL));
|
|
3846
|
+
}
|
|
3847
|
+
return sum;
|
|
3848
|
+
}
|
|
3849
|
+
/**
|
|
3850
|
+
* Search and rank all documents
|
|
3851
|
+
*/
|
|
3852
|
+
search(query) {
|
|
3853
|
+
return this.documents.map((_, i) => ({
|
|
3854
|
+
index: i,
|
|
3855
|
+
score: this.score(query, i)
|
|
3856
|
+
})).sort((a, b) => b.score - a.score);
|
|
3857
|
+
}
|
|
3858
|
+
};
|
|
3859
|
+
function normalizeScores(scores) {
|
|
3860
|
+
if (scores.length === 0) return [];
|
|
3861
|
+
const min = Math.min(...scores);
|
|
3862
|
+
const max = Math.max(...scores);
|
|
3863
|
+
if (max === min) {
|
|
3864
|
+
return scores.map(() => max === 0 ? 0 : 1);
|
|
3865
|
+
}
|
|
3866
|
+
return scores.map((score) => (score - min) / (max - min));
|
|
3867
|
+
}
|
|
3868
|
+
function hybridRerank(query, items, getDocument, getSemanticScore, options = {}) {
|
|
3869
|
+
const {
|
|
3870
|
+
semanticWeight = 0.7,
|
|
3871
|
+
bm25Weight = 0.3,
|
|
3872
|
+
minScore = 0,
|
|
3873
|
+
k1 = 1.5,
|
|
3874
|
+
b = 0.75,
|
|
3875
|
+
delta = 0.5
|
|
3876
|
+
} = options;
|
|
3877
|
+
if (items.length === 0) return [];
|
|
3878
|
+
const documents = items.map(getDocument);
|
|
3879
|
+
const semanticScores = items.map(getSemanticScore);
|
|
3880
|
+
const bm25 = new BM25L(documents, { k1, b, delta });
|
|
3881
|
+
const bm25Scores = items.map((_, i) => bm25.score(query, i));
|
|
3882
|
+
const normalizedSemantic = normalizeScores(semanticScores);
|
|
3883
|
+
const normalizedBM25 = normalizeScores(bm25Scores);
|
|
3884
|
+
const results = items.map((item, i) => {
|
|
3885
|
+
const hybridScore = semanticWeight * normalizedSemantic[i] + bm25Weight * normalizedBM25[i];
|
|
3886
|
+
return {
|
|
3887
|
+
item,
|
|
3888
|
+
originalIndex: i,
|
|
3889
|
+
semanticScore: semanticScores[i],
|
|
3890
|
+
bm25Score: bm25Scores[i],
|
|
3891
|
+
hybridScore
|
|
3892
|
+
};
|
|
3893
|
+
});
|
|
3894
|
+
return results.filter((r) => r.hybridScore >= minScore).sort((a, b2) => b2.hybridScore - a.hybridScore);
|
|
3895
|
+
}
|
|
3896
|
+
function rerankChromaResults(query, chromaResults, options = {}) {
|
|
3897
|
+
const ids = chromaResults.ids[0] || [];
|
|
3898
|
+
const documents = chromaResults.documents[0] || [];
|
|
3899
|
+
const metadatas = chromaResults.metadatas[0] || [];
|
|
3900
|
+
const distances = chromaResults.distances[0] || [];
|
|
3901
|
+
if (ids.length === 0) return [];
|
|
3902
|
+
const items = ids.map((id, i) => ({
|
|
3903
|
+
id,
|
|
3904
|
+
document: documents[i],
|
|
3905
|
+
metadata: metadatas[i],
|
|
3906
|
+
distance: distances[i]
|
|
3907
|
+
}));
|
|
3908
|
+
const reranked = hybridRerank(
|
|
3909
|
+
query,
|
|
3910
|
+
items,
|
|
3911
|
+
(item) => item.document || "",
|
|
3912
|
+
// Convert L2 distance to similarity score
|
|
3913
|
+
(item) => 1 / (1 + item.distance),
|
|
3914
|
+
options
|
|
3915
|
+
);
|
|
3916
|
+
return reranked.map((r) => ({
|
|
3917
|
+
id: r.item.id,
|
|
3918
|
+
document: r.item.document,
|
|
3919
|
+
metadata: r.item.metadata,
|
|
3920
|
+
distance: r.item.distance,
|
|
3921
|
+
semanticScore: r.semanticScore,
|
|
3922
|
+
bm25Score: r.bm25Score,
|
|
3923
|
+
hybridScore: r.hybridScore
|
|
3924
|
+
}));
|
|
3925
|
+
}
|
|
3926
|
+
function rerankConversationResults(query, results, options = {}) {
|
|
3927
|
+
if (results.length === 0) return [];
|
|
3928
|
+
const reranked = hybridRerank(
|
|
3929
|
+
query,
|
|
3930
|
+
results,
|
|
3931
|
+
(item) => item.userPrompt || "",
|
|
3932
|
+
(item) => item.similarity || 0,
|
|
3933
|
+
options
|
|
3934
|
+
);
|
|
3935
|
+
return reranked.map((r) => ({
|
|
3936
|
+
...r.item,
|
|
3937
|
+
hybridScore: r.hybridScore,
|
|
3938
|
+
bm25Score: r.bm25Score
|
|
3939
|
+
}));
|
|
3940
|
+
}
|
|
3941
|
+
|
|
3782
3942
|
// src/userResponse/conversation-search.ts
|
|
3783
3943
|
var searchConversations = async ({
|
|
3784
3944
|
userPrompt,
|
|
@@ -3825,8 +3985,93 @@ var searchConversations = async ({
|
|
|
3825
3985
|
return null;
|
|
3826
3986
|
}
|
|
3827
3987
|
};
|
|
3988
|
+
var searchConversationsWithReranking = async (options) => {
|
|
3989
|
+
const {
|
|
3990
|
+
userPrompt,
|
|
3991
|
+
collections,
|
|
3992
|
+
userId,
|
|
3993
|
+
similarityThreshold = 0.6,
|
|
3994
|
+
rerankCandidates = 50,
|
|
3995
|
+
// Fetch more candidates for better reranking
|
|
3996
|
+
hybridOptions = {
|
|
3997
|
+
semanticWeight: 0.7,
|
|
3998
|
+
bm25Weight: 0.3
|
|
3999
|
+
}
|
|
4000
|
+
} = options;
|
|
4001
|
+
try {
|
|
4002
|
+
if (!collections || !collections["conversation-history"]) {
|
|
4003
|
+
logger.info("[ConversationSearch] conversation-history collection not registered, skipping");
|
|
4004
|
+
return null;
|
|
4005
|
+
}
|
|
4006
|
+
if (!collections["conversation-history"]["searchMultiple"]) {
|
|
4007
|
+
logger.info("[ConversationSearch] searchMultiple not available, falling back to standard search");
|
|
4008
|
+
return searchConversations({
|
|
4009
|
+
userPrompt,
|
|
4010
|
+
collections,
|
|
4011
|
+
userId,
|
|
4012
|
+
similarityThreshold
|
|
4013
|
+
});
|
|
4014
|
+
}
|
|
4015
|
+
logger.info(`[ConversationSearch] Hybrid search for: "${userPrompt.substring(0, 50)}..."`);
|
|
4016
|
+
logger.info(`[ConversationSearch] Fetching ${rerankCandidates} candidates for reranking`);
|
|
4017
|
+
logger.info(`[ConversationSearch] Weights - Semantic: ${hybridOptions.semanticWeight}, BM25: ${hybridOptions.bm25Weight}`);
|
|
4018
|
+
const results = await collections["conversation-history"]["searchMultiple"]({
|
|
4019
|
+
userPrompt,
|
|
4020
|
+
userId,
|
|
4021
|
+
limit: rerankCandidates,
|
|
4022
|
+
threshold: 0
|
|
4023
|
+
// No threshold - get all candidates for reranking
|
|
4024
|
+
});
|
|
4025
|
+
if (!results || results.length === 0) {
|
|
4026
|
+
logger.info("[ConversationSearch] No conversations found in database");
|
|
4027
|
+
return null;
|
|
4028
|
+
}
|
|
4029
|
+
logger.info(`[ConversationSearch] Retrieved ${results.length} candidates for reranking`);
|
|
4030
|
+
const candidatesForReranking = results.map((r) => ({
|
|
4031
|
+
...r,
|
|
4032
|
+
userPrompt: r.metadata?.userPrompt || ""
|
|
4033
|
+
}));
|
|
4034
|
+
const reranked = rerankConversationResults(userPrompt, candidatesForReranking, hybridOptions);
|
|
4035
|
+
if (reranked.length === 0) {
|
|
4036
|
+
logger.info("[ConversationSearch] No results after reranking");
|
|
4037
|
+
return null;
|
|
4038
|
+
}
|
|
4039
|
+
const best = reranked[0];
|
|
4040
|
+
const hybridScore = best.hybridScore;
|
|
4041
|
+
const semanticScore = best.similarity || 0;
|
|
4042
|
+
const matchedUserPrompt = best.userPrompt || best.metadata?.userPrompt || "";
|
|
4043
|
+
logger.info(`[ConversationSearch] Best match after reranking:`);
|
|
4044
|
+
logger.info(` - Hybrid score: ${(hybridScore * 100).toFixed(2)}%`);
|
|
4045
|
+
logger.info(` - Semantic score: ${(semanticScore * 100).toFixed(2)}%`);
|
|
4046
|
+
logger.info(` - BM25L score: ${best.bm25Score.toFixed(4)}`);
|
|
4047
|
+
logger.info(` - Matched prompt: "${matchedUserPrompt}"`);
|
|
4048
|
+
logger.info(` - Query prompt: "${userPrompt}"`);
|
|
4049
|
+
if (semanticScore < similarityThreshold) {
|
|
4050
|
+
logger.info(
|
|
4051
|
+
`[ConversationSearch] Semantic score ${(semanticScore * 100).toFixed(2)}% below threshold ${(similarityThreshold * 100).toFixed(2)}% - rejecting match`
|
|
4052
|
+
);
|
|
4053
|
+
return null;
|
|
4054
|
+
}
|
|
4055
|
+
logger.info(
|
|
4056
|
+
`[ConversationSearch] \u2713 Found match with semantic score ${(semanticScore * 100).toFixed(2)}%`
|
|
4057
|
+
);
|
|
4058
|
+
logger.info(` - Returning cached result for: "${matchedUserPrompt}"`);
|
|
4059
|
+
return {
|
|
4060
|
+
uiBlock: best.uiBlock,
|
|
4061
|
+
similarity: semanticScore,
|
|
4062
|
+
hybridScore,
|
|
4063
|
+
bm25Score: best.bm25Score,
|
|
4064
|
+
metadata: best.metadata
|
|
4065
|
+
};
|
|
4066
|
+
} catch (error) {
|
|
4067
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4068
|
+
logger.warn(`[ConversationSearch] Error in hybrid search: ${errorMsg}`);
|
|
4069
|
+
return null;
|
|
4070
|
+
}
|
|
4071
|
+
};
|
|
3828
4072
|
var ConversationSearch = {
|
|
3829
|
-
searchConversations
|
|
4073
|
+
searchConversations,
|
|
4074
|
+
searchConversationsWithReranking
|
|
3830
4075
|
};
|
|
3831
4076
|
var conversation_search_default = ConversationSearch;
|
|
3832
4077
|
|
|
@@ -3875,7 +4120,7 @@ var BaseLLM = class {
|
|
|
3875
4120
|
* @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
|
|
3876
4121
|
* @returns Object containing matched components, layout title/description, and follow-up actions
|
|
3877
4122
|
*/
|
|
3878
|
-
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback) {
|
|
4123
|
+
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
|
|
3879
4124
|
try {
|
|
3880
4125
|
logger.debug(`[${this.getProviderName()}] Starting component matching from text response`);
|
|
3881
4126
|
let availableComponentsText = "No components available";
|
|
@@ -3891,12 +4136,44 @@ var BaseLLM = class {
|
|
|
3891
4136
|
Props Structure: ${propsPreview}`;
|
|
3892
4137
|
}).join("\n\n");
|
|
3893
4138
|
}
|
|
4139
|
+
let deferredToolsText = "No deferred external tools for this request.";
|
|
4140
|
+
if (deferredTools && deferredTools.length > 0) {
|
|
4141
|
+
logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools to component matching`);
|
|
4142
|
+
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) => {
|
|
4143
|
+
return `${idx + 1}. **${tool.name}**
|
|
4144
|
+
toolId: "${tool.id}" (USE THIS EXACT VALUE - do not modify!)
|
|
4145
|
+
toolName: "${tool.name}"
|
|
4146
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
4147
|
+
requiredFields:
|
|
4148
|
+
${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
4149
|
+
}).join("\n\n");
|
|
4150
|
+
}
|
|
4151
|
+
let executedToolsText = "No external tools were executed for data fetching.";
|
|
4152
|
+
if (executedTools && executedTools.length > 0) {
|
|
4153
|
+
logger.info(`[${this.getProviderName()}] Passing ${executedTools.length} executed tools to component matching`);
|
|
4154
|
+
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) => {
|
|
4155
|
+
let resultPreview = "No result data";
|
|
4156
|
+
if (tool.result) {
|
|
4157
|
+
const resultStr = typeof tool.result === "string" ? tool.result : JSON.stringify(tool.result, null, 2);
|
|
4158
|
+
resultPreview = resultStr.length > 2e3 ? resultStr.substring(0, 2e3) + "\n... (truncated)" : resultStr;
|
|
4159
|
+
}
|
|
4160
|
+
return `${idx + 1}. **${tool.name}**
|
|
4161
|
+
toolId: "${tool.id}" (USE THIS EXACT VALUE for externalTool.toolId)
|
|
4162
|
+
toolName: "${tool.name}" (USE THIS EXACT VALUE for externalTool.toolName)
|
|
4163
|
+
parameters: ${JSON.stringify(tool.params || {})} (USE THESE for externalTool.parameters)
|
|
4164
|
+
result: ${resultPreview}`;
|
|
4165
|
+
}).join("\n\n");
|
|
4166
|
+
}
|
|
3894
4167
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
3895
4168
|
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
4169
|
+
logger.file("\n=============================\nDeferred tools:", deferredToolsText);
|
|
4170
|
+
logger.file("\n=============================\nExecuted tools:", executedToolsText);
|
|
3896
4171
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
3897
4172
|
ANALYSIS_CONTENT: analysisContent,
|
|
3898
4173
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
3899
|
-
SCHEMA_DOC: schemaDoc
|
|
4174
|
+
SCHEMA_DOC: schemaDoc,
|
|
4175
|
+
DEFERRED_TOOLS: deferredToolsText,
|
|
4176
|
+
EXECUTED_TOOLS: executedToolsText
|
|
3900
4177
|
});
|
|
3901
4178
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
3902
4179
|
logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
|
|
@@ -4016,9 +4293,6 @@ var BaseLLM = class {
|
|
|
4016
4293
|
matchedComponents.forEach((comp, idx) => {
|
|
4017
4294
|
logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
|
|
4018
4295
|
});
|
|
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
4296
|
logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
|
|
4023
4297
|
const rawActions = result.actions || [];
|
|
4024
4298
|
const actions = convertQuestionsToActions(rawActions);
|
|
@@ -4240,21 +4514,44 @@ var BaseLLM = class {
|
|
|
4240
4514
|
let availableToolsDoc = "No external tools are available for this request.";
|
|
4241
4515
|
if (externalTools && externalTools.length > 0) {
|
|
4242
4516
|
logger.info(`[${this.getProviderName()}] External tools available: ${externalTools.map((t) => t.name).join(", ")}`);
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
}
|
|
4249
|
-
|
|
4517
|
+
const immediateTools = externalTools.filter((t) => t.executionType === "immediate" || t.executionType === "deferred" && t.userProvidedData);
|
|
4518
|
+
const deferredTools = externalTools.filter((t) => t.executionType === "deferred" && !t.userProvidedData);
|
|
4519
|
+
let toolsDocParts = [];
|
|
4520
|
+
if (immediateTools.length > 0) {
|
|
4521
|
+
const immediateDoc = "## IMMEDIATE EXECUTION TOOLS\nExecute these tools right away:\n\n" + immediateTools.map((tool, idx) => {
|
|
4522
|
+
const paramsText = Object.entries(tool.params || {}).map(([key, value]) => {
|
|
4523
|
+
const valueType = typeof value;
|
|
4524
|
+
if (valueType === "string" && ["string", "number", "integer", "boolean", "array", "object"].includes(String(value).toLowerCase())) {
|
|
4525
|
+
return `- ${key}: ${value}`;
|
|
4526
|
+
} else {
|
|
4527
|
+
return `- ${key}: ${JSON.stringify(value)} (default value - use this)`;
|
|
4528
|
+
}
|
|
4529
|
+
}).join("\n ");
|
|
4530
|
+
let userDataText = "";
|
|
4531
|
+
if (tool.userProvidedData) {
|
|
4532
|
+
userDataText = "\n **User Provided Data** (use these values):\n " + Object.entries(tool.userProvidedData).map(([key, value]) => `- ${key}: ${JSON.stringify(value)}`).join("\n ");
|
|
4250
4533
|
}
|
|
4251
|
-
|
|
4252
|
-
|
|
4534
|
+
return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
|
|
4535
|
+
Execution Type: IMMEDIATE
|
|
4253
4536
|
Description: ${tool.description}
|
|
4254
|
-
**ACTION REQUIRED**: Call this tool with the parameters below
|
|
4255
4537
|
Parameters:
|
|
4256
|
-
${paramsText}`;
|
|
4257
|
-
|
|
4538
|
+
${paramsText}${userDataText}`;
|
|
4539
|
+
}).join("\n\n");
|
|
4540
|
+
toolsDocParts.push(immediateDoc);
|
|
4541
|
+
}
|
|
4542
|
+
if (deferredTools.length > 0) {
|
|
4543
|
+
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) => {
|
|
4544
|
+
const requiredFieldsText = (tool.requiredFields || []).map((f) => `- ${f.label || f.name} (${f.type})${f.required ? " *required*" : ""}`).join("\n ");
|
|
4545
|
+
return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
|
|
4546
|
+
Execution Type: DEFERRED (needs form input)
|
|
4547
|
+
Description: ${tool.description}
|
|
4548
|
+
Reason: ${tool.executionReason || "Write operation requires user confirmation"}
|
|
4549
|
+
Required Fields:
|
|
4550
|
+
${requiredFieldsText || "(fields will be determined by form)"}`;
|
|
4551
|
+
}).join("\n\n");
|
|
4552
|
+
toolsDocParts.push(deferredDoc);
|
|
4553
|
+
}
|
|
4554
|
+
availableToolsDoc = toolsDocParts.join("\n\n---\n\n");
|
|
4258
4555
|
}
|
|
4259
4556
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
4260
4557
|
const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
|
|
@@ -4295,8 +4592,12 @@ var BaseLLM = class {
|
|
|
4295
4592
|
}
|
|
4296
4593
|
}];
|
|
4297
4594
|
if (externalTools && externalTools.length > 0) {
|
|
4298
|
-
externalTools.
|
|
4299
|
-
|
|
4595
|
+
const executableTools = externalTools.filter(
|
|
4596
|
+
(t) => t.executionType === "immediate" || t.executionType === "deferred" && t.userProvidedData
|
|
4597
|
+
);
|
|
4598
|
+
logger.info(`[${this.getProviderName()}] Executable tools: ${executableTools.length} of ${externalTools.length} total`);
|
|
4599
|
+
executableTools.forEach((tool) => {
|
|
4600
|
+
logger.info(`[${this.getProviderName()}] Processing executable tool:`, JSON.stringify(tool, null, 2));
|
|
4300
4601
|
const properties = {};
|
|
4301
4602
|
const required = [];
|
|
4302
4603
|
Object.entries(tool.params || {}).forEach(([key, typeOrValue]) => {
|
|
@@ -4365,13 +4666,14 @@ var BaseLLM = class {
|
|
|
4365
4666
|
input_schema: inputSchema
|
|
4366
4667
|
});
|
|
4367
4668
|
});
|
|
4368
|
-
logger.info(`[${this.getProviderName()}] Added ${
|
|
4669
|
+
logger.info(`[${this.getProviderName()}] Added ${executableTools.length} executable tools to tool calling capability (${externalTools.length - executableTools.length} deferred tools await form input)`);
|
|
4369
4670
|
logger.info(`[${this.getProviderName()}] Complete tools array:`, JSON.stringify(tools, null, 2));
|
|
4370
4671
|
}
|
|
4371
4672
|
const queryAttempts = /* @__PURE__ */ new Map();
|
|
4372
4673
|
const MAX_QUERY_ATTEMPTS = 6;
|
|
4373
4674
|
const toolAttempts = /* @__PURE__ */ new Map();
|
|
4374
4675
|
const MAX_TOOL_ATTEMPTS = 3;
|
|
4676
|
+
const executedToolsList = [];
|
|
4375
4677
|
let maxAttemptsReached = false;
|
|
4376
4678
|
let fullStreamedText = "";
|
|
4377
4679
|
const wrappedStreamCallback = streamCallback ? (chunk) => {
|
|
@@ -4554,6 +4856,17 @@ Please try rephrasing your request or contact support.
|
|
|
4554
4856
|
const result2 = await externalTool.fn(toolInput);
|
|
4555
4857
|
logger.info(`[${this.getProviderName()}] External tool ${externalTool.name} executed successfully`);
|
|
4556
4858
|
logCollector?.info(`\u2713 ${externalTool.name} executed successfully`);
|
|
4859
|
+
if (!executedToolsList.find((t) => t.id === externalTool.id)) {
|
|
4860
|
+
executedToolsList.push({
|
|
4861
|
+
id: externalTool.id,
|
|
4862
|
+
name: externalTool.name,
|
|
4863
|
+
params: toolInput,
|
|
4864
|
+
// The actual parameters used in this execution
|
|
4865
|
+
result: result2
|
|
4866
|
+
// Store the actual result data for populating deferred tool params
|
|
4867
|
+
});
|
|
4868
|
+
logger.info(`[${this.getProviderName()}] Tracked executed tool: ${externalTool.name} with params: ${JSON.stringify(toolInput)}`);
|
|
4869
|
+
}
|
|
4557
4870
|
if (wrappedStreamCallback) {
|
|
4558
4871
|
wrappedStreamCallback(`\u2705 **${externalTool.name} completed successfully**
|
|
4559
4872
|
|
|
@@ -4643,12 +4956,31 @@ ${errorMsg}
|
|
|
4643
4956
|
wrappedStreamCallback(answerMarker);
|
|
4644
4957
|
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
4645
4958
|
} : void 0;
|
|
4959
|
+
const deferredTools = externalTools?.filter((t) => {
|
|
4960
|
+
if (t.executionType === "deferred" && !t.userProvidedData) return true;
|
|
4961
|
+
if (category === "data_modification" && !t.userProvidedData) {
|
|
4962
|
+
const name = (t.name || t.id || "").toLowerCase();
|
|
4963
|
+
const isWriteOperation = /create|add|insert|new|update|edit|modify|delete|remove|send/.test(name);
|
|
4964
|
+
if (isWriteOperation) {
|
|
4965
|
+
logger.info(`[${this.getProviderName()}] Inferred deferred execution for tool: ${t.name}`);
|
|
4966
|
+
return true;
|
|
4967
|
+
}
|
|
4968
|
+
}
|
|
4969
|
+
return false;
|
|
4970
|
+
}) || [];
|
|
4971
|
+
if (deferredTools.length > 0) {
|
|
4972
|
+
logger.info(`[${this.getProviderName()}] Passing ${deferredTools.length} deferred tools for Form generation`);
|
|
4973
|
+
}
|
|
4974
|
+
logger.info(`[${this.getProviderName()}] passing deferred tools to the matching function: ${JSON.stringify(deferredTools, null, 2)}`);
|
|
4975
|
+
logger.info(`[${this.getProviderName()}] passing executed tools to the matching function: ${JSON.stringify(executedToolsList, null, 2)}`);
|
|
4646
4976
|
const matchResult = await this.matchComponentsFromAnalysis(
|
|
4647
4977
|
textResponse,
|
|
4648
4978
|
components,
|
|
4649
4979
|
apiKey,
|
|
4650
4980
|
logCollector,
|
|
4651
|
-
componentStreamCallback
|
|
4981
|
+
componentStreamCallback,
|
|
4982
|
+
deferredTools,
|
|
4983
|
+
executedToolsList
|
|
4652
4984
|
);
|
|
4653
4985
|
matchedComponents = matchResult.components;
|
|
4654
4986
|
layoutTitle = matchResult.layoutTitle;
|
|
@@ -4717,23 +5049,20 @@ ${errorMsg}
|
|
|
4717
5049
|
*/
|
|
4718
5050
|
async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "text", streamCallback, collections, externalTools, userId) {
|
|
4719
5051
|
const startTime = Date.now();
|
|
4720
|
-
logger.info(`[${this.getProviderName()}] handleUserRequest called
|
|
5052
|
+
logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
|
|
4721
5053
|
logCollector?.info(`Starting request processing with mode: ${responseMode}`);
|
|
4722
5054
|
try {
|
|
4723
5055
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
4724
5056
|
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
4725
|
-
const conversationMatch = await conversation_search_default.
|
|
5057
|
+
const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
|
|
4726
5058
|
userPrompt,
|
|
4727
5059
|
collections,
|
|
4728
5060
|
userId,
|
|
4729
5061
|
similarityThreshold: 0.6
|
|
4730
5062
|
// 60% threshold
|
|
4731
5063
|
});
|
|
4732
|
-
logger.info("conversationMatch:", conversationMatch);
|
|
4733
5064
|
if (conversationMatch) {
|
|
4734
|
-
logger.info(
|
|
4735
|
-
`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`
|
|
4736
|
-
);
|
|
5065
|
+
logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
|
|
4737
5066
|
logCollector?.info(
|
|
4738
5067
|
`\u2713 Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`
|
|
4739
5068
|
);
|
|
@@ -4741,7 +5070,6 @@ ${errorMsg}
|
|
|
4741
5070
|
const isValidComponent = rawComponent && typeof rawComponent === "object" && Object.keys(rawComponent).length > 0;
|
|
4742
5071
|
const component = isValidComponent ? rawComponent : null;
|
|
4743
5072
|
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
5073
|
if (this.containsFormComponent(component)) {
|
|
4746
5074
|
logger.info(`[${this.getProviderName()}] Skipping cached result - Form components contain stale defaultValues, fetching fresh data`);
|
|
4747
5075
|
logCollector?.info("Skipping cache for form - fetching current values from database...");
|
|
@@ -4839,22 +5167,31 @@ ${errorMsg}
|
|
|
4839
5167
|
if (categoryClassification.externalTools && categoryClassification.externalTools.length > 0) {
|
|
4840
5168
|
logger.info(`[${this.getProviderName()}] Identified ${categoryClassification.externalTools.length} external tools needed`);
|
|
4841
5169
|
logCollector?.info(`Identified external tools: ${categoryClassification.externalTools.map((t) => t.name || t.type).join(", ")}`);
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
5170
|
+
logger.info(`[${this.getProviderName()}] Raw external tools from classification: ${JSON.stringify(categoryClassification.externalTools, null, 2)}`);
|
|
5171
|
+
toolsToUse = categoryClassification.externalTools?.map((t) => {
|
|
5172
|
+
const realTool = externalTools?.find((tool) => tool.id === t.type);
|
|
5173
|
+
logger.info(`[${this.getProviderName()}] Tool ${t.name}: executionType=${t.executionType}, userProvidedData=${t.userProvidedData ? "present" : "null"}`);
|
|
5174
|
+
return {
|
|
5175
|
+
id: t.type,
|
|
5176
|
+
name: t.name,
|
|
5177
|
+
description: t.description,
|
|
5178
|
+
params: t.parameters || {},
|
|
5179
|
+
// NEW: Include execution type info from category classification
|
|
5180
|
+
executionType: t.executionType || "immediate",
|
|
5181
|
+
executionReason: t.executionReason || "",
|
|
5182
|
+
requiredFields: t.requiredFields || [],
|
|
5183
|
+
userProvidedData: t.userProvidedData || null,
|
|
5184
|
+
fn: (() => {
|
|
5185
|
+
if (realTool) {
|
|
5186
|
+
logger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);
|
|
5187
|
+
return realTool.fn;
|
|
5188
|
+
} else {
|
|
5189
|
+
logger.warn(`[${this.getProviderName()}] Tool ${t.type} not found in registered tools`);
|
|
5190
|
+
return async () => ({ success: false, message: `Tool ${t.name || t.type} not registered` });
|
|
5191
|
+
}
|
|
5192
|
+
})()
|
|
5193
|
+
};
|
|
5194
|
+
}) || [];
|
|
4858
5195
|
}
|
|
4859
5196
|
if (categoryClassification.category === "general") {
|
|
4860
5197
|
logger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);
|
|
@@ -5545,7 +5882,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
5545
5882
|
}
|
|
5546
5883
|
logCollector.info(`Starting user prompt request with ${components.length} components`);
|
|
5547
5884
|
const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId);
|
|
5548
|
-
logger.info("conversationHistory", conversationHistory);
|
|
5549
5885
|
const responseMode = payload.responseMode || "component";
|
|
5550
5886
|
logger.info("responseMode", responseMode);
|
|
5551
5887
|
let streamCallback;
|
|
@@ -9482,6 +9818,7 @@ var SuperatomSDK = class {
|
|
|
9482
9818
|
}
|
|
9483
9819
|
};
|
|
9484
9820
|
export {
|
|
9821
|
+
BM25L,
|
|
9485
9822
|
CONTEXT_CONFIG,
|
|
9486
9823
|
CleanupService,
|
|
9487
9824
|
LLM,
|
|
@@ -9493,6 +9830,9 @@ export {
|
|
|
9493
9830
|
UIBlock,
|
|
9494
9831
|
UILogCollector,
|
|
9495
9832
|
UserManager,
|
|
9496
|
-
|
|
9833
|
+
hybridRerank,
|
|
9834
|
+
logger,
|
|
9835
|
+
rerankChromaResults,
|
|
9836
|
+
rerankConversationResults
|
|
9497
9837
|
};
|
|
9498
9838
|
//# sourceMappingURL=index.mjs.map
|