@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.mjs
CHANGED
|
@@ -525,10 +525,14 @@ var ReportsRequestMessageSchema = z3.object({
|
|
|
525
525
|
var UIBlockSchema = z3.object({
|
|
526
526
|
id: z3.string().optional(),
|
|
527
527
|
userQuestion: z3.string().optional(),
|
|
528
|
+
user_prompt: z3.string().optional(),
|
|
529
|
+
// DB field name
|
|
528
530
|
text: z3.string().optional(),
|
|
529
531
|
textResponse: z3.string().optional(),
|
|
532
|
+
analysis: z3.string().optional(),
|
|
533
|
+
// DB field name for textResponse
|
|
530
534
|
component: ComponentSchema.optional(),
|
|
531
|
-
// Legacy field
|
|
535
|
+
// DB field name / Legacy field
|
|
532
536
|
generatedComponentMetadata: ComponentSchema.optional(),
|
|
533
537
|
// Actual field used by UIBlock class
|
|
534
538
|
componentData: z3.record(z3.any()).optional(),
|
|
@@ -3407,6 +3411,26 @@ var BaseLLM = class {
|
|
|
3407
3411
|
getApiKey(apiKey) {
|
|
3408
3412
|
return apiKey || this.apiKey || this.getDefaultApiKey();
|
|
3409
3413
|
}
|
|
3414
|
+
/**
|
|
3415
|
+
* Check if a component contains a Form (data_modification component)
|
|
3416
|
+
* Forms have hardcoded defaultValues that become stale when cached
|
|
3417
|
+
* This checks both single Form components and Forms inside MultiComponentContainer
|
|
3418
|
+
*/
|
|
3419
|
+
containsFormComponent(component) {
|
|
3420
|
+
if (!component) return false;
|
|
3421
|
+
if (component.type === "Form" || component.name === "DynamicForm") {
|
|
3422
|
+
return true;
|
|
3423
|
+
}
|
|
3424
|
+
if (component.type === "Container" || component.name === "MultiComponentContainer") {
|
|
3425
|
+
const nestedComponents = component.props?.config?.components || [];
|
|
3426
|
+
for (const nested of nestedComponents) {
|
|
3427
|
+
if (nested.type === "Form" || nested.name === "DynamicForm") {
|
|
3428
|
+
return true;
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3432
|
+
return false;
|
|
3433
|
+
}
|
|
3410
3434
|
/**
|
|
3411
3435
|
* Match components from text response suggestions and generate follow-up questions
|
|
3412
3436
|
* Takes a text response with component suggestions (c1:type format) and matches with available components
|
|
@@ -3774,8 +3798,9 @@ var BaseLLM = class {
|
|
|
3774
3798
|
* @param collections - Collection registry for executing database queries via database.execute
|
|
3775
3799
|
* @param components - Optional list of available components for matching suggestions
|
|
3776
3800
|
* @param externalTools - Optional array of external tools (email, calendar, etc.) that can be called
|
|
3801
|
+
* @param category - Question category ('data_analysis' | 'data_modification' | 'general'). For data_modification, answer component streaming is skipped. For general, component generation is skipped entirely.
|
|
3777
3802
|
*/
|
|
3778
|
-
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools) {
|
|
3803
|
+
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory, streamCallback, collections, components, externalTools, category) {
|
|
3779
3804
|
const errors = [];
|
|
3780
3805
|
logger.debug(`[${this.getProviderName()}] Starting text response generation`);
|
|
3781
3806
|
logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
|
|
@@ -4169,16 +4194,19 @@ ${errorMsg}
|
|
|
4169
4194
|
textLength: textResponse.length
|
|
4170
4195
|
}
|
|
4171
4196
|
);
|
|
4172
|
-
if (wrappedStreamCallback && components && components.length > 0) {
|
|
4197
|
+
if (wrappedStreamCallback && components && components.length > 0 && category !== "general") {
|
|
4173
4198
|
wrappedStreamCallback("__TEXT_COMPLETE__COMPONENT_GENERATION_START__");
|
|
4174
4199
|
}
|
|
4175
4200
|
let matchedComponents = [];
|
|
4176
4201
|
let layoutTitle = "Dashboard";
|
|
4177
4202
|
let layoutDescription = "Multi-component dashboard";
|
|
4178
4203
|
let actions = [];
|
|
4179
|
-
if (
|
|
4204
|
+
if (category === "general") {
|
|
4205
|
+
logger.info(`[${this.getProviderName()}] Skipping component generation for general/conversational question`);
|
|
4206
|
+
logCollector?.info("Skipping component generation for general question");
|
|
4207
|
+
} else if (components && components.length > 0) {
|
|
4180
4208
|
logger.info(`[${this.getProviderName()}] Matching components from text response...`);
|
|
4181
|
-
const componentStreamCallback = wrappedStreamCallback ? (component) => {
|
|
4209
|
+
const componentStreamCallback = wrappedStreamCallback && category !== "data_modification" ? (component) => {
|
|
4182
4210
|
const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
|
|
4183
4211
|
wrappedStreamCallback(answerMarker);
|
|
4184
4212
|
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
@@ -4277,52 +4305,84 @@ ${errorMsg}
|
|
|
4277
4305
|
logCollector?.info(
|
|
4278
4306
|
`\u2713 Found similar conversation (${(conversationMatch.similarity * 100).toFixed(2)}% match)`
|
|
4279
4307
|
);
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
}
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4312
|
-
return {
|
|
4313
|
-
success: true,
|
|
4314
|
-
data: {
|
|
4315
|
-
component: adaptResult.adaptedComponent,
|
|
4316
|
-
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
4317
|
-
method: `${this.getProviderName()}-semantic-match`,
|
|
4318
|
-
semanticSimilarity: conversationMatch.similarity,
|
|
4319
|
-
parametersChanged: adaptResult.parametersChanged
|
|
4320
|
-
},
|
|
4321
|
-
errors: []
|
|
4322
|
-
};
|
|
4308
|
+
const rawComponent = conversationMatch.uiBlock?.component || conversationMatch.uiBlock?.generatedComponentMetadata;
|
|
4309
|
+
const isValidComponent = rawComponent && typeof rawComponent === "object" && Object.keys(rawComponent).length > 0;
|
|
4310
|
+
const component = isValidComponent ? rawComponent : null;
|
|
4311
|
+
const cachedTextResponse = conversationMatch.uiBlock?.analysis || conversationMatch.uiBlock?.textResponse || conversationMatch.uiBlock?.text || "";
|
|
4312
|
+
logger.debug(`[${this.getProviderName()}] Cached component: ${component ? "present" : "null"}, cachedTextResponse: ${cachedTextResponse ? cachedTextResponse.substring(0, 50) + "..." : "empty"}`);
|
|
4313
|
+
if (this.containsFormComponent(component)) {
|
|
4314
|
+
logger.info(`[${this.getProviderName()}] Skipping cached result - Form components contain stale defaultValues, fetching fresh data`);
|
|
4315
|
+
logCollector?.info("Skipping cache for form - fetching current values from database...");
|
|
4316
|
+
} else if (!component) {
|
|
4317
|
+
if (conversationMatch.similarity >= 0.99) {
|
|
4318
|
+
const elapsedTime2 = Date.now() - startTime;
|
|
4319
|
+
logger.info(`[${this.getProviderName()}] \u2713 Exact match for general question - returning cached text response`);
|
|
4320
|
+
logCollector?.info(`\u2713 Exact match for general question - returning cached response`);
|
|
4321
|
+
logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4322
|
+
return {
|
|
4323
|
+
success: true,
|
|
4324
|
+
data: {
|
|
4325
|
+
text: cachedTextResponse,
|
|
4326
|
+
component: null,
|
|
4327
|
+
matchedComponents: [],
|
|
4328
|
+
actions: conversationMatch.uiBlock?.actions || [],
|
|
4329
|
+
reasoning: `Exact match from previous general conversation`,
|
|
4330
|
+
method: `${this.getProviderName()}-semantic-match-general`,
|
|
4331
|
+
semanticSimilarity: conversationMatch.similarity
|
|
4332
|
+
},
|
|
4333
|
+
errors: []
|
|
4334
|
+
};
|
|
4335
|
+
} else {
|
|
4336
|
+
logger.info(`[${this.getProviderName()}] Similar match but no component (general question) - processing fresh`);
|
|
4337
|
+
logCollector?.info("Similar match found but was a general conversation - processing as new question");
|
|
4338
|
+
}
|
|
4323
4339
|
} else {
|
|
4324
|
-
|
|
4325
|
-
|
|
4340
|
+
if (conversationMatch.similarity >= 0.99) {
|
|
4341
|
+
const elapsedTime2 = Date.now() - startTime;
|
|
4342
|
+
logger.info(`[${this.getProviderName()}] \u2713 100% match - returning UI block directly without adaptation`);
|
|
4343
|
+
logCollector?.info(`\u2713 Exact match (${(conversationMatch.similarity * 100).toFixed(2)}%) - returning cached result`);
|
|
4344
|
+
logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4345
|
+
return {
|
|
4346
|
+
success: true,
|
|
4347
|
+
data: {
|
|
4348
|
+
component,
|
|
4349
|
+
reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
|
|
4350
|
+
method: `${this.getProviderName()}-semantic-match-exact`,
|
|
4351
|
+
semanticSimilarity: conversationMatch.similarity
|
|
4352
|
+
},
|
|
4353
|
+
errors: []
|
|
4354
|
+
};
|
|
4355
|
+
}
|
|
4356
|
+
logCollector?.info(`Adapting parameters for similar question...`);
|
|
4357
|
+
const originalPrompt = conversationMatch.metadata?.userPrompt || "Previous question";
|
|
4358
|
+
const adaptResult = await this.adaptUIBlockParameters(
|
|
4359
|
+
userPrompt,
|
|
4360
|
+
originalPrompt,
|
|
4361
|
+
conversationMatch.uiBlock,
|
|
4362
|
+
apiKey,
|
|
4363
|
+
logCollector
|
|
4364
|
+
);
|
|
4365
|
+
if (adaptResult.success && adaptResult.adaptedComponent) {
|
|
4366
|
+
const elapsedTime2 = Date.now() - startTime;
|
|
4367
|
+
logger.info(`[${this.getProviderName()}] \u2713 Successfully adapted UI block parameters`);
|
|
4368
|
+
logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4369
|
+
logCollector?.info(`\u2713 UI block adapted successfully`);
|
|
4370
|
+
logCollector?.info(`Total time taken: ${elapsedTime2}ms (${(elapsedTime2 / 1e3).toFixed(2)}s)`);
|
|
4371
|
+
return {
|
|
4372
|
+
success: true,
|
|
4373
|
+
data: {
|
|
4374
|
+
component: adaptResult.adaptedComponent,
|
|
4375
|
+
reasoning: `Adapted from previous conversation: ${originalPrompt}`,
|
|
4376
|
+
method: `${this.getProviderName()}-semantic-match`,
|
|
4377
|
+
semanticSimilarity: conversationMatch.similarity,
|
|
4378
|
+
parametersChanged: adaptResult.parametersChanged
|
|
4379
|
+
},
|
|
4380
|
+
errors: []
|
|
4381
|
+
};
|
|
4382
|
+
} else {
|
|
4383
|
+
logger.info(`[${this.getProviderName()}] Could not adapt matched conversation, continuing to category classification`);
|
|
4384
|
+
logCollector?.warn(`Could not adapt matched conversation: ${adaptResult.explanation}`);
|
|
4385
|
+
}
|
|
4326
4386
|
}
|
|
4327
4387
|
} else {
|
|
4328
4388
|
logger.info(`[${this.getProviderName()}] No matching previous conversations found, proceeding to category classification`);
|
|
@@ -4364,7 +4424,10 @@ ${errorMsg}
|
|
|
4364
4424
|
})()
|
|
4365
4425
|
})) || [];
|
|
4366
4426
|
}
|
|
4367
|
-
if (categoryClassification.category === "
|
|
4427
|
+
if (categoryClassification.category === "general") {
|
|
4428
|
+
logger.info(`[${this.getProviderName()}] Routing to general conversation (no database operations)`);
|
|
4429
|
+
logCollector?.info("Routing to general conversation...");
|
|
4430
|
+
} else if (categoryClassification.category === "data_analysis") {
|
|
4368
4431
|
logger.info(`[${this.getProviderName()}] Routing to data analysis (SELECT operations)`);
|
|
4369
4432
|
logCollector?.info("Routing to data analysis...");
|
|
4370
4433
|
} else if (categoryClassification.category === "data_modification") {
|
|
@@ -4379,7 +4442,8 @@ ${errorMsg}
|
|
|
4379
4442
|
streamCallback,
|
|
4380
4443
|
collections,
|
|
4381
4444
|
components,
|
|
4382
|
-
toolsToUse
|
|
4445
|
+
toolsToUse,
|
|
4446
|
+
categoryClassification.category
|
|
4383
4447
|
);
|
|
4384
4448
|
const elapsedTime = Date.now() - startTime;
|
|
4385
4449
|
logger.info(`[${this.getProviderName()}] Total time taken: ${elapsedTime}ms (${(elapsedTime / 1e3).toFixed(2)}s)`);
|
|
@@ -5036,8 +5100,10 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
|
|
|
5036
5100
|
if ("component" in userResponse.data) {
|
|
5037
5101
|
component = userResponse.data.component;
|
|
5038
5102
|
}
|
|
5039
|
-
if ("
|
|
5103
|
+
if ("text" in userResponse.data) {
|
|
5040
5104
|
textResponse = userResponse.data.text;
|
|
5105
|
+
} else if ("textResponse" in userResponse.data) {
|
|
5106
|
+
textResponse = userResponse.data.textResponse;
|
|
5041
5107
|
}
|
|
5042
5108
|
if ("actions" in userResponse.data) {
|
|
5043
5109
|
actions = userResponse.data.actions || [];
|