@superatomai/sdk-node 0.0.42 → 0.0.43
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 +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.js +399 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +399 -101
- package/dist/index.mjs.map +1 -1
- package/package.json +49 -48
package/dist/index.js
CHANGED
|
@@ -1050,11 +1050,29 @@ Analyze the user's request and:
|
|
|
1050
1050
|
2. **Match by Type**: Choose the component type that best fits the data visualization or action need
|
|
1051
1051
|
3. **Match by Description**: Use component descriptions and keywords to find the best fit
|
|
1052
1052
|
|
|
1053
|
+
## Component Update Handling
|
|
1054
|
+
|
|
1055
|
+
The user prompt may contain an **existing component** to update. Detect this by looking for:
|
|
1056
|
+
- JSON object with \`componentId\`, \`props\`, or similar component structure in the prompt
|
|
1057
|
+
- Phrases like "update this", "modify", "change", "edit this component"
|
|
1058
|
+
|
|
1059
|
+
### When UPDATING an existing component:
|
|
1060
|
+
1. **Preserve the \`componentId\`** from the current component (do NOT pick a new one)
|
|
1061
|
+
2. **Keep the same \`componentType\`** unless the user explicitly asks to change it
|
|
1062
|
+
3. **Merge props**: Start with existing props, then modify only what the user requested
|
|
1063
|
+
4. **Set \`isUpdate: true\`** in your response
|
|
1064
|
+
5. **Preserve unmentioned props**: If user only asks to change the query, keep title/config unchanged
|
|
1065
|
+
|
|
1066
|
+
### When CREATING a new component:
|
|
1067
|
+
1. Pick the best component from the available list
|
|
1068
|
+
2. Generate all props from scratch
|
|
1069
|
+
3. Set \`isUpdate: false\` in your response
|
|
1070
|
+
|
|
1053
1071
|
## Data Source Decision
|
|
1054
1072
|
|
|
1055
1073
|
### Use DATABASE when:
|
|
1056
|
-
- User asks about data that exists in the database schema
|
|
1057
|
-
- Questions about internal business data
|
|
1074
|
+
- User asks about data that exists in the database schema
|
|
1075
|
+
- Questions about internal business data
|
|
1058
1076
|
- CRUD operations on database tables
|
|
1059
1077
|
|
|
1060
1078
|
### Use EXTERNAL TOOL when:
|
|
@@ -1135,11 +1153,12 @@ Analyze the user's request and:
|
|
|
1135
1153
|
You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
1136
1154
|
|
|
1137
1155
|
{
|
|
1138
|
-
"componentId": "
|
|
1156
|
+
"componentId": "id_from_available_list_or_existing_component_id",
|
|
1139
1157
|
"componentName": "name_of_component",
|
|
1140
1158
|
"componentType": "type_of_component",
|
|
1141
1159
|
"dataSourceType": "database" | "external_tool",
|
|
1142
1160
|
"operationType": "view" | "create" | "update" | "delete",
|
|
1161
|
+
"isUpdate": true | false,
|
|
1143
1162
|
"reasoning": "Why this component was selected and why this data source",
|
|
1144
1163
|
"props": {
|
|
1145
1164
|
// Generate ALL props based on the component's Props Structure
|
|
@@ -1150,25 +1169,165 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1150
1169
|
|
|
1151
1170
|
**CRITICAL:**
|
|
1152
1171
|
- Return ONLY valid JSON (no markdown code blocks, no text before/after)
|
|
1153
|
-
- \`componentId
|
|
1172
|
+
- \`componentId\`: For new components, MUST match an ID from the available components list. For updates, preserve the existing component's ID
|
|
1173
|
+
- \`isUpdate\`: Set to \`true\` if updating an existing component, \`false\` if creating new
|
|
1154
1174
|
- \`dataSourceType\` indicates whether data comes from database or external tool
|
|
1155
|
-
- \`operationType\` indicates the type of operation (view/create/update/delete)
|
|
1175
|
+
- \`operationType\` indicates the type of data operation (view/create/update/delete)
|
|
1156
1176
|
- Generate COMPLETE props based on the component's "Props Structure"
|
|
1157
1177
|
- For queries, ALWAYS use \`$paramName\` placeholders and include \`params\` object
|
|
1158
1178
|
- For external tools, \`toolId\` MUST match an ID from the available tools list
|
|
1159
1179
|
|
|
1180
|
+
## Database Schema
|
|
1181
|
+
{{SCHEMA_DOC}}
|
|
1182
|
+
|
|
1183
|
+
## Available External Tools
|
|
1184
|
+
{{AVAILABLE_TOOLS}}
|
|
1185
|
+
|
|
1186
|
+
## Available Components
|
|
1187
|
+
{{AVAILABLE_COMPONENTS}}
|
|
1188
|
+
|
|
1160
1189
|
---
|
|
1161
1190
|
|
|
1162
|
-
## CONTEXT
|
|
1191
|
+
## CONTEXT`,
|
|
1192
|
+
user: `{{USER_PROMPT}}`
|
|
1193
|
+
},
|
|
1194
|
+
"dash-filter-picker": {
|
|
1195
|
+
system: `You are a dashboard filter expert that creates filter components and updates existing dashboard components to work with the filter.
|
|
1196
|
+
|
|
1197
|
+
## Your Task
|
|
1198
|
+
|
|
1199
|
+
1. **Create a filter component** based on the user's request (DatePicker, Dropdown, SearchBox, etc.)
|
|
1200
|
+
2. **Update all existing components** to use the filter values in their queries/params
|
|
1201
|
+
|
|
1202
|
+
## Filter Types
|
|
1203
|
+
|
|
1204
|
+
Choose the appropriate filter component based on user intent:
|
|
1205
|
+
- **DateRangePicker**: For date range filtering (start date, end date)
|
|
1206
|
+
- **DatePicker**: For single date filtering
|
|
1207
|
+
- **Dropdown**: For categorical filtering (status, category, type, etc.)
|
|
1208
|
+
- **MultiSelect**: For multiple value selection
|
|
1209
|
+
- **SearchBox**: For text search filtering
|
|
1210
|
+
- **NumberRange**: For numeric range filtering
|
|
1211
|
+
|
|
1212
|
+
## Filter Component Structure
|
|
1213
|
+
|
|
1214
|
+
Generate a filter component with these props:
|
|
1215
|
+
\`\`\`json
|
|
1216
|
+
{
|
|
1217
|
+
"componentId": "unique_filter_id",
|
|
1218
|
+
"componentType": "DateRangePicker | Dropdown | SearchBox | etc.",
|
|
1219
|
+
"componentName": "Display Name",
|
|
1220
|
+
"props": {
|
|
1221
|
+
"filterId": "unique_filter_id",
|
|
1222
|
+
"label": "Filter Label",
|
|
1223
|
+
"defaultValue": "optional default value",
|
|
1224
|
+
"options": []
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
\`\`\`
|
|
1228
|
+
|
|
1229
|
+
## Updating Existing Components
|
|
1230
|
+
|
|
1231
|
+
For each existing component, update its query/externalTool to use the filter:
|
|
1232
|
+
|
|
1233
|
+
### For Database Queries:
|
|
1234
|
+
- Add filter conditions to WHERE clause using \`$paramName\` placeholders
|
|
1235
|
+
- Add the filter param to the \`params\` object with binding reference
|
|
1236
|
+
|
|
1237
|
+
### For External Tools:
|
|
1238
|
+
- Add filter params to the tool's params object with binding reference
|
|
1239
|
+
|
|
1240
|
+
## Filter Bindings
|
|
1241
|
+
|
|
1242
|
+
Use this binding format to connect filter values to component params:
|
|
1243
|
+
\`\`\`json
|
|
1244
|
+
{
|
|
1245
|
+
"paramName": "$filter.filterId.value"
|
|
1246
|
+
}
|
|
1247
|
+
\`\`\`
|
|
1163
1248
|
|
|
1164
|
-
|
|
1249
|
+
For DateRangePicker:
|
|
1250
|
+
- \`$filter.filterId.startDate\`
|
|
1251
|
+
- \`$filter.filterId.endDate\`
|
|
1252
|
+
|
|
1253
|
+
For Dropdown/MultiSelect:
|
|
1254
|
+
- \`$filter.filterId.value\`
|
|
1255
|
+
|
|
1256
|
+
For SearchBox:
|
|
1257
|
+
- \`$filter.filterId.searchText\`
|
|
1258
|
+
|
|
1259
|
+
### Database Query Rules
|
|
1260
|
+
{{DATABASE_RULES}}
|
|
1261
|
+
|
|
1262
|
+
## Output Format
|
|
1263
|
+
|
|
1264
|
+
You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
1265
|
+
|
|
1266
|
+
{
|
|
1267
|
+
"filterComponent": {
|
|
1268
|
+
"componentId": "filter_unique_id",
|
|
1269
|
+
"componentType": "DateRangePicker | Dropdown | etc.",
|
|
1270
|
+
"componentName": "Filter Display Name",
|
|
1271
|
+
"props": {
|
|
1272
|
+
"filterId": "filter_unique_id",
|
|
1273
|
+
"label": "Filter Label",
|
|
1274
|
+
"defaultValue": null,
|
|
1275
|
+
"options": []
|
|
1276
|
+
}
|
|
1277
|
+
},
|
|
1278
|
+
"updatedComponents": [
|
|
1279
|
+
{
|
|
1280
|
+
"componentId": "existing_component_id",
|
|
1281
|
+
"componentType": "existing_type",
|
|
1282
|
+
"componentName": "existing_name",
|
|
1283
|
+
"props": {
|
|
1284
|
+
// RETURN THE COMPLETE PROPS OBJECT
|
|
1285
|
+
// Copy ALL existing props and only modify the necessary fields
|
|
1286
|
+
"title": "Existing Title",
|
|
1287
|
+
"description": "Existing Description",
|
|
1288
|
+
"config": {},
|
|
1289
|
+
"query": {
|
|
1290
|
+
"sql": "SELECT ... WHERE column BETWEEN $startDate AND $endDate",
|
|
1291
|
+
"params": {
|
|
1292
|
+
"existingParam": "existing_value",
|
|
1293
|
+
"startDate": "$filter.filterId.startDate",
|
|
1294
|
+
"endDate": "$filter.filterId.endDate"
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
],
|
|
1300
|
+
"filterBindings": {
|
|
1301
|
+
"startDate": "$filter.filterId.startDate",
|
|
1302
|
+
"endDate": "$filter.filterId.endDate"
|
|
1303
|
+
},
|
|
1304
|
+
"reasoning": "Explanation of filter choice and how components were updated"
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
**CRITICAL:**
|
|
1308
|
+
- Return ONLY valid JSON (no markdown code blocks, no text before/after)
|
|
1309
|
+
- **RETURN COMPLETE PROPS**: Copy ALL existing props from each component, only modify what's needed for the filter
|
|
1310
|
+
- Do NOT omit existing props like title, description, config - include them unchanged
|
|
1311
|
+
- Only modify query.sql (add WHERE conditions) and query.params (add filter bindings)
|
|
1312
|
+
- For externalTool, only add filter params to the params object
|
|
1313
|
+
- Use consistent param naming across all components
|
|
1314
|
+
- Ensure SQL syntax is valid with the new filter conditions
|
|
1315
|
+
|
|
1316
|
+
## Database Schema
|
|
1165
1317
|
{{SCHEMA_DOC}}
|
|
1166
1318
|
|
|
1167
|
-
|
|
1319
|
+
## Available External Tools
|
|
1168
1320
|
{{AVAILABLE_TOOLS}}
|
|
1169
1321
|
|
|
1170
|
-
|
|
1171
|
-
{{AVAILABLE_COMPONENTS}}
|
|
1322
|
+
## Available Filter Components
|
|
1323
|
+
{{AVAILABLE_COMPONENTS}}
|
|
1324
|
+
|
|
1325
|
+
## Existing Dashboard Components
|
|
1326
|
+
{{EXISTING_COMPONENTS}}
|
|
1327
|
+
|
|
1328
|
+
---
|
|
1329
|
+
|
|
1330
|
+
## CONTEXT`,
|
|
1172
1331
|
user: `{{USER_PROMPT}}`
|
|
1173
1332
|
}
|
|
1174
1333
|
};
|
|
@@ -1904,6 +2063,7 @@ var AuthVerifyRequestMessageSchema = import_zod3.z.object({
|
|
|
1904
2063
|
});
|
|
1905
2064
|
var UserPromptRequestPayloadSchema = import_zod3.z.object({
|
|
1906
2065
|
prompt: import_zod3.z.string(),
|
|
2066
|
+
userId: import_zod3.z.string().optional(),
|
|
1907
2067
|
SA_RUNTIME: import_zod3.z.object({
|
|
1908
2068
|
threadId: import_zod3.z.string(),
|
|
1909
2069
|
uiBlockId: import_zod3.z.string()
|
|
@@ -1918,6 +2078,7 @@ var UserPromptRequestMessageSchema = import_zod3.z.object({
|
|
|
1918
2078
|
});
|
|
1919
2079
|
var UserPromptSuggestionsPayloadSchema = import_zod3.z.object({
|
|
1920
2080
|
prompt: import_zod3.z.string(),
|
|
2081
|
+
userId: import_zod3.z.string().optional(),
|
|
1921
2082
|
limit: import_zod3.z.number().int().positive().default(5),
|
|
1922
2083
|
similarityThreshold: import_zod3.z.number().min(0).max(1).default(0.4)
|
|
1923
2084
|
});
|
|
@@ -2007,6 +2168,7 @@ var UILogsMessageSchema = import_zod3.z.object({
|
|
|
2007
2168
|
payload: UILogsPayloadSchema
|
|
2008
2169
|
});
|
|
2009
2170
|
var ActionsRequestPayloadSchema = import_zod3.z.object({
|
|
2171
|
+
userId: import_zod3.z.string().optional(),
|
|
2010
2172
|
SA_RUNTIME: import_zod3.z.object({
|
|
2011
2173
|
threadId: import_zod3.z.string(),
|
|
2012
2174
|
uiBlockId: import_zod3.z.string()
|
|
@@ -2207,10 +2369,15 @@ var KbNodesRequestMessageSchema = import_zod3.z.object({
|
|
|
2207
2369
|
});
|
|
2208
2370
|
var DashCompRequestPayloadSchema = import_zod3.z.object({
|
|
2209
2371
|
prompt: import_zod3.z.string(),
|
|
2372
|
+
userId: import_zod3.z.string().optional(),
|
|
2210
2373
|
SA_RUNTIME: import_zod3.z.object({
|
|
2211
2374
|
threadId: import_zod3.z.string().optional(),
|
|
2212
2375
|
uiBlockId: import_zod3.z.string().optional()
|
|
2213
|
-
}).optional()
|
|
2376
|
+
}).optional(),
|
|
2377
|
+
/** Existing components in the dashboard (for update/filter operations) */
|
|
2378
|
+
existingComponents: import_zod3.z.array(ComponentSchema).optional(),
|
|
2379
|
+
/** Request type: create (new component), update (modify existing), filter (create filter + update components) */
|
|
2380
|
+
req_type: import_zod3.z.enum(["create", "update", "filter"]).optional()
|
|
2214
2381
|
});
|
|
2215
2382
|
var DashCompRequestMessageSchema = import_zod3.z.object({
|
|
2216
2383
|
id: import_zod3.z.string(),
|
|
@@ -7353,7 +7520,7 @@ var CONTEXT_CONFIG = {
|
|
|
7353
7520
|
};
|
|
7354
7521
|
|
|
7355
7522
|
// src/handlers/user-prompt-request.ts
|
|
7356
|
-
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools
|
|
7523
|
+
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools) => {
|
|
7357
7524
|
const errors = [];
|
|
7358
7525
|
logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
|
|
7359
7526
|
const parseResult = UserPromptRequestMessageSchema.safeParse(data);
|
|
@@ -7367,6 +7534,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
7367
7534
|
const userPromptRequest = parseResult.data;
|
|
7368
7535
|
const { id, payload } = userPromptRequest;
|
|
7369
7536
|
const prompt = payload.prompt;
|
|
7537
|
+
const userId = payload.userId;
|
|
7370
7538
|
const SA_RUNTIME = payload.SA_RUNTIME;
|
|
7371
7539
|
const wsId = userPromptRequest.from.id || "unknown";
|
|
7372
7540
|
const promptContext = `User Prompt: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
@@ -7539,8 +7707,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
7539
7707
|
wsId
|
|
7540
7708
|
};
|
|
7541
7709
|
};
|
|
7542
|
-
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools
|
|
7543
|
-
const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools
|
|
7710
|
+
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools) {
|
|
7711
|
+
const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools);
|
|
7544
7712
|
sendDataResponse4(
|
|
7545
7713
|
response.id || data.id,
|
|
7546
7714
|
{
|
|
@@ -7572,11 +7740,11 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
|
7572
7740
|
|
|
7573
7741
|
// src/handlers/user-prompt-suggestions.ts
|
|
7574
7742
|
init_logger();
|
|
7575
|
-
async function handleUserPromptSuggestions(data, components, sendMessage, collections
|
|
7743
|
+
async function handleUserPromptSuggestions(data, components, sendMessage, collections) {
|
|
7576
7744
|
try {
|
|
7577
7745
|
const request = UserPromptSuggestionsMessageSchema.parse(data);
|
|
7578
7746
|
const { id, payload, from } = request;
|
|
7579
|
-
const { prompt, limit = 10 } = payload;
|
|
7747
|
+
const { prompt, userId, limit = 10 } = payload;
|
|
7580
7748
|
const wsId = from.id;
|
|
7581
7749
|
logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Processing user prompt suggestions: ${prompt}`);
|
|
7582
7750
|
if (!prompt || prompt.trim().length === 0) {
|
|
@@ -10216,40 +10384,108 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10216
10384
|
sendMessage(response);
|
|
10217
10385
|
}
|
|
10218
10386
|
|
|
10219
|
-
// src/
|
|
10387
|
+
// src/dashComp/index.ts
|
|
10220
10388
|
init_logger();
|
|
10221
|
-
|
|
10389
|
+
|
|
10390
|
+
// src/dashComp/types.ts
|
|
10222
10391
|
var DEFAULT_DASH_COMP_MODELS = {
|
|
10223
10392
|
anthropic: "anthropic/claude-haiku-4-5-20251001",
|
|
10224
10393
|
gemini: "gemini/gemini-3-flash-preview",
|
|
10225
10394
|
openai: "openai/gpt-4o-mini",
|
|
10226
10395
|
groq: "groq/llama-3.3-70b-versatile"
|
|
10227
10396
|
};
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10397
|
+
|
|
10398
|
+
// src/dashComp/utils.ts
|
|
10399
|
+
function getApiKeyAndModel(anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, dashCompModels) {
|
|
10400
|
+
const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
|
|
10401
|
+
let apiKey;
|
|
10402
|
+
let model;
|
|
10403
|
+
if (dashCompModels?.model) {
|
|
10404
|
+
model = dashCompModels.model;
|
|
10405
|
+
const modelProvider = model.split("/")[0];
|
|
10406
|
+
if (modelProvider === "anthropic") apiKey = anthropicApiKey;
|
|
10407
|
+
else if (modelProvider === "gemini") apiKey = geminiApiKey;
|
|
10408
|
+
else if (modelProvider === "openai") apiKey = openaiApiKey;
|
|
10409
|
+
else if (modelProvider === "groq") apiKey = groqApiKey;
|
|
10410
|
+
} else {
|
|
10411
|
+
for (const provider of providers) {
|
|
10412
|
+
if (provider === "anthropic" && anthropicApiKey) {
|
|
10413
|
+
apiKey = anthropicApiKey;
|
|
10414
|
+
model = DEFAULT_DASH_COMP_MODELS.anthropic;
|
|
10415
|
+
break;
|
|
10416
|
+
} else if (provider === "gemini" && geminiApiKey) {
|
|
10417
|
+
apiKey = geminiApiKey;
|
|
10418
|
+
model = DEFAULT_DASH_COMP_MODELS.gemini;
|
|
10419
|
+
break;
|
|
10420
|
+
} else if (provider === "openai" && openaiApiKey) {
|
|
10421
|
+
apiKey = openaiApiKey;
|
|
10422
|
+
model = DEFAULT_DASH_COMP_MODELS.openai;
|
|
10423
|
+
break;
|
|
10424
|
+
} else if (provider === "groq" && groqApiKey) {
|
|
10425
|
+
apiKey = groqApiKey;
|
|
10426
|
+
model = DEFAULT_DASH_COMP_MODELS.groq;
|
|
10427
|
+
break;
|
|
10428
|
+
}
|
|
10429
|
+
}
|
|
10430
|
+
}
|
|
10431
|
+
return { apiKey, model };
|
|
10432
|
+
}
|
|
10433
|
+
function formatComponentsForPrompt(components) {
|
|
10434
|
+
if (!components || components.length === 0) {
|
|
10435
|
+
return "No components available";
|
|
10436
|
+
}
|
|
10437
|
+
return components.map((comp, idx) => {
|
|
10438
|
+
const keywords = comp.keywords ? comp.keywords.join(", ") : "";
|
|
10439
|
+
const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
|
|
10440
|
+
return `${idx + 1}. ID: ${comp.id}
|
|
10236
10441
|
Name: ${comp.name}
|
|
10237
10442
|
Type: ${comp.type}
|
|
10238
10443
|
Description: ${comp.description || "No description"}
|
|
10239
10444
|
Keywords: ${keywords}
|
|
10240
10445
|
Props Structure: ${propsPreview}`;
|
|
10241
|
-
|
|
10446
|
+
}).join("\n\n");
|
|
10447
|
+
}
|
|
10448
|
+
function formatToolsForPrompt(tools) {
|
|
10449
|
+
if (!tools || tools.length === 0) {
|
|
10450
|
+
return "No external tools available.";
|
|
10242
10451
|
}
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
10247
|
-
return `${idx + 1}. ID: ${tool.id}
|
|
10452
|
+
return tools.map((tool, idx) => {
|
|
10453
|
+
const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
10454
|
+
return `${idx + 1}. ID: ${tool.id}
|
|
10248
10455
|
Name: ${tool.name}
|
|
10249
10456
|
Description: ${tool.description}
|
|
10250
10457
|
Parameters: { ${paramsStr} }`;
|
|
10251
|
-
|
|
10458
|
+
}).join("\n\n");
|
|
10459
|
+
}
|
|
10460
|
+
function formatExistingComponentsForPrompt(existingComponents) {
|
|
10461
|
+
if (!existingComponents || existingComponents.length === 0) {
|
|
10462
|
+
return "No existing components in dashboard";
|
|
10252
10463
|
}
|
|
10464
|
+
return JSON.stringify(existingComponents, null, 2);
|
|
10465
|
+
}
|
|
10466
|
+
function sendDashCompResponse(id, res, sendMessage, clientId) {
|
|
10467
|
+
const response = {
|
|
10468
|
+
id,
|
|
10469
|
+
type: "DASH_COMP_RES",
|
|
10470
|
+
from: { type: "data-agent" },
|
|
10471
|
+
to: {
|
|
10472
|
+
type: "runtime",
|
|
10473
|
+
id: clientId
|
|
10474
|
+
},
|
|
10475
|
+
payload: {
|
|
10476
|
+
...res
|
|
10477
|
+
}
|
|
10478
|
+
};
|
|
10479
|
+
sendMessage(response);
|
|
10480
|
+
}
|
|
10481
|
+
|
|
10482
|
+
// src/dashComp/pick-component.ts
|
|
10483
|
+
init_logger();
|
|
10484
|
+
init_prompt_loader();
|
|
10485
|
+
async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, _collections, tools, dashCompModels) {
|
|
10486
|
+
const errors = [];
|
|
10487
|
+
const availableComponentsText = formatComponentsForPrompt(components);
|
|
10488
|
+
const availableToolsText = formatToolsForPrompt(tools);
|
|
10253
10489
|
try {
|
|
10254
10490
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
10255
10491
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
@@ -10261,38 +10497,14 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10261
10497
|
AVAILABLE_TOOLS: availableToolsText
|
|
10262
10498
|
});
|
|
10263
10499
|
logger.debug("[DASH_COMP_REQ] Loaded dash-comp-picker prompts with schema and tools");
|
|
10264
|
-
const
|
|
10265
|
-
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
else if (modelProvider === "openai") apiKey = openaiApiKey;
|
|
10273
|
-
else if (modelProvider === "groq") apiKey = groqApiKey;
|
|
10274
|
-
logger.info(`[DASH_COMP_REQ] Using configured model: ${model}`);
|
|
10275
|
-
} else {
|
|
10276
|
-
for (const provider of providers) {
|
|
10277
|
-
if (provider === "anthropic" && anthropicApiKey) {
|
|
10278
|
-
apiKey = anthropicApiKey;
|
|
10279
|
-
model = DEFAULT_DASH_COMP_MODELS.anthropic;
|
|
10280
|
-
break;
|
|
10281
|
-
} else if (provider === "gemini" && geminiApiKey) {
|
|
10282
|
-
apiKey = geminiApiKey;
|
|
10283
|
-
model = DEFAULT_DASH_COMP_MODELS.gemini;
|
|
10284
|
-
break;
|
|
10285
|
-
} else if (provider === "openai" && openaiApiKey) {
|
|
10286
|
-
apiKey = openaiApiKey;
|
|
10287
|
-
model = DEFAULT_DASH_COMP_MODELS.openai;
|
|
10288
|
-
break;
|
|
10289
|
-
} else if (provider === "groq" && groqApiKey) {
|
|
10290
|
-
apiKey = groqApiKey;
|
|
10291
|
-
model = DEFAULT_DASH_COMP_MODELS.groq;
|
|
10292
|
-
break;
|
|
10293
|
-
}
|
|
10294
|
-
}
|
|
10295
|
-
}
|
|
10500
|
+
const { apiKey, model } = getApiKeyAndModel(
|
|
10501
|
+
anthropicApiKey,
|
|
10502
|
+
groqApiKey,
|
|
10503
|
+
geminiApiKey,
|
|
10504
|
+
openaiApiKey,
|
|
10505
|
+
llmProviders,
|
|
10506
|
+
dashCompModels
|
|
10507
|
+
);
|
|
10296
10508
|
if (!apiKey || !model) {
|
|
10297
10509
|
errors.push("No API key available for any LLM provider");
|
|
10298
10510
|
return { success: false, errors };
|
|
@@ -10352,7 +10564,8 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10352
10564
|
data: {
|
|
10353
10565
|
component: finalComponent,
|
|
10354
10566
|
reasoning: result.reasoning || "Component selected based on user prompt",
|
|
10355
|
-
dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none"
|
|
10567
|
+
dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none",
|
|
10568
|
+
isUpdate: result.isUpdate || false
|
|
10356
10569
|
},
|
|
10357
10570
|
errors: []
|
|
10358
10571
|
};
|
|
@@ -10368,6 +10581,84 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10368
10581
|
return { success: false, errors };
|
|
10369
10582
|
}
|
|
10370
10583
|
}
|
|
10584
|
+
|
|
10585
|
+
// src/dashComp/create-filter.ts
|
|
10586
|
+
init_logger();
|
|
10587
|
+
init_prompt_loader();
|
|
10588
|
+
async function createFilterWithLLM(prompt, components, existingComponents, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, tools, dashCompModels) {
|
|
10589
|
+
const errors = [];
|
|
10590
|
+
try {
|
|
10591
|
+
const filterComponents = components.filter((c) => c.type.startsWith("Filter"));
|
|
10592
|
+
if (filterComponents.length === 0) {
|
|
10593
|
+
errors.push("No filter components available");
|
|
10594
|
+
return { success: false, errors };
|
|
10595
|
+
}
|
|
10596
|
+
logger.debug(`[DASH_COMP_REQ:FILTER] Found ${filterComponents.length} filter components`);
|
|
10597
|
+
const schemaDoc = schema.generateSchemaDocumentation();
|
|
10598
|
+
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
10599
|
+
const prompts = await promptLoader.loadPrompts("dash-filter-picker", {
|
|
10600
|
+
USER_PROMPT: prompt,
|
|
10601
|
+
AVAILABLE_COMPONENTS: formatComponentsForPrompt(filterComponents),
|
|
10602
|
+
EXISTING_COMPONENTS: formatExistingComponentsForPrompt(existingComponents),
|
|
10603
|
+
SCHEMA_DOC: schemaDoc || "No database schema available",
|
|
10604
|
+
DATABASE_RULES: databaseRules,
|
|
10605
|
+
AVAILABLE_TOOLS: formatToolsForPrompt(tools)
|
|
10606
|
+
});
|
|
10607
|
+
logger.debug("[DASH_COMP_REQ:FILTER] Loaded dash-filter-picker prompts");
|
|
10608
|
+
const { apiKey, model } = getApiKeyAndModel(
|
|
10609
|
+
anthropicApiKey,
|
|
10610
|
+
groqApiKey,
|
|
10611
|
+
geminiApiKey,
|
|
10612
|
+
openaiApiKey,
|
|
10613
|
+
llmProviders,
|
|
10614
|
+
dashCompModels
|
|
10615
|
+
);
|
|
10616
|
+
if (!apiKey || !model) {
|
|
10617
|
+
errors.push("No API key available for any LLM provider");
|
|
10618
|
+
return { success: false, errors };
|
|
10619
|
+
}
|
|
10620
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10621
|
+
const result = await LLM.stream(
|
|
10622
|
+
{ sys: prompts.system, user: prompts.user },
|
|
10623
|
+
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10624
|
+
true
|
|
10625
|
+
);
|
|
10626
|
+
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10627
|
+
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10628
|
+
if (!result.filterComponent) {
|
|
10629
|
+
errors.push("Invalid LLM response: missing filterComponent");
|
|
10630
|
+
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", "Invalid LLM response structure", {
|
|
10631
|
+
prompt,
|
|
10632
|
+
result,
|
|
10633
|
+
missingFields: { filterComponent: !result.filterComponent }
|
|
10634
|
+
});
|
|
10635
|
+
return { success: false, errors };
|
|
10636
|
+
}
|
|
10637
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10638
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Updated ${result.updatedComponents?.length || 0} components`);
|
|
10639
|
+
return {
|
|
10640
|
+
success: true,
|
|
10641
|
+
data: {
|
|
10642
|
+
filterComponent: result.filterComponent,
|
|
10643
|
+
updatedComponents: result.updatedComponents || [],
|
|
10644
|
+
filterBindings: result.filterBindings || {},
|
|
10645
|
+
reasoning: result.reasoning || "Filter created based on user prompt"
|
|
10646
|
+
},
|
|
10647
|
+
errors: []
|
|
10648
|
+
};
|
|
10649
|
+
} catch (error) {
|
|
10650
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
10651
|
+
logger.error(`[DASH_COMP_REQ:FILTER] Error creating filter: ${errorMsg}`);
|
|
10652
|
+
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", error instanceof Error ? error : new Error(errorMsg), {
|
|
10653
|
+
prompt,
|
|
10654
|
+
existingComponentsCount: existingComponents.length
|
|
10655
|
+
});
|
|
10656
|
+
errors.push(errorMsg);
|
|
10657
|
+
return { success: false, errors };
|
|
10658
|
+
}
|
|
10659
|
+
}
|
|
10660
|
+
|
|
10661
|
+
// src/dashComp/index.ts
|
|
10371
10662
|
var processDashCompRequest = async (data, components, _sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, dashCompModels) => {
|
|
10372
10663
|
const errors = [];
|
|
10373
10664
|
logger.debug("[DASH_COMP_REQ] Parsing incoming message data");
|
|
@@ -10382,17 +10673,25 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
10382
10673
|
const dashCompRequest = parseResult.data;
|
|
10383
10674
|
const { id, payload } = dashCompRequest;
|
|
10384
10675
|
const prompt = payload.prompt;
|
|
10676
|
+
const reqType = payload.req_type || "create";
|
|
10677
|
+
const existingComponents = payload.existingComponents || [];
|
|
10385
10678
|
const wsId = dashCompRequest.from.id || "unknown";
|
|
10386
|
-
const promptContext = `DASH_COMP: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
10679
|
+
const promptContext = `DASH_COMP[${reqType}]: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
10387
10680
|
llmUsageLogger.resetLogFile(promptContext);
|
|
10388
10681
|
if (!prompt) {
|
|
10389
10682
|
errors.push("Prompt is required");
|
|
10390
10683
|
}
|
|
10684
|
+
if (reqType === "filter" && existingComponents.length === 0) {
|
|
10685
|
+
errors.push("Filter request requires existingComponents");
|
|
10686
|
+
}
|
|
10391
10687
|
if (errors.length > 0) {
|
|
10392
10688
|
return { success: false, errors, id, wsId };
|
|
10393
10689
|
}
|
|
10394
|
-
logger.info(`[DASH_COMP_REQ] Processing request for prompt: "${prompt.substring(0, 50)}..."`);
|
|
10690
|
+
logger.info(`[DASH_COMP_REQ] Processing ${reqType} request for prompt: "${prompt.substring(0, 50)}..."`);
|
|
10395
10691
|
logger.info(`[DASH_COMP_REQ] Available: ${components?.length || 0} components, ${tools?.length || 0} tools`);
|
|
10692
|
+
if (existingComponents.length > 0) {
|
|
10693
|
+
logger.info(`[DASH_COMP_REQ] Existing components in dashboard: ${existingComponents.length}`);
|
|
10694
|
+
}
|
|
10396
10695
|
if (!components || components.length === 0) {
|
|
10397
10696
|
logger.warn("[DASH_COMP_REQ] No components available");
|
|
10398
10697
|
return {
|
|
@@ -10402,19 +10701,35 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
10402
10701
|
wsId
|
|
10403
10702
|
};
|
|
10404
10703
|
}
|
|
10405
|
-
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10704
|
+
let llmResponse;
|
|
10705
|
+
if (reqType === "filter") {
|
|
10706
|
+
llmResponse = await createFilterWithLLM(
|
|
10707
|
+
prompt,
|
|
10708
|
+
components,
|
|
10709
|
+
existingComponents,
|
|
10710
|
+
anthropicApiKey,
|
|
10711
|
+
groqApiKey,
|
|
10712
|
+
geminiApiKey,
|
|
10713
|
+
openaiApiKey,
|
|
10714
|
+
llmProviders,
|
|
10715
|
+
tools,
|
|
10716
|
+
dashCompModels
|
|
10717
|
+
);
|
|
10718
|
+
} else {
|
|
10719
|
+
llmResponse = await pickComponentWithLLM(
|
|
10720
|
+
prompt,
|
|
10721
|
+
components,
|
|
10722
|
+
anthropicApiKey,
|
|
10723
|
+
groqApiKey,
|
|
10724
|
+
geminiApiKey,
|
|
10725
|
+
openaiApiKey,
|
|
10726
|
+
llmProviders,
|
|
10727
|
+
collections,
|
|
10728
|
+
tools,
|
|
10729
|
+
dashCompModels
|
|
10730
|
+
);
|
|
10731
|
+
}
|
|
10732
|
+
llmUsageLogger.logSessionSummary(`DASH_COMP[${reqType}]: ${prompt?.substring(0, 30)}`);
|
|
10418
10733
|
return {
|
|
10419
10734
|
success: llmResponse.success,
|
|
10420
10735
|
data: llmResponse.data,
|
|
@@ -10447,22 +10762,7 @@ async function handleDashCompRequest(data, components, sendMessage, anthropicApi
|
|
|
10447
10762
|
sendMessage,
|
|
10448
10763
|
response.wsId || data.from?.id
|
|
10449
10764
|
);
|
|
10450
|
-
}
|
|
10451
|
-
function sendDashCompResponse(id, res, sendMessage, clientId) {
|
|
10452
|
-
const response = {
|
|
10453
|
-
id,
|
|
10454
|
-
type: "DASH_COMP_RES",
|
|
10455
|
-
from: { type: "data-agent" },
|
|
10456
|
-
to: {
|
|
10457
|
-
type: "runtime",
|
|
10458
|
-
id: clientId
|
|
10459
|
-
},
|
|
10460
|
-
payload: {
|
|
10461
|
-
...res
|
|
10462
|
-
}
|
|
10463
|
-
};
|
|
10464
|
-
sendMessage(response);
|
|
10465
|
-
logger.info(`[DASH_COMP_REQ] Response sent to client ${clientId}`);
|
|
10765
|
+
logger.info(`[DASH_COMP_REQ] Response sent to client ${response.wsId || data.from?.id}`);
|
|
10466
10766
|
}
|
|
10467
10767
|
|
|
10468
10768
|
// src/auth/user-manager.ts
|
|
@@ -11310,7 +11610,6 @@ var SuperatomSDK = class {
|
|
|
11310
11610
|
}
|
|
11311
11611
|
this.apiKey = config.apiKey;
|
|
11312
11612
|
this.projectId = config.projectId;
|
|
11313
|
-
this.userId = config.userId || "anonymous";
|
|
11314
11613
|
this.type = config.type || "data-agent";
|
|
11315
11614
|
this.bundleDir = config.bundleDir;
|
|
11316
11615
|
this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;
|
|
@@ -11412,7 +11711,6 @@ var SuperatomSDK = class {
|
|
|
11412
11711
|
url.searchParams.set("apiKey", this.apiKey);
|
|
11413
11712
|
}
|
|
11414
11713
|
url.searchParams.set("projectId", this.projectId);
|
|
11415
|
-
url.searchParams.set("userId", this.userId);
|
|
11416
11714
|
url.searchParams.set("type", this.type);
|
|
11417
11715
|
logger.info(`Connecting to WebSocket: ${url.toString()}`);
|
|
11418
11716
|
this.ws = createWebSocket(url.toString());
|
|
@@ -11473,7 +11771,7 @@ var SuperatomSDK = class {
|
|
|
11473
11771
|
});
|
|
11474
11772
|
break;
|
|
11475
11773
|
case "USER_PROMPT_REQ":
|
|
11476
|
-
handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools
|
|
11774
|
+
handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
|
|
11477
11775
|
logger.error("Failed to handle user prompt request:", error);
|
|
11478
11776
|
});
|
|
11479
11777
|
break;
|
|
@@ -11483,7 +11781,7 @@ var SuperatomSDK = class {
|
|
|
11483
11781
|
});
|
|
11484
11782
|
break;
|
|
11485
11783
|
case "USER_PROMPT_SUGGESTIONS_REQ":
|
|
11486
|
-
handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections
|
|
11784
|
+
handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections).catch((error) => {
|
|
11487
11785
|
logger.error("Failed to handle user prompt suggestions request:", error);
|
|
11488
11786
|
});
|
|
11489
11787
|
break;
|