@superatomai/sdk-node 0.0.52 → 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 +619 -84
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +619 -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,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,35 +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"}`;
|
|
5728
5850
|
const fieldsText = fields.map(
|
|
5729
|
-
(f) => `
|
|
5730
|
-
type: ${f.type}
|
|
5731
|
-
description: ${f.description}`
|
|
5851
|
+
(f) => ` "${f.name}" (${f.type}): ${f.description}`
|
|
5732
5852
|
).join("\n");
|
|
5733
5853
|
outputSchemaText = `${tool.outputSchema.description}
|
|
5734
|
-
Fields
|
|
5854
|
+
Fields:
|
|
5735
5855
|
${fieldsText}`;
|
|
5736
5856
|
}
|
|
5737
5857
|
return `${idx + 1}. **${tool.name}**
|
|
5738
|
-
toolId: "${tool.id}"
|
|
5739
|
-
toolName: "${tool.name}"
|
|
5740
|
-
parameters: ${JSON.stringify(tool.params || {})}
|
|
5858
|
+
toolId: "${tool.id}"
|
|
5859
|
+
toolName: "${tool.name}"
|
|
5860
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
5741
5861
|
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`;
|
|
5862
|
+
outputSchema: ${outputSchemaText}${fieldNamesList}`;
|
|
5744
5863
|
}).join("\n\n");
|
|
5745
5864
|
}
|
|
5746
5865
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
5747
5866
|
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
5867
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
5752
5868
|
ANALYSIS_CONTENT: analysisContent,
|
|
5753
5869
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -5757,7 +5873,13 @@ ${fieldsText}`;
|
|
|
5757
5873
|
EXECUTED_TOOLS: executedToolsText
|
|
5758
5874
|
});
|
|
5759
5875
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
5760
|
-
|
|
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}`);
|
|
5761
5883
|
logCollector?.info("Matching components from text response...");
|
|
5762
5884
|
let fullResponseText = "";
|
|
5763
5885
|
let answerComponentExtracted = false;
|
|
@@ -5894,40 +6016,41 @@ ${fieldsText}`;
|
|
|
5894
6016
|
if (executedTool?.outputSchema?.fields && cleanedProps.config) {
|
|
5895
6017
|
const validFieldNames = executedTool.outputSchema.fields.map((f) => f.name);
|
|
5896
6018
|
const validFieldNamesLower = validFieldNames.map((n) => n.toLowerCase());
|
|
5897
|
-
const findMatchingField = (fieldName) => {
|
|
6019
|
+
const findMatchingField = (fieldName, configKey) => {
|
|
5898
6020
|
if (!fieldName) return null;
|
|
5899
6021
|
const lowerField = fieldName.toLowerCase();
|
|
5900
6022
|
const exactIdx = validFieldNamesLower.indexOf(lowerField);
|
|
5901
6023
|
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
|
-
|
|
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];
|
|
5919
6041
|
}
|
|
5920
6042
|
}
|
|
5921
|
-
if (
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
logger.warn(`[${this.getProviderName()}]
|
|
5927
|
-
return
|
|
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];
|
|
5928
6050
|
}
|
|
5929
6051
|
}
|
|
5930
|
-
|
|
6052
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first field: ${validFieldNames[0]}`);
|
|
6053
|
+
return validFieldNames[0];
|
|
5931
6054
|
};
|
|
5932
6055
|
const configFieldsToValidate = [
|
|
5933
6056
|
"xAxisKey",
|
|
@@ -5946,12 +6069,10 @@ ${fieldsText}`;
|
|
|
5946
6069
|
const fieldValue = cleanedProps.config[configKey];
|
|
5947
6070
|
if (fieldValue && typeof fieldValue === "string") {
|
|
5948
6071
|
if (!validFieldNames.includes(fieldValue)) {
|
|
5949
|
-
const correctedField = findMatchingField(fieldValue);
|
|
6072
|
+
const correctedField = findMatchingField(fieldValue, configKey);
|
|
5950
6073
|
if (correctedField) {
|
|
5951
6074
|
logger.warn(`[${this.getProviderName()}] Correcting config.${configKey}: "${fieldValue}" \u2192 "${correctedField}"`);
|
|
5952
6075
|
cleanedProps.config[configKey] = correctedField;
|
|
5953
|
-
} else {
|
|
5954
|
-
logger.warn(`[${this.getProviderName()}] config.${configKey}="${fieldValue}" not found in outputSchema [${validFieldNames.join(", ")}]`);
|
|
5955
6076
|
}
|
|
5956
6077
|
}
|
|
5957
6078
|
}
|
|
@@ -5959,7 +6080,7 @@ ${fieldsText}`;
|
|
|
5959
6080
|
if (Array.isArray(cleanedProps.config.series)) {
|
|
5960
6081
|
cleanedProps.config.series = cleanedProps.config.series.map((s) => {
|
|
5961
6082
|
if (s.dataKey && typeof s.dataKey === "string" && !validFieldNames.includes(s.dataKey)) {
|
|
5962
|
-
const correctedField = findMatchingField(s.dataKey);
|
|
6083
|
+
const correctedField = findMatchingField(s.dataKey, "yAxisKey");
|
|
5963
6084
|
if (correctedField) {
|
|
5964
6085
|
logger.warn(`[${this.getProviderName()}] Correcting series.dataKey: "${s.dataKey}" \u2192 "${correctedField}"`);
|
|
5965
6086
|
return { ...s, dataKey: correctedField };
|
|
@@ -6026,6 +6147,10 @@ ${fieldsText}`;
|
|
|
6026
6147
|
AVAILABLE_TOOLS: availableToolsDoc,
|
|
6027
6148
|
SCHEMA_DOC: schemaDoc || "No database schema available"
|
|
6028
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);
|
|
6029
6154
|
const result = await LLM.stream(
|
|
6030
6155
|
{
|
|
6031
6156
|
sys: prompts.system,
|
|
@@ -6213,7 +6338,6 @@ ${fieldsText}`;
|
|
|
6213
6338
|
collections,
|
|
6214
6339
|
topK: 1
|
|
6215
6340
|
});
|
|
6216
|
-
logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
|
|
6217
6341
|
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
6218
6342
|
USER_PROMPT: userPrompt,
|
|
6219
6343
|
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
@@ -6222,8 +6346,10 @@ ${fieldsText}`;
|
|
|
6222
6346
|
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
|
|
6223
6347
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc
|
|
6224
6348
|
});
|
|
6225
|
-
|
|
6226
|
-
|
|
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);
|
|
6227
6353
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6228
6354
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6229
6355
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6609,7 +6735,6 @@ ${errorMsg}
|
|
|
6609
6735
|
data: {
|
|
6610
6736
|
text: textResponse,
|
|
6611
6737
|
// Include the streamed text showing all attempts
|
|
6612
|
-
matchedComponents: [],
|
|
6613
6738
|
actions: [],
|
|
6614
6739
|
method: `${this.getProviderName()}-text-response-max-attempts`
|
|
6615
6740
|
}
|
|
@@ -6707,7 +6832,6 @@ ${errorMsg}
|
|
|
6707
6832
|
success: true,
|
|
6708
6833
|
data: {
|
|
6709
6834
|
text: textResponse,
|
|
6710
|
-
matchedComponents,
|
|
6711
6835
|
component: container_componet,
|
|
6712
6836
|
actions,
|
|
6713
6837
|
method: `${this.getProviderName()}-text-response`
|
|
@@ -6731,7 +6855,6 @@ ${errorMsg}
|
|
|
6731
6855
|
errors,
|
|
6732
6856
|
data: {
|
|
6733
6857
|
text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
|
|
6734
|
-
matchedComponents: [],
|
|
6735
6858
|
actions: [],
|
|
6736
6859
|
method: `${this.getProviderName()}-text-response-error`
|
|
6737
6860
|
}
|
|
@@ -6755,6 +6878,8 @@ ${errorMsg}
|
|
|
6755
6878
|
const startTime = Date.now();
|
|
6756
6879
|
logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
|
|
6757
6880
|
logCollector?.info(`Starting request processing with mode: ${responseMode}`);
|
|
6881
|
+
logger.clearFile();
|
|
6882
|
+
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
6758
6883
|
try {
|
|
6759
6884
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
6760
6885
|
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
@@ -6762,8 +6887,8 @@ ${errorMsg}
|
|
|
6762
6887
|
userPrompt,
|
|
6763
6888
|
collections,
|
|
6764
6889
|
userId,
|
|
6765
|
-
similarityThreshold: 0.
|
|
6766
|
-
//
|
|
6890
|
+
similarityThreshold: 0.8
|
|
6891
|
+
// 80% threshold
|
|
6767
6892
|
});
|
|
6768
6893
|
if (conversationMatch) {
|
|
6769
6894
|
logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
|
|
@@ -6788,7 +6913,6 @@ ${errorMsg}
|
|
|
6788
6913
|
data: {
|
|
6789
6914
|
text: cachedTextResponse,
|
|
6790
6915
|
component: null,
|
|
6791
|
-
matchedComponents: [],
|
|
6792
6916
|
actions: conversationMatch.uiBlock?.actions || [],
|
|
6793
6917
|
reasoning: `Exact match from previous general conversation`,
|
|
6794
6918
|
method: `${this.getProviderName()}-semantic-match-general`,
|
|
@@ -6816,7 +6940,6 @@ ${errorMsg}
|
|
|
6816
6940
|
data: {
|
|
6817
6941
|
text: cachedTextResponse,
|
|
6818
6942
|
component,
|
|
6819
|
-
matchedComponents: component?.props?.config?.components || [],
|
|
6820
6943
|
actions: cachedActions,
|
|
6821
6944
|
reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
|
|
6822
6945
|
method: `${this.getProviderName()}-semantic-match-exact`,
|
|
@@ -6852,7 +6975,6 @@ ${errorMsg}
|
|
|
6852
6975
|
data: {
|
|
6853
6976
|
text: textResponseToUse,
|
|
6854
6977
|
component: adaptResult.adaptedComponent,
|
|
6855
|
-
matchedComponents: adaptResult.adaptedComponent?.props?.config?.components || [],
|
|
6856
6978
|
actions: cachedActions,
|
|
6857
6979
|
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
6858
6980
|
method: `${this.getProviderName()}-semantic-match`,
|
|
@@ -10459,6 +10581,331 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10459
10581
|
sendMessage(response);
|
|
10460
10582
|
}
|
|
10461
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
|
+
|
|
10462
10909
|
// src/dashComp/index.ts
|
|
10463
10910
|
init_logger();
|
|
10464
10911
|
|
|
@@ -10585,37 +11032,74 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10585
11032
|
return { success: false, errors };
|
|
10586
11033
|
}
|
|
10587
11034
|
logger.info(`[DASH_COMP_REQ] Using model: ${model}`);
|
|
10588
|
-
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(
|
|
10589
11065
|
{
|
|
10590
11066
|
sys: prompts.system,
|
|
10591
11067
|
user: prompts.user
|
|
10592
11068
|
},
|
|
11069
|
+
llmTools,
|
|
11070
|
+
toolHandler,
|
|
10593
11071
|
{
|
|
10594
11072
|
model,
|
|
10595
11073
|
maxTokens: 8192,
|
|
10596
11074
|
temperature: 0.2,
|
|
10597
11075
|
apiKey
|
|
10598
11076
|
},
|
|
10599
|
-
|
|
10600
|
-
//
|
|
11077
|
+
5
|
|
11078
|
+
// max iterations
|
|
10601
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
|
+
}
|
|
10602
11086
|
logger.debug("[DASH_COMP_REQ] LLM response received");
|
|
10603
|
-
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(
|
|
10604
|
-
if (!
|
|
11087
|
+
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
|
|
11088
|
+
if (!parsedResult.componentId || !parsedResult.props) {
|
|
10605
11089
|
errors.push("Invalid LLM response: missing componentId or props");
|
|
10606
11090
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
|
|
10607
11091
|
prompt,
|
|
10608
|
-
result,
|
|
10609
|
-
missingFields: { componentId: !
|
|
11092
|
+
result: parsedResult,
|
|
11093
|
+
missingFields: { componentId: !parsedResult.componentId, props: !parsedResult.props }
|
|
10610
11094
|
});
|
|
10611
11095
|
return { success: false, errors };
|
|
10612
11096
|
}
|
|
10613
|
-
const originalComponent = components.find((c) => c.name ===
|
|
11097
|
+
const originalComponent = components.find((c) => c.name === parsedResult.componentName);
|
|
10614
11098
|
if (!originalComponent) {
|
|
10615
|
-
errors.push(`Component ${
|
|
11099
|
+
errors.push(`Component ${parsedResult.componentName} not found in available components`);
|
|
10616
11100
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
10617
11101
|
prompt,
|
|
10618
|
-
componentName:
|
|
11102
|
+
componentName: parsedResult.componentName,
|
|
10619
11103
|
availableComponentNames: components.map((c) => c.name)
|
|
10620
11104
|
});
|
|
10621
11105
|
return { success: false, errors };
|
|
@@ -10624,23 +11108,27 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10624
11108
|
...originalComponent,
|
|
10625
11109
|
props: {
|
|
10626
11110
|
...originalComponent.props,
|
|
10627
|
-
...
|
|
11111
|
+
...parsedResult.props
|
|
10628
11112
|
}
|
|
10629
11113
|
};
|
|
10630
11114
|
logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
|
|
10631
|
-
if (
|
|
11115
|
+
if (parsedResult.props.query) {
|
|
10632
11116
|
logger.info(`[DASH_COMP_REQ] Data source: Database query`);
|
|
10633
11117
|
}
|
|
10634
|
-
if (
|
|
10635
|
-
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(", ")}`);
|
|
10636
11123
|
}
|
|
10637
11124
|
return {
|
|
10638
11125
|
success: true,
|
|
10639
11126
|
data: {
|
|
10640
11127
|
component: finalComponent,
|
|
10641
|
-
reasoning:
|
|
10642
|
-
dataSource:
|
|
10643
|
-
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
|
|
10644
11132
|
},
|
|
10645
11133
|
errors: []
|
|
10646
11134
|
};
|
|
@@ -10693,11 +11181,49 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10693
11181
|
return { success: false, errors };
|
|
10694
11182
|
}
|
|
10695
11183
|
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10696
|
-
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(
|
|
10697
11214
|
{ sys: prompts.system, user: prompts.user },
|
|
11215
|
+
llmTools,
|
|
11216
|
+
toolHandler,
|
|
10698
11217
|
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10699
|
-
|
|
11218
|
+
5
|
|
11219
|
+
// max iterations
|
|
10700
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
|
+
}
|
|
10701
11227
|
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10702
11228
|
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10703
11229
|
if (!result.filterComponent) {
|
|
@@ -10711,13 +11237,17 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10711
11237
|
}
|
|
10712
11238
|
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10713
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
|
+
}
|
|
10714
11243
|
return {
|
|
10715
11244
|
success: true,
|
|
10716
11245
|
data: {
|
|
10717
11246
|
filterComponent: result.filterComponent,
|
|
10718
11247
|
updatedComponents: result.updatedComponents || [],
|
|
10719
11248
|
filterBindings: result.filterBindings || {},
|
|
10720
|
-
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
|
|
10721
11251
|
},
|
|
10722
11252
|
errors: []
|
|
10723
11253
|
};
|
|
@@ -11895,6 +12425,11 @@ var SuperatomSDK = class {
|
|
|
11895
12425
|
logger.error("Failed to handle KB nodes request:", error);
|
|
11896
12426
|
});
|
|
11897
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;
|
|
11898
12433
|
case "DASH_COMP_REQ":
|
|
11899
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) => {
|
|
11900
12435
|
logger.error("Failed to handle dash comp request:", error);
|