@superatomai/sdk-node 0.0.33 → 0.0.35

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/dist/index.js CHANGED
@@ -1033,6 +1033,143 @@ If adaptation is not possible or would fundamentally change the component:
1033
1033
  4. **Preserve structure**: Keep the same number and type of components
1034
1034
 
1035
1035
  5. **Return complete JSON** with all adapted properties for all components`
1036
+ },
1037
+ "dash-comp-picker": {
1038
+ system: `You are a component selection expert that picks the best dashboard component and generates complete props based on user requests.
1039
+
1040
+ ## Your Task
1041
+
1042
+ Analyze the user's request and:
1043
+ 1. **Select the most appropriate component** from the available components list
1044
+ 2. **Determine the data source**: Database query OR External tool (ERP)
1045
+ 3. **Generate complete props** for the selected component including the data retrieval/modification method
1046
+
1047
+ ## Component Selection Rules
1048
+
1049
+ 1. **Match by Intent**: Understand what the user wants to display/achieve
1050
+ 2. **Match by Type**: Choose the component type that best fits the data visualization or action need
1051
+ 3. **Match by Description**: Use component descriptions and keywords to find the best fit
1052
+
1053
+ ## Data Source Decision
1054
+
1055
+ ### Use DATABASE when:
1056
+ - User asks about data that exists in the database schema (customers, orders, products, etc.)
1057
+ - Questions about internal business data (sales, inventory, users, transactions)
1058
+ - CRUD operations on database tables
1059
+
1060
+ ### Use EXTERNAL TOOL when:
1061
+ - User mentions specific external systems (ERP, CRM, email, calendar, etc.)
1062
+ - Data not available in database schema
1063
+ - Actions that require external integrations (send email, create calendar event, sync with ERP)
1064
+ - Tool description matches the user's request
1065
+
1066
+ ## Props Generation Rules
1067
+
1068
+ **CRITICAL**: Look at each component's "Props Structure" in the available components list. Generate ALL props that the component expects.
1069
+
1070
+ ### For Data Viewing Components (charts, tables, KPIs):
1071
+
1072
+ **Option A: Database Query** (when data is in database)
1073
+ \`\`\`json
1074
+ {
1075
+ "query": {
1076
+ "sql": "SELECT column1, column2 FROM table WHERE condition = $param LIMIT 32",
1077
+ "params": { "param": "value" }
1078
+ }
1079
+ }
1080
+ \`\`\`
1081
+
1082
+ **Option B: External Tool** (when data is from ERP/external system)
1083
+ \`\`\`json
1084
+ {
1085
+ "externalTool": {
1086
+ "toolId": "tool_id_from_list",
1087
+ "toolName": "Tool Display Name",
1088
+ "action": "get",
1089
+ "params": {
1090
+ "param1": "value1",
1091
+ "param2": "value2"
1092
+ }
1093
+ }
1094
+ }
1095
+ \`\`\`
1096
+
1097
+ ### For Data Modification Components (forms):
1098
+
1099
+ **Option A: Database Mutation**
1100
+ \`\`\`json
1101
+ {
1102
+ "query": {
1103
+ "sql": "INSERT INTO table (col1, col2) VALUES ($col1, $col2)",
1104
+ "params": {}
1105
+ },
1106
+ "fields": [
1107
+ { "name": "col1", "type": "text", "required": true },
1108
+ { "name": "col2", "type": "number", "required": false }
1109
+ ]
1110
+ }
1111
+ \`\`\`
1112
+
1113
+ **Option B: External Tool Mutation**
1114
+ \`\`\`json
1115
+ {
1116
+ "externalTool": {
1117
+ "toolId": "tool_id_from_list",
1118
+ "toolName": "Tool Display Name",
1119
+ "action": "create|update|delete",
1120
+ "params": {
1121
+ "param1": "value_or_placeholder"
1122
+ }
1123
+ },
1124
+ "fields": [
1125
+ { "name": "param1", "type": "text", "required": true }
1126
+ ]
1127
+ }
1128
+ \`\`\`
1129
+
1130
+ ### Database Query Rules
1131
+ {{DATABASE_RULES}}
1132
+
1133
+ ## Output Format
1134
+
1135
+ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
1136
+
1137
+ {
1138
+ "componentId": "id_from_available_list",
1139
+ "componentName": "name_of_component",
1140
+ "componentType": "type_of_component",
1141
+ "dataSourceType": "database" | "external_tool",
1142
+ "operationType": "view" | "create" | "update" | "delete",
1143
+ "reasoning": "Why this component was selected and why this data source",
1144
+ "props": {
1145
+ // Generate ALL props based on the component's Props Structure
1146
+ // Include either "query" OR "externalTool" based on data source
1147
+ // Include all other required props (title, description, config, fields, etc.)
1148
+ }
1149
+ }
1150
+
1151
+ **CRITICAL:**
1152
+ - Return ONLY valid JSON (no markdown code blocks, no text before/after)
1153
+ - \`componentId\` MUST match an ID from the available components list
1154
+ - \`dataSourceType\` indicates whether data comes from database or external tool
1155
+ - \`operationType\` indicates the type of operation (view/create/update/delete)
1156
+ - Generate COMPLETE props based on the component's "Props Structure"
1157
+ - For queries, ALWAYS use \`$paramName\` placeholders and include \`params\` object
1158
+ - For external tools, \`toolId\` MUST match an ID from the available tools list
1159
+
1160
+ ---
1161
+
1162
+ ## CONTEXT (for this specific request)
1163
+
1164
+ ### Database Schema
1165
+ {{SCHEMA_DOC}}
1166
+
1167
+ ### Available External Tools
1168
+ {{AVAILABLE_TOOLS}}
1169
+
1170
+ ### Available Components
1171
+ {{AVAILABLE_COMPONENTS}}`,
1172
+ user: `{{USER_PROMPT}}`
1036
1173
  }
