@superatomai/sdk-node 0.0.32 → 0.0.34

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.mjs CHANGED
@@ -1011,6 +1011,143 @@ If adaptation is not possible or would fundamentally change the component:
1011
1011
  4. **Preserve structure**: Keep the same number and type of components
1012
1012
 
1013
1013
  5. **Return complete JSON** with all adapted properties for all components`
1014
+ },
1015
+ "dash-comp-picker": {
1016
+ system: `You are a component selection expert that picks the best dashboard component and generates complete props based on user requests.
1017
+
1018
+ ## Your Task
1019
+
1020
+ Analyze the user's request and:
1021
+ 1. **Select the most appropriate component** from the available components list
1022
+ 2. **Determine the data source**: Database query OR External tool (ERP)
1023
+ 3. **Generate complete props** for the selected component including the data retrieval/modification method
1024
+
1025
+ ## Component Selection Rules
1026
+
1027
+ 1. **Match by Intent**: Understand what the user wants to display/achieve
1028
+ 2. **Match by Type**: Choose the component type that best fits the data visualization or action need
1029
+ 3. **Match by Description**: Use component descriptions and keywords to find the best fit
1030
+
1031
+ ## Data Source Decision
1032
+
1033
+ ### Use DATABASE when:
1034
+ - User asks about data that exists in the database schema (customers, orders, products, etc.)
1035
+ - Questions about internal business data (sales, inventory, users, transactions)
1036
+ - CRUD operations on database tables
1037
+
1038
+ ### Use EXTERNAL TOOL when:
1039
+ - User mentions specific external systems (ERP, CRM, email, calendar, etc.)
1040
+ - Data not available in database schema
1041
+ - Actions that require external integrations (send email, create calendar event, sync with ERP)
1042
+ - Tool description matches the user's request
1043
+
1044
+ ## Props Generation Rules
1045
+
1046
+ **CRITICAL**: Look at each component's "Props Structure" in the available components list. Generate ALL props that the component expects.
1047
+
1048
+ ### For Data Viewing Components (charts, tables, KPIs):
1049
+
1050
+ **Option A: Database Query** (when data is in database)
1051
+ \`\`\`json
1052
+ {
1053
+ "query": {
1054
+ "sql": "SELECT column1, column2 FROM table WHERE condition = $param LIMIT 32",
1055
+ "params": { "param": "value" }
1056
+ }
1057
+ }
1058
+ \`\`\`
1059
+
1060
+ **Option B: External Tool** (when data is from ERP/external system)
1061
+ \`\`\`json
1062
+ {
1063
+ "externalTool": {
1064
+ "toolId": "tool_id_from_list",
1065
+ "toolName": "Tool Display Name",
1066
+ "action": "get",
1067
+ "params": {
1068
+ "param1": "value1",
1069
+ "param2": "value2"
1070
+ }
1071
+ }
1072
+ }
1073
+ \`\`\`
1074
+
1075
+ ### For Data Modification Components (forms):
1076
+
1077
+ **Option A: Database Mutation**
1078
+ \`\`\`json
1079
+ {
1080
+ "query": {
1081
+ "sql": "INSERT INTO table (col1, col2) VALUES ($col1, $col2)",
1082
+ "params": {}
1083
+ },
1084
+ "fields": [
1085
+ { "name": "col1", "type": "text", "required": true },
1086
+ { "name": "col2", "type": "number", "required": false }
1087
+ ]
1088
+ }
1089
+ \`\`\`
1090
+
1091
+ **Option B: External Tool Mutation**
1092
+ \`\`\`json
1093
+ {
1094
+ "externalTool": {
1095
+ "toolId": "tool_id_from_list",
1096
+ "toolName": "Tool Display Name",
1097
+ "action": "create|update|delete",
1098
+ "params": {
1099
+ "param1": "value_or_placeholder"
1100
+ }
1101
+ },
1102
+ "fields": [
1103
+ { "name": "param1", "type": "text", "required": true }
1104
+ ]
1105
+ }
1106
+ \`\`\`
1107
+
1108
+ ### Database Query Rules
1109
+ {{DATABASE_RULES}}
1110
+
1111
+ ## Output Format
1112
+
1113
+ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
1114
+
1115
+ {
1116
+ "componentId": "id_from_available_list",
1117
+ "componentName": "name_of_component",
1118
+ "componentType": "type_of_component",
1119
+ "dataSourceType": "database" | "external_tool",
1120
+ "operationType": "view" | "create" | "update" | "delete",
1121
+ "reasoning": "Why this component was selected and why this data source",
1122
+ "props": {
1123
+ // Generate ALL props based on the component's Props Structure
1124
+ // Include either "query" OR "externalTool" based on data source
1125
+ // Include all other required props (title, description, config, fields, etc.)
1126
+ }
1127
+ }
1128
+
1129
+ **CRITICAL:**
1130
+ - Return ONLY valid JSON (no markdown code blocks, no text before/after)
1131
+ - \`componentId\` MUST match an ID from the available components list
1132
+ - \`dataSourceType\` indicates whether data comes from database or external tool
1133
+ - \`operationType\` indicates the type of operation (view/create/update/delete)
1134
+ - Generate COMPLETE props based on the component's "Props Structure"
1135
+ - For queries, ALWAYS use \`$paramName\` placeholders and include \`params\` object
1136
+ - For external tools, \`toolId\` MUST match an ID from the available tools list
1137
+
1138
+ ---
1139
+
1140
+ ## CONTEXT (for this specific request)
1141
+
1142
+ ### Database Schema
1143
+ {{SCHEMA_DOC}}
1144
+
1145
+ ### Available External Tools
1146
+ {{AVAILABLE_TOOLS}}
1147
+
1148
+ ### Available Components
1149
+ {{AVAILABLE_COMPONENTS}}`,
1150
+ user: `{{USER_PROMPT}}`
1014
1151
  }
