@superatomai/sdk-node 0.0.12 → 0.0.13
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 +124 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +124 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3708,14 +3708,14 @@ var BaseLLM = class {
|
|
|
3708
3708
|
* Takes a text response with component suggestions (c1:type format) and matches with available components
|
|
3709
3709
|
* Also generates title, description, and intelligent follow-up questions (actions) based on the analysis
|
|
3710
3710
|
* All components are placed in a default MultiComponentContainer layout
|
|
3711
|
-
* @param
|
|
3711
|
+
* @param analysisContent - The text response containing component suggestions
|
|
3712
3712
|
* @param components - List of available components
|
|
3713
3713
|
* @param apiKey - Optional API key
|
|
3714
3714
|
* @param logCollector - Optional log collector
|
|
3715
3715
|
* @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
|
|
3716
3716
|
* @returns Object containing matched components, layout title/description, and follow-up actions
|
|
3717
3717
|
*/
|
|
3718
|
-
async
|
|
3718
|
+
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback) {
|
|
3719
3719
|
try {
|
|
3720
3720
|
logger.debug(`[${this.getProviderName()}] Starting component matching from text response`);
|
|
3721
3721
|
let availableComponentsText = "No components available";
|
|
@@ -3732,14 +3732,94 @@ var BaseLLM = class {
|
|
|
3732
3732
|
}).join("\n\n");
|
|
3733
3733
|
}
|
|
3734
3734
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
3735
|
+
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
3735
3736
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
3736
|
-
|
|
3737
|
+
ANALYSIS_CONTENT: analysisContent,
|
|
3737
3738
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
3738
3739
|
SCHEMA_DOC: schemaDoc
|
|
3739
3740
|
});
|
|
3740
3741
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
3741
3742
|
logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
|
|
3742
3743
|
logCollector?.info("Matching components from text response...");
|
|
3744
|
+
let fullResponseText = "";
|
|
3745
|
+
let answerComponentExtracted = false;
|
|
3746
|
+
const answerCallback = componentStreamCallback;
|
|
3747
|
+
const partialCallback = answerCallback ? (chunk) => {
|
|
3748
|
+
fullResponseText += chunk;
|
|
3749
|
+
if (!answerComponentExtracted && answerCallback) {
|
|
3750
|
+
const hasAnswerComponentMatch = fullResponseText.match(/"hasAnswerComponent"\s*:\s*(true|false)/);
|
|
3751
|
+
if (!hasAnswerComponentMatch || hasAnswerComponentMatch[1] !== "true") {
|
|
3752
|
+
return;
|
|
3753
|
+
}
|
|
3754
|
+
const answerComponentStartMatch = fullResponseText.match(/"answerComponent"\s*:\s*\{/);
|
|
3755
|
+
if (!answerComponentStartMatch) {
|
|
3756
|
+
return;
|
|
3757
|
+
}
|
|
3758
|
+
const startPos = answerComponentStartMatch.index + answerComponentStartMatch[0].length - 1;
|
|
3759
|
+
let braceDepth = 0;
|
|
3760
|
+
let inString = false;
|
|
3761
|
+
let escapeNext = false;
|
|
3762
|
+
let endPos = -1;
|
|
3763
|
+
for (let i = startPos; i < fullResponseText.length; i++) {
|
|
3764
|
+
const char = fullResponseText[i];
|
|
3765
|
+
if (escapeNext) {
|
|
3766
|
+
escapeNext = false;
|
|
3767
|
+
continue;
|
|
3768
|
+
}
|
|
3769
|
+
if (char === "\\") {
|
|
3770
|
+
escapeNext = true;
|
|
3771
|
+
continue;
|
|
3772
|
+
}
|
|
3773
|
+
if (char === '"') {
|
|
3774
|
+
inString = !inString;
|
|
3775
|
+
continue;
|
|
3776
|
+
}
|
|
3777
|
+
if (!inString) {
|
|
3778
|
+
if (char === "{") {
|
|
3779
|
+
braceDepth++;
|
|
3780
|
+
} else if (char === "}") {
|
|
3781
|
+
braceDepth--;
|
|
3782
|
+
if (braceDepth === 0) {
|
|
3783
|
+
endPos = i + 1;
|
|
3784
|
+
break;
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
if (endPos > startPos) {
|
|
3790
|
+
const answerComponentString = fullResponseText.substring(startPos, endPos);
|
|
3791
|
+
try {
|
|
3792
|
+
const answerComponentData = JSON.parse(answerComponentString);
|
|
3793
|
+
if (answerComponentData && answerComponentData.componentId) {
|
|
3794
|
+
const originalComponent = components.find((c) => c.id === answerComponentData.componentId);
|
|
3795
|
+
if (originalComponent) {
|
|
3796
|
+
const answerComponent = {
|
|
3797
|
+
...originalComponent,
|
|
3798
|
+
props: {
|
|
3799
|
+
...originalComponent.props,
|
|
3800
|
+
...answerComponentData.props
|
|
3801
|
+
}
|
|
3802
|
+
};
|
|
3803
|
+
const streamTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
3804
|
+
logger.info(`[${this.getProviderName()}] \u2713 [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type}) - STREAMING TO FRONTEND NOW`);
|
|
3805
|
+
logCollector?.info(`\u2713 Answer component: ${answerComponent.name} (${answerComponent.type}) - streaming to frontend at ${streamTime}`);
|
|
3806
|
+
if (answerComponentData.props?.query) {
|
|
3807
|
+
logCollector?.logQuery(
|
|
3808
|
+
"Answer component query",
|
|
3809
|
+
answerComponentData.props.query,
|
|
3810
|
+
{ componentName: answerComponent.name, componentType: answerComponent.type, reasoning: answerComponentData.reasoning }
|
|
3811
|
+
);
|
|
3812
|
+
}
|
|
3813
|
+
answerCallback(answerComponent);
|
|
3814
|
+
answerComponentExtracted = true;
|
|
3815
|
+
}
|
|
3816
|
+
}
|
|
3817
|
+
} catch (e) {
|
|
3818
|
+
logger.debug(`[${this.getProviderName()}] Partial answerComponent parse failed, waiting for more data...`);
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3822
|
+
} : void 0;
|
|
3743
3823
|
const result = await LLM.stream(
|
|
3744
3824
|
{
|
|
3745
3825
|
sys: prompts.system,
|
|
@@ -3749,23 +3829,54 @@ var BaseLLM = class {
|
|
|
3749
3829
|
model: this.model,
|
|
3750
3830
|
maxTokens: 3e3,
|
|
3751
3831
|
temperature: 0.2,
|
|
3752
|
-
apiKey: this.getApiKey(apiKey)
|
|
3832
|
+
apiKey: this.getApiKey(apiKey),
|
|
3833
|
+
partial: partialCallback
|
|
3753
3834
|
},
|
|
3754
3835
|
true
|
|
3755
3836
|
// Parse as JSON
|
|
3756
3837
|
);
|
|
3757
3838
|
logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
|
|
3839
|
+
const componentSuggestionPattern = /c\d+:(\w+)\s*:\s*(.+)/g;
|
|
3840
|
+
const suggestedComponents = [];
|
|
3841
|
+
let match;
|
|
3842
|
+
while ((match = componentSuggestionPattern.exec(analysisContent)) !== null) {
|
|
3843
|
+
suggestedComponents.push({
|
|
3844
|
+
type: match[1],
|
|
3845
|
+
reasoning: match[2].trim()
|
|
3846
|
+
});
|
|
3847
|
+
}
|
|
3758
3848
|
const matchedComponents = result.matchedComponents || [];
|
|
3759
3849
|
const layoutTitle = result.layoutTitle || "Dashboard";
|
|
3760
3850
|
const layoutDescription = result.layoutDescription || "Multi-component dashboard";
|
|
3851
|
+
logger.info(`[${this.getProviderName()}] \u{1F4CA} Component Suggestions from Text Analysis: ${suggestedComponents.length}`);
|
|
3852
|
+
suggestedComponents.forEach((comp, idx) => {
|
|
3853
|
+
logger.info(`[${this.getProviderName()}] c${idx + 1}: ${comp.type} - ${comp.reasoning}`);
|
|
3854
|
+
});
|
|
3855
|
+
logger.info(`[${this.getProviderName()}] \u{1F4E6} Matched Components from LLM: ${matchedComponents.length}`);
|
|
3856
|
+
matchedComponents.forEach((comp, idx) => {
|
|
3857
|
+
logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
|
|
3858
|
+
});
|
|
3859
|
+
if (suggestedComponents.length !== matchedComponents.length) {
|
|
3860
|
+
logger.warn(`[${this.getProviderName()}] \u26A0\uFE0F MISMATCH: Text suggested ${suggestedComponents.length} components, but LLM matched ${matchedComponents.length}`);
|
|
3861
|
+
}
|
|
3862
|
+
logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
|
|
3761
3863
|
const rawActions = result.actions || [];
|
|
3762
3864
|
const actions = convertQuestionsToActions(rawActions);
|
|
3763
3865
|
logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
|
|
3764
3866
|
logger.info(`[${this.getProviderName()}] Layout title: "${layoutTitle}"`);
|
|
3765
3867
|
logger.info(`[${this.getProviderName()}] Layout description: "${layoutDescription}"`);
|
|
3766
3868
|
logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
|
|
3869
|
+
if (suggestedComponents.length > 0) {
|
|
3870
|
+
logCollector?.info(`\u{1F4DD} Text Analysis suggested ${suggestedComponents.length} dashboard components:`);
|
|
3871
|
+
suggestedComponents.forEach((comp, idx) => {
|
|
3872
|
+
logCollector?.info(` c${idx + 1}: ${comp.type} - ${comp.reasoning}`);
|
|
3873
|
+
});
|
|
3874
|
+
}
|
|
3767
3875
|
if (matchedComponents.length > 0) {
|
|
3768
|
-
logCollector?.info(
|
|
3876
|
+
logCollector?.info(`\u{1F4E6} Matched ${matchedComponents.length} components for dashboard`);
|
|
3877
|
+
if (suggestedComponents.length !== matchedComponents.length) {
|
|
3878
|
+
logCollector?.warn(`\u26A0\uFE0F Component count mismatch: Suggested ${suggestedComponents.length}, but matched ${matchedComponents.length}`);
|
|
3879
|
+
}
|
|
3769
3880
|
logCollector?.info(`Dashboard: "${layoutTitle}"`);
|
|
3770
3881
|
matchedComponents.forEach((comp, idx) => {
|
|
3771
3882
|
logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
|
|
@@ -4240,11 +4351,17 @@ ${errorMsg}
|
|
|
4240
4351
|
let actions = [];
|
|
4241
4352
|
if (components && components.length > 0) {
|
|
4242
4353
|
logger.info(`[${this.getProviderName()}] Matching components from text response...`);
|
|
4243
|
-
const
|
|
4354
|
+
const componentStreamCallback = wrappedStreamCallback ? (component) => {
|
|
4355
|
+
const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
|
|
4356
|
+
wrappedStreamCallback(answerMarker);
|
|
4357
|
+
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
4358
|
+
} : void 0;
|
|
4359
|
+
const matchResult = await this.matchComponentsFromAnalysis(
|
|
4244
4360
|
textResponse,
|
|
4245
4361
|
components,
|
|
4246
4362
|
apiKey,
|
|
4247
|
-
logCollector
|
|
4363
|
+
logCollector,
|
|
4364
|
+
componentStreamCallback
|
|
4248
4365
|
);
|
|
4249
4366
|
matchedComponents = matchResult.components;
|
|
4250
4367
|
layoutTitle = matchResult.layoutTitle;
|
|
@@ -5119,7 +5236,6 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
|
5119
5236
|
...res
|
|
5120
5237
|
}
|
|
5121
5238
|
};
|
|
5122
|
-
logger.info("sending user prompt response", response);
|
|
5123
5239
|
sendMessage(response);
|
|
5124
5240
|
}
|
|
5125
5241
|
|