@superatomai/sdk-node 0.0.15 → 0.0.17
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 +119 -53
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +119 -53
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -565,10 +565,14 @@ var ReportsRequestMessageSchema = import_zod3.z.object({
|
|
|
565
565
|
var UIBlockSchema = import_zod3.z.object({
|
|
566
566
|
id: import_zod3.z.string().optional(),
|
|
567
567
|
userQuestion: import_zod3.z.string().optional(),
|
|
568
|
+
user_prompt: import_zod3.z.string().optional(),
|
|
569
|
+
// DB field name
|
|
568
570
|
text: import_zod3.z.string().optional(),
|
|
569
571
|
textResponse: import_zod3.z.string().optional(),
|
|
572
|
+
analysis: import_zod3.z.string().optional(),
|
|
573
|
+
// DB field name for textResponse
|
|
570
574
|
component: ComponentSchema.optional(),
|
|
571
|
-
// Legacy field
|
|
575
|
+
// DB field name / Legacy field
|
|
572
576
|
generatedComponentMetadata: ComponentSchema.optional(),
|
|
573
577
|
// Actual field used by UIBlock class
|
|
574
578
|
componentData: import_zod3.z.record(import_zod3.z.any()).optional(),
|
|
@@ -3447,6 +3451,26 @@ var BaseLLM = class {
|
|
|
3447
3451
|
getApiKey(apiKey) {
|
|
3448
3452
|
return apiKey || this.apiKey || this.getDefaultApiKey();
|
|
3449
3453
|
}
|
|
3454
|
+
/**
|
|
3455
|
+
* Check if a component contains a Form (data_modification component)
|
|
3456
|
+
* Forms have hardcoded defaultValues that become stale when cached
|
|
3457
|
+
* This checks both single Form components and Forms inside MultiComponentContainer
|
|
3458
|
+
*/
|
|
3459
|
+
containsFormComponent(component) {
|
|
3460
|
+
if (!component) return false;
|
|
3461
|
+
if (component.type === "Form" || component.name === "DynamicForm") {
|
|
3462
|
+
return true;
|
|
3463
|
+
}
|
|
3464
|
+
if (component.type === "Container" || component.name === "MultiComponentContainer") {
|
|
3465
|
+
const nestedComponents = component.props?.config?.components || [];
|
|
3466
|
+
for (const nested of nestedComponents) {
|
|
3467
|
+
if (nested.type === "Form" || nested.name === "DynamicForm") {
|
|
3468
|
+
return true;
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
return false;
|
|
3473
|
+
}
|
|
3450
3474
|
/**
|
|
3451
3475
|
* Match components from text response suggestions and generate follow-up questions
|
|
3452
3476
|
* Takes a text response with component suggestions (c1:type format) and matches with available components
|
|
@@ -3814,8 +3838,9 @@ var BaseLLM = class {
|
|
|
3814
3838
|
* @param collections - Collection registry for executing database queries via database.execute
|
|
3815
3839
|
* @param components - Optional list of available components for matching suggestions
|
|
3816
3840
|
* @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called
|
|
3841
|
+
* @param category - Question category ('data_analysis' | 'data_modification' | 'general'). For data_modification, answer component streaming is skipped. For general, component generation is skipped entirely.
|
|
3817
3842
|
*/
|
|
3818
|
-
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools) {
|
|
3843
|
+
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools, category) {
|
|
3819
3844
|
const errors = [];
|
|
3820
3845
|
logger.debug(`[${this.getProviderName()}] Starting text response generation`);
|
|
3821
3846
|
logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
|
|
@@ -4209,16 +4234,19 @@ ${errorMsg}
|
|
|
4209
4234
|
textLength: textResponse.length
|
|
4210
4235
|
}
|
|
4211
4236
|
);
|
|
4212
|
-
if (wrappedStreamCallback && components && components.length > 0) {
|
|
4237
|
+
if (wrappedStreamCallback && components && components.length > 0 && category !== "general") {
|
|
4213
4238
|
wrappedStreamCallback("__TEXT_COMPLETE__COMPONENT_GENERATION_START__");
|
|
4214
4239
|
}
|
|
4215
4240
|
let matchedComponents = [];
|
|
4216
4241
|
let layoutTitle = "Dashboard";
|
|
4217
4242
|
let layoutDescription = "Multi-component dashboard";
|
|
4218
4243
|
let actions = [];
|
|
4219
|
-
if (
|
|
4244
|
+
if (category === "general") {
|
|
4245
|
+
logger.info(`[${this.getProviderName()}] Skipping component generation for general/conversational question`);
|
|
4246
|
+
logCollector?.info("Skipping component generation for general question");
|
|
4247
|
+
} else if (components && components.length > 0) {
|
|
4220
4248
|
logger.info(`[${this.getProviderName()}] Matching components from text response...`);
|
|
4221
|
-
const componentStreamCallback = wrappedStreamCallback ? (component) => {
|
|
4249
|
+
const componentStreamCallback = wrappedStreamCallback && category !== "data_modification" ? (component) => {
|
|
4222
4250
|
const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
|
|
4223
4251
|
wrappedStreamCallback(answerMarker);
|
|
4224
4252
|
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
@@ -4317,52 +4345,84 @@ ${errorMsg}
|
|
|
4317
4345
|
logCollector?.info(
|
|
4318
4346
|
`\u2713 Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`
|
|
4319
4347
|
);
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
}
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4352
|
-
return {
|
|
4353
|
-
success: true,
|
|
4354
|
-
data: {
|
|
4355
|
-
component: adaptResult.adaptedComponent,
|
|
4356
|
-
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
4357
|
-
method: `${this.getProviderName()}-semantic-match`,
|
|
4358
|
-
semanticSimilarity: conversationMatch.similarity,
|
|
4359
|
-
parametersChanged: adaptResult.parametersChanged
|
|
4360
|
-
},
|
|
4361
|
-
errors: []
|
|
4362
|
-
};
|
|
4348
|
+
const rawComponent = conversationMatch.uiBlock?.component || conversationMatch.uiBlock?.generatedComponentMetadata;
|
|
4349
|
+
const isValidComponent = rawComponent && typeof rawComponent === "object" && Object.keys(rawComponent).length > 0;
|
|
4350
|
+
const component = isValidComponent ? rawComponent : null;
|
|
4351
|
+
const cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || "";
|
|
4352
|
+
logger.debug(`[${this.getProviderName()}] Cached component: ${component ? "present" : "null"}, cachedTextResponse: ${cachedTextResponse ? cachedTextResponse.substring(0, 50) + "..." : "empty"}`);
|
|
4353
|
+
if (this.containsFormComponent(component)) {
|
|
4354
|
+
logger.info(`[${this.getProviderName()}] Skipping cached result - Form components contain stale defaultValues, fetching fresh data`);
|
|
4355
|
+
logCollector?.info("Skipping cache for form - fetching current values from database...");
|
|
4356
|
+
} else if (!component) {
|
|
4357
|
+
if (conversationMatch.similarity >= 0.99) {
|
|
4358
|
+
const elapsedTime2 = Date.now() - startTime;
|
|
4359
|
+
logger.info(`[${this.getProviderName()}] \u2713 Exact match for general question - returning cached text response`);
|
|
4360
|
+
logCollector?.info(`\u2713 Exact match for general question - returning cached response`);
|
|
4361
|
+
logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4362
|
+
return {
|
|
4363
|
+
success: true,
|
|
4364
|
+
data: {
|
|
4365
|
+
text: cachedTextResponse,
|
|
4366
|
+
component: null,
|
|
4367
|
+
matchedComponents: [],
|
|
4368
|
+
actions: conversationMatch.uiBlock?.actions || [],
|
|
4369
|
+
reasoning: `Exact match from previous general conversation`,
|
|
4370
|
+
method: `${this.getProviderName()}-semantic-match-general`,
|
|
4371
|
+
semanticSimilarity: conversationMatch.similarity
|
|
4372
|
+
},
|
|
4373
|
+
errors: []
|
|
4374
|
+
};
|
|
4375
|
+
} else {
|
|
4376
|
+
logger.info(`[${this.getProviderName()}] Similar match but no component (general question) - processing fresh`);
|
|
4377
|
+
logCollector?.info("Similar match found but was a general conversation - processing as new question");
|
|
4378
|
+
}
|
|
4363
4379
|
} else {
|
|
4364
|
-
|
|
4365
|
-
|
|
4380
|
+
if (conversationMatch.similarity >= 0.99) {
|
|
4381
|
+
const elapsedTime2 = Date.now() - startTime;
|
|
4382
|
+
logger.info(`[${this.getProviderName()}] \u2713 100% match - returning UI block directly without adaptation`);
|
|
4383
|
+
logCollector?.info(`\u2713 Exact match (${(conversationMatch.similarity * 100).toFixed(2)}%) - returning cached result`);
|
|
4384
|
+
logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4385
|
+
return {
|
|
4386
|
+
success: true,
|
|
4387
|
+
data: {
|
|
4388
|
+
component,
|
|
4389
|
+
reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
|
|
4390
|
+
method: `${this.getProviderName()}-semantic-match-exact`,
|
|
4391
|
+
semanticSimilarity: conversationMatch.similarity
|
|
4392
|
+
},
|
|
4393
|
+
errors: []
|
|
4394
|
+
};
|
|
4395
|
+
}
|
|
4396
|
+
logCollector?.info(`Adapting parameters for similar question...`);
|
|
4397
|
+
const originalPrompt = conversationMatch.metadata?.userPrompt || "Previous question";
|
|
4398
|
+
const adaptResult = await this.adaptUIBlockParameters(
|
|
4399
|
+
userPrompt,
|
|
4400
|
+
originalPrompt,
|
|
4401
|
+
conversationMatch.uiBlock,
|
|
4402
|
+
apiKey,
|
|
4403
|
+
logCollector
|
|
4404
|
+
);
|
|
4405
|
+
if (adaptResult.success && adaptResult.adaptedComponent) {
|
|
4406
|
+
const elapsedTime2 = Date.now() - startTime;
|
|
4407
|
+
logger.info(`[${this.getProviderName()}] \u2713 Successfully adapted UI block parameters`);
|
|
4408
|
+
logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4409
|
+
logCollector?.info(`\u2713 UI block adapted successfully`);
|
|
4410
|
+
logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4411
|
+
return {
|
|
4412
|
+
success: true,
|
|
4413
|
+
data: {
|
|
4414
|
+
component: adaptResult.adaptedComponent,
|
|
4415
|
+
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
4416
|
+
method: `${this.getProviderName()}-semantic-match`,
|
|
4417
|
+
semanticSimilarity: conversationMatch.similarity,
|
|
4418
|
+
parametersChanged: adaptResult.parametersChanged
|
|
4419
|
+
},
|
|
4420
|
+
errors: []
|
|
4421
|
+
};
|
|
4422
|
+
} else {
|
|
4423
|
+
logger.info(`[${this.getProviderName()}] Could not adapt matched conversation, continuing to category classification`);
|
|
4424
|
+
logCollector?.warn(`Could not adapt matched conversation: ${adaptResult.explanation}`);
|
|
4425
|
+
}
|
|
4366
4426
|
}
|
|
4367
4427
|
} else {
|
|
4368
4428
|
logger.info(`[${this.getProviderName()}] No matching previous conversations found, proceeding to category classification`);
|
|
@@ -4404,7 +4464,10 @@ ${errorMsg}
|
|
|
4404
4464
|
})()
|
|
4405
4465
|
})) || [];
|
|
4406
4466
|
}
|
|
4407
|
-
if (categoryClassification.category === "
|
|
4467
|
+
if (categoryClassification.category === "general") {
|
|
4468
|
+
logger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);
|
|
4469
|
+
logCollector?.info("Routing to general conversation...");
|
|
4470
|
+
} else if (categoryClassification.category === "data_analysis") {
|
|
4408
4471
|
logger.info(`[${this.getProviderName()}] Routing to data analysis (SELECT operations)`);
|
|
4409
4472
|
logCollector?.info("Routing to data analysis...");
|
|
4410
4473
|
} else if (categoryClassification.category === "data_modification") {
|
|
@@ -4419,7 +4482,8 @@ ${errorMsg}
|
|
|
4419
4482
|
streamCallback,
|
|
4420
4483
|
collections,
|
|
4421
4484
|
components,
|
|
4422
|
-
toolsToUse
|
|
4485
|
+
toolsToUse,
|
|
4486
|
+
categoryClassification.category
|
|
4423
4487
|
);
|
|
4424
4488
|
const elapsedTime = Date.now() - startTime;
|
|
4425
4489
|
logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1e3).toFixed(2)}s)`);
|
|
@@ -5076,8 +5140,10 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
5076
5140
|
if ("component" in userResponse.data) {
|
|
5077
5141
|
component = userResponse.data.component;
|
|
5078
5142
|
}
|
|
5079
|
-
if ("
|
|
5143
|
+
if ("text" in userResponse.data) {
|
|
5080
5144
|
textResponse = userResponse.data.text;
|
|
5145
|
+
} else if ("textResponse" in userResponse.data) {
|
|
5146
|
+
textResponse = userResponse.data.textResponse;
|
|
5081
5147
|
}
|
|
5082
5148
|
if ("actions" in userResponse.data) {
|
|
5083
5149
|
actions = userResponse.data.actions || [];
|