@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.mjs
CHANGED
|
@@ -1028,11 +1028,29 @@ Analyze the user's request and:
|
|
|
1028
1028
|
2. **Match by Type**: Choose the component type that best fits the data visualization or action need
|
|
1029
1029
|
3. **Match by Description**: Use component descriptions and keywords to find the best fit
|
|
1030
1030
|
|
|
1031
|
+
## Component Update Handling
|
|
1032
|
+
|
|
1033
|
+
The user prompt may contain an **existing component** to update. Detect this by looking for:
|
|
1034
|
+
- JSON object with \`componentId\`, \`props\`, or similar component structure in the prompt
|
|
1035
|
+
- Phrases like "update this", "modify", "change", "edit this component"
|
|
1036
|
+
|
|
1037
|
+
### When UPDATING an existing component:
|
|
1038
|
+
1. **Preserve the \`componentId\`** from the current component (do NOT pick a new one)
|
|
1039
|
+
2. **Keep the same \`componentType\`** unless the user explicitly asks to change it
|
|
1040
|
+
3. **Merge props**: Start with existing props, then modify only what the user requested
|
|
1041
|
+
4. **Set \`isUpdate: true\`** in your response
|
|
1042
|
+
5. **Preserve unmentioned props**: If user only asks to change the query, keep title/config unchanged
|
|
1043
|
+
|
|
1044
|
+
### When CREATING a new component:
|
|
1045
|
+
1. Pick the best component from the available list
|
|
1046
|
+
2. Generate all props from scratch
|
|
1047
|
+
3. Set \`isUpdate: false\` in your response
|
|
1048
|
+
|
|
1031
1049
|
## Data Source Decision
|
|
1032
1050
|
|
|
1033
1051
|
### Use DATABASE when:
|
|
1034
|
-
- User asks about data that exists in the database schema
|
|
1035
|
-
- Questions about internal business data
|
|
1052
|
+
- User asks about data that exists in the database schema
|
|
1053
|
+
- Questions about internal business data
|
|
1036
1054
|
- CRUD operations on database tables
|
|
1037
1055
|
|
|
1038
1056
|
### Use EXTERNAL TOOL when:
|
|
@@ -1113,11 +1131,12 @@ Analyze the user's request and:
|
|
|
1113
1131
|
You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
1114
1132
|
|
|
1115
1133
|
{
|
|
1116
|
-
"componentId": "
|
|
1134
|
+
"componentId": "id_from_available_list_or_existing_component_id",
|
|
1117
1135
|
"componentName": "name_of_component",
|
|
1118
1136
|
"componentType": "type_of_component",
|
|
1119
1137
|
"dataSourceType": "database" | "external_tool",
|
|
1120
1138
|
"operationType": "view" | "create" | "update" | "delete",
|
|
1139
|
+
"isUpdate": true | false,
|
|
1121
1140
|
"reasoning": "Why this component was selected and why this data source",
|
|
1122
1141
|
"props": {
|
|
1123
1142
|
// Generate ALL props based on the component's Props Structure
|
|
@@ -1128,25 +1147,165 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
1128
1147
|
|
|
1129
1148
|
**CRITICAL:**
|
|
1130
1149
|
- Return ONLY valid JSON (no markdown code blocks, no text before/after)
|
|
1131
|
-
- \`componentId
|
|
1150
|
+
- \`componentId\`: For new components, MUST match an ID from the available components list. For updates, preserve the existing component's ID
|
|
1151
|
+
- \`isUpdate\`: Set to \`true\` if updating an existing component, \`false\` if creating new
|
|
1132
1152
|
- \`dataSourceType\` indicates whether data comes from database or external tool
|
|
1133
|
-
- \`operationType\` indicates the type of operation (view/create/update/delete)
|
|
1153
|
+
- \`operationType\` indicates the type of data operation (view/create/update/delete)
|
|
1134
1154
|
- Generate COMPLETE props based on the component's "Props Structure"
|
|
1135
1155
|
- For queries, ALWAYS use \`$paramName\` placeholders and include \`params\` object
|
|
1136
1156
|
- For external tools, \`toolId\` MUST match an ID from the available tools list
|
|
1137
1157
|
|
|
1158
|
+
## Database Schema
|
|
1159
|
+
{{SCHEMA_DOC}}
|
|
1160
|
+
|
|
1161
|
+
## Available External Tools
|
|
1162
|
+
{{AVAILABLE_TOOLS}}
|
|
1163
|
+
|
|
1164
|
+
## Available Components
|
|
1165
|
+
{{AVAILABLE_COMPONENTS}}
|
|
1166
|
+
|
|
1138
1167
|
---
|
|
1139
1168
|
|
|
1140
|
-
## CONTEXT
|
|
1169
|
+
## CONTEXT`,
|
|
1170
|
+
user: `{{USER_PROMPT}}`
|
|
1171
|
+
},
|
|
1172
|
+
"dash-filter-picker": {
|
|
1173
|
+
system: `You are a dashboard filter expert that creates filter components and updates existing dashboard components to work with the filter.
|
|
1174
|
+
|
|
1175
|
+
## Your Task
|
|
1176
|
+
|
|
1177
|
+
1. **Create a filter component** based on the user's request (DatePicker, Dropdown, SearchBox, etc.)
|
|
1178
|
+
2. **Update all existing components** to use the filter values in their queries/params
|
|
1179
|
+
|
|
1180
|
+
## Filter Types
|
|
1181
|
+
|
|
1182
|
+
Choose the appropriate filter component based on user intent:
|
|
1183
|
+
- **DateRangePicker**: For date range filtering (start date, end date)
|
|
1184
|
+
- **DatePicker**: For single date filtering
|
|
1185
|
+
- **Dropdown**: For categorical filtering (status, category, type, etc.)
|
|
1186
|
+
- **MultiSelect**: For multiple value selection
|
|
1187
|
+
- **SearchBox**: For text search filtering
|
|
1188
|
+
- **NumberRange**: For numeric range filtering
|
|
1189
|
+
|
|
1190
|
+
## Filter Component Structure
|
|
1191
|
+
|
|
1192
|
+
Generate a filter component with these props:
|
|
1193
|
+
\`\`\`json
|
|
1194
|
+
{
|
|
1195
|
+
"componentId": "unique_filter_id",
|
|
1196
|
+
"componentType": "DateRangePicker | Dropdown | SearchBox | etc.",
|
|
1197
|
+
"componentName": "Display Name",
|
|
1198
|
+
"props": {
|
|
1199
|
+
"filterId": "unique_filter_id",
|
|
1200
|
+
"label": "Filter Label",
|
|
1201
|
+
"defaultValue": "optional default value",
|
|
1202
|
+
"options": []
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
\`\`\`
|
|
1206
|
+
|
|
1207
|
+
## Updating Existing Components
|
|
1208
|
+
|
|
1209
|
+
For each existing component, update its query/externalTool to use the filter:
|
|
1210
|
+
|
|
1211
|
+
### For Database Queries:
|
|
1212
|
+
- Add filter conditions to WHERE clause using \`$paramName\` placeholders
|
|
1213
|
+
- Add the filter param to the \`params\` object with binding reference
|
|
1214
|
+
|
|
1215
|
+
### For External Tools:
|
|
1216
|
+
- Add filter params to the tool's params object with binding reference
|
|
1217
|
+
|
|
1218
|
+
## Filter Bindings
|
|
1219
|
+
|
|
1220
|
+
Use this binding format to connect filter values to component params:
|
|
1221
|
+
\`\`\`json
|
|
1222
|
+
{
|
|
1223
|
+
"paramName": "$filter.filterId.value"
|
|
1224
|
+
}
|
|
1225
|
+
\`\`\`
|
|
1141
1226
|
|
|
1142
|
-
|
|
1227
|
+
For DateRangePicker:
|
|
1228
|
+
- \`$filter.filterId.startDate\`
|
|
1229
|
+
- \`$filter.filterId.endDate\`
|
|
1230
|
+
|
|
1231
|
+
For Dropdown/MultiSelect:
|
|
1232
|
+
- \`$filter.filterId.value\`
|
|
1233
|
+
|
|
1234
|
+
For SearchBox:
|
|
1235
|
+
- \`$filter.filterId.searchText\`
|
|
1236
|
+
|
|
1237
|
+
### Database Query Rules
|
|
1238
|
+
{{DATABASE_RULES}}
|
|
1239
|
+
|
|
1240
|
+
## Output Format
|
|
1241
|
+
|
|
1242
|
+
You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
1243
|
+
|
|
1244
|
+
{
|
|
1245
|
+
"filterComponent": {
|
|
1246
|
+
"componentId": "filter_unique_id",
|
|
1247
|
+
"componentType": "DateRangePicker | Dropdown | etc.",
|
|
1248
|
+
"componentName": "Filter Display Name",
|
|
1249
|
+
"props": {
|
|
1250
|
+
"filterId": "filter_unique_id",
|
|
1251
|
+
"label": "Filter Label",
|
|
1252
|
+
"defaultValue": null,
|
|
1253
|
+
"options": []
|
|
1254
|
+
}
|
|
1255
|
+
},
|
|
1256
|
+
"updatedComponents": [
|
|
1257
|
+
{
|
|
1258
|
+
"componentId": "existing_component_id",
|
|
1259
|
+
"componentType": "existing_type",
|
|
1260
|
+
"componentName": "existing_name",
|
|
1261
|
+
"props": {
|
|
1262
|
+
// RETURN THE COMPLETE PROPS OBJECT
|
|
1263
|
+
// Copy ALL existing props and only modify the necessary fields
|
|
1264
|
+
"title": "Existing Title",
|
|
1265
|
+
"description": "Existing Description",
|
|
1266
|
+
"config": {},
|
|
1267
|
+
"query": {
|
|
1268
|
+
"sql": "SELECT ... WHERE column BETWEEN $startDate AND $endDate",
|
|
1269
|
+
"params": {
|
|
1270
|
+
"existingParam": "existing_value",
|
|
1271
|
+
"startDate": "$filter.filterId.startDate",
|
|
1272
|
+
"endDate": "$filter.filterId.endDate"
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
],
|
|
1278
|
+
"filterBindings": {
|
|
1279
|
+
"startDate": "$filter.filterId.startDate",
|
|
1280
|
+
"endDate": "$filter.filterId.endDate"
|
|
1281
|
+
},
|
|
1282
|
+
"reasoning": "Explanation of filter choice and how components were updated"
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
**CRITICAL:**
|
|
1286
|
+
- Return ONLY valid JSON (no markdown code blocks, no text before/after)
|
|
1287
|
+
- **RETURN COMPLETE PROPS**: Copy ALL existing props from each component, only modify what's needed for the filter
|
|
1288
|
+
- Do NOT omit existing props like title, description, config - include them unchanged
|
|
1289
|
+
- Only modify query.sql (add WHERE conditions) and query.params (add filter bindings)
|
|
1290
|
+
- For externalTool, only add filter params to the params object
|
|
1291
|
+
- Use consistent param naming across all components
|
|
1292
|
+
- Ensure SQL syntax is valid with the new filter conditions
|
|
1293
|
+
|
|
1294
|
+
## Database Schema
|
|
1143
1295
|
{{SCHEMA_DOC}}
|
|
1144
1296
|
|
|
1145
|
-
|
|
1297
|
+
## Available External Tools
|
|
1146
1298
|
{{AVAILABLE_TOOLS}}
|
|
1147
1299
|
|
|
1148
|
-
|
|
1149
|
-
{{AVAILABLE_COMPONENTS}}
|
|
1300
|
+
## Available Filter Components
|
|
1301
|
+
{{AVAILABLE_COMPONENTS}}
|
|
1302
|
+
|
|
1303
|
+
## Existing Dashboard Components
|
|
1304
|
+
{{EXISTING_COMPONENTS}}
|
|
1305
|
+
|
|
1306
|
+
---
|
|
1307
|
+
|
|
1308
|
+
## CONTEXT`,
|
|
1150
1309
|
user: `{{USER_PROMPT}}`
|
|
1151
1310
|
}
|
|
1152
1311
|
};
|
|
@@ -1854,6 +2013,7 @@ var AuthVerifyRequestMessageSchema = z3.object({
|
|
|
1854
2013
|
});
|
|
1855
2014
|
var UserPromptRequestPayloadSchema = z3.object({
|
|
1856
2015
|
prompt: z3.string(),
|
|
2016
|
+
userId: z3.string().optional(),
|
|
1857
2017
|
SA_RUNTIME: z3.object({
|
|
1858
2018
|
threadId: z3.string(),
|
|
1859
2019
|
uiBlockId: z3.string()
|
|
@@ -1868,6 +2028,7 @@ var UserPromptRequestMessageSchema = z3.object({
|
|
|
1868
2028
|
});
|
|
1869
2029
|
var UserPromptSuggestionsPayloadSchema = z3.object({
|
|
1870
2030
|
prompt: z3.string(),
|
|
2031
|
+
userId: z3.string().optional(),
|
|
1871
2032
|
limit: z3.number().int().positive().default(5),
|
|
1872
2033
|
similarityThreshold: z3.number().min(0).max(1).default(0.4)
|
|
1873
2034
|
});
|
|
@@ -1957,6 +2118,7 @@ var UILogsMessageSchema = z3.object({
|
|
|
1957
2118
|
payload: UILogsPayloadSchema
|
|
1958
2119
|
});
|
|
1959
2120
|
var ActionsRequestPayloadSchema = z3.object({
|
|
2121
|
+
userId: z3.string().optional(),
|
|
1960
2122
|
SA_RUNTIME: z3.object({
|
|
1961
2123
|
threadId: z3.string(),
|
|
1962
2124
|
uiBlockId: z3.string()
|
|
@@ -2157,10 +2319,15 @@ var KbNodesRequestMessageSchema = z3.object({
|
|
|
2157
2319
|
});
|
|
2158
2320
|
var DashCompRequestPayloadSchema = z3.object({
|
|
2159
2321
|
prompt: z3.string(),
|
|
2322
|
+
userId: z3.string().optional(),
|
|
2160
2323
|
SA_RUNTIME: z3.object({
|
|
2161
2324
|
threadId: z3.string().optional(),
|
|
2162
2325
|
uiBlockId: z3.string().optional()
|
|
2163
|
-
}).optional()
|
|
2326
|
+
}).optional(),
|
|
2327
|
+
/** Existing components in the dashboard (for update/filter operations) */
|
|
2328
|
+
existingComponents: z3.array(ComponentSchema).optional(),
|
|
2329
|
+
/** Request type: create (new component), update (modify existing), filter (create filter + update components) */
|
|
2330
|
+
req_type: z3.enum(["create", "update", "filter"]).optional()
|
|
2164
2331
|
});
|
|
2165
2332
|
var DashCompRequestMessageSchema = z3.object({
|
|
2166
2333
|
id: z3.string(),
|
|
@@ -7303,7 +7470,7 @@ var CONTEXT_CONFIG = {
|
|
|
7303
7470
|
};
|
|
7304
7471
|
|
|
7305
7472
|
// src/handlers/user-prompt-request.ts
|
|
7306
|
-
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools
|
|
7473
|
+
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools) => {
|
|
7307
7474
|
const errors = [];
|
|
7308
7475
|
logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
|
|
7309
7476
|
const parseResult = UserPromptRequestMessageSchema.safeParse(data);
|
|
@@ -7317,6 +7484,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
7317
7484
|
const userPromptRequest = parseResult.data;
|
|
7318
7485
|
const { id, payload } = userPromptRequest;
|
|
7319
7486
|
const prompt = payload.prompt;
|
|
7487
|
+
const userId = payload.userId;
|
|
7320
7488
|
const SA_RUNTIME = payload.SA_RUNTIME;
|
|
7321
7489
|
const wsId = userPromptRequest.from.id || "unknown";
|
|
7322
7490
|
const promptContext = `User Prompt: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
@@ -7489,8 +7657,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
7489
7657
|
wsId
|
|
7490
7658
|
};
|
|
7491
7659
|
};
|
|
7492
|
-
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools
|
|
7493
|
-
const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools
|
|
7660
|
+
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools) {
|
|
7661
|
+
const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools);
|
|
7494
7662
|
sendDataResponse4(
|
|
7495
7663
|
response.id || data.id,
|
|
7496
7664
|
{
|
|
@@ -7522,11 +7690,11 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
|
7522
7690
|
|
|
7523
7691
|
// src/handlers/user-prompt-suggestions.ts
|
|
7524
7692
|
init_logger();
|
|
7525
|
-
async function handleUserPromptSuggestions(data, components, sendMessage, collections
|
|
7693
|
+
async function handleUserPromptSuggestions(data, components, sendMessage, collections) {
|
|
7526
7694
|
try {
|
|
7527
7695
|
const request = UserPromptSuggestionsMessageSchema.parse(data);
|
|
7528
7696
|
const { id, payload, from } = request;
|
|
7529
|
-
const { prompt, limit = 10 } = payload;
|
|
7697
|
+
const { prompt, userId, limit = 10 } = payload;
|
|
7530
7698
|
const wsId = from.id;
|
|
7531
7699
|
logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Processing user prompt suggestions: ${prompt}`);
|
|
7532
7700
|
if (!prompt || prompt.trim().length === 0) {
|
|
@@ -10166,40 +10334,108 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10166
10334
|
sendMessage(response);
|
|
10167
10335
|
}
|
|
10168
10336
|
|
|
10169
|
-
// src/
|
|
10337
|
+
// src/dashComp/index.ts
|
|
10170
10338
|
init_logger();
|
|
10171
|
-
|
|
10339
|
+
|
|
10340
|
+
// src/dashComp/types.ts
|
|
10172
10341
|
var DEFAULT_DASH_COMP_MODELS = {
|
|
10173
10342
|
anthropic: "anthropic/claude-haiku-4-5-20251001",
|
|
10174
10343
|
gemini: "gemini/gemini-3-flash-preview",
|
|
10175
10344
|
openai: "openai/gpt-4o-mini",
|
|
10176
10345
|
groq: "groq/llama-3.3-70b-versatile"
|
|
10177
10346
|
};
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
|
|
10184
|
-
|
|
10185
|
-
|
|
10347
|
+
|
|
10348
|
+
// src/dashComp/utils.ts
|
|
10349
|
+
function getApiKeyAndModel(anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, dashCompModels) {
|
|
10350
|
+
const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
|
|
10351
|
+
let apiKey;
|
|
10352
|
+
let model;
|
|
10353
|
+
if (dashCompModels?.model) {
|
|
10354
|
+
model = dashCompModels.model;
|
|
10355
|
+
const modelProvider = model.split("/")[0];
|
|
10356
|
+
if (modelProvider === "anthropic") apiKey = anthropicApiKey;
|
|
10357
|
+
else if (modelProvider === "gemini") apiKey = geminiApiKey;
|
|
10358
|
+
else if (modelProvider === "openai") apiKey = openaiApiKey;
|
|
10359
|
+
else if (modelProvider === "groq") apiKey = groqApiKey;
|
|
10360
|
+
} else {
|
|
10361
|
+
for (const provider of providers) {
|
|
10362
|
+
if (provider === "anthropic" && anthropicApiKey) {
|
|
10363
|
+
apiKey = anthropicApiKey;
|
|
10364
|
+
model = DEFAULT_DASH_COMP_MODELS.anthropic;
|
|
10365
|
+
break;
|
|
10366
|
+
} else if (provider === "gemini" && geminiApiKey) {
|
|
10367
|
+
apiKey = geminiApiKey;
|
|
10368
|
+
model = DEFAULT_DASH_COMP_MODELS.gemini;
|
|
10369
|
+
break;
|
|
10370
|
+
} else if (provider === "openai" && openaiApiKey) {
|
|
10371
|
+
apiKey = openaiApiKey;
|
|
10372
|
+
model = DEFAULT_DASH_COMP_MODELS.openai;
|
|
10373
|
+
break;
|
|
10374
|
+
} else if (provider === "groq" && groqApiKey) {
|
|
10375
|
+
apiKey = groqApiKey;
|
|
10376
|
+
model = DEFAULT_DASH_COMP_MODELS.groq;
|
|
10377
|
+
break;
|
|
10378
|
+
}
|
|
10379
|
+
}
|
|
10380
|
+
}
|
|
10381
|
+
return { apiKey, model };
|
|
10382
|
+
}
|
|
10383
|
+
function formatComponentsForPrompt(components) {
|
|
10384
|
+
if (!components || components.length === 0) {
|
|
10385
|
+
return "No components available";
|
|
10386
|
+
}
|
|
10387
|
+
return components.map((comp, idx) => {
|
|
10388
|
+
const keywords = comp.keywords ? comp.keywords.join(", ") : "";
|
|
10389
|
+
const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
|
|
10390
|
+
return `${idx + 1}. ID: ${comp.id}
|
|
10186
10391
|
Name: ${comp.name}
|
|
10187
10392
|
Type: ${comp.type}
|
|
10188
10393
|
Description: ${comp.description || "No description"}
|
|
10189
10394
|
Keywords: ${keywords}
|
|
10190
10395
|
Props Structure: ${propsPreview}`;
|
|
10191
|
-
|
|
10396
|
+
}).join("\n\n");
|
|
10397
|
+
}
|
|
10398
|
+
function formatToolsForPrompt(tools) {
|
|
10399
|
+
if (!tools || tools.length === 0) {
|
|
10400
|
+
return "No external tools available.";
|
|
10192
10401
|
}
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
10197
|
-
return `${idx + 1}. ID: ${tool.id}
|
|
10402
|
+
return tools.map((tool, idx) => {
|
|
10403
|
+
const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
10404
|
+
return `${idx + 1}. ID: ${tool.id}
|
|
10198
10405
|
Name: ${tool.name}
|
|
10199
10406
|
Description: ${tool.description}
|
|
10200
10407
|
Parameters: { ${paramsStr} }`;
|
|
10201
|
-
|
|
10408
|
+
}).join("\n\n");
|
|
10409
|
+
}
|
|
10410
|
+
function formatExistingComponentsForPrompt(existingComponents) {
|
|
10411
|
+
if (!existingComponents || existingComponents.length === 0) {
|
|
10412
|
+
return "No existing components in dashboard";
|
|
10202
10413
|
}
|
|
10414
|
+
return JSON.stringify(existingComponents, null, 2);
|
|
10415
|
+
}
|
|
10416
|
+
function sendDashCompResponse(id, res, sendMessage, clientId) {
|
|
10417
|
+
const response = {
|
|
10418
|
+
id,
|
|
10419
|
+
type: "DASH_COMP_RES",
|
|
10420
|
+
from: { type: "data-agent" },
|
|
10421
|
+
to: {
|
|
10422
|
+
type: "runtime",
|
|
10423
|
+
id: clientId
|
|
10424
|
+
},
|
|
10425
|
+
payload: {
|
|
10426
|
+
...res
|
|
10427
|
+
}
|
|
10428
|
+
};
|
|
10429
|
+
sendMessage(response);
|
|
10430
|
+
}
|
|
10431
|
+
|
|
10432
|
+
// src/dashComp/pick-component.ts
|
|
10433
|
+
init_logger();
|
|
10434
|
+
init_prompt_loader();
|
|
10435
|
+
async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, _collections, tools, dashCompModels) {
|
|
10436
|
+
const errors = [];
|
|
10437
|
+
const availableComponentsText = formatComponentsForPrompt(components);
|
|
10438
|
+
const availableToolsText = formatToolsForPrompt(tools);
|
|
10203
10439
|
try {
|
|
10204
10440
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
10205
10441
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
@@ -10211,38 +10447,14 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10211
10447
|
AVAILABLE_TOOLS: availableToolsText
|
|
10212
10448
|
});
|
|
10213
10449
|
logger.debug("[DASH_COMP_REQ] Loaded dash-comp-picker prompts with schema and tools");
|
|
10214
|
-
const
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
else if (modelProvider === "openai") apiKey = openaiApiKey;
|
|
10223
|
-
else if (modelProvider === "groq") apiKey = groqApiKey;
|
|
10224
|
-
logger.info(`[DASH_COMP_REQ] Using configured model: ${model}`);
|
|
10225
|
-
} else {
|
|
10226
|
-
for (const provider of providers) {
|
|
10227
|
-
if (provider === "anthropic" && anthropicApiKey) {
|
|
10228
|
-
apiKey = anthropicApiKey;
|
|
10229
|
-
model = DEFAULT_DASH_COMP_MODELS.anthropic;
|
|
10230
|
-
break;
|
|
10231
|
-
} else if (provider === "gemini" && geminiApiKey) {
|
|
10232
|
-
apiKey = geminiApiKey;
|
|
10233
|
-
model = DEFAULT_DASH_COMP_MODELS.gemini;
|
|
10234
|
-
break;
|
|
10235
|
-
} else if (provider === "openai" && openaiApiKey) {
|
|
10236
|
-
apiKey = openaiApiKey;
|
|
10237
|
-
model = DEFAULT_DASH_COMP_MODELS.openai;
|
|
10238
|
-
break;
|
|
10239
|
-
} else if (provider === "groq" && groqApiKey) {
|
|
10240
|
-
apiKey = groqApiKey;
|
|
10241
|
-
model = DEFAULT_DASH_COMP_MODELS.groq;
|
|
10242
|
-
break;
|
|
10243
|
-
}
|
|
10244
|
-
}
|
|
10245
|
-
}
|
|
10450
|
+
const { apiKey, model } = getApiKeyAndModel(
|
|
10451
|
+
anthropicApiKey,
|
|
10452
|
+
groqApiKey,
|
|
10453
|
+
geminiApiKey,
|
|
10454
|
+
openaiApiKey,
|
|
10455
|
+
llmProviders,
|
|
10456
|
+
dashCompModels
|
|
10457
|
+
);
|
|
10246
10458
|
if (!apiKey || !model) {
|
|
10247
10459
|
errors.push("No API key available for any LLM provider");
|
|
10248
10460
|
return { success: false, errors };
|
|
@@ -10302,7 +10514,8 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10302
10514
|
data: {
|
|
10303
10515
|
component: finalComponent,
|
|
10304
10516
|
reasoning: result.reasoning || "Component selected based on user prompt",
|
|
10305
|
-
dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none"
|
|
10517
|
+
dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none",
|
|
10518
|
+
isUpdate: result.isUpdate || false
|
|
10306
10519
|
},
|
|
10307
10520
|
errors: []
|
|
10308
10521
|
};
|
|
@@ -10318,6 +10531,84 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10318
10531
|
return { success: false, errors };
|
|
10319
10532
|
}
|
|
10320
10533
|
}
|
|
10534
|
+
|
|
10535
|
+
// src/dashComp/create-filter.ts
|
|
10536
|
+
init_logger();
|
|
10537
|
+
init_prompt_loader();
|
|
10538
|
+
async function createFilterWithLLM(prompt, components, existingComponents, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, tools, dashCompModels) {
|
|
10539
|
+
const errors = [];
|
|
10540
|
+
try {
|
|
10541
|
+
const filterComponents = components.filter((c) => c.type.startsWith("Filter"));
|
|
10542
|
+
if (filterComponents.length === 0) {
|
|
10543
|
+
errors.push("No filter components available");
|
|
10544
|
+
return { success: false, errors };
|
|
10545
|
+
}
|
|
10546
|
+
logger.debug(`[DASH_COMP_REQ:FILTER] Found ${filterComponents.length} filter components`);
|
|
10547
|
+
const schemaDoc = schema.generateSchemaDocumentation();
|
|
10548
|
+
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
10549
|
+
const prompts = await promptLoader.loadPrompts("dash-filter-picker", {
|
|
10550
|
+
USER_PROMPT: prompt,
|
|
10551
|
+
AVAILABLE_COMPONENTS: formatComponentsForPrompt(filterComponents),
|
|
10552
|
+
EXISTING_COMPONENTS: formatExistingComponentsForPrompt(existingComponents),
|
|
10553
|
+
SCHEMA_DOC: schemaDoc || "No database schema available",
|
|
10554
|
+
DATABASE_RULES: databaseRules,
|
|
10555
|
+
AVAILABLE_TOOLS: formatToolsForPrompt(tools)
|
|
10556
|
+
});
|
|
10557
|
+
logger.debug("[DASH_COMP_REQ:FILTER] Loaded dash-filter-picker prompts");
|
|
10558
|
+
const { apiKey, model } = getApiKeyAndModel(
|
|
10559
|
+
anthropicApiKey,
|
|
10560
|
+
groqApiKey,
|
|
10561
|
+
geminiApiKey,
|
|
10562
|
+
openaiApiKey,
|
|
10563
|
+
llmProviders,
|
|
10564
|
+
dashCompModels
|
|
10565
|
+
);
|
|
10566
|
+
if (!apiKey || !model) {
|
|
10567
|
+
errors.push("No API key available for any LLM provider");
|
|
10568
|
+
return { success: false, errors };
|
|
10569
|
+
}
|
|
10570
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10571
|
+
const result = await LLM.stream(
|
|
10572
|
+
{ sys: prompts.system, user: prompts.user },
|
|
10573
|
+
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10574
|
+
true
|
|
10575
|
+
);
|
|
10576
|
+
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10577
|
+
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10578
|
+
if (!result.filterComponent) {
|
|
10579
|
+
errors.push("Invalid LLM response: missing filterComponent");
|
|
10580
|
+
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", "Invalid LLM response structure", {
|
|
10581
|
+
prompt,
|
|
10582
|
+
result,
|
|
10583
|
+
missingFields: { filterComponent: !result.filterComponent }
|
|
10584
|
+
});
|
|
10585
|
+
return { success: false, errors };
|
|
10586
|
+
}
|
|
10587
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10588
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Updated ${result.updatedComponents?.length || 0} components`);
|
|
10589
|
+
return {
|
|
10590
|
+
success: true,
|
|
10591
|
+
data: {
|
|
10592
|
+
filterComponent: result.filterComponent,
|
|
10593
|
+
updatedComponents: result.updatedComponents || [],
|
|
10594
|
+
filterBindings: result.filterBindings || {},
|
|
10595
|
+
reasoning: result.reasoning || "Filter created based on user prompt"
|
|
10596
|
+
},
|
|
10597
|
+
errors: []
|
|
10598
|
+
};
|
|
10599
|
+
} catch (error) {
|
|
10600
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
10601
|
+
logger.error(`[DASH_COMP_REQ:FILTER] Error creating filter: ${errorMsg}`);
|
|
10602
|
+
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", error instanceof Error ? error : new Error(errorMsg), {
|
|
10603
|
+
prompt,
|
|
10604
|
+
existingComponentsCount: existingComponents.length
|
|
10605
|
+
});
|
|
10606
|
+
errors.push(errorMsg);
|
|
10607
|
+
return { success: false, errors };
|
|
10608
|
+
}
|
|
10609
|
+
}
|
|
10610
|
+
|
|
10611
|
+
// src/dashComp/index.ts
|
|
10321
10612
|
var processDashCompRequest = async (data, components, _sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, dashCompModels) => {
|
|
10322
10613
|
const errors = [];
|
|
10323
10614
|
logger.debug("[DASH_COMP_REQ] Parsing incoming message data");
|
|
@@ -10332,17 +10623,25 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
10332
10623
|
const dashCompRequest = parseResult.data;
|
|
10333
10624
|
const { id, payload } = dashCompRequest;
|
|
10334
10625
|
const prompt = payload.prompt;
|
|
10626
|
+
const reqType = payload.req_type || "create";
|
|
10627
|
+
const existingComponents = payload.existingComponents || [];
|
|
10335
10628
|
const wsId = dashCompRequest.from.id || "unknown";
|
|
10336
|
-
const promptContext = `DASH_COMP: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
10629
|
+
const promptContext = `DASH_COMP[${reqType}]: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
10337
10630
|
llmUsageLogger.resetLogFile(promptContext);
|
|
10338
10631
|
if (!prompt) {
|
|
10339
10632
|
errors.push("Prompt is required");
|
|
10340
10633
|
}
|
|
10634
|
+
if (reqType === "filter" && existingComponents.length === 0) {
|
|
10635
|
+
errors.push("Filter request requires existingComponents");
|
|
10636
|
+
}
|
|
10341
10637
|
if (errors.length > 0) {
|
|
10342
10638
|
return { success: false, errors, id, wsId };
|
|
10343
10639
|
}
|
|
10344
|
-
logger.info(`[DASH_COMP_REQ] Processing request for prompt: "${prompt.substring(0, 50)}..."`);
|
|
10640
|
+
logger.info(`[DASH_COMP_REQ] Processing ${reqType} request for prompt: "${prompt.substring(0, 50)}..."`);
|
|
10345
10641
|
logger.info(`[DASH_COMP_REQ] Available: ${components?.length || 0} components, ${tools?.length || 0} tools`);
|
|
10642
|
+
if (existingComponents.length > 0) {
|
|
10643
|
+
logger.info(`[DASH_COMP_REQ] Existing components in dashboard: ${existingComponents.length}`);
|
|
10644
|
+
}
|
|
10346
10645
|
if (!components || components.length === 0) {
|
|
10347
10646
|
logger.warn("[DASH_COMP_REQ] No components available");
|
|
10348
10647
|
return {
|
|
@@ -10352,19 +10651,35 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
10352
10651
|
wsId
|
|
10353
10652
|
};
|
|
10354
10653
|
}
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10654
|
+
let llmResponse;
|
|
10655
|
+
if (reqType === "filter") {
|
|
10656
|
+
llmResponse = await createFilterWithLLM(
|
|
10657
|
+
prompt,
|
|
10658
|
+
components,
|
|
10659
|
+
existingComponents,
|
|
10660
|
+
anthropicApiKey,
|
|
10661
|
+
groqApiKey,
|
|
10662
|
+
geminiApiKey,
|
|
10663
|
+
openaiApiKey,
|
|
10664
|
+
llmProviders,
|
|
10665
|
+
tools,
|
|
10666
|
+
dashCompModels
|
|
10667
|
+
);
|
|
10668
|
+
} else {
|
|
10669
|
+
llmResponse = await pickComponentWithLLM(
|
|
10670
|
+
prompt,
|
|
10671
|
+
components,
|
|
10672
|
+
anthropicApiKey,
|
|
10673
|
+
groqApiKey,
|
|
10674
|
+
geminiApiKey,
|
|
10675
|
+
openaiApiKey,
|
|
10676
|
+
llmProviders,
|
|
10677
|
+
collections,
|
|
10678
|
+
tools,
|
|
10679
|
+
dashCompModels
|
|
10680
|
+
);
|
|
10681
|
+
}
|
|
10682
|
+
llmUsageLogger.logSessionSummary(`DASH_COMP[${reqType}]: ${prompt?.substring(0, 30)}`);
|
|
10368
10683
|
return {
|
|
10369
10684
|
success: llmResponse.success,
|
|
10370
10685
|
data: llmResponse.data,
|
|
@@ -10397,22 +10712,7 @@ async function handleDashCompRequest(data, components, sendMessage, anthropicApi
|
|
|
10397
10712
|
sendMessage,
|
|
10398
10713
|
response.wsId || data.from?.id
|
|
10399
10714
|
);
|
|
10400
|
-
}
|
|
10401
|
-
function sendDashCompResponse(id, res, sendMessage, clientId) {
|
|
10402
|
-
const response = {
|
|
10403
|
-
id,
|
|
10404
|
-
type: "DASH_COMP_RES",
|
|
10405
|
-
from: { type: "data-agent" },
|
|
10406
|
-
to: {
|
|
10407
|
-
type: "runtime",
|
|
10408
|
-
id: clientId
|
|
10409
|
-
},
|
|
10410
|
-
payload: {
|
|
10411
|
-
...res
|
|
10412
|
-
}
|
|
10413
|
-
};
|
|
10414
|
-
sendMessage(response);
|
|
10415
|
-
logger.info(`[DASH_COMP_REQ] Response sent to client ${clientId}`);
|
|
10715
|
+
logger.info(`[DASH_COMP_REQ] Response sent to client ${response.wsId || data.from?.id}`);
|
|
10416
10716
|
}
|
|
10417
10717
|
|
|
10418
10718
|
// src/auth/user-manager.ts
|
|
@@ -11260,7 +11560,6 @@ var SuperatomSDK = class {
|
|
|
11260
11560
|
}
|
|
11261
11561
|
this.apiKey = config.apiKey;
|
|
11262
11562
|
this.projectId = config.projectId;
|
|
11263
|
-
this.userId = config.userId || "anonymous";
|
|
11264
11563
|
this.type = config.type || "data-agent";
|
|
11265
11564
|
this.bundleDir = config.bundleDir;
|
|
11266
11565
|
this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;
|
|
@@ -11362,7 +11661,6 @@ var SuperatomSDK = class {
|
|
|
11362
11661
|
url.searchParams.set("apiKey", this.apiKey);
|
|
11363
11662
|
}
|
|
11364
11663
|
url.searchParams.set("projectId", this.projectId);
|
|
11365
|
-
url.searchParams.set("userId", this.userId);
|
|
11366
11664
|
url.searchParams.set("type", this.type);
|
|
11367
11665
|
logger.info(`Connecting to WebSocket: ${url.toString()}`);
|
|
11368
11666
|
this.ws = createWebSocket(url.toString());
|
|
@@ -11423,7 +11721,7 @@ var SuperatomSDK = class {
|
|
|
11423
11721
|
});
|
|
11424
11722
|
break;
|
|
11425
11723
|
case "USER_PROMPT_REQ":
|
|
11426
|
-
handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools
|
|
11724
|
+
handleUserPromptRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
|
|
11427
11725
|
logger.error("Failed to handle user prompt request:", error);
|
|
11428
11726
|
});
|
|
11429
11727
|
break;
|
|
@@ -11433,7 +11731,7 @@ var SuperatomSDK = class {
|
|
|
11433
11731
|
});
|
|
11434
11732
|
break;
|
|
11435
11733
|
case "USER_PROMPT_SUGGESTIONS_REQ":
|
|
11436
|
-
handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections
|
|
11734
|
+
handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections).catch((error) => {
|
|
11437
11735
|
logger.error("Failed to handle user prompt suggestions request:", error);
|
|
11438
11736
|
});
|
|
11439
11737
|
break;
|