1015
1152
  };
1016
1153
  }
@@ -1520,6 +1657,13 @@ var UIElementSchema = z.lazy(
1520
1657
  }).optional()
1521
1658
  })
1522
1659
  );
1660
+ var PageSchema = z.object({
1661
+ id: z.string(),
1662
+ name: z.string(),
1663
+ order: z.number(),
1664
+ icon: z.string().optional(),
1665
+ render: UIElementSchema
1666
+ });
1523
1667
  var UIComponentSchema = z.object({
1524
1668
  id: z.string(),
1525
1669
  name: z.string().optional(),
@@ -1539,7 +1683,9 @@ var UIComponentSchema = z.object({
1539
1683
  })
1540
1684
  ).optional(),
1541
1685
  data: z.record(z.string(), z.any()).optional(),
1542
- render: UIElementSchema,
1686
+ render: UIElementSchema.optional(),
1687
+ pages: z.array(PageSchema).optional(),
1688
+ defaultPageId: z.string().optional(),
1543
1689
  query: QuerySpecSchema.optional()
1544
1690
  });
1545
1691
  var DSLRendererPropsSchema = z.object({
@@ -2005,6 +2151,19 @@ var KbNodesRequestMessageSchema = z3.object({
2005
2151
  type: z3.literal("KB_NODES"),
2006
2152
  payload: KbNodesRequestPayloadSchema
2007
2153
  });
2154
+ var DashCompRequestPayloadSchema = z3.object({
2155
+ prompt: z3.string(),
2156
+ SA_RUNTIME: z3.object({
2157
+ threadId: z3.string().optional(),
2158
+ uiBlockId: z3.string().optional()
2159
+ }).optional()
2160
+ });
2161
+ var DashCompRequestMessageSchema = z3.object({
2162
+ id: z3.string(),
2163
+ from: MessageParticipantSchema,
2164
+ type: z3.literal("DASH_COMP_REQ"),
2165
+ payload: DashCompRequestPayloadSchema
2166
+ });
2008
2167
 
2009
2168
  // src/index.ts
2010
2169
  init_logger();
@@ -5552,7 +5711,7 @@ var AnthropicLLM = class extends BaseLLM {
5552
5711
  super(config);
5553
5712
  }
5554
5713
  getDefaultModel() {
5555
- return "anthropic/claude-haiku-4-5-20251001";
5714
+ return "anthropic/claude-sonnet-4-5-20250929";
5556
5715
  }
5557
5716
  getDefaultApiKey() {
5558
5717
  return process.env.ANTHROPIC_API_KEY;
@@ -8930,6 +9089,219 @@ function sendResponse8(id, res, sendMessage, clientId) {
8930
9089
  sendMessage(response);
8931
9090
  }
8932
9091
 
9092
+ // src/handlers/dash-comp-request.ts
9093
+ init_logger();
9094
+ init_prompt_loader();
9095
+ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, _collections, tools) {
9096
+ const errors = [];
9097
+ let availableComponentsText = "No components available";
9098
+ if (components && components.length > 0) {
9099
+ availableComponentsText = components.map((comp, idx) => {
9100
+ const keywords = comp.keywords ? comp.keywords.join(", ") : "";
9101
+ const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
9102
+ return `${idx + 1}. ID: ${comp.id}
9103
+ Name: ${comp.name}
9104
+ Type: ${comp.type}
9105
+ Description: ${comp.description || "No description"}
9106
+ Keywords: ${keywords}
9107
+ Props Structure: ${propsPreview}`;
9108
+ }).join("\n\n");
9109
+ }
9110
+ let availableToolsText = "No external tools available.";
9111
+ if (tools && tools.length > 0) {
9112
+ availableToolsText = tools.map((tool, idx) => {
9113
+ const paramsStr = Object.entries(tool.params || {}).map(([key, type]) => `${key}: ${type}`).join(", ");
9114
+ return `${idx + 1}. ID: ${tool.id}
9115
+ Name: ${tool.name}
9116
+ Description: ${tool.description}
9117
+ Parameters: { ${paramsStr} }`;
9118
+ }).join("\n\n");
9119
+ }
9120
+ try {
9121
+ const schemaDoc = schema.generateSchemaDocumentation();
9122
+ const databaseRules = await promptLoader.loadDatabaseRules();
9123
+ const prompts = await promptLoader.loadPrompts("dash-comp-picker", {
9124
+ USER_PROMPT: prompt,
9125
+ AVAILABLE_COMPONENTS: availableComponentsText,
9126
+ SCHEMA_DOC: schemaDoc || "No database schema available",
9127
+ DATABASE_RULES: databaseRules,
9128
+ AVAILABLE_TOOLS: availableToolsText
9129
+ });
9130
+ logger.debug("[DASH_COMP_REQ] Loaded dash-comp-picker prompts with schema and tools");
9131
+ const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
9132
+ let apiKey;
9133
+ let model = "anthropic/claude-sonnet-4-5-20250929";
9134
+ for (const provider of providers) {
9135
+ if (provider === "anthropic" && anthropicApiKey) {
9136
+ apiKey = anthropicApiKey;
9137
+ model = "anthropic/claude-sonnet-4-5-20250929";
9138
+ break;
9139
+ } else if (provider === "openai" && openaiApiKey) {
9140
+ apiKey = openaiApiKey;
9141
+ model = "openai/gpt-4o-mini";
9142
+ break;
9143
+ } else if (provider === "gemini" && geminiApiKey) {
9144
+ apiKey = geminiApiKey;
9145
+ model = "google/gemini-2.0-flash-001";
9146
+ break;
9147
+ } else if (provider === "groq" && groqApiKey) {
9148
+ apiKey = groqApiKey;
9149
+ model = "groq/llama-3.3-70b-versatile";
9150
+ break;
9151
+ }
9152
+ }
9153
+ if (!apiKey) {
9154
+ errors.push("No API key available for any LLM provider");
9155
+ return { success: false, errors };
9156
+ }
9157
+ logger.info(`[DASH_COMP_REQ] Using model: ${model}`);
9158
+ const result = await LLM.stream(
9159
+ {
9160
+ sys: prompts.system,
9161
+ user: prompts.user
9162
+ },
9163
+ {
9164
+ model,
9165
+ maxTokens: 3e3,
9166
+ temperature: 0.2,
9167
+ apiKey
9168
+ },
9169
+ true
9170
+ // Parse as JSON
9171
+ );
9172
+ logger.debug("[DASH_COMP_REQ] LLM response received");
9173
+ logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(result, null, 2));
9174
+ if (!result.componentId || !result.props) {
9175
+ errors.push("Invalid LLM response: missing componentId or props");
9176
+ return { success: false, errors };
9177
+ }
9178
+ const originalComponent = components.find((c) => c.id === result.componentId);
9179
+ if (!originalComponent) {
9180
+ errors.push(`Component ${result.componentId} not found in available components`);
9181
+ return { success: false, errors };
9182
+ }
9183
+ const finalComponent = {
9184
+ ...originalComponent,
9185
+ props: {
9186
+ ...originalComponent.props,
9187
+ ...result.props
9188
+ }
9189
+ };
9190
+ logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
9191
+ if (result.props.query) {
9192
+ logger.info(`[DASH_COMP_REQ] Data source: Database query`);
9193
+ }
9194
+ if (result.props.externalTool) {
9195
+ logger.info(`[DASH_COMP_REQ] Data source: External tool - ${result.props.externalTool.toolName}`);
9196
+ }
9197
+ return {
9198
+ success: true,
9199
+ data: {
9200
+ component: finalComponent,
9201
+ reasoning: result.reasoning || "Component selected based on user prompt",
9202
+ dataSource: result.props.query ? "database" : result.props.externalTool ? "external_tool" : "none"
9203
+ },
9204
+ errors: []
9205
+ };
9206
+ } catch (error) {
9207
+ const errorMsg = error instanceof Error ? error.message : String(error);
9208
+ logger.error(`[DASH_COMP_REQ] Error picking component: ${errorMsg}`);
9209
+ errors.push(errorMsg);
9210
+ return { success: false, errors };
9211
+ }
9212
+ }
9213
+ var processDashCompRequest = async (data, components, _sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools) => {
9214
+ const errors = [];
9215
+ logger.debug("[DASH_COMP_REQ] Parsing incoming message data");
9216
+ const parseResult = DashCompRequestMessageSchema.safeParse(data);
9217
+ if (!parseResult.success) {
9218
+ const zodError = parseResult.error;
9219
+ zodError.errors.forEach((err) => {
9220
+ errors.push(`${err.path.join(".")}: ${err.message}`);
9221
+ });
9222
+ return { success: false, errors };
9223
+ }
9224
+ const dashCompRequest = parseResult.data;
9225
+ const { id, payload } = dashCompRequest;
9226
+ const prompt = payload.prompt;
9227
+ const wsId = dashCompRequest.from.id || "unknown";
9228
+ if (!prompt) {
9229
+ errors.push("Prompt is required");
9230
+ }
9231
+ if (errors.length > 0) {
9232
+ return { success: false, errors, id, wsId };
9233
+ }
9234
+ logger.info(`[DASH_COMP_REQ] Processing request for prompt: "${prompt.substring(0, 50)}..."`);
9235
+ logger.info(`[DASH_COMP_REQ] Available: ${components?.length || 0} components, ${tools?.length || 0} tools`);
9236
+ if (!components || components.length === 0) {
9237
+ logger.warn("[DASH_COMP_REQ] No components available");
9238
+ return {
9239
+ success: false,
9240
+ errors: ["No components available. Please ensure components are loaded."],
9241
+ id,
9242
+ wsId
9243
+ };
9244
+ }
9245
+ const llmResponse = await pickComponentWithLLM(
9246
+ prompt,
9247
+ components,
9248
+ anthropicApiKey,
9249
+ groqApiKey,
9250
+ geminiApiKey,
9251
+ openaiApiKey,
9252
+ llmProviders,
9253
+ collections,
9254
+ tools
9255
+ );
9256
+ return {
9257
+ success: llmResponse.success,
9258
+ data: llmResponse.data,
9259
+ errors: llmResponse.errors,
9260
+ id,
9261
+ wsId
9262
+ };
9263
+ };
9264
+ async function handleDashCompRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools) {
9265
+ const response = await processDashCompRequest(
9266
+ data,
9267
+ components,
9268
+ sendMessage,
9269
+ anthropicApiKey,
9270
+ groqApiKey,
9271
+ geminiApiKey,
9272
+ openaiApiKey,
9273
+ llmProviders,
9274
+ collections,
9275
+ tools
9276
+ );
9277
+ sendDashCompResponse(
9278
+ response.id || data.id,
9279
+ {
9280
+ success: response.success,
9281
+ errors: response.errors,
9282
+ data: response.data
9283
+ },
9284
+ sendMessage,
9285
+ response.wsId || data.from?.id
9286
+ );
9287
+ }
9288
+ function sendDashCompResponse(id, res, sendMessage, clientId) {
9289
+ const response = {
9290
+ id,
9291
+ type: "DASH_COMP_RES",
9292
+ from: { type: "data-agent" },
9293
+ to: {
9294
+ type: "runtime",
9295
+ id: clientId
9296
+ },
9297
+ payload: {
9298
+ ...res
9299
+ }
9300
+ };
9301
+ sendMessage(response);
9302
+ logger.info(`[DASH_COMP_REQ] Response sent to client ${clientId}`);
9303
+ }
9304
+
8933
9305
  // src/auth/user-manager.ts
8934
9306
  init_logger();
8935
9307
  import fs5 from "fs";
@@ -9985,6 +10357,11 @@ var SuperatomSDK = class {
9985
10357
  logger.error("Failed to handle KB nodes request:", error);
9986
10358
  });
9987
10359
  break;
10360
+ case "DASH_COMP_REQ":
10361
+ handleDashCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools).catch((error) => {
10362
+ logger.error("Failed to handle dash comp request:", error);
10363
+ });
10364
+ break;
9988
10365
  default:
9989
10366
  const handler = this.messageTypeHandlers.get(message.type);
9990
10367
  if (handler) {