@superatomai/sdk-node 0.0.50 → 0.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +942 -942
- package/dist/index.d.mts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +672 -52
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +672 -52
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -10,12 +10,13 @@ var __export = (target, all) => {
|
|
|
10
10
|
|
|
11
11
|
// src/utils/logger.ts
|
|
12
12
|
import fs from "fs";
|
|
13
|
-
var PREFIX, LOGSTREAM, LOG_LEVEL_PRIORITY, MESSAGE_LEVEL_PRIORITY, Logger, logger;
|
|
13
|
+
var PREFIX, LOG_FILE_PATH, LOGSTREAM, LOG_LEVEL_PRIORITY, MESSAGE_LEVEL_PRIORITY, Logger, logger;
|
|
14
14
|
var init_logger = __esm({
|
|
15
15
|
"src/utils/logger.ts"() {
|
|
16
16
|
"use strict";
|
|
17
17
|
PREFIX = "[SuperatomSDK]";
|
|
18
|
-
|
|
18
|
+
LOG_FILE_PATH = "superatom-sdk.log";
|
|
19
|
+
LOGSTREAM = fs.createWriteStream(LOG_FILE_PATH, { flags: "a" });
|
|
19
20
|
LOG_LEVEL_PRIORITY = {
|
|
20
21
|
errors: 0,
|
|
21
22
|
warnings: 1,
|
|
@@ -99,9 +100,43 @@ var init_logger = __esm({
|
|
|
99
100
|
console.log(PREFIX, "[DEBUG]", ...args);
|
|
100
101
|
}
|
|
101
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Write to log file
|
|
105
|
+
*/
|
|
102
106
|
file(...args) {
|
|
103
107
|
LOGSTREAM.write(args.join(" ") + "\n");
|
|
104
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Clear the log file (call at start of new user request)
|
|
111
|
+
*/
|
|
112
|
+
clearFile() {
|
|
113
|
+
LOGSTREAM.end();
|
|
114
|
+
LOGSTREAM = fs.createWriteStream(LOG_FILE_PATH, { flags: "w" });
|
|
115
|
+
LOGSTREAM.write(`
|
|
116
|
+
${"=".repeat(80)}
|
|
117
|
+
`);
|
|
118
|
+
LOGSTREAM.write(`NEW REQUEST - ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
119
|
+
`);
|
|
120
|
+
LOGSTREAM.write(`${"=".repeat(80)}
|
|
121
|
+
|
|
122
|
+
`);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Log LLM method prompts with clear labeling
|
|
126
|
+
*/
|
|
127
|
+
logLLMPrompt(methodName, promptType, content) {
|
|
128
|
+
const header = `
|
|
129
|
+
${"#".repeat(80)}
|
|
130
|
+
[LLM METHOD: ${methodName}] - ${promptType.toUpperCase()} PROMPT
|
|
131
|
+
${"#".repeat(80)}
|
|
132
|
+
`;
|
|
133
|
+
LOGSTREAM.write(header);
|
|
134
|
+
LOGSTREAM.write(content);
|
|
135
|
+
LOGSTREAM.write(`
|
|
136
|
+
${"#".repeat(80)}
|
|
137
|
+
|
|
138
|
+
`);
|
|
139
|
+
}
|
|
105
140
|
};
|
|
106
141
|
logger = new Logger();
|
|
107
142
|
}
|
|
@@ -1019,8 +1054,20 @@ If adaptation is not possible or would fundamentally change the component:
|
|
|
1019
1054
|
|
|
1020
1055
|
Analyze the user's request and:
|
|
1021
1056
|
1. **Select the most appropriate component** from the available components list
|
|
1022
|
-
2. **Determine the data source**: Database query OR External tool
|
|
1023
|
-
3. **Generate complete props** for the selected component
|
|
1057
|
+
2. **Determine the data source**: Database query OR External tool
|
|
1058
|
+
3. **Generate complete props** for the selected component
|
|
1059
|
+
|
|
1060
|
+
## Available External Tools
|
|
1061
|
+
|
|
1062
|
+
The following external tools are available:
|
|
1063
|
+
|
|
1064
|
+
{{AVAILABLE_TOOLS}}
|
|
1065
|
+
|
|
1066
|
+
When a tool is needed to complete the user's request:
|
|
1067
|
+
1. **Analyze the request** to determine which tool is needed
|
|
1068
|
+
2. **Extract parameters** from the user's question
|
|
1069
|
+
3. **Execute the tool** by calling it with the extracted parameters
|
|
1070
|
+
4. **Use the results** to configure the component (field names for axes, columns, etc.)
|
|
1024
1071
|
|
|
1025
1072
|
## Component Selection Rules
|
|
1026
1073
|
|
|
@@ -1176,7 +1223,20 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1176
1223
|
|
|
1177
1224
|
1. **Create a filter component** based on the user's request
|
|
1178
1225
|
2. **Update existing components** with dynamic title/description interpolation if needed
|
|
1179
|
-
3. **
|
|
1226
|
+
3. **Set default values in component externalTool.params** that match the filter's default option
|
|
1227
|
+
4. **Preserve all existing props** - the filter system handles param merging at runtime
|
|
1228
|
+
|
|
1229
|
+
## Available External Tools
|
|
1230
|
+
|
|
1231
|
+
The following external tools are available:
|
|
1232
|
+
|
|
1233
|
+
{{AVAILABLE_TOOLS}}
|
|
1234
|
+
|
|
1235
|
+
When a tool is needed to complete the user's request:
|
|
1236
|
+
1. **Analyze the request** to determine which tool is needed
|
|
1237
|
+
2. **Extract parameters** from the user's question
|
|
1238
|
+
3. **Execute the tool** by calling it with the extracted parameters
|
|
1239
|
+
4. **Use the results** to configure the filter and components properly
|
|
1180
1240
|
|
|
1181
1241
|
## How The Filter System Works
|
|
1182
1242
|
|
|
@@ -1206,16 +1266,20 @@ Use \`{%filterKeyLabel%}\` syntax for dynamic text:
|
|
|
1206
1266
|
## Updating Existing Components
|
|
1207
1267
|
|
|
1208
1268
|
**IMPORTANT - Parameter Handling:**
|
|
1209
|
-
- Do NOT change existing parameter values to placeholders
|
|
1210
|
-
- Keep all existing/default parameter values as they are
|
|
1211
1269
|
- The filter system MERGES params at runtime: filter params override component defaults
|
|
1270
|
+
- Component's \`externalTool.params\` should have DEFAULT values matching the filter's default option
|
|
1271
|
+
- This ensures the component shows correct data on initial load before user changes the filter
|
|
1212
1272
|
|
|
1213
1273
|
**What to modify in existing components:**
|
|
1214
1274
|
- Modify \`title\` for \`{%filterKeyLabel%}\` interpolation (only if title exists)
|
|
1215
1275
|
- Modify \`description\` for interpolation (only if description exists)
|
|
1216
|
-
-
|
|
1276
|
+
- Set \`externalTool.params\` default values to match filter's default option params
|
|
1217
1277
|
- Copy ALL other props exactly as provided
|
|
1218
1278
|
|
|
1279
|
+
**Example - Setting default params:**
|
|
1280
|
+
If filter has default option with params: \`{ startDate: "2025-01-01", endDate: "2025-01-31" }\`
|
|
1281
|
+
Then component's externalTool should have: \`{ params: { startDate: "2025-01-01", endDate: "2025-01-31" } }\`
|
|
1282
|
+
|
|
1219
1283
|
### Database Query Rules
|
|
1220
1284
|
{{DATABASE_RULES}}
|
|
1221
1285
|
|
|
@@ -1263,10 +1327,11 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1263
1327
|
**CRITICAL RULES:**
|
|
1264
1328
|
1. Return ONLY valid JSON (no markdown code blocks)
|
|
1265
1329
|
2. **COPY ALL existing props** - modify title/description for interpolation only if they exist
|
|
1266
|
-
3. **
|
|
1330
|
+
3. **Set externalTool.params defaults** to match the filter's default option params
|
|
1267
1331
|
4. Use \`{%filterKeyLabel%}\` for dynamic text (NOT \`{{...}}\` or \`$...\`)
|
|
1268
1332
|
5. Filter \`params\` must have ACTUAL values (real dates, strings), not placeholders
|
|
1269
1333
|
6. Each filter option needs: label, value, params (and optionally isDefault)
|
|
1334
|
+
7. Component default params MUST match filter default - this ensures correct initial data load
|
|
1270
1335
|
|
|
1271
1336
|
## Database Schema
|
|
1272
1337
|
{{SCHEMA_DOC}}
|
|
@@ -2309,6 +2374,57 @@ var KbNodesRequestMessageSchema = z3.object({
|
|
|
2309
2374
|
type: z3.literal("KB_NODES"),
|
|
2310
2375
|
payload: KbNodesRequestPayloadSchema
|
|
2311
2376
|
});
|
|
2377
|
+
var MenusQueryFiltersSchema = z3.object({
|
|
2378
|
+
parentId: z3.number().nullable().optional(),
|
|
2379
|
+
isActive: z3.boolean().optional()
|
|
2380
|
+
});
|
|
2381
|
+
var MenusRequestPayloadSchema = z3.object({
|
|
2382
|
+
operation: z3.enum([
|
|
2383
|
+
"create",
|
|
2384
|
+
"update",
|
|
2385
|
+
"delete",
|
|
2386
|
+
"getAll",
|
|
2387
|
+
"getOne",
|
|
2388
|
+
"getRootMenus",
|
|
2389
|
+
"getChildMenus",
|
|
2390
|
+
"getHierarchy",
|
|
2391
|
+
"query",
|
|
2392
|
+
"reorder"
|
|
2393
|
+
]),
|
|
2394
|
+
data: z3.object({
|
|
2395
|
+
id: z3.number().optional(),
|
|
2396
|
+
name: z3.string().optional(),
|
|
2397
|
+
componentName: z3.string().optional(),
|
|
2398
|
+
icon: z3.string().optional(),
|
|
2399
|
+
userMessage: z3.string().optional(),
|
|
2400
|
+
parentId: z3.number().nullable().optional(),
|
|
2401
|
+
sortOrder: z3.number().optional(),
|
|
2402
|
+
props: z3.record(z3.unknown()).optional(),
|
|
2403
|
+
isActive: z3.boolean().optional(),
|
|
2404
|
+
// Query operation fields
|
|
2405
|
+
filters: MenusQueryFiltersSchema.optional(),
|
|
2406
|
+
limit: z3.number().optional(),
|
|
2407
|
+
sort: z3.enum(["ASC", "DESC"]).optional(),
|
|
2408
|
+
// Reorder operation fields
|
|
2409
|
+
items: z3.array(z3.object({
|
|
2410
|
+
id: z3.number(),
|
|
2411
|
+
sortOrder: z3.number()
|
|
2412
|
+
})).optional()
|
|
2413
|
+
}).optional()
|
|
2414
|
+
});
|
|
2415
|
+
var MenusRequestMessageSchema = z3.object({
|
|
2416
|
+
id: z3.string(),
|
|
2417
|
+
from: MessageParticipantSchema,
|
|
2418
|
+
type: z3.literal("MENUS"),
|
|
2419
|
+
payload: MenusRequestPayloadSchema
|
|
2420
|
+
});
|
|
2421
|
+
var MenusResponsePayloadSchema = z3.object({
|
|
2422
|
+
success: z3.boolean(),
|
|
2423
|
+
error: z3.string().optional(),
|
|
2424
|
+
data: z3.any().optional(),
|
|
2425
|
+
count: z3.number().optional(),
|
|
2426
|
+
message: z3.string().optional()
|
|
2427
|
+
});
|
|
2312
2428
|
var DashCompRequestPayloadSchema = z3.object({
|
|
2313
2429
|
prompt: z3.string(),
|
|
2314
2430
|
userId: z3.string().optional(),
|
|
@@ -5669,30 +5785,35 @@ ${JSON.stringify(tool.requiredFields || [], null, 2)}`;
|
|
|
5669
5785
|
let executedToolsText = "No external tools were executed for data fetching.";
|
|
5670
5786
|
if (executedTools && executedTools.length > 0) {
|
|
5671
5787
|
logger.info(`[${this.getProviderName()}] Passing ${executedTools.length} executed tools to component matching`);
|
|
5672
|
-
executedToolsText = "The following external tools were executed to fetch data.\n**IMPORTANT: For components displaying this data, use externalTool prop instead of query.**\n**IMPORTANT: Use the
|
|
5788
|
+
executedToolsText = "The following external tools were executed to fetch data.\n**IMPORTANT: For components displaying this data, use externalTool prop instead of query.**\n**IMPORTANT: Use ONLY the field names listed in outputSchema for config keys.**\n\n" + executedTools.map((tool, idx) => {
|
|
5673
5789
|
let outputSchemaText = "Not available";
|
|
5790
|
+
let fieldNamesList = "";
|
|
5674
5791
|
let recordCount = "unknown";
|
|
5675
5792
|
if (tool.outputSchema) {
|
|
5676
5793
|
const fields = tool.outputSchema.fields || [];
|
|
5677
5794
|
recordCount = tool.result?._recordCount || (Array.isArray(tool.result) ? tool.result.length : "unknown");
|
|
5795
|
+
const numericFields = fields.filter((f) => f.type === "number").map((f) => f.name);
|
|
5796
|
+
const stringFields = fields.filter((f) => f.type === "string").map((f) => f.name);
|
|
5797
|
+
fieldNamesList = `
|
|
5798
|
+
\u{1F4CA} NUMERIC FIELDS (use for yAxisKey, valueKey, aggregationField): ${numericFields.join(", ") || "none"}
|
|
5799
|
+
\u{1F4DD} STRING FIELDS (use for xAxisKey, groupBy, nameKey): ${stringFields.join(", ") || "none"}`;
|
|
5800
|
+
const fieldsText = fields.map(
|
|
5801
|
+
(f) => ` "${f.name}" (${f.type}): ${f.description}`
|
|
5802
|
+
).join("\n");
|
|
5678
5803
|
outputSchemaText = `${tool.outputSchema.description}
|
|
5679
|
-
Fields
|
|
5680
|
-
${
|
|
5804
|
+
Fields:
|
|
5805
|
+
${fieldsText}`;
|
|
5681
5806
|
}
|
|
5682
5807
|
return `${idx + 1}. **${tool.name}**
|
|
5683
|
-
toolId: "${tool.id}"
|
|
5684
|
-
toolName: "${tool.name}"
|
|
5685
|
-
parameters: ${JSON.stringify(tool.params || {})}
|
|
5808
|
+
toolId: "${tool.id}"
|
|
5809
|
+
toolName: "${tool.name}"
|
|
5810
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
5686
5811
|
recordCount: ${recordCount} rows returned
|
|
5687
|
-
outputSchema: ${outputSchemaText}
|
|
5688
|
-
\u26A0\uFE0F DO NOT embed this tool's data in SQL - use externalTool prop OR query database tables`;
|
|
5812
|
+
outputSchema: ${outputSchemaText}${fieldNamesList}`;
|
|
5689
5813
|
}).join("\n\n");
|
|
5690
5814
|
}
|
|
5691
5815
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
5692
5816
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
5693
|
-
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
5694
|
-
logger.file("\n=============================\nDeferred tools:", deferredToolsText);
|
|
5695
|
-
logger.file("\n=============================\nExecuted tools:", executedToolsText);
|
|
5696
5817
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
5697
5818
|
ANALYSIS_CONTENT: analysisContent,
|
|
5698
5819
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -5702,7 +5823,13 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
5702
5823
|
EXECUTED_TOOLS: executedToolsText
|
|
5703
5824
|
});
|
|
5704
5825
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
5705
|
-
|
|
5826
|
+
const systemPromptStr = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
5827
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "system", systemPromptStr);
|
|
5828
|
+
logger.logLLMPrompt("matchComponentsFromAnalysis", "user", `Text Analysis:
|
|
5829
|
+
${analysisContent}
|
|
5830
|
+
|
|
5831
|
+
Executed Tools:
|
|
5832
|
+
${executedToolsText}`);
|
|
5706
5833
|
logCollector?.info("Matching components from text response...");
|
|
5707
5834
|
let fullResponseText = "";
|
|
5708
5835
|
let answerComponentExtracted = false;
|
|
@@ -5834,6 +5961,85 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
5834
5961
|
if (!isValidTool) {
|
|
5835
5962
|
logger.warn(`[${this.getProviderName()}] externalTool.toolId "${toolId}" not found in executed tools [${validToolIds.join(", ")}], setting to null`);
|
|
5836
5963
|
cleanedProps.externalTool = null;
|
|
5964
|
+
} else {
|
|
5965
|
+
const executedTool = executedTools?.find((t) => t.id === toolId);
|
|
5966
|
+
if (executedTool?.outputSchema?.fields && cleanedProps.config) {
|
|
5967
|
+
const validFieldNames = executedTool.outputSchema.fields.map((f) => f.name);
|
|
5968
|
+
const validFieldNamesLower = validFieldNames.map((n) => n.toLowerCase());
|
|
5969
|
+
const findMatchingField = (fieldName, configKey) => {
|
|
5970
|
+
if (!fieldName) return null;
|
|
5971
|
+
const lowerField = fieldName.toLowerCase();
|
|
5972
|
+
const exactIdx = validFieldNamesLower.indexOf(lowerField);
|
|
5973
|
+
if (exactIdx !== -1) return validFieldNames[exactIdx];
|
|
5974
|
+
const containsMatches = validFieldNames.filter(
|
|
5975
|
+
(_, i) => validFieldNamesLower[i].includes(lowerField) || lowerField.includes(validFieldNamesLower[i])
|
|
5976
|
+
);
|
|
5977
|
+
if (containsMatches.length === 1) return containsMatches[0];
|
|
5978
|
+
const fieldTypes = executedTool.outputSchema.fields.reduce((acc, f) => {
|
|
5979
|
+
acc[f.name] = f.type;
|
|
5980
|
+
return acc;
|
|
5981
|
+
}, {});
|
|
5982
|
+
const numericConfigKeys = ["yAxisKey", "valueKey", "aggregationField", "sizeKey"];
|
|
5983
|
+
const stringConfigKeys = ["xAxisKey", "nameKey", "labelKey", "groupBy"];
|
|
5984
|
+
if (numericConfigKeys.includes(configKey)) {
|
|
5985
|
+
const numericFields = validFieldNames.filter((f) => fieldTypes[f] === "number");
|
|
5986
|
+
const match = numericFields.find((f) => f.toLowerCase().includes(lowerField) || lowerField.includes(f.toLowerCase()));
|
|
5987
|
+
if (match) return match;
|
|
5988
|
+
if (numericFields.length > 0) {
|
|
5989
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first numeric field: ${numericFields[0]}`);
|
|
5990
|
+
return numericFields[0];
|
|
5991
|
+
}
|
|
5992
|
+
}
|
|
5993
|
+
if (stringConfigKeys.includes(configKey)) {
|
|
5994
|
+
const stringFields = validFieldNames.filter((f) => fieldTypes[f] === "string");
|
|
5995
|
+
const match = stringFields.find((f) => f.toLowerCase().includes(lowerField) || lowerField.includes(f.toLowerCase()));
|
|
5996
|
+
if (match) return match;
|
|
5997
|
+
if (stringFields.length > 0) {
|
|
5998
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first string field: ${stringFields[0]}`);
|
|
5999
|
+
return stringFields[0];
|
|
6000
|
+
}
|
|
6001
|
+
}
|
|
6002
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first field: ${validFieldNames[0]}`);
|
|
6003
|
+
return validFieldNames[0];
|
|
6004
|
+
};
|
|
6005
|
+
const configFieldsToValidate = [
|
|
6006
|
+
"xAxisKey",
|
|
6007
|
+
"yAxisKey",
|
|
6008
|
+
"valueKey",
|
|
6009
|
+
"nameKey",
|
|
6010
|
+
"labelKey",
|
|
6011
|
+
"groupBy",
|
|
6012
|
+
"aggregationField",
|
|
6013
|
+
"seriesKey",
|
|
6014
|
+
"sizeKey",
|
|
6015
|
+
"xAggregationField",
|
|
6016
|
+
"yAggregationField"
|
|
6017
|
+
];
|
|
6018
|
+
for (const configKey of configFieldsToValidate) {
|
|
6019
|
+
const fieldValue = cleanedProps.config[configKey];
|
|
6020
|
+
if (fieldValue && typeof fieldValue === "string") {
|
|
6021
|
+
if (!validFieldNames.includes(fieldValue)) {
|
|
6022
|
+
const correctedField = findMatchingField(fieldValue, configKey);
|
|
6023
|
+
if (correctedField) {
|
|
6024
|
+
logger.warn(`[${this.getProviderName()}] Correcting config.${configKey}: "${fieldValue}" \u2192 "${correctedField}"`);
|
|
6025
|
+
cleanedProps.config[configKey] = correctedField;
|
|
6026
|
+
}
|
|
6027
|
+
}
|
|
6028
|
+
}
|
|
6029
|
+
}
|
|
6030
|
+
if (Array.isArray(cleanedProps.config.series)) {
|
|
6031
|
+
cleanedProps.config.series = cleanedProps.config.series.map((s) => {
|
|
6032
|
+
if (s.dataKey && typeof s.dataKey === "string" && !validFieldNames.includes(s.dataKey)) {
|
|
6033
|
+
const correctedField = findMatchingField(s.dataKey, "yAxisKey");
|
|
6034
|
+
if (correctedField) {
|
|
6035
|
+
logger.warn(`[${this.getProviderName()}] Correcting series.dataKey: "${s.dataKey}" \u2192 "${correctedField}"`);
|
|
6036
|
+
return { ...s, dataKey: correctedField };
|
|
6037
|
+
}
|
|
6038
|
+
}
|
|
6039
|
+
return s;
|
|
6040
|
+
});
|
|
6041
|
+
}
|
|
6042
|
+
}
|
|
5837
6043
|
}
|
|
5838
6044
|
}
|
|
5839
6045
|
if (cleanedProps.query) {
|
|
@@ -5891,6 +6097,10 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
5891
6097
|
AVAILABLE_TOOLS: availableToolsDoc,
|
|
5892
6098
|
SCHEMA_DOC: schemaDoc || "No database schema available"
|
|
5893
6099
|
});
|
|
6100
|
+
const systemPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
6101
|
+
const userPromptText = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
|
|
6102
|
+
logger.logLLMPrompt("classifyQuestionCategory", "system", systemPrompt);
|
|
6103
|
+
logger.logLLMPrompt("classifyQuestionCategory", "user", userPromptText);
|
|
5894
6104
|
const result = await LLM.stream(
|
|
5895
6105
|
{
|
|
5896
6106
|
sys: prompts.system,
|
|
@@ -6078,7 +6288,6 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
6078
6288
|
collections,
|
|
6079
6289
|
topK: 1
|
|
6080
6290
|
});
|
|
6081
|
-
logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
|
|
6082
6291
|
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
6083
6292
|
USER_PROMPT: userPrompt,
|
|
6084
6293
|
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
@@ -6087,8 +6296,10 @@ ${fields.map((f) => ` - ${f.name} (${f.type}): ${f.description}`).join("\n")
|
|
|
6087
6296
|
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
|
|
6088
6297
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc
|
|
6089
6298
|
});
|
|
6090
|
-
|
|
6091
|
-
|
|
6299
|
+
const sysPrompt = Array.isArray(prompts.system) ? prompts.system.join("\n") : prompts.system;
|
|
6300
|
+
const usrPrompt = Array.isArray(prompts.user) ? prompts.user.join("\n") : prompts.user;
|
|
6301
|
+
logger.logLLMPrompt("generateTextResponse", "system", sysPrompt);
|
|
6302
|
+
logger.logLLMPrompt("generateTextResponse", "user", usrPrompt);
|
|
6092
6303
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6093
6304
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6094
6305
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6474,7 +6685,6 @@ ${errorMsg}
|
|
|
6474
6685
|
data: {
|
|
6475
6686
|
text: textResponse,
|
|
6476
6687
|
// Include the streamed text showing all attempts
|
|
6477
|
-
matchedComponents: [],
|
|
6478
6688
|
actions: [],
|
|
6479
6689
|
method: `${this.getProviderName()}-text-response-max-attempts`
|
|
6480
6690
|
}
|
|
@@ -6572,7 +6782,6 @@ ${errorMsg}
|
|
|
6572
6782
|
success: true,
|
|
6573
6783
|
data: {
|
|
6574
6784
|
text: textResponse,
|
|
6575
|
-
matchedComponents,
|
|
6576
6785
|
component: container_componet,
|
|
6577
6786
|
actions,
|
|
6578
6787
|
method: `${this.getProviderName()}-text-response`
|
|
@@ -6596,7 +6805,6 @@ ${errorMsg}
|
|
|
6596
6805
|
errors,
|
|
6597
6806
|
data: {
|
|
6598
6807
|
text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
|
|
6599
|
-
matchedComponents: [],
|
|
6600
6808
|
actions: [],
|
|
6601
6809
|
method: `${this.getProviderName()}-text-response-error`
|
|
6602
6810
|
}
|
|
@@ -6620,6 +6828,8 @@ ${errorMsg}
|
|
|
6620
6828
|
const startTime = Date.now();
|
|
6621
6829
|
logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
|
|
6622
6830
|
logCollector?.info(`Starting request processing with mode: ${responseMode}`);
|
|
6831
|
+
logger.clearFile();
|
|
6832
|
+
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
6623
6833
|
try {
|
|
6624
6834
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
6625
6835
|
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
@@ -6627,8 +6837,8 @@ ${errorMsg}
|
|
|
6627
6837
|
userPrompt,
|
|
6628
6838
|
collections,
|
|
6629
6839
|
userId,
|
|
6630
|
-
similarityThreshold: 0.
|
|
6631
|
-
//
|
|
6840
|
+
similarityThreshold: 0.8
|
|
6841
|
+
// 80% threshold
|
|
6632
6842
|
});
|
|
6633
6843
|
if (conversationMatch) {
|
|
6634
6844
|
logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
|
|
@@ -6653,7 +6863,6 @@ ${errorMsg}
|
|
|
6653
6863
|
data: {
|
|
6654
6864
|
text: cachedTextResponse,
|
|
6655
6865
|
component: null,
|
|
6656
|
-
matchedComponents: [],
|
|
6657
6866
|
actions: conversationMatch.uiBlock?.actions || [],
|
|
6658
6867
|
reasoning: `Exact match from previous general conversation`,
|
|
6659
6868
|
method: `${this.getProviderName()}-semantic-match-general`,
|
|
@@ -6681,7 +6890,6 @@ ${errorMsg}
|
|
|
6681
6890
|
data: {
|
|
6682
6891
|
text: cachedTextResponse,
|
|
6683
6892
|
component,
|
|
6684
|
-
matchedComponents: component?.props?.config?.components || [],
|
|
6685
6893
|
actions: cachedActions,
|
|
6686
6894
|
reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
|
|
6687
6895
|
method: `${this.getProviderName()}-semantic-match-exact`,
|
|
@@ -6717,7 +6925,6 @@ ${errorMsg}
|
|
|
6717
6925
|
data: {
|
|
6718
6926
|
text: textResponseToUse,
|
|
6719
6927
|
component: adaptResult.adaptedComponent,
|
|
6720
|
-
matchedComponents: adaptResult.adaptedComponent?.props?.config?.components || [],
|
|
6721
6928
|
actions: cachedActions,
|
|
6722
6929
|
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
6723
6930
|
method: `${this.getProviderName()}-semantic-match`,
|
|
@@ -10324,6 +10531,331 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10324
10531
|
sendMessage(response);
|
|
10325
10532
|
}
|
|
10326
10533
|
|
|
10534
|
+
// src/handlers/menus.ts
|
|
10535
|
+
init_logger();
|
|
10536
|
+
async function handleMenusRequest(data, collections, sendMessage) {
|
|
10537
|
+
const executeCollection = async (collection, op, params) => {
|
|
10538
|
+
const handler = collections[collection]?.[op];
|
|
10539
|
+
if (!handler) {
|
|
10540
|
+
throw new Error(`Collection operation ${collection}.${op} not found`);
|
|
10541
|
+
}
|
|
10542
|
+
return await handler(params);
|
|
10543
|
+
};
|
|
10544
|
+
try {
|
|
10545
|
+
const request = MenusRequestMessageSchema.parse(data);
|
|
10546
|
+
const { id, payload, from } = request;
|
|
10547
|
+
const { operation, data: requestData } = payload;
|
|
10548
|
+
const menuId = requestData?.id;
|
|
10549
|
+
const name = requestData?.name;
|
|
10550
|
+
const componentName = requestData?.componentName;
|
|
10551
|
+
const icon = requestData?.icon;
|
|
10552
|
+
const userMessage = requestData?.userMessage;
|
|
10553
|
+
const parentId = requestData?.parentId;
|
|
10554
|
+
const sortOrder = requestData?.sortOrder;
|
|
10555
|
+
const props = requestData?.props;
|
|
10556
|
+
const isActive = requestData?.isActive;
|
|
10557
|
+
const filters = requestData?.filters;
|
|
10558
|
+
const limit = requestData?.limit;
|
|
10559
|
+
const sort = requestData?.sort;
|
|
10560
|
+
const items = requestData?.items;
|
|
10561
|
+
switch (operation) {
|
|
10562
|
+
case "create":
|
|
10563
|
+
await handleCreate7(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, from.id);
|
|
10564
|
+
break;
|
|
10565
|
+
case "update":
|
|
10566
|
+
await handleUpdate7(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, from.id);
|
|
10567
|
+
break;
|
|
10568
|
+
case "delete":
|
|
10569
|
+
await handleDelete7(id, menuId, executeCollection, sendMessage, from.id);
|
|
10570
|
+
break;
|
|
10571
|
+
case "getAll":
|
|
10572
|
+
await handleGetAll7(id, executeCollection, sendMessage, from.id);
|
|
10573
|
+
break;
|
|
10574
|
+
case "getOne":
|
|
10575
|
+
await handleGetOne7(id, menuId, executeCollection, sendMessage, from.id);
|
|
10576
|
+
break;
|
|
10577
|
+
case "getRootMenus":
|
|
10578
|
+
await handleGetRootMenus(id, executeCollection, sendMessage, from.id);
|
|
10579
|
+
break;
|
|
10580
|
+
case "getChildMenus":
|
|
10581
|
+
await handleGetChildMenus(id, parentId, executeCollection, sendMessage, from.id);
|
|
10582
|
+
break;
|
|
10583
|
+
case "getHierarchy":
|
|
10584
|
+
await handleGetHierarchy(id, executeCollection, sendMessage, from.id);
|
|
10585
|
+
break;
|
|
10586
|
+
case "query":
|
|
10587
|
+
await handleQuery6(id, filters, limit, sort, executeCollection, sendMessage, from.id);
|
|
10588
|
+
break;
|
|
10589
|
+
case "reorder":
|
|
10590
|
+
await handleReorder(id, items, executeCollection, sendMessage, from.id);
|
|
10591
|
+
break;
|
|
10592
|
+
default:
|
|
10593
|
+
sendResponse9(id, {
|
|
10594
|
+
success: false,
|
|
10595
|
+
error: `Unknown operation: ${operation}`
|
|
10596
|
+
}, sendMessage, from.id);
|
|
10597
|
+
}
|
|
10598
|
+
} catch (error) {
|
|
10599
|
+
logger.error("Failed to handle menus request:", error);
|
|
10600
|
+
sendResponse9(null, {
|
|
10601
|
+
success: false,
|
|
10602
|
+
error: error instanceof Error ? error.message : "Unknown error occurred"
|
|
10603
|
+
}, sendMessage);
|
|
10604
|
+
}
|
|
10605
|
+
}
|
|
10606
|
+
async function handleCreate7(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
|
|
10607
|
+
if (!name) {
|
|
10608
|
+
sendResponse9(id, {
|
|
10609
|
+
success: false,
|
|
10610
|
+
error: "name is required"
|
|
10611
|
+
}, sendMessage, clientId);
|
|
10612
|
+
return;
|
|
10613
|
+
}
|
|
10614
|
+
if (!componentName) {
|
|
10615
|
+
sendResponse9(id, {
|
|
10616
|
+
success: false,
|
|
10617
|
+
error: "componentName is required"
|
|
10618
|
+
}, sendMessage, clientId);
|
|
10619
|
+
return;
|
|
10620
|
+
}
|
|
10621
|
+
try {
|
|
10622
|
+
const result = await executeCollection("menus", "create", {
|
|
10623
|
+
name,
|
|
10624
|
+
componentName,
|
|
10625
|
+
icon,
|
|
10626
|
+
userMessage,
|
|
10627
|
+
parentId,
|
|
10628
|
+
sortOrder,
|
|
10629
|
+
props,
|
|
10630
|
+
isActive
|
|
10631
|
+
});
|
|
10632
|
+
sendResponse9(id, {
|
|
10633
|
+
success: true,
|
|
10634
|
+
data: result.data,
|
|
10635
|
+
message: "Menu created successfully"
|
|
10636
|
+
}, sendMessage, clientId);
|
|
10637
|
+
logger.info(`Menu created: ID ${result.data?.id}`);
|
|
10638
|
+
} catch (error) {
|
|
10639
|
+
sendResponse9(id, {
|
|
10640
|
+
success: false,
|
|
10641
|
+
error: error instanceof Error ? error.message : "Failed to create menu"
|
|
10642
|
+
}, sendMessage, clientId);
|
|
10643
|
+
}
|
|
10644
|
+
}
|
|
10645
|
+
async function handleUpdate7(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
|
|
10646
|
+
if (!menuId) {
|
|
10647
|
+
sendResponse9(id, {
|
|
10648
|
+
success: false,
|
|
10649
|
+
error: "Menu ID is required"
|
|
10650
|
+
}, sendMessage, clientId);
|
|
10651
|
+
return;
|
|
10652
|
+
}
|
|
10653
|
+
try {
|
|
10654
|
+
const result = await executeCollection("menus", "update", {
|
|
10655
|
+
id: menuId,
|
|
10656
|
+
name,
|
|
10657
|
+
componentName,
|
|
10658
|
+
icon,
|
|
10659
|
+
userMessage,
|
|
10660
|
+
parentId,
|
|
10661
|
+
sortOrder,
|
|
10662
|
+
props,
|
|
10663
|
+
isActive
|
|
10664
|
+
});
|
|
10665
|
+
sendResponse9(id, {
|
|
10666
|
+
success: true,
|
|
10667
|
+
data: result.data,
|
|
10668
|
+
message: "Menu updated successfully"
|
|
10669
|
+
}, sendMessage, clientId);
|
|
10670
|
+
logger.info(`Menu updated: ID ${menuId}`);
|
|
10671
|
+
} catch (error) {
|
|
10672
|
+
sendResponse9(id, {
|
|
10673
|
+
success: false,
|
|
10674
|
+
error: error instanceof Error ? error.message : "Failed to update menu"
|
|
10675
|
+
}, sendMessage, clientId);
|
|
10676
|
+
}
|
|
10677
|
+
}
|
|
10678
|
+
async function handleDelete7(id, menuId, executeCollection, sendMessage, clientId) {
|
|
10679
|
+
if (!menuId) {
|
|
10680
|
+
sendResponse9(id, {
|
|
10681
|
+
success: false,
|
|
10682
|
+
error: "Menu ID is required"
|
|
10683
|
+
}, sendMessage, clientId);
|
|
10684
|
+
return;
|
|
10685
|
+
}
|
|
10686
|
+
try {
|
|
10687
|
+
const result = await executeCollection("menus", "delete", { id: menuId });
|
|
10688
|
+
sendResponse9(id, {
|
|
10689
|
+
success: true,
|
|
10690
|
+
data: result.data,
|
|
10691
|
+
message: "Menu deleted successfully"
|
|
10692
|
+
}, sendMessage, clientId);
|
|
10693
|
+
logger.info(`Menu deleted: ID ${menuId}`);
|
|
10694
|
+
} catch (error) {
|
|
10695
|
+
sendResponse9(id, {
|
|
10696
|
+
success: false,
|
|
10697
|
+
error: error instanceof Error ? error.message : "Failed to delete menu"
|
|
10698
|
+
}, sendMessage, clientId);
|
|
10699
|
+
}
|
|
10700
|
+
}
|
|
10701
|
+
async function handleGetAll7(id, executeCollection, sendMessage, clientId) {
|
|
10702
|
+
try {
|
|
10703
|
+
const result = await executeCollection("menus", "getAll", {});
|
|
10704
|
+
sendResponse9(id, {
|
|
10705
|
+
success: true,
|
|
10706
|
+
data: result.data,
|
|
10707
|
+
count: result.count,
|
|
10708
|
+
message: `Retrieved ${result.count} menus`
|
|
10709
|
+
}, sendMessage, clientId);
|
|
10710
|
+
logger.info(`Retrieved all menus (count: ${result.count})`);
|
|
10711
|
+
} catch (error) {
|
|
10712
|
+
sendResponse9(id, {
|
|
10713
|
+
success: false,
|
|
10714
|
+
error: error instanceof Error ? error.message : "Failed to get menus"
|
|
10715
|
+
}, sendMessage, clientId);
|
|
10716
|
+
}
|
|
10717
|
+
}
|
|
10718
|
+
async function handleGetOne7(id, menuId, executeCollection, sendMessage, clientId) {
|
|
10719
|
+
if (!menuId) {
|
|
10720
|
+
sendResponse9(id, {
|
|
10721
|
+
success: false,
|
|
10722
|
+
error: "Menu ID is required"
|
|
10723
|
+
}, sendMessage, clientId);
|
|
10724
|
+
return;
|
|
10725
|
+
}
|
|
10726
|
+
try {
|
|
10727
|
+
const result = await executeCollection("menus", "getOne", { id: menuId });
|
|
10728
|
+
sendResponse9(id, {
|
|
10729
|
+
success: true,
|
|
10730
|
+
data: result.data,
|
|
10731
|
+
message: `Retrieved menu ID ${menuId}`
|
|
10732
|
+
}, sendMessage, clientId);
|
|
10733
|
+
logger.info(`Retrieved menu: ID ${menuId}`);
|
|
10734
|
+
} catch (error) {
|
|
10735
|
+
sendResponse9(id, {
|
|
10736
|
+
success: false,
|
|
10737
|
+
error: error instanceof Error ? error.message : "Failed to get menu"
|
|
10738
|
+
}, sendMessage, clientId);
|
|
10739
|
+
}
|
|
10740
|
+
}
|
|
10741
|
+
async function handleGetRootMenus(id, executeCollection, sendMessage, clientId) {
|
|
10742
|
+
try {
|
|
10743
|
+
const result = await executeCollection("menus", "getRootMenus", {});
|
|
10744
|
+
sendResponse9(id, {
|
|
10745
|
+
success: true,
|
|
10746
|
+
data: result.data,
|
|
10747
|
+
count: result.count,
|
|
10748
|
+
message: `Retrieved ${result.count} root menus`
|
|
10749
|
+
}, sendMessage, clientId);
|
|
10750
|
+
logger.info(`Retrieved root menus (count: ${result.count})`);
|
|
10751
|
+
} catch (error) {
|
|
10752
|
+
sendResponse9(id, {
|
|
10753
|
+
success: false,
|
|
10754
|
+
error: error instanceof Error ? error.message : "Failed to get root menus"
|
|
10755
|
+
}, sendMessage, clientId);
|
|
10756
|
+
}
|
|
10757
|
+
}
|
|
10758
|
+
async function handleGetChildMenus(id, parentId, executeCollection, sendMessage, clientId) {
|
|
10759
|
+
if (parentId === void 0 || parentId === null) {
|
|
10760
|
+
sendResponse9(id, {
|
|
10761
|
+
success: false,
|
|
10762
|
+
error: "parentId is required"
|
|
10763
|
+
}, sendMessage, clientId);
|
|
10764
|
+
return;
|
|
10765
|
+
}
|
|
10766
|
+
try {
|
|
10767
|
+
const result = await executeCollection("menus", "getChildMenus", { parentId });
|
|
10768
|
+
sendResponse9(id, {
|
|
10769
|
+
success: true,
|
|
10770
|
+
data: result.data,
|
|
10771
|
+
count: result.count,
|
|
10772
|
+
message: `Retrieved ${result.count} child menus for parent ${parentId}`
|
|
10773
|
+
}, sendMessage, clientId);
|
|
10774
|
+
logger.info(`Retrieved child menus for parent ${parentId} (count: ${result.count})`);
|
|
10775
|
+
} catch (error) {
|
|
10776
|
+
sendResponse9(id, {
|
|
10777
|
+
success: false,
|
|
10778
|
+
error: error instanceof Error ? error.message : "Failed to get child menus"
|
|
10779
|
+
}, sendMessage, clientId);
|
|
10780
|
+
}
|
|
10781
|
+
}
|
|
10782
|
+
async function handleGetHierarchy(id, executeCollection, sendMessage, clientId) {
|
|
10783
|
+
try {
|
|
10784
|
+
const result = await executeCollection("menus", "getHierarchy", {});
|
|
10785
|
+
sendResponse9(id, {
|
|
10786
|
+
success: true,
|
|
10787
|
+
data: result.data,
|
|
10788
|
+
count: result.count,
|
|
10789
|
+
message: `Retrieved menus hierarchy with ${result.count} root items`
|
|
10790
|
+
}, sendMessage, clientId);
|
|
10791
|
+
logger.info(`Retrieved menus hierarchy (root count: ${result.count})`);
|
|
10792
|
+
} catch (error) {
|
|
10793
|
+
sendResponse9(id, {
|
|
10794
|
+
success: false,
|
|
10795
|
+
error: error instanceof Error ? error.message : "Failed to get menus hierarchy"
|
|
10796
|
+
}, sendMessage, clientId);
|
|
10797
|
+
}
|
|
10798
|
+
}
|
|
10799
|
+
async function handleQuery6(id, filters, limit, sort, executeCollection, sendMessage, clientId) {
|
|
10800
|
+
try {
|
|
10801
|
+
const result = await executeCollection("menus", "query", {
|
|
10802
|
+
filters: filters || {},
|
|
10803
|
+
limit,
|
|
10804
|
+
sort
|
|
10805
|
+
});
|
|
10806
|
+
sendResponse9(id, {
|
|
10807
|
+
success: true,
|
|
10808
|
+
data: result.data,
|
|
10809
|
+
count: result.count,
|
|
10810
|
+
message: `Query returned ${result.count} menus`
|
|
10811
|
+
}, sendMessage, clientId);
|
|
10812
|
+
logger.info(`Query returned ${result.count} menus`);
|
|
10813
|
+
} catch (error) {
|
|
10814
|
+
sendResponse9(id, {
|
|
10815
|
+
success: false,
|
|
10816
|
+
error: error instanceof Error ? error.message : "Failed to query menus"
|
|
10817
|
+
}, sendMessage, clientId);
|
|
10818
|
+
}
|
|
10819
|
+
}
|
|
10820
|
+
async function handleReorder(id, items, executeCollection, sendMessage, clientId) {
|
|
10821
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
10822
|
+
sendResponse9(id, {
|
|
10823
|
+
success: false,
|
|
10824
|
+
error: "items array is required"
|
|
10825
|
+
}, sendMessage, clientId);
|
|
10826
|
+
return;
|
|
10827
|
+
}
|
|
10828
|
+
try {
|
|
10829
|
+
const result = await executeCollection("menus", "reorder", { items });
|
|
10830
|
+
sendResponse9(id, {
|
|
10831
|
+
success: true,
|
|
10832
|
+
data: result.data,
|
|
10833
|
+
message: `Reordered ${items.length} menus successfully`
|
|
10834
|
+
}, sendMessage, clientId);
|
|
10835
|
+
logger.info(`Reordered ${items.length} menus`);
|
|
10836
|
+
} catch (error) {
|
|
10837
|
+
sendResponse9(id, {
|
|
10838
|
+
success: false,
|
|
10839
|
+
error: error instanceof Error ? error.message : "Failed to reorder menus"
|
|
10840
|
+
}, sendMessage, clientId);
|
|
10841
|
+
}
|
|
10842
|
+
}
|
|
10843
|
+
function sendResponse9(id, res, sendMessage, clientId) {
|
|
10844
|
+
const response = {
|
|
10845
|
+
id: id || "unknown",
|
|
10846
|
+
type: "MENUS_RES",
|
|
10847
|
+
from: { type: "data-agent" },
|
|
10848
|
+
to: {
|
|
10849
|
+
type: "admin",
|
|
10850
|
+
id: clientId
|
|
10851
|
+
},
|
|
10852
|
+
payload: {
|
|
10853
|
+
...res
|
|
10854
|
+
}
|
|
10855
|
+
};
|
|
10856
|
+
sendMessage(response);
|
|
10857
|
+
}
|
|
10858
|
+
|
|
10327
10859
|
// src/dashComp/index.ts
|
|
10328
10860
|
init_logger();
|
|
10329
10861
|
|
|
@@ -10450,37 +10982,74 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10450
10982
|
return { success: false, errors };
|
|
10451
10983
|
}
|
|
10452
10984
|
logger.info(`[DASH_COMP_REQ] Using model: ${model}`);
|
|
10453
|
-
const
|
|
10985
|
+
const executedTools = [];
|
|
10986
|
+
const llmTools = (tools || []).map((tool) => ({
|
|
10987
|
+
name: tool.id,
|
|
10988
|
+
description: tool.description,
|
|
10989
|
+
input_schema: {
|
|
10990
|
+
type: "object",
|
|
10991
|
+
properties: Object.fromEntries(
|
|
10992
|
+
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` }])
|
|
10993
|
+
),
|
|
10994
|
+
additionalProperties: false
|
|
10995
|
+
}
|
|
10996
|
+
}));
|
|
10997
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
10998
|
+
const tool = tools?.find((t) => t.id === toolName);
|
|
10999
|
+
if (!tool) {
|
|
11000
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
11001
|
+
}
|
|
11002
|
+
logger.info(`[DASH_COMP_REQ] Executing external tool: ${tool.name} (${tool.id})`);
|
|
11003
|
+
const result2 = await tool.fn(toolInput);
|
|
11004
|
+
executedTools.push({
|
|
11005
|
+
id: tool.id,
|
|
11006
|
+
name: tool.name,
|
|
11007
|
+
params: toolInput,
|
|
11008
|
+
result: result2,
|
|
11009
|
+
outputSchema: tool.outputSchema
|
|
11010
|
+
});
|
|
11011
|
+
logger.info(`[DASH_COMP_REQ] Tool ${tool.name} executed successfully`);
|
|
11012
|
+
return JSON.stringify(result2, null, 2);
|
|
11013
|
+
};
|
|
11014
|
+
const result = await LLM.streamWithTools(
|
|
10454
11015
|
{
|
|
10455
11016
|
sys: prompts.system,
|
|
10456
11017
|
user: prompts.user
|
|
10457
11018
|
},
|
|
11019
|
+
llmTools,
|
|
11020
|
+
toolHandler,
|
|
10458
11021
|
{
|
|
10459
11022
|
model,
|
|
10460
11023
|
maxTokens: 8192,
|
|
10461
11024
|
temperature: 0.2,
|
|
10462
11025
|
apiKey
|
|
10463
11026
|
},
|
|
10464
|
-
|
|
10465
|
-
//
|
|
11027
|
+
5
|
|
11028
|
+
// max iterations
|
|
10466
11029
|
);
|
|
11030
|
+
const jsonMatch = result.match(/\{[\s\S]*\}/);
|
|
11031
|
+
const parsedResult = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
11032
|
+
if (!parsedResult) {
|
|
11033
|
+
errors.push("Failed to parse LLM response as JSON");
|
|
11034
|
+
return { success: false, errors };
|
|
11035
|
+
}
|
|
10467
11036
|
logger.debug("[DASH_COMP_REQ] LLM response received");
|
|
10468
|
-
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(
|
|
10469
|
-
if (!
|
|
11037
|
+
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
|
|
11038
|
+
if (!parsedResult.componentId || !parsedResult.props) {
|
|
10470
11039
|
errors.push("Invalid LLM response: missing componentId or props");
|
|
10471
11040
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
|
|
10472
11041
|
prompt,
|
|
10473
|
-
result,
|
|
10474
|
-
missingFields: { componentId: !
|
|
11042
|
+
result: parsedResult,
|
|
11043
|
+
missingFields: { componentId: !parsedResult.componentId, props: !parsedResult.props }
|
|
10475
11044
|
});
|
|
10476
11045
|
return { success: false, errors };
|
|
10477
11046
|
}
|
|
10478
|
-
const originalComponent = components.find((c) => c.name ===
|
|
11047
|
+
const originalComponent = components.find((c) => c.name === parsedResult.componentName);
|
|
10479
11048
|
if (!originalComponent) {
|
|
10480
|
-
errors.push(`Component ${
|
|
11049
|
+
errors.push(`Component ${parsedResult.componentName} not found in available components`);
|
|
10481
11050
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
10482
11051
|
prompt,
|
|
10483
|
-
componentName:
|
|
11052
|
+
componentName: parsedResult.componentName,
|
|
10484
11053
|
availableComponentNames: components.map((c) => c.name)
|
|
10485
11054
|
});
|
|
10486
11055
|
return { success: false, errors };
|
|
@@ -10489,23 +11058,27 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10489
11058
|
...originalComponent,
|
|
10490
11059
|
props: {
|
|
10491
11060
|
...originalComponent.props,
|
|
10492
|
-
...
|
|
11061
|
+
...parsedResult.props
|
|
10493
11062
|
}
|
|
10494
11063
|
};
|
|
10495
11064
|
logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
|
|
10496
|
-
if (
|
|
11065
|
+
if (parsedResult.props.query) {
|
|
10497
11066
|
logger.info(`[DASH_COMP_REQ] Data source: Database query`);
|
|
10498
11067
|
}
|
|
10499
|
-
if (
|
|
10500
|
-
logger.info(`[DASH_COMP_REQ] Data source: External tool - ${
|
|
11068
|
+
if (parsedResult.props.externalTool) {
|
|
11069
|
+
logger.info(`[DASH_COMP_REQ] Data source: External tool - ${parsedResult.props.externalTool.toolName}`);
|
|
11070
|
+
}
|
|
11071
|
+
if (executedTools.length > 0) {
|
|
11072
|
+
logger.info(`[DASH_COMP_REQ] Executed ${executedTools.length} external tool(s): ${executedTools.map((t) => t.name).join(", ")}`);
|
|
10501
11073
|
}
|
|
10502
11074
|
return {
|
|
10503
11075
|
success: true,
|
|
10504
11076
|
data: {
|
|
10505
11077
|
component: finalComponent,
|
|
10506
|
-
reasoning:
|
|
10507
|
-
dataSource:
|
|
10508
|
-
isUpdate:
|
|
11078
|
+
reasoning: parsedResult.reasoning || "Component selected based on user prompt",
|
|
11079
|
+
dataSource: parsedResult.props.query ? "database" : parsedResult.props.externalTool ? "external_tool" : "none",
|
|
11080
|
+
isUpdate: parsedResult.isUpdate || false,
|
|
11081
|
+
executedTools: executedTools.length > 0 ? executedTools : void 0
|
|
10509
11082
|
},
|
|
10510
11083
|
errors: []
|
|
10511
11084
|
};
|
|
@@ -10558,11 +11131,49 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10558
11131
|
return { success: false, errors };
|
|
10559
11132
|
}
|
|
10560
11133
|
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10561
|
-
const
|
|
11134
|
+
const executedTools = [];
|
|
11135
|
+
const llmTools = (tools || []).map((tool) => ({
|
|
11136
|
+
name: tool.id,
|
|
11137
|
+
description: tool.description,
|
|
11138
|
+
input_schema: {
|
|
11139
|
+
type: "object",
|
|
11140
|
+
properties: Object.fromEntries(
|
|
11141
|
+
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` }])
|
|
11142
|
+
),
|
|
11143
|
+
additionalProperties: false
|
|
11144
|
+
}
|
|
11145
|
+
}));
|
|
11146
|
+
const toolHandler = async (toolName, toolInput) => {
|
|
11147
|
+
const tool = tools?.find((t) => t.id === toolName);
|
|
11148
|
+
if (!tool) {
|
|
11149
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
11150
|
+
}
|
|
11151
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Executing external tool: ${tool.name} (${tool.id})`);
|
|
11152
|
+
const result2 = await tool.fn(toolInput);
|
|
11153
|
+
executedTools.push({
|
|
11154
|
+
id: tool.id,
|
|
11155
|
+
name: tool.name,
|
|
11156
|
+
params: toolInput,
|
|
11157
|
+
result: result2,
|
|
11158
|
+
outputSchema: tool.outputSchema
|
|
11159
|
+
});
|
|
11160
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Tool ${tool.name} executed successfully`);
|
|
11161
|
+
return JSON.stringify(result2, null, 2);
|
|
11162
|
+
};
|
|
11163
|
+
const rawResult = await LLM.streamWithTools(
|
|
10562
11164
|
{ sys: prompts.system, user: prompts.user },
|
|
11165
|
+
llmTools,
|
|
11166
|
+
toolHandler,
|
|
10563
11167
|
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10564
|
-
|
|
11168
|
+
5
|
|
11169
|
+
// max iterations
|
|
10565
11170
|
);
|
|
11171
|
+
const jsonMatch = rawResult.match(/\{[\s\S]*\}/);
|
|
11172
|
+
const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
11173
|
+
if (!result) {
|
|
11174
|
+
errors.push("Failed to parse LLM response as JSON");
|
|
11175
|
+
return { success: false, errors };
|
|
11176
|
+
}
|
|
10566
11177
|
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10567
11178
|
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10568
11179
|
if (!result.filterComponent) {
|
|
@@ -10576,13 +11187,17 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10576
11187
|
}
|
|
10577
11188
|
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10578
11189
|
logger.info(`[DASH_COMP_REQ:FILTER] Updated ${result.updatedComponents?.length || 0} components`);
|
|
11190
|
+
if (executedTools.length > 0) {
|
|
11191
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Executed ${executedTools.length} external tool(s): ${executedTools.map((t) => t.name).join(", ")}`);
|
|
11192
|
+
}
|
|
10579
11193
|
return {
|
|
10580
11194
|
success: true,
|
|
10581
11195
|
data: {
|
|
10582
11196
|
filterComponent: result.filterComponent,
|
|
10583
11197
|
updatedComponents: result.updatedComponents || [],
|
|
10584
11198
|
filterBindings: result.filterBindings || {},
|
|
10585
|
-
reasoning: result.reasoning || "Filter created based on user prompt"
|
|
11199
|
+
reasoning: result.reasoning || "Filter created based on user prompt",
|
|
11200
|
+
executedTools: executedTools.length > 0 ? executedTools : void 0
|
|
10586
11201
|
},
|
|
10587
11202
|
errors: []
|
|
10588
11203
|
};
|
|
@@ -11760,6 +12375,11 @@ var SuperatomSDK = class {
|
|
|
11760
12375
|
logger.error("Failed to handle KB nodes request:", error);
|
|
11761
12376
|
});
|
|
11762
12377
|
break;
|
|
12378
|
+
case "MENUS":
|
|
12379
|
+
handleMenusRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
|
|
12380
|
+
logger.error("Failed to handle menus request:", error);
|
|
12381
|
+
});
|
|
12382
|
+
break;
|
|
11763
12383
|
case "DASH_COMP_REQ":
|
|
11764
12384
|
handleDashCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
|
|
11765
12385
|
logger.error("Failed to handle dash comp request:", error);
|