1037
1174
  };
1038
1175
  }
@@ -2058,6 +2195,19 @@ var KbNodesRequestMessageSchema = import_zod3.z.object({
2058
2195
  type: import_zod3.z.literal("KB_NODES"),
2059
2196
  payload: KbNodesRequestPayloadSchema
2060
2197
  });
2198
+ var DashCompRequestPayloadSchema = import_zod3.z.object({
2199
+ prompt: import_zod3.z.string(),
2200
+ SA_RUNTIME: import_zod3.z.object({
2201
+ threadId: import_zod3.z.string().optional(),
2202
+ uiBlockId: import_zod3.z.string().optional()
2203
+ }).optional()
2204
+ });
2205
+ var DashCompRequestMessageSchema = import_zod3.z.object({
2206
+ id: import_zod3.z.string(),
2207
+ from: MessageParticipantSchema,
2208
+ type: import_zod3.z.literal("DASH_COMP_REQ"),
2209
+ payload: DashCompRequestPayloadSchema
2210
+ });
2061
2211
 
2062
2212
  // src/index.ts
2063
2213
  init_logger();
@@ -3970,19 +4120,44 @@ var LLM = class {
3970
4120
  }
3971
4121
  const firstBrace = jsonText.indexOf("{");
3972
4122
  const firstBracket = jsonText.indexOf("[");
3973
- const lastBrace = jsonText.lastIndexOf("}");
3974
- const lastBracket = jsonText.lastIndexOf("]");
3975
4123
  let startIdx = -1;
3976
- let endIdx = -1;
4124
+ let openChar = "";
4125
+ let closeChar = "";
3977
4126
  if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {
3978
4127
  startIdx = firstBrace;
3979
- endIdx = lastBrace;
4128
+ openChar = "{";
4129
+ closeChar = "}";
3980
4130
  } else if (firstBracket !== -1) {
3981
4131
  startIdx = firstBracket;
3982
- endIdx = lastBracket;
3983
- }
3984
- if (startIdx !== -1 && endIdx !== -1 && startIdx < endIdx) {
3985
- jsonText = jsonText.substring(startIdx, endIdx + 1);
4132
+ openChar = "[";
4133
+ closeChar = "]";
4134
+ }
4135
+ if (startIdx !== -1) {
4136
+ let depth = 0;
4137
+ let inString = false;
4138
+ let endIdx = -1;
4139
+ for (let i = startIdx; i < jsonText.length; i++) {
4140
+ const char = jsonText[i];
4141
+ const prevChar = i > 0 ? jsonText[i - 1] : "";
4142
+ if (char === '"' && prevChar !== "\\") {
4143
+ inString = !inString;
4144
+ continue;
4145
+ }
4146
+ if (!inString) {
4147
+ if (char === openChar) {
4148
+ depth++;
4149
+ } else if (char === closeChar) {
4150
+ depth--;
4151
+ if (depth === 0) {
4152
+ endIdx = i;
4153
+ break;
4154
+ }
4155
+ }
4156
+ }
4157
+ }
4158
+ if (endIdx !== -1) {
4159
+ jsonText = jsonText.substring(startIdx, endIdx + 1);
4160
+ }
3986
4161
  }
