@superatomai/sdk-node 0.0.3 → 0.0.5
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 +74 -25
- package/dist/index.d.mts +150 -11
- package/dist/index.d.ts +150 -11
- package/dist/index.js +1016 -305
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1014 -304
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -441,7 +441,8 @@ __export(index_exports, {
|
|
|
441
441
|
ThreadManager: () => ThreadManager,
|
|
442
442
|
UIBlock: () => UIBlock,
|
|
443
443
|
UILogCollector: () => UILogCollector,
|
|
444
|
-
UserManager: () => UserManager
|
|
444
|
+
UserManager: () => UserManager,
|
|
445
|
+
logger: () => logger
|
|
445
446
|
});
|
|
446
447
|
module.exports = __toCommonJS(index_exports);
|
|
447
448
|
|
|
@@ -641,6 +642,18 @@ var DSLRendererPropsSchema2 = import_zod2.z.object({
|
|
|
641
642
|
});
|
|
642
643
|
|
|
643
644
|
// src/types.ts
|
|
645
|
+
var UserSchema = import_zod3.z.object({
|
|
646
|
+
username: import_zod3.z.string().min(1, "Username is required"),
|
|
647
|
+
email: import_zod3.z.string().email("Invalid email format").optional(),
|
|
648
|
+
password: import_zod3.z.string().min(1, "Password is required"),
|
|
649
|
+
fullname: import_zod3.z.string().optional(),
|
|
650
|
+
role: import_zod3.z.string().optional(),
|
|
651
|
+
wsIds: import_zod3.z.array(import_zod3.z.string()).optional()
|
|
652
|
+
// Only in memory, not persisted to file
|
|
653
|
+
});
|
|
654
|
+
var UsersDataSchema = import_zod3.z.object({
|
|
655
|
+
users: import_zod3.z.array(UserSchema)
|
|
656
|
+
});
|
|
644
657
|
var MessageParticipantSchema = import_zod3.z.object({
|
|
645
658
|
id: import_zod3.z.string().optional(),
|
|
646
659
|
type: import_zod3.z.string().optional()
|
|
@@ -741,7 +754,10 @@ var UsersRequestPayloadSchema = import_zod3.z.object({
|
|
|
741
754
|
operation: import_zod3.z.enum(["create", "update", "delete", "getAll", "getOne"]),
|
|
742
755
|
data: import_zod3.z.object({
|
|
743
756
|
username: import_zod3.z.string().optional(),
|
|
744
|
-
|
|
757
|
+
email: import_zod3.z.string().email("Invalid email format").optional(),
|
|
758
|
+
password: import_zod3.z.string().optional(),
|
|
759
|
+
fullname: import_zod3.z.string().optional(),
|
|
760
|
+
role: import_zod3.z.string().optional()
|
|
745
761
|
}).optional()
|
|
746
762
|
});
|
|
747
763
|
var UsersRequestMessageSchema = import_zod3.z.object({
|
|
@@ -807,20 +823,91 @@ var ReportsRequestMessageSchema = import_zod3.z.object({
|
|
|
807
823
|
|
|
808
824
|
// src/utils/logger.ts
|
|
809
825
|
var PREFIX = "[SuperatomSDK]";
|
|
810
|
-
var
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
debug:
|
|
821
|
-
|
|
826
|
+
var LOG_LEVEL_PRIORITY = {
|
|
827
|
+
errors: 0,
|
|
828
|
+
warnings: 1,
|
|
829
|
+
info: 2,
|
|
830
|
+
verbose: 3
|
|
831
|
+
};
|
|
832
|
+
var MESSAGE_LEVEL_PRIORITY = {
|
|
833
|
+
error: 0,
|
|
834
|
+
warn: 1,
|
|
835
|
+
info: 2,
|
|
836
|
+
debug: 3
|
|
837
|
+
};
|
|
838
|
+
var Logger = class {
|
|
839
|
+
constructor() {
|
|
840
|
+
const envLevel = (process.env.SUPERATOM_LOG_LEVEL || "info").toLowerCase();
|
|
841
|
+
if (this.isValidLogLevel(envLevel)) {
|
|
842
|
+
this.currentLevel = envLevel;
|
|
843
|
+
} else {
|
|
844
|
+
this.currentLevel = "info";
|
|
845
|
+
console.warn(
|
|
846
|
+
`${PREFIX} Invalid log level "${envLevel}". Using default "info". Valid levels: errors, warnings, info, verbose`
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
this.currentLevelPriority = LOG_LEVEL_PRIORITY[this.currentLevel];
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Check if a string is a valid log level
|
|
853
|
+
*/
|
|
854
|
+
isValidLogLevel(level) {
|
|
855
|
+
return level === "errors" || level === "warnings" || level === "info" || level === "verbose";
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Check if a message should be logged based on current log level
|
|
859
|
+
*/
|
|
860
|
+
shouldLog(messageLevel) {
|
|
861
|
+
const messagePriority = MESSAGE_LEVEL_PRIORITY[messageLevel];
|
|
862
|
+
return messagePriority <= this.currentLevelPriority;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Get current log level
|
|
866
|
+
*/
|
|
867
|
+
getLogLevel() {
|
|
868
|
+
return this.currentLevel;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Set log level programmatically
|
|
872
|
+
*/
|
|
873
|
+
setLogLevel(level) {
|
|
874
|
+
this.currentLevel = level;
|
|
875
|
+
this.currentLevelPriority = LOG_LEVEL_PRIORITY[level];
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Log info message (shown for info and verbose levels)
|
|
879
|
+
*/
|
|
880
|
+
info(...args) {
|
|
881
|
+
if (this.shouldLog("info")) {
|
|
882
|
+
console.log(PREFIX, ...args);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Log error message (shown for all levels)
|
|
887
|
+
*/
|
|
888
|
+
error(...args) {
|
|
889
|
+
if (this.shouldLog("error")) {
|
|
890
|
+
console.error(PREFIX, ...args);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Log warning message (shown for warnings, info, and verbose levels)
|
|
895
|
+
*/
|
|
896
|
+
warn(...args) {
|
|
897
|
+
if (this.shouldLog("warn")) {
|
|
898
|
+
console.warn(PREFIX, ...args);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Log debug message (only shown for verbose level)
|
|
903
|
+
*/
|
|
904
|
+
debug(...args) {
|
|
905
|
+
if (this.shouldLog("debug")) {
|
|
906
|
+
console.log(PREFIX, "[DEBUG]", ...args);
|
|
907
|
+
}
|
|
822
908
|
}
|
|
823
909
|
};
|
|
910
|
+
var logger = new Logger();
|
|
824
911
|
|
|
825
912
|
// src/threads/uiblock.ts
|
|
826
913
|
var import_crypto = require("crypto");
|
|
@@ -855,13 +942,15 @@ var UIBlock = class {
|
|
|
855
942
|
* @param generatedComponentMetadata - Optional metadata about the generated component
|
|
856
943
|
* @param actions - Optional array of available actions
|
|
857
944
|
* @param id - Optional custom ID, generates UUID if not provided
|
|
945
|
+
* @param textResponse - Optional text response from LLM
|
|
858
946
|
*/
|
|
859
|
-
constructor(userQuestion, componentData = {}, generatedComponentMetadata = {}, actions = [], id) {
|
|
947
|
+
constructor(userQuestion, componentData = {}, generatedComponentMetadata = {}, actions = [], id, textResponse = null) {
|
|
860
948
|
this.id = id || (0, import_crypto.randomUUID)();
|
|
861
949
|
this.userQuestion = userQuestion;
|
|
862
950
|
this.componentData = componentData;
|
|
863
951
|
this.generatedComponentMetadata = generatedComponentMetadata;
|
|
864
952
|
this.actions = actions;
|
|
953
|
+
this.textResponse = textResponse;
|
|
865
954
|
this.createdAt = /* @__PURE__ */ new Date();
|
|
866
955
|
}
|
|
867
956
|
/**
|
|
@@ -980,6 +1069,18 @@ var UIBlock = class {
|
|
|
980
1069
|
const processedData = this.processDataForStorage(data);
|
|
981
1070
|
this.componentData = { ...this.componentData, ...processedData };
|
|
982
1071
|
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Get text response
|
|
1074
|
+
*/
|
|
1075
|
+
getTextResponse() {
|
|
1076
|
+
return this.textResponse;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Set or update text response
|
|
1080
|
+
*/
|
|
1081
|
+
setTextResponse(textResponse) {
|
|
1082
|
+
this.textResponse = textResponse;
|
|
1083
|
+
}
|
|
983
1084
|
/**
|
|
984
1085
|
* Get all actions (only if they are resolved, not if fetching)
|
|
985
1086
|
*/
|
|
@@ -1063,6 +1164,7 @@ var UIBlock = class {
|
|
|
1063
1164
|
userQuestion: this.userQuestion,
|
|
1064
1165
|
generatedComponentMetadata: this.generatedComponentMetadata,
|
|
1065
1166
|
componentData: this.componentData,
|
|
1167
|
+
textResponse: this.textResponse,
|
|
1066
1168
|
actions: actionsValue,
|
|
1067
1169
|
isFetchingActions: this.actions instanceof Promise,
|
|
1068
1170
|
createdAt: this.createdAt.toISOString()
|
|
@@ -1497,9 +1599,9 @@ function getUserManager() {
|
|
|
1497
1599
|
}
|
|
1498
1600
|
return currentUserManager;
|
|
1499
1601
|
}
|
|
1500
|
-
function
|
|
1602
|
+
function findUserByUsernameOrEmail(identifier) {
|
|
1501
1603
|
const manager = getUserManager();
|
|
1502
|
-
const user = manager.
|
|
1604
|
+
const user = manager.getUserByUsernameOrEmail(identifier);
|
|
1503
1605
|
return user || null;
|
|
1504
1606
|
}
|
|
1505
1607
|
function addWsIdToUser(username, wsId) {
|
|
@@ -1521,60 +1623,81 @@ async function cleanupUserStorage() {
|
|
|
1521
1623
|
|
|
1522
1624
|
// src/auth/validator.ts
|
|
1523
1625
|
function validateUser(credentials) {
|
|
1524
|
-
const { username, password } = credentials;
|
|
1525
|
-
|
|
1526
|
-
|
|
1626
|
+
const { username, email, password } = credentials;
|
|
1627
|
+
const identifier = username || email;
|
|
1628
|
+
logger.debug("[validateUser] Starting user validation");
|
|
1629
|
+
logger.debug(`[validateUser] Username provided: ${username ? "\u2713" : "\u2717"}, Email provided: ${email ? "\u2713" : "\u2717"}, Password provided: ${password ? "\u2713" : "\u2717"}`);
|
|
1630
|
+
if (!identifier || !password) {
|
|
1631
|
+
logger.warn("[validateUser] Validation failed: Username/email and password are required");
|
|
1527
1632
|
return {
|
|
1528
1633
|
success: false,
|
|
1529
|
-
error: "Username and password are required"
|
|
1634
|
+
error: "Username or email and password are required"
|
|
1530
1635
|
};
|
|
1531
1636
|
}
|
|
1532
|
-
|
|
1637
|
+
logger.debug(`[validateUser] Looking up user by identifier: ${identifier}`);
|
|
1638
|
+
const user = findUserByUsernameOrEmail(identifier);
|
|
1533
1639
|
if (!user) {
|
|
1534
|
-
logger.warn(`Validation failed: User not found - ${
|
|
1640
|
+
logger.warn(`[validateUser] Validation failed: User not found - ${identifier}`);
|
|
1535
1641
|
return {
|
|
1536
1642
|
success: false,
|
|
1537
|
-
error: "Invalid username"
|
|
1643
|
+
error: "Invalid username or email"
|
|
1538
1644
|
};
|
|
1539
1645
|
}
|
|
1646
|
+
logger.debug(`[validateUser] User found: ${user.username}, verifying password`);
|
|
1540
1647
|
const hashedPassword = hashPassword(user.password);
|
|
1541
1648
|
if (hashedPassword !== password) {
|
|
1542
|
-
logger.warn(`Validation failed: Invalid password for user - ${username}`);
|
|
1649
|
+
logger.warn(`[validateUser] Validation failed: Invalid password for user - ${user.username}`);
|
|
1650
|
+
logger.debug(`[validateUser] Password hash mismatch for user: ${user.username}`);
|
|
1543
1651
|
return {
|
|
1544
1652
|
success: false,
|
|
1545
1653
|
error: "Invalid password"
|
|
1546
1654
|
};
|
|
1547
1655
|
}
|
|
1548
|
-
logger.
|
|
1656
|
+
logger.info(`[validateUser] \u2713 User validated successfully: ${user.username}`);
|
|
1657
|
+
logger.debug(`[validateUser] Returning user data for: ${user.username}`);
|
|
1549
1658
|
return {
|
|
1550
1659
|
success: true,
|
|
1551
|
-
data: user.username
|
|
1660
|
+
data: user.username,
|
|
1661
|
+
username: user.username
|
|
1552
1662
|
};
|
|
1553
1663
|
}
|
|
1554
1664
|
function authenticateAndStoreWsId(credentials, wsId) {
|
|
1665
|
+
const identifier = credentials.username || credentials.email;
|
|
1666
|
+
logger.debug("[authenticateAndStoreWsId] Starting authentication and WebSocket ID storage");
|
|
1667
|
+
logger.debug("[authenticateAndStoreWsId] Validating user credentials");
|
|
1555
1668
|
const validationResult = validateUser(credentials);
|
|
1556
1669
|
if (!validationResult.success) {
|
|
1670
|
+
logger.warn(`[authenticateAndStoreWsId] User validation failed for: ${identifier}`);
|
|
1557
1671
|
return validationResult;
|
|
1558
1672
|
}
|
|
1559
|
-
const
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
error: "Failed to store user session"
|
|
1565
|
-
};
|
|
1566
|
-
}
|
|
1567
|
-
logger.info(`WebSocket ID stored for user: ${credentials.username}`);
|
|
1673
|
+
const username = validationResult.username;
|
|
1674
|
+
logger.info(`[authenticateAndStoreWsId] User ${username} validated, storing WebSocket ID`);
|
|
1675
|
+
logger.debug(`[authenticateAndStoreWsId] Calling addWsIdToUser for ${username}`);
|
|
1676
|
+
addWsIdToUser(username, wsId);
|
|
1677
|
+
logger.debug(`[authenticateAndStoreWsId] WebSocket ID ${wsId} associated with user ${username}`);
|
|
1568
1678
|
return validationResult;
|
|
1569
1679
|
}
|
|
1570
1680
|
function verifyAuthToken(authToken) {
|
|
1571
1681
|
try {
|
|
1682
|
+
logger.debug("[verifyAuthToken] Starting token verification");
|
|
1683
|
+
logger.debug("[verifyAuthToken] Decoding base64 token");
|
|
1572
1684
|
const decodedString = Buffer.from(authToken, "base64").toString("utf-8");
|
|
1685
|
+
logger.debug("[verifyAuthToken] Parsing decoded token as JSON");
|
|
1573
1686
|
const credentials = JSON.parse(decodedString);
|
|
1574
|
-
logger.debug("Token decoded and parsed successfully");
|
|
1575
|
-
|
|
1687
|
+
logger.debug("[verifyAuthToken] Token decoded and parsed successfully");
|
|
1688
|
+
logger.debug(`[verifyAuthToken] Token contains username: ${credentials.username ? "\u2713" : "\u2717"}`);
|
|
1689
|
+
logger.debug("[verifyAuthToken] Validating credentials from token");
|
|
1690
|
+
const result = validateUser(credentials);
|
|
1691
|
+
if (result.success) {
|
|
1692
|
+
logger.info(`[verifyAuthToken] \u2713 Token verified successfully for user: ${credentials.username || "unknown"}`);
|
|
1693
|
+
} else {
|
|
1694
|
+
logger.warn(`[verifyAuthToken] Token verification failed: ${result.error}`);
|
|
1695
|
+
}
|
|
1696
|
+
return result;
|
|
1576
1697
|
} catch (error) {
|
|
1577
|
-
|
|
1698
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1699
|
+
logger.error(`[verifyAuthToken] Failed to verify auth token: ${errorMsg}`);
|
|
1700
|
+
logger.debug("[verifyAuthToken] Token verification error details:", error);
|
|
1578
1701
|
return {
|
|
1579
1702
|
success: false,
|
|
1580
1703
|
error: "Invalid token format"
|
|
@@ -1585,36 +1708,49 @@ function verifyAuthToken(authToken) {
|
|
|
1585
1708
|
// src/handlers/auth-login-requests.ts
|
|
1586
1709
|
async function handleAuthLoginRequest(data, sendMessage) {
|
|
1587
1710
|
try {
|
|
1711
|
+
logger.debug("[AUTH_LOGIN_REQ] Parsing incoming auth login request");
|
|
1588
1712
|
const authRequest = AuthLoginRequestMessageSchema.parse(data);
|
|
1589
1713
|
const { id, payload } = authRequest;
|
|
1590
1714
|
const login_data = payload.login_data;
|
|
1591
1715
|
const wsId = authRequest.from.id;
|
|
1716
|
+
logger.info(`[AUTH_LOGIN_REQ ${id}] Processing auth login request from client: ${wsId}`);
|
|
1717
|
+
logger.debug(`[AUTH_LOGIN_REQ ${id}] Login data present: ${!!login_data}`);
|
|
1592
1718
|
if (!login_data) {
|
|
1719
|
+
logger.error(`[AUTH_LOGIN_REQ ${id}] Login data not found in request`);
|
|
1593
1720
|
sendDataResponse2(id, {
|
|
1594
1721
|
success: false,
|
|
1595
1722
|
error: "Login data not found"
|
|
1596
1723
|
}, sendMessage, wsId);
|
|
1597
1724
|
return;
|
|
1598
1725
|
}
|
|
1726
|
+
logger.debug(`[AUTH_LOGIN_REQ ${id}] Decoding base64 login data`);
|
|
1599
1727
|
let loginData;
|
|
1600
1728
|
try {
|
|
1601
1729
|
loginData = decodeBase64ToJson(login_data);
|
|
1730
|
+
logger.debug(`[AUTH_LOGIN_REQ ${id}] Login data decoded successfully`);
|
|
1602
1731
|
} catch (error) {
|
|
1732
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1733
|
+
logger.error(`[AUTH_LOGIN_REQ ${id}] Failed to decode login data: ${errorMsg}`);
|
|
1734
|
+
logger.debug(`[AUTH_LOGIN_REQ ${id}] Decode error details:`, error);
|
|
1603
1735
|
sendDataResponse2(id, {
|
|
1604
1736
|
success: false,
|
|
1605
1737
|
error: "Invalid login data format"
|
|
1606
1738
|
}, sendMessage, wsId);
|
|
1607
1739
|
return;
|
|
1608
1740
|
}
|
|
1609
|
-
const { username, password } = loginData;
|
|
1610
|
-
|
|
1741
|
+
const { username, email, password } = loginData;
|
|
1742
|
+
const identifier = username || email;
|
|
1743
|
+
logger.debug(`[AUTH_LOGIN_REQ ${id}] Validating credentials - username: ${username ? "\u2713" : "\u2717"}, email: ${email ? "\u2713" : "\u2717"}, password: ${password ? "\u2713" : "\u2717"}`);
|
|
1744
|
+
if (!identifier) {
|
|
1745
|
+
logger.error(`[AUTH_LOGIN_REQ ${id}] Username or email not found in login data`);
|
|
1611
1746
|
sendDataResponse2(id, {
|
|
1612
1747
|
success: false,
|
|
1613
|
-
error: "Username
|
|
1748
|
+
error: "Username or email is required"
|
|
1614
1749
|
}, sendMessage, wsId);
|
|
1615
1750
|
return;
|
|
1616
1751
|
}
|
|
1617
1752
|
if (!password) {
|
|
1753
|
+
logger.error(`[AUTH_LOGIN_REQ ${id}] Password not found in login data`);
|
|
1618
1754
|
sendDataResponse2(id, {
|
|
1619
1755
|
success: false,
|
|
1620
1756
|
error: "Password not found in login data"
|
|
@@ -1622,20 +1758,46 @@ async function handleAuthLoginRequest(data, sendMessage) {
|
|
|
1622
1758
|
return;
|
|
1623
1759
|
}
|
|
1624
1760
|
if (!wsId) {
|
|
1761
|
+
logger.error(`[AUTH_LOGIN_REQ ${id}] WebSocket ID not found in request`);
|
|
1625
1762
|
sendDataResponse2(id, {
|
|
1626
1763
|
success: false,
|
|
1627
1764
|
error: "WebSocket ID not found"
|
|
1628
1765
|
}, sendMessage, wsId);
|
|
1629
1766
|
return;
|
|
1630
1767
|
}
|
|
1768
|
+
logger.info(`[AUTH_LOGIN_REQ ${id}] Credentials validated, authenticating user: ${identifier}`);
|
|
1769
|
+
logger.debug(`[AUTH_LOGIN_REQ ${id}] WebSocket ID: ${wsId}`);
|
|
1770
|
+
logger.debug(`[AUTH_LOGIN_REQ ${id}] Calling authenticateAndStoreWsId for user: ${identifier}`);
|
|
1631
1771
|
const authResult = authenticateAndStoreWsId(
|
|
1632
|
-
{ username, password },
|
|
1772
|
+
{ username, email, password },
|
|
1633
1773
|
wsId
|
|
1634
1774
|
);
|
|
1775
|
+
logger.info(`[AUTH_LOGIN_REQ ${id}] Authentication result for ${identifier}: ${authResult.success ? "success" : "failed"}`);
|
|
1776
|
+
if (!authResult.success) {
|
|
1777
|
+
logger.warn(`[AUTH_LOGIN_REQ ${id}] Authentication failed for ${identifier}: ${authResult.error}`);
|
|
1778
|
+
} else {
|
|
1779
|
+
logger.info(`[AUTH_LOGIN_REQ ${id}] User ${authResult.username || identifier} authenticated successfully`);
|
|
1780
|
+
}
|
|
1781
|
+
logger.debug(`[AUTH_LOGIN_REQ ${id}] Sending auth response to client`);
|
|
1635
1782
|
sendDataResponse2(id, authResult, sendMessage, wsId);
|
|
1783
|
+
logger.info(`[AUTH_LOGIN_REQ ${id}] ${authResult.success ? "\u2713" : "\u2717"} Auth login request completed`);
|
|
1636
1784
|
return;
|
|
1637
1785
|
} catch (error) {
|
|
1638
|
-
|
|
1786
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1787
|
+
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
1788
|
+
logger.error(`[AUTH_LOGIN_REQ] Failed to handle auth login request: ${errorMessage}`);
|
|
1789
|
+
logger.debug(`[AUTH_LOGIN_REQ] Error stack trace:`, errorStack);
|
|
1790
|
+
try {
|
|
1791
|
+
const parsedData = data;
|
|
1792
|
+
if (parsedData?.id) {
|
|
1793
|
+
sendDataResponse2(parsedData.id, {
|
|
1794
|
+
success: false,
|
|
1795
|
+
error: `Internal error: ${errorMessage}`
|
|
1796
|
+
}, sendMessage, parsedData.from?.id);
|
|
1797
|
+
}
|
|
1798
|
+
} catch (sendError) {
|
|
1799
|
+
logger.error("[AUTH_LOGIN_REQ] Failed to send error response:", sendError);
|
|
1800
|
+
}
|
|
1639
1801
|
}
|
|
1640
1802
|
}
|
|
1641
1803
|
function sendDataResponse2(id, res, sendMessage, clientId) {
|
|
@@ -1651,17 +1813,27 @@ function sendDataResponse2(id, res, sendMessage, clientId) {
|
|
|
1651
1813
|
...res
|
|
1652
1814
|
}
|
|
1653
1815
|
};
|
|
1816
|
+
logger.debug(`[AUTH_LOGIN_RES ${id}] Sending ${res.success ? "successful" : "failed"} auth response to client: ${clientId}`);
|
|
1817
|
+
logger.debug(`[AUTH_LOGIN_RES ${id}] Response payload size: ${JSON.stringify(response).length} bytes`);
|
|
1818
|
+
if (res.error) {
|
|
1819
|
+
logger.debug(`[AUTH_LOGIN_RES ${id}] Error message: ${res.error}`);
|
|
1820
|
+
}
|
|
1654
1821
|
sendMessage(response);
|
|
1655
1822
|
}
|
|
1656
1823
|
|
|
1657
1824
|
// src/handlers/auth-verify-request.ts
|
|
1658
1825
|
async function handleAuthVerifyRequest(data, sendMessage) {
|
|
1659
1826
|
try {
|
|
1827
|
+
logger.debug("[AUTH_VERIFY_REQ] Parsing incoming auth verify request");
|
|
1660
1828
|
const authRequest = AuthVerifyRequestMessageSchema.parse(data);
|
|
1661
1829
|
const { id, payload } = authRequest;
|
|
1662
1830
|
const token = payload.token;
|
|
1663
1831
|
const wsId = authRequest.from.id;
|
|
1832
|
+
logger.info(`[AUTH_VERIFY_REQ ${id}] Processing auth verify request from client: ${wsId}`);
|
|
1833
|
+
logger.debug(`[AUTH_VERIFY_REQ ${id}] Token present: ${!!token}`);
|
|
1834
|
+
logger.debug(`[AUTH_VERIFY_REQ ${id}] Token length: ${token ? token.length : 0} characters`);
|
|
1664
1835
|
if (!token) {
|
|
1836
|
+
logger.error(`[AUTH_VERIFY_REQ ${id}] Token not found in request`);
|
|
1665
1837
|
sendDataResponse3(id, {
|
|
1666
1838
|
success: false,
|
|
1667
1839
|
error: "Token not found"
|
|
@@ -1669,17 +1841,45 @@ async function handleAuthVerifyRequest(data, sendMessage) {
|
|
|
1669
1841
|
return;
|
|
1670
1842
|
}
|
|
1671
1843
|
if (!wsId) {
|
|
1844
|
+
logger.error(`[AUTH_VERIFY_REQ ${id}] WebSocket ID not found in request`);
|
|
1672
1845
|
sendDataResponse3(id, {
|
|
1673
1846
|
success: false,
|
|
1674
1847
|
error: "WebSocket ID not found"
|
|
1675
1848
|
}, sendMessage, wsId);
|
|
1676
1849
|
return;
|
|
1677
1850
|
}
|
|
1851
|
+
logger.info(`[AUTH_VERIFY_REQ ${id}] Token validation starting`);
|
|
1852
|
+
logger.debug(`[AUTH_VERIFY_REQ ${id}] WebSocket ID: ${wsId}`);
|
|
1853
|
+
logger.debug(`[AUTH_VERIFY_REQ ${id}] Calling verifyAuthToken`);
|
|
1854
|
+
const startTime = Date.now();
|
|
1678
1855
|
const authResult = verifyAuthToken(token);
|
|
1856
|
+
const verificationTime = Date.now() - startTime;
|
|
1857
|
+
logger.info(`[AUTH_VERIFY_REQ ${id}] Token verification completed in ${verificationTime}ms - ${authResult.success ? "valid" : "invalid"}`);
|
|
1858
|
+
if (!authResult.success) {
|
|
1859
|
+
logger.warn(`[AUTH_VERIFY_REQ ${id}] Token verification failed: ${authResult.error}`);
|
|
1860
|
+
} else {
|
|
1861
|
+
logger.info(`[AUTH_VERIFY_REQ ${id}] Token verified successfully for user: ${authResult.data || "unknown"}`);
|
|
1862
|
+
}
|
|
1863
|
+
logger.debug(`[AUTH_VERIFY_REQ ${id}] Sending verification response to client`);
|
|
1679
1864
|
sendDataResponse3(id, authResult, sendMessage, wsId);
|
|
1865
|
+
logger.info(`[AUTH_VERIFY_REQ ${id}] ${authResult.success ? "\u2713" : "\u2717"} Auth verify request completed`);
|
|
1680
1866
|
return;
|
|
1681
1867
|
} catch (error) {
|
|
1682
|
-
|
|
1868
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1869
|
+
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
1870
|
+
logger.error(`[AUTH_VERIFY_REQ] Failed to handle auth verify request: ${errorMessage}`);
|
|
1871
|
+
logger.debug(`[AUTH_VERIFY_REQ] Error stack trace:`, errorStack);
|
|
1872
|
+
try {
|
|
1873
|
+
const parsedData = data;
|
|
1874
|
+
if (parsedData?.id) {
|
|
1875
|
+
sendDataResponse3(parsedData.id, {
|
|
1876
|
+
success: false,
|
|
1877
|
+
error: `Internal error: ${errorMessage}`
|
|
1878
|
+
}, sendMessage, parsedData.from?.id);
|
|
1879
|
+
}
|
|
1880
|
+
} catch (sendError) {
|
|
1881
|
+
logger.error("[AUTH_VERIFY_REQ] Failed to send error response:", sendError);
|
|
1882
|
+
}
|
|
1683
1883
|
}
|
|
1684
1884
|
}
|
|
1685
1885
|
function sendDataResponse3(id, res, sendMessage, clientId) {
|
|
@@ -1695,6 +1895,14 @@ function sendDataResponse3(id, res, sendMessage, clientId) {
|
|
|
1695
1895
|
...res
|
|
1696
1896
|
}
|
|
1697
1897
|
};
|
|
1898
|
+
logger.debug(`[AUTH_VERIFY_RES ${id}] Sending ${res.success ? "successful" : "failed"} verification response to client: ${clientId}`);
|
|
1899
|
+
logger.debug(`[AUTH_VERIFY_RES ${id}] Response payload size: ${JSON.stringify(response).length} bytes`);
|
|
1900
|
+
if (res.error) {
|
|
1901
|
+
logger.debug(`[AUTH_VERIFY_RES ${id}] Error message: ${res.error}`);
|
|
1902
|
+
}
|
|
1903
|
+
if (res.data) {
|
|
1904
|
+
logger.debug(`[AUTH_VERIFY_RES ${id}] User verified: ${res.data}`);
|
|
1905
|
+
}
|
|
1698
1906
|
sendMessage(response);
|
|
1699
1907
|
}
|
|
1700
1908
|
|
|
@@ -1744,6 +1952,47 @@ function ensureQueryLimit(query, defaultLimit = 50) {
|
|
|
1744
1952
|
}
|
|
1745
1953
|
return trimmedQuery;
|
|
1746
1954
|
}
|
|
1955
|
+
function fixScalarSubqueries(query) {
|
|
1956
|
+
if (!query || query.trim().length === 0) {
|
|
1957
|
+
return query;
|
|
1958
|
+
}
|
|
1959
|
+
let modifiedQuery = query;
|
|
1960
|
+
let hasChanges = false;
|
|
1961
|
+
const scalarOperatorPattern = /([=<>!]=?|<>)\s*\(\s*SELECT\s/gi;
|
|
1962
|
+
const matches = [...modifiedQuery.matchAll(scalarOperatorPattern)];
|
|
1963
|
+
for (let i = matches.length - 1; i >= 0; i--) {
|
|
1964
|
+
const match = matches[i];
|
|
1965
|
+
const startPos = match.index + match[0].length - "SELECT ".length;
|
|
1966
|
+
let parenDepth = 1;
|
|
1967
|
+
let endPos = startPos;
|
|
1968
|
+
let foundEnd = false;
|
|
1969
|
+
for (let j = startPos; j < modifiedQuery.length; j++) {
|
|
1970
|
+
const char = modifiedQuery[j];
|
|
1971
|
+
if (char === "(") parenDepth++;
|
|
1972
|
+
if (char === ")") {
|
|
1973
|
+
parenDepth--;
|
|
1974
|
+
if (parenDepth === 0) {
|
|
1975
|
+
endPos = j;
|
|
1976
|
+
foundEnd = true;
|
|
1977
|
+
break;
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
if (!foundEnd) continue;
|
|
1982
|
+
const subquery = modifiedQuery.substring(startPos, endPos);
|
|
1983
|
+
if (/\bLIMIT\s+\d+/i.test(subquery)) {
|
|
1984
|
+
continue;
|
|
1985
|
+
}
|
|
1986
|
+
const fixedSubquery = subquery.trim() + " LIMIT 1";
|
|
1987
|
+
modifiedQuery = modifiedQuery.substring(0, startPos) + fixedSubquery + modifiedQuery.substring(endPos);
|
|
1988
|
+
hasChanges = true;
|
|
1989
|
+
console.warn(`\u26A0\uFE0F Fixed scalar subquery: added LIMIT 1 to prevent multiple row error`);
|
|
1990
|
+
}
|
|
1991
|
+
if (hasChanges) {
|
|
1992
|
+
console.log("\u2713 Query validated and fixed for PostgreSQL scalar subquery compatibility");
|
|
1993
|
+
}
|
|
1994
|
+
return modifiedQuery;
|
|
1995
|
+
}
|
|
1747
1996
|
|
|
1748
1997
|
// src/userResponse/schema.ts
|
|
1749
1998
|
var import_path = __toESM(require("path"));
|
|
@@ -1906,7 +2155,8 @@ var PromptLoader = class {
|
|
|
1906
2155
|
"single-component",
|
|
1907
2156
|
"mutli-component",
|
|
1908
2157
|
"actions",
|
|
1909
|
-
"container-metadata"
|
|
2158
|
+
"container-metadata",
|
|
2159
|
+
"text-response"
|
|
1910
2160
|
];
|
|
1911
2161
|
for (const promptType of promptTypes) {
|
|
1912
2162
|
try {
|
|
@@ -2258,7 +2508,9 @@ var BaseLLM = class {
|
|
|
2258
2508
|
needsMultipleComponents: result.needsMultipleComponents || false
|
|
2259
2509
|
};
|
|
2260
2510
|
} catch (error) {
|
|
2261
|
-
|
|
2511
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2512
|
+
logger.error(`[${this.getProviderName()}] Error classifying user question: ${errorMsg}`);
|
|
2513
|
+
logger.debug(`[${this.getProviderName()}] Classification error details:`, error);
|
|
2262
2514
|
throw error;
|
|
2263
2515
|
}
|
|
2264
2516
|
}
|
|
@@ -2296,6 +2548,7 @@ var BaseLLM = class {
|
|
|
2296
2548
|
);
|
|
2297
2549
|
const props = result.props || originalProps;
|
|
2298
2550
|
if (props && props.query) {
|
|
2551
|
+
props.query = fixScalarSubqueries(props.query);
|
|
2299
2552
|
props.query = ensureQueryLimit(props.query, this.defaultLimit);
|
|
2300
2553
|
}
|
|
2301
2554
|
if (props && props.query) {
|
|
@@ -2322,7 +2575,9 @@ var BaseLLM = class {
|
|
|
2322
2575
|
modifications: result.modifications || []
|
|
2323
2576
|
};
|
|
2324
2577
|
} catch (error) {
|
|
2325
|
-
|
|
2578
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2579
|
+
logger.error(`[${this.getProviderName()}] Error validating/modifying props: ${errorMsg}`);
|
|
2580
|
+
logger.debug(`[${this.getProviderName()}] Props validation error details:`, error);
|
|
2326
2581
|
throw error;
|
|
2327
2582
|
}
|
|
2328
2583
|
}
|
|
@@ -2442,7 +2697,9 @@ var BaseLLM = class {
|
|
|
2442
2697
|
isGenerated: true
|
|
2443
2698
|
};
|
|
2444
2699
|
} catch (error) {
|
|
2445
|
-
|
|
2700
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2701
|
+
logger.error(`[${this.getProviderName()}] Error generating analytical component: ${errorMsg}`);
|
|
2702
|
+
logger.debug(`[${this.getProviderName()}] Analytical component generation error details:`, error);
|
|
2446
2703
|
throw error;
|
|
2447
2704
|
}
|
|
2448
2705
|
}
|
|
@@ -2484,7 +2741,9 @@ var BaseLLM = class {
|
|
|
2484
2741
|
description: result.description || `Multi-component dashboard showing ${visualizationTypes.join(", ")}`
|
|
2485
2742
|
};
|
|
2486
2743
|
} catch (error) {
|
|
2487
|
-
|
|
2744
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2745
|
+
logger.error(`[${this.getProviderName()}] Error generating container metadata: ${errorMsg}`);
|
|
2746
|
+
logger.debug(`[${this.getProviderName()}] Container metadata error details:`, error);
|
|
2488
2747
|
return {
|
|
2489
2748
|
title: `${userPrompt} - Dashboard`,
|
|
2490
2749
|
description: `Multi-component dashboard showing ${visualizationTypes.join(", ")}`
|
|
@@ -2536,24 +2795,24 @@ var BaseLLM = class {
|
|
|
2536
2795
|
component = components[componentIndex - 1];
|
|
2537
2796
|
}
|
|
2538
2797
|
const matchedMsg = `${this.getProviderName()} matched component: ${component?.name || "None"}`;
|
|
2539
|
-
|
|
2798
|
+
logger.info(`[${this.getProviderName()}] \u2713 ${matchedMsg}`);
|
|
2540
2799
|
logCollector?.info(matchedMsg);
|
|
2541
2800
|
if (result.alternativeMatches && result.alternativeMatches.length > 0) {
|
|
2542
|
-
|
|
2801
|
+
logger.debug(`[${this.getProviderName()}] Alternative matches found: ${result.alternativeMatches.length}`);
|
|
2543
2802
|
const altMatches = result.alternativeMatches.map(
|
|
2544
2803
|
(alt) => `${components[alt.index - 1]?.name} (${alt.score}%): ${alt.reason}`
|
|
2545
2804
|
).join(" | ");
|
|
2546
2805
|
logCollector?.info(`Alternative matches: ${altMatches}`);
|
|
2547
2806
|
result.alternativeMatches.forEach((alt) => {
|
|
2548
|
-
|
|
2807
|
+
logger.debug(`[${this.getProviderName()}] - ${components[alt.index - 1]?.name} (${alt.score}%): ${alt.reason}`);
|
|
2549
2808
|
});
|
|
2550
2809
|
}
|
|
2551
2810
|
if (!component) {
|
|
2552
2811
|
const noMatchMsg = `No matching component found (confidence: ${confidence}%)`;
|
|
2553
|
-
|
|
2812
|
+
logger.warn(`[${this.getProviderName()}] \u2717 ${noMatchMsg}`);
|
|
2554
2813
|
logCollector?.warn(noMatchMsg);
|
|
2555
2814
|
const genMsg = "Attempting to match component from analytical question...";
|
|
2556
|
-
|
|
2815
|
+
logger.info(`[${this.getProviderName()}] \u2713 ${genMsg}`);
|
|
2557
2816
|
logCollector?.info(genMsg);
|
|
2558
2817
|
const generatedResult = await this.generateAnalyticalComponent(userPrompt, components, void 0, apiKey, logCollector, conversationHistory);
|
|
2559
2818
|
if (generatedResult.component) {
|
|
@@ -2614,8 +2873,10 @@ var BaseLLM = class {
|
|
|
2614
2873
|
confidence
|
|
2615
2874
|
};
|
|
2616
2875
|
} catch (error) {
|
|
2617
|
-
|
|
2618
|
-
|
|
2876
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2877
|
+
logger.error(`[${this.getProviderName()}] Error matching component: ${errorMsg}`);
|
|
2878
|
+
logger.debug(`[${this.getProviderName()}] Component matching error details:`, error);
|
|
2879
|
+
logCollector?.error(`Error matching component: ${errorMsg}`);
|
|
2619
2880
|
throw error;
|
|
2620
2881
|
}
|
|
2621
2882
|
}
|
|
@@ -2646,7 +2907,9 @@ var BaseLLM = class {
|
|
|
2646
2907
|
isGenerated: true
|
|
2647
2908
|
};
|
|
2648
2909
|
} catch (error) {
|
|
2649
|
-
|
|
2910
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2911
|
+
logger.error(`[${this.getProviderName()}] Error matching multiple analytical components: ${errorMsg}`);
|
|
2912
|
+
logger.debug(`[${this.getProviderName()}] Multiple components matching error details:`, error);
|
|
2650
2913
|
return {
|
|
2651
2914
|
components: [],
|
|
2652
2915
|
reasoning: "Error occurred while matching components",
|
|
@@ -2725,17 +2988,91 @@ var BaseLLM = class {
|
|
|
2725
2988
|
isGenerated: true
|
|
2726
2989
|
};
|
|
2727
2990
|
} catch (error) {
|
|
2728
|
-
|
|
2991
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2992
|
+
logger.error(`[${this.getProviderName()}] Error generating multi-component response: ${errorMsg}`);
|
|
2993
|
+
logger.debug(`[${this.getProviderName()}] Multi-component response error details:`, error);
|
|
2729
2994
|
throw error;
|
|
2730
2995
|
}
|
|
2731
2996
|
}
|
|
2732
2997
|
/**
|
|
2733
|
-
*
|
|
2734
|
-
* This
|
|
2735
|
-
|
|
2998
|
+
* Generate text-based response for user question
|
|
2999
|
+
* This provides conversational text responses instead of component generation
|
|
3000
|
+
*/
|
|
3001
|
+
async generateTextResponse(userPrompt, apiKey, logCollector, conversationHistory) {
|
|
3002
|
+
const errors = [];
|
|
3003
|
+
logger.debug(`[${this.getProviderName()}] Starting text response generation`);
|
|
3004
|
+
logger.debug(`[${this.getProviderName()}] User prompt: "${userPrompt.substring(0, 50)}..."`);
|
|
3005
|
+
try {
|
|
3006
|
+
const prompts = await promptLoader.loadPrompts("text-response", {
|
|
3007
|
+
USER_PROMPT: userPrompt,
|
|
3008
|
+
CONVERSATION_HISTORY: conversationHistory || "No previous conversation"
|
|
3009
|
+
});
|
|
3010
|
+
logger.debug(`[${this.getProviderName()}] Loaded text-response prompts`);
|
|
3011
|
+
logger.debug(`[${this.getProviderName()}] System prompt length: ${prompts.system.length}, User prompt length: ${prompts.user.length}`);
|
|
3012
|
+
logCollector?.info("Generating text response...");
|
|
3013
|
+
const result = await LLM.stream(
|
|
3014
|
+
{
|
|
3015
|
+
sys: prompts.system,
|
|
3016
|
+
user: prompts.user
|
|
3017
|
+
},
|
|
3018
|
+
{
|
|
3019
|
+
model: this.model,
|
|
3020
|
+
maxTokens: 1e3,
|
|
3021
|
+
temperature: 0.7,
|
|
3022
|
+
apiKey: this.getApiKey(apiKey)
|
|
3023
|
+
},
|
|
3024
|
+
true
|
|
3025
|
+
// Parse as JSON
|
|
3026
|
+
);
|
|
3027
|
+
logger.info(`[${this.getProviderName()}] Text response generated successfully`);
|
|
3028
|
+
logger.debug(`[${this.getProviderName()}] Response type: ${result.responseType}, Confidence: ${result.confidence}`);
|
|
3029
|
+
logCollector?.info(`Text response: ${result.text?.substring(0, 100)}${result.text?.length > 100 ? "..." : ""}`);
|
|
3030
|
+
logCollector?.logExplanation(
|
|
3031
|
+
"Text response generated",
|
|
3032
|
+
result.reasoning || "Generated text response for user question",
|
|
3033
|
+
{
|
|
3034
|
+
responseType: result.responseType,
|
|
3035
|
+
confidence: result.confidence,
|
|
3036
|
+
textLength: result.text?.length || 0
|
|
3037
|
+
}
|
|
3038
|
+
);
|
|
3039
|
+
return {
|
|
3040
|
+
success: true,
|
|
3041
|
+
data: {
|
|
3042
|
+
text: result.text || "I apologize, but I was unable to generate a response.",
|
|
3043
|
+
responseType: result.responseType || "answer",
|
|
3044
|
+
confidence: result.confidence || 0.5,
|
|
3045
|
+
reasoning: result.reasoning || "No reasoning provided"
|
|
3046
|
+
},
|
|
3047
|
+
errors: []
|
|
3048
|
+
};
|
|
3049
|
+
} catch (error) {
|
|
3050
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3051
|
+
logger.error(`[${this.getProviderName()}] Error generating text response: ${errorMsg}`);
|
|
3052
|
+
logger.debug(`[${this.getProviderName()}] Text response generation error details:`, error);
|
|
3053
|
+
logCollector?.error(`Error generating text response: ${errorMsg}`);
|
|
3054
|
+
errors.push(errorMsg);
|
|
3055
|
+
return {
|
|
3056
|
+
success: false,
|
|
3057
|
+
errors,
|
|
3058
|
+
data: {
|
|
3059
|
+
text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
|
|
3060
|
+
responseType: "error",
|
|
3061
|
+
confidence: 0,
|
|
3062
|
+
reasoning: `Error: ${errorMsg}`
|
|
3063
|
+
}
|
|
3064
|
+
};
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
/**
|
|
3068
|
+
* Generate component response for user question
|
|
3069
|
+
* This provides conversational component suggestions based on user question
|
|
3070
|
+
* Supports component generation and matching
|
|
2736
3071
|
*/
|
|
2737
|
-
async
|
|
3072
|
+
async generateComponentResponse(userPrompt, components, apiKey, logCollector, conversationHistory) {
|
|
3073
|
+
const errors = [];
|
|
2738
3074
|
try {
|
|
3075
|
+
logger.info(`[${this.getProviderName()}] Using component response mode`);
|
|
2739
3076
|
const classifyMsg = "Classifying user question...";
|
|
2740
3077
|
logCollector?.info(classifyMsg);
|
|
2741
3078
|
const classification = await this.classifyUserQuestion(userPrompt, apiKey, logCollector, conversationHistory);
|
|
@@ -2745,33 +3082,47 @@ var BaseLLM = class {
|
|
|
2745
3082
|
if (classification.visualizations.length > 1) {
|
|
2746
3083
|
const multiMsg = `Matching ${classification.visualizations.length} components for types: ${classification.visualizations.join(", ")}`;
|
|
2747
3084
|
logCollector?.info(multiMsg);
|
|
2748
|
-
const
|
|
2749
|
-
for (const vizType of classification.visualizations) {
|
|
3085
|
+
const componentPromises = classification.visualizations.map((vizType) => {
|
|
2750
3086
|
logCollector?.info(`Matching component for type: ${vizType}`);
|
|
2751
|
-
|
|
3087
|
+
return this.generateAnalyticalComponent(
|
|
2752
3088
|
userPrompt,
|
|
2753
3089
|
components,
|
|
2754
3090
|
vizType,
|
|
2755
3091
|
apiKey,
|
|
2756
3092
|
logCollector,
|
|
2757
3093
|
conversationHistory
|
|
2758
|
-
);
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
3094
|
+
).then((result) => ({ vizType, result }));
|
|
3095
|
+
});
|
|
3096
|
+
const settledResults = await Promise.allSettled(componentPromises);
|
|
3097
|
+
const matchedComponents = [];
|
|
3098
|
+
for (const settledResult of settledResults) {
|
|
3099
|
+
if (settledResult.status === "fulfilled") {
|
|
3100
|
+
const { vizType, result } = settledResult.value;
|
|
3101
|
+
if (result.component) {
|
|
3102
|
+
matchedComponents.push(result.component);
|
|
3103
|
+
logCollector?.info(`Matched: ${result.component.name}`);
|
|
3104
|
+
logger.info("Component : ", result.component.name, " props: ", result.component.props);
|
|
3105
|
+
} else {
|
|
3106
|
+
logCollector?.warn(`Failed to match component for type: ${vizType}`);
|
|
3107
|
+
}
|
|
2762
3108
|
} else {
|
|
2763
|
-
logCollector?.warn(`
|
|
3109
|
+
logCollector?.warn(`Error matching component: ${settledResult.reason?.message || "Unknown error"}`);
|
|
2764
3110
|
}
|
|
2765
3111
|
}
|
|
3112
|
+
logger.debug(`[${this.getProviderName()}] Matched ${matchedComponents.length} components for multi-component container`);
|
|
2766
3113
|
if (matchedComponents.length === 0) {
|
|
2767
3114
|
return {
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
3115
|
+
success: true,
|
|
3116
|
+
data: {
|
|
3117
|
+
component: null,
|
|
3118
|
+
reasoning: "Failed to match any components for the requested visualization types",
|
|
3119
|
+
method: "classification-multi-failed",
|
|
3120
|
+
questionType: classification.questionType,
|
|
3121
|
+
needsMultipleComponents: true,
|
|
3122
|
+
propsModified: false,
|
|
3123
|
+
queryModified: false
|
|
3124
|
+
},
|
|
3125
|
+
errors: []
|
|
2775
3126
|
};
|
|
2776
3127
|
}
|
|
2777
3128
|
logCollector?.info("Generating container metadata...");
|
|
@@ -2801,38 +3152,50 @@ var BaseLLM = class {
|
|
|
2801
3152
|
};
|
|
2802
3153
|
logCollector?.info(`Created multi-component container with ${matchedComponents.length} components: "${containerMetadata.title}"`);
|
|
2803
3154
|
return {
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
3155
|
+
success: true,
|
|
3156
|
+
data: {
|
|
3157
|
+
component: containerComponent,
|
|
3158
|
+
reasoning: `Matched ${matchedComponents.length} components for visualization types: ${classification.visualizations.join(", ")}`,
|
|
3159
|
+
method: "classification-multi-generated",
|
|
3160
|
+
questionType: classification.questionType,
|
|
3161
|
+
needsMultipleComponents: true,
|
|
3162
|
+
propsModified: false,
|
|
3163
|
+
queryModified: false
|
|
3164
|
+
},
|
|
3165
|
+
errors: []
|
|
2811
3166
|
};
|
|
2812
3167
|
} else if (classification.visualizations.length === 1) {
|
|
2813
3168
|
const vizType = classification.visualizations[0];
|
|
2814
3169
|
logCollector?.info(`Matching single component for type: ${vizType}`);
|
|
2815
3170
|
const result = await this.generateAnalyticalComponent(userPrompt, components, vizType, apiKey, logCollector, conversationHistory);
|
|
2816
3171
|
return {
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
3172
|
+
success: true,
|
|
3173
|
+
data: {
|
|
3174
|
+
component: result.component,
|
|
3175
|
+
reasoning: result.reasoning,
|
|
3176
|
+
method: "classification-generated",
|
|
3177
|
+
questionType: classification.questionType,
|
|
3178
|
+
needsMultipleComponents: false,
|
|
3179
|
+
propsModified: false,
|
|
3180
|
+
queryModified: false
|
|
3181
|
+
},
|
|
3182
|
+
errors: []
|
|
2824
3183
|
};
|
|
2825
3184
|
} else {
|
|
2826
3185
|
logCollector?.info("No specific visualization type - matching from all components");
|
|
2827
3186
|
const result = await this.generateAnalyticalComponent(userPrompt, components, void 0, apiKey, logCollector, conversationHistory);
|
|
2828
3187
|
return {
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
3188
|
+
success: true,
|
|
3189
|
+
data: {
|
|
3190
|
+
component: result.component,
|
|
3191
|
+
reasoning: result.reasoning,
|
|
3192
|
+
method: "classification-generated-auto",
|
|
3193
|
+
questionType: classification.questionType,
|
|
3194
|
+
needsMultipleComponents: false,
|
|
3195
|
+
propsModified: false,
|
|
3196
|
+
queryModified: false
|
|
3197
|
+
},
|
|
3198
|
+
errors: []
|
|
2836
3199
|
};
|
|
2837
3200
|
}
|
|
2838
3201
|
} else if (classification.questionType === "data_modification" || classification.questionType === "general") {
|
|
@@ -2840,28 +3203,109 @@ var BaseLLM = class {
|
|
|
2840
3203
|
logCollector?.info(matchMsg);
|
|
2841
3204
|
const matchResult = await this.matchComponent(userPrompt, components, apiKey, logCollector, conversationHistory);
|
|
2842
3205
|
return {
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
3206
|
+
success: true,
|
|
3207
|
+
data: {
|
|
3208
|
+
component: matchResult.component,
|
|
3209
|
+
reasoning: matchResult.reasoning,
|
|
3210
|
+
method: "classification-matched",
|
|
3211
|
+
questionType: classification.questionType,
|
|
3212
|
+
needsMultipleComponents: false,
|
|
3213
|
+
propsModified: matchResult.propsModified,
|
|
3214
|
+
queryModified: matchResult.queryModified
|
|
3215
|
+
},
|
|
3216
|
+
errors: []
|
|
2850
3217
|
};
|
|
2851
3218
|
} else {
|
|
2852
3219
|
logCollector?.info("General question - no component needed");
|
|
2853
3220
|
return {
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
3221
|
+
success: true,
|
|
3222
|
+
data: {
|
|
3223
|
+
component: null,
|
|
3224
|
+
reasoning: "General question - no component needed",
|
|
3225
|
+
method: "classification-general",
|
|
3226
|
+
questionType: classification.questionType,
|
|
3227
|
+
needsMultipleComponents: false,
|
|
3228
|
+
propsModified: false,
|
|
3229
|
+
queryModified: false
|
|
3230
|
+
},
|
|
3231
|
+
errors: []
|
|
2859
3232
|
};
|
|
2860
3233
|
}
|
|
2861
3234
|
} catch (error) {
|
|
2862
|
-
|
|
2863
|
-
|
|
3235
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3236
|
+
logger.error(`[${this.getProviderName()}] Error generating component response: ${errorMsg}`);
|
|
3237
|
+
logger.debug(`[${this.getProviderName()}] Component response generation error details:`, error);
|
|
3238
|
+
logCollector?.error(`Error generating component response: ${errorMsg}`);
|
|
3239
|
+
errors.push(errorMsg);
|
|
3240
|
+
return {
|
|
3241
|
+
success: false,
|
|
3242
|
+
errors,
|
|
3243
|
+
data: void 0
|
|
3244
|
+
};
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
/**
|
|
3248
|
+
* Main orchestration function that classifies question and routes to appropriate handler
|
|
3249
|
+
* This is the NEW recommended entry point for handling user requests
|
|
3250
|
+
* Supports both component generation and text response modes
|
|
3251
|
+
*
|
|
3252
|
+
* @param responseMode - 'component' for component generation (default), 'text' for text responses
|
|
3253
|
+
*/
|
|
3254
|
+
async handleUserRequest(userPrompt, components, apiKey, logCollector, conversationHistory, responseMode = "component") {
|
|
3255
|
+
logger.info(`[${this.getProviderName()}] handleUserRequest called with responseMode: ${responseMode}`);
|
|
3256
|
+
if (responseMode === "text") {
|
|
3257
|
+
logger.info(`[${this.getProviderName()}] Using text response mode`);
|
|
3258
|
+
logCollector?.info("Generating text response...");
|
|
3259
|
+
const textResponse = await this.generateTextResponse(
|
|
3260
|
+
userPrompt,
|
|
3261
|
+
apiKey,
|
|
3262
|
+
logCollector,
|
|
3263
|
+
conversationHistory
|
|
3264
|
+
);
|
|
3265
|
+
if (!textResponse.success) {
|
|
3266
|
+
logger.error(`[${this.getProviderName()}] Text response generation failed`);
|
|
3267
|
+
return textResponse;
|
|
3268
|
+
}
|
|
3269
|
+
logger.info(`[${this.getProviderName()}] Text response generated successfully`);
|
|
3270
|
+
return {
|
|
3271
|
+
success: true,
|
|
3272
|
+
data: {
|
|
3273
|
+
textResponse: textResponse.data.text,
|
|
3274
|
+
text: textResponse.data.text,
|
|
3275
|
+
responseType: textResponse.data.responseType,
|
|
3276
|
+
confidence: textResponse.data.confidence,
|
|
3277
|
+
reasoning: textResponse.data.reasoning,
|
|
3278
|
+
method: `${this.getProviderName()}-text-response`
|
|
3279
|
+
},
|
|
3280
|
+
errors: []
|
|
3281
|
+
};
|
|
2864
3282
|
}
|
|
3283
|
+
const componentResponse = await this.generateComponentResponse(
|
|
3284
|
+
userPrompt,
|
|
3285
|
+
components,
|
|
3286
|
+
apiKey,
|
|
3287
|
+
logCollector,
|
|
3288
|
+
conversationHistory
|
|
3289
|
+
);
|
|
3290
|
+
if (!componentResponse.success) {
|
|
3291
|
+
logger.error(`[${this.getProviderName()}] Component response generation failed`);
|
|
3292
|
+
return componentResponse;
|
|
3293
|
+
}
|
|
3294
|
+
logger.info(`[${this.getProviderName()}] Component response generated successfully`);
|
|
3295
|
+
return {
|
|
3296
|
+
success: true,
|
|
3297
|
+
data: {
|
|
3298
|
+
component: componentResponse.data.component,
|
|
3299
|
+
reasoning: componentResponse.data.reasoning,
|
|
3300
|
+
method: componentResponse.data.method,
|
|
3301
|
+
// Preserve the original method name
|
|
3302
|
+
questionType: componentResponse.data.questionType,
|
|
3303
|
+
needsMultipleComponents: componentResponse.data.needsMultipleComponents,
|
|
3304
|
+
propsModified: componentResponse.data.propsModified,
|
|
3305
|
+
queryModified: componentResponse.data.queryModified
|
|
3306
|
+
},
|
|
3307
|
+
errors: []
|
|
3308
|
+
};
|
|
2865
3309
|
}
|
|
2866
3310
|
/**
|
|
2867
3311
|
* Generate next questions that the user might ask based on the original prompt and generated component
|
|
@@ -2907,8 +3351,10 @@ var BaseLLM = class {
|
|
|
2907
3351
|
);
|
|
2908
3352
|
return nextQuestions;
|
|
2909
3353
|
} catch (error) {
|
|
2910
|
-
|
|
2911
|
-
|
|
3354
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3355
|
+
logger.error(`[${this.getProviderName()}] Error generating next questions: ${errorMsg}`);
|
|
3356
|
+
logger.debug(`[${this.getProviderName()}] Next questions generation error details:`, error);
|
|
3357
|
+
logCollector?.error(`Error generating next questions: ${errorMsg}`);
|
|
2912
3358
|
return [];
|
|
2913
3359
|
}
|
|
2914
3360
|
}
|
|
@@ -2972,112 +3418,130 @@ function getLLMProviders() {
|
|
|
2972
3418
|
return DEFAULT_PROVIDERS;
|
|
2973
3419
|
}
|
|
2974
3420
|
}
|
|
2975
|
-
var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conversationHistory) => {
|
|
2976
|
-
|
|
2977
|
-
|
|
3421
|
+
var useAnthropicMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component") => {
|
|
3422
|
+
logger.debug("[useAnthropicMethod] Initializing Anthropic Claude matching method");
|
|
3423
|
+
logger.debug(`[useAnthropicMethod] Response mode: ${responseMode}`);
|
|
3424
|
+
const msg = `Using Anthropic Claude ${responseMode === "text" ? "text response" : "matching"} method...`;
|
|
2978
3425
|
logCollector?.info(msg);
|
|
2979
|
-
if (components.length === 0) {
|
|
3426
|
+
if (responseMode === "component" && components.length === 0) {
|
|
2980
3427
|
const emptyMsg = "Components not loaded in memory. Please ensure components are fetched first.";
|
|
3428
|
+
logger.error("[useAnthropicMethod] No components available");
|
|
2981
3429
|
logCollector?.error(emptyMsg);
|
|
2982
|
-
return { success: false,
|
|
2983
|
-
}
|
|
2984
|
-
try {
|
|
2985
|
-
const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory);
|
|
2986
|
-
return { success: true, data: matchResult };
|
|
2987
|
-
} catch (error) {
|
|
2988
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2989
|
-
logCollector?.error(`Anthropic method failed: ${errorMsg}`);
|
|
2990
|
-
throw error;
|
|
3430
|
+
return { success: false, errors: [emptyMsg] };
|
|
2991
3431
|
}
|
|
3432
|
+
logger.debug(`[useAnthropicMethod] Processing with ${components.length} components`);
|
|
3433
|
+
const matchResult = await anthropicLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode);
|
|
3434
|
+
logger.info(`[useAnthropicMethod] Successfully generated ${responseMode} using Anthropic`);
|
|
3435
|
+
return matchResult;
|
|
2992
3436
|
};
|
|
2993
|
-
var useGroqMethod = async (prompt, components, apiKey, logCollector, conversationHistory) => {
|
|
2994
|
-
|
|
2995
|
-
|
|
3437
|
+
var useGroqMethod = async (prompt, components, apiKey, logCollector, conversationHistory, responseMode = "component") => {
|
|
3438
|
+
logger.debug("[useGroqMethod] Initializing Groq LLM matching method");
|
|
3439
|
+
logger.debug(`[useGroqMethod] Response mode: ${responseMode}`);
|
|
3440
|
+
const msg = `Using Groq LLM ${responseMode === "text" ? "text response" : "matching"} method...`;
|
|
3441
|
+
logger.info(msg);
|
|
2996
3442
|
logCollector?.info(msg);
|
|
2997
|
-
if (components.length === 0) {
|
|
3443
|
+
if (responseMode === "component" && components.length === 0) {
|
|
2998
3444
|
const emptyMsg = "Components not loaded in memory. Please ensure components are fetched first.";
|
|
3445
|
+
logger.error("[useGroqMethod] No components available");
|
|
2999
3446
|
logCollector?.error(emptyMsg);
|
|
3000
|
-
return { success: false,
|
|
3001
|
-
}
|
|
3002
|
-
try {
|
|
3003
|
-
const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory);
|
|
3004
|
-
return { success: true, data: matchResult };
|
|
3005
|
-
} catch (error) {
|
|
3006
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3007
|
-
logCollector?.error(`Groq method failed: ${errorMsg}`);
|
|
3008
|
-
throw error;
|
|
3447
|
+
return { success: false, errors: [emptyMsg] };
|
|
3009
3448
|
}
|
|
3449
|
+
logger.debug(`[useGroqMethod] Processing with ${components.length} components`);
|
|
3450
|
+
const matchResult = await groqLLM.handleUserRequest(prompt, components, apiKey, logCollector, conversationHistory, responseMode);
|
|
3451
|
+
logger.info(`[useGroqMethod] Successfully generated ${responseMode} using Groq`);
|
|
3452
|
+
return matchResult;
|
|
3010
3453
|
};
|
|
3011
3454
|
var getUserResponseFromCache = async (prompt) => {
|
|
3012
3455
|
return false;
|
|
3013
3456
|
};
|
|
3014
3457
|
var get_user_response = async (prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory) => {
|
|
3458
|
+
const responseMode = "component";
|
|
3459
|
+
logger.debug(`[get_user_response] Starting user response generation for prompt: "${prompt.substring(0, 50)}..."`);
|
|
3460
|
+
logger.debug("[get_user_response] Checking cache for existing response");
|
|
3015
3461
|
const userResponse = await getUserResponseFromCache(prompt);
|
|
3016
3462
|
if (userResponse) {
|
|
3463
|
+
logger.info("[get_user_response] User response found in cache - returning cached result");
|
|
3017
3464
|
logCollector?.info("User response found in cache");
|
|
3018
3465
|
return {
|
|
3019
3466
|
success: true,
|
|
3020
|
-
data: userResponse
|
|
3467
|
+
data: userResponse,
|
|
3468
|
+
errors: []
|
|
3021
3469
|
};
|
|
3022
3470
|
}
|
|
3471
|
+
logger.debug("[get_user_response] No cached response found, proceeding with LLM providers");
|
|
3023
3472
|
const providers = llmProviders || getLLMProviders();
|
|
3024
3473
|
const errors = [];
|
|
3025
3474
|
const providerOrder = providers.join(", ");
|
|
3026
3475
|
logCollector?.info(`LLM Provider order: [${providerOrder}]`);
|
|
3027
3476
|
if (conversationHistory && conversationHistory.length > 0) {
|
|
3028
|
-
|
|
3477
|
+
const exchangeCount = conversationHistory.split("\n").filter((l) => l.startsWith("Q")).length;
|
|
3478
|
+
logger.debug(`[get_user_response] Using conversation history with ${exchangeCount} previous exchanges`);
|
|
3479
|
+
logCollector?.info(`Using conversation history with ${exchangeCount} previous exchanges`);
|
|
3480
|
+
} else {
|
|
3481
|
+
logger.debug("[get_user_response] No conversation history available");
|
|
3029
3482
|
}
|
|
3030
3483
|
for (let i = 0; i < providers.length; i++) {
|
|
3031
3484
|
const provider = providers[i];
|
|
3032
3485
|
const isLastProvider = i === providers.length - 1;
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
}
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
const errorMsg = `Provider ${provider} failed: ${errorMessage}`;
|
|
3057
|
-
logCollector?.error(errorMsg);
|
|
3486
|
+
const attemptMsg = `Attempting provider: ${provider} (${i + 1}/${providers.length})`;
|
|
3487
|
+
logCollector?.info(attemptMsg);
|
|
3488
|
+
let result;
|
|
3489
|
+
if (provider === "anthropic") {
|
|
3490
|
+
result = await useAnthropicMethod(prompt, components, anthropicApiKey, logCollector, conversationHistory, responseMode);
|
|
3491
|
+
} else if (provider === "groq") {
|
|
3492
|
+
result = await useGroqMethod(prompt, components, groqApiKey, logCollector, conversationHistory, responseMode);
|
|
3493
|
+
} else {
|
|
3494
|
+
logger.warn(`[get_user_response] Unknown provider: ${provider} - skipping`);
|
|
3495
|
+
errors.push(`Unknown provider: ${provider}`);
|
|
3496
|
+
continue;
|
|
3497
|
+
}
|
|
3498
|
+
if (result.success) {
|
|
3499
|
+
const successMsg = `Success with provider: ${provider} result: ${JSON.stringify(result)}`;
|
|
3500
|
+
logger.info(`${successMsg}`);
|
|
3501
|
+
logCollector?.info(successMsg);
|
|
3502
|
+
return result;
|
|
3503
|
+
} else {
|
|
3504
|
+
const providerErrors = result.errors.map((err) => `${provider}: ${err}`);
|
|
3505
|
+
errors.push(...providerErrors);
|
|
3506
|
+
const warnMsg = `Provider ${provider} returned unsuccessful result: ${result.errors.join(", ")}`;
|
|
3507
|
+
logger.warn(`[get_user_response] ${warnMsg}`);
|
|
3508
|
+
logCollector?.warn(warnMsg);
|
|
3058
3509
|
if (!isLastProvider) {
|
|
3059
3510
|
const fallbackMsg = "Falling back to next provider...";
|
|
3511
|
+
logger.info(`[get_user_response] ${fallbackMsg}`);
|
|
3060
3512
|
logCollector?.info(fallbackMsg);
|
|
3061
|
-
continue;
|
|
3062
3513
|
}
|
|
3063
3514
|
}
|
|
3064
3515
|
}
|
|
3065
|
-
const
|
|
3066
|
-
|
|
3067
|
-
logCollector?.error(failureMsg);
|
|
3516
|
+
const failureMsg = `All LLM providers failed`;
|
|
3517
|
+
logger.error(`[get_user_response] ${failureMsg}. Errors: ${errors.join("; ")}`);
|
|
3518
|
+
logCollector?.error(`${failureMsg}. Errors: ${errors.join("; ")}`);
|
|
3068
3519
|
return {
|
|
3069
3520
|
success: false,
|
|
3070
|
-
|
|
3521
|
+
errors
|
|
3071
3522
|
};
|
|
3072
3523
|
};
|
|
3073
3524
|
|
|
3074
3525
|
// src/utils/log-collector.ts
|
|
3526
|
+
var LOG_LEVEL_PRIORITY2 = {
|
|
3527
|
+
errors: 0,
|
|
3528
|
+
warnings: 1,
|
|
3529
|
+
info: 2,
|
|
3530
|
+
verbose: 3
|
|
3531
|
+
};
|
|
3532
|
+
var MESSAGE_LEVEL_PRIORITY2 = {
|
|
3533
|
+
error: 0,
|
|
3534
|
+
warn: 1,
|
|
3535
|
+
info: 2,
|
|
3536
|
+
debug: 3
|
|
3537
|
+
};
|
|
3075
3538
|
var UILogCollector = class {
|
|
3076
3539
|
constructor(clientId, sendMessage, uiBlockId) {
|
|
3077
3540
|
this.logs = [];
|
|
3078
3541
|
this.uiBlockId = uiBlockId || null;
|
|
3079
3542
|
this.clientId = clientId;
|
|
3080
3543
|
this.sendMessage = sendMessage;
|
|
3544
|
+
this.currentLogLevel = logger.getLogLevel();
|
|
3081
3545
|
}
|
|
3082
3546
|
/**
|
|
3083
3547
|
* Check if logging is enabled (uiBlockId is provided)
|
|
@@ -3085,10 +3549,22 @@ var UILogCollector = class {
|
|
|
3085
3549
|
isEnabled() {
|
|
3086
3550
|
return this.uiBlockId !== null;
|
|
3087
3551
|
}
|
|
3552
|
+
/**
|
|
3553
|
+
* Check if a message should be logged based on current log level
|
|
3554
|
+
*/
|
|
3555
|
+
shouldLog(messageLevel) {
|
|
3556
|
+
const currentLevelPriority = LOG_LEVEL_PRIORITY2[this.currentLogLevel];
|
|
3557
|
+
const messagePriority = MESSAGE_LEVEL_PRIORITY2[messageLevel];
|
|
3558
|
+
return messagePriority <= currentLevelPriority;
|
|
3559
|
+
}
|
|
3088
3560
|
/**
|
|
3089
3561
|
* Add a log entry with timestamp and immediately send to runtime
|
|
3562
|
+
* Only logs that pass the log level filter are captured and sent
|
|
3090
3563
|
*/
|
|
3091
3564
|
addLog(level, message, type, data) {
|
|
3565
|
+
if (!this.shouldLog(level)) {
|
|
3566
|
+
return;
|
|
3567
|
+
}
|
|
3092
3568
|
const log = {
|
|
3093
3569
|
timestamp: Date.now(),
|
|
3094
3570
|
level,
|
|
@@ -3098,6 +3574,20 @@ var UILogCollector = class {
|
|
|
3098
3574
|
};
|
|
3099
3575
|
this.logs.push(log);
|
|
3100
3576
|
this.sendLogImmediately(log);
|
|
3577
|
+
switch (level) {
|
|
3578
|
+
case "error":
|
|
3579
|
+
logger.error("UILogCollector:", log);
|
|
3580
|
+
break;
|
|
3581
|
+
case "warn":
|
|
3582
|
+
logger.warn("UILogCollector:", log);
|
|
3583
|
+
break;
|
|
3584
|
+
case "info":
|
|
3585
|
+
logger.info("UILogCollector:", log);
|
|
3586
|
+
break;
|
|
3587
|
+
case "debug":
|
|
3588
|
+
logger.debug("UILogCollector:", log);
|
|
3589
|
+
break;
|
|
3590
|
+
}
|
|
3101
3591
|
}
|
|
3102
3592
|
/**
|
|
3103
3593
|
* Send a single log to runtime immediately
|
|
@@ -3228,100 +3718,131 @@ var CONTEXT_CONFIG = {
|
|
|
3228
3718
|
|
|
3229
3719
|
// src/handlers/user-prompt-request.ts
|
|
3230
3720
|
var processedMessageIds = /* @__PURE__ */ new Set();
|
|
3231
|
-
async
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
const
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3721
|
+
var get_user_request = async (data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders) => {
|
|
3722
|
+
const errors = [];
|
|
3723
|
+
logger.debug("[USER_PROMPT_REQ] Parsing incoming message data");
|
|
3724
|
+
const parseResult = UserPromptRequestMessageSchema.safeParse(data);
|
|
3725
|
+
if (!parseResult.success) {
|
|
3726
|
+
const zodError = parseResult.error;
|
|
3727
|
+
zodError.errors.forEach((err) => {
|
|
3728
|
+
errors.push(`${err.path.join(".")}: ${err.message}`);
|
|
3729
|
+
});
|
|
3730
|
+
return { success: false, errors };
|
|
3731
|
+
}
|
|
3732
|
+
const userPromptRequest = parseResult.data;
|
|
3733
|
+
const { id, payload } = userPromptRequest;
|
|
3734
|
+
const prompt = payload.prompt;
|
|
3735
|
+
const SA_RUNTIME = payload.SA_RUNTIME;
|
|
3736
|
+
const wsId = userPromptRequest.from.id || "unknown";
|
|
3737
|
+
logger.debug(`[REQUEST ${id}] Full request details - wsId: ${wsId}, prompt length: ${prompt.length}`);
|
|
3738
|
+
if (processedMessageIds.has(id)) {
|
|
3739
|
+
logger.warn(`[REQUEST ${id}] Duplicate request detected - ignoring`);
|
|
3740
|
+
}
|
|
3741
|
+
processedMessageIds.add(id);
|
|
3742
|
+
logger.debug(`[REQUEST ${id}] Message ID marked as processed (${processedMessageIds.size} total)`);
|
|
3743
|
+
if (processedMessageIds.size > 100) {
|
|
3744
|
+
const firstId = processedMessageIds.values().next().value;
|
|
3745
|
+
if (firstId) {
|
|
3746
|
+
processedMessageIds.delete(firstId);
|
|
3747
|
+
logger.debug(`[REQUEST ${id}] Cleaned up old message ID from cache`);
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
if (!SA_RUNTIME) {
|
|
3751
|
+
errors.push("SA_RUNTIME is required");
|
|
3752
|
+
}
|
|
3753
|
+
const threadId = SA_RUNTIME?.threadId;
|
|
3754
|
+
const existingUiBlockId = SA_RUNTIME?.uiBlockId;
|
|
3755
|
+
if (!threadId) {
|
|
3756
|
+
errors.push("threadId in SA_RUNTIME is required");
|
|
3757
|
+
}
|
|
3758
|
+
if (!existingUiBlockId) {
|
|
3759
|
+
errors.push("uiBlockId in SA_RUNTIME is required");
|
|
3760
|
+
}
|
|
3761
|
+
if (!prompt) {
|
|
3762
|
+
errors.push("Prompt not found");
|
|
3763
|
+
}
|
|
3764
|
+
if (!components || components.length === 0) {
|
|
3765
|
+
errors.push("Components not found");
|
|
3766
|
+
}
|
|
3767
|
+
if (errors.length > 0) {
|
|
3768
|
+
return { success: false, errors, id, wsId };
|
|
3769
|
+
}
|
|
3770
|
+
const logCollector = new UILogCollector(wsId, sendMessage, existingUiBlockId);
|
|
3771
|
+
const threadManager = ThreadManager.getInstance();
|
|
3772
|
+
let thread = threadManager.getThread(threadId);
|
|
3773
|
+
if (!thread) {
|
|
3774
|
+
thread = threadManager.createThread(threadId);
|
|
3775
|
+
logger.info(`Created new thread: ${threadId}`);
|
|
3776
|
+
}
|
|
3777
|
+
logCollector.info(`Starting user prompt request with ${components.length} components`);
|
|
3778
|
+
const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId);
|
|
3779
|
+
logger.info("conversationHistory", conversationHistory);
|
|
3780
|
+
const userResponse = await get_user_response(prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory);
|
|
3781
|
+
logger.info("llm userResponse", userResponse);
|
|
3782
|
+
logCollector.info("User prompt request completed");
|
|
3783
|
+
const uiBlockId = existingUiBlockId;
|
|
3784
|
+
if (!userResponse.success) {
|
|
3785
|
+
logger.error(`User prompt request failed with errors: ${userResponse.errors.join(", ")}`);
|
|
3786
|
+
return {
|
|
3787
|
+
success: false,
|
|
3788
|
+
data: userResponse.data,
|
|
3789
|
+
errors: userResponse.errors,
|
|
3790
|
+
uiBlockId,
|
|
3791
|
+
threadId,
|
|
3792
|
+
id,
|
|
3793
|
+
wsId
|
|
3794
|
+
};
|
|
3795
|
+
}
|
|
3796
|
+
let component = null;
|
|
3797
|
+
let textResponse = null;
|
|
3798
|
+
if (userResponse.data) {
|
|
3799
|
+
if (typeof userResponse.data === "object") {
|
|
3800
|
+
if ("component" in userResponse.data) {
|
|
3801
|
+
component = userResponse.data.component;
|
|
3802
|
+
}
|
|
3803
|
+
if ("textResponse" in userResponse.data) {
|
|
3804
|
+
textResponse = userResponse.data.textResponse;
|
|
3248
3805
|
}
|
|
3249
3806
|
}
|
|
3250
|
-
if (!SA_RUNTIME) {
|
|
3251
|
-
sendDataResponse4(id, {
|
|
3252
|
-
success: false,
|
|
3253
|
-
error: "SA_RUNTIME is required"
|
|
3254
|
-
}, sendMessage, wsId);
|
|
3255
|
-
return;
|
|
3256
|
-
}
|
|
3257
|
-
const threadId = SA_RUNTIME.threadId;
|
|
3258
|
-
const existingUiBlockId = SA_RUNTIME.uiBlockId;
|
|
3259
|
-
if (!threadId) {
|
|
3260
|
-
sendDataResponse4(id, {
|
|
3261
|
-
success: false,
|
|
3262
|
-
error: "threadId in SA_RUNTIME is required"
|
|
3263
|
-
}, sendMessage, wsId);
|
|
3264
|
-
return;
|
|
3265
|
-
}
|
|
3266
|
-
if (!existingUiBlockId) {
|
|
3267
|
-
sendDataResponse4(id, {
|
|
3268
|
-
success: false,
|
|
3269
|
-
error: "uiBlockId in SA_RUNTIME is required"
|
|
3270
|
-
}, sendMessage, wsId);
|
|
3271
|
-
return;
|
|
3272
|
-
}
|
|
3273
|
-
const logCollector = new UILogCollector(wsId, sendMessage, existingUiBlockId);
|
|
3274
|
-
if (!prompt) {
|
|
3275
|
-
sendDataResponse4(id, {
|
|
3276
|
-
success: false,
|
|
3277
|
-
error: "Prompt not found"
|
|
3278
|
-
}, sendMessage, wsId);
|
|
3279
|
-
return;
|
|
3280
|
-
}
|
|
3281
|
-
if (!components || components.length === 0) {
|
|
3282
|
-
sendDataResponse4(id, {
|
|
3283
|
-
success: false,
|
|
3284
|
-
error: "Components not found"
|
|
3285
|
-
}, sendMessage, wsId);
|
|
3286
|
-
return;
|
|
3287
|
-
}
|
|
3288
|
-
logCollector.info(`Starting user prompt request with ${components.length} components`);
|
|
3289
|
-
const threadManager = ThreadManager.getInstance();
|
|
3290
|
-
let thread = threadManager.getThread(threadId);
|
|
3291
|
-
if (!thread) {
|
|
3292
|
-
thread = threadManager.createThread(threadId);
|
|
3293
|
-
logger.info(`Created new thread: ${threadId}`);
|
|
3294
|
-
}
|
|
3295
|
-
const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, existingUiBlockId);
|
|
3296
|
-
const userResponse = await get_user_response(prompt, components, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory);
|
|
3297
|
-
logCollector.info("User prompt request completed");
|
|
3298
|
-
if (userResponse.success && userResponse.data && typeof userResponse.data === "object" && "component" in userResponse.data) {
|
|
3299
|
-
const component = userResponse.data.component;
|
|
3300
|
-
const uiBlockId = existingUiBlockId;
|
|
3301
|
-
const uiBlock = new UIBlock(
|
|
3302
|
-
prompt,
|
|
3303
|
-
{},
|
|
3304
|
-
// componentData: initially empty, will be filled later
|
|
3305
|
-
component || {},
|
|
3306
|
-
// generatedComponentMetadata: full component object (ComponentSchema)
|
|
3307
|
-
[],
|
|
3308
|
-
// actions: empty initially
|
|
3309
|
-
uiBlockId
|
|
3310
|
-
);
|
|
3311
|
-
thread.addUIBlock(uiBlock);
|
|
3312
|
-
logger.info(`Created UIBlock: ${uiBlockId} in Thread: ${threadId}`);
|
|
3313
|
-
sendDataResponse4(id, {
|
|
3314
|
-
...userResponse,
|
|
3315
|
-
uiBlockId,
|
|
3316
|
-
threadId
|
|
3317
|
-
}, sendMessage, wsId);
|
|
3318
|
-
} else {
|
|
3319
|
-
sendDataResponse4(id, userResponse, sendMessage, wsId);
|
|
3320
|
-
}
|
|
3321
|
-
return;
|
|
3322
|
-
} catch (error) {
|
|
3323
|
-
logger.error("Failed to handle user prompt request:", error);
|
|
3324
3807
|
}
|
|
3808
|
+
const uiBlock = new UIBlock(
|
|
3809
|
+
prompt,
|
|
3810
|
+
{},
|
|
3811
|
+
// componentData: initially empty, will be filled later
|
|
3812
|
+
component,
|
|
3813
|
+
// generatedComponentMetadata: full component object (ComponentSchema)
|
|
3814
|
+
[],
|
|
3815
|
+
// actions: empty initially
|
|
3816
|
+
uiBlockId,
|
|
3817
|
+
textResponse
|
|
3818
|
+
// textResponse: text response from LLM
|
|
3819
|
+
);
|
|
3820
|
+
thread.addUIBlock(uiBlock);
|
|
3821
|
+
logger.info(`Created UIBlock: ${uiBlockId} in Thread: ${threadId}`);
|
|
3822
|
+
return {
|
|
3823
|
+
success: userResponse.success,
|
|
3824
|
+
data: userResponse.data,
|
|
3825
|
+
errors: userResponse.errors,
|
|
3826
|
+
uiBlockId,
|
|
3827
|
+
threadId,
|
|
3828
|
+
id,
|
|
3829
|
+
wsId
|
|
3830
|
+
};
|
|
3831
|
+
};
|
|
3832
|
+
async function handleUserPromptRequest(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders) {
|
|
3833
|
+
const response = await get_user_request(data, components, sendMessage, anthropicApiKey, groqApiKey, llmProviders);
|
|
3834
|
+
sendDataResponse4(
|
|
3835
|
+
response.id || data.id,
|
|
3836
|
+
{
|
|
3837
|
+
success: response.success,
|
|
3838
|
+
errors: response.errors,
|
|
3839
|
+
data: response.data,
|
|
3840
|
+
uiBlockId: response.uiBlockId,
|
|
3841
|
+
threadId: response.threadId
|
|
3842
|
+
},
|
|
3843
|
+
sendMessage,
|
|
3844
|
+
response.wsId || data.from?.id
|
|
3845
|
+
);
|
|
3325
3846
|
}
|
|
3326
3847
|
function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
3327
3848
|
const response = {
|
|
@@ -3336,6 +3857,7 @@ function sendDataResponse4(id, res, sendMessage, clientId) {
|
|
|
3336
3857
|
...res
|
|
3337
3858
|
}
|
|
3338
3859
|
};
|
|
3860
|
+
logger.info("sending user prompt response", response);
|
|
3339
3861
|
sendMessage(response);
|
|
3340
3862
|
}
|
|
3341
3863
|
|
|
@@ -3433,12 +3955,27 @@ function sendResponse(id, res, sendMessage, clientId) {
|
|
|
3433
3955
|
// src/userResponse/next-questions.ts
|
|
3434
3956
|
async function generateNextQuestions(originalUserPrompt, component, componentData, anthropicApiKey, groqApiKey, llmProviders, logCollector, conversationHistory) {
|
|
3435
3957
|
try {
|
|
3958
|
+
logger.debug("[generateNextQuestions] Starting next questions generation");
|
|
3959
|
+
logger.debug(`[generateNextQuestions] User prompt: "${originalUserPrompt?.substring(0, 50)}..."`);
|
|
3960
|
+
logger.debug(`[generateNextQuestions] Component: ${component?.name || "unknown"} (${component?.type || "unknown"})`);
|
|
3961
|
+
logger.debug(`[generateNextQuestions] Component data available: ${componentData ? "yes" : "no"}`);
|
|
3436
3962
|
const providers = llmProviders || ["anthropic"];
|
|
3437
|
-
|
|
3963
|
+
logger.info(`[generateNextQuestions] Using LLM providers: [${providers.join(", ")}]`);
|
|
3964
|
+
if (conversationHistory && conversationHistory.length > 0) {
|
|
3965
|
+
const exchangeCount = conversationHistory.split("\n").filter((l) => l.startsWith("Q")).length;
|
|
3966
|
+
logger.debug(`[generateNextQuestions] Using conversation history with ${exchangeCount} previous exchanges`);
|
|
3967
|
+
} else {
|
|
3968
|
+
logger.debug("[generateNextQuestions] No conversation history available");
|
|
3969
|
+
}
|
|
3970
|
+
for (let i = 0; i < providers.length; i++) {
|
|
3971
|
+
const provider = providers[i];
|
|
3972
|
+
const isLastProvider = i === providers.length - 1;
|
|
3438
3973
|
try {
|
|
3439
|
-
logger.info(`
|
|
3974
|
+
logger.info(`[generateNextQuestions] Attempting provider: ${provider} (${i + 1}/${providers.length})`);
|
|
3975
|
+
logCollector?.info(`Generating questions with ${provider}...`);
|
|
3440
3976
|
let result = [];
|
|
3441
3977
|
if (provider === "groq") {
|
|
3978
|
+
logger.debug("[generateNextQuestions] Using Groq LLM for next questions");
|
|
3442
3979
|
result = await groqLLM.generateNextQuestions(
|
|
3443
3980
|
originalUserPrompt,
|
|
3444
3981
|
component,
|
|
@@ -3448,6 +3985,7 @@ async function generateNextQuestions(originalUserPrompt, component, componentDat
|
|
|
3448
3985
|
conversationHistory
|
|
3449
3986
|
);
|
|
3450
3987
|
} else {
|
|
3988
|
+
logger.debug("[generateNextQuestions] Using Anthropic LLM for next questions");
|
|
3451
3989
|
result = await anthropicLLM.generateNextQuestions(
|
|
3452
3990
|
originalUserPrompt,
|
|
3453
3991
|
component,
|
|
@@ -3458,21 +3996,39 @@ async function generateNextQuestions(originalUserPrompt, component, componentDat
|
|
|
3458
3996
|
);
|
|
3459
3997
|
}
|
|
3460
3998
|
if (result && result.length > 0) {
|
|
3461
|
-
logger.info(`Successfully generated ${result.length} questions with ${provider}`);
|
|
3999
|
+
logger.info(`[generateNextQuestions] Successfully generated ${result.length} questions with ${provider}`);
|
|
4000
|
+
logger.debug(`[generateNextQuestions] Questions: ${JSON.stringify(result)}`);
|
|
4001
|
+
logCollector?.info(`Generated ${result.length} follow-up questions`);
|
|
3462
4002
|
return result;
|
|
3463
4003
|
}
|
|
3464
|
-
|
|
4004
|
+
const warnMsg = `No questions generated from ${provider}${!isLastProvider ? ", trying next provider..." : ""}`;
|
|
4005
|
+
logger.warn(`[generateNextQuestions] ${warnMsg}`);
|
|
4006
|
+
if (!isLastProvider) {
|
|
4007
|
+
logCollector?.warn(warnMsg);
|
|
4008
|
+
}
|
|
3465
4009
|
} catch (providerError) {
|
|
3466
|
-
|
|
3467
|
-
|
|
4010
|
+
const errorMsg = providerError instanceof Error ? providerError.message : String(providerError);
|
|
4011
|
+
logger.error(`[generateNextQuestions] Provider ${provider} failed: ${errorMsg}`);
|
|
4012
|
+
logger.debug(`[generateNextQuestions] Provider error details:`, providerError);
|
|
4013
|
+
if (!isLastProvider) {
|
|
4014
|
+
const fallbackMsg = `Provider ${provider} failed, trying next provider...`;
|
|
4015
|
+
logger.info(`[generateNextQuestions] ${fallbackMsg}`);
|
|
4016
|
+
logCollector?.warn(fallbackMsg);
|
|
4017
|
+
} else {
|
|
4018
|
+
logCollector?.error(`Failed to generate questions with ${provider}`);
|
|
4019
|
+
}
|
|
3468
4020
|
continue;
|
|
3469
4021
|
}
|
|
3470
4022
|
}
|
|
3471
|
-
logger.warn("All providers failed or returned no questions");
|
|
4023
|
+
logger.warn("[generateNextQuestions] All providers failed or returned no questions");
|
|
4024
|
+
logCollector?.warn("Unable to generate follow-up questions");
|
|
3472
4025
|
return [];
|
|
3473
4026
|
} catch (error) {
|
|
3474
|
-
|
|
3475
|
-
|
|
4027
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4028
|
+
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
4029
|
+
logger.error(`[generateNextQuestions] Error generating next questions: ${errorMsg}`);
|
|
4030
|
+
logger.debug("[generateNextQuestions] Error stack trace:", errorStack);
|
|
4031
|
+
logCollector?.error(`Error generating next questions: ${errorMsg}`);
|
|
3476
4032
|
return [];
|
|
3477
4033
|
}
|
|
3478
4034
|
}
|
|
@@ -3480,11 +4036,15 @@ async function generateNextQuestions(originalUserPrompt, component, componentDat
|
|
|
3480
4036
|
// src/handlers/actions-request.ts
|
|
3481
4037
|
async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiKey, llmProviders) {
|
|
3482
4038
|
try {
|
|
4039
|
+
logger.debug("[ACTIONS_REQ] Parsing incoming actions request");
|
|
3483
4040
|
const actionsRequest = ActionsRequestMessageSchema.parse(data);
|
|
3484
4041
|
const { id, payload } = actionsRequest;
|
|
3485
4042
|
const { SA_RUNTIME } = payload;
|
|
3486
4043
|
const wsId = actionsRequest.from.id || "unknown";
|
|
4044
|
+
logger.info(`[ACTIONS_REQ ${id}] Processing actions request from client: ${wsId}`);
|
|
4045
|
+
logger.debug(`[ACTIONS_REQ ${id}] Request payload:`, JSON.stringify(payload, null, 2).substring(0, 200));
|
|
3487
4046
|
if (!SA_RUNTIME) {
|
|
4047
|
+
logger.error(`[ACTIONS_REQ ${id}] SA_RUNTIME missing from request`);
|
|
3488
4048
|
sendResponse2(id, {
|
|
3489
4049
|
success: false,
|
|
3490
4050
|
error: "SA_RUNTIME with threadId and uiBlockId is required"
|
|
@@ -3493,31 +4053,54 @@ async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiK
|
|
|
3493
4053
|
}
|
|
3494
4054
|
const uiBlockId = SA_RUNTIME.uiBlockId;
|
|
3495
4055
|
const threadId = SA_RUNTIME.threadId;
|
|
4056
|
+
logger.debug(`[ACTIONS_REQ ${id}] SA_RUNTIME validated - threadId: ${threadId}, uiBlockId: ${uiBlockId}`);
|
|
4057
|
+
logger.debug(`[ACTIONS_REQ ${id}] Retrieving thread: ${threadId}`);
|
|
3496
4058
|
const threadManager = ThreadManager.getInstance();
|
|
3497
4059
|
const thread = threadManager.getThread(threadId);
|
|
3498
4060
|
if (!thread) {
|
|
4061
|
+
logger.error(`[ACTIONS_REQ ${id}] Thread '${threadId}' not found`);
|
|
3499
4062
|
sendResponse2(id, {
|
|
3500
4063
|
success: false,
|
|
3501
4064
|
error: `Thread '${threadId}' not found`
|
|
3502
4065
|
}, sendMessage, wsId);
|
|
3503
4066
|
return;
|
|
3504
4067
|
}
|
|
4068
|
+
logger.debug(`[ACTIONS_REQ ${id}] Thread found with ${thread.getUIBlocks().length} UIBlocks`);
|
|
4069
|
+
logger.debug(`[ACTIONS_REQ ${id}] Retrieving UIBlock: ${uiBlockId}`);
|
|
3505
4070
|
const uiBlock = thread.getUIBlock(uiBlockId);
|
|
3506
4071
|
if (!uiBlock) {
|
|
4072
|
+
logger.error(`[ACTIONS_REQ ${id}] UIBlock '${uiBlockId}' not found in thread '${threadId}'`);
|
|
3507
4073
|
sendResponse2(id, {
|
|
3508
4074
|
success: false,
|
|
3509
4075
|
error: `UIBlock '${uiBlockId}' not found in thread '${threadId}'`
|
|
3510
4076
|
}, sendMessage, wsId);
|
|
3511
4077
|
return;
|
|
3512
4078
|
}
|
|
4079
|
+
logger.info(`[ACTIONS_REQ ${id}] UIBlock retrieved successfully`);
|
|
4080
|
+
logger.debug(`[ACTIONS_REQ ${id}] Creating UILogCollector for uiBlockId: ${uiBlockId}`);
|
|
3513
4081
|
const logCollector = new UILogCollector(wsId, sendMessage, uiBlockId);
|
|
4082
|
+
logger.info(`[ACTIONS_REQ ${id}] UILogCollector initialized`);
|
|
4083
|
+
logger.debug(`[ACTIONS_REQ ${id}] Extracting data from UIBlock`);
|
|
3514
4084
|
const userQuestion = uiBlock.getUserQuestion();
|
|
3515
4085
|
const component = uiBlock.getComponentMetadata();
|
|
3516
4086
|
const componentData = uiBlock.getComponentData();
|
|
4087
|
+
logger.debug(`[ACTIONS_REQ ${id}] User question: "${userQuestion?.substring(0, 50)}..."`);
|
|
4088
|
+
logger.debug(`[ACTIONS_REQ ${id}] Component: ${component?.name || "unknown"} (${component?.type || "unknown"})`);
|
|
4089
|
+
logger.debug(`[ACTIONS_REQ ${id}] Component data available: ${componentData ? "yes" : "no"}`);
|
|
4090
|
+
logger.debug(`[ACTIONS_REQ ${id}] Extracting conversation history (max ${CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS} blocks)`);
|
|
3517
4091
|
const conversationHistory = thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, uiBlockId);
|
|
4092
|
+
const historyLineCount = conversationHistory.split("\n").filter((l) => l.trim()).length;
|
|
4093
|
+
logger.info(`[ACTIONS_REQ ${id}] Conversation history extracted: ${historyLineCount} lines`);
|
|
4094
|
+
logger.debug(`[ACTIONS_REQ ${id}] Conversation history preview:
|
|
4095
|
+
${conversationHistory.substring(0, 200)}...`);
|
|
3518
4096
|
logCollector.info(`Generating actions for UIBlock: ${uiBlockId}`);
|
|
3519
|
-
logger.info(`Generating actions for component: ${component?.name || "unknown"}`);
|
|
4097
|
+
logger.info(`[ACTIONS_REQ ${id}] Generating actions for component: ${component?.name || "unknown"}`);
|
|
4098
|
+
logger.debug(`[ACTIONS_REQ ${id}] Checking if actions are already cached`);
|
|
4099
|
+
const startTime = Date.now();
|
|
3520
4100
|
const actions = await uiBlock.getOrFetchActions(async () => {
|
|
4101
|
+
logger.info(`[ACTIONS_REQ ${id}] Actions not cached, generating new actions...`);
|
|
4102
|
+
logCollector.info("Generating follow-up questions...");
|
|
4103
|
+
logger.info(`[ACTIONS_REQ ${id}] Starting next questions generation with ${llmProviders?.join(", ") || "default"} providers`);
|
|
3521
4104
|
const nextQuestions = await generateNextQuestions(
|
|
3522
4105
|
userQuestion,
|
|
3523
4106
|
component,
|
|
@@ -3528,14 +4111,28 @@ async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiK
|
|
|
3528
4111
|
logCollector,
|
|
3529
4112
|
conversationHistory
|
|
3530
4113
|
);
|
|
3531
|
-
|
|
4114
|
+
logger.info(`[ACTIONS_REQ ${id}] Generated ${nextQuestions.length} questions`);
|
|
4115
|
+
logger.debug(`[ACTIONS_REQ ${id}] Questions: ${JSON.stringify(nextQuestions)}`);
|
|
4116
|
+
logger.debug(`[ACTIONS_REQ ${id}] Converting questions to actions format`);
|
|
4117
|
+
const convertedActions = nextQuestions.map((question, index) => ({
|
|
3532
4118
|
id: `action_${index}_${Date.now()}`,
|
|
3533
4119
|
name: question,
|
|
3534
4120
|
type: "next_question",
|
|
3535
4121
|
question
|
|
3536
4122
|
}));
|
|
4123
|
+
logger.debug(`[ACTIONS_REQ ${id}] Converted ${convertedActions.length} actions`);
|
|
4124
|
+
return convertedActions;
|
|
3537
4125
|
});
|
|
3538
|
-
|
|
4126
|
+
const processingTime = Date.now() - startTime;
|
|
4127
|
+
logger.info(`[ACTIONS_REQ ${id}] Actions retrieved in ${processingTime}ms - ${actions.length} actions total`);
|
|
4128
|
+
if (actions.length > 0) {
|
|
4129
|
+
logCollector.info(`Generated ${actions.length} follow-up questions successfully`);
|
|
4130
|
+
logger.debug(`[ACTIONS_REQ ${id}] Actions: ${actions.map((a) => a.name).join(", ")}`);
|
|
4131
|
+
} else {
|
|
4132
|
+
logger.warn(`[ACTIONS_REQ ${id}] No actions generated`);
|
|
4133
|
+
logCollector.warn("No follow-up questions could be generated");
|
|
4134
|
+
}
|
|
4135
|
+
logger.debug(`[ACTIONS_REQ ${id}] Sending successful response to client`);
|
|
3539
4136
|
sendResponse2(id, {
|
|
3540
4137
|
success: true,
|
|
3541
4138
|
data: {
|
|
@@ -3546,12 +4143,26 @@ async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiK
|
|
|
3546
4143
|
threadId
|
|
3547
4144
|
}
|
|
3548
4145
|
}, sendMessage, wsId);
|
|
4146
|
+
logger.info(`[ACTIONS_REQ ${id}] \u2713 Actions request completed successfully`);
|
|
3549
4147
|
} catch (error) {
|
|
3550
|
-
|
|
4148
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
4149
|
+
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
4150
|
+
logger.error(`[ACTIONS_REQ] Failed to handle actions request: ${errorMessage}`);
|
|
4151
|
+
logger.debug(`[ACTIONS_REQ] Error stack trace:`, errorStack);
|
|
4152
|
+
try {
|
|
4153
|
+
const parsedData = data;
|
|
4154
|
+
if (parsedData?.id && parsedData?.from?.id) {
|
|
4155
|
+
const logCollector = parsedData?.payload?.SA_RUNTIME?.uiBlockId ? new UILogCollector(parsedData.from.id, sendMessage, parsedData.payload.SA_RUNTIME.uiBlockId) : void 0;
|
|
4156
|
+
logCollector?.error(`Failed to generate actions: ${errorMessage}`);
|
|
4157
|
+
}
|
|
4158
|
+
} catch (logError) {
|
|
4159
|
+
logger.debug("[ACTIONS_REQ] Failed to send error logs to UI:", logError);
|
|
4160
|
+
}
|
|
3551
4161
|
sendResponse2(null, {
|
|
3552
4162
|
success: false,
|
|
3553
|
-
error:
|
|
4163
|
+
error: errorMessage
|
|
3554
4164
|
}, sendMessage);
|
|
4165
|
+
logger.info("[ACTIONS_REQ] \u2717 Actions request completed with errors");
|
|
3555
4166
|
}
|
|
3556
4167
|
}
|
|
3557
4168
|
function sendResponse2(id, res, sendMessage, clientId) {
|
|
@@ -3567,6 +4178,11 @@ function sendResponse2(id, res, sendMessage, clientId) {
|
|
|
3567
4178
|
...res
|
|
3568
4179
|
}
|
|
3569
4180
|
};
|
|
4181
|
+
logger.debug(`[ACTIONS_RES ${id || "unknown"}] Sending ${res.success ? "successful" : "failed"} response to client`);
|
|
4182
|
+
logger.debug(`[ACTIONS_RES ${id || "unknown"}] Response payload size: ${JSON.stringify(response).length} bytes`);
|
|
4183
|
+
if (res.data?.actions) {
|
|
4184
|
+
logger.debug(`[ACTIONS_RES ${id || "unknown"}] Sending ${res.data.actions.length} actions`);
|
|
4185
|
+
}
|
|
3570
4186
|
sendMessage(response);
|
|
3571
4187
|
}
|
|
3572
4188
|
|
|
@@ -3595,7 +4211,10 @@ async function handleUsersRequest(data, sendMessage) {
|
|
|
3595
4211
|
const { id, payload, from } = request;
|
|
3596
4212
|
const { operation, data: requestData } = payload;
|
|
3597
4213
|
const username = requestData?.username;
|
|
4214
|
+
const email = requestData?.email;
|
|
3598
4215
|
const password = requestData?.password;
|
|
4216
|
+
const fullname = requestData?.fullname;
|
|
4217
|
+
const role = requestData?.role;
|
|
3599
4218
|
if (from.type !== "admin") {
|
|
3600
4219
|
sendResponse3(id, {
|
|
3601
4220
|
success: false,
|
|
@@ -3607,10 +4226,10 @@ async function handleUsersRequest(data, sendMessage) {
|
|
|
3607
4226
|
const userManager = getUserManager();
|
|
3608
4227
|
switch (operation) {
|
|
3609
4228
|
case "create":
|
|
3610
|
-
await handleCreate(id, username, password, userManager, sendMessage, from.id);
|
|
4229
|
+
await handleCreate(id, { username, email, password, fullname, role }, userManager, sendMessage, from.id);
|
|
3611
4230
|
break;
|
|
3612
4231
|
case "update":
|
|
3613
|
-
await handleUpdate(id, username, password, userManager, sendMessage, from.id);
|
|
4232
|
+
await handleUpdate(id, { username, email, password, fullname, role }, userManager, sendMessage, from.id);
|
|
3614
4233
|
break;
|
|
3615
4234
|
case "delete":
|
|
3616
4235
|
await handleDelete(id, username, userManager, sendMessage, from.id);
|
|
@@ -3635,7 +4254,8 @@ async function handleUsersRequest(data, sendMessage) {
|
|
|
3635
4254
|
}, sendMessage);
|
|
3636
4255
|
}
|
|
3637
4256
|
}
|
|
3638
|
-
async function handleCreate(id,
|
|
4257
|
+
async function handleCreate(id, userData, userManager, sendMessage, clientId) {
|
|
4258
|
+
const { username, email, password, fullname, role } = userData;
|
|
3639
4259
|
if (!username || username.trim().length === 0) {
|
|
3640
4260
|
sendResponse3(id, {
|
|
3641
4261
|
success: false,
|
|
@@ -3650,6 +4270,16 @@ async function handleCreate(id, username, password, userManager, sendMessage, cl
|
|
|
3650
4270
|
}, sendMessage, clientId);
|
|
3651
4271
|
return;
|
|
3652
4272
|
}
|
|
4273
|
+
if (email && email.trim().length > 0) {
|
|
4274
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
4275
|
+
if (!emailRegex.test(email)) {
|
|
4276
|
+
sendResponse3(id, {
|
|
4277
|
+
success: false,
|
|
4278
|
+
error: "Invalid email format"
|
|
4279
|
+
}, sendMessage, clientId);
|
|
4280
|
+
return;
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
3653
4283
|
if (userManager.userExists(username)) {
|
|
3654
4284
|
sendResponse3(id, {
|
|
3655
4285
|
success: false,
|
|
@@ -3657,25 +4287,41 @@ async function handleCreate(id, username, password, userManager, sendMessage, cl
|
|
|
3657
4287
|
}, sendMessage, clientId);
|
|
3658
4288
|
return;
|
|
3659
4289
|
}
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
4290
|
+
if (email && userManager.getUserByEmail(email)) {
|
|
4291
|
+
sendResponse3(id, {
|
|
4292
|
+
success: false,
|
|
4293
|
+
error: `User with email '${email}' already exists`
|
|
4294
|
+
}, sendMessage, clientId);
|
|
4295
|
+
return;
|
|
3663
4296
|
}
|
|
3664
|
-
const
|
|
4297
|
+
const newUserData = {
|
|
3665
4298
|
username,
|
|
3666
|
-
password
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
4299
|
+
password
|
|
4300
|
+
};
|
|
4301
|
+
if (email && email.trim().length > 0) {
|
|
4302
|
+
newUserData.email = email.trim();
|
|
4303
|
+
}
|
|
4304
|
+
if (fullname && fullname.trim().length > 0) {
|
|
4305
|
+
newUserData.fullname = fullname.trim();
|
|
4306
|
+
}
|
|
4307
|
+
if (role && role.trim().length > 0) {
|
|
4308
|
+
newUserData.role = role.trim();
|
|
4309
|
+
}
|
|
4310
|
+
const newUser = userManager.createUser(newUserData);
|
|
4311
|
+
logger.info(`User created by admin: ${username}${email ? ` (${email})` : ""}`);
|
|
3670
4312
|
sendResponse3(id, {
|
|
3671
4313
|
success: true,
|
|
3672
4314
|
data: {
|
|
3673
4315
|
username: newUser.username,
|
|
4316
|
+
email: newUser.email,
|
|
4317
|
+
fullname: newUser.fullname,
|
|
4318
|
+
role: newUser.role,
|
|
3674
4319
|
message: `User '${username}' created successfully`
|
|
3675
4320
|
}
|
|
3676
4321
|
}, sendMessage, clientId);
|
|
3677
4322
|
}
|
|
3678
|
-
async function handleUpdate(id,
|
|
4323
|
+
async function handleUpdate(id, userData, userManager, sendMessage, clientId) {
|
|
4324
|
+
const { username, email, password, fullname, role } = userData;
|
|
3679
4325
|
if (!username || username.trim().length === 0) {
|
|
3680
4326
|
sendResponse3(id, {
|
|
3681
4327
|
success: false,
|
|
@@ -3691,13 +4337,42 @@ async function handleUpdate(id, username, password, userManager, sendMessage, cl
|
|
|
3691
4337
|
return;
|
|
3692
4338
|
}
|
|
3693
4339
|
const updates = {};
|
|
3694
|
-
if (
|
|
3695
|
-
|
|
4340
|
+
if (email !== void 0) {
|
|
4341
|
+
if (email.trim().length > 0) {
|
|
4342
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
4343
|
+
if (!emailRegex.test(email)) {
|
|
4344
|
+
sendResponse3(id, {
|
|
4345
|
+
success: false,
|
|
4346
|
+
error: "Invalid email format"
|
|
4347
|
+
}, sendMessage, clientId);
|
|
4348
|
+
return;
|
|
4349
|
+
}
|
|
4350
|
+
const existingUser = userManager.getUserByEmail(email);
|
|
4351
|
+
if (existingUser && existingUser.username !== username) {
|
|
4352
|
+
sendResponse3(id, {
|
|
4353
|
+
success: false,
|
|
4354
|
+
error: `Email '${email}' is already used by another user`
|
|
4355
|
+
}, sendMessage, clientId);
|
|
4356
|
+
return;
|
|
4357
|
+
}
|
|
4358
|
+
updates.email = email.trim();
|
|
4359
|
+
} else {
|
|
4360
|
+
updates.email = void 0;
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
if (password !== void 0 && password.trim().length > 0) {
|
|
4364
|
+
updates.password = password.trim();
|
|
4365
|
+
}
|
|
4366
|
+
if (fullname !== void 0) {
|
|
4367
|
+
updates.fullname = fullname.trim().length > 0 ? fullname.trim() : void 0;
|
|
4368
|
+
}
|
|
4369
|
+
if (role !== void 0) {
|
|
4370
|
+
updates.role = role.trim().length > 0 ? role.trim() : void 0;
|
|
3696
4371
|
}
|
|
3697
4372
|
if (Object.keys(updates).length === 0) {
|
|
3698
4373
|
sendResponse3(id, {
|
|
3699
4374
|
success: false,
|
|
3700
|
-
error: "No fields to update. Please provide
|
|
4375
|
+
error: "No fields to update. Please provide at least one field to update."
|
|
3701
4376
|
}, sendMessage, clientId);
|
|
3702
4377
|
return;
|
|
3703
4378
|
}
|
|
@@ -3707,6 +4382,9 @@ async function handleUpdate(id, username, password, userManager, sendMessage, cl
|
|
|
3707
4382
|
success: true,
|
|
3708
4383
|
data: {
|
|
3709
4384
|
username: updatedUser.username,
|
|
4385
|
+
email: updatedUser.email,
|
|
4386
|
+
fullname: updatedUser.fullname,
|
|
4387
|
+
role: updatedUser.role,
|
|
3710
4388
|
message: `User '${username}' updated successfully`
|
|
3711
4389
|
}
|
|
3712
4390
|
}, sendMessage, clientId);
|
|
@@ -3747,6 +4425,9 @@ async function handleGetAll(id, userManager, sendMessage, clientId) {
|
|
|
3747
4425
|
const users = userManager.getAllUsers();
|
|
3748
4426
|
const sanitizedUsers = users.map((user) => ({
|
|
3749
4427
|
username: user.username,
|
|
4428
|
+
email: user.email,
|
|
4429
|
+
fullname: user.fullname,
|
|
4430
|
+
role: user.role,
|
|
3750
4431
|
wsIds: user.wsIds || []
|
|
3751
4432
|
}));
|
|
3752
4433
|
logger.info(`Admin retrieved all users (count: ${sanitizedUsers.length})`);
|
|
@@ -3777,6 +4458,9 @@ async function handleGetOne(id, username, userManager, sendMessage, clientId) {
|
|
|
3777
4458
|
const user = userManager.getUser(username);
|
|
3778
4459
|
const sanitizedUser = {
|
|
3779
4460
|
username: user.username,
|
|
4461
|
+
email: user.email,
|
|
4462
|
+
fullname: user.fullname,
|
|
4463
|
+
role: user.role,
|
|
3780
4464
|
wsIds: user.wsIds || []
|
|
3781
4465
|
};
|
|
3782
4466
|
logger.info(`Admin retrieved user: ${username}`);
|
|
@@ -4275,8 +4959,9 @@ var UserManager = class {
|
|
|
4275
4959
|
return;
|
|
4276
4960
|
}
|
|
4277
4961
|
const fileContent = import_fs3.default.readFileSync(this.filePath, "utf-8");
|
|
4278
|
-
const
|
|
4279
|
-
|
|
4962
|
+
const rawData = JSON.parse(fileContent);
|
|
4963
|
+
const validatedData = UsersDataSchema.parse(rawData);
|
|
4964
|
+
this.users = validatedData.users;
|
|
4280
4965
|
this.hasChanged = false;
|
|
4281
4966
|
logger.debug(`Loaded ${this.users.length} users from file`);
|
|
4282
4967
|
} catch (error) {
|
|
@@ -4296,10 +4981,14 @@ var UserManager = class {
|
|
|
4296
4981
|
if (!import_fs3.default.existsSync(dir)) {
|
|
4297
4982
|
import_fs3.default.mkdirSync(dir, { recursive: true });
|
|
4298
4983
|
}
|
|
4299
|
-
const
|
|
4984
|
+
const usersToSave = this.users.map((user) => {
|
|
4985
|
+
const { wsIds, ...userWithoutWsIds } = user;
|
|
4986
|
+
return userWithoutWsIds;
|
|
4987
|
+
});
|
|
4988
|
+
const data = { users: usersToSave };
|
|
4300
4989
|
import_fs3.default.writeFileSync(this.filePath, JSON.stringify(data, null, 4));
|
|
4301
4990
|
this.hasChanged = false;
|
|
4302
|
-
logger.debug(`Synced ${this.users.length} users to file`);
|
|
4991
|
+
logger.debug(`Synced ${this.users.length} users to file (wsIds excluded)`);
|
|
4303
4992
|
} catch (error) {
|
|
4304
4993
|
logger.error("Failed to save users to file:", error);
|
|
4305
4994
|
throw new Error(`Failed to save users to file: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -4346,13 +5035,17 @@ var UserManager = class {
|
|
|
4346
5035
|
* @returns The created user
|
|
4347
5036
|
*/
|
|
4348
5037
|
createUser(user) {
|
|
4349
|
-
|
|
4350
|
-
|
|
5038
|
+
const validatedUser = UserSchema.parse(user);
|
|
5039
|
+
if (this.users.some((u) => u.username === validatedUser.username)) {
|
|
5040
|
+
throw new Error(`User with username ${validatedUser.username} already exists`);
|
|
4351
5041
|
}
|
|
4352
|
-
this.users.
|
|
5042
|
+
if (validatedUser.email && this.users.some((u) => u.email === validatedUser.email)) {
|
|
5043
|
+
throw new Error(`User with email ${validatedUser.email} already exists`);
|
|
5044
|
+
}
|
|
5045
|
+
this.users.push(validatedUser);
|
|
4353
5046
|
this.hasChanged = true;
|
|
4354
|
-
logger.debug(`User created: ${
|
|
4355
|
-
return
|
|
5047
|
+
logger.debug(`User created: ${validatedUser.username}`);
|
|
5048
|
+
return validatedUser;
|
|
4356
5049
|
}
|
|
4357
5050
|
/**
|
|
4358
5051
|
* Read a user by username
|
|
@@ -4362,6 +5055,22 @@ var UserManager = class {
|
|
|
4362
5055
|
getUser(username) {
|
|
4363
5056
|
return this.users.find((u) => u.username === username);
|
|
4364
5057
|
}
|
|
5058
|
+
/**
|
|
5059
|
+
* Read a user by email
|
|
5060
|
+
* @param email - Email to retrieve
|
|
5061
|
+
* @returns The user if found, undefined otherwise
|
|
5062
|
+
*/
|
|
5063
|
+
getUserByEmail(email) {
|
|
5064
|
+
return this.users.find((u) => u.email === email);
|
|
5065
|
+
}
|
|
5066
|
+
/**
|
|
5067
|
+
* Find user by username or email
|
|
5068
|
+
* @param identifier - Username or email to search for
|
|
5069
|
+
* @returns The user if found, undefined otherwise
|
|
5070
|
+
*/
|
|
5071
|
+
getUserByUsernameOrEmail(identifier) {
|
|
5072
|
+
return this.users.find((u) => u.username === identifier || u.email === identifier);
|
|
5073
|
+
}
|
|
4365
5074
|
/**
|
|
4366
5075
|
* Read all users
|
|
4367
5076
|
* @returns Array of all users
|
|
@@ -4450,7 +5159,6 @@ var UserManager = class {
|
|
|
4450
5159
|
}
|
|
4451
5160
|
if (!user.wsIds.includes(wsId)) {
|
|
4452
5161
|
user.wsIds.push(wsId);
|
|
4453
|
-
this.hasChanged = true;
|
|
4454
5162
|
logger.debug(`WebSocket ID added to user ${username}: ${wsId}`);
|
|
4455
5163
|
}
|
|
4456
5164
|
return true;
|
|
@@ -4472,7 +5180,6 @@ var UserManager = class {
|
|
|
4472
5180
|
const initialLength = user.wsIds.length;
|
|
4473
5181
|
user.wsIds = user.wsIds.filter((id) => id !== wsId);
|
|
4474
5182
|
if (user.wsIds.length < initialLength) {
|
|
4475
|
-
this.hasChanged = true;
|
|
4476
5183
|
logger.debug(`WebSocket ID removed from user ${username}: ${wsId}`);
|
|
4477
5184
|
}
|
|
4478
5185
|
return true;
|
|
@@ -5022,6 +5729,9 @@ var SuperatomSDK = class {
|
|
|
5022
5729
|
this.maxReconnectAttempts = 5;
|
|
5023
5730
|
this.collections = {};
|
|
5024
5731
|
this.components = [];
|
|
5732
|
+
if (config.logLevel) {
|
|
5733
|
+
logger.setLogLevel(config.logLevel);
|
|
5734
|
+
}
|
|
5025
5735
|
this.apiKey = config.apiKey;
|
|
5026
5736
|
this.projectId = config.projectId;
|
|
5027
5737
|
this.userId = config.userId || "anonymous";
|
|
@@ -5325,6 +6035,7 @@ var SuperatomSDK = class {
|
|
|
5325
6035
|
ThreadManager,
|
|
5326
6036
|
UIBlock,
|
|
5327
6037
|
UILogCollector,
|
|
5328
|
-
UserManager
|
|
6038
|
+
UserManager,
|
|
6039
|
+
logger
|
|
5329
6040
|
});
|
|
5330
6041
|
//# sourceMappingURL=index.js.map
|