@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.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,35 +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"}`;
|
|
5678
5800
|
const fieldsText = fields.map(
|
|
5679
|
-
(f) => `
|
|
5680
|
-
type: ${f.type}
|
|
5681
|
-
description: ${f.description}`
|
|
5801
|
+
(f) => ` "${f.name}" (${f.type}): ${f.description}`
|
|
5682
5802
|
).join("\n");
|
|
5683
5803
|
outputSchemaText = `${tool.outputSchema.description}
|
|
5684
|
-
Fields
|
|
5804
|
+
Fields:
|
|
5685
5805
|
${fieldsText}`;
|
|
5686
5806
|
}
|
|
5687
5807
|
return `${idx + 1}. **${tool.name}**
|
|
5688
|
-
toolId: "${tool.id}"
|
|
5689
|
-
toolName: "${tool.name}"
|
|
5690
|
-
parameters: ${JSON.stringify(tool.params || {})}
|
|
5808
|
+
toolId: "${tool.id}"
|
|
5809
|
+
toolName: "${tool.name}"
|
|
5810
|
+
parameters: ${JSON.stringify(tool.params || {})}
|
|
5691
5811
|
recordCount: ${recordCount} rows returned
|
|
5692
|
-
outputSchema: ${outputSchemaText}
|
|
5693
|
-
\u26A0\uFE0F DO NOT embed this tool's data in SQL - use externalTool prop OR query database tables`;
|
|
5812
|
+
outputSchema: ${outputSchemaText}${fieldNamesList}`;
|
|
5694
5813
|
}).join("\n\n");
|
|
5695
5814
|
}
|
|
5696
5815
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
5697
5816
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
5698
|
-
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
5699
|
-
logger.file("\n=============================\nDeferred tools:", deferredToolsText);
|
|
5700
|
-
logger.file("\n=============================\nExecuted tools:", executedToolsText);
|
|
5701
5817
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
5702
5818
|
ANALYSIS_CONTENT: analysisContent,
|
|
5703
5819
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -5707,7 +5823,13 @@ ${fieldsText}`;
|
|
|
5707
5823
|
EXECUTED_TOOLS: executedToolsText
|
|
5708
5824
|
});
|
|
5709
5825
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
5710
|
-
|
|
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}`);
|
|
5711
5833
|
logCollector?.info("Matching components from text response...");
|
|
5712
5834
|
let fullResponseText = "";
|
|
5713
5835
|
let answerComponentExtracted = false;
|
|
@@ -5844,40 +5966,41 @@ ${fieldsText}`;
|
|
|
5844
5966
|
if (executedTool?.outputSchema?.fields && cleanedProps.config) {
|
|
5845
5967
|
const validFieldNames = executedTool.outputSchema.fields.map((f) => f.name);
|
|
5846
5968
|
const validFieldNamesLower = validFieldNames.map((n) => n.toLowerCase());
|
|
5847
|
-
const findMatchingField = (fieldName) => {
|
|
5969
|
+
const findMatchingField = (fieldName, configKey) => {
|
|
5848
5970
|
if (!fieldName) return null;
|
|
5849
5971
|
const lowerField = fieldName.toLowerCase();
|
|
5850
5972
|
const exactIdx = validFieldNamesLower.indexOf(lowerField);
|
|
5851
5973
|
if (exactIdx !== -1) return validFieldNames[exactIdx];
|
|
5852
|
-
const
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
if (
|
|
5867
|
-
|
|
5868
|
-
|
|
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];
|
|
5869
5991
|
}
|
|
5870
5992
|
}
|
|
5871
|
-
if (
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
logger.warn(`[${this.getProviderName()}]
|
|
5877
|
-
return
|
|
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];
|
|
5878
6000
|
}
|
|
5879
6001
|
}
|
|
5880
|
-
|
|
6002
|
+
logger.warn(`[${this.getProviderName()}] No match for "${fieldName}", using first field: ${validFieldNames[0]}`);
|
|
6003
|
+
return validFieldNames[0];
|
|
5881
6004
|
};
|
|
5882
6005
|
const configFieldsToValidate = [
|
|
5883
6006
|
"xAxisKey",
|
|
@@ -5896,12 +6019,10 @@ ${fieldsText}`;
|
|
|
5896
6019
|
const fieldValue = cleanedProps.config[configKey];
|
|
5897
6020
|
if (fieldValue && typeof fieldValue === "string") {
|
|
5898
6021
|
if (!validFieldNames.includes(fieldValue)) {
|
|
5899
|
-
const correctedField = findMatchingField(fieldValue);
|
|
6022
|
+
const correctedField = findMatchingField(fieldValue, configKey);
|
|
5900
6023
|
if (correctedField) {
|
|
5901
6024
|
logger.warn(`[${this.getProviderName()}] Correcting config.${configKey}: "${fieldValue}" \u2192 "${correctedField}"`);
|
|
5902
6025
|
cleanedProps.config[configKey] = correctedField;
|
|
5903
|
-
} else {
|
|
5904
|
-
logger.warn(`[${this.getProviderName()}] config.${configKey}="${fieldValue}" not found in outputSchema [${validFieldNames.join(", ")}]`);
|
|
5905
6026
|
}
|
|
5906
6027
|
}
|
|
5907
6028
|
}
|
|
@@ -5909,7 +6030,7 @@ ${fieldsText}`;
|
|
|
5909
6030
|
if (Array.isArray(cleanedProps.config.series)) {
|
|
5910
6031
|
cleanedProps.config.series = cleanedProps.config.series.map((s) => {
|
|
5911
6032
|
if (s.dataKey && typeof s.dataKey === "string" && !validFieldNames.includes(s.dataKey)) {
|
|
5912
|
-
const correctedField = findMatchingField(s.dataKey);
|
|
6033
|
+
const correctedField = findMatchingField(s.dataKey, "yAxisKey");
|
|
5913
6034
|
if (correctedField) {
|
|
5914
6035
|
logger.warn(`[${this.getProviderName()}] Correcting series.dataKey: "${s.dataKey}" \u2192 "${correctedField}"`);
|
|
5915
6036
|
return { ...s, dataKey: correctedField };
|
|
@@ -5976,6 +6097,10 @@ ${fieldsText}`;
|
|
|
5976
6097
|
AVAILABLE_TOOLS: availableToolsDoc,
|
|
5977
6098
|
SCHEMA_DOC: schemaDoc || "No database schema available"
|
|
5978
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);
|
|
5979
6104
|
const result = await LLM.stream(
|
|
5980
6105
|
{
|
|
5981
6106
|
sys: prompts.system,
|
|
@@ -6163,7 +6288,6 @@ ${fieldsText}`;
|
|
|
6163
6288
|
collections,
|
|
6164
6289
|
topK: 1
|
|
6165
6290
|
});
|
|
6166
|
-
logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
|
|
6167
6291
|
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
6168
6292
|
USER_PROMPT: userPrompt,
|
|
6169
6293
|
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
@@ -6172,8 +6296,10 @@ ${fieldsText}`;
|
|
|
6172
6296
|
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available.",
|
|
6173
6297
|
AVAILABLE_EXTERNAL_TOOLS: availableToolsDoc
|
|
6174
6298
|
});
|
|
6175
|
-
|
|
6176
|
-
|
|
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);
|
|
6177
6303
|
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts with schema`);
|
|
6178
6304
|
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
6179
6305
|
logCollector?.info("Generating text response with query execution capability...");
|
|
@@ -6559,7 +6685,6 @@ ${errorMsg}
|
|
|
6559
6685
|
data: {
|
|
6560
6686
|
text: textResponse,
|
|
6561
6687
|
// Include the streamed text showing all attempts
|
|
6562
|
-
matchedComponents: [],
|
|
6563
6688
|
actions: [],
|
|
6564
6689
|
method: `${this.getProviderName()}-text-response-max-attempts`
|
|
6565
6690
|
}
|
|
@@ -6657,7 +6782,6 @@ ${errorMsg}
|
|
|
6657
6782
|
success: true,
|
|
6658
6783
|
data: {
|
|
6659
6784
|
text: textResponse,
|
|
6660
|
-
matchedComponents,
|
|
6661
6785
|
component: container_componet,
|
|
6662
6786
|
actions,
|
|
6663
6787
|
method: `${this.getProviderName()}-text-response`
|
|
@@ -6681,7 +6805,6 @@ ${errorMsg}
|
|
|
6681
6805
|
errors,
|
|
6682
6806
|
data: {
|
|
6683
6807
|
text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
|
|
6684
|
-
matchedComponents: [],
|
|
6685
6808
|
actions: [],
|
|
6686
6809
|
method: `${this.getProviderName()}-text-response-error`
|
|
6687
6810
|
}
|
|
@@ -6705,6 +6828,8 @@ ${errorMsg}
|
|
|
6705
6828
|
const startTime = Date.now();
|
|
6706
6829
|
logger.info(`[${this.getProviderName()}] handleUserRequest called for user prompt: ${userPrompt}`);
|
|
6707
6830
|
logCollector?.info(`Starting request processing with mode: ${responseMode}`);
|
|
6831
|
+
logger.clearFile();
|
|
6832
|
+
logger.logLLMPrompt("handleUserRequest", "user", `User Prompt: ${userPrompt}`);
|
|
6708
6833
|
try {
|
|
6709
6834
|
logger.info(`[${this.getProviderName()}] Step 1: Searching previous conversations...`);
|
|
6710
6835
|
logCollector?.info("Step 1: Searching for similar previous conversations...");
|
|
@@ -6712,8 +6837,8 @@ ${errorMsg}
|
|
|
6712
6837
|
userPrompt,
|
|
6713
6838
|
collections,
|
|
6714
6839
|
userId,
|
|
6715
|
-
similarityThreshold: 0.
|
|
6716
|
-
//
|
|
6840
|
+
similarityThreshold: 0.8
|
|
6841
|
+
// 80% threshold
|
|
6717
6842
|
});
|
|
6718
6843
|
if (conversationMatch) {
|
|
6719
6844
|
logger.info(`[${this.getProviderName()}] \u2713 Found matching conversation with ${(conversationMatch.similarity * 100).toFixed(2)}% similarity`);
|
|
@@ -6738,7 +6863,6 @@ ${errorMsg}
|
|
|
6738
6863
|
data: {
|
|
6739
6864
|
text: cachedTextResponse,
|
|
6740
6865
|
component: null,
|
|
6741
|
-
matchedComponents: [],
|
|
6742
6866
|
actions: conversationMatch.uiBlock?.actions || [],
|
|
6743
6867
|
reasoning: `Exact match from previous general conversation`,
|
|
6744
6868
|
method: `${this.getProviderName()}-semantic-match-general`,
|
|
@@ -6766,7 +6890,6 @@ ${errorMsg}
|
|
|
6766
6890
|
data: {
|
|
6767
6891
|
text: cachedTextResponse,
|
|
6768
6892
|
component,
|
|
6769
|
-
matchedComponents: component?.props?.config?.components || [],
|
|
6770
6893
|
actions: cachedActions,
|
|
6771
6894
|
reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
|
|
6772
6895
|
method: `${this.getProviderName()}-semantic-match-exact`,
|
|
@@ -6802,7 +6925,6 @@ ${errorMsg}
|
|
|
6802
6925
|
data: {
|
|
6803
6926
|
text: textResponseToUse,
|
|
6804
6927
|
component: adaptResult.adaptedComponent,
|
|
6805
|
-
matchedComponents: adaptResult.adaptedComponent?.props?.config?.components || [],
|
|
6806
6928
|
actions: cachedActions,
|
|
6807
6929
|
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
6808
6930
|
method: `${this.getProviderName()}-semantic-match`,
|
|
@@ -10409,6 +10531,331 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10409
10531
|
sendMessage(response);
|
|
10410
10532
|
}
|
|
10411
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
|
+
|
|
10412
10859
|
// src/dashComp/index.ts
|
|
10413
10860
|
init_logger();
|
|
10414
10861
|
|
|
@@ -10535,37 +10982,74 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10535
10982
|
return { success: false, errors };
|
|
10536
10983
|
}
|
|
10537
10984
|
logger.info(`[DASH_COMP_REQ] Using model: ${model}`);
|
|
10538
|
-
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(
|
|
10539
11015
|
{
|
|
10540
11016
|
sys: prompts.system,
|
|
10541
11017
|
user: prompts.user
|
|
10542
11018
|
},
|
|
11019
|
+
llmTools,
|
|
11020
|
+
toolHandler,
|
|
10543
11021
|
{
|
|
10544
11022
|
model,
|
|
10545
11023
|
maxTokens: 8192,
|
|
10546
11024
|
temperature: 0.2,
|
|
10547
11025
|
apiKey
|
|
10548
11026
|
},
|
|
10549
|
-
|
|
10550
|
-
//
|
|
11027
|
+
5
|
|
11028
|
+
// max iterations
|
|
10551
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
|
+
}
|
|
10552
11036
|
logger.debug("[DASH_COMP_REQ] LLM response received");
|
|
10553
|
-
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(
|
|
10554
|
-
if (!
|
|
11037
|
+
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
|
|
11038
|
+
if (!parsedResult.componentId || !parsedResult.props) {
|
|
10555
11039
|
errors.push("Invalid LLM response: missing componentId or props");
|
|
10556
11040
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
|
|
10557
11041
|
prompt,
|
|
10558
|
-
result,
|
|
10559
|
-
missingFields: { componentId: !
|
|
11042
|
+
result: parsedResult,
|
|
11043
|
+
missingFields: { componentId: !parsedResult.componentId, props: !parsedResult.props }
|
|
10560
11044
|
});
|
|
10561
11045
|
return { success: false, errors };
|
|
10562
11046
|
}
|
|
10563
|
-
const originalComponent = components.find((c) => c.name ===
|
|
11047
|
+
const originalComponent = components.find((c) => c.name === parsedResult.componentName);
|
|
10564
11048
|
if (!originalComponent) {
|
|
10565
|
-
errors.push(`Component ${
|
|
11049
|
+
errors.push(`Component ${parsedResult.componentName} not found in available components`);
|
|
10566
11050
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
10567
11051
|
prompt,
|
|
10568
|
-
componentName:
|
|
11052
|
+
componentName: parsedResult.componentName,
|
|
10569
11053
|
availableComponentNames: components.map((c) => c.name)
|
|
10570
11054
|
});
|
|
10571
11055
|
return { success: false, errors };
|
|
@@ -10574,23 +11058,27 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10574
11058
|
...originalComponent,
|
|
10575
11059
|
props: {
|
|
10576
11060
|
...originalComponent.props,
|
|
10577
|
-
...
|
|
11061
|
+
...parsedResult.props
|
|
10578
11062
|
}
|
|
10579
11063
|
};
|
|
10580
11064
|
logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
|
|
10581
|
-
if (
|
|
11065
|
+
if (parsedResult.props.query) {
|
|
10582
11066
|
logger.info(`[DASH_COMP_REQ] Data source: Database query`);
|
|
10583
11067
|
}
|
|
10584
|
-
if (
|
|
10585
|
-
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(", ")}`);
|
|
10586
11073
|
}
|
|
10587
11074
|
return {
|
|
10588
11075
|
success: true,
|
|
10589
11076
|
data: {
|
|
10590
11077
|
component: finalComponent,
|
|
10591
|
-
reasoning:
|
|
10592
|
-
dataSource:
|
|
10593
|
-
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
|
|
10594
11082
|
},
|
|
10595
11083
|
errors: []
|
|
10596
11084
|
};
|
|
@@ -10643,11 +11131,49 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10643
11131
|
return { success: false, errors };
|
|
10644
11132
|
}
|
|
10645
11133
|
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10646
|
-
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(
|
|
10647
11164
|
{ sys: prompts.system, user: prompts.user },
|
|
11165
|
+
llmTools,
|
|
11166
|
+
toolHandler,
|
|
10648
11167
|
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10649
|
-
|
|
11168
|
+
5
|
|
11169
|
+
// max iterations
|
|
10650
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
|
+
}
|
|
10651
11177
|
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10652
11178
|
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10653
11179
|
if (!result.filterComponent) {
|
|
@@ -10661,13 +11187,17 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
10661
11187
|
}
|
|
10662
11188
|
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10663
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
|
+
}
|
|
10664
11193
|
return {
|
|
10665
11194
|
success: true,
|
|
10666
11195
|
data: {
|
|
10667
11196
|
filterComponent: result.filterComponent,
|
|
10668
11197
|
updatedComponents: result.updatedComponents || [],
|
|
10669
11198
|
filterBindings: result.filterBindings || {},
|
|
10670
|
-
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
|
|
10671
11201
|
},
|
|
10672
11202
|
errors: []
|
|
10673
11203
|
};
|
|
@@ -11845,6 +12375,11 @@ var SuperatomSDK = class {
|
|
|
11845
12375
|
logger.error("Failed to handle KB nodes request:", error);
|
|
11846
12376
|
});
|
|
11847
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;
|
|
11848
12383
|
case "DASH_COMP_REQ":
|
|
11849
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) => {
|
|
11850
12385
|
logger.error("Failed to handle dash comp request:", error);
|