@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.d.mts CHANGED
@@ -1042,6 +1042,10 @@ declare class UIBlock {
1042
1042
  * @returns Promise resolving to Action[]
1043
1043
  */
1044
1044
  getOrFetchActions(generateFn: () => Promise<Action[]>): Promise<Action[]>;
1045
+ /**
1046
+ * Set or replace all actions
1047
+ */
1048
+ setActions(actions: Action[]): void;
1045
1049
  /**
1046
1050
  * Add a single action (only if actions are resolved)
1047
1051
  */
package/dist/index.d.ts CHANGED
@@ -1042,6 +1042,10 @@ declare class UIBlock {
1042
1042
  * @returns Promise resolving to Action[]
1043
1043
  */
1044
1044
  getOrFetchActions(generateFn: () => Promise<Action[]>): Promise<Action[]>;
1045
+ /**
1046
+ * Set or replace all actions
1047
+ */
1048
+ setActions(actions: Action[]): void;
1045
1049
  /**
1046
1050
  * Add a single action (only if actions are resolved)
1047
1051
  */
package/dist/index.js CHANGED
@@ -434,6 +434,7 @@ var require_main = __commonJS({
434
434
  // src/userResponse/utils.ts
435
435
  var utils_exports = {};
436
436
  __export(utils_exports, {
437
+ convertQuestionsToActions: () => convertQuestionsToActions,
437
438
  convertTopToLimit: () => convertTopToLimit,
438
439
  ensureQueryLimit: () => ensureQueryLimit,
439
440
  fixScalarSubqueries: () => fixScalarSubqueries,
@@ -535,6 +536,14 @@ function fixScalarSubqueries(query) {
535
536
  }
536
537
  return modifiedQuery;
537
538
  }
539
+ function convertQuestionsToActions(questions) {
540
+ return questions.map((question, index) => ({
541
+ id: `action_${index}_${Date.now()}`,
542
+ name: question,
543
+ type: "next_question",
544
+ question
545
+ }));
546
+ }
538
547
  function getJsonSizeInBytes(obj) {
539
548
  const jsonString = JSON.stringify(obj);
540
549
  return Buffer.byteLength(jsonString, "utf8");
@@ -855,7 +864,8 @@ var ComponentPropsSchema = import_zod3.z.object({
855
864
  query: import_zod3.z.string().optional(),
856
865
  title: import_zod3.z.string().optional(),
857
866
  description: import_zod3.z.string().optional(),
858
- config: import_zod3.z.record(import_zod3.z.unknown()).optional()
867
+ config: import_zod3.z.record(import_zod3.z.unknown()).optional(),
868
+ actions: import_zod3.z.array(import_zod3.z.any()).optional()
859
869
  });
860
870
  var ComponentSchema = import_zod3.z.object({
861
871
  id: import_zod3.z.string(),
@@ -1238,6 +1248,12 @@ var UIBlock = class {
1238
1248
  throw error;
1239
1249
  }
1240
1250
  }
1251
+ /**
1252
+ * Set or replace all actions
1253
+ */
1254
+ setActions(actions) {
1255
+ this.actions = actions;
1256
+ }
1241
1257
  /**
1242
1258
  * Add a single action (only if actions are resolved)
1243
1259
  */
@@ -2600,6 +2616,42 @@ var LLM = class {
2600
2616
  }
2601
2617
  };
2602
2618
 
2619
+ // src/userResponse/knowledge-base.ts
2620
+ var getKnowledgeBase = async ({
2621
+ prompt,
2622
+ collections,
2623
+ topK = 1
2624
+ }) => {
2625
+ try {
2626
+ if (!collections || !collections["knowledge-base"] || !collections["knowledge-base"]["query"]) {
2627
+ logger.info("[KnowledgeBase] knowledge-base.query collection not registered, skipping");
2628
+ return "";
2629
+ }
2630
+ logger.info(`[KnowledgeBase] Querying knowledge base for: "${prompt.substring(0, 50)}..."`);
2631
+ const result = await collections["knowledge-base"]["query"]({
2632
+ prompt,
2633
+ topK
2634
+ });
2635
+ if (!result || !result.content) {
2636
+ logger.error("[KnowledgeBase] No knowledge base results returned");
2637
+ return "";
2638
+ }
2639
+ logger.info(`[KnowledgeBase] Retrieved knowledge base context (${result.content.length} chars)`);
2640
+ if (result.metadata?.sources && result.metadata.sources.length > 0) {
2641
+ logger.debug(`[KnowledgeBase] Sources: ${result.metadata.sources.map((s) => s.title).join(", ")}`);
2642
+ }
2643
+ return result.content;
2644
+ } catch (error) {
2645
+ const errorMsg = error instanceof Error ? error.message : String(error);
2646
+ logger.warn(`[KnowledgeBase] Error querying knowledge base: ${errorMsg}`);
2647
+ return "";
2648
+ }
2649
+ };
2650
+ var KB = {
2651
+ getKnowledgeBase
2652
+ };
2653
+ var knowledge_base_default = KB;
2654
+
2603
2655
  // src/userResponse/base-llm.ts
2604
2656
  var BaseLLM = class {
2605
2657
  constructor(config) {
@@ -3139,13 +3191,14 @@ var BaseLLM = class {
3139
3191
  }
3140
3192
  }
3141
3193
  /**
3142
- * Match components from text response suggestions
3194
+ * Match components from text response suggestions and generate follow-up questions
3143
3195
  * Takes a text response with component suggestions (c1:type format) and matches with available components
3196
+ * Also generates intelligent follow-up questions (actions) based on the analysis
3144
3197
  * @param textResponse - The text response containing component suggestions
3145
3198
  * @param components - List of available components
3146
3199
  * @param apiKey - Optional API key
3147
3200
  * @param logCollector - Optional log collector
3148
- * @returns Object containing matched components, selected layout, and reasoning
3201
+ * @returns Object containing matched components, selected layout, reasoning, and follow-up actions
3149
3202
  */
3150
3203
  async matchComponentsFromTextResponse(textResponse, components, apiKey, logCollector) {
3151
3204
  try {
@@ -3187,7 +3240,6 @@ var BaseLLM = class {
3187
3240
  // Don't parse as JSON yet, get raw response
3188
3241
  );
3189
3242
  logger.debug(`[${this.getProviderName()}] Raw component matching response length: ${rawResponse?.length || 0}`);
3190
- logger.file(`[${this.getProviderName()}] Component matching raw response:`, rawResponse);
3191
3243
  let result;
3192
3244
  try {
3193
3245
  let cleanedResponse = rawResponse || "";
@@ -3230,7 +3282,8 @@ var BaseLLM = class {
3230
3282
  selectedLayout: "MultiComponentContainer",
3231
3283
  selectedLayoutId: "",
3232
3284
  selectedLayoutComponent: null,
3233
- layoutReasoning: "No layout selected"
3285
+ layoutReasoning: "No layout selected",
3286
+ actions: []
3234
3287
  };
3235
3288
  }
3236
3289
  }
@@ -3238,6 +3291,8 @@ var BaseLLM = class {
3238
3291
  const selectedLayout = result.selectedLayout || "MultiComponentContainer";
3239
3292
  const selectedLayoutId = result.selectedLayoutId || "";
3240
3293
  const layoutReasoning = result.layoutReasoning || "No layout reasoning provided";
3294
+ const rawActions = result.actions || [];
3295
+ const actions = convertQuestionsToActions(rawActions);
3241
3296
  let selectedLayoutComponent = null;
3242
3297
  if (selectedLayoutId) {
3243
3298
  selectedLayoutComponent = components.find((c) => c.id === selectedLayoutId) || null;
@@ -3248,6 +3303,7 @@ var BaseLLM = class {
3248
3303
  logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
3249
3304
  logger.info(`[${this.getProviderName()}] Selected layout: ${selectedLayout} (ID: ${selectedLayoutId})`);
3250
3305
  logger.info(`[${this.getProviderName()}] Layout reasoning: ${layoutReasoning}`);
3306
+ logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
3251
3307
  if (matchedComponents.length > 0) {
3252
3308
  logCollector?.info(`Matched ${matchedComponents.length} components for visualization using ${selectedLayout}`);
3253
3309
  logCollector?.info(`Layout reasoning: ${layoutReasoning}`);
@@ -3262,6 +3318,12 @@ var BaseLLM = class {
3262
3318
  }
3263
3319
  });
3264
3320
  }
3321
+ if (actions.length > 0) {
3322
+ logCollector?.info(`Generated ${actions.length} follow-up questions`);
3323
+ actions.forEach((action, idx) => {
3324
+ logCollector?.info(` ${idx + 1}. ${action.name}`);
3325
+ });
3326
+ }
3265
3327
  const finalComponents = matchedComponents.map((mc) => {
3266
3328
  const originalComponent = components.find((c) => c.id === mc.componentId);
3267
3329
  if (!originalComponent) {
@@ -3281,7 +3343,8 @@ var BaseLLM = class {
3281
3343
  selectedLayout,
3282
3344
  selectedLayoutId,
3283
3345
  selectedLayoutComponent,
3284
- layoutReasoning
3346
+ layoutReasoning,
3347
+ actions
3285
3348
  };
3286
3349
  } catch (error) {
3287
3350
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -3293,7 +3356,8 @@ var BaseLLM = class {
3293
3356
  selectedLayout: "MultiComponentContainer",
3294
3357
  selectedLayoutId: "",
3295
3358
  selectedLayoutComponent: null,
3296
- layoutReasoning: "Error occurred during component matching"
3359
+ layoutReasoning: "Error occurred during component matching",
3360
+ actions: []
3297
3361
  };
3298
3362
  }
3299
3363
  }
@@ -3312,10 +3376,17 @@ var BaseLLM = class {
3312
3376
  logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
3313
3377
  try {
3314
3378
  const schemaDoc = schema.generateSchemaDocumentation();
3379
+ const knowledgeBaseContext = await knowledge_base_default.getKnowledgeBase({
3380
+ prompt: userPrompt,
3381
+ collections,
3382
+ topK: 1
3383
+ });
3384
+ logger.file("\n=============================\nknowledge base context:", knowledgeBaseContext);
3315
3385
  const prompts = await promptLoader.loadPrompts("text-response", {
3316
3386
  USER_PROMPT: userPrompt,
3317
3387
  CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
3318
- SCHEMA_DOC: schemaDoc
3388
+ SCHEMA_DOC: schemaDoc,
3389
+ KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext || "No additional knowledge base context available."
3319
3390
  });
3320
3391
  logger.file("\n=============================\nsystem prompt:", prompts.system);
3321
3392
  logger.file("\n=============================\nuser prompt:", prompts.user);
@@ -3516,6 +3587,7 @@ ${errorMsg}
3516
3587
  text: textResponse,
3517
3588
  // Include the streamed text showing all attempts
3518
3589
  matchedComponents: [],
3590
+ actions: [],
3519
3591
  method: `${this.getProviderName()}-text-response-max-attempts`
3520
3592
  }
3521
3593
  };
@@ -3531,6 +3603,7 @@ ${errorMsg}
3531
3603
  let matchedComponents = [];
3532
3604
  let selectedLayoutComponent = null;
3533
3605
  let layoutReasoning = "No layout selected";
3606
+ let actions = [];
3534
3607
  if (components && components.length > 0) {
3535
3608
  logger.info(`[${this.getProviderName()}] Matching components from text response...`);
3536
3609
  const matchResult = await this.matchComponentsFromTextResponse(
@@ -3542,6 +3615,7 @@ ${errorMsg}
3542
3615
  matchedComponents = matchResult.components;
3543
3616
  selectedLayoutComponent = matchResult.selectedLayoutComponent;
3544
3617
  layoutReasoning = matchResult.layoutReasoning;
3618
+ actions = matchResult.actions;
3545
3619
  }
3546
3620
  let container_componet = null;
3547
3621
  if (matchedComponents.length > 0) {
@@ -3555,11 +3629,12 @@ ${errorMsg}
3555
3629
  config: {
3556
3630
  ...selectedLayoutComponent.props?.config || {},
3557
3631
  components: matchedComponents
3558
- }
3632
+ },
3633
+ actions
3559
3634
  }
3560
3635
  };
3561
- logger.info(`[${this.getProviderName()}] Created ${selectedLayoutComponent.name} (${selectedLayoutComponent.type}) container with ${matchedComponents.length} components`);
3562
- logCollector?.info(`Created ${selectedLayoutComponent.name} with ${matchedComponents.length} components: ${layoutReasoning}`);
3636
+ logger.info(`[${this.getProviderName()}] Created ${selectedLayoutComponent.name} (${selectedLayoutComponent.type}) container with ${matchedComponents.length} components and ${actions.length} actions`);
3637
+ logCollector?.info(`Created ${selectedLayoutComponent.name} with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
3563
3638
  } else {
3564
3639
  container_componet = {
3565
3640
  id: `multi_container_${Date.now()}`,
@@ -3571,11 +3646,12 @@ ${errorMsg}
3571
3646
  props: {
3572
3647
  config: {
3573
3648
  components: matchedComponents
3574
- }
3649
+ },
3650
+ actions
3575
3651
  }
3576
3652
  };
3577
- logger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components`);
3578
- logCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components: ${layoutReasoning}`);
3653
+ logger.info(`[${this.getProviderName()}] Created fallback MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions`);
3654
+ logCollector?.info(`Created MultiComponentContainer with ${matchedComponents.length} components and ${actions.length} actions: ${layoutReasoning}`);
3579
3655
  }
3580
3656
  }
3581
3657
  return {
@@ -3585,6 +3661,7 @@ ${errorMsg}
3585
3661
  matchedComponents,
3586
3662
  component: container_componet,
3587
3663
  layoutReasoning,
3664
+ actions,
3588
3665
  method: `${this.getProviderName()}-text-response`
3589
3666
  },
3590
3667
  errors: []
@@ -3600,6 +3677,7 @@ ${errorMsg}
3600
3677
  data: {
3601
3678
  text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
3602
3679
  matchedComponents: [],
3680
+ actions: [],
3603
3681
  method: `${this.getProviderName()}-text-response-error`
3604
3682
  }
3605
3683
  };
@@ -4350,6 +4428,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4350
4428
  }
4351
4429
  let component = null;
4352
4430
  let textResponse = null;
4431
+ let actions = [];
4353
4432
  if (userResponse.data) {
4354
4433
  if (typeof userResponse.data === "object") {
4355
4434
  if ("component" in userResponse.data) {
@@ -4358,6 +4437,9 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4358
4437
  if ("textResponse" in userResponse.data) {
4359
4438
  textResponse = userResponse.data.text;
4360
4439
  }
4440
+ if ("actions" in userResponse.data) {
4441
+ actions = userResponse.data.actions || [];
4442
+ }
4361
4443
  }
4362
4444
  }
4363
4445
  const finalTextResponse = responseMode === "text" && accumulatedStreamResponse ? accumulatedStreamResponse : textResponse;
@@ -4368,11 +4450,15 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
4368
4450
  component,
4369
4451
  // generatedComponentMetadata: full component object (ComponentSchema)
4370
4452
  [],
4371
- // actions: empty initially
4453
+ // actions: empty initially, will be set below
4372
4454
  uiBlockId,
4373
4455
  finalTextResponse
4374
4456
  // textResponse: FULL streaming response including all intermediate messages
4375
4457
  );
4458
+ if (actions.length > 0) {
4459
+ uiBlock.setActions(actions);
4460
+ logger.info(`Stored ${actions.length} actions in UIBlock: ${uiBlockId}`);
4461
+ }
4376
4462
  thread.addUIBlock(uiBlock);
4377
4463
  logger.info(`Created UIBlock: ${uiBlockId} in Thread: ${threadId}`);
4378
4464
  return {
@@ -4610,7 +4696,6 @@ async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiK
4610
4696
  const uiBlockId = SA_RUNTIME.uiBlockId;
4611
4697
  const threadId = SA_RUNTIME.threadId;
4612
4698
  logger.debug(`[ACTIONS_REQ ${id}] SA_RUNTIME validated - threadId: ${threadId}, uiBlockId: ${uiBlockId}`);
4613
- logger.debug(`[ACTIONS_REQ ${id}] Retrieving thread: ${threadId}`);
4614
4699
  const threadManager = ThreadManager.getInstance();
4615
4700
  const thread = threadManager.getThread(threadId);
4616
4701
  if (!thread) {