3987
4162
  try {
3988
4163
  const repairedJson = (0, import_jsonrepair.jsonrepair)(jsonText);
@@ -5605,7 +5780,7 @@ var AnthropicLLM = class extends BaseLLM {
5605
5780
  super(config);
5606
5781
  }
5607
5782
  getDefaultModel() {
5608
- return "anthropic/claude-haiku-4-5-20251001";
5783
+ return "anthropic/claude-sonnet-4-5-20250929";
5609
5784
  }
5610
5785
  getDefaultApiKey() {
5611
5786
  return process.env.ANTHROPIC_API_KEY;
@@ -8983,6 +9158,219 @@ function sendResponse8(id, res, sendMessage, clientId) {
8983
9158
  sendMessage(response);
8984
9159
  }
8985
9160
 
9161
+ // src/handlers/dash-comp-request.ts
9162
+ init_logger();
9163
+ init_prompt_loader();
9164
+ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, _collections, tools) {
9165
+ const errors = [];
9166
+ let availableComponentsText = "No components available";
9167
+ if (components && components.length > 0) {
9168
+ availableComponentsText = components.map((comp, idx) => {
9169
+ const keywords = comp.keywords ? comp.keywords.join(", ") : "";
9170
+ const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
9171
+ return `${idx + 1}. ID: ${comp.id}
9172
+ Name: ${comp.name}
9173
+ Type: ${comp.type}
9174
+ Description: ${comp.description || "No description"}
9175
+ Keywords: ${keywords}
9176
+ Props Structure: ${propsPreview}`;
9177
+ }).join("\n\n");
9178
+ }
9179
+ let availableToolsText = "No external tools available.";
9180
+ if (tools && tools.length > 0) {
9181
+ availableToolsText = tools.map((tool, idx) => {
9182
+ const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
9183
+ return `${idx + 1}. ID: ${tool.id}
9184
+ Name: ${tool.name}
9185
+ Description: ${tool.description}
9186
+ Parameters: { ${paramsStr} }`;
9187
+ }).join("\n\n");
9188
+ }
9189
+ try {
9190
+ const schemaDoc = schema.generateSchemaDocumentation();
9191
+ const databaseRules = await promptLoader.loadDatabaseRules();
9192
+ const prompts = await promptLoader.loadPrompts("dash-comp-picker", {
9193
+ USER_PROMPT: prompt,
9194
+ AVAILABLE_COMPONENTS: availableComponentsText,
9195
+ SCHEMA_DOC: schemaDoc || "No database schema available",
9196
+ DATABASE_RULES: databaseRules,
9197
+ AVAILABLE_TOOLS: availableToolsText
9198
+ });
9199
+ logger.debug("[DASH_COMP_REQ] Loaded dash-comp-picker prompts with schema and tools");
9200
+ const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
9201
+ let apiKey;
9202
+ let model = "anthropic/claude-sonnet-4-5-20250929";
9203
+ for (const provider of providers) {
9204
+ if (provider === "anthropic" && anthropicApiKey) {
9205
+ apiKey = anthropicApiKey;
9206
+ model = "anthropic/claude-sonnet-4-5-20250929";
9207
+ break;
9208
+ } else if (provider === "openai" && openaiApiKey) {
9209
+ apiKey = openaiApiKey;
9210
+ model = "openai/gpt-4o-mini";
9211
+ break;
9212
+ } else if (provider === "gemini" && geminiApiKey) {
9213
+ apiKey = geminiApiKey;
9214
+ model = "google/gemini-2.0-flash-001";
9215
+ break;
9216
+ } else if (provider === "groq" && groqApiKey) {
9217
+ apiKey = groqApiKey;
9218
+ model = "groq/llama-3.3-70b-versatile";
9219
+ break;
9220
+ }
9221
+ }
9222
+ if (!apiKey) {
9223
+ errors.push("No API key available for any LLM provider");
9224
+ return { success: false, errors };
9225
+ }
9226
+ logger.info(`[DASH_COMP_REQ] Using model: ${model}`);
9227
+ const result = await LLM.stream(
9228
+ {
9229
+ sys: prompts.system,
9230
+ user: prompts.user
9231
+ },
9232
+ {
9233
+ model,
9234
+ maxTokens: 3e3,
9235
+ temperature: 0.2,
9236
+ apiKey
9237
+ },
9238
+ true
9239
+ // Parse as JSON
9240
+ );
9241
+ logger.debug("[DASH_COMP_REQ] LLM response received");
9242
+ logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(result, null, 2));
9243
+ if (!result.componentId || !result.props) {
9244
+ errors.push("Invalid LLM response: missing componentId or props");
9245
+ return { success: false, errors };
9246
+ }
9247
+ const originalComponent = components.find((c) => c.id === result.componentId);
9248
+ if (!originalComponent) {
9249
+ errors.push(`Component ${result.componentId} not found in available components`);
9250
+ return { success: false, errors };
9251
+ }
9252
+ const finalComponent = {
9253
+ ...originalComponent,
9254
+ props: {
9255
+ ...originalComponent.props,
9256
+ ...result.props
9257
+ }
9258
+ };
9259
+ logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
9260
+ if (result.props.query) {
9261
+ logger.info(`[DASH_COMP_REQ] Data source: Database query`);
9262
+ }
9263
+ if (result.props.externalTool) {
9264
+ logger.info(`[DASH_COMP_REQ] Data source: External tool - ${result.props.externalTool.toolName}`);
9265
+ }
9266
+ return {
9267
+ success: true,
9268
+ data: {
9269
+ component: finalComponent,
9270
+ reasoning: result.reasoning || "Component selected based on user prompt",
9271
+ dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none"
9272
+ },
9273
+ errors: []
9274
+ };
9275
+ } catch (error) {
9276
+ const errorMsg = error instanceof Error ? error.message : String(error);
9277
+ logger.error(`[DASH_COMP_REQ] Error picking component: ${errorMsg}`);
9278
+ errors.push(errorMsg);
9279
+ return { success: false, errors };
9280
+ }
9281
+ }
9282
+ var processDashCompRequest = async (data, components, _sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools) => {
9283
+ const errors = [];
9284
+ logger.debug("[DASH_COMP_REQ] Parsing incoming message data");
9285
+ const parseResult = DashCompRequestMessageSchema.safeParse(data);
9286
+ if (!parseResult.success) {
9287
+ const zodError = parseResult.error;
9288
+ zodError.errors.forEach((err) => {
9289
+ errors.push(`${err.path.join(".")}: ${err.message}`);
9290
+ });
9291
+ return { success: false, errors };
9292
+ }
9293
+ const dashCompRequest = parseResult.data;
9294
+ const { id, payload } = dashCompRequest;
9295
+ const prompt = payload.prompt;
9296
+ const wsId = dashCompRequest.from.id || "unknown";
9297
+ if (!prompt) {
9298
+ errors.push("Prompt is required");
9299
+ }
9300
+ if (errors.length > 0) {
9301
+ return { success: false, errors, id, wsId };
9302
+ }
9303
+ logger.info(`[DASH_COMP_REQ] Processing request for prompt: "${prompt.substring(0, 50)}..."`);
9304
+ logger.info(`[DASH_COMP_REQ] Available: ${components?.length || 0} components, ${tools?.length || 0} tools`);
9305
+ if (!components || components.length === 0) {
9306
+ logger.warn("[DASH_COMP_REQ] No components available");
9307
+ return {
9308
+ success: false,
9309
+ errors: ["No components available. Please ensure components are loaded."],
9310
+ id,
9311
+ wsId
9312
+ };
9313
+ }
9314
+ const llmResponse = await pickComponentWithLLM(
9315
+ prompt,
9316
+ components,
9317
+ anthropicApiKey,
9318
+ groqApiKey,
9319
+ geminiApiKey,
9320
+ openaiApiKey,
9321
+ llmProviders,
9322
+ collections,
9323
+ tools
9324
+ );
9325
+ return {
9326
+ success: llmResponse.success,
9327
+ data: llmResponse.data,
9328
+ errors: llmResponse.errors,
9329
+ id,
9330
+ wsId
9331
+ };
9332
+ };
9333
+ async function handleDashCompRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools) {
9334
+ const response = await processDashCompRequest(
9335
+ data,
9336
+ components,
9337
+ sendMessage,
9338
+ anthropicApiKey,
9339
+ groqApiKey,
9340
+ geminiApiKey,
9341
+ openaiApiKey,
9342
+ llmProviders,
9343
+ collections,
9344
+ tools
9345
+ );
9346
+ sendDashCompResponse(
9347
+ response.id || data.id,
9348
+ {
9349
+ success: response.success,
9350
+ errors: response.errors,
9351
+ data: response.data
9352
+ },
9353
+ sendMessage,
9354
+ response.wsId || data.from?.id
9355
+ );
9356
+ }
9357
+ function sendDashCompResponse(id, res, sendMessage, clientId) {
9358
+ const response = {
9359
+ id,
9360
+ type: "DASH_COMP_RES",
9361
+ from: { type: "data-agent" },
9362
+ to: {
9363
+ type: "runtime",
9364
+ id: clientId
9365
+ },
9366
+ payload: {
9367
+ ...res
9368
+ }
9369
+ };
9370
+ sendMessage(response);
9371
+ logger.info(`[DASH_COMP_REQ] Response sent to client ${clientId}`);
9372
+ }
9373
+
8986
9374
  // src/auth/user-manager.ts
8987
9375
  var import_fs4 = __toESM(require("fs"));
8988
9376
  var import_path3 = __toESM(require("path"));
@@ -10038,6 +10426,11 @@ var SuperatomSDK = class {
10038
10426
  logger.error("Failed to handle KB nodes request:", error);
10039
10427
  });
10040
10428
  break;
10429
+ case "DASH_COMP_REQ":
10430
+ handleDashCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
10431
+ logger.error("Failed to handle dash comp request:", error);
10432
+ });
10433
+ break;
10041
10434
  default:
10042
10435
  const handler = this.messageTypeHandlers.get(message.type);
10043
10436
  if (handler) {