@superatomai/sdk-node 0.0.6 → 0.0.7

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
@@ -438,6 +438,7 @@ var require_main = __commonJS({
438
438
  // src/userResponse/utils.ts
439
439
  var utils_exports = {};
440
440
  __export(utils_exports, {
441
+ convertQuestionsToActions: () => convertQuestionsToActions,
441
442
  convertTopToLimit: () => convertTopToLimit,
442
443
  ensureQueryLimit: () => ensureQueryLimit,
443
444
  fixScalarSubqueries: () => fixScalarSubqueries,
@@ -539,6 +540,14 @@ function fixScalarSubqueries(query) {
539
540
  }
540
541
  return modifiedQuery;
541
542
  }
543
+ function convertQuestionsToActions(questions) {
544
+ return questions.map((question, index) => ({
545
+ id: `action_${index}_${Date.now()}`,
546
+ name: question,
547
+ type: "next_question",
548
+ question
549
+ }));
550
+ }
542
551
  function getJsonSizeInBytes(obj) {
543
552
  const jsonString = JSON.stringify(obj);
544
553
  return Buffer.byteLength(jsonString, "utf8");
@@ -841,7 +850,8 @@ var ComponentPropsSchema = z3.object({
841
850
  query: z3.string().optional(),
842
851
  title: z3.string().optional(),
843
852
  description: z3.string().optional(),
844
- config: z3.record(z3.unknown()).optional()
853
+ config: z3.record(z3.unknown()).optional(),
854
+ actions: z3.array(z3.any()).optional()
845
855
  });
846
856
  var ComponentSchema = z3.object({
847
857
  id: z3.string(),
@@ -1224,6 +1234,12 @@ var UIBlock = class {
1224
1234
  throw error;
1225
1235
  }
1226
1236
  }
1237
+ /**
1238
+ * Set or replace all actions
1239
+ */
1240
+ setActions(actions) {
1241
+ this.actions = actions;
1242
+ }
1227
1243
  /**
1228
1244
  * Add a single action (only if actions are resolved)
1229
1245
  */
@@ -2586,6 +2602,42 @@ var LLM = class {
2586
2602
  }
2587
2603
  };
2588
2604
 
2605
+ // src/userResponse/knowledge-base.ts
2606
+ var getKnowledgeBase = async ({
2607
+ prompt,
2608
+ collections,
2609
+ topK = 1
2610
+ }) => {
2611
+ try {
2612
+ if (!collections || !collections["knowledge-base"] || !collections["knowledge-base"]["query"]) {
2613
+ logger.info("[KnowledgeBase] knowledge-base.query collection not registered, skipping");
2614
+ return "";
2615
+ }
2616
+ logger.info(`[KnowledgeBase] Querying knowledge base for: "${prompt.substring(0, 50)}..."`);
2617
+ const result = await collections["knowledge-base"]["query"]({
2618
+ prompt,
2619
+ topK
2620
+ });
2621
+ if (!result || !result.content) {
2622
+ logger.error("[KnowledgeBase] No knowledge base results returned");
2623
+ return "";
2624
+ }
2625
+ logger.info(`[KnowledgeBase] Retrieved knowledge base context (${result.content.length} chars)`);
2626
+ if (result.metadata?.sources && result.metadata.sources.length > 0) {
2627
+ logger.debug(`[KnowledgeBase] Sources: ${result.metadata.sources.map((s) => s.title).join(", ")}`);
2628
+ }
2629
+ return result.content;
2630
+ } catch (error) {
2631
+ const errorMsg = error instanceof Error ? error.message : String(error);
2632
+ logger.warn(`[KnowledgeBase] Error querying knowledge base: ${errorMsg}`);
2633
+ return "";
2634
+ }
2635
+ };
2636
+ var KB = {
2637
+ getKnowledgeBase
2638
+ };
2639
+ var knowledge_base_default = KB;
2640
+
2589
2641
  // src/userResponse/base-llm.ts
2590
2642
  var BaseLLM = class {
2591
2643
  constructor(config) {
@@ -3125,13 +3177,14 @@ var BaseLLM = class {
3125
3177
  }
3126
3178
  }
3127
3179
  /**
3128
- * Match components from text response suggestions
3180
+ * Match components from text response suggestions and generate follow-up questions
3129
3181
  * Takes a text response with component suggestions (c1:type format) and matches with available components
3182
+ * Also generates intelligent follow-up questions (actions) based on the analysis
3130
3183
  * @param textResponse - The text response containing component suggestions
3131
3184
  * @param components - List of available components
3132
3185
  * @param apiKey - Optional API key
3133
3186
  * @param logCollector - Optional log collector
3134
- * @returns Object containing matched components, selected layout, and reasoning
3187
+ * @returns Object containing matched components, selected layout, reasoning, and follow-up actions
3135
3188
  */
3136
3189
  async matchComponentsFromTextResponse(textResponse, components, apiKey, logCollector) {
3137
3190
  try {
@@ -3173,7 +3226,6 @@ var BaseLLM = class {
3173
3226
  // Don't parse as JSON yet, get raw response
3174
3227
  );
3175
3228
  logger.debug(`[${this.getProviderName()}] Raw component matching response length: ${rawResponse?.length || 0}`);
3176
- logger.file(`[${this.getProviderName()}] Component matching raw response:`, rawResponse);
3177
3229
  let result;
3178
3230
  try {
3179
3231
  let cleanedResponse = rawResponse || "";
@@ -3216,7 +3268,8 @@ var BaseLLM = class {
3216
3268
  selectedLayout: "MultiComponentContainer",
3217
3269
  selectedLayoutId: "",
3218
3270
  selectedLayoutComponent: null,
3219
- layoutReasoning: "No layout selected"
3271
+ layoutReasoning: "No layout selected",
3272
+ actions: []
3220
3273
  };
3221
3274
  }
3222
3275
  }
@@ -3224,6 +3277,8 @@ var BaseLLM = class {
3224
3277
  const selectedLayout = result.selectedLayout || "MultiComponentContainer";
3225
3278
  const selectedLayoutId = result.selectedLayoutId || "";
3226
3279
  const layoutReasoning = result.layoutReasoning || "No layout reasoning provided";
3280
+ const rawActions = result.actions || [];
3281
+ const actions = convertQuestionsToActions(rawActions);
3227
3282
  let selectedLayoutComponent = null;
3228
3283
  if (selectedLayoutId) {
3229
3284
  selectedLayoutComponent = components.find((c) => c.id === selectedLayoutId) || null;
@@ -3234,6 +3289,7 @@ var BaseLLM = class {
3234
3289
  logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
3235
3290
  logger.info(`[${this.getProviderName()}] Selected layout: ${selectedLayout} (ID: ${selectedLayoutId})`);
3236
3291
  logger.info(`[${this.getProviderName()}] Layout reasoning: ${layoutReasoning}`);
3292
+ logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
3237
3293
  if (matchedComponents.length > 0) {
3238
3294
  logCollector?.info(`Matched ${matchedComponents.length} components for visualization using ${selectedLayout}`);
3239
3295
  logCollector?.info(`Layout reasoning: ${layoutReasoning}`);
@@ -3248,6 +3304,12 @@ var BaseLLM = class {
3248
3304
  }
3249
3305
  });
3250
3306
  }
3307
+ if (actions.length > 0) {
3308
+ logCollector?.info(`Generated ${actions.length} follow-up questions`);
3309
+ actions.forEach((action, idx) => {
3310
+ logCollector?.info(` ${idx + 1}. ${action.name}`);
3311
+ });
3312
+ }
3251
3313
  const finalComponents = matchedComponents.map((mc) => {
3252
3314
  const originalComponent = components.find((c) => c.id === mc.componentId);
3253
3315
  if (!originalComponent) {
@@ -3267,7 +3329,8 @@ var BaseLLM = class {
3267
3329
  selectedLayout,
3268
3330
  selectedLayoutId,
3269
3331
  selectedLayoutComponent,
3270
- layoutReasoning
3332
+ layoutReasoning,
3333
+ actions
3271
3334
  };
3272
3335
  } catch (error) {
3273
3336
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -3279,7 +3342,8 @@ var BaseLLM = class {
3279
3342
  selectedLayout: "MultiComponentContainer",
3280
3343
  selectedLayoutId: "",
3281
3344
  selectedLayoutComponent: null,
3282
- layoutReasoning: "Error occurred during component matching"
3345
+ layoutReasoning: "Error occurred during component matching",
3346
+ actions: []
3283
3347
  };
3284
3348
  }
3285
3349
  }
@@ -3298,10 +3362,17 @@ var BaseLLM = class {
3298
3362
  logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
3299
3363
  try {
3300
3364
  const schemaDoc = schema.generateSchemaDocumentation();
3365
+ const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
3366
+ prompt: userPrompt,
3367
+ collections,
3368
+ topK: 1
3369
+ });
3370
+ logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
3301
3371
  const prompts = await promptLoader.loadPrompts("text-response", {
3302
3372
  USER_PROMPT: userPrompt,
3303
3373
  CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
3304
- SCHEMA_DOC: schemaDoc
3374
+ SCHEMA_DOC: schemaDoc,
3375
+ KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available."
3305
3376
  });
3306
3377
  logger.file("\n=============================\nsystem prompt:", prompts.system);
3307
3378
  logger.file("\n=============================\nuser prompt:", prompts.user);
@@ -3502,6 +3573,7 @@ ${errorMsg}
3502
3573
  text: textResponse,
3503
3574
  // Include the streamed text showing all attempts
3504
3575
  matchedComponents: [],
3576
+ actions: [],
3505
3577
  method: `${this.getProviderName()}-text-response-max-attempts`
3506
3578
  }
3507
3579
  };
@@ -3517,6 +3589,7 @@ ${errorMsg}
3517
3589
  let matchedComponents = [];
3518
3590
  let selectedLayoutComponent = null;
3519
3591
  let layoutReasoning = "No layout selected";
3592
+ let actions = [];
3520
3593
  if (components && components.length > 0) {
3521
3594
  logger.info(`[${this.getProviderName()}] Matching components from text response...`);
3522
3595
  const matchResult = await this.matchComponentsFromTextResponse(
@@ -3528,6 +3601,7 @@ ${errorMsg}
3528
3601
  matchedComponents = matchResult.components;
3529
3602
  selectedLayoutComponent = matchResult.selectedLayoutComponent;
3530
3603
  layoutReasoning = matchResult.layoutReasoning;
3604
+ actions = matchResult.actions;
3531
3605
  }
3532
3606
  let container_componet = null;
3533
3607
  if (matchedComponents.length > 0) {
@@ -3541,11 +3615,12 @@ ${errorMsg}
3541
3615
  config: {
3542
3616
  ...selectedLayoutComponent.props?.config || {},
3543
3617
  components: matchedComponents
3544
- }
3618
+ },
3619
+ actions
3545
3620
  }
3546
3621
  };
3547
- logger.info(`[${this.getProviderName()}] Created ${selectedLayoutComponent.name} (${selectedLayoutComponent.type}) container with ${matchedComponents.length} components`);
3548
- logCollector?.info(`Created ${selectedLayoutComponent.name} with ${matchedComponents.length} components: ${layoutReasoning}`);
3622
+ logger.info(`[${this.getProviderName()}] Created ${selectedLayoutComponent.name} (${selectedLayoutComponent.type}) container with ${matchedComponents.length} components and ${actions.length} actions`);
3623
+ logCollector?.info(`Created ${selectedLayoutComponent.name} with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
3549
3624
  } else {
3550
3625
  container_componet = {
3551
3626
  id: `multi_container_${Date.now()}`,
@@ -3557,11 +3632,12 @@ ${errorMsg}
3557
3632
  props: {
3558
3633
  config: {
3559
3634
  components: matchedComponents
3560
- }
3635
+ },
3636
+ actions
3561
3637
  }
3562
3638
  };
3563
- logger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components`);
3564
- logCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components: ${layoutReasoning}`);
3639
+ logger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions`);
3640
+ logCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
3565
3641
  }
3566
3642
  }
3567
3643
  return {
@@ -3571,6 +3647,7 @@ ${errorMsg}
3571
3647
  matchedComponents,
3572
3648
  component: container_componet,
3573
3649
  layoutReasoning,
3650
+ actions,
3574
3651
  method: `${this.getProviderName()}-text-response`
3575
3652
  },
3576
3653
  errors: []
@@ -3586,6 +3663,7 @@ ${errorMsg}
3586
3663
  data: {
3587
3664
  text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
3588
3665
  matchedComponents: [],
3666
+ actions: [],
3589
3667
  method: `${this.getProviderName()}-text-response-error`
3590
3668
  }
3591
3669
  };
@@ -4336,6 +4414,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4336
4414
  }
