@superatomai/sdk-node 0.0.52 → 0.0.54
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 +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +636 -84
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +636 -84
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -10,12 +10,13 @@ var __export = (target, all) => {
|
|
|
10
10
|
|
|
11
11
|
// src/utils/logger.ts
|
|
12
12
|
import fs from "fs";
|
|
13
|
-
var PREFIX, LOGSTREAM, LOG_LEVEL_PRIORITY, MESSAGE_LEVEL_PRIORITY, Logger, logger;
|
|
13
|
+
var PREFIX, LOG_FILE_PATH, LOGSTREAM, LOG_LEVEL_PRIORITY, MESSAGE_LEVEL_PRIORITY, Logger, logger;
|
|
14
14
|
var init_logger = __esm({
|
|
15
15
|
"src/utils/logger.ts"() {
|
|
16
16
|
"use strict";
|
|
17
17
|
PREFIX = "[SuperatomSDK]";
|
|
18
|
-
|
|
18
|
+
LOG_FILE_PATH = "superatom-sdk.log";
|
|
19
|
+
LOGSTREAM = fs.createWriteStream(LOG_FILE_PATH, { flags: "a" });
|
|
19
20
|
LOG_LEVEL_PRIORITY = {
|
|
20
21
|
errors: 0,
|
|
21
22
|
warnings: 1,
|
|
@@ -99,9 +100,58 @@ var init_logger = __esm({
|
|
|
99
100
|
console.log(PREFIX, "[DEBUG]", ...args);
|
|
100
101
|
}
|
|
101
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Write to log file
|
|
105
|
+
*/
|
|
102
106
|
file(...args) {
|
|
103
107
|
LOGSTREAM.write(args.join(" ") + "\n");
|
|
104
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Clear the log file (call at start of new user request)
|
|
111
|
+
*/
|
|
112
|
+
clearFile() {
|
|
113
|
+
LOGSTREAM.end();
|
|
114
|
+
LOGSTREAM = fs.createWriteStream(LOG_FILE_PATH, { flags: "w" });
|
|
115
|
+
LOGSTREAM.write(`
|
|
116
|
+
${"=".repeat(80)}
|
|
117
|
+
`);
|
|
118
|
+
LOGSTREAM.write(`NEW REQUEST - ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
119
|
+
`);
|
|
120
|
+
LOGSTREAM.write(`${"=".repeat(80)}
|
|
121
|
+
|
|
122
|
+
`);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Log LLM method prompts with clear labeling
|
|
126
|
+
*/
|
|
127
|
+
logLLMPrompt(methodName, promptType, content) {
|
|
128
|
+
const header = `
|
|
129
|
+
${"#".repeat(80)}
|
|
130
|
+
[LLM METHOD: ${methodName}] - ${promptType.toUpperCase()} PROMPT
|
|
131
|
+
${"#".repeat(80)}
|
|
132
|
+
`;
|
|
133
|
+
LOGSTREAM.write(header);
|
|
134
|
+
let contentStr;
|
|
135
|
+
if (typeof content === "string") {
|
|
136
|
+
contentStr = content;
|
|
137
|
+
} else if (Array.isArray(content)) {
|
|
138
|
+
contentStr = content.map((item) => {
|
|
139
|
+
if (typeof item === "string") return item;
|
|
140
|
+
if (item.text) return item.text;
|
|
141
|
+
if (item.content) return typeof item.content === "string" ? item.content : JSON.stringify(item.content, null, 2);
|
|
142
|
+
return JSON.stringify(item, null, 2);
|
|
143
|
+
}).join("\n\n");
|
|
144
|
+
} else if (typeof content === "object") {
|
|
145
|
+
contentStr = JSON.stringify(content, null, 2);
|
|
146
|
+
} else {
|
|
147
|
+
contentStr = String(content);
|
|
148
|
+
}
|
|
149
|
+
LOGSTREAM.write(contentStr);
|
|
150
|
+
LOGSTREAM.write(`
|
|
151
|
+
${"#".repeat(80)}
|
|
152
|
+
|
|
153
|
+
`);
|
|
154
|
+
}
|
|
105
155
|
};
|
|
106
156
|
logger = new Logger();
|
|
107
157
|
}
|
|
@@ -1019,8 +1069,20 @@ If adaptation is not possible or would fundamentally change the component:
|
|
|
1019
1069
|
|
|
1020
1070
|
Analyze the user's request and:
|
|
1021
1071
|
1. **Select the most appropriate component** from the available components list
|
|
1022
|
-
2. **Determine the data source**: Database query OR External tool
|
|
1023
|
-
3. **Generate complete props** for the selected component
|
|
1072
|
+
2. **Determine the data source**: Database query OR External tool
|
|
1073
|
+
3. **Generate complete props** for the selected component
|
|
1074
|
+
|
|
1075
|
+
## Available External Tools
|
|
1076
|
+
|
|
1077
|
+
The following external tools are available:
|
|
1078
|
+
|
|
1079
|
+
{{AVAILABLE_TOOLS}}
|
|
1080
|
+
|
|
1081
|
+
When a tool is needed to complete the user's request:
|
|
1082
|
+
1. **Analyze the request** to determine which tool is needed
|
|
1083
|
+
2. **Extract parameters** from the user's question
|
|
1084
|
+
3. **Execute the tool** by calling it with the extracted parameters
|
|
1085
|
+
4. **Use the results** to configure the component (field names for axes, columns, etc.)
|
|
1024
1086
|
|
|
1025
1087
|
## Component Selection Rules
|
|
1026
1088
|
|
|
@@ -1176,7 +1238,20 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1176
1238
|
|
|
1177
1239
|
1. **Create a filter component** based on the user's request
|
|
1178
1240
|
2. **Update existing components** with dynamic title/description interpolation if needed
|
|
1179
|
-
3. **
|
|
1241
|
+
3. **Set default values in component externalTool.params** that match the filter's default option
|
|
1242
|
+
4. **Preserve all existing props** - the filter system handles param merging at runtime
|
|
1243
|
+
|
|
1244
|
+
## Available External Tools
|
|
1245
|
+
|
|
1246
|
+
The following external tools are available:
|
|
1247
|
+
|
|
1248
|
+
{{AVAILABLE_TOOLS}}
|
|
1249
|
+
|
|
1250
|
+
When a tool is needed to complete the user's request:
|
|
1251
|
+
1. **Analyze the request** to determine which tool is needed
|
|
1252
|
+
2. **Extract parameters** from the user's question
|
|
1253
|
+
3. **Execute the tool** by calling it with the extracted parameters
|
|
1254
|
+
4. **Use the results** to configure the filter and components properly
|
|
1180
1255
|
|
|
1181
1256
|
## How The Filter System Works
|
|
1182
1257
|
|
|
@@ -1206,16 +1281,20 @@ Use \`{%filterKeyLabel%}\` syntax for dynamic text:
|
|
|
1206
1281
|
## Updating Existing Components
|
|
1207
1282
|
|
|
1208
1283
|
**IMPORTANT - Parameter Handling:**
|
|
1209
|
-
- Do NOT change existing parameter values to placeholders
|
|
1210
|
-
- Keep all existing/default parameter values as they are
|
|
1211
1284
|
- The filter system MERGES params at runtime: filter params override component defaults
|
|
1285
|
+
- Component's \`externalTool.params\` should have DEFAULT values matching the filter's default option
|
|
1286
|
+
- This ensures the component shows correct data on initial load before user changes the filter
|
|
1212
1287
|
|
|
1213
1288
|
**What to modify in existing components:**
|
|
1214
1289
|
- Modify \`title\` for \`{%filterKeyLabel%}\` interpolation (only if title exists)
|
|
1215
1290
|
- Modify \`description\` for interpolation (only if description exists)
|
|
1216
|
-
-
|
|
1291
|
+
- Set \`externalTool.params\` default values to match filter's default option params
|
|
1217
1292
|
- Copy ALL other props exactly as provided
|
|
1218
1293
|
|
|
1294
|
+
**Example - Setting default params:**
|
|
1295
|
+
If filter has default option with params: \`{ startDate: "2025-01-01", endDate: "2025-01-31" }\`
|
|
1296
|
+
Then component's externalTool should have: \`{ params: { startDate: "2025-01-01", endDate: "2025-01-31" } }\`
|
|
1297
|
+
|
|
1219
1298
|
### Database Query Rules
|
|
1220
1299
|
{{DATABASE_RULES}}
|
|
1221
1300
|
|
|
@@ -1263,10 +1342,11 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1263
1342
|
**CRITICAL RULES:**
|
|
1264
1343
|
1. Return ONLY valid JSON (no markdown code blocks)
|
|
1265
1344
|
2. **COPY ALL existing props** - modify title/description for interpolation only if they exist
|
|
1266
|
-
3. **
|
|
1345
|
+
3. **Set externalTool.params defaults** to match the filter's default option params
|
|
1267
1346
|
4. Use \`{%filterKeyLabel%}\` for dynamic text (NOT \`{{...}}\` or \`$...\`)
|
|
1268
1347
|
5. Filter \`params\` must have ACTUAL values (real dates, strings), not placeholders
|
|
1269
1348
|
6. Each filter option needs: label, value, params (and optionally isDefault)
|
|
1349
|
+
7. Component default params MUST match filter default - this ensures correct initial data load
|
|
1270
1350
|
|
|
1271
1351
|
## Database Schema
|
|
1272
1352
|
{{SCHEMA_DOC}}
|
|
@@ -2309,6 +2389,57 @@ var KbNodesRequestMessageSchema = z3.object({
|
|
|
2309
2389
|
type: z3.literal("KB_NODES"),
|
|
2310
2390
|
payload: KbNodesRequestPayloadSchema
|
|
2311
2391
|
});
|
|
2392
|
+
var MenusQueryFiltersSchema = z3.object({
|
|
2393
|
+
parentId: z3.number().nullable().optional(),
|
|
2394
|
+
isActive: z3.boolean().optional()
|
|
2395
|
+
});
|
|
2396
|
+
var MenusRequestPayloadSchema = z3.object({
|
|
2397
|
+
operation: z3.enum([
|
|
2398
|
+
"create",
|
|
2399
|
+
"update",
|
|
2400
|
+
"delete",
|
|
2401
|
+
"getAll",
|
|
2402
|
+
"getOne",
|
|
2403
|
+
"getRootMenus",
|
|
2404
|
+
"getChildMenus",
|
|
2405
|
+
"getHierarchy",
|
|
2406
|
+
"query",
|
|
2407
|
+
"reorder"
|
|
2408
|
+
]),
|
|
2409
|
+
data: z3.object({
|
|
2410
|
+
id: z3.number().optional(),
|
|
2411
|
+
name: z3.string().optional(),
|
|
2412
|
+
componentName: z3.string().optional(),
|
|
2413
|
+
icon: z3.string().optional(),
|
|
2414
|
+
userMessage: z3.string().optional(),
|
|
2415
|
+
parentId: z3.number().nullable().optional(),
|
|
2416
|
+
sortOrder: z3.number().optional(),
|
|
2417
|
+
props: z3.record(z3.unknown()).optional(),
|
|
2418
|
+
isActive: z3.boolean().optional(),
|
|
2419
|
+
// Query operation fields
|
|
2420
|
+
filters: MenusQueryFiltersSchema.optional(),
|
|
2421
|
+
limit: z3.number().optional(),
|
|
2422
|
+
sort: z3.enum(["ASC", "DESC"]).optional(),
|
|
2423
|
+
// Reorder operation fields
|
|
2424
|
+
items: z3.array(z3.object({
|
|
2425
|
+
id: z3.number(),
|
|
2426
|
+
sortOrder: z3.number()
|
|
2427
|
+
})).optional()
|
|
2428
|
+
}).optional()
|
|
2429
|
+
});
|
|
2430
|
+
var MenusRequestMessageSchema = z3.object({
|
|
2431
|
+
id: z3.string(),
|
|
2432
|
+
from: MessageParticipantSchema,
|
|
2433
|
+
type: z3.literal("MENUS"),
|
|
2434
|
+
payload: MenusRequestPayloadSchema
|
|
2435
|
+
});
|
|
2436
|
+
var MenusResponsePayloadSchema = z3.object({
|
|
2437
|
+
success: z3.boolean(),
|
|
2438
|
+
error: z3.string().optional(),
|
|
2439
|
+
data: z3.any().optional(),
|
|
2440
|
+
count: z3.number().optional(),
|
|
2441
|
+
message: z3.string().optional()
|
|
2442
|
+
});
|
|
2312
2443
|
var DashCompRequestPayloadSchema = z3.object({
|
|
2313
2444
|
prompt: z3.string(),
|
|
2314
2445
|
userId: z3.string().optional(),
|
|
@@ -5669,35 +5800,35 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
|
5669
5800
|
let executedToolsText = "No external tools were executed for data fetching.";
|
|
5670
5801
|
if (executedTools && executedTools.length > 0) {
|
|
5671
5802
|
logger.info(`[${this.getProviderName()}] Passing ${executedTools.length} executed tools to component matching`);
|
|
5672
|
-
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
|
|
5803
|
+
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 ONLY the field names listed in outputSchema for config keys.**\n\n" + executedTools.map((tool, idx) => {
|
|
5673
5804
|
let outputSchemaText = "Not available";
|
|
5805
|
+
let fieldNamesList = "";
|
|
5674
5806
|
let recordCount = "unknown";
|
|
5675
5807
|
if (tool.outputSchema) {
|
|
5676
5808
|
const fields = tool.outputSchema.fields || [];
|
|
5677
5809
|
recordCount = tool.result?._recordCount || (Array.isArray(tool.result) ? tool.result.length : "unknown");
|
|
5810
|
+
const numericFields = fields.filter((f) => f.type === "number").map((f) => f.name);
|
|
5811
|
+
const stringFields = fields.filter((f) => f.type === "string").map((f) => f.name);
|
|
5812
|
+
fieldNamesList = `
|
|
5813
|
+
\u{1F4CA} NUMERIC FIELDS (use for yAxisKey, valueKey, aggregationField): ${numericFields.join(", ") || "none"}
|
|
5814
|
+
\u{1F4DD} STRING FIELDS (use for xAxisKey, groupBy, nameKey): ${stringFields.join(", ") || "none"}`;
|
|
5678
5815
|
const fieldsText = fields.map(
|
|
5679
|
-
(f) => `
|
|
5680
|
-
type: ${f.type}
|
|
5681
|
-
description: ${f.description}`
|
|
5816
|
+
(f) => ` "${f.name}" (${f.type}): ${f.description}`
|
|
5682
5817
|
).join("\n");
|
|
5683
5818
|
outputSchemaText = `${tool.outputSchema.description}
|
|
5684
|
-
Fields
|
|
5819
|
+
Fields:
|
|
5685
5820
|
${fieldsText}`;
|
|
5686
5821
|
}
|
|
5687
5822
|
return `${idx + 1}. **${tool.name}**
|
|
5688
|
-
toolId: "${tool.id}"
|
|
5689
|
-
toolName: "${tool.name}"
|
|
5690
|
-
parameters: ${JSON.stringify(tool.params || {})}
|
|
5823
|
+
toolId: "${tool.id}"
|
|
5824
|
+
toolName: "${tool.name}"
|
|
5825
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
5691
5826
|
recordCount: ${recordCount} rows returned
|
|
5692
|
-
outputSchema: ${outputSchemaText}
|
|
5693
|
-
\u26A0\uFE0F DO NOT embed this tool's data in SQL - use externalTool prop OR query database tables`;
|
|
5827
|
+
outputSchema: ${outputSchemaText}${fieldNamesList}`;
|
|
5694
5828
|
}).join("\n\n");
|
|
5695
5829
|
}
|
|
5696
5830
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
5697
5831
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
5698
|
-
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
5699
|
-
logger.file("\n=============================\nDeferred tools:", deferredToolsText);
|
|
5700
|
-
logger.file("\n=============================\nExecuted tools:", executedToolsText);
|
|
5701
5832
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
5702
5833
|
ANALYSIS_CONTENT: analysisContent,
|
|
5703
5834
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -5707,7 +5838,13 @@ ${fieldsText}`;
|
|
|
5707
5838
|
EXECUTED_TOOLS: executedToolsText
|
|
5708
5839
|
});
|
|
5709
5840
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
5710
|
-
|
|
5841
|
+
const systemPromptStr = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
5842
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "system", systemPromptStr);
|
|
5843
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
|
|
5844
|
+
${analysisContent}
|
|
5845
|
+
|
|
5846
|
+
Executed Tools:
|
|
5847
|
+
${executedToolsText}`);
|
|
5711
5848
|
logCollector?.info("Matching components from text response...");
|
|
5712
5849
|
let fullResponseText = "";
|
|
5713
5850
|
let answerComponentExtracted = false;
|
|
@@ -5844,40 +5981,41 @@ ${fieldsText}`;
|
|
|
5844
5981
|
if (executedTool?.outputSchema?.fields && cleanedProps.config) {
|
|
5845
5982
|
const validFieldNames = executedTool.outputSchema.fields.map((f) => f.name);
|
|
5846
5983
|
const validFieldNamesLower = validFieldNames.map((n) => n.toLowerCase());
|
|
5847
|
-
const findMatchingField = (fieldName) => {
|
|
5984
|
+
const findMatchingField = (fieldName, configKey) => {
|
|
5848
5985
|
if (!fieldName) return null;
|
|
5849
5986
|
const lowerField = fieldName.toLowerCase();
|
|
5850
5987
|
const exactIdx = validFieldNamesLower.indexOf(lowerField);
|
|
5851
5988
|
if (exactIdx !== -1) return validFieldNames[exactIdx];
|
|
5852
|
-
const
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
if (
|
|
5867
|
-
|
|
5868
|
-
|
|
5989
|
+
const containsMatches = validFieldNames.filter(
|
|
5990
|
+
(_, i) => validFieldNamesLower[i].includes(lowerField) || lowerField.includes(validFieldNamesLower[i])
|
|
5991
|
+
);
|
|
5992
|
+
if (containsMatches.length === 1) return containsMatches[0];
|
|
5993
|
+
const fieldTypes = executedTool.outputSchema.fields.reduce((acc, f) => {
|
|
5994
|
+
acc[f.name] = f.type;
|
|
5995
|
+
return acc;
|
|
5996
|
+
}, {});
|
|
5997
|
+
const numericConfigKeys = ["yAxisKey", "valueKey", "aggregationField", "sizeKey"];
|
|
5998
|
+
const stringConfigKeys = ["xAxisKey", "nameKey", "labelKey", "groupBy"];
|
|
5999
|
+
if (numericConfigKeys.includes(configKey)) {
|
|
6000
|
+
const numericFields = validFieldNames.filter((f) => fieldTypes[f] === "number");
|
|
6001
|
+
const match = numericFields.find((f) => f.toLowerCase().includes(lowerField) || lowerField.includes(f.toLowerCase()));
|
|
6002
|
+
if (match) return match;
|
|
6003
|
+
if (numericFields.length > 0) {
|
|
6004
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first numeric field: ${numericFields[0]}`);
|
|
6005
|
+
return numericFields[0];
|
|
5869
6006
|
}
|
|
5870
6007
|
}
|
|
5871
|
-
if (
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
logger.warn(`[${this.getProviderName()}]
|
|
5877
|
-
return
|
|
6008
|
+
if (stringConfigKeys.includes(configKey)) {
|
|
6009
|
+
const stringFields = validFieldNames.filter((f) => fieldTypes[f] === "string");
|
|
6010
|
+
const match = stringFields.find((f) => f.toLowerCase().includes(lowerField) || lowerField.includes(f.toLowerCase()));
|
|
6011
|
+
if (match) return match;
|
|
6012
|
+
if (stringFields.length > 0) {
|
|
6013
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first string field: ${stringFields[0]}`);
|
|
6014
|
+
return stringFields[0];
|
|
5878
6015
|
}
|
|
5879
6016
|
}
|
|
5880
|
-
|
|
6017
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first field: ${validFieldNames[0]}`);
|
|
6018
|
+
return validFieldNames[0];
|
|
5881
6019
|
};
|
|
5882
6020
|
const configFieldsToValidate = [
|
|
5883
6021
|
"xAxisKey",
|
|
@@ -5896,12 +6034,10 @@ ${fieldsText}`;
|
|
|
5896
6034
|
const fieldValue = cleanedProps.config[configKey];
|
|
5897
6035
|
if (fieldValue && typeof fieldValue === "string") {
|
|
5898
6036
|
if (!validFieldNames.includes(fieldValue)) {
|
|
5899
|
-
const correctedField = findMatchingField(fieldValue);
|
|
6037
|
+
const correctedField = findMatchingField(fieldValue, configKey);
|
|
5900
6038
|
if (correctedField) {
|
|
5901
6039
|
logger.warn(`[${this.getProviderName()}] Correcting config.${configKey}: "${fieldValue}" \u2192 "${correctedField}"`);
|
|
5902
6040
|
cleanedProps.config[configKey] = correctedField;
|
|
5903
|
-
} else {
|
|
5904
|
-
logger.warn(`[${this.getProviderName()}] config.${configKey}="${fieldValue}" not found in outputSchema [${validFieldNames.join(", ")}]`);
|
|
5905
6041
|
}
|
|
5906
6042
|
}
|
|
5907
6043
|
}
|
|
@@ -5909,7 +6045,7 @@ ${fieldsText}`;
|
|
|
5909
6045
|
if (Array.isArray(cleanedProps.config.series)) {
|
|
5910
6046
|
cleanedProps.config.series = cleanedProps.config.series.map((s) => {
|
|
5911
6047
|
if (s.dataKey && typeof s.dataKey === "string" && !validFieldNames.includes(s.dataKey)) {
|
|
5912
|
-
const correctedField = findMatchingField(s.dataKey);
|
|
6048
|
+
const correctedField = findMatchingField(s.dataKey, "yAxisKey");
|
|
5913
6049
|
if (correctedField) {
|
|
5914
6050
|
logger.warn(`[${this.getProviderName()}] Correcting series.dataKey: "${s.dataKey}" \u2192 "${correctedField}"`);
|
|
5915
6051
|
return { ...s, dataKey: correctedField };
|
|
@@ -5976,6 +6112,10 @@ ${fieldsText}`;
|
|
|
5976
6112
|
AVAILABLE_TOOLS: availableToolsDoc,
|
|
5977
6113
|
SCHEMA_DOC: schemaDoc || "No database schema available"
|
|
5978
6114
|
});
|
|
6115
|
+
const systemPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
6116
|
+
const userPromptText = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
|
|
6117
|
+
logger.logLLMPrompt("classifyQuestionCategory", "system", systemPrompt);
|
|
6118
|
+
logger.logLLMPrompt("classifyQuestionCategory", "user", userPromptText);
|
|
5979
6119
|
const result = await LLM.stream(
|
|
5980
6120
|
{
|
|
5981
6121
|
sys: prompts.system,
|
|
@@ -6163,7 +6303,6 @@ ${fieldsText}`;
|
|
|
6163
6303
|
collections,
|
|
6164
6304
|
topK: 1
|
|
6165
6305
|
});
|
|
6166
|
-
logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
|
|
6167
6306
|
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
6168
6307
|
USER_PROMPT: userPrompt,
|
|
6169
6308
|
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
@@ -6172,8 +6311,10 @@ ${fieldsText}`;
|
|
|
6172
6311
|
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
|
|
6173
6312
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc
|
|
6174
6313
|
});
|
|
6175
|
-
|
|
6176
|
-
|
|
6314
|
+
const sysPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
6315
|
+
const usrPrompt = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
|
|
6316
|
+
logger.logLLMPrompt("generateTextResponse", "system", sysPrompt);
|
|
6317
|
+
logger.logLLMPrompt("generateTextResponse", "user", usrPrompt);
|
|
6177
6318
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6178
6319
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6179
6320
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6559,7 +6700,6 @@ ${errorMsg}
|
|
|
6559
6700
|
data: {
|
|
6560
6701
|
text: textResponse,
|
|
6561
6702
|
// Include the streamed text showing all attempts
|
|
6562
|
-
matchedComponents: [],
|
|
6563
6703
|
actions: [],
|
|
6564
6704
|
method: `${this.getProviderName()}-text-response-max-attempts`
|
|
6565
6705
|
}
|
|
@@ -6657,7 +6797,6 @@ ${errorMsg}
|
|
|
6657
6797
|
success: true,
|
|
6658
6798
|
data: {
|
|
6659
6799
|
text: textResponse,
|
|
6660
|
-
matchedComponents,
|
|
6661
6800
|
component: container_componet,
|
|
6662
6801
|
actions,
|
|
6663
6802
|
method: `${this.getProviderName()}-text-response`
|
|
@@ -6681,7 +6820,6 @@ ${errorMsg}
|
|
|
6681
6820
|
errors,
|
|
6682
6821
|
data: {
|
|
6683
6822
|
text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
|
|
6684
|
-
matchedComponents: [],
|
|
6685
6823
|
actions: [],
|
|
6686
6824
|
method: `${this.getProviderName()}-text-response-error`
|
|
6687
6825
|
}
|
|
@@ -6705,6 +6843,8 @@ ${errorMsg}
|
|
|
6705
6843
|
const startTime = Date.now();
|
|
6706
6844
|
logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
|
|
6707
6845
|
logCollector?.info(`Starting request processing with mode: ${responseMode}`);
|
|
6846
|
+
logger.clearFile();
|
|
6847
|
+
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
6708
6848
|
try {
|
|
6709
6849
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
6710
6850
|
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
@@ -6712,8 +6852,8 @@ ${errorMsg}
|
|
|
6712
6852
|
userPrompt,
|
|
6713
6853
|
collections,
|
|
6714
6854
|
userId,
|
|
6715
|
-
similarityThreshold: 0.
|
|
6716
|
-
//
|
|
6855
|
+
similarityThreshold: 0.8
|
|
6856
|
+
// 80% threshold
|
|
6717
6857
|
});
|
|
6718
6858
|
if (conversationMatch) {
|
|
6719
6859
|
logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
|
|
@@ -6738,7 +6878,6 @@ ${errorMsg}
|
|
|
6738
6878
|
data: {
|
|
6739
6879
|
text: cachedTextResponse,
|
|
6740
6880
|
component: null,
|
|
6741
|
-
matchedComponents: [],
|
|
6742
6881
|
actions: conversationMatch.uiBlock?.actions || [],
|
|
6743
6882
|
reasoning: `Exact match from previous general conversation`,
|
|
6744
6883
|
method: `${this.getProviderName()}-semantic-match-general`,
|
|
@@ -6766,7 +6905,6 @@ ${errorMsg}
|
|
|
6766
6905
|
data: {
|
|
6767
6906
|
text: cachedTextResponse,
|
|
6768
6907
|
component,
|
|
6769
|
-
matchedComponents: component?.props?.config?.components || [],
|
|
6770
6908
|
actions: cachedActions,
|
|
6771
6909
|
reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
|
|
6772
6910
|
method: `${this.getProviderName()}-semantic-match-exact`,
|
|
@@ -6802,7 +6940,6 @@ ${errorMsg}
|
|
|
6802
6940
|
data: {
|
|
6803
6941
|
text: textResponseToUse,
|
|
6804
6942
|
component: adaptResult.adaptedComponent,
|
|
6805
|
-
matchedComponents: adaptResult.adaptedComponent?.props?.config?.components || [],
|
|
6806
6943
|
actions: cachedActions,
|
|
6807
6944
|
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
6808
6945
|
method: `${this.getProviderName()}-semantic-match`,
|
|
@@ -6853,6 +6990,8 @@ ${errorMsg}
|
|
|
6853
6990
|
executionReason: t.executionReason || "",
|
|
6854
6991
|
requiredFields: t.requiredFields || [],
|
|
6855
6992
|
userProvidedData: t.userProvidedData || null,
|
|
6993
|
+
// CRITICAL: Include outputSchema from real tool for component config generation
|
|
6994
|
+
outputSchema: realTool?.outputSchema,
|
|
6856
6995
|
fn: (() => {
|
|
6857
6996
|
if (realTool) {
|
|
6858
6997
|
logger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);
|
|
@@ -10409,6 +10548,331 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10409
10548
|
sendMessage(response);
|
|
10410
10549
|
}
|
|
10411
10550
|
|
|
10551
|
+
// src/handlers/menus.ts
|
|
10552
|
+
init_logger();
|
|
10553
|
+
async function handleMenusRequest(data, collections, sendMessage) {
|
|
10554
|
+
const executeCollection = async (collection, op, params) => {
|
|
10555
|
+
const handler = collections[collection]?.[op];
|
|
10556
|
+
if (!handler) {
|
|
10557
|
+
throw new Error(`Collection operation ${collection}.${op} not found`);
|
|
10558
|
+
}
|
|
10559
|
+
return await handler(params);
|
|
10560
|
+
};
|
|
10561
|
+
try {
|
|
10562
|
+
const request = MenusRequestMessageSchema.parse(data);
|
|
10563
|
+
const { id, payload, from } = request;
|
|
10564
|
+
const { operation, data: requestData } = payload;
|
|
10565
|
+
const menuId = requestData?.id;
|
|
10566
|
+
const name = requestData?.name;
|
|
10567
|
+
const componentName = requestData?.componentName;
|
|
10568
|
+
const icon = requestData?.icon;
|
|
10569
|
+
const userMessage = requestData?.userMessage;
|
|
10570
|
+
const parentId = requestData?.parentId;
|
|
10571
|
+
const sortOrder = requestData?.sortOrder;
|
|
10572
|
+
const props = requestData?.props;
|
|
10573
|
+
const isActive = requestData?.isActive;
|
|
10574
|
+
const filters = requestData?.filters;
|
|
10575
|
+
const limit = requestData?.limit;
|
|
10576
|
+
const sort = requestData?.sort;
|
|
10577
|
+
const items = requestData?.items;
|
|
10578
|
+
switch (operation) {
|
|
10579
|
+
case "create":
|
|
10580
|
+
await handleCreate7(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, from.id);
|
|
10581
|
+
break;
|
|
10582
|
+
case "update":
|
|
10583
|
+
await handleUpdate7(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, from.id);
|
|
10584
|
+
break;
|
|
10585
|
+
case "delete":
|
|
10586
|
+
await handleDelete7(id, menuId, executeCollection, sendMessage, from.id);
|
|
10587
|
+
break;
|
|
10588
|
+
case "getAll":
|
|
10589
|
+
await handleGetAll7(id, executeCollection, sendMessage, from.id);
|
|
10590
|
+
break;
|
|
10591
|
+
case "getOne":
|
|
10592
|
+
await handleGetOne7(id, menuId, executeCollection, sendMessage, from.id);
|
|
10593
|
+
break;
|
|
10594
|
+
case "getRootMenus":
|
|
10595
|
+
await handleGetRootMenus(id, executeCollection, sendMessage, from.id);
|
|
10596
|
+
break;
|
|
10597
|
+
case "getChildMenus":
|
|
10598
|
+
await handleGetChildMenus(id, parentId, executeCollection, sendMessage, from.id);
|
|
10599
|
+
break;
|
|
10600
|
+
case "getHierarchy":
|
|
10601
|
+
await handleGetHierarchy(id, executeCollection, sendMessage, from.id);
|
|
10602
|
+
break;
|
|
10603
|
+
case "query":
|
|
10604
|
+
await handleQuery6(id, filters, limit, sort, executeCollection, sendMessage, from.id);
|
|
10605
|
+
break;
|
|
10606
|
+
case "reorder":
|
|
10607
|
+
await handleReorder(id, items, executeCollection, sendMessage, from.id);
|
|
10608
|
+
break;
|
|
10609
|
+
default:
|
|
10610
|
+
sendResponse9(id, {
|
|
10611
|
+
success: false,
|
|
10612
|
+
error: `Unknown operation: ${operation}`
|
|
10613
|
+
}, sendMessage, from.id);
|
|
10614
|
+
}
|
|
10615
|
+
} catch (error) {
|
|
10616
|
+
logger.error("Failed to handle menus request:", error);
|
|
10617
|
+
sendResponse9(null, {
|
|
10618
|
+
success: false,
|
|
10619
|
+
error: error instanceof Error ? error.message : "Unknown error occurred"
|
|
10620
|
+
}, sendMessage);
|
|
10621
|
+
}
|
|
10622
|
+
}
|
|
10623
|
+
async function handleCreate7(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
|
|
10624
|
+
if (!name) {
|
|
10625
|
+
sendResponse9(id, {
|
|
10626
|
+
success: false,
|
|
10627
|
+
error: "name is required"
|
|
10628
|
+
}, sendMessage, clientId);
|
|
10629
|
+
return;
|
|
10630
|
+
}
|
|
10631
|
+
if (!componentName) {
|
|
10632
|
+
sendResponse9(id, {
|
|
10633
|
+
success: false,
|
|
10634
|
+
error: "componentName is required"
|
|
10635
|
+
}, sendMessage, clientId);
|
|
10636
|
+
return;
|
|
10637
|
+
}
|
|
10638
|
+
try {
|
|
10639
|
+
const result = await executeCollection("menus", "create", {
|
|
10640
|
+
name,
|
|
10641
|
+
componentName,
|
|
10642
|
+
icon,
|
|
10643
|
+
userMessage,
|
|
10644
|
+
parentId,
|
|
10645
|
+
sortOrder,
|
|
10646
|
+
props,
|
|
10647
|
+
isActive
|
|
10648
|
+
});
|
|
10649
|
+
sendResponse9(id, {
|
|
10650
|
+
success: true,
|
|
10651
|
+
data: result.data,
|
|
10652
|
+
message: "Menu created successfully"
|
|
10653
|
+
}, sendMessage, clientId);
|
|
10654
|
+
logger.info(`Menu created: ID ${result.data?.id}`);
|
|
10655
|
+
} catch (error) {
|
|
10656
|
+
sendResponse9(id, {
|
|
10657
|
+
success: false,
|
|
10658
|
+
error: error instanceof Error ? error.message : "Failed to create menu"
|
|
10659
|
+
}, sendMessage, clientId);
|
|
10660
|
+
}
|
|
10661
|
+
}
|
|
10662
|
+
async function handleUpdate7(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
|
|
10663
|
+
if (!menuId) {
|
|
10664
|
+
sendResponse9(id, {
|
|
10665
|
+
success: false,
|
|
10666
|
+
error: "Menu ID is required"
|
|
10667
|
+
}, sendMessage, clientId);
|
|
10668
|
+
return;
|
|
10669
|
+
}
|
|
10670
|
+
try {
|
|
10671
|
+
const result = await executeCollection("menus", "update", {
|
|
10672
|
+
id: menuId,
|
|
10673
|
+
name,
|
|
10674
|
+
componentName,
|
|
10675
|
+
icon,
|
|
10676
|
+
userMessage,
|
|
10677
|
+
parentId,
|
|
10678
|
+
sortOrder,
|
|
10679
|
+
props,
|
|
10680
|
+
isActive
|
|
10681
|
+
});
|
|
10682
|
+
sendResponse9(id, {
|
|
10683
|
+
success: true,
|
|
10684
|
+
data: result.data,
|
|
10685
|
+
message: "Menu updated successfully"
|
|
10686
|
+
}, sendMessage, clientId);
|
|
10687
|
+
logger.info(`Menu updated: ID ${menuId}`);
|
|
10688
|
+
} catch (error) {
|
|
10689
|
+
sendResponse9(id, {
|
|
10690
|
+
success: false,
|
|
10691
|
+
error: error instanceof Error ? error.message : "Failed to update menu"
|
|
10692
|
+
}, sendMessage, clientId);
|
|
10693
|
+
}
|
|
10694
|
+
}
|
|
10695
|
+
async function handleDelete7(id, menuId, executeCollection, sendMessage, clientId) {
|
|
10696
|
+
if (!menuId) {
|
|
10697
|
+
sendResponse9(id, {
|
|
10698
|
+
success: false,
|
|
10699
|
+
error: "Menu ID is required"
|
|
10700
|
+
}, sendMessage, clientId);
|
|
10701
|
+
return;
|
|
10702
|
+
}
|
|
10703
|
+
try {
|
|
10704
|
+
const result = await executeCollection("menus", "delete", { id: menuId });
|
|
10705
|
+
sendResponse9(id, {
|
|
10706
|
+
success: true,
|
|
10707
|
+
data: result.data,
|
|
10708
|
+
message: "Menu deleted successfully"
|
|
10709
|
+
}, sendMessage, clientId);
|
|
10710
|
+
logger.info(`Menu deleted: ID ${menuId}`);
|
|
10711
|
+
} catch (error) {
|
|
10712
|
+
sendResponse9(id, {
|
|
10713
|
+
success: false,
|
|
10714
|
+
error: error instanceof Error ? error.message : "Failed to delete menu"
|
|
10715
|
+
}, sendMessage, clientId);
|
|
10716
|
+
}
|
|
10717
|
+
}
|
|
10718
|
+
async function handleGetAll7(id, executeCollection, sendMessage, clientId) {
|
|
10719
|
+
try {
|
|
10720
|
+
const result = await executeCollection("menus", "getAll", {});
|
|
10721
|
+
sendResponse9(id, {
|
|
10722
|
+
success: true,
|
|
10723
|
+
data: result.data,
|
|
10724
|
+
count: result.count,
|
|
10725
|
+
message: `Retrieved ${result.count} menus`
|
|
10726
|
+
}, sendMessage, clientId);
|
|
10727
|
+
logger.info(`Retrieved all menus (count: ${result.count})`);
|
|
10728
|
+
} catch (error) {
|
|
10729
|
+
sendResponse9(id, {
|
|
10730
|
+
success: false,
|
|
10731
|
+
error: error instanceof Error ? error.message : "Failed to get menus"
|
|
10732
|
+
}, sendMessage, clientId);
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
async function handleGetOne7(id, menuId, executeCollection, sendMessage, clientId) {
|
|
10736
|
+
if (!menuId) {
|
|
10737
|
+
sendResponse9(id, {
|
|
10738
|
+
success: false,
|
|
10739
|
+
error: "Menu ID is required"
|
|
10740
|
+
}, sendMessage, clientId);
|
|
10741
|
+
return;
|
|
10742
|
+
}
|
|
10743
|
+
try {
|
|
10744
|
+
const result = await executeCollection("menus", "getOne", { id: menuId });
|
|
10745
|
+
sendResponse9(id, {
|
|
10746
|
+
success: true,
|
|
10747
|
+
data: result.data,
|
|
10748
|
+
message: `Retrieved menu ID ${menuId}`
|
|
10749
|
+
}, sendMessage, clientId);
|
|
10750
|
+
logger.info(`Retrieved menu: ID ${menuId}`);
|
|
10751
|
+
} catch (error) {
|
|
10752
|
+
sendResponse9(id, {
|
|
10753
|
+
success: false,
|
|
10754
|
+
error: error instanceof Error ? error.message : "Failed to get menu"
|
|
10755
|
+
}, sendMessage, clientId);
|
|
10756
|
+
}
|
|
10757
|
+
}
|
|
10758
|
+
async function handleGetRootMenus(id, executeCollection, sendMessage, clientId) {
|
|
10759
|
+
try {
|
|
10760
|
+
const result = await executeCollection("menus", "getRootMenus", {});
|
|
10761
|
+
sendResponse9(id, {
|
|
10762
|
+
success: true,
|
|
10763
|
+
data: result.data,
|
|
10764
|
+
count: result.count,
|
|
10765
|
+
message: `Retrieved ${result.count} root menus`
|
|
10766
|
+
}, sendMessage, clientId);
|
|
10767
|
+
logger.info(`Retrieved root menus (count: ${result.count})`);
|
|
10768
|
+
} catch (error) {
|
|
10769
|
+
sendResponse9(id, {
|
|
10770
|
+
success: false,
|
|
10771
|
+
error: error instanceof Error ? error.message : "Failed to get root menus"
|
|
10772
|
+
}, sendMessage, clientId);
|
|
10773
|
+
}
|
|
10774
|
+
}
|
|
10775
|
+
async function handleGetChildMenus(id, parentId, executeCollection, sendMessage, clientId) {
|
|
10776
|
+
if (parentId === void 0 || parentId === null) {
|
|
10777
|
+
sendResponse9(id, {
|
|
10778
|
+
success: false,
|
|
10779
|
+
error: "parentId is required"
|
|
10780
|
+
}, sendMessage, clientId);
|
|
10781
|
+
return;
|
|
10782
|
+
}
|
|
10783
|
+
try {
|
|
10784
|
+
const result = await executeCollection("menus", "getChildMenus", { parentId });
|
|
10785
|
+
sendResponse9(id, {
|
|
10786
|
+
success: true,
|
|
10787
|
+
data: result.data,
|
|
10788
|
+
count: result.count,
|
|
10789
|
+
message: `Retrieved ${result.count} child menus for parent ${parentId}`
|
|
10790
|
+
}, sendMessage, clientId);
|
|
10791
|
+
logger.info(`Retrieved child menus for parent ${parentId} (count: ${result.count})`);
|
|
10792
|
+
} catch (error) {
|
|
10793
|
+
sendResponse9(id, {
|
|
10794
|
+
success: false,
|
|
10795
|
+
error: error instanceof Error ? error.message : "Failed to get child menus"
|
|
10796
|
+
}, sendMessage, clientId);
|
|
10797
|
+
}
|
|
10798
|
+
}
|
|
10799
|
+
async function handleGetHierarchy(id, executeCollection, sendMessage, clientId) {
|
|
10800
|
+
try {
|
|
10801
|
+
const result = await executeCollection("menus", "getHierarchy", {});
|
|
10802
|
+
sendResponse9(id, {
|
|
10803
|
+
success: true,
|
|
10804
|
+
data: result.data,
|
|
10805
|
+
count: result.count,
|
|
10806
|
+
message: `Retrieved menus hierarchy with ${result.count} root items`
|
|
10807
|
+
}, sendMessage, clientId);
|
|
10808
|
+
logger.info(`Retrieved menus hierarchy (root count: ${result.count})`);
|
|
10809
|
+
} catch (error) {
|
|
10810
|
+
sendResponse9(id, {
|
|
10811
|
+
success: false,
|
|
10812
|
+
error: error instanceof Error ? error.message : "Failed to get menus hierarchy"
|
|
10813
|
+
}, sendMessage, clientId);
|
|
10814
|
+
}
|
|
10815
|
+
}
|
|
10816
|
+
async function handleQuery6(id, filters, limit, sort, executeCollection, sendMessage, clientId) {
|
|
10817
|
+
try {
|
|
10818
|
+
const result = await executeCollection("menus", "query", {
|
|
10819
|
+
filters: filters || {},
|
|
10820
|
+
limit,
|
|
10821
|
+
sort
|
|
10822
|
+
});
|
|
10823
|
+
sendResponse9(id, {
|
|
10824
|
+
success: true,
|
|
10825
|
+
data: result.data,
|
|
10826
|
+
count: result.count,
|
|
10827
|
+
message: `Query returned ${result.count} menus`
|
|
10828
|
+
}, sendMessage, clientId);
|
|
10829
|
+
logger.info(`Query returned ${result.count} menus`);
|
|
10830
|
+
} catch (error) {
|
|
10831
|
+
sendResponse9(id, {
|
|
10832
|
+
success: false,
|
|
10833
|
+
error: error instanceof Error ? error.message : "Failed to query menus"
|
|
10834
|
+
}, sendMessage, clientId);
|
|
10835
|
+
}
|
|
10836
|
+
}
|
|
10837
|
+
async function handleReorder(id, items, executeCollection, sendMessage, clientId) {
|
|
10838
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
10839
|
+
sendResponse9(id, {
|
|
10840
|
+
success: false,
|
|
10841
|
+
error: "items array is required"
|
|
10842
|
+
}, sendMessage, clientId);
|
|
10843
|
+
return;
|
|
10844
|
+
}
|
|
10845
|
+
try {
|
|
10846
|
+
const result = await executeCollection("menus", "reorder", { items });
|
|
10847
|
+
sendResponse9(id, {
|
|
10848
|
+
success: true,
|
|
10849
|
+
data: result.data,
|
|
10850
|
+
message: `Reordered ${items.length} menus successfully`
|
|
10851
|
+
}, sendMessage, clientId);
|
|
10852
|
+
logger.info(`Reordered ${items.length} menus`);
|
|
10853
|
+
} catch (error) {
|
|
10854
|
+
sendResponse9(id, {
|
|
10855
|
+
success: false,
|
|
10856
|
+
error: error instanceof Error ? error.message : "Failed to reorder menus"
|
|
10857
|
+
}, sendMessage, clientId);
|
|
10858
|
+
}
|
|
10859
|
+
}
|
|
10860
|
+
function sendResponse9(id, res, sendMessage, clientId) {
|
|
10861
|
+
const response = {
|
|
10862
|
+
id: id || "unknown",
|
|
10863
|
+
type: "MENUS_RES",
|
|
10864
|
+
from: { type: "data-agent" },
|
|
10865
|
+
to: {
|
|
10866
|
+
type: "admin",
|
|
10867
|
+
id: clientId
|
|
10868
|
+
},
|
|
10869
|
+
payload: {
|
|
10870
|
+
...res
|
|
10871
|
+
}
|
|
10872
|
+
};
|
|
10873
|
+
sendMessage(response);
|
|
10874
|
+
}
|
|
10875
|
+
|
|
10412
10876
|
// src/dashComp/index.ts
|
|
10413
10877
|
init_logger();
|
|
10414
10878
|
|
|
@@ -10535,37 +10999,74 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10535
10999
|
return { success: false, errors };
|
|
10536
11000
|
}
|
|
10537
11001
|
logger.info(`[DASH_COMP_REQ] Using model: ${model}`);
|
|
10538
|
-
const
|
|
11002
|
+
const executedTools = [];
|
|
11003
|
+
const llmTools = (tools || []).map((tool) => ({
|
|
11004
|
+
name: tool.id,
|
|
11005
|
+
description: tool.description,
|
|
11006
|
+
input_schema: {
|
|
11007
|
+
type: "object",
|
|
11008
|
+
properties: Object.fromEntries(
|
|
11009
|
+
Object.entries(tool.params || {}).map(([key, val]) => [key, { type: typeof val === "string" && ["string", "number", "boolean", "integer"].includes(val.toLowerCase()) ? val.toLowerCase() : "string", description: `${key} parameter` }])
|
|
11010
|
+
),
|
|
11011
|
+
additionalProperties: false
|
|
11012
|
+
}
|
|
11013
|
+
}));
|
|
11014
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
11015
|
+
const tool = tools?.find((t) => t.id === toolName);
|
|
11016
|
+
if (!tool) {
|
|
11017
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
11018
|
+
}
|
|
11019
|
+
logger.info(`[DASH_COMP_REQ] Executing external tool: ${tool.name} (${tool.id})`);
|
|
11020
|
+
const result2 = await tool.fn(toolInput);
|
|
11021
|
+
executedTools.push({
|
|
11022
|
+
id: tool.id,
|
|
11023
|
+
name: tool.name,
|
|
11024
|
+
params: toolInput,
|
|
11025
|
+
result: result2,
|
|
11026
|
+
outputSchema: tool.outputSchema
|
|
11027
|
+
});
|
|
11028
|
+
logger.info(`[DASH_COMP_REQ] Tool ${tool.name} executed successfully`);
|
|
11029
|
+
return JSON.stringify(result2, null, 2);
|
|
11030
|
+
};
|
|
11031
|
+
const result = await LLM.streamWithTools(
|
|
10539
11032
|
{
|
|
10540
11033
|
sys: prompts.system,
|
|
10541
11034
|
user: prompts.user
|
|
10542
11035
|
},
|
|
11036
|
+
llmTools,
|
|
11037
|
+
toolHandler,
|
|
10543
11038
|
{
|
|
10544
11039
|
model,
|
|
10545
11040
|
maxTokens: 8192,
|
|
10546
11041
|
temperature: 0.2,
|
|
10547
11042
|
apiKey
|
|
10548
11043
|
},
|
|
10549
|
-
|
|
10550
|
-
//
|
|
11044
|
+
5
|
|
11045
|
+
// max iterations
|
|
10551
11046
|
);
|
|
11047
|
+
const jsonMatch = result.match(/\{[\s\S]*\}/);
|
|
11048
|
+
const parsedResult = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
11049
|
+
if (!parsedResult) {
|
|
11050
|
+
errors.push("Failed to parse LLM response as JSON");
|
|
11051
|
+
return { success: false, errors };
|
|
11052
|
+
}
|
|
10552
11053
|
logger.debug("[DASH_COMP_REQ] LLM response received");
|
|
10553
|
-
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(
|
|
10554
|
-
if (!
|
|
11054
|
+
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
|
|
11055
|
+
if (!parsedResult.componentId || !parsedResult.props) {
|
|
10555
11056
|
errors.push("Invalid LLM response: missing componentId or props");
|
|
10556
11057
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
|
|
10557
11058
|
prompt,
|
|
10558
|
-
result,
|
|
10559
|
-
missingFields: { componentId: !
|
|
11059
|
+
result: parsedResult,
|
|
11060
|
+
missingFields: { componentId: !parsedResult.componentId, props: !parsedResult.props }
|
|
10560
11061
|
});
|
|
10561
11062
|
return { success: false, errors };
|
|
10562
11063
|
}
|
|
10563
|
-
const originalComponent = components.find((c) => c.name ===
|
|
11064
|
+
const originalComponent = components.find((c) => c.name === parsedResult.componentName);
|
|
10564
11065
|
if (!originalComponent) {
|
|
10565
|
-
errors.push(`Component ${
|
|
11066
|
+
errors.push(`Component ${parsedResult.componentName} not found in available components`);
|
|
10566
11067
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
10567
11068
|
prompt,
|
|
10568
|
-
componentName:
|
|
11069
|
+
componentName: parsedResult.componentName,
|
|
10569
11070
|
availableComponentNames: components.map((c) => c.name)
|
|
10570
11071
|
});
|
|
10571
11072
|
return { success: false, errors };
|
|
@@ -10574,23 +11075,27 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10574
11075
|
...originalComponent,
|
|
10575
11076
|
props: {
|
|
10576
11077
|
...originalComponent.props,
|
|
10577
|
-
...
|
|
11078
|
+
...parsedResult.props
|
|
10578
11079
|
}
|
|
10579
11080
|
};
|
|
10580
11081
|
logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
|
|
10581
|
-
if (
|
|
11082
|
+
if (parsedResult.props.query) {
|
|
10582
11083
|
logger.info(`[DASH_COMP_REQ] Data source: Database query`);
|
|
10583
11084
|
}
|
|
10584
|
-
if (
|
|
10585
|
-
logger.info(`[DASH_COMP_REQ] Data source: External tool - ${
|
|
11085
|
+
if (parsedResult.props.externalTool) {
|
|
11086
|
+
logger.info(`[DASH_COMP_REQ] Data source: External tool - ${parsedResult.props.externalTool.toolName}`);
|
|
11087
|
+
}
|
|
11088
|
+
if (executedTools.length > 0) {
|
|
11089
|
+
logger.info(`[DASH_COMP_REQ] Executed ${executedTools.length} external tool(s): ${executedTools.map((t) => t.name).join(", ")}`);
|
|
10586
11090
|
}
|
|
10587
11091
|
return {
|
|
10588
11092
|
success: true,
|
|
10589
11093
|
data: {
|
|
10590
11094
|
component: finalComponent,
|
|
10591
|
-
reasoning:
|
|
10592
|
-
dataSource:
|
|
10593
|
-
isUpdate:
|
|
11095
|
+
reasoning: parsedResult.reasoning || "Component selected based on user prompt",
|
|
11096
|
+
dataSource: parsedResult.props.query ? "database" : parsedResult.props.externalTool ? "external_tool" : "none",
|
|
11097
|
+
isUpdate: parsedResult.isUpdate || false,
|
|
11098
|
+
executedTools: executedTools.length > 0 ? executedTools : void 0
|
|
10594
11099
|
},
|
|
10595
11100
|
errors: []
|
|
10596
11101
|
};
|
|
@@ -10643,11 +11148,49 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10643
11148
|
return { success: false, errors };
|
|
10644
11149
|
}
|
|
10645
11150
|
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10646
|
-
const
|
|
11151
|
+
const executedTools = [];
|
|
11152
|
+
const llmTools = (tools || []).map((tool) => ({
|
|
11153
|
+
name: tool.id,
|
|
11154
|
+
description: tool.description,
|
|
11155
|
+
input_schema: {
|
|
11156
|
+
type: "object",
|
|
11157
|
+
properties: Object.fromEntries(
|
|
11158
|
+
Object.entries(tool.params || {}).map(([key, val]) => [key, { type: typeof val === "string" && ["string", "number", "boolean", "integer"].includes(val.toLowerCase()) ? val.toLowerCase() : "string", description: `${key} parameter` }])
|
|
11159
|
+
),
|
|
11160
|
+
additionalProperties: false
|
|
11161
|
+
}
|
|
11162
|
+
}));
|
|
11163
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
11164
|
+
const tool = tools?.find((t) => t.id === toolName);
|
|
11165
|
+
if (!tool) {
|
|
11166
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
11167
|
+
}
|
|
11168
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Executing external tool: ${tool.name} (${tool.id})`);
|
|
11169
|
+
const result2 = await tool.fn(toolInput);
|
|
11170
|
+
executedTools.push({
|
|
11171
|
+
id: tool.id,
|
|
11172
|
+
name: tool.name,
|
|
11173
|
+
params: toolInput,
|
|
11174
|
+
result: result2,
|
|
11175
|
+
outputSchema: tool.outputSchema
|
|
11176
|
+
});
|
|
11177
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Tool ${tool.name} executed successfully`);
|
|
11178
|
+
return JSON.stringify(result2, null, 2);
|
|
11179
|
+
};
|
|
11180
|
+
const rawResult = await LLM.streamWithTools(
|
|
10647
11181
|
{ sys: prompts.system, user: prompts.user },
|
|
11182
|
+
llmTools,
|
|
11183
|
+
toolHandler,
|
|
10648
11184
|
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10649
|
-
|
|
11185
|
+
5
|
|
11186
|
+
// max iterations
|
|
10650
11187
|
);
|
|
11188
|
+
const jsonMatch = rawResult.match(/\{[\s\S]*\}/);
|
|
11189
|
+
const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
11190
|
+
if (!result) {
|
|
11191
|
+
errors.push("Failed to parse LLM response as JSON");
|
|
11192
|
+
return { success: false, errors };
|
|
11193
|
+
}
|
|
10651
11194
|
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10652
11195
|
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10653
11196
|
if (!result.filterComponent) {
|
|
@@ -10661,13 +11204,17 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10661
11204
|
}
|
|
10662
11205
|
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10663
11206
|
logger.info(`[DASH_COMP_REQ:FILTER] Updated ${result.updatedComponents?.length || 0} components`);
|
|
11207
|
+
if (executedTools.length > 0) {
|
|
11208
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Executed ${executedTools.length} external tool(s): ${executedTools.map((t) => t.name).join(", ")}`);
|
|
11209
|
+
}
|
|
10664
11210
|
return {
|
|
10665
11211
|
success: true,
|
|
10666
11212
|
data: {
|
|
10667
11213
|
filterComponent: result.filterComponent,
|
|
10668
11214
|
updatedComponents: result.updatedComponents || [],
|
|
10669
11215
|
filterBindings: result.filterBindings || {},
|
|
10670
|
-
reasoning: result.reasoning || "Filter created based on user prompt"
|
|
11216
|
+
reasoning: result.reasoning || "Filter created based on user prompt",
|
|
11217
|
+
executedTools: executedTools.length > 0 ? executedTools : void 0
|
|
10671
11218
|
},
|
|
10672
11219
|
errors: []
|
|
10673
11220
|
};
|
|
@@ -11845,6 +12392,11 @@ var SuperatomSDK = class {
|
|
|
11845
12392
|
logger.error("Failed to handle KB nodes request:", error);
|
|
11846
12393
|
});
|
|
11847
12394
|
break;
|
|
12395
|
+
case "MENUS":
|
|
12396
|
+
handleMenusRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
|
|
12397
|
+
logger.error("Failed to handle menus request:", error);
|
|
12398
|
+
});
|
|
12399
|
+
break;
|
|
11848
12400
|
case "DASH_COMP_REQ":
|
|
11849
12401
|
handleDashCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
|
|
11850
12402
|
logger.error("Failed to handle dash comp request:", error);
|