@superatomai/sdk-node 0.0.50 → 0.0.53
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/README.md +942 -942
- package/dist/index.d.mts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +672 -52
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +672 -52
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,13 +31,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
33
|
// src/utils/logger.ts
|
|
34
|
-
var import_fs, PREFIX, LOGSTREAM, LOG_LEVEL_PRIORITY, MESSAGE_LEVEL_PRIORITY, Logger, logger;
|
|
34
|
+
var import_fs, PREFIX, LOG_FILE_PATH, LOGSTREAM, LOG_LEVEL_PRIORITY, MESSAGE_LEVEL_PRIORITY, Logger, logger;
|
|
35
35
|
var init_logger = __esm({
|
|
36
36
|
"src/utils/logger.ts"() {
|
|
37
37
|
"use strict";
|
|
38
38
|
import_fs = __toESM(require("fs"));
|
|
39
39
|
PREFIX = "[SuperatomSDK]";
|
|
40
|
-
|
|
40
|
+
LOG_FILE_PATH = "superatom-sdk.log";
|
|
41
|
+
LOGSTREAM = import_fs.default.createWriteStream(LOG_FILE_PATH, { flags: "a" });
|
|
41
42
|
LOG_LEVEL_PRIORITY = {
|
|
42
43
|
errors: 0,
|
|
43
44
|
warnings: 1,
|
|
@@ -121,9 +122,43 @@ var init_logger = __esm({
|
|
|
121
122
|
console.log(PREFIX, "[DEBUG]", ...args);
|
|
122
123
|
}
|
|
123
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Write to log file
|
|
127
|
+
*/
|
|
124
128
|
file(...args) {
|
|
125
129
|
LOGSTREAM.write(args.join(" ") + "\n");
|
|
126
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Clear the log file (call at start of new user request)
|
|
133
|
+
*/
|
|
134
|
+
clearFile() {
|
|
135
|
+
LOGSTREAM.end();
|
|
136
|
+
LOGSTREAM = import_fs.default.createWriteStream(LOG_FILE_PATH, { flags: "w" });
|
|
137
|
+
LOGSTREAM.write(`
|
|
138
|
+
${"=".repeat(80)}
|
|
139
|
+
`);
|
|
140
|
+
LOGSTREAM.write(`NEW REQUEST - ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
141
|
+
`);
|
|
142
|
+
LOGSTREAM.write(`${"=".repeat(80)}
|
|
143
|
+
|
|
144
|
+
`);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Log LLM method prompts with clear labeling
|
|
148
|
+
*/
|
|
149
|
+
logLLMPrompt(methodName, promptType, content) {
|
|
150
|
+
const header = `
|
|
151
|
+
${"#".repeat(80)}
|
|
152
|
+
[LLM METHOD: ${methodName}] - ${promptType.toUpperCase()} PROMPT
|
|
153
|
+
${"#".repeat(80)}
|
|
154
|
+
`;
|
|
155
|
+
LOGSTREAM.write(header);
|
|
156
|
+
LOGSTREAM.write(content);
|
|
157
|
+
LOGSTREAM.write(`
|
|
158
|
+
${"#".repeat(80)}
|
|
159
|
+
|
|
160
|
+
`);
|
|
161
|
+
}
|
|
127
162
|
};
|
|
128
163
|
logger = new Logger();
|
|
129
164
|
}
|
|
@@ -1041,8 +1076,20 @@ If adaptation is not possible or would fundamentally change the component:
|
|
|
1041
1076
|
|
|
1042
1077
|
Analyze the user's request and:
|
|
1043
1078
|
1. **Select the most appropriate component** from the available components list
|
|
1044
|
-
2. **Determine the data source**: Database query OR External tool
|
|
1045
|
-
3. **Generate complete props** for the selected component
|
|
1079
|
+
2. **Determine the data source**: Database query OR External tool
|
|
1080
|
+
3. **Generate complete props** for the selected component
|
|
1081
|
+
|
|
1082
|
+
## Available External Tools
|
|
1083
|
+
|
|
1084
|
+
The following external tools are available:
|
|
1085
|
+
|
|
1086
|
+
{{AVAILABLE_TOOLS}}
|
|
1087
|
+
|
|
1088
|
+
When a tool is needed to complete the user's request:
|
|
1089
|
+
1. **Analyze the request** to determine which tool is needed
|
|
1090
|
+
2. **Extract parameters** from the user's question
|
|
1091
|
+
3. **Execute the tool** by calling it with the extracted parameters
|
|
1092
|
+
4. **Use the results** to configure the component (field names for axes, columns, etc.)
|
|
1046
1093
|
|
|
1047
1094
|
## Component Selection Rules
|
|
1048
1095
|
|
|
@@ -1198,7 +1245,20 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1198
1245
|
|
|
1199
1246
|
1. **Create a filter component** based on the user's request
|
|
1200
1247
|
2. **Update existing components** with dynamic title/description interpolation if needed
|
|
1201
|
-
3. **
|
|
1248
|
+
3. **Set default values in component externalTool.params** that match the filter's default option
|
|
1249
|
+
4. **Preserve all existing props** - the filter system handles param merging at runtime
|
|
1250
|
+
|
|
1251
|
+
## Available External Tools
|
|
1252
|
+
|
|
1253
|
+
The following external tools are available:
|
|
1254
|
+
|
|
1255
|
+
{{AVAILABLE_TOOLS}}
|
|
1256
|
+
|
|
1257
|
+
When a tool is needed to complete the user's request:
|
|
1258
|
+
1. **Analyze the request** to determine which tool is needed
|
|
1259
|
+
2. **Extract parameters** from the user's question
|
|
1260
|
+
3. **Execute the tool** by calling it with the extracted parameters
|
|
1261
|
+
4. **Use the results** to configure the filter and components properly
|
|
1202
1262
|
|
|
1203
1263
|
## How The Filter System Works
|
|
1204
1264
|
|
|
@@ -1228,16 +1288,20 @@ Use \`{%filterKeyLabel%}\` syntax for dynamic text:
|
|
|
1228
1288
|
## Updating Existing Components
|
|
1229
1289
|
|
|
1230
1290
|
**IMPORTANT - Parameter Handling:**
|
|
1231
|
-
- Do NOT change existing parameter values to placeholders
|
|
1232
|
-
- Keep all existing/default parameter values as they are
|
|
1233
1291
|
- The filter system MERGES params at runtime: filter params override component defaults
|
|
1292
|
+
- Component's \`externalTool.params\` should have DEFAULT values matching the filter's default option
|
|
1293
|
+
- This ensures the component shows correct data on initial load before user changes the filter
|
|
1234
1294
|
|
|
1235
1295
|
**What to modify in existing components:**
|
|
1236
1296
|
- Modify \`title\` for \`{%filterKeyLabel%}\` interpolation (only if title exists)
|
|
1237
1297
|
- Modify \`description\` for interpolation (only if description exists)
|
|
1238
|
-
-
|
|
1298
|
+
- Set \`externalTool.params\` default values to match filter's default option params
|
|
1239
1299
|
- Copy ALL other props exactly as provided
|
|
1240
1300
|
|
|
1301
|
+
**Example - Setting default params:**
|
|
1302
|
+
If filter has default option with params: \`{ startDate: "2025-01-01", endDate: "2025-01-31" }\`
|
|
1303
|
+
Then component's externalTool should have: \`{ params: { startDate: "2025-01-01", endDate: "2025-01-31" } }\`
|
|
1304
|
+
|
|
1241
1305
|
### Database Query Rules
|
|
1242
1306
|
{{DATABASE_RULES}}
|
|
1243
1307
|
|
|
@@ -1285,10 +1349,11 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1285
1349
|
**CRITICAL RULES:**
|
|
1286
1350
|
1. Return ONLY valid JSON (no markdown code blocks)
|
|
1287
1351
|
2. **COPY ALL existing props** - modify title/description for interpolation only if they exist
|
|
1288
|
-
3. **
|
|
1352
|
+
3. **Set externalTool.params defaults** to match the filter's default option params
|
|
1289
1353
|
4. Use \`{%filterKeyLabel%}\` for dynamic text (NOT \`{{...}}\` or \`$...\`)
|
|
1290
1354
|
5. Filter \`params\` must have ACTUAL values (real dates, strings), not placeholders
|
|
1291
1355
|
6. Each filter option needs: label, value, params (and optionally isDefault)
|
|
1356
|
+
7. Component default params MUST match filter default - this ensures correct initial data load
|
|
1292
1357
|
|
|
1293
1358
|
## Database Schema
|
|
1294
1359
|
{{SCHEMA_DOC}}
|
|
@@ -2359,6 +2424,57 @@ var KbNodesRequestMessageSchema = import_zod3.z.object({
|
|
|
2359
2424
|
type: import_zod3.z.literal("KB_NODES"),
|
|
2360
2425
|
payload: KbNodesRequestPayloadSchema
|
|
2361
2426
|
});
|
|
2427
|
+
var MenusQueryFiltersSchema = import_zod3.z.object({
|
|
2428
|
+
parentId: import_zod3.z.number().nullable().optional(),
|
|
2429
|
+
isActive: import_zod3.z.boolean().optional()
|
|
2430
|
+
});
|
|
2431
|
+
var MenusRequestPayloadSchema = import_zod3.z.object({
|
|
2432
|
+
operation: import_zod3.z.enum([
|
|
2433
|
+
"create",
|
|
2434
|
+
"update",
|
|
2435
|
+
"delete",
|
|
2436
|
+
"getAll",
|
|
2437
|
+
"getOne",
|
|
2438
|
+
"getRootMenus",
|
|
2439
|
+
"getChildMenus",
|
|
2440
|
+
"getHierarchy",
|
|
2441
|
+
"query",
|
|
2442
|
+
"reorder"
|
|
2443
|
+
]),
|
|
2444
|
+
data: import_zod3.z.object({
|
|
2445
|
+
id: import_zod3.z.number().optional(),
|
|
2446
|
+
name: import_zod3.z.string().optional(),
|
|
2447
|
+
componentName: import_zod3.z.string().optional(),
|
|
2448
|
+
icon: import_zod3.z.string().optional(),
|
|
2449
|
+
userMessage: import_zod3.z.string().optional(),
|
|
2450
|
+
parentId: import_zod3.z.number().nullable().optional(),
|
|
2451
|
+
sortOrder: import_zod3.z.number().optional(),
|
|
2452
|
+
props: import_zod3.z.record(import_zod3.z.unknown()).optional(),
|
|
2453
|
+
isActive: import_zod3.z.boolean().optional(),
|
|
2454
|
+
// Query operation fields
|
|
2455
|
+
filters: MenusQueryFiltersSchema.optional(),
|
|
2456
|
+
limit: import_zod3.z.number().optional(),
|
|
2457
|
+
sort: import_zod3.z.enum(["ASC", "DESC"]).optional(),
|
|
2458
|
+
// Reorder operation fields
|
|
2459
|
+
items: import_zod3.z.array(import_zod3.z.object({
|
|
2460
|
+
id: import_zod3.z.number(),
|
|
2461
|
+
sortOrder: import_zod3.z.number()
|
|
2462
|
+
})).optional()
|
|
2463
|
+
}).optional()
|
|
2464
|
+
});
|
|
2465
|
+
var MenusRequestMessageSchema = import_zod3.z.object({
|
|
2466
|
+
id: import_zod3.z.string(),
|
|
2467
|
+
from: MessageParticipantSchema,
|
|
2468
|
+
type: import_zod3.z.literal("MENUS"),
|
|
2469
|
+
payload: MenusRequestPayloadSchema
|
|
2470
|
+
});
|
|
2471
|
+
var MenusResponsePayloadSchema = import_zod3.z.object({
|
|
2472
|
+
success: import_zod3.z.boolean(),
|
|
2473
|
+
error: import_zod3.z.string().optional(),
|
|
2474
|
+
data: import_zod3.z.any().optional(),
|
|
2475
|
+
count: import_zod3.z.number().optional(),
|
|
2476
|
+
message: import_zod3.z.string().optional()
|
|
2477
|
+
});
|
|
2362
2478
|
var DashCompRequestPayloadSchema = import_zod3.z.object({
|
|
2363
2479
|
prompt: import_zod3.z.string(),
|
|
2364
2480
|
userId: import_zod3.z.string().optional(),
|
|
@@ -5719,30 +5835,35 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
|
5719
5835
|
let executedToolsText = "No external tools were executed for data fetching.";
|
|
5720
5836
|
if (executedTools && executedTools.length > 0) {
|
|
5721
5837
|
logger.info(`[${this.getProviderName()}] Passing ${executedTools.length} executed tools to component matching`);
|
|
5722
|
-
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
|
|
5838
|
+
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) => {
|
|
5723
5839
|
let outputSchemaText = "Not available";
|
|
5840
|
+
let fieldNamesList = "";
|
|
5724
5841
|
let recordCount = "unknown";
|
|
5725
5842
|
if (tool.outputSchema) {
|
|
5726
5843
|
const fields = tool.outputSchema.fields || [];
|
|
5727
5844
|
recordCount = tool.result?._recordCount || (Array.isArray(tool.result) ? tool.result.length : "unknown");
|
|
5845
|
+
const numericFields = fields.filter((f) => f.type === "number").map((f) => f.name);
|
|
5846
|
+
const stringFields = fields.filter((f) => f.type === "string").map((f) => f.name);
|
|
5847
|
+
fieldNamesList = `
|
|
5848
|
+
\u{1F4CA} NUMERIC FIELDS (use for yAxisKey, valueKey, aggregationField): ${numericFields.join(", ") || "none"}
|
|
5849
|
+
\u{1F4DD} STRING FIELDS (use for xAxisKey, groupBy, nameKey): ${stringFields.join(", ") || "none"}`;
|
|
5850
|
+
const fieldsText = fields.map(
|
|
5851
|
+
(f) => ` "${f.name}" (${f.type}): ${f.description}`
|
|
5852
|
+
).join("\n");
|
|
5728
5853
|
outputSchemaText = `${tool.outputSchema.description}
|
|
5729
|
-
Fields
|
|
5730
|
-
${
|
|
5854
|
+
Fields:
|
|
5855
|
+
${fieldsText}`;
|
|
5731
5856
|
}
|
|
5732
5857
|
return `${idx + 1}. **${tool.name}**
|
|
5733
|
-
toolId: "${tool.id}"
|
|
5734
|
-
toolName: "${tool.name}"
|
|
5735
|
-
parameters: ${JSON.stringify(tool.params || {})}
|
|
5858
|
+
toolId: "${tool.id}"
|
|
5859
|
+
toolName: "${tool.name}"
|
|
5860
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
5736
5861
|
recordCount: ${recordCount} rows returned
|
|
5737
|
-
outputSchema: ${outputSchemaText}
|
|
5738
|
-
\u26A0\uFE0F DO NOT embed this tool's data in SQL - use externalTool prop OR query database tables`;
|
|
5862
|
+
outputSchema: ${outputSchemaText}${fieldNamesList}`;
|
|
5739
5863
|
}).join("\n\n");
|
|
5740
5864
|
}
|
|
5741
5865
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
5742
5866
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
5743
|
-
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
5744
|
-
logger.file("\n=============================\nDeferred tools:", deferredToolsText);
|
|
5745
|
-
logger.file("\n=============================\nExecuted tools:", executedToolsText);
|
|
5746
5867
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
5747
5868
|
ANALYSIS_CONTENT: analysisContent,
|
|
5748
5869
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -5752,7 +5873,13 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
5752
5873
|
EXECUTED_TOOLS: executedToolsText
|
|
5753
5874
|
});
|
|
5754
5875
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
5755
|
-
|
|
5876
|
+
const systemPromptStr = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
5877
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "system", systemPromptStr);
|
|
5878
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
|
|
5879
|
+
${analysisContent}
|
|
5880
|
+
|
|
5881
|
+
Executed Tools:
|
|
5882
|
+
${executedToolsText}`);
|
|
5756
5883
|
logCollector?.info("Matching components from text response...");
|
|
5757
5884
|
let fullResponseText = "";
|
|
5758
5885
|
let answerComponentExtracted = false;
|
|
@@ -5884,6 +6011,85 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
5884
6011
|
if (!isValidTool) {
|
|
5885
6012
|
logger.warn(`[${this.getProviderName()}] externalTool.toolId "${toolId}" not found in executed tools [${validToolIds.join(", ")}], setting to null`);
|
|
5886
6013
|
cleanedProps.externalTool = null;
|
|
6014
|
+
} else {
|
|
6015
|
+
const executedTool = executedTools?.find((t) => t.id === toolId);
|
|
6016
|
+
if (executedTool?.outputSchema?.fields && cleanedProps.config) {
|
|
6017
|
+
const validFieldNames = executedTool.outputSchema.fields.map((f) => f.name);
|
|
6018
|
+
const validFieldNamesLower = validFieldNames.map((n) => n.toLowerCase());
|
|
6019
|
+
const findMatchingField = (fieldName, configKey) => {
|
|
6020
|
+
if (!fieldName) return null;
|
|
6021
|
+
const lowerField = fieldName.toLowerCase();
|
|
6022
|
+
const exactIdx = validFieldNamesLower.indexOf(lowerField);
|
|
6023
|
+
if (exactIdx !== -1) return validFieldNames[exactIdx];
|
|
6024
|
+
const containsMatches = validFieldNames.filter(
|
|
6025
|
+
(_, i) => validFieldNamesLower[i].includes(lowerField) || lowerField.includes(validFieldNamesLower[i])
|
|
6026
|
+
);
|
|
6027
|
+
if (containsMatches.length === 1) return containsMatches[0];
|
|
6028
|
+
const fieldTypes = executedTool.outputSchema.fields.reduce((acc, f) => {
|
|
6029
|
+
acc[f.name] = f.type;
|
|
6030
|
+
return acc;
|
|
6031
|
+
}, {});
|
|
6032
|
+
const numericConfigKeys = ["yAxisKey", "valueKey", "aggregationField", "sizeKey"];
|
|
6033
|
+
const stringConfigKeys = ["xAxisKey", "nameKey", "labelKey", "groupBy"];
|
|
6034
|
+
if (numericConfigKeys.includes(configKey)) {
|
|
6035
|
+
const numericFields = validFieldNames.filter((f) => fieldTypes[f] === "number");
|
|
6036
|
+
const match = numericFields.find((f) => f.toLowerCase().includes(lowerField) || lowerField.includes(f.toLowerCase()));
|
|
6037
|
+
if (match) return match;
|
|
6038
|
+
if (numericFields.length > 0) {
|
|
6039
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first numeric field: ${numericFields[0]}`);
|
|
6040
|
+
return numericFields[0];
|
|
6041
|
+
}
|
|
6042
|
+
}
|
|
6043
|
+
if (stringConfigKeys.includes(configKey)) {
|
|
6044
|
+
const stringFields = validFieldNames.filter((f) => fieldTypes[f] === "string");
|
|
6045
|
+
const match = stringFields.find((f) => f.toLowerCase().includes(lowerField) || lowerField.includes(f.toLowerCase()));
|
|
6046
|
+
if (match) return match;
|
|
6047
|
+
if (stringFields.length > 0) {
|
|
6048
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first string field: ${stringFields[0]}`);
|
|
6049
|
+
return stringFields[0];
|
|
6050
|
+
}
|
|
6051
|
+
}
|
|
6052
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first field: ${validFieldNames[0]}`);
|
|
6053
|
+
return validFieldNames[0];
|
|
6054
|
+
};
|
|
6055
|
+
const configFieldsToValidate = [
|
|
6056
|
+
"xAxisKey",
|
|
6057
|
+
"yAxisKey",
|
|
6058
|
+
"valueKey",
|
|
6059
|
+
"nameKey",
|
|
6060
|
+
"labelKey",
|
|
6061
|
+
"groupBy",
|
|
6062
|
+
"aggregationField",
|
|
6063
|
+
"seriesKey",
|
|
6064
|
+
"sizeKey",
|
|
6065
|
+
"xAggregationField",
|
|
6066
|
+
"yAggregationField"
|
|
6067
|
+
];
|
|
6068
|
+
for (const configKey of configFieldsToValidate) {
|
|
6069
|
+
const fieldValue = cleanedProps.config[configKey];
|
|
6070
|
+
if (fieldValue && typeof fieldValue === "string") {
|
|
6071
|
+
if (!validFieldNames.includes(fieldValue)) {
|
|
6072
|
+
const correctedField = findMatchingField(fieldValue, configKey);
|
|
6073
|
+
if (correctedField) {
|
|
6074
|
+
logger.warn(`[${this.getProviderName()}] Correcting config.${configKey}: "${fieldValue}" \u2192 "${correctedField}"`);
|
|
6075
|
+
cleanedProps.config[configKey] = correctedField;
|
|
6076
|
+
}
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
}
|
|
6080
|
+
if (Array.isArray(cleanedProps.config.series)) {
|
|
6081
|
+
cleanedProps.config.series = cleanedProps.config.series.map((s) => {
|
|
6082
|
+
if (s.dataKey && typeof s.dataKey === "string" && !validFieldNames.includes(s.dataKey)) {
|
|
6083
|
+
const correctedField = findMatchingField(s.dataKey, "yAxisKey");
|
|
6084
|
+
if (correctedField) {
|
|
6085
|
+
logger.warn(`[${this.getProviderName()}] Correcting series.dataKey: "${s.dataKey}" \u2192 "${correctedField}"`);
|
|
6086
|
+
return { ...s, dataKey: correctedField };
|
|
6087
|
+
}
|
|
6088
|
+
}
|
|
6089
|
+
return s;
|
|
6090
|
+
});
|
|
6091
|
+
}
|
|
6092
|
+
}
|
|
5887
6093
|
}
|
|
5888
6094
|
}
|
|
5889
6095
|
if (cleanedProps.query) {
|
|
@@ -5941,6 +6147,10 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
5941
6147
|
AVAILABLE_TOOLS: availableToolsDoc,
|
|
5942
6148
|
SCHEMA_DOC: schemaDoc || "No database schema available"
|
|
5943
6149
|
});
|
|
6150
|
+
const systemPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
6151
|
+
const userPromptText = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
|
|
6152
|
+
logger.logLLMPrompt("classifyQuestionCategory", "system", systemPrompt);
|
|
6153
|
+
logger.logLLMPrompt("classifyQuestionCategory", "user", userPromptText);
|
|
5944
6154
|
const result = await LLM.stream(
|
|
5945
6155
|
{
|
|
5946
6156
|
sys: prompts.system,
|
|
@@ -6128,7 +6338,6 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
6128
6338
|
collections,
|
|
6129
6339
|
topK: 1
|
|
6130
6340
|
});
|
|
6131
|
-
logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
|
|
6132
6341
|
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
6133
6342
|
USER_PROMPT: userPrompt,
|
|
6134
6343
|
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
@@ -6137,8 +6346,10 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
6137
6346
|
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
|
|
6138
6347
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc
|
|
6139
6348
|
});
|
|
6140
|
-
|
|
6141
|
-
|
|
6349
|
+
const sysPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
6350
|
+
const usrPrompt = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
|
|
6351
|
+
logger.logLLMPrompt("generateTextResponse", "system", sysPrompt);
|
|
6352
|
+
logger.logLLMPrompt("generateTextResponse", "user", usrPrompt);
|
|
6142
6353
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6143
6354
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6144
6355
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6524,7 +6735,6 @@ ${errorMsg}
|
|
|
6524
6735
|
data: {
|
|
6525
6736
|
text: textResponse,
|
|
6526
6737
|
// Include the streamed text showing all attempts
|
|
6527
|
-
matchedComponents: [],
|
|
6528
6738
|
actions: [],
|
|
6529
6739
|
method: `${this.getProviderName()}-text-response-max-attempts`
|
|
6530
6740
|
}
|
|
@@ -6622,7 +6832,6 @@ ${errorMsg}
|
|
|
6622
6832
|
success: true,
|
|
6623
6833
|
data: {
|
|
6624
6834
|
text: textResponse,
|
|
6625
|
-
matchedComponents,
|
|
6626
6835
|
component: container_componet,
|
|
6627
6836
|
actions,
|
|
6628
6837
|
method: `${this.getProviderName()}-text-response`
|
|
@@ -6646,7 +6855,6 @@ ${errorMsg}
|
|
|
6646
6855
|
errors,
|
|
6647
6856
|
data: {
|
|
6648
6857
|
text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
|
|
6649
|
-
matchedComponents: [],
|
|
6650
6858
|
actions: [],
|
|
6651
6859
|
method: `${this.getProviderName()}-text-response-error`
|
|
6652
6860
|
}
|
|
@@ -6670,6 +6878,8 @@ ${errorMsg}
|
|
|
6670
6878
|
const startTime = Date.now();
|
|
6671
6879
|
logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
|
|
6672
6880
|
logCollector?.info(`Starting request processing with mode: ${responseMode}`);
|
|
6881
|
+
logger.clearFile();
|
|
6882
|
+
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
6673
6883
|
try {
|
|
6674
6884
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
6675
6885
|
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
@@ -6677,8 +6887,8 @@ ${errorMsg}
|
|
|
6677
6887
|
userPrompt,
|
|
6678
6888
|
collections,
|
|
6679
6889
|
userId,
|
|
6680
|
-
similarityThreshold: 0.
|
|
6681
|
-
//
|
|
6890
|
+
similarityThreshold: 0.8
|
|
6891
|
+
// 80% threshold
|
|
6682
6892
|
});
|
|
6683
6893
|
if (conversationMatch) {
|
|
6684
6894
|
logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
|
|
@@ -6703,7 +6913,6 @@ ${errorMsg}
|
|
|
6703
6913
|
data: {
|
|
6704
6914
|
text: cachedTextResponse,
|
|
6705
6915
|
component: null,
|
|
6706
|
-
matchedComponents: [],
|
|
6707
6916
|
actions: conversationMatch.uiBlock?.actions || [],
|
|
6708
6917
|
reasoning: `Exact match from previous general conversation`,
|
|
6709
6918
|
method: `${this.getProviderName()}-semantic-match-general`,
|
|
@@ -6731,7 +6940,6 @@ ${errorMsg}
|
|
|
6731
6940
|
data: {
|
|
6732
6941
|
text: cachedTextResponse,
|
|
6733
6942
|
component,
|
|
6734
|
-
matchedComponents: component?.props?.config?.components || [],
|
|
6735
6943
|
actions: cachedActions,
|
|
6736
6944
|
reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
|
|
6737
6945
|
method: `${this.getProviderName()}-semantic-match-exact`,
|
|
@@ -6767,7 +6975,6 @@ ${errorMsg}
|
|
|
6767
6975
|
data: {
|
|
6768
6976
|
text: textResponseToUse,
|
|
6769
6977
|
component: adaptResult.adaptedComponent,
|
|
6770
|
-
matchedComponents: adaptResult.adaptedComponent?.props?.config?.components || [],
|
|
6771
6978
|
actions: cachedActions,
|
|
6772
6979
|
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
6773
6980
|
method: `${this.getProviderName()}-semantic-match`,
|
|
@@ -10374,6 +10581,331 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10374
10581
|
sendMessage(response);
|
|
10375
10582
|
}
|
|
10376
10583
|
|
|
10584
|
+
// src/handlers/menus.ts
|
|
10585
|
+
init_logger();
|
|
10586
|
+
async function handleMenusRequest(data, collections, sendMessage) {
|
|
10587
|
+
const executeCollection = async (collection, op, params) => {
|
|
10588
|
+
const handler = collections[collection]?.[op];
|
|
10589
|
+
if (!handler) {
|
|
10590
|
+
throw new Error(`Collection operation ${collection}.${op} not found`);
|
|
10591
|
+
}
|
|
10592
|
+
return await handler(params);
|
|
10593
|
+
};
|
|
10594
|
+
try {
|
|
10595
|
+
const request = MenusRequestMessageSchema.parse(data);
|
|
10596
|
+
const { id, payload, from } = request;
|
|
10597
|
+
const { operation, data: requestData } = payload;
|
|
10598
|
+
const menuId = requestData?.id;
|
|
10599
|
+
const name = requestData?.name;
|
|
10600
|
+
const componentName = requestData?.componentName;
|
|
10601
|
+
const icon = requestData?.icon;
|
|
10602
|
+
const userMessage = requestData?.userMessage;
|
|
10603
|
+
const parentId = requestData?.parentId;
|
|
10604
|
+
const sortOrder = requestData?.sortOrder;
|
|
10605
|
+
const props = requestData?.props;
|
|
10606
|
+
const isActive = requestData?.isActive;
|
|
10607
|
+
const filters = requestData?.filters;
|
|
10608
|
+
const limit = requestData?.limit;
|
|
10609
|
+
const sort = requestData?.sort;
|
|
10610
|
+
const items = requestData?.items;
|
|
10611
|
+
switch (operation) {
|
|
10612
|
+
case "create":
|
|
10613
|
+
await handleCreate7(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, from.id);
|
|
10614
|
+
break;
|
|
10615
|
+
case "update":
|
|
10616
|
+
await handleUpdate7(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, from.id);
|
|
10617
|
+
break;
|
|
10618
|
+
case "delete":
|
|
10619
|
+
await handleDelete7(id, menuId, executeCollection, sendMessage, from.id);
|
|
10620
|
+
break;
|
|
10621
|
+
case "getAll":
|
|
10622
|
+
await handleGetAll7(id, executeCollection, sendMessage, from.id);
|
|
10623
|
+
break;
|
|
10624
|
+
case "getOne":
|
|
10625
|
+
await handleGetOne7(id, menuId, executeCollection, sendMessage, from.id);
|
|
10626
|
+
break;
|
|
10627
|
+
case "getRootMenus":
|
|
10628
|
+
await handleGetRootMenus(id, executeCollection, sendMessage, from.id);
|
|
10629
|
+
break;
|
|
10630
|
+
case "getChildMenus":
|
|
10631
|
+
await handleGetChildMenus(id, parentId, executeCollection, sendMessage, from.id);
|
|
10632
|
+
break;
|
|
10633
|
+
case "getHierarchy":
|
|
10634
|
+
await handleGetHierarchy(id, executeCollection, sendMessage, from.id);
|
|
10635
|
+
break;
|
|
10636
|
+
case "query":
|
|
10637
|
+
await handleQuery6(id, filters, limit, sort, executeCollection, sendMessage, from.id);
|
|
10638
|
+
break;
|
|
10639
|
+
case "reorder":
|
|
10640
|
+
await handleReorder(id, items, executeCollection, sendMessage, from.id);
|
|
10641
|
+
break;
|
|
10642
|
+
default:
|
|
10643
|
+
sendResponse9(id, {
|
|
10644
|
+
success: false,
|
|
10645
|
+
error: `Unknown operation: ${operation}`
|
|
10646
|
+
}, sendMessage, from.id);
|
|
10647
|
+
}
|
|
10648
|
+
} catch (error) {
|
|
10649
|
+
logger.error("Failed to handle menus request:", error);
|
|
10650
|
+
sendResponse9(null, {
|
|
10651
|
+
success: false,
|
|
10652
|
+
error: error instanceof Error ? error.message : "Unknown error occurred"
|
|
10653
|
+
}, sendMessage);
|
|
10654
|
+
}
|
|
10655
|
+
}
|
|
10656
|
+
async function handleCreate7(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
|
|
10657
|
+
if (!name) {
|
|
10658
|
+
sendResponse9(id, {
|
|
10659
|
+
success: false,
|
|
10660
|
+
error: "name is required"
|
|
10661
|
+
}, sendMessage, clientId);
|
|
10662
|
+
return;
|
|
10663
|
+
}
|
|
10664
|
+
if (!componentName) {
|
|
10665
|
+
sendResponse9(id, {
|
|
10666
|
+
success: false,
|
|
10667
|
+
error: "componentName is required"
|
|
10668
|
+
}, sendMessage, clientId);
|
|
10669
|
+
return;
|
|
10670
|
+
}
|
|
10671
|
+
try {
|
|
10672
|
+
const result = await executeCollection("menus", "create", {
|
|
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 created successfully"
|
|
10686
|
+
}, sendMessage, clientId);
|
|
10687
|
+
logger.info(`Menu created: ID ${result.data?.id}`);
|
|
10688
|
+
} catch (error) {
|
|
10689
|
+
sendResponse9(id, {
|
|
10690
|
+
success: false,
|
|
10691
|
+
error: error instanceof Error ? error.message : "Failed to create menu"
|
|
10692
|
+
}, sendMessage, clientId);
|
|
10693
|
+
}
|
|
10694
|
+
}
|
|
10695
|
+
async function handleUpdate7(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, 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", "update", {
|
|
10705
|
+
id: menuId,
|
|
10706
|
+
name,
|
|
10707
|
+
componentName,
|
|
10708
|
+
icon,
|
|
10709
|
+
userMessage,
|
|
10710
|
+
parentId,
|
|
10711
|
+
sortOrder,
|
|
10712
|
+
props,
|
|
10713
|
+
isActive
|
|
10714
|
+
});
|
|
10715
|
+
sendResponse9(id, {
|
|
10716
|
+
success: true,
|
|
10717
|
+
data: result.data,
|
|
10718
|
+
message: "Menu updated successfully"
|
|
10719
|
+
}, sendMessage, clientId);
|
|
10720
|
+
logger.info(`Menu updated: ID ${menuId}`);
|
|
10721
|
+
} catch (error) {
|
|
10722
|
+
sendResponse9(id, {
|
|
10723
|
+
success: false,
|
|
10724
|
+
error: error instanceof Error ? error.message : "Failed to update menu"
|
|
10725
|
+
}, sendMessage, clientId);
|
|
10726
|
+
}
|
|
10727
|
+
}
|
|
10728
|
+
async function handleDelete7(id, menuId, executeCollection, sendMessage, clientId) {
|
|
10729
|
+
if (!menuId) {
|
|
10730
|
+
sendResponse9(id, {
|
|
10731
|
+
success: false,
|
|
10732
|
+
error: "Menu ID is required"
|
|
10733
|
+
}, sendMessage, clientId);
|
|
10734
|
+
return;
|
|
10735
|
+
}
|
|
10736
|
+
try {
|
|
10737
|
+
const result = await executeCollection("menus", "delete", { id: menuId });
|
|
10738
|
+
sendResponse9(id, {
|
|
10739
|
+
success: true,
|
|
10740
|
+
data: result.data,
|
|
10741
|
+
message: "Menu deleted successfully"
|
|
10742
|
+
}, sendMessage, clientId);
|
|
10743
|
+
logger.info(`Menu deleted: ID ${menuId}`);
|
|
10744
|
+
} catch (error) {
|
|
10745
|
+
sendResponse9(id, {
|
|
10746
|
+
success: false,
|
|
10747
|
+
error: error instanceof Error ? error.message : "Failed to delete menu"
|
|
10748
|
+
}, sendMessage, clientId);
|
|
10749
|
+
}
|
|
10750
|
+
}
|
|
10751
|
+
async function handleGetAll7(id, executeCollection, sendMessage, clientId) {
|
|
10752
|
+
try {
|
|
10753
|
+
const result = await executeCollection("menus", "getAll", {});
|
|
10754
|
+
sendResponse9(id, {
|
|
10755
|
+
success: true,
|
|
10756
|
+
data: result.data,
|
|
10757
|
+
count: result.count,
|
|
10758
|
+
message: `Retrieved ${result.count} menus`
|
|
10759
|
+
}, sendMessage, clientId);
|
|
10760
|
+
logger.info(`Retrieved all menus (count: ${result.count})`);
|
|
10761
|
+
} catch (error) {
|
|
10762
|
+
sendResponse9(id, {
|
|
10763
|
+
success: false,
|
|
10764
|
+
error: error instanceof Error ? error.message : "Failed to get menus"
|
|
10765
|
+
}, sendMessage, clientId);
|
|
10766
|
+
}
|
|
10767
|
+
}
|
|
10768
|
+
async function handleGetOne7(id, menuId, executeCollection, sendMessage, clientId) {
|
|
10769
|
+
if (!menuId) {
|
|
10770
|
+
sendResponse9(id, {
|
|
10771
|
+
success: false,
|
|
10772
|
+
error: "Menu ID is required"
|
|
10773
|
+
}, sendMessage, clientId);
|
|
10774
|
+
return;
|
|
10775
|
+
}
|
|
10776
|
+
try {
|
|
10777
|
+
const result = await executeCollection("menus", "getOne", { id: menuId });
|
|
10778
|
+
sendResponse9(id, {
|
|
10779
|
+
success: true,
|
|
10780
|
+
data: result.data,
|
|
10781
|
+
message: `Retrieved menu ID ${menuId}`
|
|
10782
|
+
}, sendMessage, clientId);
|
|
10783
|
+
logger.info(`Retrieved menu: ID ${menuId}`);
|
|
10784
|
+
} catch (error) {
|
|
10785
|
+
sendResponse9(id, {
|
|
10786
|
+
success: false,
|
|
10787
|
+
error: error instanceof Error ? error.message : "Failed to get menu"
|
|
10788
|
+
}, sendMessage, clientId);
|
|
10789
|
+
}
|
|
10790
|
+
}
|
|
10791
|
+
async function handleGetRootMenus(id, executeCollection, sendMessage, clientId) {
|
|
10792
|
+
try {
|
|
10793
|
+
const result = await executeCollection("menus", "getRootMenus", {});
|
|
10794
|
+
sendResponse9(id, {
|
|
10795
|
+
success: true,
|
|
10796
|
+
data: result.data,
|
|
10797
|
+
count: result.count,
|
|
10798
|
+
message: `Retrieved ${result.count} root menus`
|
|
10799
|
+
}, sendMessage, clientId);
|
|
10800
|
+
logger.info(`Retrieved root menus (count: ${result.count})`);
|
|
10801
|
+
} catch (error) {
|
|
10802
|
+
sendResponse9(id, {
|
|
10803
|
+
success: false,
|
|
10804
|
+
error: error instanceof Error ? error.message : "Failed to get root menus"
|
|
10805
|
+
}, sendMessage, clientId);
|
|
10806
|
+
}
|
|
10807
|
+
}
|
|
10808
|
+
async function handleGetChildMenus(id, parentId, executeCollection, sendMessage, clientId) {
|
|
10809
|
+
if (parentId === void 0 || parentId === null) {
|
|
10810
|
+
sendResponse9(id, {
|
|
10811
|
+
success: false,
|
|
10812
|
+
error: "parentId is required"
|
|
10813
|
+
}, sendMessage, clientId);
|
|
10814
|
+
return;
|
|
10815
|
+
}
|
|
10816
|
+
try {
|
|
10817
|
+
const result = await executeCollection("menus", "getChildMenus", { parentId });
|
|
10818
|
+
sendResponse9(id, {
|
|
10819
|
+
success: true,
|
|
10820
|
+
data: result.data,
|
|
10821
|
+
count: result.count,
|
|
10822
|
+
message: `Retrieved ${result.count} child menus for parent ${parentId}`
|
|
10823
|
+
}, sendMessage, clientId);
|
|
10824
|
+
logger.info(`Retrieved child menus for parent ${parentId} (count: ${result.count})`);
|
|
10825
|
+
} catch (error) {
|
|
10826
|
+
sendResponse9(id, {
|
|
10827
|
+
success: false,
|
|
10828
|
+
error: error instanceof Error ? error.message : "Failed to get child menus"
|
|
10829
|
+
}, sendMessage, clientId);
|
|
10830
|
+
}
|
|
10831
|
+
}
|
|
10832
|
+
async function handleGetHierarchy(id, executeCollection, sendMessage, clientId) {
|
|
10833
|
+
try {
|
|
10834
|
+
const result = await executeCollection("menus", "getHierarchy", {});
|
|
10835
|
+
sendResponse9(id, {
|
|
10836
|
+
success: true,
|
|
10837
|
+
data: result.data,
|
|
10838
|
+
count: result.count,
|
|
10839
|
+
message: `Retrieved menus hierarchy with ${result.count} root items`
|
|
10840
|
+
}, sendMessage, clientId);
|
|
10841
|
+
logger.info(`Retrieved menus hierarchy (root count: ${result.count})`);
|
|
10842
|
+
} catch (error) {
|
|
10843
|
+
sendResponse9(id, {
|
|
10844
|
+
success: false,
|
|
10845
|
+
error: error instanceof Error ? error.message : "Failed to get menus hierarchy"
|
|
10846
|
+
}, sendMessage, clientId);
|
|
10847
|
+
}
|
|
10848
|
+
}
|
|
10849
|
+
async function handleQuery6(id, filters, limit, sort, executeCollection, sendMessage, clientId) {
|
|
10850
|
+
try {
|
|
10851
|
+
const result = await executeCollection("menus", "query", {
|
|
10852
|
+
filters: filters || {},
|
|
10853
|
+
limit,
|
|
10854
|
+
sort
|
|
10855
|
+
});
|
|
10856
|
+
sendResponse9(id, {
|
|
10857
|
+
success: true,
|
|
10858
|
+
data: result.data,
|
|
10859
|
+
count: result.count,
|
|
10860
|
+
message: `Query returned ${result.count} menus`
|
|
10861
|
+
}, sendMessage, clientId);
|
|
10862
|
+
logger.info(`Query returned ${result.count} menus`);
|
|
10863
|
+
} catch (error) {
|
|
10864
|
+
sendResponse9(id, {
|
|
10865
|
+
success: false,
|
|
10866
|
+
error: error instanceof Error ? error.message : "Failed to query menus"
|
|
10867
|
+
}, sendMessage, clientId);
|
|
10868
|
+
}
|
|
10869
|
+
}
|
|
10870
|
+
async function handleReorder(id, items, executeCollection, sendMessage, clientId) {
|
|
10871
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
10872
|
+
sendResponse9(id, {
|
|
10873
|
+
success: false,
|
|
10874
|
+
error: "items array is required"
|
|
10875
|
+
}, sendMessage, clientId);
|
|
10876
|
+
return;
|
|
10877
|
+
}
|
|
10878
|
+
try {
|
|
10879
|
+
const result = await executeCollection("menus", "reorder", { items });
|
|
10880
|
+
sendResponse9(id, {
|
|
10881
|
+
success: true,
|
|
10882
|
+
data: result.data,
|
|
10883
|
+
message: `Reordered ${items.length} menus successfully`
|
|
10884
|
+
}, sendMessage, clientId);
|
|
10885
|
+
logger.info(`Reordered ${items.length} menus`);
|
|
10886
|
+
} catch (error) {
|
|
10887
|
+
sendResponse9(id, {
|
|
10888
|
+
success: false,
|
|
10889
|
+
error: error instanceof Error ? error.message : "Failed to reorder menus"
|
|
10890
|
+
}, sendMessage, clientId);
|
|
10891
|
+
}
|
|
10892
|
+
}
|
|
10893
|
+
function sendResponse9(id, res, sendMessage, clientId) {
|
|
10894
|
+
const response = {
|
|
10895
|
+
id: id || "unknown",
|
|
10896
|
+
type: "MENUS_RES",
|
|
10897
|
+
from: { type: "data-agent" },
|
|
10898
|
+
to: {
|
|
10899
|
+
type: "admin",
|
|
10900
|
+
id: clientId
|
|
10901
|
+
},
|
|
10902
|
+
payload: {
|
|
10903
|
+
...res
|
|
10904
|
+
}
|
|
10905
|
+
};
|
|
10906
|
+
sendMessage(response);
|
|
10907
|
+
}
|
|
10908
|
+
|
|
10377
10909
|
// src/dashComp/index.ts
|
|
10378
10910
|
init_logger();
|
|
10379
10911
|
|
|
@@ -10500,37 +11032,74 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10500
11032
|
return { success: false, errors };
|
|
10501
11033
|
}
|
|
10502
11034
|
logger.info(`[DASH_COMP_REQ] Using model: ${model}`);
|
|
10503
|
-
const
|
|
11035
|
+
const executedTools = [];
|
|
11036
|
+
const llmTools = (tools || []).map((tool) => ({
|
|
11037
|
+
name: tool.id,
|
|
11038
|
+
description: tool.description,
|
|
11039
|
+
input_schema: {
|
|
11040
|
+
type: "object",
|
|
11041
|
+
properties: Object.fromEntries(
|
|
11042
|
+
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` }])
|
|
11043
|
+
),
|
|
11044
|
+
additionalProperties: false
|
|
11045
|
+
}
|
|
11046
|
+
}));
|
|
11047
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
11048
|
+
const tool = tools?.find((t) => t.id === toolName);
|
|
11049
|
+
if (!tool) {
|
|
11050
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
11051
|
+
}
|
|
11052
|
+
logger.info(`[DASH_COMP_REQ] Executing external tool: ${tool.name} (${tool.id})`);
|
|
11053
|
+
const result2 = await tool.fn(toolInput);
|
|
11054
|
+
executedTools.push({
|
|
11055
|
+
id: tool.id,
|
|
11056
|
+
name: tool.name,
|
|
11057
|
+
params: toolInput,
|
|
11058
|
+
result: result2,
|
|
11059
|
+
outputSchema: tool.outputSchema
|
|
11060
|
+
});
|
|
11061
|
+
logger.info(`[DASH_COMP_REQ] Tool ${tool.name} executed successfully`);
|
|
11062
|
+
return JSON.stringify(result2, null, 2);
|
|
11063
|
+
};
|
|
11064
|
+
const result = await LLM.streamWithTools(
|
|
10504
11065
|
{
|
|
10505
11066
|
sys: prompts.system,
|
|
10506
11067
|
user: prompts.user
|
|
10507
11068
|
},
|
|
11069
|
+
llmTools,
|
|
11070
|
+
toolHandler,
|
|
10508
11071
|
{
|
|
10509
11072
|
model,
|
|
10510
11073
|
maxTokens: 8192,
|
|
10511
11074
|
temperature: 0.2,
|
|
10512
11075
|
apiKey
|
|
10513
11076
|
},
|
|
10514
|
-
|
|
10515
|
-
//
|
|
11077
|
+
5
|
|
11078
|
+
// max iterations
|
|
10516
11079
|
);
|
|
11080
|
+
const jsonMatch = result.match(/\{[\s\S]*\}/);
|
|
11081
|
+
const parsedResult = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
11082
|
+
if (!parsedResult) {
|
|
11083
|
+
errors.push("Failed to parse LLM response as JSON");
|
|
11084
|
+
return { success: false, errors };
|
|
11085
|
+
}
|
|
10517
11086
|
logger.debug("[DASH_COMP_REQ] LLM response received");
|
|
10518
|
-
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(
|
|
10519
|
-
if (!
|
|
11087
|
+
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
|
|
11088
|
+
if (!parsedResult.componentId || !parsedResult.props) {
|
|
10520
11089
|
errors.push("Invalid LLM response: missing componentId or props");
|
|
10521
11090
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
|
|
10522
11091
|
prompt,
|
|
10523
|
-
result,
|
|
10524
|
-
missingFields: { componentId: !
|
|
11092
|
+
result: parsedResult,
|
|
11093
|
+
missingFields: { componentId: !parsedResult.componentId, props: !parsedResult.props }
|
|
10525
11094
|
});
|
|
10526
11095
|
return { success: false, errors };
|
|
10527
11096
|
}
|
|
10528
|
-
const originalComponent = components.find((c) => c.name ===
|
|
11097
|
+
const originalComponent = components.find((c) => c.name === parsedResult.componentName);
|
|
10529
11098
|
if (!originalComponent) {
|
|
10530
|
-
errors.push(`Component ${
|
|
11099
|
+
errors.push(`Component ${parsedResult.componentName} not found in available components`);
|
|
10531
11100
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
10532
11101
|
prompt,
|
|
10533
|
-
componentName:
|
|
11102
|
+
componentName: parsedResult.componentName,
|
|
10534
11103
|
availableComponentNames: components.map((c) => c.name)
|
|
10535
11104
|
});
|
|
10536
11105
|
return { success: false, errors };
|
|
@@ -10539,23 +11108,27 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10539
11108
|
...originalComponent,
|
|
10540
11109
|
props: {
|
|
10541
11110
|
...originalComponent.props,
|
|
10542
|
-
...
|
|
11111
|
+
...parsedResult.props
|
|
10543
11112
|
}
|
|
10544
11113
|
};
|
|
10545
11114
|
logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
|
|
10546
|
-
if (
|
|
11115
|
+
if (parsedResult.props.query) {
|
|
10547
11116
|
logger.info(`[DASH_COMP_REQ] Data source: Database query`);
|
|
10548
11117
|
}
|
|
10549
|
-
if (
|
|
10550
|
-
logger.info(`[DASH_COMP_REQ] Data source: External tool - ${
|
|
11118
|
+
if (parsedResult.props.externalTool) {
|
|
11119
|
+
logger.info(`[DASH_COMP_REQ] Data source: External tool - ${parsedResult.props.externalTool.toolName}`);
|
|
11120
|
+
}
|
|
11121
|
+
if (executedTools.length > 0) {
|
|
11122
|
+
logger.info(`[DASH_COMP_REQ] Executed ${executedTools.length} external tool(s): ${executedTools.map((t) => t.name).join(", ")}`);
|
|
10551
11123
|
}
|
|
10552
11124
|
return {
|
|
10553
11125
|
success: true,
|
|
10554
11126
|
data: {
|
|
10555
11127
|
component: finalComponent,
|
|
10556
|
-
reasoning:
|
|
10557
|
-
dataSource:
|
|
10558
|
-
isUpdate:
|
|
11128
|
+
reasoning: parsedResult.reasoning || "Component selected based on user prompt",
|
|
11129
|
+
dataSource: parsedResult.props.query ? "database" : parsedResult.props.externalTool ? "external_tool" : "none",
|
|
11130
|
+
isUpdate: parsedResult.isUpdate || false,
|
|
11131
|
+
executedTools: executedTools.length > 0 ? executedTools : void 0
|
|
10559
11132
|
},
|
|
10560
11133
|
errors: []
|
|
10561
11134
|
};
|
|
@@ -10608,11 +11181,49 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10608
11181
|
return { success: false, errors };
|
|
10609
11182
|
}
|
|
10610
11183
|
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10611
|
-
const
|
|
11184
|
+
const executedTools = [];
|
|
11185
|
+
const llmTools = (tools || []).map((tool) => ({
|
|
11186
|
+
name: tool.id,
|
|
11187
|
+
description: tool.description,
|
|
11188
|
+
input_schema: {
|
|
11189
|
+
type: "object",
|
|
11190
|
+
properties: Object.fromEntries(
|
|
11191
|
+
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` }])
|
|
11192
|
+
),
|
|
11193
|
+
additionalProperties: false
|
|
11194
|
+
}
|
|
11195
|
+
}));
|
|
11196
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
11197
|
+
const tool = tools?.find((t) => t.id === toolName);
|
|
11198
|
+
if (!tool) {
|
|
11199
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
11200
|
+
}
|
|
11201
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Executing external tool: ${tool.name} (${tool.id})`);
|
|
11202
|
+
const result2 = await tool.fn(toolInput);
|
|
11203
|
+
executedTools.push({
|
|
11204
|
+
id: tool.id,
|
|
11205
|
+
name: tool.name,
|
|
11206
|
+
params: toolInput,
|
|
11207
|
+
result: result2,
|
|
11208
|
+
outputSchema: tool.outputSchema
|
|
11209
|
+
});
|
|
11210
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Tool ${tool.name} executed successfully`);
|
|
11211
|
+
return JSON.stringify(result2, null, 2);
|
|
11212
|
+
};
|
|
11213
|
+
const rawResult = await LLM.streamWithTools(
|
|
10612
11214
|
{ sys: prompts.system, user: prompts.user },
|
|
11215
|
+
llmTools,
|
|
11216
|
+
toolHandler,
|
|
10613
11217
|
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10614
|
-
|
|
11218
|
+
5
|
|
11219
|
+
// max iterations
|
|
10615
11220
|
);
|
|
11221
|
+
const jsonMatch = rawResult.match(/\{[\s\S]*\}/);
|
|
11222
|
+
const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
11223
|
+
if (!result) {
|
|
11224
|
+
errors.push("Failed to parse LLM response as JSON");
|
|
11225
|
+
return { success: false, errors };
|
|
11226
|
+
}
|
|
10616
11227
|
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10617
11228
|
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10618
11229
|
if (!result.filterComponent) {
|
|
@@ -10626,13 +11237,17 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10626
11237
|
}
|
|
10627
11238
|
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10628
11239
|
logger.info(`[DASH_COMP_REQ:FILTER] Updated ${result.updatedComponents?.length || 0} components`);
|
|
11240
|
+
if (executedTools.length > 0) {
|
|
11241
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Executed ${executedTools.length} external tool(s): ${executedTools.map((t) => t.name).join(", ")}`);
|
|
11242
|
+
}
|
|
10629
11243
|
return {
|
|
10630
11244
|
success: true,
|
|
10631
11245
|
data: {
|
|
10632
11246
|
filterComponent: result.filterComponent,
|
|
10633
11247
|
updatedComponents: result.updatedComponents || [],
|
|
10634
11248
|
filterBindings: result.filterBindings || {},
|
|
10635
|
-
reasoning: result.reasoning || "Filter created based on user prompt"
|
|
11249
|
+
reasoning: result.reasoning || "Filter created based on user prompt",
|
|
11250
|
+
executedTools: executedTools.length > 0 ? executedTools : void 0
|
|
10636
11251
|
},
|
|
10637
11252
|
errors: []
|
|
10638
11253
|
};
|
|
@@ -11810,6 +12425,11 @@ var SuperatomSDK = class {
|
|
|
11810
12425
|
logger.error("Failed to handle KB nodes request:", error);
|
|
11811
12426
|
});
|
|
11812
12427
|
break;
|
|
12428
|
+
case "MENUS":
|
|
12429
|
+
handleMenusRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
|
|
12430
|
+
logger.error("Failed to handle menus request:", error);
|
|
12431
|
+
});
|
|
12432
|
+
break;
|
|
11813
12433
|
case "DASH_COMP_REQ":
|
|
11814
12434
|
handleDashCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
|
|
11815
12435
|
logger.error("Failed to handle dash comp request:", error);
|