4337
4415
  let component = null;
4338
4416
  let textResponse = null;
4417
+ let actions = [];
4339
4418
  if (userResponse.data) {
4340
4419
  if (typeof userResponse.data === "object") {
4341
4420
  if ("component" in userResponse.data) {
@@ -4344,6 +4423,9 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4344
4423
  if ("textResponse" in userResponse.data) {
4345
4424
  textResponse = userResponse.data.text;
4346
4425
  }
4426
+ if ("actions" in userResponse.data) {
4427
+ actions = userResponse.data.actions || [];
4428
+ }
4347
4429
  }
4348
4430
  }
4349
4431
  const finalTextResponse = responseMode === "text" && accumulatedStreamResponse ? accumulatedStreamResponse : textResponse;
@@ -4354,11 +4436,15 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4354
4436
  component,
4355
4437
  // generatedComponentMetadata: full component object (ComponentSchema)
4356
4438
  [],
4357
- // actions: empty initially
4439
+ // actions: empty initially, will be set below
4358
4440
  uiBlockId,
4359
4441
  finalTextResponse
4360
4442
  // textResponse: FULL streaming response including all intermediate messages
4361
4443
  );
4444
+ if (actions.length > 0) {
4445
+ uiBlock.setActions(actions);
4446
+ logger.info(`Stored ${actions.length} actions in UIBlock: ${uiBlockId}`);
4447
+ }
4362
4448
  thread.addUIBlock(uiBlock);
4363
4449
  logger.info(`Created UIBlock: ${uiBlockId} in Thread: ${threadId}`);
4364
4450
  return {
@@ -4596,7 +4682,6 @@ async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiK
4596
4682
  const uiBlockId = SA_RUNTIME.uiBlockId;
4597
4683
  const threadId = SA_RUNTIME.threadId;
4598
4684
  logger.debug(`[ACTIONS_REQ ${id}] SA_RUNTIME validated - threadId: ${threadId}, uiBlockId: ${uiBlockId}`);
4599
- logger.debug(`[ACTIONS_REQ ${id}] Retrieving thread: ${threadId}`);
4600
4685
  const threadManager = ThreadManager.getInstance();
4601
4686
  const thread = threadManager.getThread(threadId);
4602
4687
  if (!thread) {