@superatomai/sdk-node 0.0.23 → 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 +258 -1
- package/dist/index.d.ts +258 -1
- package/dist/index.js +879 -48
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +874 -47
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -662,6 +662,36 @@ var BookmarksRequestMessageSchema = z3.object({
|
|
|
662
662
|
type: z3.literal("BOOKMARKS"),
|
|
663
663
|
payload: BookmarksRequestPayloadSchema
|
|
664
664
|
});
|
|
665
|
+
var KbNodesQueryFiltersSchema = z3.object({
|
|
666
|
+
query: z3.string().optional(),
|
|
667
|
+
category: z3.string().optional(),
|
|
668
|
+
tags: z3.array(z3.string()).optional(),
|
|
669
|
+
createdBy: z3.number().optional()
|
|
670
|
+
});
|
|
671
|
+
var KbNodesRequestPayloadSchema = z3.object({
|
|
672
|
+
operation: z3.enum(["create", "update", "delete", "getAll", "getOne", "search", "getByCategory", "getByUser", "getCategories", "getTags"]),
|
|
673
|
+
data: z3.object({
|
|
674
|
+
id: z3.number().optional(),
|
|
675
|
+
title: z3.string().optional(),
|
|
676
|
+
content: z3.string().optional(),
|
|
677
|
+
category: z3.string().optional(),
|
|
678
|
+
tags: z3.array(z3.string()).optional(),
|
|
679
|
+
createdBy: z3.number().optional(),
|
|
680
|
+
updatedBy: z3.number().optional(),
|
|
681
|
+
userId: z3.number().optional(),
|
|
682
|
+
// Query/search operation fields
|
|
683
|
+
query: z3.string().optional(),
|
|
684
|
+
filters: KbNodesQueryFiltersSchema.optional(),
|
|
685
|
+
limit: z3.number().optional(),
|
|
686
|
+
offset: z3.number().optional()
|
|
687
|
+
}).optional()
|
|
688
|
+
});
|
|
689
|
+
var KbNodesRequestMessageSchema = z3.object({
|
|
690
|
+
id: z3.string(),
|
|
691
|
+
from: MessageParticipantSchema,
|
|
692
|
+
type: z3.literal("KB_NODES"),
|
|
693
|
+
payload: KbNodesRequestPayloadSchema
|
|
694
|
+
});
|
|
665
695
|
|
|
666
696
|
// src/utils/logger.ts
|
|
667
697
|
import fs from "fs";
|
|
@@ -3749,6 +3779,166 @@ var KB = {
|
|
|
3749
3779
|
};
|
|
3750
3780
|
var knowledge_base_default = KB;
|
|
3751
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
|
+
|
|
3752
3942
|
// src/userResponse/conversation-search.ts
|
|
3753
3943
|
var searchConversations = async ({
|
|
3754
3944
|
userPrompt,
|
|
@@ -3795,8 +3985,93 @@ var searchConversations = async ({
|
|
|
3795
3985
|
return null;
|
|
3796
3986
|
}
|
|
3797
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
|
+
};
|
|
3798
4072
|
var ConversationSearch = {
|
|
3799
|
-
searchConversations
|
|
4073
|
+
searchConversations,
|
|
4074
|
+
searchConversationsWithReranking
|
|
3800
4075
|
};
|
|
3801
4076
|
var conversation_search_default = ConversationSearch;
|
|
3802
4077
|
|
|
@@ -3845,7 +4120,7 @@ var BaseLLM = class {
|
|
|
3845
4120
|
* @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
|
|
3846
4121
|
* @returns Object containing matched components, layout title/description, and follow-up actions
|
|
3847
4122
|
*/
|
|
3848
|
-
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback) {
|
|
4123
|
+
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback, deferredTools, executedTools) {
|
|
3849
4124
|
try {
|
|
3850
4125
|
logger.debug(`[${this.getProviderName()}] Starting component matching from text response`);
|
|
3851
4126
|
let availableComponentsText = "No components available";
|
|
@@ -3861,12 +4136,44 @@ var BaseLLM = class {
|
|
|
3861
4136
|
Props Structure: ${propsPreview}`;
|
|
3862
4137
|
}).join("\n\n");
|
|
3863
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
|
+
}
|
|
3864
4167
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
3865
4168
|
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
4169
|
+
logger.file("\n=============================\nDeferred tools:", deferredToolsText);
|
|
4170
|
+
logger.file("\n=============================\nExecuted tools:", executedToolsText);
|
|
3866
4171
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
3867
4172
|
ANALYSIS_CONTENT: analysisContent,
|
|
3868
4173
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
3869
|
-
SCHEMA_DOC: schemaDoc
|
|
4174
|
+
SCHEMA_DOC: schemaDoc,
|
|
4175
|
+
DEFERRED_TOOLS: deferredToolsText,
|
|
4176
|
+
EXECUTED_TOOLS: executedToolsText
|
|
3870
4177
|
});
|
|
3871
4178
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
3872
4179
|
logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
|
|
@@ -3986,9 +4293,6 @@ var BaseLLM = class {
|
|
|
3986
4293
|
matchedComponents.forEach((comp, idx) => {
|
|
3987
4294
|
logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
|
|
3988
4295
|
});
|
|
3989
|
-
if (suggestedComponents.length !== matchedComponents.length) {
|
|
3990
|
-
logger.warn(`[${this.getProviderName()}] \u26A0\uFE0F MISMATCH: Text suggested ${suggestedComponents.length} components, but LLM matched ${matchedComponents.length}`);
|
|
3991
|
-
}
|
|
3992
4296
|
logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
|
|
3993
4297
|
const rawActions = result.actions || [];
|
|
3994
4298
|
const actions = convertQuestionsToActions(rawActions);
|
|
@@ -4210,21 +4514,44 @@ var BaseLLM = class {
|
|
|
4210
4514
|
let availableToolsDoc = "No external tools are available for this request.";
|
|
4211
4515
|
if (externalTools && externalTools.length > 0) {
|
|
4212
4516
|
logger.info(`[${this.getProviderName()}] External tools available: ${externalTools.map((t) => t.name).join(", ")}`);
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
}
|
|
4219
|
-
|
|
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 ");
|
|
4220
4533
|
}
|
|
4221
|
-
|
|
4222
|
-
|
|
4534
|
+
return `${idx + 1}. **${tool.name}** (ID: ${tool.id})
|
|
4535
|
+
Execution Type: IMMEDIATE
|
|
4223
4536
|
Description: ${tool.description}
|
|
4224
|
-
**ACTION REQUIRED**: Call this tool with the parameters below
|
|
4225
4537
|
Parameters:
|
|
4226
|
-
${paramsText}`;
|
|
4227
|
-
|
|
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");
|
|
4228
4555
|
}
|
|
4229
4556
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
4230
4557
|
const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
|
|
@@ -4265,8 +4592,12 @@ var BaseLLM = class {
|
|
|
4265
4592
|
}
|
|
4266
4593
|
}];
|
|
4267
4594
|
if (externalTools && externalTools.length > 0) {
|
|
4268
|
-
externalTools.
|
|
4269
|
-
|
|
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));
|
|
4270
4601
|
const properties = {};
|
|
4271
4602
|
const required = [];
|
|
4272
4603
|
Object.entries(tool.params || {}).forEach(([key, typeOrValue]) => {
|
|
@@ -4335,13 +4666,14 @@ var BaseLLM = class {
|
|
|
4335
4666
|
input_schema: inputSchema
|
|
4336
4667
|
});
|
|
4337
4668
|
});
|
|
4338
|
-
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)`);
|
|
4339
4670
|
logger.info(`[${this.getProviderName()}] Complete tools array:`, JSON.stringify(tools, null, 2));
|
|
4340
4671
|
}
|
|
4341
4672
|
const queryAttempts = /* @__PURE__ */ new Map();
|
|
4342
4673
|
const MAX_QUERY_ATTEMPTS = 6;
|
|
4343
4674
|
const toolAttempts = /* @__PURE__ */ new Map();
|
|
4344
4675
|
const MAX_TOOL_ATTEMPTS = 3;
|
|
4676
|
+
const executedToolsList = [];
|
|
4345
4677
|
let maxAttemptsReached = false;
|
|
4346
4678
|
let fullStreamedText = "";
|
|
4347
4679
|
const wrappedStreamCallback = streamCallback ? (chunk) => {
|
|
@@ -4524,6 +4856,17 @@ Please try rephrasing your request or contact support.
|
|
|
4524
4856
|
const result2 = await externalTool.fn(toolInput);
|
|
4525
4857
|
logger.info(`[${this.getProviderName()}] External tool ${externalTool.name} executed successfully`);
|
|
4526
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
|
+
}
|
|
4527
4870
|
if (wrappedStreamCallback) {
|
|
4528
4871
|
wrappedStreamCallback(`\u2705 **${externalTool.name} completed successfully**
|
|
4529
4872
|
|
|
@@ -4613,12 +4956,31 @@ ${errorMsg}
|
|
|
4613
4956
|
wrappedStreamCallback(answerMarker);
|
|
4614
4957
|
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
4615
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)}`);
|
|
4616
4976
|
const matchResult = await this.matchComponentsFromAnalysis(
|
|
4617
4977
|
textResponse,
|
|
4618
4978
|
components,
|
|
4619
4979
|
apiKey,
|
|
4620
4980
|
logCollector,
|
|
4621
|
-
componentStreamCallback
|
|
4981
|
+
componentStreamCallback,
|
|
4982
|
+
deferredTools,
|
|
4983
|
+
executedToolsList
|
|
4622
4984
|
);
|
|
4623
4985
|
matchedComponents = matchResult.components;
|
|
4624
4986
|
layoutTitle = matchResult.layoutTitle;
|
|
@@ -4687,23 +5049,20 @@ ${errorMsg}
|
|
|
4687
5049
|
*/
|
|
4688
5050
|
async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "text", streamCallback, collections, externalTools, userId) {
|
|
4689
5051
|
const startTime = Date.now();
|
|
4690
|
-
logger.info(`[${this.getProviderName()}] handleUserRequest called
|
|
5052
|
+
logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
|
|
4691
5053
|
logCollector?.info(`Starting request processing with mode: ${responseMode}`);
|
|
4692
5054
|
try {
|
|
4693
5055
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
4694
5056
|
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
4695
|
-
const conversationMatch = await conversation_search_default.
|
|
5057
|
+
const conversationMatch = await conversation_search_default.searchConversationsWithReranking({
|
|
4696
5058
|
userPrompt,
|
|
4697
5059
|
collections,
|
|
4698
5060
|
userId,
|
|
4699
5061
|
similarityThreshold: 0.6
|
|
4700
5062
|
// 60% threshold
|
|
4701
5063
|
});
|
|
4702
|
-
logger.info("conversationMatch:", conversationMatch);
|
|
4703
5064
|
if (conversationMatch) {
|
|
4704
|
-
logger.info(
|
|
4705
|
-
`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`
|
|
4706
|
-
);
|
|
5065
|
+
logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
|
|
4707
5066
|
logCollector?.info(
|
|
4708
5067
|
`\u2713 Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`
|
|
4709
5068
|
);
|
|
@@ -4711,7 +5070,6 @@ ${errorMsg}
|
|
|
4711
5070
|
const isValidComponent = rawComponent && typeof rawComponent === "object" && Object.keys(rawComponent).length > 0;
|
|
4712
5071
|
const component = isValidComponent ? rawComponent : null;
|
|
4713
5072
|
const cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || "";
|
|
4714
|
-
logger.debug(`[${this.getProviderName()}] Cached component: ${component ? "present" : "null"}, cachedTextResponse: ${cachedTextResponse ? cachedTextResponse.substring(0, 50) + "..." : "empty"}`);
|
|
4715
5073
|
if (this.containsFormComponent(component)) {
|
|
4716
5074
|
logger.info(`[${this.getProviderName()}] Skipping cached result - Form components contain stale defaultValues, fetching fresh data`);
|
|
4717
5075
|
logCollector?.info("Skipping cache for form - fetching current values from database...");
|
|
@@ -4809,22 +5167,31 @@ ${errorMsg}
|
|
|
4809
5167
|
if (categoryClassification.externalTools && categoryClassification.externalTools.length > 0) {
|
|
4810
5168
|
logger.info(`[${this.getProviderName()}] Identified ${categoryClassification.externalTools.length} external tools needed`);
|
|
4811
5169
|
logCollector?.info(`Identified external tools: ${categoryClassification.externalTools.map((t) => t.name || t.type).join(", ")}`);
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
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
|
+
}) || [];
|
|
4828
5195
|
}
|
|
4829
5196
|
if (categoryClassification.category === "general") {
|
|
4830
5197
|
logger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);
|
|
@@ -5515,7 +5882,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
5515
5882
|
}
|
|
5516
5883
|
logCollector.info(`Starting user prompt request with ${components.length} components`);
|
|
5517
5884
|
const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId);
|
|
5518
|
-
logger.info("conversationHistory", conversationHistory);
|
|
5519
5885
|
const responseMode = payload.responseMode || "component";
|
|
5520
5886
|
logger.info("responseMode", responseMode);
|
|
5521
5887
|
let streamCallback;
|
|
@@ -7845,6 +8211,458 @@ function sendResponse7(id, res, sendMessage, clientId) {
|
|
|
7845
8211
|
sendMessage(response);
|
|
7846
8212
|
}
|
|
7847
8213
|
|
|
8214
|
+
// src/handlers/kb-nodes.ts
|
|
8215
|
+
async function handleKbNodesRequest(data, collections, sendMessage) {
|
|
8216
|
+
const executeCollection = async (collection, op, params) => {
|
|
8217
|
+
const handler = collections[collection]?.[op];
|
|
8218
|
+
if (!handler) {
|
|
8219
|
+
throw new Error(`Collection '${collection}' or operation '${op}' not found`);
|
|
8220
|
+
}
|
|
8221
|
+
return await handler(params);
|
|
8222
|
+
};
|
|
8223
|
+
try {
|
|
8224
|
+
const request = KbNodesRequestMessageSchema.parse(data);
|
|
8225
|
+
const { id, payload, from } = request;
|
|
8226
|
+
const { operation, data: requestData } = payload;
|
|
8227
|
+
const nodeId = requestData?.id;
|
|
8228
|
+
const title = requestData?.title;
|
|
8229
|
+
const content = requestData?.content;
|
|
8230
|
+
const category = requestData?.category;
|
|
8231
|
+
const tags = requestData?.tags;
|
|
8232
|
+
const createdBy = requestData?.createdBy;
|
|
8233
|
+
const updatedBy = requestData?.updatedBy;
|
|
8234
|
+
const userId = requestData?.userId;
|
|
8235
|
+
const query = requestData?.query;
|
|
8236
|
+
const filters = requestData?.filters;
|
|
8237
|
+
const limit = requestData?.limit;
|
|
8238
|
+
const offset = requestData?.offset;
|
|
8239
|
+
switch (operation) {
|
|
8240
|
+
case "create":
|
|
8241
|
+
await handleCreate6(id, { title, content, category, tags, createdBy }, executeCollection, sendMessage, from.id);
|
|
8242
|
+
break;
|
|
8243
|
+
case "update":
|
|
8244
|
+
await handleUpdate6(id, nodeId, { title, content, category, tags, updatedBy }, executeCollection, sendMessage, from.id);
|
|
8245
|
+
break;
|
|
8246
|
+
case "delete":
|
|
8247
|
+
await handleDelete6(id, nodeId, executeCollection, sendMessage, from.id);
|
|
8248
|
+
break;
|
|
8249
|
+
case "getAll":
|
|
8250
|
+
await handleGetAll6(id, limit, offset, executeCollection, sendMessage, from.id);
|
|
8251
|
+
break;
|
|
8252
|
+
case "getOne":
|
|
8253
|
+
await handleGetOne6(id, nodeId, executeCollection, sendMessage, from.id);
|
|
8254
|
+
break;
|
|
8255
|
+
case "search":
|
|
8256
|
+
await handleSearch(id, { query, category, tags, createdBy, limit, offset }, executeCollection, sendMessage, from.id);
|
|
8257
|
+
break;
|
|
8258
|
+
case "getByCategory":
|
|
8259
|
+
await handleGetByCategory(id, category, limit, offset, executeCollection, sendMessage, from.id);
|
|
8260
|
+
break;
|
|
8261
|
+
case "getByUser":
|
|
8262
|
+
await handleGetByUser(id, userId, limit, offset, executeCollection, sendMessage, from.id);
|
|
8263
|
+
break;
|
|
8264
|
+
case "getCategories":
|
|
8265
|
+
await handleGetCategories(id, executeCollection, sendMessage, from.id);
|
|
8266
|
+
break;
|
|
8267
|
+
case "getTags":
|
|
8268
|
+
await handleGetTags(id, executeCollection, sendMessage, from.id);
|
|
8269
|
+
break;
|
|
8270
|
+
default:
|
|
8271
|
+
sendResponse8(id, {
|
|
8272
|
+
success: false,
|
|
8273
|
+
error: `Unknown operation: ${operation}`
|
|
8274
|
+
}, sendMessage, from.id);
|
|
8275
|
+
}
|
|
8276
|
+
} catch (error) {
|
|
8277
|
+
logger.error("Failed to handle KB nodes request:", error);
|
|
8278
|
+
sendResponse8(null, {
|
|
8279
|
+
success: false,
|
|
8280
|
+
error: error instanceof Error ? error.message : "Unknown error occurred"
|
|
8281
|
+
}, sendMessage);
|
|
8282
|
+
}
|
|
8283
|
+
}
|
|
8284
|
+
async function handleCreate6(id, nodeData, executeCollection, sendMessage, clientId) {
|
|
8285
|
+
const { title, content, category, tags, createdBy } = nodeData;
|
|
8286
|
+
if (!title || title.trim().length === 0) {
|
|
8287
|
+
sendResponse8(id, {
|
|
8288
|
+
success: false,
|
|
8289
|
+
error: "Title is required and cannot be empty"
|
|
8290
|
+
}, sendMessage, clientId);
|
|
8291
|
+
return;
|
|
8292
|
+
}
|
|
8293
|
+
if (!content || content.trim().length === 0) {
|
|
8294
|
+
sendResponse8(id, {
|
|
8295
|
+
success: false,
|
|
8296
|
+
error: "Content is required and cannot be empty"
|
|
8297
|
+
}, sendMessage, clientId);
|
|
8298
|
+
return;
|
|
8299
|
+
}
|
|
8300
|
+
if (!createdBy) {
|
|
8301
|
+
sendResponse8(id, {
|
|
8302
|
+
success: false,
|
|
8303
|
+
error: "createdBy (user ID) is required"
|
|
8304
|
+
}, sendMessage, clientId);
|
|
8305
|
+
return;
|
|
8306
|
+
}
|
|
8307
|
+
try {
|
|
8308
|
+
const result = await executeCollection("kbNodes", "create", {
|
|
8309
|
+
title,
|
|
8310
|
+
content,
|
|
8311
|
+
category: category || void 0,
|
|
8312
|
+
tags: tags || void 0,
|
|
8313
|
+
createdBy
|
|
8314
|
+
});
|
|
8315
|
+
if (result && result.success) {
|
|
8316
|
+
logger.info(`[DB] KB node created successfully: ${title}`);
|
|
8317
|
+
sendResponse8(id, {
|
|
8318
|
+
success: true,
|
|
8319
|
+
data: {
|
|
8320
|
+
...result.data,
|
|
8321
|
+
message: `Knowledge node '${title}' created successfully`
|
|
8322
|
+
}
|
|
8323
|
+
}, sendMessage, clientId);
|
|
8324
|
+
return;
|
|
8325
|
+
}
|
|
8326
|
+
sendResponse8(id, {
|
|
8327
|
+
success: false,
|
|
8328
|
+
error: "Failed to create knowledge node"
|
|
8329
|
+
}, sendMessage, clientId);
|
|
8330
|
+
} catch (error) {
|
|
8331
|
+
logger.error("[DB] Failed to create KB node:", error);
|
|
8332
|
+
sendResponse8(id, {
|
|
8333
|
+
success: false,
|
|
8334
|
+
error: error instanceof Error ? error.message : "Failed to create knowledge node"
|
|
8335
|
+
}, sendMessage, clientId);
|
|
8336
|
+
}
|
|
8337
|
+
}
|
|
8338
|
+
async function handleUpdate6(id, nodeId, nodeData, executeCollection, sendMessage, clientId) {
|
|
8339
|
+
const { title, content, category, tags, updatedBy } = nodeData;
|
|
8340
|
+
if (!nodeId) {
|
|
8341
|
+
sendResponse8(id, {
|
|
8342
|
+
success: false,
|
|
8343
|
+
error: "Knowledge node ID is required"
|
|
8344
|
+
}, sendMessage, clientId);
|
|
8345
|
+
return;
|
|
8346
|
+
}
|
|
8347
|
+
if (!updatedBy) {
|
|
8348
|
+
sendResponse8(id, {
|
|
8349
|
+
success: false,
|
|
8350
|
+
error: "updatedBy (user ID) is required"
|
|
8351
|
+
}, sendMessage, clientId);
|
|
8352
|
+
return;
|
|
8353
|
+
}
|
|
8354
|
+
try {
|
|
8355
|
+
const result = await executeCollection("kbNodes", "update", {
|
|
8356
|
+
id: nodeId,
|
|
8357
|
+
title,
|
|
8358
|
+
content,
|
|
8359
|
+
category,
|
|
8360
|
+
tags,
|
|
8361
|
+
updatedBy
|
|
8362
|
+
});
|
|
8363
|
+
if (result && result.success) {
|
|
8364
|
+
logger.info(`[DB] KB node updated successfully, ID: ${nodeId}`);
|
|
8365
|
+
sendResponse8(id, {
|
|
8366
|
+
success: true,
|
|
8367
|
+
data: {
|
|
8368
|
+
...result.data,
|
|
8369
|
+
message: `Knowledge node updated successfully`
|
|
8370
|
+
}
|
|
8371
|
+
}, sendMessage, clientId);
|
|
8372
|
+
return;
|
|
8373
|
+
}
|
|
8374
|
+
sendResponse8(id, {
|
|
8375
|
+
success: false,
|
|
8376
|
+
error: "Failed to update knowledge node"
|
|
8377
|
+
}, sendMessage, clientId);
|
|
8378
|
+
} catch (error) {
|
|
8379
|
+
logger.error("[DB] Failed to update KB node:", error);
|
|
8380
|
+
sendResponse8(id, {
|
|
8381
|
+
success: false,
|
|
8382
|
+
error: error instanceof Error ? error.message : "Failed to update knowledge node"
|
|
8383
|
+
}, sendMessage, clientId);
|
|
8384
|
+
}
|
|
8385
|
+
}
|
|
8386
|
+
async function handleDelete6(id, nodeId, executeCollection, sendMessage, clientId) {
|
|
8387
|
+
if (!nodeId) {
|
|
8388
|
+
sendResponse8(id, {
|
|
8389
|
+
success: false,
|
|
8390
|
+
error: "Knowledge node ID is required"
|
|
8391
|
+
}, sendMessage, clientId);
|
|
8392
|
+
return;
|
|
8393
|
+
}
|
|
8394
|
+
try {
|
|
8395
|
+
const result = await executeCollection("kbNodes", "delete", { id: nodeId });
|
|
8396
|
+
if (result && result.success) {
|
|
8397
|
+
logger.info(`[DB] KB node deleted successfully, ID: ${nodeId}`);
|
|
8398
|
+
sendResponse8(id, {
|
|
8399
|
+
success: true,
|
|
8400
|
+
data: {
|
|
8401
|
+
id: nodeId,
|
|
8402
|
+
...result.data,
|
|
8403
|
+
message: `Knowledge node deleted successfully`
|
|
8404
|
+
}
|
|
8405
|
+
}, sendMessage, clientId);
|
|
8406
|
+
return;
|
|
8407
|
+
}
|
|
8408
|
+
sendResponse8(id, {
|
|
8409
|
+
success: false,
|
|
8410
|
+
error: "Failed to delete knowledge node"
|
|
8411
|
+
}, sendMessage, clientId);
|
|
8412
|
+
} catch (error) {
|
|
8413
|
+
logger.error("[DB] Failed to delete KB node:", error);
|
|
8414
|
+
sendResponse8(id, {
|
|
8415
|
+
success: false,
|
|
8416
|
+
error: error instanceof Error ? error.message : "Failed to delete knowledge node"
|
|
8417
|
+
}, sendMessage, clientId);
|
|
8418
|
+
}
|
|
8419
|
+
}
|
|
8420
|
+
async function handleGetAll6(id, limit, offset, executeCollection, sendMessage, clientId) {
|
|
8421
|
+
try {
|
|
8422
|
+
const result = await executeCollection("kbNodes", "getAll", {
|
|
8423
|
+
limit: limit || 100,
|
|
8424
|
+
offset: offset || 0
|
|
8425
|
+
});
|
|
8426
|
+
if (result && result.success) {
|
|
8427
|
+
logger.info(`[DB] Retrieved ${result.count} KB nodes`);
|
|
8428
|
+
sendResponse8(id, {
|
|
8429
|
+
success: true,
|
|
8430
|
+
data: {
|
|
8431
|
+
nodes: result.data,
|
|
8432
|
+
count: result.count,
|
|
8433
|
+
message: `Retrieved ${result.count} knowledge nodes`
|
|
8434
|
+
}
|
|
8435
|
+
}, sendMessage, clientId);
|
|
8436
|
+
return;
|
|
8437
|
+
}
|
|
8438
|
+
sendResponse8(id, {
|
|
8439
|
+
success: false,
|
|
8440
|
+
error: "Failed to retrieve knowledge nodes"
|
|
8441
|
+
}, sendMessage, clientId);
|
|
8442
|
+
} catch (error) {
|
|
8443
|
+
logger.error("[DB] Failed to get all KB nodes:", error);
|
|
8444
|
+
sendResponse8(id, {
|
|
8445
|
+
success: false,
|
|
8446
|
+
error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes"
|
|
8447
|
+
}, sendMessage, clientId);
|
|
8448
|
+
}
|
|
8449
|
+
}
|
|
8450
|
+
async function handleGetOne6(id, nodeId, executeCollection, sendMessage, clientId) {
|
|
8451
|
+
if (!nodeId) {
|
|
8452
|
+
sendResponse8(id, {
|
|
8453
|
+
success: false,
|
|
8454
|
+
error: "Knowledge node ID is required"
|
|
8455
|
+
}, sendMessage, clientId);
|
|
8456
|
+
return;
|
|
8457
|
+
}
|
|
8458
|
+
try {
|
|
8459
|
+
const result = await executeCollection("kbNodes", "getOne", { id: nodeId });
|
|
8460
|
+
if (result && result.success) {
|
|
8461
|
+
logger.info(`[DB] Retrieved KB node ID: ${nodeId}`);
|
|
8462
|
+
sendResponse8(id, {
|
|
8463
|
+
success: true,
|
|
8464
|
+
data: {
|
|
8465
|
+
node: result.data,
|
|
8466
|
+
message: `Retrieved knowledge node`
|
|
8467
|
+
}
|
|
8468
|
+
}, sendMessage, clientId);
|
|
8469
|
+
return;
|
|
8470
|
+
}
|
|
8471
|
+
sendResponse8(id, {
|
|
8472
|
+
success: false,
|
|
8473
|
+
error: "Failed to retrieve knowledge node"
|
|
8474
|
+
}, sendMessage, clientId);
|
|
8475
|
+
} catch (error) {
|
|
8476
|
+
logger.error("[DB] Failed to get KB node:", error);
|
|
8477
|
+
sendResponse8(id, {
|
|
8478
|
+
success: false,
|
|
8479
|
+
error: error instanceof Error ? error.message : "Failed to retrieve knowledge node"
|
|
8480
|
+
}, sendMessage, clientId);
|
|
8481
|
+
}
|
|
8482
|
+
}
|
|
8483
|
+
async function handleSearch(id, searchParams, executeCollection, sendMessage, clientId) {
|
|
8484
|
+
const { query, category, tags, createdBy, limit, offset } = searchParams;
|
|
8485
|
+
try {
|
|
8486
|
+
const result = await executeCollection("kbNodes", "search", {
|
|
8487
|
+
query,
|
|
8488
|
+
category,
|
|
8489
|
+
tags,
|
|
8490
|
+
createdBy,
|
|
8491
|
+
limit: limit || 50,
|
|
8492
|
+
offset: offset || 0
|
|
8493
|
+
});
|
|
8494
|
+
if (result && result.success) {
|
|
8495
|
+
logger.info(`[DB] Search returned ${result.count} KB nodes`);
|
|
8496
|
+
sendResponse8(id, {
|
|
8497
|
+
success: true,
|
|
8498
|
+
data: {
|
|
8499
|
+
nodes: result.data,
|
|
8500
|
+
count: result.count,
|
|
8501
|
+
message: `Search returned ${result.count} knowledge nodes`
|
|
8502
|
+
}
|
|
8503
|
+
}, sendMessage, clientId);
|
|
8504
|
+
return;
|
|
8505
|
+
}
|
|
8506
|
+
sendResponse8(id, {
|
|
8507
|
+
success: false,
|
|
8508
|
+
error: "Failed to search knowledge nodes"
|
|
8509
|
+
}, sendMessage, clientId);
|
|
8510
|
+
} catch (error) {
|
|
8511
|
+
logger.error("[DB] Failed to search KB nodes:", error);
|
|
8512
|
+
sendResponse8(id, {
|
|
8513
|
+
success: false,
|
|
8514
|
+
error: error instanceof Error ? error.message : "Failed to search knowledge nodes"
|
|
8515
|
+
}, sendMessage, clientId);
|
|
8516
|
+
}
|
|
8517
|
+
}
|
|
8518
|
+
async function handleGetByCategory(id, category, limit, offset, executeCollection, sendMessage, clientId) {
|
|
8519
|
+
if (!category) {
|
|
8520
|
+
sendResponse8(id, {
|
|
8521
|
+
success: false,
|
|
8522
|
+
error: "Category is required"
|
|
8523
|
+
}, sendMessage, clientId);
|
|
8524
|
+
return;
|
|
8525
|
+
}
|
|
8526
|
+
try {
|
|
8527
|
+
const result = await executeCollection("kbNodes", "getByCategory", {
|
|
8528
|
+
category,
|
|
8529
|
+
limit: limit || 50,
|
|
8530
|
+
offset: offset || 0
|
|
8531
|
+
});
|
|
8532
|
+
if (result && result.success) {
|
|
8533
|
+
logger.info(`[DB] Retrieved ${result.count} KB nodes for category: ${category}`);
|
|
8534
|
+
sendResponse8(id, {
|
|
8535
|
+
success: true,
|
|
8536
|
+
data: {
|
|
8537
|
+
nodes: result.data,
|
|
8538
|
+
count: result.count,
|
|
8539
|
+
category,
|
|
8540
|
+
message: `Retrieved ${result.count} knowledge nodes for category '${category}'`
|
|
8541
|
+
}
|
|
8542
|
+
}, sendMessage, clientId);
|
|
8543
|
+
return;
|
|
8544
|
+
}
|
|
8545
|
+
sendResponse8(id, {
|
|
8546
|
+
success: false,
|
|
8547
|
+
error: "Failed to retrieve knowledge nodes by category"
|
|
8548
|
+
}, sendMessage, clientId);
|
|
8549
|
+
} catch (error) {
|
|
8550
|
+
logger.error("[DB] Failed to get KB nodes by category:", error);
|
|
8551
|
+
sendResponse8(id, {
|
|
8552
|
+
success: false,
|
|
8553
|
+
error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes by category"
|
|
8554
|
+
}, sendMessage, clientId);
|
|
8555
|
+
}
|
|
8556
|
+
}
|
|
8557
|
+
async function handleGetByUser(id, userId, limit, offset, executeCollection, sendMessage, clientId) {
|
|
8558
|
+
if (!userId) {
|
|
8559
|
+
sendResponse8(id, {
|
|
8560
|
+
success: false,
|
|
8561
|
+
error: "User ID is required"
|
|
8562
|
+
}, sendMessage, clientId);
|
|
8563
|
+
return;
|
|
8564
|
+
}
|
|
8565
|
+
try {
|
|
8566
|
+
const result = await executeCollection("kbNodes", "getByUser", {
|
|
8567
|
+
userId,
|
|
8568
|
+
limit: limit || 50,
|
|
8569
|
+
offset: offset || 0
|
|
8570
|
+
});
|
|
8571
|
+
if (result && result.success) {
|
|
8572
|
+
logger.info(`[DB] Retrieved ${result.count} KB nodes for user: ${userId}`);
|
|
8573
|
+
sendResponse8(id, {
|
|
8574
|
+
success: true,
|
|
8575
|
+
data: {
|
|
8576
|
+
nodes: result.data,
|
|
8577
|
+
count: result.count,
|
|
8578
|
+
userId,
|
|
8579
|
+
message: `Retrieved ${result.count} knowledge nodes for user ${userId}`
|
|
8580
|
+
}
|
|
8581
|
+
}, sendMessage, clientId);
|
|
8582
|
+
return;
|
|
8583
|
+
}
|
|
8584
|
+
sendResponse8(id, {
|
|
8585
|
+
success: false,
|
|
8586
|
+
error: "Failed to retrieve knowledge nodes by user"
|
|
8587
|
+
}, sendMessage, clientId);
|
|
8588
|
+
} catch (error) {
|
|
8589
|
+
logger.error("[DB] Failed to get KB nodes by user:", error);
|
|
8590
|
+
sendResponse8(id, {
|
|
8591
|
+
success: false,
|
|
8592
|
+
error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes by user"
|
|
8593
|
+
}, sendMessage, clientId);
|
|
8594
|
+
}
|
|
8595
|
+
}
|
|
8596
|
+
async function handleGetCategories(id, executeCollection, sendMessage, clientId) {
|
|
8597
|
+
try {
|
|
8598
|
+
const result = await executeCollection("kbNodes", "getCategories", {});
|
|
8599
|
+
if (result && result.success) {
|
|
8600
|
+
logger.info(`[DB] Retrieved ${result.count} categories`);
|
|
8601
|
+
sendResponse8(id, {
|
|
8602
|
+
success: true,
|
|
8603
|
+
data: {
|
|
8604
|
+
categories: result.data,
|
|
8605
|
+
count: result.count,
|
|
8606
|
+
message: `Retrieved ${result.count} categories`
|
|
8607
|
+
}
|
|
8608
|
+
}, sendMessage, clientId);
|
|
8609
|
+
return;
|
|
8610
|
+
}
|
|
8611
|
+
sendResponse8(id, {
|
|
8612
|
+
success: false,
|
|
8613
|
+
error: "Failed to retrieve categories"
|
|
8614
|
+
}, sendMessage, clientId);
|
|
8615
|
+
} catch (error) {
|
|
8616
|
+
logger.error("[DB] Failed to get categories:", error);
|
|
8617
|
+
sendResponse8(id, {
|
|
8618
|
+
success: false,
|
|
8619
|
+
error: error instanceof Error ? error.message : "Failed to retrieve categories"
|
|
8620
|
+
}, sendMessage, clientId);
|
|
8621
|
+
}
|
|
8622
|
+
}
|
|
8623
|
+
async function handleGetTags(id, executeCollection, sendMessage, clientId) {
|
|
8624
|
+
try {
|
|
8625
|
+
const result = await executeCollection("kbNodes", "getTags", {});
|
|
8626
|
+
if (result && result.success) {
|
|
8627
|
+
logger.info(`[DB] Retrieved ${result.count} tags`);
|
|
8628
|
+
sendResponse8(id, {
|
|
8629
|
+
success: true,
|
|
8630
|
+
data: {
|
|
8631
|
+
tags: result.data,
|
|
8632
|
+
count: result.count,
|
|
8633
|
+
message: `Retrieved ${result.count} tags`
|
|
8634
|
+
}
|
|
8635
|
+
}, sendMessage, clientId);
|
|
8636
|
+
return;
|
|
8637
|
+
}
|
|
8638
|
+
sendResponse8(id, {
|
|
8639
|
+
success: false,
|
|
8640
|
+
error: "Failed to retrieve tags"
|
|
8641
|
+
}, sendMessage, clientId);
|
|
8642
|
+
} catch (error) {
|
|
8643
|
+
logger.error("[DB] Failed to get tags:", error);
|
|
8644
|
+
sendResponse8(id, {
|
|
8645
|
+
success: false,
|
|
8646
|
+
error: error instanceof Error ? error.message : "Failed to retrieve tags"
|
|
8647
|
+
}, sendMessage, clientId);
|
|
8648
|
+
}
|
|
8649
|
+
}
|
|
8650
|
+
function sendResponse8(id, res, sendMessage, clientId) {
|
|
8651
|
+
const response = {
|
|
8652
|
+
id: id || "unknown",
|
|
8653
|
+
type: "KB_NODES_RES",
|
|
8654
|
+
from: { type: "data-agent" },
|
|
8655
|
+
to: {
|
|
8656
|
+
type: "admin",
|
|
8657
|
+
id: clientId
|
|
8658
|
+
},
|
|
8659
|
+
payload: {
|
|
8660
|
+
...res
|
|
8661
|
+
}
|
|
8662
|
+
};
|
|
8663
|
+
sendMessage(response);
|
|
8664
|
+
}
|
|
8665
|
+
|
|
7848
8666
|
// src/auth/user-manager.ts
|
|
7849
8667
|
import fs5 from "fs";
|
|
7850
8668
|
import path4 from "path";
|
|
@@ -8874,6 +9692,11 @@ var SuperatomSDK = class {
|
|
|
8874
9692
|
logger.error("Failed to handle bookmarks request:", error);
|
|
8875
9693
|
});
|
|
8876
9694
|
break;
|
|
9695
|
+
case "KB_NODES":
|
|
9696
|
+
handleKbNodesRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
|
|
9697
|
+
logger.error("Failed to handle KB nodes request:", error);
|
|
9698
|
+
});
|
|
9699
|
+
break;
|
|
8877
9700
|
default:
|
|
8878
9701
|
const handler = this.messageTypeHandlers.get(message.type);
|
|
8879
9702
|
if (handler) {
|
|
@@ -8995,6 +9818,7 @@ var SuperatomSDK = class {
|
|
|
8995
9818
|
}
|
|
8996
9819
|
};
|
|
8997
9820
|
export {
|
|
9821
|
+
BM25L,
|
|
8998
9822
|
CONTEXT_CONFIG,
|
|
8999
9823
|
CleanupService,
|
|
9000
9824
|
LLM,
|
|
@@ -9006,6 +9830,9 @@ export {
|
|
|
9006
9830
|
UIBlock,
|
|
9007
9831
|
UILogCollector,
|
|
9008
9832
|
UserManager,
|
|
9009
|
-
|
|
9833
|
+
hybridRerank,
|
|
9834
|
+
logger,
|
|
9835
|
+
rerankChromaResults,
|
|
9836
|
+
rerankConversationResults
|
|
9010
9837
|
};
|
|
9011
9838
|
//# sourceMappingURL=index.mjs.map
|