@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.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,58 @@ 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
|
+
let contentStr;
|
|
157
|
+
if (typeof content === "string") {
|
|
158
|
+
contentStr = content;
|
|
159
|
+
} else if (Array.isArray(content)) {
|
|
160
|
+
contentStr = content.map((item) => {
|
|
161
|
+
if (typeof item === "string") return item;
|
|
162
|
+
if (item.text) return item.text;
|
|
163
|
+
if (item.content) return typeof item.content === "string" ? item.content : JSON.stringify(item.content, null, 2);
|
|
164
|
+
return JSON.stringify(item, null, 2);
|
|
165
|
+
}).join("\n\n");
|
|
166
|
+
} else if (typeof content === "object") {
|
|
167
|
+
contentStr = JSON.stringify(content, null, 2);
|
|
168
|
+
} else {
|
|
169
|
+
contentStr = String(content);
|
|
170
|
+
}
|
|
171
|
+
LOGSTREAM.write(contentStr);
|
|
172
|
+
LOGSTREAM.write(`
|
|
173
|
+
${"#".repeat(80)}
|
|
174
|
+
|
|
175
|
+
`);
|
|
176
|
+
}
|
|
127
177
|
};
|
|
128
178
|
logger = new Logger();
|
|
129
179
|
}
|
|
@@ -1041,8 +1091,20 @@ If adaptation is not possible or would fundamentally change the component:
|
|
|
1041
1091
|
|
|
1042
1092
|
Analyze the user's request and:
|
|
1043
1093
|
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
|
|
1094
|
+
2. **Determine the data source**: Database query OR External tool
|
|
1095
|
+
3. **Generate complete props** for the selected component
|
|
1096
|
+
|
|
1097
|
+
## Available External Tools
|
|
1098
|
+
|
|
1099
|
+
The following external tools are available:
|
|
1100
|
+
|
|
1101
|
+
{{AVAILABLE_TOOLS}}
|
|
1102
|
+
|
|
1103
|
+
When a tool is needed to complete the user's request:
|
|
1104
|
+
1. **Analyze the request** to determine which tool is needed
|
|
1105
|
+
2. **Extract parameters** from the user's question
|
|
1106
|
+
3. **Execute the tool** by calling it with the extracted parameters
|
|
1107
|
+
4. **Use the results** to configure the component (field names for axes, columns, etc.)
|
|
1046
1108
|
|
|
1047
1109
|
## Component Selection Rules
|
|
1048
1110
|
|
|
@@ -1198,7 +1260,20 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1198
1260
|
|
|
1199
1261
|
1. **Create a filter component** based on the user's request
|
|
1200
1262
|
2. **Update existing components** with dynamic title/description interpolation if needed
|
|
1201
|
-
3. **
|
|
1263
|
+
3. **Set default values in component externalTool.params** that match the filter's default option
|
|
1264
|
+
4. **Preserve all existing props** - the filter system handles param merging at runtime
|
|
1265
|
+
|
|
1266
|
+
## Available External Tools
|
|
1267
|
+
|
|
1268
|
+
The following external tools are available:
|
|
1269
|
+
|
|
1270
|
+
{{AVAILABLE_TOOLS}}
|
|
1271
|
+
|
|
1272
|
+
When a tool is needed to complete the user's request:
|
|
1273
|
+
1. **Analyze the request** to determine which tool is needed
|
|
1274
|
+
2. **Extract parameters** from the user's question
|
|
1275
|
+
3. **Execute the tool** by calling it with the extracted parameters
|
|
1276
|
+
4. **Use the results** to configure the filter and components properly
|
|
1202
1277
|
|
|
1203
1278
|
## How The Filter System Works
|
|
1204
1279
|
|
|
@@ -1228,16 +1303,20 @@ Use \`{%filterKeyLabel%}\` syntax for dynamic text:
|
|
|
1228
1303
|
## Updating Existing Components
|
|
1229
1304
|
|
|
1230
1305
|
**IMPORTANT - Parameter Handling:**
|
|
1231
|
-
- Do NOT change existing parameter values to placeholders
|
|
1232
|
-
- Keep all existing/default parameter values as they are
|
|
1233
1306
|
- The filter system MERGES params at runtime: filter params override component defaults
|
|
1307
|
+
- Component's \`externalTool.params\` should have DEFAULT values matching the filter's default option
|
|
1308
|
+
- This ensures the component shows correct data on initial load before user changes the filter
|
|
1234
1309
|
|
|
1235
1310
|
**What to modify in existing components:**
|
|
1236
1311
|
- Modify \`title\` for \`{%filterKeyLabel%}\` interpolation (only if title exists)
|
|
1237
1312
|
- Modify \`description\` for interpolation (only if description exists)
|
|
1238
|
-
-
|
|
1313
|
+
- Set \`externalTool.params\` default values to match filter's default option params
|
|
1239
1314
|
- Copy ALL other props exactly as provided
|
|
1240
1315
|
|
|
1316
|
+
**Example - Setting default params:**
|
|
1317
|
+
If filter has default option with params: \`{ startDate: "2025-01-01", endDate: "2025-01-31" }\`
|
|
1318
|
+
Then component's externalTool should have: \`{ params: { startDate: "2025-01-01", endDate: "2025-01-31" } }\`
|
|
1319
|
+
|
|
1241
1320
|
### Database Query Rules
|
|
1242
1321
|
{{DATABASE_RULES}}
|
|
1243
1322
|
|
|
@@ -1285,10 +1364,11 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1285
1364
|
**CRITICAL RULES:**
|
|
1286
1365
|
1. Return ONLY valid JSON (no markdown code blocks)
|
|
1287
1366
|
2. **COPY ALL existing props** - modify title/description for interpolation only if they exist
|
|
1288
|
-
3. **
|
|
1367
|
+
3. **Set externalTool.params defaults** to match the filter's default option params
|
|
1289
1368
|
4. Use \`{%filterKeyLabel%}\` for dynamic text (NOT \`{{...}}\` or \`$...\`)
|
|
1290
1369
|
5. Filter \`params\` must have ACTUAL values (real dates, strings), not placeholders
|
|
1291
1370
|
6. Each filter option needs: label, value, params (and optionally isDefault)
|
|
1371
|
+
7. Component default params MUST match filter default - this ensures correct initial data load
|
|
1292
1372
|
|
|
1293
1373
|
## Database Schema
|
|
1294
1374
|
{{SCHEMA_DOC}}
|
|
@@ -2359,6 +2439,57 @@ var KbNodesRequestMessageSchema = import_zod3.z.object({
|
|
|
2359
2439
|
type: import_zod3.z.literal("KB_NODES"),
|
|
2360
2440
|
payload: KbNodesRequestPayloadSchema
|
|
2361
2441
|
});
|
|
2442
|
+
var MenusQueryFiltersSchema = import_zod3.z.object({
|
|
2443
|
+
parentId: import_zod3.z.number().nullable().optional(),
|
|
2444
|
+
isActive: import_zod3.z.boolean().optional()
|
|
2445
|
+
});
|
|
2446
|
+
var MenusRequestPayloadSchema = import_zod3.z.object({
|
|
2447
|
+
operation: import_zod3.z.enum([
|
|
2448
|
+
"create",
|
|
2449
|
+
"update",
|
|
2450
|
+
"delete",
|
|
2451
|
+
"getAll",
|
|
2452
|
+
"getOne",
|
|
2453
|
+
"getRootMenus",
|
|
2454
|
+
"getChildMenus",
|
|
2455
|
+
"getHierarchy",
|
|
2456
|
+
"query",
|
|
2457
|
+
"reorder"
|
|
2458
|
+
]),
|
|
2459
|
+
data: import_zod3.z.object({
|
|
2460
|
+
id: import_zod3.z.number().optional(),
|
|
2461
|
+
name: import_zod3.z.string().optional(),
|
|
2462
|
+
componentName: import_zod3.z.string().optional(),
|
|
2463
|
+
icon: import_zod3.z.string().optional(),
|
|
2464
|
+
userMessage: import_zod3.z.string().optional(),
|
|
2465
|
+
parentId: import_zod3.z.number().nullable().optional(),
|
|
2466
|
+
sortOrder: import_zod3.z.number().optional(),
|
|
2467
|
+
props: import_zod3.z.record(import_zod3.z.unknown()).optional(),
|
|
2468
|
+
isActive: import_zod3.z.boolean().optional(),
|
|
2469
|
+
// Query operation fields
|
|
2470
|
+
filters: MenusQueryFiltersSchema.optional(),
|
|
2471
|
+
limit: import_zod3.z.number().optional(),
|
|
2472
|
+
sort: import_zod3.z.enum(["ASC", "DESC"]).optional(),
|
|
2473
|
+
// Reorder operation fields
|
|
2474
|
+
items: import_zod3.z.array(import_zod3.z.object({
|
|
2475
|
+
id: import_zod3.z.number(),
|
|
2476
|
+
sortOrder: import_zod3.z.number()
|
|
2477
|
+
})).optional()
|
|
2478
|
+
}).optional()
|
|
2479
|
+
});
|
|
2480
|
+
var MenusRequestMessageSchema = import_zod3.z.object({
|
|
2481
|
+
id: import_zod3.z.string(),
|
|
2482
|
+
from: MessageParticipantSchema,
|
|
2483
|
+
type: import_zod3.z.literal("MENUS"),
|
|
2484
|
+
payload: MenusRequestPayloadSchema
|
|
2485
|
+
});
|
|
2486
|
+
var MenusResponsePayloadSchema = import_zod3.z.object({
|
|
2487
|
+
success: import_zod3.z.boolean(),
|
|
2488
|
+
error: import_zod3.z.string().optional(),
|
|
2489
|
+
data: import_zod3.z.any().optional(),
|
|
2490
|
+
count: import_zod3.z.number().optional(),
|
|
2491
|
+
message: import_zod3.z.string().optional()
|
|
2492
|
+
});
|
|
2362
2493
|
var DashCompRequestPayloadSchema = import_zod3.z.object({
|
|
2363
2494
|
prompt: import_zod3.z.string(),
|
|
2364
2495
|
userId: import_zod3.z.string().optional(),
|
|
@@ -5719,35 +5850,35 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
|
5719
5850
|
let executedToolsText = "No external tools were executed for data fetching.";
|
|
5720
5851
|
if (executedTools && executedTools.length > 0) {
|
|
5721
5852
|
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
|
|
5853
|
+
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
5854
|
let outputSchemaText = "Not available";
|
|
5855
|
+
let fieldNamesList = "";
|
|
5724
5856
|
let recordCount = "unknown";
|
|
5725
5857
|
if (tool.outputSchema) {
|
|
5726
5858
|
const fields = tool.outputSchema.fields || [];
|
|
5727
5859
|
recordCount = tool.result?._recordCount || (Array.isArray(tool.result) ? tool.result.length : "unknown");
|
|
5860
|
+
const numericFields = fields.filter((f) => f.type === "number").map((f) => f.name);
|
|
5861
|
+
const stringFields = fields.filter((f) => f.type === "string").map((f) => f.name);
|
|
5862
|
+
fieldNamesList = `
|
|
5863
|
+
\u{1F4CA} NUMERIC FIELDS (use for yAxisKey, valueKey, aggregationField): ${numericFields.join(", ") || "none"}
|
|
5864
|
+
\u{1F4DD} STRING FIELDS (use for xAxisKey, groupBy, nameKey): ${stringFields.join(", ") || "none"}`;
|
|
5728
5865
|
const fieldsText = fields.map(
|
|
5729
|
-
(f) => `
|
|
5730
|
-
type: ${f.type}
|
|
5731
|
-
description: ${f.description}`
|
|
5866
|
+
(f) => ` "${f.name}" (${f.type}): ${f.description}`
|
|
5732
5867
|
).join("\n");
|
|
5733
5868
|
outputSchemaText = `${tool.outputSchema.description}
|
|
5734
|
-
Fields
|
|
5869
|
+
Fields:
|
|
5735
5870
|
${fieldsText}`;
|
|
5736
5871
|
}
|
|
5737
5872
|
return `${idx + 1}. **${tool.name}**
|
|
5738
|
-
toolId: "${tool.id}"
|
|
5739
|
-
toolName: "${tool.name}"
|
|
5740
|
-
parameters: ${JSON.stringify(tool.params || {})}
|
|
5873
|
+
toolId: "${tool.id}"
|
|
5874
|
+
toolName: "${tool.name}"
|
|
5875
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
5741
5876
|
recordCount: ${recordCount} rows returned
|
|
5742
|
-
outputSchema: ${outputSchemaText}
|
|
5743
|
-
\u26A0\uFE0F DO NOT embed this tool's data in SQL - use externalTool prop OR query database tables`;
|
|
5877
|
+
outputSchema: ${outputSchemaText}${fieldNamesList}`;
|
|
5744
5878
|
}).join("\n\n");
|
|
5745
5879
|
}
|
|
5746
5880
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
5747
5881
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
5748
|
-
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
5749
|
-
logger.file("\n=============================\nDeferred tools:", deferredToolsText);
|
|
5750
|
-
logger.file("\n=============================\nExecuted tools:", executedToolsText);
|
|
5751
5882
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
5752
5883
|
ANALYSIS_CONTENT: analysisContent,
|
|
5753
5884
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -5757,7 +5888,13 @@ ${fieldsText}`;
|
|
|
5757
5888
|
EXECUTED_TOOLS: executedToolsText
|
|
5758
5889
|
});
|
|
5759
5890
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
5760
|
-
|
|
5891
|
+
const systemPromptStr = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
5892
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "system", systemPromptStr);
|
|
5893
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
|
|
5894
|
+
${analysisContent}
|
|
5895
|
+
|
|
5896
|
+
Executed Tools:
|
|
5897
|
+
${executedToolsText}`);
|
|
5761
5898
|
logCollector?.info("Matching components from text response...");
|
|
5762
5899
|
let fullResponseText = "";
|
|
5763
5900
|
let answerComponentExtracted = false;
|
|
@@ -5894,40 +6031,41 @@ ${fieldsText}`;
|
|
|
5894
6031
|
if (executedTool?.outputSchema?.fields && cleanedProps.config) {
|
|
5895
6032
|
const validFieldNames = executedTool.outputSchema.fields.map((f) => f.name);
|
|
5896
6033
|
const validFieldNamesLower = validFieldNames.map((n) => n.toLowerCase());
|
|
5897
|
-
const findMatchingField = (fieldName) => {
|
|
6034
|
+
const findMatchingField = (fieldName, configKey) => {
|
|
5898
6035
|
if (!fieldName) return null;
|
|
5899
6036
|
const lowerField = fieldName.toLowerCase();
|
|
5900
6037
|
const exactIdx = validFieldNamesLower.indexOf(lowerField);
|
|
5901
6038
|
if (exactIdx !== -1) return validFieldNames[exactIdx];
|
|
5902
|
-
const
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
if (
|
|
5917
|
-
|
|
5918
|
-
|
|
6039
|
+
const containsMatches = validFieldNames.filter(
|
|
6040
|
+
(_, i) => validFieldNamesLower[i].includes(lowerField) || lowerField.includes(validFieldNamesLower[i])
|
|
6041
|
+
);
|
|
6042
|
+
if (containsMatches.length === 1) return containsMatches[0];
|
|
6043
|
+
const fieldTypes = executedTool.outputSchema.fields.reduce((acc, f) => {
|
|
6044
|
+
acc[f.name] = f.type;
|
|
6045
|
+
return acc;
|
|
6046
|
+
}, {});
|
|
6047
|
+
const numericConfigKeys = ["yAxisKey", "valueKey", "aggregationField", "sizeKey"];
|
|
6048
|
+
const stringConfigKeys = ["xAxisKey", "nameKey", "labelKey", "groupBy"];
|
|
6049
|
+
if (numericConfigKeys.includes(configKey)) {
|
|
6050
|
+
const numericFields = validFieldNames.filter((f) => fieldTypes[f] === "number");
|
|
6051
|
+
const match = numericFields.find((f) => f.toLowerCase().includes(lowerField) || lowerField.includes(f.toLowerCase()));
|
|
6052
|
+
if (match) return match;
|
|
6053
|
+
if (numericFields.length > 0) {
|
|
6054
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first numeric field: ${numericFields[0]}`);
|
|
6055
|
+
return numericFields[0];
|
|
5919
6056
|
}
|
|
5920
6057
|
}
|
|
5921
|
-
if (
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
logger.warn(`[${this.getProviderName()}]
|
|
5927
|
-
return
|
|
6058
|
+
if (stringConfigKeys.includes(configKey)) {
|
|
6059
|
+
const stringFields = validFieldNames.filter((f) => fieldTypes[f] === "string");
|
|
6060
|
+
const match = stringFields.find((f) => f.toLowerCase().includes(lowerField) || lowerField.includes(f.toLowerCase()));
|
|
6061
|
+
if (match) return match;
|
|
6062
|
+
if (stringFields.length > 0) {
|
|
6063
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first string field: ${stringFields[0]}`);
|
|
6064
|
+
return stringFields[0];
|
|
5928
6065
|
}
|
|
5929
6066
|
}
|
|
5930
|
-
|
|
6067
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first field: ${validFieldNames[0]}`);
|
|
6068
|
+
return validFieldNames[0];
|
|
5931
6069
|
};
|
|
5932
6070
|
const configFieldsToValidate = [
|
|
5933
6071
|
"xAxisKey",
|
|
@@ -5946,12 +6084,10 @@ ${fieldsText}`;
|
|
|
5946
6084
|
const fieldValue = cleanedProps.config[configKey];
|
|
5947
6085
|
if (fieldValue && typeof fieldValue === "string") {
|
|
5948
6086
|
if (!validFieldNames.includes(fieldValue)) {
|
|
5949
|
-
const correctedField = findMatchingField(fieldValue);
|
|
6087
|
+
const correctedField = findMatchingField(fieldValue, configKey);
|
|
5950
6088
|
if (correctedField) {
|
|
5951
6089
|
logger.warn(`[${this.getProviderName()}] Correcting config.${configKey}: "${fieldValue}" \u2192 "${correctedField}"`);
|
|
5952
6090
|
cleanedProps.config[configKey] = correctedField;
|
|
5953
|
-
} else {
|
|
5954
|
-
logger.warn(`[${this.getProviderName()}] config.${configKey}="${fieldValue}" not found in outputSchema [${validFieldNames.join(", ")}]`);
|
|
5955
6091
|
}
|
|
5956
6092
|
}
|
|
5957
6093
|
}
|
|
@@ -5959,7 +6095,7 @@ ${fieldsText}`;
|
|
|
5959
6095
|
if (Array.isArray(cleanedProps.config.series)) {
|
|
5960
6096
|
cleanedProps.config.series = cleanedProps.config.series.map((s) => {
|
|
5961
6097
|
if (s.dataKey && typeof s.dataKey === "string" && !validFieldNames.includes(s.dataKey)) {
|
|
5962
|
-
const correctedField = findMatchingField(s.dataKey);
|
|
6098
|
+
const correctedField = findMatchingField(s.dataKey, "yAxisKey");
|
|
5963
6099
|
if (correctedField) {
|
|
5964
6100
|
logger.warn(`[${this.getProviderName()}] Correcting series.dataKey: "${s.dataKey}" \u2192 "${correctedField}"`);
|
|
5965
6101
|
return { ...s, dataKey: correctedField };
|
|
@@ -6026,6 +6162,10 @@ ${fieldsText}`;
|
|
|
6026
6162
|
AVAILABLE_TOOLS: availableToolsDoc,
|
|
6027
6163
|
SCHEMA_DOC: schemaDoc || "No database schema available"
|
|
6028
6164
|
});
|
|
6165
|
+
const systemPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
6166
|
+
const userPromptText = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
|
|
6167
|
+
logger.logLLMPrompt("classifyQuestionCategory", "system", systemPrompt);
|
|
6168
|
+
logger.logLLMPrompt("classifyQuestionCategory", "user", userPromptText);
|
|
6029
6169
|
const result = await LLM.stream(
|
|
6030
6170
|
{
|
|
6031
6171
|
sys: prompts.system,
|
|
@@ -6213,7 +6353,6 @@ ${fieldsText}`;
|
|
|
6213
6353
|
collections,
|
|
6214
6354
|
topK: 1
|
|
6215
6355
|
});
|
|
6216
|
-
logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
|
|
6217
6356
|
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
6218
6357
|
USER_PROMPT: userPrompt,
|
|
6219
6358
|
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
@@ -6222,8 +6361,10 @@ ${fieldsText}`;
|
|
|
6222
6361
|
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
|
|
6223
6362
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc
|
|
6224
6363
|
});
|
|
6225
|
-
|
|
6226
|
-
|
|
6364
|
+
const sysPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
6365
|
+
const usrPrompt = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
|
|
6366
|
+
logger.logLLMPrompt("generateTextResponse", "system", sysPrompt);
|
|
6367
|
+
logger.logLLMPrompt("generateTextResponse", "user", usrPrompt);
|
|
6227
6368
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6228
6369
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6229
6370
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6609,7 +6750,6 @@ ${errorMsg}
|
|
|
6609
6750
|
data: {
|
|
6610
6751
|
text: textResponse,
|
|
6611
6752
|
// Include the streamed text showing all attempts
|
|
6612
|
-
matchedComponents: [],
|
|
6613
6753
|
actions: [],
|
|
6614
6754
|
method: `${this.getProviderName()}-text-response-max-attempts`
|
|
6615
6755
|
}
|
|
@@ -6707,7 +6847,6 @@ ${errorMsg}
|
|
|
6707
6847
|
success: true,
|
|
6708
6848
|
data: {
|
|
6709
6849
|
text: textResponse,
|
|
6710
|
-
matchedComponents,
|
|
6711
6850
|
component: container_componet,
|
|
6712
6851
|
actions,
|
|
6713
6852
|
method: `${this.getProviderName()}-text-response`
|
|
@@ -6731,7 +6870,6 @@ ${errorMsg}
|
|
|
6731
6870
|
errors,
|
|
6732
6871
|
data: {
|
|
6733
6872
|
text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
|
|
6734
|
-
matchedComponents: [],
|
|
6735
6873
|
actions: [],
|
|
6736
6874
|
method: `${this.getProviderName()}-text-response-error`
|
|
6737
6875
|
}
|
|
@@ -6755,6 +6893,8 @@ ${errorMsg}
|
|
|
6755
6893
|
const startTime = Date.now();
|
|
6756
6894
|
logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
|
|
6757
6895
|
logCollector?.info(`Starting request processing with mode: ${responseMode}`);
|
|
6896
|
+
logger.clearFile();
|
|
6897
|
+
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
6758
6898
|
try {
|
|
6759
6899
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
6760
6900
|
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
@@ -6762,8 +6902,8 @@ ${errorMsg}
|
|
|
6762
6902
|
userPrompt,
|
|
6763
6903
|
collections,
|
|
6764
6904
|
userId,
|
|
6765
|
-
similarityThreshold: 0.
|
|
6766
|
-
//
|
|
6905
|
+
similarityThreshold: 0.8
|
|
6906
|
+
// 80% threshold
|
|
6767
6907
|
});
|
|
6768
6908
|
if (conversationMatch) {
|
|
6769
6909
|
logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
|
|
@@ -6788,7 +6928,6 @@ ${errorMsg}
|
|
|
6788
6928
|
data: {
|
|
6789
6929
|
text: cachedTextResponse,
|
|
6790
6930
|
component: null,
|
|
6791
|
-
matchedComponents: [],
|
|
6792
6931
|
actions: conversationMatch.uiBlock?.actions || [],
|
|
6793
6932
|
reasoning: `Exact match from previous general conversation`,
|
|
6794
6933
|
method: `${this.getProviderName()}-semantic-match-general`,
|
|
@@ -6816,7 +6955,6 @@ ${errorMsg}
|
|
|
6816
6955
|
data: {
|
|
6817
6956
|
text: cachedTextResponse,
|
|
6818
6957
|
component,
|
|
6819
|
-
matchedComponents: component?.props?.config?.components || [],
|
|
6820
6958
|
actions: cachedActions,
|
|
6821
6959
|
reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
|
|
6822
6960
|
method: `${this.getProviderName()}-semantic-match-exact`,
|
|
@@ -6852,7 +6990,6 @@ ${errorMsg}
|
|
|
6852
6990
|
data: {
|
|
6853
6991
|
text: textResponseToUse,
|
|
6854
6992
|
component: adaptResult.adaptedComponent,
|
|
6855
|
-
matchedComponents: adaptResult.adaptedComponent?.props?.config?.components || [],
|
|
6856
6993
|
actions: cachedActions,
|
|
6857
6994
|
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
6858
6995
|
method: `${this.getProviderName()}-semantic-match`,
|
|
@@ -6903,6 +7040,8 @@ ${errorMsg}
|
|
|
6903
7040
|
executionReason: t.executionReason || "",
|
|
6904
7041
|
requiredFields: t.requiredFields || [],
|
|
6905
7042
|
userProvidedData: t.userProvidedData || null,
|
|
7043
|
+
// CRITICAL: Include outputSchema from real tool for component config generation
|
|
7044
|
+
outputSchema: realTool?.outputSchema,
|
|
6906
7045
|
fn: (() => {
|
|
6907
7046
|
if (realTool) {
|
|
6908
7047
|
logger.info(`[${this.getProviderName()}] Using real tool implementation for ${t.type}`);
|
|
@@ -10459,6 +10598,331 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10459
10598
|
sendMessage(response);
|
|
10460
10599
|
}
|
|
10461
10600
|
|
|
10601
|
+
// src/handlers/menus.ts
|
|
10602
|
+
init_logger();
|
|
10603
|
+
async function handleMenusRequest(data, collections, sendMessage) {
|
|
10604
|
+
const executeCollection = async (collection, op, params) => {
|
|
10605
|
+
const handler = collections[collection]?.[op];
|
|
10606
|
+
if (!handler) {
|
|
10607
|
+
throw new Error(`Collection operation ${collection}.${op} not found`);
|
|
10608
|
+
}
|
|
10609
|
+
return await handler(params);
|
|
10610
|
+
};
|
|
10611
|
+
try {
|
|
10612
|
+
const request = MenusRequestMessageSchema.parse(data);
|
|
10613
|
+
const { id, payload, from } = request;
|
|
10614
|
+
const { operation, data: requestData } = payload;
|
|
10615
|
+
const menuId = requestData?.id;
|
|
10616
|
+
const name = requestData?.name;
|
|
10617
|
+
const componentName = requestData?.componentName;
|
|
10618
|
+
const icon = requestData?.icon;
|
|
10619
|
+
const userMessage = requestData?.userMessage;
|
|
10620
|
+
const parentId = requestData?.parentId;
|
|
10621
|
+
const sortOrder = requestData?.sortOrder;
|
|
10622
|
+
const props = requestData?.props;
|
|
10623
|
+
const isActive = requestData?.isActive;
|
|
10624
|
+
const filters = requestData?.filters;
|
|
10625
|
+
const limit = requestData?.limit;
|
|
10626
|
+
const sort = requestData?.sort;
|
|
10627
|
+
const items = requestData?.items;
|
|
10628
|
+
switch (operation) {
|
|
10629
|
+
case "create":
|
|
10630
|
+
await handleCreate7(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, from.id);
|
|
10631
|
+
break;
|
|
10632
|
+
case "update":
|
|
10633
|
+
await handleUpdate7(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, from.id);
|
|
10634
|
+
break;
|
|
10635
|
+
case "delete":
|
|
10636
|
+
await handleDelete7(id, menuId, executeCollection, sendMessage, from.id);
|
|
10637
|
+
break;
|
|
10638
|
+
case "getAll":
|
|
10639
|
+
await handleGetAll7(id, executeCollection, sendMessage, from.id);
|
|
10640
|
+
break;
|
|
10641
|
+
case "getOne":
|
|
10642
|
+
await handleGetOne7(id, menuId, executeCollection, sendMessage, from.id);
|
|
10643
|
+
break;
|
|
10644
|
+
case "getRootMenus":
|
|
10645
|
+
await handleGetRootMenus(id, executeCollection, sendMessage, from.id);
|
|
10646
|
+
break;
|
|
10647
|
+
case "getChildMenus":
|
|
10648
|
+
await handleGetChildMenus(id, parentId, executeCollection, sendMessage, from.id);
|
|
10649
|
+
break;
|
|
10650
|
+
case "getHierarchy":
|
|
10651
|
+
await handleGetHierarchy(id, executeCollection, sendMessage, from.id);
|
|
10652
|
+
break;
|
|
10653
|
+
case "query":
|
|
10654
|
+
await handleQuery6(id, filters, limit, sort, executeCollection, sendMessage, from.id);
|
|
10655
|
+
break;
|
|
10656
|
+
case "reorder":
|
|
10657
|
+
await handleReorder(id, items, executeCollection, sendMessage, from.id);
|
|
10658
|
+
break;
|
|
10659
|
+
default:
|
|
10660
|
+
sendResponse9(id, {
|
|
10661
|
+
success: false,
|
|
10662
|
+
error: `Unknown operation: ${operation}`
|
|
10663
|
+
}, sendMessage, from.id);
|
|
10664
|
+
}
|
|
10665
|
+
} catch (error) {
|
|
10666
|
+
logger.error("Failed to handle menus request:", error);
|
|
10667
|
+
sendResponse9(null, {
|
|
10668
|
+
success: false,
|
|
10669
|
+
error: error instanceof Error ? error.message : "Unknown error occurred"
|
|
10670
|
+
}, sendMessage);
|
|
10671
|
+
}
|
|
10672
|
+
}
|
|
10673
|
+
async function handleCreate7(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
|
|
10674
|
+
if (!name) {
|
|
10675
|
+
sendResponse9(id, {
|
|
10676
|
+
success: false,
|
|
10677
|
+
error: "name is required"
|
|
10678
|
+
}, sendMessage, clientId);
|
|
10679
|
+
return;
|
|
10680
|
+
}
|
|
10681
|
+
if (!componentName) {
|
|
10682
|
+
sendResponse9(id, {
|
|
10683
|
+
success: false,
|
|
10684
|
+
error: "componentName is required"
|
|
10685
|
+
}, sendMessage, clientId);
|
|
10686
|
+
return;
|
|
10687
|
+
}
|
|
10688
|
+
try {
|
|
10689
|
+
const result = await executeCollection("menus", "create", {
|
|
10690
|
+
name,
|
|
10691
|
+
componentName,
|
|
10692
|
+
icon,
|
|
10693
|
+
userMessage,
|
|
10694
|
+
parentId,
|
|
10695
|
+
sortOrder,
|
|
10696
|
+
props,
|
|
10697
|
+
isActive
|
|
10698
|
+
});
|
|
10699
|
+
sendResponse9(id, {
|
|
10700
|
+
success: true,
|
|
10701
|
+
data: result.data,
|
|
10702
|
+
message: "Menu created successfully"
|
|
10703
|
+
}, sendMessage, clientId);
|
|
10704
|
+
logger.info(`Menu created: ID ${result.data?.id}`);
|
|
10705
|
+
} catch (error) {
|
|
10706
|
+
sendResponse9(id, {
|
|
10707
|
+
success: false,
|
|
10708
|
+
error: error instanceof Error ? error.message : "Failed to create menu"
|
|
10709
|
+
}, sendMessage, clientId);
|
|
10710
|
+
}
|
|
10711
|
+
}
|
|
10712
|
+
async function handleUpdate7(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
|
|
10713
|
+
if (!menuId) {
|
|
10714
|
+
sendResponse9(id, {
|
|
10715
|
+
success: false,
|
|
10716
|
+
error: "Menu ID is required"
|
|
10717
|
+
}, sendMessage, clientId);
|
|
10718
|
+
return;
|
|
10719
|
+
}
|
|
10720
|
+
try {
|
|
10721
|
+
const result = await executeCollection("menus", "update", {
|
|
10722
|
+
id: menuId,
|
|
10723
|
+
name,
|
|
10724
|
+
componentName,
|
|
10725
|
+
icon,
|
|
10726
|
+
userMessage,
|
|
10727
|
+
parentId,
|
|
10728
|
+
sortOrder,
|
|
10729
|
+
props,
|
|
10730
|
+
isActive
|
|
10731
|
+
});
|
|
10732
|
+
sendResponse9(id, {
|
|
10733
|
+
success: true,
|
|
10734
|
+
data: result.data,
|
|
10735
|
+
message: "Menu updated successfully"
|
|
10736
|
+
}, sendMessage, clientId);
|
|
10737
|
+
logger.info(`Menu updated: ID ${menuId}`);
|
|
10738
|
+
} catch (error) {
|
|
10739
|
+
sendResponse9(id, {
|
|
10740
|
+
success: false,
|
|
10741
|
+
error: error instanceof Error ? error.message : "Failed to update menu"
|
|
10742
|
+
}, sendMessage, clientId);
|
|
10743
|
+
}
|
|
10744
|
+
}
|
|
10745
|
+
async function handleDelete7(id, menuId, executeCollection, sendMessage, clientId) {
|
|
10746
|
+
if (!menuId) {
|
|
10747
|
+
sendResponse9(id, {
|
|
10748
|
+
success: false,
|
|
10749
|
+
error: "Menu ID is required"
|
|
10750
|
+
}, sendMessage, clientId);
|
|
10751
|
+
return;
|
|
10752
|
+
}
|
|
10753
|
+
try {
|
|
10754
|
+
const result = await executeCollection("menus", "delete", { id: menuId });
|
|
10755
|
+
sendResponse9(id, {
|
|
10756
|
+
success: true,
|
|
10757
|
+
data: result.data,
|
|
10758
|
+
message: "Menu deleted successfully"
|
|
10759
|
+
}, sendMessage, clientId);
|
|
10760
|
+
logger.info(`Menu deleted: ID ${menuId}`);
|
|
10761
|
+
} catch (error) {
|
|
10762
|
+
sendResponse9(id, {
|
|
10763
|
+
success: false,
|
|
10764
|
+
error: error instanceof Error ? error.message : "Failed to delete menu"
|
|
10765
|
+
}, sendMessage, clientId);
|
|
10766
|
+
}
|
|
10767
|
+
}
|
|
10768
|
+
async function handleGetAll7(id, executeCollection, sendMessage, clientId) {
|
|
10769
|
+
try {
|
|
10770
|
+
const result = await executeCollection("menus", "getAll", {});
|
|
10771
|
+
sendResponse9(id, {
|
|
10772
|
+
success: true,
|
|
10773
|
+
data: result.data,
|
|
10774
|
+
count: result.count,
|
|
10775
|
+
message: `Retrieved ${result.count} menus`
|
|
10776
|
+
}, sendMessage, clientId);
|
|
10777
|
+
logger.info(`Retrieved all menus (count: ${result.count})`);
|
|
10778
|
+
} catch (error) {
|
|
10779
|
+
sendResponse9(id, {
|
|
10780
|
+
success: false,
|
|
10781
|
+
error: error instanceof Error ? error.message : "Failed to get menus"
|
|
10782
|
+
}, sendMessage, clientId);
|
|
10783
|
+
}
|
|
10784
|
+
}
|
|
10785
|
+
async function handleGetOne7(id, menuId, executeCollection, sendMessage, clientId) {
|
|
10786
|
+
if (!menuId) {
|
|
10787
|
+
sendResponse9(id, {
|
|
10788
|
+
success: false,
|
|
10789
|
+
error: "Menu ID is required"
|
|
10790
|
+
}, sendMessage, clientId);
|
|
10791
|
+
return;
|
|
10792
|
+
}
|
|
10793
|
+
try {
|
|
10794
|
+
const result = await executeCollection("menus", "getOne", { id: menuId });
|
|
10795
|
+
sendResponse9(id, {
|
|
10796
|
+
success: true,
|
|
10797
|
+
data: result.data,
|
|
10798
|
+
message: `Retrieved menu ID ${menuId}`
|
|
10799
|
+
}, sendMessage, clientId);
|
|
10800
|
+
logger.info(`Retrieved menu: ID ${menuId}`);
|
|
10801
|
+
} catch (error) {
|
|
10802
|
+
sendResponse9(id, {
|
|
10803
|
+
success: false,
|
|
10804
|
+
error: error instanceof Error ? error.message : "Failed to get menu"
|
|
10805
|
+
}, sendMessage, clientId);
|
|
10806
|
+
}
|
|
10807
|
+
}
|
|
10808
|
+
async function handleGetRootMenus(id, executeCollection, sendMessage, clientId) {
|
|
10809
|
+
try {
|
|
10810
|
+
const result = await executeCollection("menus", "getRootMenus", {});
|
|
10811
|
+
sendResponse9(id, {
|
|
10812
|
+
success: true,
|
|
10813
|
+
data: result.data,
|
|
10814
|
+
count: result.count,
|
|
10815
|
+
message: `Retrieved ${result.count} root menus`
|
|
10816
|
+
}, sendMessage, clientId);
|
|
10817
|
+
logger.info(`Retrieved root menus (count: ${result.count})`);
|
|
10818
|
+
} catch (error) {
|
|
10819
|
+
sendResponse9(id, {
|
|
10820
|
+
success: false,
|
|
10821
|
+
error: error instanceof Error ? error.message : "Failed to get root menus"
|
|
10822
|
+
}, sendMessage, clientId);
|
|
10823
|
+
}
|
|
10824
|
+
}
|
|
10825
|
+
async function handleGetChildMenus(id, parentId, executeCollection, sendMessage, clientId) {
|
|
10826
|
+
if (parentId === void 0 || parentId === null) {
|
|
10827
|
+
sendResponse9(id, {
|
|
10828
|
+
success: false,
|
|
10829
|
+
error: "parentId is required"
|
|
10830
|
+
}, sendMessage, clientId);
|
|
10831
|
+
return;
|
|
10832
|
+
}
|
|
10833
|
+
try {
|
|
10834
|
+
const result = await executeCollection("menus", "getChildMenus", { parentId });
|
|
10835
|
+
sendResponse9(id, {
|
|
10836
|
+
success: true,
|
|
10837
|
+
data: result.data,
|
|
10838
|
+
count: result.count,
|
|
10839
|
+
message: `Retrieved ${result.count} child menus for parent ${parentId}`
|
|
10840
|
+
}, sendMessage, clientId);
|
|
10841
|
+
logger.info(`Retrieved child menus for parent ${parentId} (count: ${result.count})`);
|
|
10842
|
+
} catch (error) {
|
|
10843
|
+
sendResponse9(id, {
|
|
10844
|
+
success: false,
|
|
10845
|
+
error: error instanceof Error ? error.message : "Failed to get child menus"
|
|
10846
|
+
}, sendMessage, clientId);
|
|
10847
|
+
}
|
|
10848
|
+
}
|
|
10849
|
+
async function handleGetHierarchy(id, executeCollection, sendMessage, clientId) {
|
|
10850
|
+
try {
|
|
10851
|
+
const result = await executeCollection("menus", "getHierarchy", {});
|
|
10852
|
+
sendResponse9(id, {
|
|
10853
|
+
success: true,
|
|
10854
|
+
data: result.data,
|
|
10855
|
+
count: result.count,
|
|
10856
|
+
message: `Retrieved menus hierarchy with ${result.count} root items`
|
|
10857
|
+
}, sendMessage, clientId);
|
|
10858
|
+
logger.info(`Retrieved menus hierarchy (root count: ${result.count})`);
|
|
10859
|
+
} catch (error) {
|
|
10860
|
+
sendResponse9(id, {
|
|
10861
|
+
success: false,
|
|
10862
|
+
error: error instanceof Error ? error.message : "Failed to get menus hierarchy"
|
|
10863
|
+
}, sendMessage, clientId);
|
|
10864
|
+
}
|
|
10865
|
+
}
|
|
10866
|
+
async function handleQuery6(id, filters, limit, sort, executeCollection, sendMessage, clientId) {
|
|
10867
|
+
try {
|
|
10868
|
+
const result = await executeCollection("menus", "query", {
|
|
10869
|
+
filters: filters || {},
|
|
10870
|
+
limit,
|
|
10871
|
+
sort
|
|
10872
|
+
});
|
|
10873
|
+
sendResponse9(id, {
|
|
10874
|
+
success: true,
|
|
10875
|
+
data: result.data,
|
|
10876
|
+
count: result.count,
|
|
10877
|
+
message: `Query returned ${result.count} menus`
|
|
10878
|
+
}, sendMessage, clientId);
|
|
10879
|
+
logger.info(`Query returned ${result.count} menus`);
|
|
10880
|
+
} catch (error) {
|
|
10881
|
+
sendResponse9(id, {
|
|
10882
|
+
success: false,
|
|
10883
|
+
error: error instanceof Error ? error.message : "Failed to query menus"
|
|
10884
|
+
}, sendMessage, clientId);
|
|
10885
|
+
}
|
|
10886
|
+
}
|
|
10887
|
+
async function handleReorder(id, items, executeCollection, sendMessage, clientId) {
|
|
10888
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
10889
|
+
sendResponse9(id, {
|
|
10890
|
+
success: false,
|
|
10891
|
+
error: "items array is required"
|
|
10892
|
+
}, sendMessage, clientId);
|
|
10893
|
+
return;
|
|
10894
|
+
}
|
|
10895
|
+
try {
|
|
10896
|
+
const result = await executeCollection("menus", "reorder", { items });
|
|
10897
|
+
sendResponse9(id, {
|
|
10898
|
+
success: true,
|
|
10899
|
+
data: result.data,
|
|
10900
|
+
message: `Reordered ${items.length} menus successfully`
|
|
10901
|
+
}, sendMessage, clientId);
|
|
10902
|
+
logger.info(`Reordered ${items.length} menus`);
|
|
10903
|
+
} catch (error) {
|
|
10904
|
+
sendResponse9(id, {
|
|
10905
|
+
success: false,
|
|
10906
|
+
error: error instanceof Error ? error.message : "Failed to reorder menus"
|
|
10907
|
+
}, sendMessage, clientId);
|
|
10908
|
+
}
|
|
10909
|
+
}
|
|
10910
|
+
function sendResponse9(id, res, sendMessage, clientId) {
|
|
10911
|
+
const response = {
|
|
10912
|
+
id: id || "unknown",
|
|
10913
|
+
type: "MENUS_RES",
|
|
10914
|
+
from: { type: "data-agent" },
|
|
10915
|
+
to: {
|
|
10916
|
+
type: "admin",
|
|
10917
|
+
id: clientId
|
|
10918
|
+
},
|
|
10919
|
+
payload: {
|
|
10920
|
+
...res
|
|
10921
|
+
}
|
|
10922
|
+
};
|
|
10923
|
+
sendMessage(response);
|
|
10924
|
+
}
|
|
10925
|
+
|
|
10462
10926
|
// src/dashComp/index.ts
|
|
10463
10927
|
init_logger();
|
|
10464
10928
|
|
|
@@ -10585,37 +11049,74 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10585
11049
|
return { success: false, errors };
|
|
10586
11050
|
}
|
|
10587
11051
|
logger.info(`[DASH_COMP_REQ] Using model: ${model}`);
|
|
10588
|
-
const
|
|
11052
|
+
const executedTools = [];
|
|
11053
|
+
const llmTools = (tools || []).map((tool) => ({
|
|
11054
|
+
name: tool.id,
|
|
11055
|
+
description: tool.description,
|
|
11056
|
+
input_schema: {
|
|
11057
|
+
type: "object",
|
|
11058
|
+
properties: Object.fromEntries(
|
|
11059
|
+
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` }])
|
|
11060
|
+
),
|
|
11061
|
+
additionalProperties: false
|
|
11062
|
+
}
|
|
11063
|
+
}));
|
|
11064
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
11065
|
+
const tool = tools?.find((t) => t.id === toolName);
|
|
11066
|
+
if (!tool) {
|
|
11067
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
11068
|
+
}
|
|
11069
|
+
logger.info(`[DASH_COMP_REQ] Executing external tool: ${tool.name} (${tool.id})`);
|
|
11070
|
+
const result2 = await tool.fn(toolInput);
|
|
11071
|
+
executedTools.push({
|
|
11072
|
+
id: tool.id,
|
|
11073
|
+
name: tool.name,
|
|
11074
|
+
params: toolInput,
|
|
11075
|
+
result: result2,
|
|
11076
|
+
outputSchema: tool.outputSchema
|
|
11077
|
+
});
|
|
11078
|
+
logger.info(`[DASH_COMP_REQ] Tool ${tool.name} executed successfully`);
|
|
11079
|
+
return JSON.stringify(result2, null, 2);
|
|
11080
|
+
};
|
|
11081
|
+
const result = await LLM.streamWithTools(
|
|
10589
11082
|
{
|
|
10590
11083
|
sys: prompts.system,
|
|
10591
11084
|
user: prompts.user
|
|
10592
11085
|
},
|
|
11086
|
+
llmTools,
|
|
11087
|
+
toolHandler,
|
|
10593
11088
|
{
|
|
10594
11089
|
model,
|
|
10595
11090
|
maxTokens: 8192,
|
|
10596
11091
|
temperature: 0.2,
|
|
10597
11092
|
apiKey
|
|
10598
11093
|
},
|
|
10599
|
-
|
|
10600
|
-
//
|
|
11094
|
+
5
|
|
11095
|
+
// max iterations
|
|
10601
11096
|
);
|
|
11097
|
+
const jsonMatch = result.match(/\{[\s\S]*\}/);
|
|
11098
|
+
const parsedResult = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
11099
|
+
if (!parsedResult) {
|
|
11100
|
+
errors.push("Failed to parse LLM response as JSON");
|
|
11101
|
+
return { success: false, errors };
|
|
11102
|
+
}
|
|
10602
11103
|
logger.debug("[DASH_COMP_REQ] LLM response received");
|
|
10603
|
-
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(
|
|
10604
|
-
if (!
|
|
11104
|
+
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
|
|
11105
|
+
if (!parsedResult.componentId || !parsedResult.props) {
|
|
10605
11106
|
errors.push("Invalid LLM response: missing componentId or props");
|
|
10606
11107
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
|
|
10607
11108
|
prompt,
|
|
10608
|
-
result,
|
|
10609
|
-
missingFields: { componentId: !
|
|
11109
|
+
result: parsedResult,
|
|
11110
|
+
missingFields: { componentId: !parsedResult.componentId, props: !parsedResult.props }
|
|
10610
11111
|
});
|
|
10611
11112
|
return { success: false, errors };
|
|
10612
11113
|
}
|
|
10613
|
-
const originalComponent = components.find((c) => c.name ===
|
|
11114
|
+
const originalComponent = components.find((c) => c.name === parsedResult.componentName);
|
|
10614
11115
|
if (!originalComponent) {
|
|
10615
|
-
errors.push(`Component ${
|
|
11116
|
+
errors.push(`Component ${parsedResult.componentName} not found in available components`);
|
|
10616
11117
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
10617
11118
|
prompt,
|
|
10618
|
-
componentName:
|
|
11119
|
+
componentName: parsedResult.componentName,
|
|
10619
11120
|
availableComponentNames: components.map((c) => c.name)
|
|
10620
11121
|
});
|
|
10621
11122
|
return { success: false, errors };
|
|
@@ -10624,23 +11125,27 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10624
11125
|
...originalComponent,
|
|
10625
11126
|
props: {
|
|
10626
11127
|
...originalComponent.props,
|
|
10627
|
-
...
|
|
11128
|
+
...parsedResult.props
|
|
10628
11129
|
}
|
|
10629
11130
|
};
|
|
10630
11131
|
logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
|
|
10631
|
-
if (
|
|
11132
|
+
if (parsedResult.props.query) {
|
|
10632
11133
|
logger.info(`[DASH_COMP_REQ] Data source: Database query`);
|
|
10633
11134
|
}
|
|
10634
|
-
if (
|
|
10635
|
-
logger.info(`[DASH_COMP_REQ] Data source: External tool - ${
|
|
11135
|
+
if (parsedResult.props.externalTool) {
|
|
11136
|
+
logger.info(`[DASH_COMP_REQ] Data source: External tool - ${parsedResult.props.externalTool.toolName}`);
|
|
11137
|
+
}
|
|
11138
|
+
if (executedTools.length > 0) {
|
|
11139
|
+
logger.info(`[DASH_COMP_REQ] Executed ${executedTools.length} external tool(s): ${executedTools.map((t) => t.name).join(", ")}`);
|
|
10636
11140
|
}
|
|
10637
11141
|
return {
|
|
10638
11142
|
success: true,
|
|
10639
11143
|
data: {
|
|
10640
11144
|
component: finalComponent,
|
|
10641
|
-
reasoning:
|
|
10642
|
-
dataSource:
|
|
10643
|
-
isUpdate:
|
|
11145
|
+
reasoning: parsedResult.reasoning || "Component selected based on user prompt",
|
|
11146
|
+
dataSource: parsedResult.props.query ? "database" : parsedResult.props.externalTool ? "external_tool" : "none",
|
|
11147
|
+
isUpdate: parsedResult.isUpdate || false,
|
|
11148
|
+
executedTools: executedTools.length > 0 ? executedTools : void 0
|
|
10644
11149
|
},
|
|
10645
11150
|
errors: []
|
|
10646
11151
|
};
|
|
@@ -10693,11 +11198,49 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10693
11198
|
return { success: false, errors };
|
|
10694
11199
|
}
|
|
10695
11200
|
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10696
|
-
const
|
|
11201
|
+
const executedTools = [];
|
|
11202
|
+
const llmTools = (tools || []).map((tool) => ({
|
|
11203
|
+
name: tool.id,
|
|
11204
|
+
description: tool.description,
|
|
11205
|
+
input_schema: {
|
|
11206
|
+
type: "object",
|
|
11207
|
+
properties: Object.fromEntries(
|
|
11208
|
+
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` }])
|
|
11209
|
+
),
|
|
11210
|
+
additionalProperties: false
|
|
11211
|
+
}
|
|
11212
|
+
}));
|
|
11213
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
11214
|
+
const tool = tools?.find((t) => t.id === toolName);
|
|
11215
|
+
if (!tool) {
|
|
11216
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
11217
|
+
}
|
|
11218
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Executing external tool: ${tool.name} (${tool.id})`);
|
|
11219
|
+
const result2 = await tool.fn(toolInput);
|
|
11220
|
+
executedTools.push({
|
|
11221
|
+
id: tool.id,
|
|
11222
|
+
name: tool.name,
|
|
11223
|
+
params: toolInput,
|
|
11224
|
+
result: result2,
|
|
11225
|
+
outputSchema: tool.outputSchema
|
|
11226
|
+
});
|
|
11227
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Tool ${tool.name} executed successfully`);
|
|
11228
|
+
return JSON.stringify(result2, null, 2);
|
|
11229
|
+
};
|
|
11230
|
+
const rawResult = await LLM.streamWithTools(
|
|
10697
11231
|
{ sys: prompts.system, user: prompts.user },
|
|
11232
|
+
llmTools,
|
|
11233
|
+
toolHandler,
|
|
10698
11234
|
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10699
|
-
|
|
11235
|
+
5
|
|
11236
|
+
// max iterations
|
|
10700
11237
|
);
|
|
11238
|
+
const jsonMatch = rawResult.match(/\{[\s\S]*\}/);
|
|
11239
|
+
const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
11240
|
+
if (!result) {
|
|
11241
|
+
errors.push("Failed to parse LLM response as JSON");
|
|
11242
|
+
return { success: false, errors };
|
|
11243
|
+
}
|
|
10701
11244
|
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10702
11245
|
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10703
11246
|
if (!result.filterComponent) {
|
|
@@ -10711,13 +11254,17 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10711
11254
|
}
|
|
10712
11255
|
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10713
11256
|
logger.info(`[DASH_COMP_REQ:FILTER] Updated ${result.updatedComponents?.length || 0} components`);
|
|
11257
|
+
if (executedTools.length > 0) {
|
|
11258
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Executed ${executedTools.length} external tool(s): ${executedTools.map((t) => t.name).join(", ")}`);
|
|
11259
|
+
}
|
|
10714
11260
|
return {
|
|
10715
11261
|
success: true,
|
|
10716
11262
|
data: {
|
|
10717
11263
|
filterComponent: result.filterComponent,
|
|
10718
11264
|
updatedComponents: result.updatedComponents || [],
|
|
10719
11265
|
filterBindings: result.filterBindings || {},
|
|
10720
|
-
reasoning: result.reasoning || "Filter created based on user prompt"
|
|
11266
|
+
reasoning: result.reasoning || "Filter created based on user prompt",
|
|
11267
|
+
executedTools: executedTools.length > 0 ? executedTools : void 0
|
|
10721
11268
|
},
|
|
10722
11269
|
errors: []
|
|
10723
11270
|
};
|
|
@@ -11895,6 +12442,11 @@ var SuperatomSDK = class {
|
|
|
11895
12442
|
logger.error("Failed to handle KB nodes request:", error);
|
|
11896
12443
|
});
|
|
11897
12444
|
break;
|
|
12445
|
+
case "MENUS":
|
|
12446
|
+
handleMenusRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
|
|
12447
|
+
logger.error("Failed to handle menus request:", error);
|
|
12448
|
+
});
|
|
12449
|
+
break;
|
|
11898
12450
|
case "DASH_COMP_REQ":
|
|
11899
12451
|
handleDashCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
|
|
11900
12452
|
logger.error("Failed to handle dash comp request:", error);
|