@superatomai/sdk-node 0.0.77 → 0.0.79
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/README.md +942 -942
- package/dist/index.js +240 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +240 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -345,7 +345,8 @@ var UserQueryFiltersSchema = z3.object({
|
|
|
345
345
|
username: z3.string().optional(),
|
|
346
346
|
email: z3.string().optional(),
|
|
347
347
|
role: z3.string().optional(),
|
|
348
|
-
fullname: z3.string().optional()
|
|
348
|
+
fullname: z3.string().optional(),
|
|
349
|
+
id: z3.number().optional()
|
|
349
350
|
});
|
|
350
351
|
var UsersRequestPayloadSchema = z3.object({
|
|
351
352
|
operation: z3.enum(["create", "update", "delete", "getAll", "getOne", "query"]),
|
|
@@ -695,6 +696,67 @@ var DashCompRequestMessageSchema = z3.object({
|
|
|
695
696
|
type: z3.literal("DASH_COMP_REQ"),
|
|
696
697
|
payload: DashCompRequestPayloadSchema
|
|
697
698
|
});
|
|
699
|
+
var SchemaColumnStatisticsSchema = z3.object({
|
|
700
|
+
distinct: z3.number().optional(),
|
|
701
|
+
min: z3.number().optional(),
|
|
702
|
+
max: z3.number().optional()
|
|
703
|
+
});
|
|
704
|
+
var SchemaColumnSchema = z3.object({
|
|
705
|
+
name: z3.string(),
|
|
706
|
+
type: z3.string(),
|
|
707
|
+
nativeType: z3.string(),
|
|
708
|
+
nullable: z3.boolean(),
|
|
709
|
+
description: z3.string(),
|
|
710
|
+
statistics: SchemaColumnStatisticsSchema.optional(),
|
|
711
|
+
cardinality: z3.enum(["unique", "high", "medium", "low"]).optional(),
|
|
712
|
+
sampleValues: z3.array(z3.string()).optional()
|
|
713
|
+
});
|
|
714
|
+
var SchemaTableSchema = z3.object({
|
|
715
|
+
name: z3.string(),
|
|
716
|
+
fullName: z3.string(),
|
|
717
|
+
rowCount: z3.number(),
|
|
718
|
+
description: z3.string(),
|
|
719
|
+
columns: z3.array(SchemaColumnSchema)
|
|
720
|
+
});
|
|
721
|
+
var SchemaRelationshipSchema = z3.object({
|
|
722
|
+
from: z3.string(),
|
|
723
|
+
to: z3.string(),
|
|
724
|
+
type: z3.string(),
|
|
725
|
+
keys: z3.array(z3.string())
|
|
726
|
+
});
|
|
727
|
+
var DatabaseSchemaSchema = z3.object({
|
|
728
|
+
database: z3.string(),
|
|
729
|
+
databaseType: z3.string().optional(),
|
|
730
|
+
schema: z3.string(),
|
|
731
|
+
description: z3.string(),
|
|
732
|
+
tables: z3.array(SchemaTableSchema),
|
|
733
|
+
relationships: z3.array(SchemaRelationshipSchema).optional()
|
|
734
|
+
});
|
|
735
|
+
var SchemaRequestPayloadSchema = z3.object({
|
|
736
|
+
/** If true, returns the formatted documentation string in addition to raw JSON */
|
|
737
|
+
formatted: z3.boolean().optional()
|
|
738
|
+
});
|
|
739
|
+
var SchemaRequestMessageSchema = z3.object({
|
|
740
|
+
id: z3.string(),
|
|
741
|
+
from: MessageParticipantSchema,
|
|
742
|
+
type: z3.literal("SCHEMA_REQ"),
|
|
743
|
+
payload: SchemaRequestPayloadSchema
|
|
744
|
+
});
|
|
745
|
+
var SchemaResponsePayloadSchema = z3.object({
|
|
746
|
+
success: z3.boolean(),
|
|
747
|
+
error: z3.string().optional(),
|
|
748
|
+
data: z3.object({
|
|
749
|
+
schema: DatabaseSchemaSchema,
|
|
750
|
+
/** Formatted schema documentation (only if formatted: true was requested) */
|
|
751
|
+
formatted: z3.string().optional()
|
|
752
|
+
}).optional()
|
|
753
|
+
});
|
|
754
|
+
var SchemaResponseMessageSchema = z3.object({
|
|
755
|
+
id: z3.string(),
|
|
756
|
+
from: MessageParticipantSchema,
|
|
757
|
+
type: z3.literal("SCHEMA_RES"),
|
|
758
|
+
payload: SchemaResponsePayloadSchema
|
|
759
|
+
});
|
|
698
760
|
|
|
699
761
|
// src/utils/logger.ts
|
|
700
762
|
import fs from "fs";
|
|
@@ -3479,6 +3541,7 @@ You MUST respond with ONLY a valid JSON object (no markdown, no code blocks):
|
|
|
3479
3541
|
|
|
3480
3542
|
**CRITICAL:**
|
|
3481
3543
|
- Return ONLY valid JSON (no markdown code blocks, no text before/after)
|
|
3544
|
+
-\`componentName\`: MUST be the EXACT \`name\` field from the Available Components list. Never use a title or description as componentName.
|
|
3482
3545
|
- \`componentId\`: For new components, MUST match an ID from the available components list. For updates, preserve the existing component's ID
|
|
3483
3546
|
- \`isUpdate\`: Set to \`true\` if updating an existing component, \`false\` if creating new
|
|
3484
3547
|
- \`dataSourceType\` indicates whether data comes from database or external tool
|
|
@@ -6476,6 +6539,7 @@ var STREAM_PREVIEW_MAX_CHARS = 200;
|
|
|
6476
6539
|
var TOOL_TRACKING_MAX_ROWS = 5;
|
|
6477
6540
|
var TOOL_TRACKING_MAX_CHARS = 200;
|
|
6478
6541
|
var TOOL_TRACKING_SAMPLE_ROWS = 3;
|
|
6542
|
+
var DEFAULT_QUERY_LIMIT = 10;
|
|
6479
6543
|
var MAX_COMPONENT_QUERY_LIMIT = 10;
|
|
6480
6544
|
var EXACT_MATCH_SIMILARITY_THRESHOLD = 0.99;
|
|
6481
6545
|
var DEFAULT_CONVERSATION_SIMILARITY_THRESHOLD = 0.8;
|
|
@@ -12166,6 +12230,7 @@ function formatComponentsForPrompt(components) {
|
|
|
12166
12230
|
if (!components || components.length === 0) {
|
|
12167
12231
|
return "No components available";
|
|
12168
12232
|
}
|
|
12233
|
+
components = components.filter((c) => c.name !== "MultiComponentContainer");
|
|
12169
12234
|
return components.map((comp, idx) => {
|
|
12170
12235
|
const keywords = comp.keywords ? comp.keywords.join(", ") : "";
|
|
12171
12236
|
const propsPreview = comp.props ? JSON.stringify(comp.props, null, 2) : "No props";
|
|
@@ -12212,7 +12277,7 @@ function sendDashCompResponse(id, res, sendMessage, clientId) {
|
|
|
12212
12277
|
}
|
|
12213
12278
|
|
|
12214
12279
|
// src/dashComp/pick-component.ts
|
|
12215
|
-
async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders,
|
|
12280
|
+
async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, dashCompModels) {
|
|
12216
12281
|
const errors = [];
|
|
12217
12282
|
const availableComponentsText = formatComponentsForPrompt(components);
|
|
12218
12283
|
const availableToolsText = formatToolsForPrompt(tools);
|
|
@@ -12268,7 +12333,8 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
12268
12333
|
outputSchema: tool.outputSchema
|
|
12269
12334
|
});
|
|
12270
12335
|
logger.info(`[DASH_COMP_REQ] Tool ${tool.name} executed successfully`);
|
|
12271
|
-
|
|
12336
|
+
const resultJson = JSON.stringify(result2, null, 2);
|
|
12337
|
+
return resultJson + "\n\n[REMINDER: The above is tool output for verification. You MUST still respond with ONLY the JSON component selection object. Do NOT summarize or describe these results.]";
|
|
12272
12338
|
};
|
|
12273
12339
|
const result = await LLM.streamWithTools(
|
|
12274
12340
|
{
|
|
@@ -12286,16 +12352,59 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
12286
12352
|
5
|
|
12287
12353
|
// max iterations
|
|
12288
12354
|
);
|
|
12289
|
-
|
|
12290
|
-
|
|
12355
|
+
let jsonMatch = result.match(/\{[\s\S]*\}/);
|
|
12356
|
+
let parsedResult = jsonMatch ? (() => {
|
|
12357
|
+
try {
|
|
12358
|
+
return JSON.parse(jsonMatch[0]);
|
|
12359
|
+
} catch {
|
|
12360
|
+
return null;
|
|
12361
|
+
}
|
|
12362
|
+
})() : null;
|
|
12363
|
+
const isValidComponent = parsedResult && parsedResult.componentId && parsedResult.props;
|
|
12364
|
+
if (!isValidComponent && executedTools.length > 0) {
|
|
12365
|
+
const toolDataSummary = executedTools.map(
|
|
12366
|
+
(t) => `Tool "${t.name}" was called with params ${JSON.stringify(t.params)} and returned:
|
|
12367
|
+
${JSON.stringify(t.result, null, 2).substring(0, 5e3)}`
|
|
12368
|
+
).join("\n\n");
|
|
12369
|
+
const retryUserPrompt = `Original user request: ${prompt}
|
|
12370
|
+
|
|
12371
|
+
The following tool was already called and returned data:
|
|
12372
|
+
${toolDataSummary}
|
|
12373
|
+
|
|
12374
|
+
Using this data, select the appropriate component and respond with ONLY the JSON component selection object. No explanation, no markdown, just JSON.`;
|
|
12375
|
+
const retryResult = await LLM.text(
|
|
12376
|
+
{
|
|
12377
|
+
sys: prompts.system,
|
|
12378
|
+
user: retryUserPrompt
|
|
12379
|
+
},
|
|
12380
|
+
{
|
|
12381
|
+
model,
|
|
12382
|
+
maxTokens: 4096,
|
|
12383
|
+
temperature: 0.1,
|
|
12384
|
+
apiKey
|
|
12385
|
+
}
|
|
12386
|
+
);
|
|
12387
|
+
jsonMatch = retryResult.match(/\{[\s\S]*\}/);
|
|
12388
|
+
parsedResult = jsonMatch ? (() => {
|
|
12389
|
+
try {
|
|
12390
|
+
return JSON.parse(jsonMatch[0]);
|
|
12391
|
+
} catch {
|
|
12392
|
+
return null;
|
|
12393
|
+
}
|
|
12394
|
+
})() : null;
|
|
12395
|
+
}
|
|
12291
12396
|
if (!parsedResult) {
|
|
12292
12397
|
errors.push("Failed to parse LLM response as JSON");
|
|
12398
|
+
errors.push(`LLM Response: ${result}`);
|
|
12399
|
+
logger.error(`[DASH_COMP_REQ] Failed to parse JSON from LLM response`);
|
|
12293
12400
|
return { success: false, errors };
|
|
12294
12401
|
}
|
|
12295
|
-
logger.
|
|
12402
|
+
logger.info(`[DASH_COMP_REQ] Parsed component: ${parsedResult.componentName} (${parsedResult.componentId})`);
|
|
12296
12403
|
logger.file("[DASH_COMP_REQ] LLM response:", JSON.stringify(parsedResult, null, 2));
|
|
12297
12404
|
if (!parsedResult.componentId || !parsedResult.props) {
|
|
12298
12405
|
errors.push("Invalid LLM response: missing componentId or props");
|
|
12406
|
+
errors.push(`LLM Response: ${result}`);
|
|
12407
|
+
logger.error(`[DASH_COMP_REQ] Invalid structure - missing componentId: ${!parsedResult.componentId}, missing props: ${!parsedResult.props}`);
|
|
12299
12408
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Invalid LLM response structure", {
|
|
12300
12409
|
prompt,
|
|
12301
12410
|
result: parsedResult,
|
|
@@ -12306,6 +12415,7 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
12306
12415
|
const originalComponent = components.find((c) => c.name === parsedResult.componentName);
|
|
12307
12416
|
if (!originalComponent) {
|
|
12308
12417
|
errors.push(`Component ${parsedResult.componentName} not found in available components`);
|
|
12418
|
+
errors.push(`LLM Response: ${result}`);
|
|
12309
12419
|
userPromptErrorLogger.logError("DASH_COMP_REQ", "Component not found", {
|
|
12310
12420
|
prompt,
|
|
12311
12421
|
componentName: parsedResult.componentName,
|
|
@@ -12313,14 +12423,72 @@ async function pickComponentWithLLM(prompt, components, anthropicApiKey, groqApi
|
|
|
12313
12423
|
});
|
|
12314
12424
|
return { success: false, errors };
|
|
12315
12425
|
}
|
|
12316
|
-
|
|
12426
|
+
let finalComponent = {
|
|
12317
12427
|
...originalComponent,
|
|
12318
12428
|
props: {
|
|
12319
12429
|
...originalComponent.props,
|
|
12320
12430
|
...parsedResult.props
|
|
12321
12431
|
}
|
|
12322
12432
|
};
|
|
12433
|
+
if (finalComponent.props?.query) {
|
|
12434
|
+
const query = finalComponent.props.query;
|
|
12435
|
+
if (typeof query === "string") {
|
|
12436
|
+
finalComponent.props.query = ensureQueryLimit(query, DEFAULT_QUERY_LIMIT, MAX_COMPONENT_QUERY_LIMIT);
|
|
12437
|
+
} else if (query?.sql) {
|
|
12438
|
+
finalComponent.props.query = {
|
|
12439
|
+
...query,
|
|
12440
|
+
sql: ensureQueryLimit(query.sql, DEFAULT_QUERY_LIMIT, MAX_COMPONENT_QUERY_LIMIT)
|
|
12441
|
+
};
|
|
12442
|
+
}
|
|
12443
|
+
}
|
|
12323
12444
|
logger.info(`[DASH_COMP_REQ] Successfully picked component: ${finalComponent.name} (${finalComponent.type})`);
|
|
12445
|
+
if (finalComponent.props?.query && collections?.["database"]?.["execute"]) {
|
|
12446
|
+
logger.info(`[DASH_COMP_REQ] Validating query for component: ${finalComponent.name}`);
|
|
12447
|
+
const queryService = new QueryExecutionService({
|
|
12448
|
+
defaultLimit: DEFAULT_QUERY_LIMIT,
|
|
12449
|
+
getModelForTask: () => model,
|
|
12450
|
+
// Use the same model for query fixes
|
|
12451
|
+
getApiKey: () => apiKey,
|
|
12452
|
+
providerName: "DASH_COMP_REQ"
|
|
12453
|
+
});
|
|
12454
|
+
try {
|
|
12455
|
+
const validationResult = await queryService.validateSingleQuery(
|
|
12456
|
+
finalComponent,
|
|
12457
|
+
collections,
|
|
12458
|
+
apiKey
|
|
12459
|
+
);
|
|
12460
|
+
if (!validationResult.validated) {
|
|
12461
|
+
logger.error(`[DASH_COMP_REQ] Query validation failed for component: ${finalComponent.name}`);
|
|
12462
|
+
errors.push(`Query validation failed for component ${finalComponent.name}. The generated SQL query could not be executed.`);
|
|
12463
|
+
return {
|
|
12464
|
+
success: false,
|
|
12465
|
+
errors,
|
|
12466
|
+
data: {
|
|
12467
|
+
reasoning: parsedResult.reasoning || "Component selected but query validation failed",
|
|
12468
|
+
rawResponse: parsedResult
|
|
12469
|
+
}
|
|
12470
|
+
};
|
|
12471
|
+
}
|
|
12472
|
+
if (validationResult.component) {
|
|
12473
|
+
finalComponent = validationResult.component;
|
|
12474
|
+
}
|
|
12475
|
+
logger.info(`[DASH_COMP_REQ] Query validated successfully for component: ${finalComponent.name}`);
|
|
12476
|
+
} catch (validationError) {
|
|
12477
|
+
const validationErrorMsg = validationError instanceof Error ? validationError.message : String(validationError);
|
|
12478
|
+
logger.error(`[DASH_COMP_REQ] Query validation error: ${validationErrorMsg}`);
|
|
12479
|
+
errors.push(`Query validation error: ${validationErrorMsg}`);
|
|
12480
|
+
return {
|
|
12481
|
+
success: false,
|
|
12482
|
+
errors,
|
|
12483
|
+
data: {
|
|
12484
|
+
reasoning: parsedResult.reasoning || "Component selected but query validation encountered an error",
|
|
12485
|
+
rawResponse: parsedResult
|
|
12486
|
+
}
|
|
12487
|
+
};
|
|
12488
|
+
}
|
|
12489
|
+
} else if (finalComponent.props?.query && !collections?.["database"]?.["execute"]) {
|
|
12490
|
+
logger.warn(`[DASH_COMP_REQ] Skipping query validation - database execute function not available`);
|
|
12491
|
+
}
|
|
12324
12492
|
if (parsedResult.props.query) {
|
|
12325
12493
|
logger.info(`[DASH_COMP_REQ] Data source: Database query`);
|
|
12326
12494
|
}
|
|
@@ -12430,12 +12598,14 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
12430
12598
|
const result = jsonMatch ? JSON.parse(jsonMatch[0]) : null;
|
|
12431
12599
|
if (!result) {
|
|
12432
12600
|
errors.push("Failed to parse LLM response as JSON");
|
|
12601
|
+
errors.push(`LLM Response: ${rawResult}`);
|
|
12433
12602
|
return { success: false, errors };
|
|
12434
12603
|
}
|
|
12435
12604
|
logger.debug("[DASH_COMP_REQ:FILTER] LLM response received");
|
|
12436
12605
|
logger.file("[DASH_COMP_REQ:FILTER] LLM response:", JSON.stringify(result, null, 2));
|
|
12437
12606
|
if (!result.filterComponent) {
|
|
12438
12607
|
errors.push("Invalid LLM response: missing filterComponent");
|
|
12608
|
+
errors.push(`LLM Response: ${rawResult}`);
|
|
12439
12609
|
userPromptErrorLogger.logError("DASH_COMP_REQ:FILTER", "Invalid LLM response structure", {
|
|
12440
12610
|
prompt,
|
|
12441
12611
|
result,
|
|
@@ -12578,6 +12748,64 @@ async function handleDashCompRequest(data, components, sendMessage, anthropicApi
|
|
|
12578
12748
|
logger.info(`[DASH_COMP_REQ] Response sent to client ${response.wsId || data.from?.id}`);
|
|
12579
12749
|
}
|
|
12580
12750
|
|
|
12751
|
+
// src/handlers/schema-request.ts
|
|
12752
|
+
async function handleSchemaRequest(message, sendMessage) {
|
|
12753
|
+
const startTime = Date.now();
|
|
12754
|
+
try {
|
|
12755
|
+
const payload = message.payload;
|
|
12756
|
+
const formatted = payload?.formatted ?? false;
|
|
12757
|
+
logger.info(`[SchemaRequest] Processing schema request (formatted: ${formatted})`);
|
|
12758
|
+
const schemaData = schema.getSchema();
|
|
12759
|
+
if (!schemaData) {
|
|
12760
|
+
const response2 = {
|
|
12761
|
+
id: message.id,
|
|
12762
|
+
type: "SCHEMA_RES",
|
|
12763
|
+
from: { type: "data-agent" },
|
|
12764
|
+
to: message.from,
|
|
12765
|
+
payload: {
|
|
12766
|
+
success: false,
|
|
12767
|
+
error: "Schema not found or failed to load"
|
|
12768
|
+
}
|
|
12769
|
+
};
|
|
12770
|
+
sendMessage(response2);
|
|
12771
|
+
return;
|
|
12772
|
+
}
|
|
12773
|
+
const responseData = {
|
|
12774
|
+
schema: schemaData
|
|
12775
|
+
};
|
|
12776
|
+
if (formatted) {
|
|
12777
|
+
responseData.formatted = schema.generateSchemaDocumentation();
|
|
12778
|
+
}
|
|
12779
|
+
const executionMs = Date.now() - startTime;
|
|
12780
|
+
logger.info(`[SchemaRequest] Schema retrieved successfully in ${executionMs}ms`);
|
|
12781
|
+
const response = {
|
|
12782
|
+
id: message.id,
|
|
12783
|
+
type: "SCHEMA_RES",
|
|
12784
|
+
from: { type: "data-agent" },
|
|
12785
|
+
to: message.from,
|
|
12786
|
+
payload: {
|
|
12787
|
+
success: true,
|
|
12788
|
+
data: responseData
|
|
12789
|
+
}
|
|
12790
|
+
};
|
|
12791
|
+
sendMessage(response);
|
|
12792
|
+
} catch (error) {
|
|
12793
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
12794
|
+
logger.error(`[SchemaRequest] Error: ${errorMsg}`);
|
|
12795
|
+
const response = {
|
|
12796
|
+
id: message.id,
|
|
12797
|
+
type: "SCHEMA_RES",
|
|
12798
|
+
from: { type: "data-agent" },
|
|
12799
|
+
to: message.from,
|
|
12800
|
+
payload: {
|
|
12801
|
+
success: false,
|
|
12802
|
+
error: errorMsg
|
|
12803
|
+
}
|
|
12804
|
+
};
|
|
12805
|
+
sendMessage(response);
|
|
12806
|
+
}
|
|
12807
|
+
}
|
|
12808
|
+
|
|
12581
12809
|
// src/auth/user-manager.ts
|
|
12582
12810
|
import fs7 from "fs";
|
|
12583
12811
|
import path6 from "path";
|
|
@@ -13826,6 +14054,11 @@ var SuperatomSDK = class {
|
|
|
13826
14054
|
logger.error("Failed to handle dash comp request:", error);
|
|
13827
14055
|
});
|
|
13828
14056
|
break;
|
|
14057
|
+
case "SCHEMA_REQ":
|
|
14058
|
+
handleSchemaRequest(parsed, (msg) => this.send(msg)).catch((error) => {
|
|
14059
|
+
logger.error("Failed to handle schema request:", error);
|
|
14060
|
+
});
|
|
14061
|
+
break;
|
|
13829
14062
|
default:
|
|
13830
14063
|
const handler = this.messageTypeHandlers.get(message.type);
|
|
13831
14064
|
if (handler) {
|