@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.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,142 @@ 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
|
|
1200
|
+
2. **Update existing components** with dynamic title/description interpolation if needed
|
|
1201
|
+
3. **Preserve all existing props** - the filter system handles param merging at runtime
|
|
1202
|
+
|
|
1203
|
+
## How The Filter System Works
|
|
1204
|
+
|
|
1205
|
+
1. Filter component has a \`filters\` array with preset options, each containing \`label\`, \`value\`, and \`params\`
|
|
1206
|
+
2. When user selects a filter option, those \`params\` are broadcast to all listening components
|
|
1207
|
+
3. Components automatically merge filter params with their existing params (filter values override defaults)
|
|
1208
|
+
4. Component titles/descriptions can use \`{%filterKeyLabel%}\` syntax for dynamic text
|
|
1209
|
+
|
|
1210
|
+
## Filter Component Structure
|
|
1211
|
+
|
|
1212
|
+
The filter uses DynamicFilterDropdown with:
|
|
1213
|
+
- **filterKey**: Identifier for label interpolation (e.g., "period", "name", "category")
|
|
1214
|
+
- **filters**: Array of options with label, value, params, and optionally isDefault
|
|
1215
|
+
- **defaultValue**: The value of the initially selected option
|
|
1216
|
+
|
|
1217
|
+
## Dynamic Title/Description Interpolation
|
|
1218
|
+
|
|
1219
|
+
Use \`{%filterKeyLabel%}\` syntax for dynamic text:
|
|
1220
|
+
- filterKey "period" \u2192 use \`{%periodLabel%}\` in titles/descriptions
|
|
1221
|
+
- filterKey "name" \u2192 use \`{%nameLabel%}\` in titles/descriptions
|
|
1222
|
+
- Example: \`"{%periodLabel%} Revenue"\` becomes "Q3 2025 Revenue" when user selects "Q3 2025"
|
|
1223
|
+
|
|
1224
|
+
**CRITICAL Template Syntax:**
|
|
1225
|
+
- Use \`{%keyLabel%}\` format (percent signs, key + "Label" suffix)
|
|
1226
|
+
- Do NOT use \`{{...}}\` or \`$...\` syntax - these don't work
|
|
1227
|
+
|
|
1228
|
+
## Updating Existing Components
|
|
1229
|
+
|
|
1230
|
+
**IMPORTANT - Parameter Handling:**
|
|
1231
|
+
- Do NOT change existing parameter values to placeholders
|
|
1232
|
+
- Keep all existing/default parameter values as they are
|
|
1233
|
+
- The filter system MERGES params at runtime: filter params override component defaults
|
|
1234
|
+
|
|
1235
|
+
**What to modify in existing components:**
|
|
1236
|
+
- Modify \`title\` for \`{%filterKeyLabel%}\` interpolation (only if title exists)
|
|
1237
|
+
- Modify \`description\` for interpolation (only if description exists)
|
|
1238
|
+
- Modify other props only if specifically needed for the filter to function
|
|
1239
|
+
- Copy ALL other props exactly as provided
|
|
1240
|
+
|
|
1241
|
+
### Database Query Rules
|
|
1242
|
+
{{DATABASE_RULES}}
|
|
1243
|
+
|
|
1244
|
+
## Output Format
|
|
1245
|
+
|
|
1246
|
+
You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
1247
|
+
|
|
1248
|
+
{
|
|
1249
|
+
"filterComponent": {
|
|
1250
|
+
"id": "filter-<descriptive-id>",
|
|
1251
|
+
"name": "DynamicFilterDropdown",
|
|
1252
|
+
"type": "FilterDropdown",
|
|
1253
|
+
"props": {
|
|
1254
|
+
"title": "<Filter display title>",
|
|
1255
|
+
"filterKey": "<key_for_interpolation>",
|
|
1256
|
+
"defaultValue": "<default_option_value>",
|
|
1257
|
+
"filters": [
|
|
1258
|
+
{
|
|
1259
|
+
"label": "<Display label for option>",
|
|
1260
|
+
"value": "<unique_option_value>",
|
|
1261
|
+
"params": { "<param_key>": "<actual_value>", "...": "..." },
|
|
1262
|
+
"isDefault": true
|
|
1263
|
+
}
|
|
1264
|
+
]
|
|
1265
|
+
}
|
|
1266
|
+
},
|
|
1267
|
+
"updatedComponents": [
|
|
1268
|
+
{
|
|
1269
|
+
"id": "<existing_component_id>",
|
|
1270
|
+
"name": "<existing_component_name>",
|
|
1271
|
+
"type": "<existing_type>",
|
|
1272
|
+
"props": {
|
|
1273
|
+
"...all existing props preserved...",
|
|
1274
|
+
"title": "{%<filterKey>Label%} <rest of title>",
|
|
1275
|
+
"description": "<updated if needed>"
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
],
|
|
1279
|
+
"filterBindings": {
|
|
1280
|
+
"<param_key>": "Describes which filter param this binds to"
|
|
1281
|
+
},
|
|
1282
|
+
"reasoning": "Explanation of filter choice and what params it provides"
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
**CRITICAL RULES:**
|
|
1286
|
+
1. Return ONLY valid JSON (no markdown code blocks)
|
|
1287
|
+
2. **COPY ALL existing props** - modify title/description for interpolation only if they exist
|
|
1288
|
+
3. **DO NOT change parameter values** - keep existing defaults, filter merges at runtime
|
|
1289
|
+
4. Use \`{%filterKeyLabel%}\` for dynamic text (NOT \`{{...}}\` or \`$...\`)
|
|
1290
|
+
5. Filter \`params\` must have ACTUAL values (real dates, strings), not placeholders
|
|
1291
|
+
6. Each filter option needs: label, value, params (and optionally isDefault)
|
|
1163
1292
|
|
|
1164
|
-
|
|
1293
|
+
## Database Schema
|
|
1165
1294
|
{{SCHEMA_DOC}}
|
|
1166
1295
|
|
|
1167
|
-
|
|
1296
|
+
## Available External Tools
|
|
1168
1297
|
{{AVAILABLE_TOOLS}}
|
|
1169
1298
|
|
|
1170
|
-
|
|
1171
|
-
{{AVAILABLE_COMPONENTS}}
|
|
1299
|
+
## Available Filter Components
|
|
1300
|
+
{{AVAILABLE_COMPONENTS}}
|
|
1301
|
+
|
|
1302
|
+
## Existing Dashboard Components
|
|
1303
|
+
{{EXISTING_COMPONENTS}}
|
|
1304
|
+
|
|
1305
|
+
---
|
|
1306
|
+
|
|
1307
|
+
## CONTEXT`,
|
|
1172
1308
|
user: `{{USER_PROMPT}}`
|
|
1173
1309
|
}
|
|
1174
1310
|
};
|
|
@@ -1904,6 +2040,7 @@ var AuthVerifyRequestMessageSchema = import_zod3.z.object({
|
|
|
1904
2040
|
});
|
|
1905
2041
|
var UserPromptRequestPayloadSchema = import_zod3.z.object({
|
|
1906
2042
|
prompt: import_zod3.z.string(),
|
|
2043
|
+
userId: import_zod3.z.string().optional(),
|
|
1907
2044
|
SA_RUNTIME: import_zod3.z.object({
|
|
1908
2045
|
threadId: import_zod3.z.string(),
|
|
1909
2046
|
uiBlockId: import_zod3.z.string()
|
|
@@ -1918,6 +2055,7 @@ var UserPromptRequestMessageSchema = import_zod3.z.object({
|
|
|
1918
2055
|
});
|
|
1919
2056
|
var UserPromptSuggestionsPayloadSchema = import_zod3.z.object({
|
|
1920
2057
|
prompt: import_zod3.z.string(),
|
|
2058
|
+
userId: import_zod3.z.string().optional(),
|
|
1921
2059
|
limit: import_zod3.z.number().int().positive().default(5),
|
|
1922
2060
|
similarityThreshold: import_zod3.z.number().min(0).max(1).default(0.4)
|
|
1923
2061
|
});
|
|
@@ -2007,6 +2145,7 @@ var UILogsMessageSchema = import_zod3.z.object({
|
|
|
2007
2145
|
payload: UILogsPayloadSchema
|
|
2008
2146
|
});
|
|
2009
2147
|
var ActionsRequestPayloadSchema = import_zod3.z.object({
|
|
2148
|
+
userId: import_zod3.z.string().optional(),
|
|
2010
2149
|
SA_RUNTIME: import_zod3.z.object({
|
|
2011
2150
|
threadId: import_zod3.z.string(),
|
|
2012
2151
|
uiBlockId: import_zod3.z.string()
|
|
@@ -2207,10 +2346,15 @@ var KbNodesRequestMessageSchema = import_zod3.z.object({
|
|
|
2207
2346
|
});
|
|
2208
2347
|
var DashCompRequestPayloadSchema = import_zod3.z.object({
|
|
2209
2348
|
prompt: import_zod3.z.string(),
|
|
2349
|
+
userId: import_zod3.z.string().optional(),
|
|
2210
2350
|
SA_RUNTIME: import_zod3.z.object({
|
|
2211
2351
|
threadId: import_zod3.z.string().optional(),
|
|
2212
2352
|
uiBlockId: import_zod3.z.string().optional()
|
|
2213
|
-
}).optional()
|
|
2353
|
+
}).optional(),
|
|
2354
|
+
/** Existing components in the dashboard (for update/filter operations) */
|
|
2355
|
+
existingComponents: import_zod3.z.array(ComponentSchema).optional(),
|
|
2356
|
+
/** Request type: create (new component), update (modify existing), filter (create filter + update components) */
|
|
2357
|
+
req_type: import_zod3.z.enum(["create", "update", "filter"]).optional()
|
|
2214
2358
|
});
|
|
2215
2359
|
var DashCompRequestMessageSchema = import_zod3.z.object({
|
|
2216
2360
|
id: import_zod3.z.string(),
|
|
@@ -7353,7 +7497,7 @@ var CONTEXT_CONFIG = {
|
|
|
7353
7497
|
};
|
|
7354
7498
|
|
|
7355
7499
|
// src/handlers/user-prompt-request.ts
|
|
7356
|
-
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools
|
|
7500
|
+
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools) => {
|
|
7357
7501
|
const errors = [];
|
|
7358
7502
|
logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
|
|
7359
7503
|
const parseResult = UserPromptRequestMessageSchema.safeParse(data);
|
|
@@ -7367,6 +7511,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
7367
7511
|
const userPromptRequest = parseResult.data;
|
|
7368
7512
|
const { id, payload } = userPromptRequest;
|
|
7369
7513
|
const prompt = payload.prompt;
|
|
7514
|
+
const userId = payload.userId;
|
|
7370
7515
|
const SA_RUNTIME = payload.SA_RUNTIME;
|
|
7371
7516
|
const wsId = userPromptRequest.from.id || "unknown";
|
|
7372
7517
|
const promptContext = `User Prompt: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
@@ -7539,8 +7684,8 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
7539
7684
|
wsId
|
|
7540
7685
|
};
|
|
7541
7686
|
};
|
|
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
|
|
7687
|
+
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools) {
|
|
7688
|
+
const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, externalTools);
|
|
7544
7689
|
sendDataResponse4(
|
|
7545
7690
|
response.id || data.id,
|
|
7546
7691
|
{
|
|
@@ -7572,11 +7717,11 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
|
7572
7717
|
|
|
7573
7718
|
// src/handlers/user-prompt-suggestions.ts
|
|
7574
7719
|
init_logger();
|
|
7575
|
-
async function handleUserPromptSuggestions(data, components, sendMessage, collections
|
|
7720
|
+
async function handleUserPromptSuggestions(data, components, sendMessage, collections) {
|
|
7576
7721
|
try {
|
|
7577
7722
|
const request = UserPromptSuggestionsMessageSchema.parse(data);
|
|
7578
7723
|
const { id, payload, from } = request;
|
|
7579
|
-
const { prompt, limit = 10 } = payload;
|
|
7724
|
+
const { prompt, userId, limit = 10 } = payload;
|
|
7580
7725
|
const wsId = from.id;
|
|
7581
7726
|
logger.info(`[USER_PROMPT_SUGGESTIONS_REQ ${id}] Processing user prompt suggestions: ${prompt}`);
|
|
7582
7727
|
if (!prompt || prompt.trim().length === 0) {
|
|
@@ -10216,40 +10361,108 @@ function sendResponse8(id, res, sendMessage, clientId) {
|
|
|
10216
10361
|
sendMessage(response);
|
|
10217
10362
|
}
|
|
10218
10363
|
|
|
10219
|
-
// src/
|
|
10364
|
+
// src/dashComp/index.ts
|
|
10220
10365
|
init_logger();
|
|
10221
|
-
|
|
10366
|
+
|
|
10367
|
+
// src/dashComp/types.ts
|
|
10222
10368
|
var DEFAULT_DASH_COMP_MODELS = {
|
|
10223
10369
|
anthropic: "anthropic/claude-haiku-4-5-20251001",
|
|
10224
10370
|
gemini: "gemini/gemini-3-flash-preview",
|
|
10225
10371
|
openai: "openai/gpt-4o-mini",
|
|
10226
10372
|
groq: "groq/llama-3.3-70b-versatile"
|
|
10227
10373
|
};
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10374
|
+
|
|
10375
|
+
// src/dashComp/utils.ts
|
|
10376
|
+
function getApiKeyAndModel(anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, dashCompModels) {
|
|
10377
|
+
const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
|
|
10378
|
+
let apiKey;
|
|
10379
|
+
let model;
|
|
10380
|
+
if (dashCompModels?.model) {
|
|
10381
|
+
model = dashCompModels.model;
|
|
10382
|
+
const modelProvider = model.split("/")[0];
|
|
10383
|
+
if (modelProvider === "anthropic") apiKey = anthropicApiKey;
|
|
10384
|
+
else if (modelProvider === "gemini") apiKey = geminiApiKey;
|
|
10385
|
+
else if (modelProvider === "openai") apiKey = openaiApiKey;
|
|
10386
|
+
else if (modelProvider === "groq") apiKey = groqApiKey;
|
|
10387
|
+
} else {
|
|
10388
|
+
for (const provider of providers) {
|
|
10389
|
+
if (provider === "anthropic" && anthropicApiKey) {
|
|
10390
|
+
apiKey = anthropicApiKey;
|
|
10391
|
+
model = DEFAULT_DASH_COMP_MODELS.anthropic;
|
|
10392
|
+
break;
|
|
10393
|
+
} else if (provider === "gemini" && geminiApiKey) {
|
|
10394
|
+
apiKey = geminiApiKey;
|
|
10395
|
+
model = DEFAULT_DASH_COMP_MODELS.gemini;
|
|
10396
|
+
break;
|
|
10397
|
+
} else if (provider === "openai" && openaiApiKey) {
|
|
10398
|
+
apiKey = openaiApiKey;
|
|
10399
|
+
model = DEFAULT_DASH_COMP_MODELS.openai;
|
|
10400
|
+
break;
|
|
10401
|
+
} else if (provider === "groq" && groqApiKey) {
|
|
10402
|
+
apiKey = groqApiKey;
|
|
10403
|
+
model = DEFAULT_DASH_COMP_MODELS.groq;
|
|
10404
|
+
break;
|
|
10405
|
+
}
|
|
10406
|
+
}
|
|
10407
|
+
}
|
|
10408
|
+
return { apiKey, model };
|
|
10409
|
+
}
|
|
10410
|
+
function formatComponentsForPrompt(components) {
|
|
10411
|
+
if (!components || components.length === 0) {
|
|
10412
|
+
return "No components available";
|
|
10413
|
+
}
|
|
10414
|
+
return components.map((comp, idx) => {
|
|
10415
|
+
const keywords = comp.keywords ? comp.keywords.join(", ") : "";
|
|
10416
|
+
const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
|
|
10417
|
+
return `${idx + 1}. ID: ${comp.id}
|
|
10236
10418
|
Name: ${comp.name}
|
|
10237
10419
|
Type: ${comp.type}
|
|
10238
10420
|
Description: ${comp.description || "No description"}
|
|
10239
10421
|
Keywords: ${keywords}
|
|
10240
10422
|
Props Structure: ${propsPreview}`;
|
|
10241
|
-
|
|
10423
|
+
}).join("\n\n");
|
|
10424
|
+
}
|
|
10425
|
+
function formatToolsForPrompt(tools) {
|
|
10426
|
+
if (!tools || tools.length === 0) {
|
|
10427
|
+
return "No external tools available.";
|
|
10242
10428
|
}
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
10247
|
-
return `${idx + 1}. ID: ${tool.id}
|
|
10429
|
+
return tools.map((tool, idx) => {
|
|
10430
|
+
const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
10431
|
+
return `${idx + 1}. ID: ${tool.id}
|
|
10248
10432
|
Name: ${tool.name}
|
|
10249
10433
|
Description: ${tool.description}
|
|
10250
10434
|
Parameters: { ${paramsStr} }`;
|
|
10251
|
-
|
|
10435
|
+
}).join("\n\n");
|
|
10436
|
+
}
|
|
10437
|
+
function formatExistingComponentsForPrompt(existingComponents) {
|
|
10438
|
+
if (!existingComponents || existingComponents.length === 0) {
|
|
10439
|
+
return "No existing components in dashboard";
|
|
10252
10440
|
}
|
|
10441
|
+
return JSON.stringify(existingComponents, null, 2);
|
|
10442
|
+
}
|
|
10443
|
+
function sendDashCompResponse(id, res, sendMessage, clientId) {
|
|
10444
|
+
const response = {
|
|
10445
|
+
id,
|
|
10446
|
+
type: "DASH_COMP_RES",
|
|
10447
|
+
from: { type: "data-agent" },
|
|
10448
|
+
to: {
|
|
10449
|
+
type: "runtime",
|
|
10450
|
+
id: clientId
|
|
10451
|
+
},
|
|
10452
|
+
payload: {
|
|
10453
|
+
...res
|
|
10454
|
+
}
|
|
10455
|
+
};
|
|
10456
|
+
sendMessage(response);
|
|
10457
|
+
}
|
|
10458
|
+
|
|
10459
|
+
// src/dashComp/pick-component.ts
|
|
10460
|
+
init_logger();
|
|
10461
|
+
init_prompt_loader();
|
|
10462
|
+
async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, _collections, tools, dashCompModels) {
|
|
10463
|
+
const errors = [];
|
|
10464
|
+
const availableComponentsText = formatComponentsForPrompt(components);
|
|
10465
|
+
const availableToolsText = formatToolsForPrompt(tools);
|
|
10253
10466
|
try {
|
|
10254
10467
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
10255
10468
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
@@ -10261,38 +10474,14 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10261
10474
|
AVAILABLE_TOOLS: availableToolsText
|
|
10262
10475
|
});
|
|
10263
10476
|
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
|
-
}
|
|
10477
|
+
const { apiKey, model } = getApiKeyAndModel(
|
|
10478
|
+
anthropicApiKey,
|
|
10479
|
+
groqApiKey,
|
|
10480
|
+
geminiApiKey,
|
|
10481
|
+
openaiApiKey,
|
|
10482
|
+
llmProviders,
|
|
10483
|
+
dashCompModels
|
|
10484
|
+
);
|
|
10296
10485
|
if (!apiKey || !model) {
|
|
10297
10486
|
errors.push("No API key available for any LLM provider");
|
|
10298
10487
|
return { success: false, errors };
|
|
@@ -10323,13 +10512,13 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10323
10512
|
});
|
|
10324
10513
|
return { success: false, errors };
|
|
10325
10514
|
}
|
|
10326
|
-
const originalComponent = components.find((c) => c.
|
|
10515
|
+
const originalComponent = components.find((c) => c.name === result.componentName);
|
|
10327
10516
|
if (!originalComponent) {
|
|
10328
|
-
errors.push(`Component ${result.
|
|
10517
|
+
errors.push(`Component ${result.componentName} not found in available components`);
|
|
10329
10518
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
10330
10519
|
prompt,
|
|
10331
|
-
|
|
10332
|
-
|
|
10520
|
+
componentName: result.componentName,
|
|
10521
|
+
availableComponentNames: components.map((c) => c.name)
|
|
10333
10522
|
});
|
|
10334
10523
|
return { success: false, errors };
|
|
10335
10524
|
}
|
|
@@ -10352,7 +10541,8 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10352
10541
|
data: {
|
|
10353
10542
|
component: finalComponent,
|
|
10354
10543
|
reasoning: result.reasoning || "Component selected based on user prompt",
|
|
10355
|
-
dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none"
|
|
10544
|
+
dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none",
|
|
10545
|
+
isUpdate: result.isUpdate || false
|
|
10356
10546
|
},
|
|
10357
10547
|
errors: []
|
|
10358
10548
|
};
|
|
@@ -10368,6 +10558,84 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
10368
10558
|
return { success: false, errors };
|
|
10369
10559
|
}
|
|
10370
10560
|
}
|
|
10561
|
+
|
|
10562
|
+
// src/dashComp/create-filter.ts
|
|
10563
|
+
init_logger();
|
|
10564
|
+
init_prompt_loader();
|
|
10565
|
+
async function createFilterWithLLM(prompt, components, existingComponents, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, tools, dashCompModels) {
|
|
10566
|
+
const errors = [];
|
|
10567
|
+
try {
|
|
10568
|
+
const filterComponents = components.filter((c) => c.type.startsWith("Filter"));
|
|
10569
|
+
if (filterComponents.length === 0) {
|
|
10570
|
+
errors.push("No filter components available");
|
|
10571
|
+
return { success: false, errors };
|
|
10572
|
+
}
|
|
10573
|
+
logger.debug(`[DASH_COMP_REQ:FILTER] Found ${filterComponents.length} filter components`);
|
|
10574
|
+
const schemaDoc = schema.generateSchemaDocumentation();
|
|
10575
|
+
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
10576
|
+
const prompts = await promptLoader.loadPrompts("dash-filter-picker", {
|
|
10577
|
+
USER_PROMPT: prompt,
|
|
10578
|
+
AVAILABLE_COMPONENTS: formatComponentsForPrompt(filterComponents),
|
|
10579
|
+
EXISTING_COMPONENTS: formatExistingComponentsForPrompt(existingComponents),
|
|
10580
|
+
SCHEMA_DOC: schemaDoc || "No database schema available",
|
|
10581
|
+
DATABASE_RULES: databaseRules,
|
|
10582
|
+
AVAILABLE_TOOLS: formatToolsForPrompt(tools)
|
|
10583
|
+
});
|
|
10584
|
+
logger.debug("[DASH_COMP_REQ:FILTER] Loaded dash-filter-picker prompts");
|
|
10585
|
+
const { apiKey, model } = getApiKeyAndModel(
|
|
10586
|
+
anthropicApiKey,
|
|
10587
|
+
groqApiKey,
|
|
10588
|
+
geminiApiKey,
|
|
10589
|
+
openaiApiKey,
|
|
10590
|
+
llmProviders,
|
|
10591
|
+
dashCompModels
|
|
10592
|
+
);
|
|
10593
|
+
if (!apiKey || !model) {
|
|
10594
|
+
errors.push("No API key available for any LLM provider");
|
|
10595
|
+
return { success: false, errors };
|
|
10596
|
+
}
|
|
10597
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Using model: ${model}`);
|
|
10598
|
+
const result = await LLM.stream(
|
|
10599
|
+
{ sys: prompts.system, user: prompts.user },
|
|
10600
|
+
{ model, maxTokens: 16384, temperature: 0.2, apiKey },
|
|
10601
|
+
true
|
|
10602
|
+
);
|
|
10603
|
+
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
10604
|
+
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
10605
|
+
if (!result.filterComponent) {
|
|
10606
|
+
errors.push("Invalid LLM response: missing filterComponent");
|
|
10607
|
+
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", "Invalid LLM response structure", {
|
|
10608
|
+
prompt,
|
|
10609
|
+
result,
|
|
10610
|
+
missingFields: { filterComponent: !result.filterComponent }
|
|
10611
|
+
});
|
|
10612
|
+
return { success: false, errors };
|
|
10613
|
+
}
|
|
10614
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Successfully created filter: ${result.filterComponent.componentType}`);
|
|
10615
|
+
logger.info(`[DASH_COMP_REQ:FILTER] Updated ${result.updatedComponents?.length || 0} components`);
|
|
10616
|
+
return {
|
|
10617
|
+
success: true,
|
|
10618
|
+
data: {
|
|
10619
|
+
filterComponent: result.filterComponent,
|
|
10620
|
+
updatedComponents: result.updatedComponents || [],
|
|
10621
|
+
filterBindings: result.filterBindings || {},
|
|
10622
|
+
reasoning: result.reasoning || "Filter created based on user prompt"
|
|
10623
|
+
},
|
|
10624
|
+
errors: []
|
|
10625
|
+
};
|
|
10626
|
+
} catch (error) {
|
|
10627
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
10628
|
+
logger.error(`[DASH_COMP_REQ:FILTER] Error creating filter: ${errorMsg}`);
|
|
10629
|
+
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", error instanceof Error ? error : new Error(errorMsg), {
|
|
10630
|
+
prompt,
|
|
10631
|
+
existingComponentsCount: existingComponents.length
|
|
10632
|
+
});
|
|
10633
|
+
errors.push(errorMsg);
|
|
10634
|
+
return { success: false, errors };
|
|
10635
|
+
}
|
|
10636
|
+
}
|
|
10637
|
+
|
|
10638
|
+
// src/dashComp/index.ts
|
|
10371
10639
|
var processDashCompRequest = async (data, components, _sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, dashCompModels) => {
|
|
10372
10640
|
const errors = [];
|
|
10373
10641
|
logger.debug("[DASH_COMP_REQ] Parsing incoming message data");
|
|
@@ -10382,17 +10650,25 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
10382
10650
|
const dashCompRequest = parseResult.data;
|
|
10383
10651
|
const { id, payload } = dashCompRequest;
|
|
10384
10652
|
const prompt = payload.prompt;
|
|
10653
|
+
const reqType = payload.req_type || "create";
|
|
10654
|
+
const existingComponents = payload.existingComponents || [];
|
|
10385
10655
|
const wsId = dashCompRequest.from.id || "unknown";
|
|
10386
|
-
const promptContext = `DASH_COMP: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
10656
|
+
const promptContext = `DASH_COMP[${reqType}]: ${prompt?.substring(0, 50)}${(prompt?.length || 0) > 50 ? "..." : ""}`;
|
|
10387
10657
|
llmUsageLogger.resetLogFile(promptContext);
|
|
10388
10658
|
if (!prompt) {
|
|
10389
10659
|
errors.push("Prompt is required");
|
|
10390
10660
|
}
|
|
10661
|
+
if (reqType === "filter" && existingComponents.length === 0) {
|
|
10662
|
+
errors.push("Filter request requires existingComponents");
|
|
10663
|
+
}
|
|
10391
10664
|
if (errors.length > 0) {
|
|
10392
10665
|
return { success: false, errors, id, wsId };
|
|
10393
10666
|
}
|
|
10394
|
-
logger.info(`[DASH_COMP_REQ] Processing request for prompt: "${prompt.substring(0, 50)}..."`);
|
|
10667
|
+
logger.info(`[DASH_COMP_REQ] Processing ${reqType} request for prompt: "${prompt.substring(0, 50)}..."`);
|
|
10395
10668
|
logger.info(`[DASH_COMP_REQ] Available: ${components?.length || 0} components, ${tools?.length || 0} tools`);
|
|
10669
|
+
if (existingComponents.length > 0) {
|
|
10670
|
+
logger.info(`[DASH_COMP_REQ] Existing components in dashboard: ${existingComponents.length}`);
|
|
10671
|
+
}
|
|
10396
10672
|
if (!components || components.length === 0) {
|
|
10397
10673
|
logger.warn("[DASH_COMP_REQ] No components available");
|
|
10398
10674
|
return {
|
|
@@ -10402,19 +10678,35 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
10402
10678
|
wsId
|
|
10403
10679
|
};
|
|
10404
10680
|
}
|
|
10405
|
-
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10681
|
+
let llmResponse;
|
|
10682
|
+
if (reqType === "filter") {
|
|
10683
|
+
llmResponse = await createFilterWithLLM(
|
|
10684
|
+
prompt,
|
|
10685
|
+
components,
|
|
10686
|
+
existingComponents,
|
|
10687
|
+
anthropicApiKey,
|
|
10688
|
+
groqApiKey,
|
|
10689
|
+
geminiApiKey,
|
|
10690
|
+
openaiApiKey,
|
|
10691
|
+
llmProviders,
|
|
10692
|
+
tools,
|
|
10693
|
+
dashCompModels
|
|
10694
|
+
);
|
|
10695
|
+
} else {
|
|
10696
|
+
llmResponse = await pickComponentWithLLM(
|
|
10697
|
+
prompt,
|
|
10698
|
+
components,
|
|
10699
|
+
anthropicApiKey,
|
|
10700
|
+
groqApiKey,
|
|
10701
|
+
geminiApiKey,
|
|
10702
|
+
openaiApiKey,
|
|
10703
|
+
llmProviders,
|
|
10704
|
+
collections,
|
|
10705
|
+
tools,
|
|
10706
|
+
dashCompModels
|
|
10707
|
+
);
|
|
10708
|
+
}
|
|
10709
|
+
llmUsageLogger.logSessionSummary(`DASH_COMP[${reqType}]: ${prompt?.substring(0, 30)}`);
|
|
10418
10710
|
return {
|
|
10419
10711
|
success: llmResponse.success,
|
|
10420
10712
|
data: llmResponse.data,
|
|
@@ -10447,22 +10739,7 @@ async function handleDashCompRequest(data, components, sendMessage, anthropicApi
|
|
|
10447
10739
|
sendMessage,
|
|
10448
10740
|
response.wsId || data.from?.id
|
|
10449
10741
|
);
|
|
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}`);
|
|
10742
|
+
logger.info(`[DASH_COMP_REQ] Response sent to client ${response.wsId || data.from?.id}`);
|
|
10466
10743
|
}
|
|
10467
10744
|
|
|
10468
10745
|
// src/auth/user-manager.ts
|
|
@@ -11310,7 +11587,6 @@ var SuperatomSDK = class {
|
|
|
11310
11587
|
}
|
|
11311
11588
|
this.apiKey = config.apiKey;
|
|
11312
11589
|
this.projectId = config.projectId;
|
|
11313
|
-
this.userId = config.userId || "anonymous";
|
|
11314
11590
|
this.type = config.type || "data-agent";
|
|
11315
11591
|
this.bundleDir = config.bundleDir;
|
|
11316
11592
|
this.url = config.url || process.env.SA_WEBSOCKET_URL || DEFAULT_WS_URL;
|
|
@@ -11412,7 +11688,6 @@ var SuperatomSDK = class {
|
|
|
11412
11688
|
url.searchParams.set("apiKey", this.apiKey);
|
|
11413
11689
|
}
|
|
11414
11690
|
url.searchParams.set("projectId", this.projectId);
|
|
11415
|
-
url.searchParams.set("userId", this.userId);
|
|
11416
11691
|
url.searchParams.set("type", this.type);
|
|
11417
11692
|
logger.info(`Connecting to WebSocket: ${url.toString()}`);
|
|
11418
11693
|
this.ws = createWebSocket(url.toString());
|
|
@@ -11473,7 +11748,7 @@ var SuperatomSDK = class {
|
|
|
11473
11748
|
});
|
|
11474
11749
|
break;
|
|
11475
11750
|
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
|
|
11751
|
+
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
11752
|
logger.error("Failed to handle user prompt request:", error);
|
|
11478
11753
|
});
|
|
11479
11754
|
break;
|
|
@@ -11483,7 +11758,7 @@ var SuperatomSDK = class {
|
|
|
11483
11758
|
});
|
|
11484
11759
|
break;
|
|
11485
11760
|
case "USER_PROMPT_SUGGESTIONS_REQ":
|
|
11486
|
-
handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections
|
|
11761
|
+
handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections).catch((error) => {
|
|
11487
11762
|
logger.error("Failed to handle user prompt suggestions request:", error);
|
|
11488
11763
|
});
|
|
11489
11764
|
break;
|