@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.js
CHANGED
|
@@ -3748,14 +3748,14 @@ var BaseLLM = class {
|
|
|
3748
3748
|
* Takes a text response with component suggestions (c1:type format) and matches with available components
|
|
3749
3749
|
* Also generates title, description, and intelligent follow-up questions (actions) based on the analysis
|
|
3750
3750
|
* All components are placed in a default MultiComponentContainer layout
|
|
3751
|
-
* @param
|
|
3751
|
+
* @param analysisContent - The text response containing component suggestions
|
|
3752
3752
|
* @param components - List of available components
|
|
3753
3753
|
* @param apiKey - Optional API key
|
|
3754
3754
|
* @param logCollector - Optional log collector
|
|
3755
3755
|
* @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
|
|
3756
3756
|
* @returns Object containing matched components, layout title/description, and follow-up actions
|
|
3757
3757
|
*/
|
|
3758
|
-
async
|
|
3758
|
+
async matchComponentsFromAnalysis(analysisContent, components, apiKey, logCollector, componentStreamCallback) {
|
|
3759
3759
|
try {
|
|
3760
3760
|
logger.debug(`[${this.getProviderName()}] Starting component matching from text response`);
|
|
3761
3761
|
let availableComponentsText = "No components available";
|
|
@@ -3772,14 +3772,94 @@ var BaseLLM = class {
|
|
|
3772
3772
|
}).join("\n\n");
|
|
3773
3773
|
}
|
|
3774
3774
|
const schemaDoc = schema.generateSchemaDocumentation();
|
|
3775
|
+
logger.file("\n=============================\nText analysis response:", analysisContent);
|
|
3775
3776
|
const prompts = await promptLoader.loadPrompts("match-text-components", {
|
|
3776
|
-
|
|
3777
|
+
ANALYSIS_CONTENT: analysisContent,
|
|
3777
3778
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
3778
3779
|
SCHEMA_DOC: schemaDoc
|
|
3779
3780
|
});
|
|
3780
3781
|
logger.debug(`[${this.getProviderName()}] Loaded match-text-components prompts`);
|
|
3781
3782
|
logger.file("\n=============================\nmatch text components system prompt:", prompts.system);
|
|
3782
3783
|
logCollector?.info("Matching components from text response...");
|
|
3784
|
+
let fullResponseText = "";
|
|
3785
|
+
let answerComponentExtracted = false;
|
|
3786
|
+
const answerCallback = componentStreamCallback;
|
|
3787
|
+
const partialCallback = answerCallback ? (chunk) => {
|
|
3788
|
+
fullResponseText += chunk;
|
|
3789
|
+
if (!answerComponentExtracted && answerCallback) {
|
|
3790
|
+
const hasAnswerComponentMatch = fullResponseText.match(/"hasAnswerComponent"\s*:\s*(true|false)/);
|
|
3791
|
+
if (!hasAnswerComponentMatch || hasAnswerComponentMatch[1] !== "true") {
|
|
3792
|
+
return;
|
|
3793
|
+
}
|
|
3794
|
+
const answerComponentStartMatch = fullResponseText.match(/"answerComponent"\s*:\s*\{/);
|
|
3795
|
+
if (!answerComponentStartMatch) {
|
|
3796
|
+
return;
|
|
3797
|
+
}
|
|
3798
|
+
const startPos = answerComponentStartMatch.index + answerComponentStartMatch[0].length - 1;
|
|
3799
|
+
let braceDepth = 0;
|
|
3800
|
+
let inString = false;
|
|
3801
|
+
let escapeNext = false;
|
|
3802
|
+
let endPos = -1;
|
|
3803
|
+
for (let i = startPos; i < fullResponseText.length; i++) {
|
|
3804
|
+
const char = fullResponseText[i];
|
|
3805
|
+
if (escapeNext) {
|
|
3806
|
+
escapeNext = false;
|
|
3807
|
+
continue;
|
|
3808
|
+
}
|
|
3809
|
+
if (char === "\\") {
|
|
3810
|
+
escapeNext = true;
|
|
3811
|
+
continue;
|
|
3812
|
+
}
|
|
3813
|
+
if (char === '"') {
|
|
3814
|
+
inString = !inString;
|
|
3815
|
+
continue;
|
|
3816
|
+
}
|
|
3817
|
+
if (!inString) {
|
|
3818
|
+
if (char === "{") {
|
|
3819
|
+
braceDepth++;
|
|
3820
|
+
} else if (char === "}") {
|
|
3821
|
+
braceDepth--;
|
|
3822
|
+
if (braceDepth === 0) {
|
|
3823
|
+
endPos = i + 1;
|
|
3824
|
+
break;
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3828
|
+
}
|
|
3829
|
+
if (endPos > startPos) {
|
|
3830
|
+
const answerComponentString = fullResponseText.substring(startPos, endPos);
|
|
3831
|
+
try {
|
|
3832
|
+
const answerComponentData = JSON.parse(answerComponentString);
|
|
3833
|
+
if (answerComponentData && answerComponentData.componentId) {
|
|
3834
|
+
const originalComponent = components.find((c) => c.id === answerComponentData.componentId);
|
|
3835
|
+
if (originalComponent) {
|
|
3836
|
+
const answerComponent = {
|
|
3837
|
+
...originalComponent,
|
|
3838
|
+
props: {
|
|
3839
|
+
...originalComponent.props,
|
|
3840
|
+
...answerComponentData.props
|
|
3841
|
+
}
|
|
3842
|
+
};
|
|
3843
|
+
const streamTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
3844
|
+
logger.info(`[${this.getProviderName()}] \u2713 [${streamTime}] Answer component detected in stream: ${answerComponent.name} (${answerComponent.type}) - STREAMING TO FRONTEND NOW`);
|
|
3845
|
+
logCollector?.info(`\u2713 Answer component: ${answerComponent.name} (${answerComponent.type}) - streaming to frontend at ${streamTime}`);
|
|
3846
|
+
if (answerComponentData.props?.query) {
|
|
3847
|
+
logCollector?.logQuery(
|
|
3848
|
+
"Answer component query",
|
|
3849
|
+
answerComponentData.props.query,
|
|
3850
|
+
{ componentName: answerComponent.name, componentType: answerComponent.type, reasoning: answerComponentData.reasoning }
|
|
3851
|
+
);
|
|
3852
|
+
}
|
|
3853
|
+
answerCallback(answerComponent);
|
|
3854
|
+
answerComponentExtracted = true;
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
} catch (e) {
|
|
3858
|
+
logger.debug(`[${this.getProviderName()}] Partial answerComponent parse failed, waiting for more data...`);
|
|
3859
|
+
}
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
} : void 0;
|
|
3783
3863
|
const result = await LLM.stream(
|
|
3784
3864
|
{
|
|
3785
3865
|
sys: prompts.system,
|
|
@@ -3789,23 +3869,54 @@ var BaseLLM = class {
|
|
|
3789
3869
|
model: this.model,
|
|
3790
3870
|
maxTokens: 3e3,
|
|
3791
3871
|
temperature: 0.2,
|
|
3792
|
-
apiKey: this.getApiKey(apiKey)
|
|
3872
|
+
apiKey: this.getApiKey(apiKey),
|
|
3873
|
+
partial: partialCallback
|
|
3793
3874
|
},
|
|
3794
3875
|
true
|
|
3795
3876
|
// Parse as JSON
|
|
3796
3877
|
);
|
|
3797
3878
|
logger.debug(`[${this.getProviderName()}] Component matching response parsed successfully`);
|
|
3879
|
+
const componentSuggestionPattern = /c\d+:(\w+)\s*:\s*(.+)/g;
|
|
3880
|
+
const suggestedComponents = [];
|
|
3881
|
+
let match;
|
|
3882
|
+
while ((match = componentSuggestionPattern.exec(analysisContent)) !== null) {
|
|
3883
|
+
suggestedComponents.push({
|
|
3884
|
+
type: match[1],
|
|
3885
|
+
reasoning: match[2].trim()
|
|
3886
|
+
});
|
|
3887
|
+
}
|
|
3798
3888
|
const matchedComponents = result.matchedComponents || [];
|
|
3799
3889
|
const layoutTitle = result.layoutTitle || "Dashboard";
|
|
3800
3890
|
const layoutDescription = result.layoutDescription || "Multi-component dashboard";
|
|
3891
|
+
logger.info(`[${this.getProviderName()}] \u{1F4CA} Component Suggestions from Text Analysis: ${suggestedComponents.length}`);
|
|
3892
|
+
suggestedComponents.forEach((comp, idx) => {
|
|
3893
|
+
logger.info(`[${this.getProviderName()}] c${idx + 1}: ${comp.type} - ${comp.reasoning}`);
|
|
3894
|
+
});
|
|
3895
|
+
logger.info(`[${this.getProviderName()}] \u{1F4E6} Matched Components from LLM: ${matchedComponents.length}`);
|
|
3896
|
+
matchedComponents.forEach((comp, idx) => {
|
|
3897
|
+
logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
|
|
3898
|
+
});
|
|
3899
|
+
if (suggestedComponents.length !== matchedComponents.length) {
|
|
3900
|
+
logger.warn(`[${this.getProviderName()}] \u26A0\uFE0F MISMATCH: Text suggested ${suggestedComponents.length} components, but LLM matched ${matchedComponents.length}`);
|
|
3901
|
+
}
|
|
3902
|
+
logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
|
|
3801
3903
|
const rawActions = result.actions || [];
|
|
3802
3904
|
const actions = convertQuestionsToActions(rawActions);
|
|
3803
3905
|
logger.info(`[${this.getProviderName()}] Matched ${matchedComponents.length} components from text response`);
|
|
3804
3906
|
logger.info(`[${this.getProviderName()}] Layout title: "${layoutTitle}"`);
|
|
3805
3907
|
logger.info(`[${this.getProviderName()}] Layout description: "${layoutDescription}"`);
|
|
3806
3908
|
logger.info(`[${this.getProviderName()}] Generated ${actions.length} follow-up actions`);
|
|
3909
|
+
if (suggestedComponents.length > 0) {
|
|
3910
|
+
logCollector?.info(`\u{1F4DD} Text Analysis suggested ${suggestedComponents.length} dashboard components:`);
|
|
3911
|
+
suggestedComponents.forEach((comp, idx) => {
|
|
3912
|
+
logCollector?.info(` c${idx + 1}: ${comp.type} - ${comp.reasoning}`);
|
|
3913
|
+
});
|
|
3914
|
+
}
|
|
3807
3915
|
if (matchedComponents.length > 0) {
|
|
3808
|
-
logCollector?.info(
|
|
3916
|
+
logCollector?.info(`\u{1F4E6} Matched ${matchedComponents.length} components for dashboard`);
|
|
3917
|
+
if (suggestedComponents.length !== matchedComponents.length) {
|
|
3918
|
+
logCollector?.warn(`\u26A0\uFE0F Component count mismatch: Suggested ${suggestedComponents.length}, but matched ${matchedComponents.length}`);
|
|
3919
|
+
}
|
|
3809
3920
|
logCollector?.info(`Dashboard: "${layoutTitle}"`);
|
|
3810
3921
|
matchedComponents.forEach((comp, idx) => {
|
|
3811
3922
|
logCollector?.info(` ${idx + 1}. ${comp.componentName} (${comp.componentType}): ${comp.reasoning}`);
|
|
@@ -4280,11 +4391,17 @@ ${errorMsg}
|
|
|
4280
4391
|
let actions = [];
|
|
4281
4392
|
if (components && components.length > 0) {
|
|
4282
4393
|
logger.info(`[${this.getProviderName()}] Matching components from text response...`);
|
|
4283
|
-
const
|
|
4394
|
+
const componentStreamCallback = wrappedStreamCallback ? (component) => {
|
|
4395
|
+
const answerMarker = `__ANSWER_COMPONENT_START__${JSON.stringify(component)}__ANSWER_COMPONENT_END__`;
|
|
4396
|
+
wrappedStreamCallback(answerMarker);
|
|
4397
|
+
logger.info(`[${this.getProviderName()}] Streamed answer component to frontend: ${component.name} (${component.type})`);
|
|
4398
|
+
} : void 0;
|
|
4399
|
+
const matchResult = await this.matchComponentsFromAnalysis(
|
|
4284
4400
|
textResponse,
|
|
4285
4401
|
components,
|
|
4286
4402
|
apiKey,
|
|
4287
|
-
logCollector
|
|
4403
|
+
logCollector,
|
|
4404
|
+
componentStreamCallback
|
|
4288
4405
|
);
|
|
4289
4406
|
matchedComponents = matchResult.components;
|
|
4290
4407
|
layoutTitle = matchResult.layoutTitle;
|
|
@@ -5159,7 +5276,6 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
|
5159
5276
|
...res
|
|
5160
5277
|
}
|
|
5161
5278
|
};
|
|
5162
|
-
logger.info("sending user prompt response", response);
|
|
5163
5279
|
sendMessage(response);
|
|
5164
5280
|
}
|
|
5165
5281
|
|