@superatomai/sdk-node 0.0.42 → 0.0.44
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 +380 -105
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +380 -105
- 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,142 @@ 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
|
|
1178
|
+
2. **Update existing components** with dynamic title/description interpolation if needed
|
|
1179
|
+
3. **Preserve all existing props** - the filter system handles param merging at runtime
|
|
1180
|
+
|
|
1181
|
+
## How The Filter System Works
|
|
1182
|
+
|
|
1183
|
+
1. Filter component has a \`filters\` array with preset options, each containing \`label\`, \`value\`, and \`params\`
|
|
1184
|
+
2. When user selects a filter option, those \`params\` are broadcast to all listening components
|
|
1185
|
+
3. Components automatically merge filter params with their existing params (filter values override defaults)
|
|
1186
|
+
4. Component titles/descriptions can use \`{%filterKeyLabel%}\` syntax for dynamic text
|
|
1187
|
+
|
|
1188
|
+
## Filter Component Structure
|
|
1189
|
+
|
|
1190
|
+
The filter uses DynamicFilterDropdown with:
|
|
1191
|
+
- **filterKey**: Identifier for label interpolation (e.g., "period", "name", "category")
|
|
1192
|
+
- **filters**: Array of options with label, value, params, and optionally isDefault
|
|
1193
|
+
- **defaultValue**: The value of the initially selected option
|
|
1194
|
+
|
|
1195
|
+
## Dynamic Title/Description Interpolation
|
|
1196
|
+
|
|
1197
|
+
Use \`{%filterKeyLabel%}\` syntax for dynamic text:
|
|
1198
|
+
- filterKey "period" \u2192 use \`{%periodLabel%}\` in titles/descriptions
|
|
1199
|
+
- filterKey "name" \u2192 use \`{%nameLabel%}\` in titles/descriptions
|
|
1200
|
+
- Example: \`"{%periodLabel%} Revenue"\` becomes "Q3 2025 Revenue" when user selects "Q3 2025"
|
|
1201
|
+
|
|
1202
|
+
**CRITICAL Template Syntax:**
|
|
1203
|
+
- Use \`{%keyLabel%}\` format (percent signs, key + "Label" suffix)
|
|
1204
|
+
- Do NOT use \`{{...}}\` or \`$...\` syntax - these don't work
|
|
1205
|
+
|
|
1206
|
+
## Updating Existing Components
|
|
1207
|
+
|
|
1208
|
+
**IMPORTANT - Parameter Handling:**
|
|
1209
|
+
- Do NOT change existing parameter values to placeholders
|
|
1210
|
+
- Keep all existing/default parameter values as they are
|
|
1211
|
+
- The filter system MERGES params at runtime: filter params override component defaults
|
|
1212
|
+
|
|
1213
|
+
**What to modify in existing components:**
|
|
1214
|
+
- Modify \`title\` for \`{%filterKeyLabel%}\` interpolation (only if title exists)
|
|
1215
|
+
- Modify \`description\` for interpolation (only if description exists)
|
|
1216
|
+
- Modify other props only if specifically needed for the filter to function
|
|
1217
|
+
- Copy ALL other props exactly as provided
|
|
1218
|
+
|
|
1219
|
+
### Database Query Rules
|
|
1220
|
+
{{DATABASE_RULES}}
|
|
1221
|
+
|
|
1222
|
+
## Output Format
|
|
1223
|
+
|
|
1224
|
+
You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
1225
|
+
|
|
1226
|
+
{
|
|
1227
|
+
"filterComponent": {
|
|
1228
|
+
"id": "filter-<descriptive-id>",
|
|
1229
|
+
"name": "DynamicFilterDropdown",
|
|
1230
|
+
"type": "FilterDropdown",
|
|
1231
|
+
"props": {
|
|
1232
|
+
"title": "<Filter display title>",
|
|
1233
|
+
"filterKey": "<key_for_interpolation>",
|
|
1234
|
+
"defaultValue": "<default_option_value>",
|
|
1235
|
+
"filters": [
|
|
1236
|
+
{
|
|
1237
|
+
"label": "<Display label for option>",
|
|
1238
|
+
"value": "<unique_option_value>",
|
|
1239
|
+
"params": { "<param_key>": "<actual_value>", "...": "..." },
|
|
1240
|
+
"isDefault": true
|
|
1241
|
+
}
|
|
1242
|
+
]
|
|
1243
|
+
}
|
|
1244
|
+
},
|
|
1245
|
+
"updatedComponents": [
|
|
1246
|
+
{
|
|
1247
|
+
"id": "<existing_component_id>",
|
|
1248
|
+
"name": "<existing_component_name>",
|
|
1249
|
+
"type": "<existing_type>",
|
|
1250
|
+
"props": {
|
|
1251
|
+
"...all existing props preserved...",
|
|
1252
|
+
"title": "{%<filterKey>Label%} <rest of title>",
|
|
1253
|
+
"description": "<updated if needed>"
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
],
|
|
1257
|
+
"filterBindings": {
|
|
1258
|
+
"<param_key>": "Describes which filter param this binds to"
|
|
1259
|
+
},
|
|
1260
|
+
"reasoning": "Explanation of filter choice and what params it provides"
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
**CRITICAL RULES:**
|
|
1264
|
+
1. Return ONLY valid JSON (no markdown code blocks)
|
|
1265
|
+
2. **COPY ALL existing props** - modify title/description for interpolation only if they exist
|
|
1266
|
+
3. **DO NOT change parameter values** - keep existing defaults, filter merges at runtime
|
|
1267
|
+
4. Use \`{%filterKeyLabel%}\` for dynamic text (NOT \`{{...}}\` or \`$...\`)
|
|
1268
|
+
5. Filter \`params\` must have ACTUAL values (real dates, strings), not placeholders
|
|
1269
|
+
6. Each filter option needs: label, value, params (and optionally isDefault)
|
|
1141
1270
|
|
|
1142
|
-
|
|
1271
|
+
## Database Schema
|
|
1143
1272
|
{{SCHEMA_DOC}}
|
|
1144
1273
|
|
|
1145
|
-
|
|
1274
|
+
## Available External Tools
|
|
1146
1275
|
{{AVAILABLE_TOOLS}}
|
|
1147
1276
|
|
|
1148
|
-
|
|
1149
|
-
{{AVAILABLE_COMPONENTS}}
|
|
1277
|
+
## Available Filter Components
|
|
1278
|
+
{{AVAILABLE_COMPONENTS}}
|
|
1279
|
+
|
|
1280
|
+
## Existing Dashboard Components
|
|
1281
|
+
{{EXISTING_COMPONENTS}}
|
|
1282
|
+
|
|
1283
|
+
---
|
|
1284
|
+
|
|
1285
|
+
## CONTEXT`,
|
|
1150
1286
|
user: `{{USER_PROMPT}}`
|
|
1151
1287
|
}
|
|
1152
1288
|
};
|
|
@@ -1854,6 +1990,7 @@ var AuthVerifyRequestMessageSchema = z3.object({
|
|
|
1854
1990
|
});
|
|
1855
1991
|
var UserPromptRequestPayloadSchema = z3.object({
|
|
1856
1992
|
prompt: z3.string(),
|
|
1993
|
+
userId: z3.string().optional(),
|
|
1857
1994
|
SA_RUNTIME: z3.object({
|
|
1858
1995
|
threadId: z3.string(),
|
|
1859
1996
|
uiBlockId: z3.string()
|
|
@@ -1868,6 +2005,7 @@ var UserPromptRequestMessageSchema = z3.object({
|
|
|
1868
2005
|
});
|
|
1869
2006
|
var UserPromptSuggestionsPayloadSchema = z3.object({
|
|
1870
2007
|
prompt: z3.string(),
|
|
2008
|
+
userId: z3.string().optional(),
|
|
1871
2009
|
limit: z3.number().int().positive().default(5),
|
|
1872
2010
|
similarityThreshold: z3.number().min(0).max(1).default(0.4)
|
|
1873
2011
|
});
|
|
@@ -1957,6 +2095,7 @@ var UILogsMessageSchema = z3.object({
|
|
|
1957
2095
|
payload: UILogsPayloadSchema
|
|
1958
2096
|
});
|
|
1959
2097
|
var ActionsRequestPayloadSchema = z3.object({
|
|
2098
|
+
userId: z3.string().optional(),
|
|
1960
2099
|
SA_RUNTIME: z3.object({
|
|
1961
2100
|
threadId: z3.string(),
|
|
1962
2101
|
uiBlockId: z3.string()
|
|
@@ -2157,10 +2296,15 @@ var KbNodesRequestMessageSchema = z3.object({
|
|
|
2157
2296
|
});
|
|
2158
2297
|
var DashCompRequestPayloadSchema = z3.object({
|
|
2159
2298
|
prompt: z3.string(),
|
|
2299
|
+
userId: z3.string().optional(),
|
|
2160
2300
|
SA_RUNTIME: z3.object({
|
|
2161
2301
|
threadId: z3.string().optional(),
|
|
2162
2302
|
uiBlockId: z3.string().optional()
|
|
2163
|
-
}).optional()
|
|
2303
|
+
}).optional(),
|
|
2304
|
+
/** Existing components in the dashboard (for update/filter operations) */
|
|
2305
|
+
existingComponents: z3.array(ComponentSchema).optional(),
|
|
2306
|
+
/** Request type: create (new component), update (modify existing), filter (create filter + update components) */
|
|
2307
|
+
req_type: z3.enum(["create", "update", "filter"]).optional()
|
|
2164
2308
|
});
|
|
2165
2309
|
var DashCompRequestMessageSchema = z3.object({
|
|
2166
2310
|
id: z3.string(),
|
|
@@ -7303,7 +7447,7 @@ var CONTEXT_CONFIG = {
|
|
|
7303
7447
|
};
|
|
7304
7448
|
|
|
7305
7449
|
// src/handlers/user-prompt-request.ts
|
|
7306
|
-
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools
|
|
7450
|
+
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools) => {
|
|
7307
7451
|
const errors = [];
|
|
7308
7452
|
logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
|
|
7309
7453
|
const parseResult = UserPromptRequestMessageSchema.safeParse(data);
|
|
@@ -7317,6 +7461,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
7317
7461
|
const userPromptRequest = parseResult.data;
|
|
7318
7462
|
const { id, payload } = userPromptRequest;
|
|
7319
7463
|
const prompt = payload.prompt;
|
|
7464
|
+
const userId = payload.userId;
|
|
7320
7465
|
const SA_RUNTIME = payload.SA_RUNTIME;
|
|
7321
7466
|
const wsId = userPromptRequest.from.id || "unknown";
|
|
7322
7467
|
const promptContext = `User Prompt: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
@@ -7489,8 +7634,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
7489
7634
|
wsId
|
|
7490
7635
|
};
|
|
7491
7636
|
};
|
|
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
|
|
7637
|
+
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools) {
|
|
7638
|
+
const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools);
|
|
7494
7639
|
sendDataResponse4(
|
|
7495
7640
|
response.id || data.id,
|
|
7496
7641
|
{
|
|
@@ -7522,11 +7667,11 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
|
7522
7667
|
|
|
7523
7668
|
// src/handlers/user-prompt-suggestions.ts
|
|
7524
7669
|
init_logger();
|
|
7525
|
-
async function handleUserPromptSuggestions(data, components, sendMessage, collections
|
|
7670
|
+
async function handleUserPromptSuggestions(data, components, sendMessage, collections) {
|
|
7526
7671
|
try {
|
|
7527
7672
|
const request = UserPromptSuggestionsMessageSchema.parse(data);
|
|
7528
7673
|
const { id, payload, from } = request;
|
|
7529
|
-
const { prompt, limit = 10 } = payload;
|
|
7674
|
+
const { prompt, userId, limit = 10 } = payload;
|
|
7530
7675
|
const wsId = from.id;
|
|
7531
7676
|
logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Processing user prompt suggestions: ${prompt}`);
|
|
7532
7677
|
if (!prompt || prompt.trim().length === 0) {
|
|
@@ -10166,40 +10311,108 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10166
10311
|
sendMessage(response);
|
|
10167
10312
|
}
|
|
10168
10313
|
|
|
10169
|
-
// src/
|
|
10314
|
+
// src/dashComp/index.ts
|
|
10170
10315
|
init_logger();
|
|
10171
|
-
|
|
10316
|
+
|
|
10317
|
+
// src/dashComp/types.ts
|
|
10172
10318
|
var DEFAULT_DASH_COMP_MODELS = {
|
|
10173
10319
|
anthropic: "anthropic/claude-haiku-4-5-20251001",
|
|
10174
10320
|
gemini: "gemini/gemini-3-flash-preview",
|
|
10175
10321
|
openai: "openai/gpt-4o-mini",
|
|
10176
10322
|
groq: "groq/llama-3.3-70b-versatile"
|
|
10177
10323
|
};
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
|
|
10184
|
-
|
|
10185
|
-
|
|
10324
|
+
|
|
10325
|
+
// src/dashComp/utils.ts
|
|
10326
|
+
function getApiKeyAndModel(anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, dashCompModels) {
|
|
10327
|
+
const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
|
|
10328
|
+
let apiKey;
|
|
10329
|
+
let model;
|
|
10330
|
+
if (dashCompModels?.model) {
|
|
10331
|
+
model = dashCompModels.model;
|
|
10332
|
+
const modelProvider = model.split("/")[0];
|
|
10333
|
+
if (modelProvider === "anthropic") apiKey = anthropicApiKey;
|
|
10334
|
+
else if (modelProvider === "gemini") apiKey = geminiApiKey;
|
|
10335
|
+
else if (modelProvider === "openai") apiKey = openaiApiKey;
|
|
10336
|
+
else if (modelProvider === "groq") apiKey = groqApiKey;
|
|
10337
|
+
} else {
|
|
10338
|
+
for (const provider of providers) {
|
|
10339
|
+
if (provider === "anthropic" && anthropicApiKey) {
|
|
10340
|
+
apiKey = anthropicApiKey;
|
|
10341
|
+
model = DEFAULT_DASH_COMP_MODELS.anthropic;
|
|
10342
|
+
break;
|
|
10343
|
+
} else if (provider === "gemini" && geminiApiKey) {
|
|
10344
|
+
apiKey = geminiApiKey;
|
|
10345
|
+
model = DEFAULT_DASH_COMP_MODELS.gemini;
|
|
10346
|
+
break;
|
|
10347
|
+
} else if (provider === "openai" && openaiApiKey) {
|
|
10348
|
+
apiKey = openaiApiKey;
|
|
10349
|
+
model = DEFAULT_DASH_COMP_MODELS.openai;
|
|
10350
|
+
break;
|
|
10351
|
+
} else if (provider === "groq" && groqApiKey) {
|
|
10352
|
+
apiKey = groqApiKey;
|
|
10353
|
+
model = DEFAULT_DASH_COMP_MODELS.groq;
|
|
10354
|
+
break;
|
|
10355
|
+
}
|
|
10356
|
+
}
|
|
10357
|
+
}
|
|
10358
|
+
return { apiKey, model };
|
|
10359
|
+
}
|
|
10360
|
+
function formatComponentsForPrompt(components) {
|
|
10361
|
+
if (!components || components.length === 0) {
|
|
10362
|
+
return "No components available";
|
|
10363
|
+
}
|
|
10364
|
+
return components.map((comp, idx) => {
|
|
10365
|
+
const keywords = comp.keywords ? comp.keywords.join(", ") : "";
|
|
10366
|
+
const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
|
|
10367
|
+
return `${idx + 1}. ID: ${comp.id}
|
|
10186
10368
|
Name: ${comp.name}
|
|
10187
10369
|
Type: ${comp.type}
|
|
10188
10370
|
Description: ${comp.description || "No description"}
|
|
10189
10371
|
Keywords: ${keywords}
|
|
10190
10372
|
Props Structure: ${propsPreview}`;
|
|
10191
|
-
|
|
10373
|
+
}).join("\n\n");
|
|
10374
|
+
}
|
|
10375
|
+
function formatToolsForPrompt(tools) {
|
|
10376
|
+
if (!tools || tools.length === 0) {
|
|
10377
|
+
return "No external tools available.";
|
|
10192
10378
|
}
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
10197
|
-
return `${idx + 1}. ID: ${tool.id}
|
|
10379
|
+
return tools.map((tool, idx) => {
|
|
10380
|
+
const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
10381
|
+
return `${idx + 1}. ID: ${tool.id}
|
|
10198
10382
|
Name: ${tool.name}
|
|
10199
10383
|
Description: ${tool.description}
|
|
10200
10384
|
Parameters: { ${paramsStr} }`;
|
|
10201
|
-
|
|
10385
|
+
}).join("\n\n");
|
|
10386
|
+
}
|
|
10387
|
+
function formatExistingComponentsForPrompt(existingComponents) {
|
|
10388
|
+
if (!existingComponents || existingComponents.length === 0) {
|
|
10389
|
+
return "No existing components in dashboard";
|
|
10202
10390
|
}
|
|
10391
|
+
return JSON.stringify(existingComponents, null, 2);
|
|
10392
|
+
}
|
|
10393
|
+
function sendDashCompResponse(id, res, sendMessage, clientId) {
|
|
10394
|
+
const response = {
|
|
10395
|
+
id,
|
|
10396
|
+
type: "DASH_COMP_RES",
|
|
10397
|
+
from: { type: "data-agent" },
|
|
10398
|
+
to: {
|
|
10399
|
+
type: "runtime",
|
|
10400
|
+
id: clientId
|
|
10401
|
+
},
|
|
10402
|
+
payload: {
|
|
10403
|
+
...res
|
|
10404
|
+
}
|
|
10405
|
+
};
|
|
10406
|
+
sendMessage(response);
|
|
10407
|
+
}
|
|
10408
|
+
|
|
10409
|
+
// src/dashComp/pick-component.ts
|
|
10410
|
+
init_logger();
|
|
10411
|
+
init_prompt_loader();
|
|
10412
|
+
async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, _collections, tools, dashCompModels) {
|
|
10413
|
+
const errors = [];
|
|
10414
|
+
const availableComponentsText = formatComponentsForPrompt(components);
|
|
10415
|
+
const availableToolsText = formatToolsForPrompt(tools);
|
|
10203
10416
|
try {
|
|
10204
10417
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
10205
10418
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
@@ -10211,38 +10424,14 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10211
10424
|
AVAILABLE_TOOLS: availableToolsText
|
|
10212
10425
|
});
|
|
10213
10426
|
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
|
-
}
|
|
10427
|
+
const { apiKey, model } = getApiKeyAndModel(
|
|
10428
|
+
anthropicApiKey,
|
|
10429
|
+
groqApiKey,
|
|
10430
|
+
geminiApiKey,
|
|
10431
|
+
openaiApiKey,
|
|
10432
|
+
llmProviders,
|
|
10433
|
+
dashCompModels
|
|
10434
|
+
);
|
|
10246
10435
|
if (!apiKey || !model) {
|
|
10247
10436
|
errors.push("No API key available for any LLM provider");
|
|
10248
10437
|
return { success: false, errors };
|
|
@@ -10273,13 +10462,13 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10273
10462
|
});
|
|
10274
10463
|
return { success: false, errors };
|
|
10275
10464
|
}
|
|
10276
|
-
const originalComponent = components.find((c) => c.
|
|
10465
|
+
const originalComponent = components.find((c) => c.name === result.componentName);
|
|
10277
10466
|
if (!originalComponent) {
|
|
10278
|
-
errors.push(`Component ${result.
|
|
10467
|
+
errors.push(`Component ${result.componentName} not found in available components`);
|
|
10279
10468
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
10280
10469
|
prompt,
|
|
10281
|
-
|
|
10282
|
-
|
|
10470
|
+
componentName: result.componentName,
|
|
10471
|
+
availableComponentNames: components.map((c) => c.name)
|
|
10283
10472
|
});
|
|
10284
10473
|
return { success: false, errors };
|
|
10285
10474
|
}
|
|
@@ -10302,7 +10491,8 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10302
10491
|
data: {
|
|
10303
10492
|
component: finalComponent,
|
|
10304
10493
|
reasoning: result.reasoning || "Component selected based on user prompt",
|
|
10305
|
-
dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none"
|
|
10494
|
+
dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none",
|
|
10495
|
+
isUpdate: result.isUpdate || false
|
|
10306
10496
|
},
|
|
10307
10497
|
errors: []
|
|
10308
10498
|
};
|
|
@@ -10318,6 +10508,84 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10318
10508
|
return { success: false, errors };
|
|
10319
10509
|
}
|
|
10320
10510
|
}
|
|
10511
|
+
|
|
10512
|
+
// src/dashComp/create-filter.ts
|
|
10513
|
+
init_logger();
|
|
10514
|
+
init_prompt_loader();
|
|
10515
|
+
async function createFilterWithLLM(prompt, components, existingComponents, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, tools, dashCompModels) {
|
|
10516
|
+
const errors = [];
|
|
10517
|
+
try {
|
|
10518
|
+
const filterComponents = components.filter((c) => c.type.startsWith("Filter"));
|
|
10519
|
+
if (filterComponents.length === 0) {
|
|
10520
|
+
errors.push("No filter components available");
|
|
10521
|
+
return { success: false, errors };
|
|
10522
|
+
}
|
|
10523
|
+
logger.debug(`[DASH_COMP_REQ:FILTER] Found ${filterComponents.length} filter components`);
|
|
10524
|
+
const schemaDoc = schema.generateSchemaDocumentation();
|
|
10525
|
+
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
10526
|
+
const prompts = await promptLoader.loadPrompts("dash-filter-picker", {
|
|
10527
|
+
USER_PROMPT: prompt,
|
|
10528
|
+
AVAILABLE_COMPONENTS: formatComponentsForPrompt(filterComponents),
|
|
10529
|
+
EXISTING_COMPONENTS: formatExistingComponentsForPrompt(existingComponents),
|
|
10530
|
+
SCHEMA_DOC: schemaDoc || "No database schema available",
|
|
10531
|
+
DATABASE_RULES: databaseRules,
|
|
10532
|
+
AVAILABLE_TOOLS: formatToolsForPrompt(tools)
|
|
10533
|
+
});
|
|
10534
|
+
logger.debug("[DASH_COMP_REQ:FILTER] Loaded dash-filter-picker prompts");
|
|
10535
|
+
const { apiKey, model } = getApiKeyAndModel(
|
|
10536
|
+
anthropicApiKey,
|
|
10537
|
+
groqApiKey,
|
|
10538
|
+
geminiApiKey,
|
|
10539
|
+
openaiApiKey,
|
|
10540
|
+
llmProviders,
|
|
10541
|
+
dashCompModels
|
|
10542
|
+
);
|
|
10543
|
+
if (!apiKey || !model) {
|
|
10544
|
+
errors.push("No API key available for any LLM provider");
|
|
10545
|
+
return { success: false, errors };
|
|
10546
|
+
}
|
|
10547
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10548
|
+
const result = await LLM.stream(
|
|
10549
|
+
{ sys: prompts.system, user: prompts.user },
|
|
10550
|
+
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10551
|
+
true
|
|
10552
|
+
);
|
|
10553
|
+
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10554
|
+
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10555
|
+
if (!result.filterComponent) {
|
|
10556
|
+
errors.push("Invalid LLM response: missing filterComponent");
|
|
10557
|
+
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", "Invalid LLM response structure", {
|
|
10558
|
+
prompt,
|
|
10559
|
+
result,
|
|
10560
|
+
missingFields: { filterComponent: !result.filterComponent }
|
|
10561
|
+
});
|
|
10562
|
+
return { success: false, errors };
|
|
10563
|
+
}
|
|
10564
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10565
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Updated ${result.updatedComponents?.length || 0} components`);
|
|
10566
|
+
return {
|
|
10567
|
+
success: true,
|
|
10568
|
+
data: {
|
|
10569
|
+
filterComponent: result.filterComponent,
|
|
10570
|
+
updatedComponents: result.updatedComponents || [],
|
|
10571
|
+
filterBindings: result.filterBindings || {},
|
|
10572
|
+
reasoning: result.reasoning || "Filter created based on user prompt"
|
|
10573
|
+
},
|
|
10574
|
+
errors: []
|
|
10575
|
+
};
|
|
10576
|
+
} catch (error) {
|
|
10577
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
10578
|
+
logger.error(`[DASH_COMP_REQ:FILTER] Error creating filter: ${errorMsg}`);
|
|
10579
|
+
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", error instanceof Error ? error : new Error(errorMsg), {
|
|
10580
|
+
prompt,
|
|
10581
|
+
existingComponentsCount: existingComponents.length
|
|
10582
|
+
});
|
|
10583
|
+
errors.push(errorMsg);
|
|
10584
|
+
return { success: false, errors };
|
|
10585
|
+
}
|
|
10586
|
+
}
|
|
10587
|
+
|
|
10588
|
+
// src/dashComp/index.ts
|
|
10321
10589
|
var processDashCompRequest = async (data, components, _sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, dashCompModels) => {
|
|
10322
10590
|
const errors = [];
|
|
10323
10591
|
logger.debug("[DASH_COMP_REQ] Parsing incoming message data");
|
|
@@ -10332,17 +10600,25 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
10332
10600
|
const dashCompRequest = parseResult.data;
|
|
10333
10601
|
const { id, payload } = dashCompRequest;
|
|
10334
10602
|
const prompt = payload.prompt;
|
|
10603
|
+
const reqType = payload.req_type || "create";
|
|
10604
|
+
const existingComponents = payload.existingComponents || [];
|
|
10335
10605
|
const wsId = dashCompRequest.from.id || "unknown";
|
|
10336
|
-
const promptContext = `DASH_COMP: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
10606
|
+
const promptContext = `DASH_COMP[${reqType}]: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
10337
10607
|
llmUsageLogger.resetLogFile(promptContext);
|
|
10338
10608
|
if (!prompt) {
|
|
10339
10609
|
errors.push("Prompt is required");
|
|
10340
10610
|
}
|
|
10611
|
+
if (reqType === "filter" && existingComponents.length === 0) {
|
|
10612
|
+
errors.push("Filter request requires existingComponents");
|
|
10613
|
+
}
|
|
10341
10614
|
if (errors.length > 0) {
|
|
10342
10615
|
return { success: false, errors, id, wsId };
|
|
10343
10616
|
}
|
|
10344
|
-
logger.info(`[DASH_COMP_REQ] Processing request for prompt: "${prompt.substring(0, 50)}..."`);
|
|
10617
|
+
logger.info(`[DASH_COMP_REQ] Processing ${reqType} request for prompt: "${prompt.substring(0, 50)}..."`);
|
|
10345
10618
|
logger.info(`[DASH_COMP_REQ] Available: ${components?.length || 0} components, ${tools?.length || 0} tools`);
|
|
10619
|
+
if (existingComponents.length > 0) {
|
|
10620
|
+
logger.info(`[DASH_COMP_REQ] Existing components in dashboard: ${existingComponents.length}`);
|
|
10621
|
+
}
|
|
10346
10622
|
if (!components || components.length === 0) {
|
|
10347
10623
|
logger.warn("[DASH_COMP_REQ] No components available");
|
|
10348
10624
|
return {
|
|
@@ -10352,19 +10628,35 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
10352
10628
|
wsId
|
|
10353
10629
|
};
|
|
10354
10630
|
}
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10631
|
+
let llmResponse;
|
|
10632
|
+
if (reqType === "filter") {
|
|
10633
|
+
llmResponse = await createFilterWithLLM(
|
|
10634
|
+
prompt,
|
|
10635
|
+
components,
|
|
10636
|
+
existingComponents,
|
|
10637
|
+
anthropicApiKey,
|
|
10638
|
+
groqApiKey,
|
|
10639
|
+
geminiApiKey,
|
|
10640
|
+
openaiApiKey,
|
|
10641
|
+
llmProviders,
|
|
10642
|
+
tools,
|
|
10643
|
+
dashCompModels
|
|
10644
|
+
);
|
|
10645
|
+
} else {
|
|
10646
|
+
llmResponse = await pickComponentWithLLM(
|
|
10647
|
+
prompt,
|
|
10648
|
+
components,
|
|
10649
|
+
anthropicApiKey,
|
|
10650
|
+
groqApiKey,
|
|
10651
|
+
geminiApiKey,
|
|
10652
|
+
openaiApiKey,
|
|
10653
|
+
llmProviders,
|
|
10654
|
+
collections,
|
|
10655
|
+
tools,
|
|
10656
|
+
dashCompModels
|
|
10657
|
+
);
|
|
10658
|
+
}
|
|
10659
|
+
llmUsageLogger.logSessionSummary(`DASH_COMP[${reqType}]: ${prompt?.substring(0, 30)}`);
|
|
10368
10660
|
return {
|
|
10369
10661
|
success: llmResponse.success,
|
|
10370
10662
|
data: llmResponse.data,
|
|
@@ -10397,22 +10689,7 @@ async function handleDashCompRequest(data, components, sendMessage, anthropicApi
|
|
|
10397
10689
|
sendMessage,
|
|
10398
10690
|
response.wsId || data.from?.id
|
|
10399
10691
|
);
|
|
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}`);
|
|
10692
|
+
logger.info(`[DASH_COMP_REQ] Response sent to client ${response.wsId || data.from?.id}`);
|
|
10416
10693
|
}
|
|
10417
10694
|
|
|
10418
10695
|
// src/auth/user-manager.ts
|
|
@@ -11260,7 +11537,6 @@ var SuperatomSDK = class {
|
|
|
11260
11537
|
}
|
|
11261
11538
|
this.apiKey = config.apiKey;
|
|
11262
11539
|
this.projectId = config.projectId;
|
|
11263
|
-
this.userId = config.userId || "anonymous";
|
|
11264
11540
|
this.type = config.type || "data-agent";
|
|
11265
11541
|
this.bundleDir = config.bundleDir;
|
|
11266
11542
|
this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;
|
|
@@ -11362,7 +11638,6 @@ var SuperatomSDK = class {
|
|
|
11362
11638
|
url.searchParams.set("apiKey", this.apiKey);
|
|
11363
11639
|
}
|
|
11364
11640
|
url.searchParams.set("projectId", this.projectId);
|
|
11365
|
-
url.searchParams.set("userId", this.userId);
|
|
11366
11641
|
url.searchParams.set("type", this.type);
|
|
11367
11642
|
logger.info(`Connecting to WebSocket: ${url.toString()}`);
|
|
11368
11643
|
this.ws = createWebSocket(url.toString());
|
|
@@ -11423,7 +11698,7 @@ var SuperatomSDK = class {
|
|
|
11423
11698
|
});
|
|
11424
11699
|
break;
|
|
11425
11700
|
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
|
|
11701
|
+
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
11702
|
logger.error("Failed to handle user prompt request:", error);
|
|
11428
11703
|
});
|
|
11429
11704
|
break;
|
|
@@ -11433,7 +11708,7 @@ var SuperatomSDK = class {
|
|
|
11433
11708
|
});
|
|
11434
11709
|
break;
|
|
11435
11710
|
case "USER_PROMPT_SUGGESTIONS_REQ":
|
|
11436
|
-
handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections
|
|
11711
|
+
handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections).catch((error) => {
|
|
11437
11712
|
logger.error("Failed to handle user prompt suggestions request:", error);
|
|
11438
11713
|
});
|
|
11439
11714
|
break;
|