openloops 0.1.16 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/clients/llm-client.d.ts +2 -1
- package/dist/common/clients/llm-client.js +18 -12
- package/dist/common/clients/llm-client.mjs +18 -12
- package/dist/common/error/reportError.js +1 -1
- package/dist/common/error/reportError.mjs +1 -1
- package/dist/common/utils/secret-manager.js +8 -2
- package/dist/common/utils/secret-manager.mjs +8 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.mjs +1 -1
- package/dist/services/app/core/current-user.d.ts +1 -1
- package/dist/services/app/core/current-user.js +1 -1
- package/dist/services/app/core/current-user.mjs +1 -1
- package/package.json +24 -25
|
@@ -3,7 +3,8 @@ import type { KnownProvider, Message, AssistantMessage } from '@mariozechner/pi-
|
|
|
3
3
|
import { CurrentUser } from '../../services/app/core/index.js';
|
|
4
4
|
export declare class LLMClient {
|
|
5
5
|
private readonly logger;
|
|
6
|
-
private readonly langfuse
|
|
6
|
+
private readonly langfuse?;
|
|
7
|
+
private readonly langfuseEnabled;
|
|
7
8
|
constructor();
|
|
8
9
|
complete(params: LLMCompletionParams): Promise<AssistantMessage>;
|
|
9
10
|
private postResponse;
|
|
@@ -41,13 +41,19 @@ var import_create_llmcall = require("../../services/agent/modules/llmcalls/lambd
|
|
|
41
41
|
class LLMClient {
|
|
42
42
|
logger = new import_logger.Logger();
|
|
43
43
|
langfuse;
|
|
44
|
+
langfuseEnabled;
|
|
44
45
|
constructor() {
|
|
45
46
|
process.env.OPENAI_API_KEY = import_secret_manager.secretManager.get("OPENAI_API_KEY");
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const publicKey = import_secret_manager.secretManager.get("LANGFUSE_PUBLIC_KEY");
|
|
48
|
+
const secretKey = import_secret_manager.secretManager.get("LANGFUSE_SECRET_KEY");
|
|
49
|
+
const baseUrl = import_secret_manager.secretManager.get("LANGFUSE_BASE_URL");
|
|
50
|
+
this.langfuseEnabled = Boolean(publicKey && secretKey && baseUrl);
|
|
51
|
+
if (this.langfuseEnabled) {
|
|
52
|
+
this.langfuse = new import_langfuse.Langfuse({ publicKey, secretKey, baseUrl });
|
|
53
|
+
this.logger.debug("[LLM Service] Langfuse enabled");
|
|
54
|
+
} else {
|
|
55
|
+
this.logger.debug("[LLM Service] Langfuse disabled: configuration variables missing");
|
|
56
|
+
}
|
|
51
57
|
}
|
|
52
58
|
async complete(params) {
|
|
53
59
|
const { getModel, complete } = await import("@mariozechner/pi-ai");
|
|
@@ -74,7 +80,7 @@ class LLMClient {
|
|
|
74
80
|
messages: this.formatMessagesForLog(messages)
|
|
75
81
|
}
|
|
76
82
|
}, "[LLM Service] context");
|
|
77
|
-
const trace = this.langfuse.trace({
|
|
83
|
+
const trace = this.langfuseEnabled ? this.langfuse.trace({
|
|
78
84
|
sessionId,
|
|
79
85
|
name: taskName,
|
|
80
86
|
userId: currentUser?.userId,
|
|
@@ -83,8 +89,8 @@ class LLMClient {
|
|
|
83
89
|
email: currentUser?.email,
|
|
84
90
|
sessionId
|
|
85
91
|
}
|
|
86
|
-
});
|
|
87
|
-
const generation = trace
|
|
92
|
+
}) : void 0;
|
|
93
|
+
const generation = trace?.generation({
|
|
88
94
|
name: "llm-completion",
|
|
89
95
|
model: modelName,
|
|
90
96
|
modelParameters: { temperature, provider },
|
|
@@ -94,7 +100,7 @@ class LLMClient {
|
|
|
94
100
|
const response = await complete(model, context, {
|
|
95
101
|
temperature
|
|
96
102
|
});
|
|
97
|
-
generation
|
|
103
|
+
generation?.end({
|
|
98
104
|
output: response,
|
|
99
105
|
usage: response.usage ? {
|
|
100
106
|
promptTokens: response.usage.input,
|
|
@@ -102,7 +108,7 @@ class LLMClient {
|
|
|
102
108
|
totalTokens: response.usage.totalTokens
|
|
103
109
|
} : void 0
|
|
104
110
|
});
|
|
105
|
-
await this.langfuse.flushAsync();
|
|
111
|
+
if (this.langfuseEnabled) await this.langfuse.flushAsync();
|
|
106
112
|
this.logger.debug({
|
|
107
113
|
taskName,
|
|
108
114
|
response: {
|
|
@@ -113,11 +119,11 @@ class LLMClient {
|
|
|
113
119
|
await this.postResponse({ taskName, sessionId, answerId, currentUser, response });
|
|
114
120
|
return response;
|
|
115
121
|
} catch (error) {
|
|
116
|
-
generation
|
|
122
|
+
generation?.end({
|
|
117
123
|
level: "ERROR",
|
|
118
124
|
statusMessage: error.message
|
|
119
125
|
});
|
|
120
|
-
await this.langfuse.flushAsync();
|
|
126
|
+
if (this.langfuseEnabled) await this.langfuse.flushAsync();
|
|
121
127
|
throw error;
|
|
122
128
|
}
|
|
123
129
|
}
|
|
@@ -9,13 +9,19 @@ import { CreateLLMCallUseCase } from "../../services/agent/modules/llmcalls/lamb
|
|
|
9
9
|
class LLMClient {
|
|
10
10
|
logger = new Logger();
|
|
11
11
|
langfuse;
|
|
12
|
+
langfuseEnabled;
|
|
12
13
|
constructor() {
|
|
13
14
|
process.env.OPENAI_API_KEY = secretManager.get("OPENAI_API_KEY");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const publicKey = secretManager.get("LANGFUSE_PUBLIC_KEY");
|
|
16
|
+
const secretKey = secretManager.get("LANGFUSE_SECRET_KEY");
|
|
17
|
+
const baseUrl = secretManager.get("LANGFUSE_BASE_URL");
|
|
18
|
+
this.langfuseEnabled = Boolean(publicKey && secretKey && baseUrl);
|
|
19
|
+
if (this.langfuseEnabled) {
|
|
20
|
+
this.langfuse = new Langfuse({ publicKey, secretKey, baseUrl });
|
|
21
|
+
this.logger.debug("[LLM Service] Langfuse enabled");
|
|
22
|
+
} else {
|
|
23
|
+
this.logger.debug("[LLM Service] Langfuse disabled: configuration variables missing");
|
|
24
|
+
}
|
|
19
25
|
}
|
|
20
26
|
async complete(params) {
|
|
21
27
|
const { getModel, complete } = await import("@mariozechner/pi-ai");
|
|
@@ -42,7 +48,7 @@ class LLMClient {
|
|
|
42
48
|
messages: this.formatMessagesForLog(messages)
|
|
43
49
|
}
|
|
44
50
|
}, "[LLM Service] context");
|
|
45
|
-
const trace = this.langfuse.trace({
|
|
51
|
+
const trace = this.langfuseEnabled ? this.langfuse.trace({
|
|
46
52
|
sessionId,
|
|
47
53
|
name: taskName,
|
|
48
54
|
userId: currentUser?.userId,
|
|
@@ -51,8 +57,8 @@ class LLMClient {
|
|
|
51
57
|
email: currentUser?.email,
|
|
52
58
|
sessionId
|
|
53
59
|
}
|
|
54
|
-
});
|
|
55
|
-
const generation = trace
|
|
60
|
+
}) : void 0;
|
|
61
|
+
const generation = trace?.generation({
|
|
56
62
|
name: "llm-completion",
|
|
57
63
|
model: modelName,
|
|
58
64
|
modelParameters: { temperature, provider },
|
|
@@ -62,7 +68,7 @@ class LLMClient {
|
|
|
62
68
|
const response = await complete(model, context, {
|
|
63
69
|
temperature
|
|
64
70
|
});
|
|
65
|
-
generation
|
|
71
|
+
generation?.end({
|
|
66
72
|
output: response,
|
|
67
73
|
usage: response.usage ? {
|
|
68
74
|
promptTokens: response.usage.input,
|
|
@@ -70,7 +76,7 @@ class LLMClient {
|
|
|
70
76
|
totalTokens: response.usage.totalTokens
|
|
71
77
|
} : void 0
|
|
72
78
|
});
|
|
73
|
-
await this.langfuse.flushAsync();
|
|
79
|
+
if (this.langfuseEnabled) await this.langfuse.flushAsync();
|
|
74
80
|
this.logger.debug({
|
|
75
81
|
taskName,
|
|
76
82
|
response: {
|
|
@@ -81,11 +87,11 @@ class LLMClient {
|
|
|
81
87
|
await this.postResponse({ taskName, sessionId, answerId, currentUser, response });
|
|
82
88
|
return response;
|
|
83
89
|
} catch (error) {
|
|
84
|
-
generation
|
|
90
|
+
generation?.end({
|
|
85
91
|
level: "ERROR",
|
|
86
92
|
statusMessage: error.message
|
|
87
93
|
});
|
|
88
|
-
await this.langfuse.flushAsync();
|
|
94
|
+
if (this.langfuseEnabled) await this.langfuse.flushAsync();
|
|
89
95
|
throw error;
|
|
90
96
|
}
|
|
91
97
|
}
|
|
@@ -35,7 +35,7 @@ const reportError = async (error, details) => {
|
|
|
35
35
|
}, "[Report Error] Reporting new error");
|
|
36
36
|
const isLocal = process.env.IS_LOCAL === "true" || process.env.NODE_ENV === "development";
|
|
37
37
|
try {
|
|
38
|
-
!isLocal && await import_sentry_client.sentryClient
|
|
38
|
+
!isLocal && await import_sentry_client.sentryClient?.captureError(error, {
|
|
39
39
|
statusCode,
|
|
40
40
|
errorMessage,
|
|
41
41
|
errorDetails,
|
|
@@ -13,7 +13,7 @@ const reportError = async (error, details) => {
|
|
|
13
13
|
}, "[Report Error] Reporting new error");
|
|
14
14
|
const isLocal = process.env.IS_LOCAL === "true" || process.env.NODE_ENV === "development";
|
|
15
15
|
try {
|
|
16
|
-
!isLocal && await sentryClient
|
|
16
|
+
!isLocal && await sentryClient?.captureError(error, {
|
|
17
17
|
statusCode,
|
|
18
18
|
errorMessage,
|
|
19
19
|
errorDetails,
|
|
@@ -74,11 +74,17 @@ class SecretManager {
|
|
|
74
74
|
}
|
|
75
75
|
getEnvVar(key) {
|
|
76
76
|
const value = process.env[key];
|
|
77
|
-
if (!value)
|
|
77
|
+
if (!value) {
|
|
78
|
+
import_logger.logger.warn({ key }, "[Secret manager] Environment variable is not set");
|
|
79
|
+
return "";
|
|
80
|
+
}
|
|
78
81
|
return value;
|
|
79
82
|
}
|
|
80
83
|
decryptEnvVar(encryptedValue) {
|
|
81
|
-
if (!encryptedValue)
|
|
84
|
+
if (!encryptedValue) {
|
|
85
|
+
import_logger.logger.debug("[Secret manager] Encrypted value cannot be empty");
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
82
88
|
if (!this.isStringEncrypted(encryptedValue)) {
|
|
83
89
|
import_logger.logger.debug("[Secret Manager] Value is not encrypted");
|
|
84
90
|
return encryptedValue;
|
|
@@ -41,11 +41,17 @@ class SecretManager {
|
|
|
41
41
|
}
|
|
42
42
|
getEnvVar(key) {
|
|
43
43
|
const value = process.env[key];
|
|
44
|
-
if (!value)
|
|
44
|
+
if (!value) {
|
|
45
|
+
logger.warn({ key }, "[Secret manager] Environment variable is not set");
|
|
46
|
+
return "";
|
|
47
|
+
}
|
|
45
48
|
return value;
|
|
46
49
|
}
|
|
47
50
|
decryptEnvVar(encryptedValue) {
|
|
48
|
-
if (!encryptedValue)
|
|
51
|
+
if (!encryptedValue) {
|
|
52
|
+
logger.debug("[Secret manager] Encrypted value cannot be empty");
|
|
53
|
+
return "";
|
|
54
|
+
}
|
|
49
55
|
if (!this.isStringEncrypted(encryptedValue)) {
|
|
50
56
|
logger.debug("[Secret Manager] Value is not encrypted");
|
|
51
57
|
return encryptedValue;
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './services/agent/core
|
|
1
|
+
export * from './services/agent/core';
|
package/dist/index.js
CHANGED
|
@@ -15,8 +15,8 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
|
|
|
15
15
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
16
|
var index_exports = {};
|
|
17
17
|
module.exports = __toCommonJS(index_exports);
|
|
18
|
-
__reExport(index_exports, require("./services/agent/core
|
|
18
|
+
__reExport(index_exports, require("./services/agent/core"), module.exports);
|
|
19
19
|
// Annotate the CommonJS export names for ESM import in node:
|
|
20
20
|
0 && (module.exports = {
|
|
21
|
-
...require("./services/agent/core
|
|
21
|
+
...require("./services/agent/core")
|
|
22
22
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./services/agent/core
|
|
1
|
+
export * from "./services/agent/core";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { User, UserProps } from '../modules/users/entities/user.entity
|
|
1
|
+
import { User, UserProps } from '../modules/users/entities/user.entity';
|
|
2
2
|
export declare class CurrentUser extends User {
|
|
3
3
|
private _isPremium;
|
|
4
4
|
static asyncFromDB(userId: string): Promise<CurrentUser | undefined>;
|
|
@@ -26,7 +26,7 @@ var import_countries_and_currencies_utils = require("countries-and-currencies-ut
|
|
|
26
26
|
var import_mongo_db = require("../../../common/repositories/mongo-db.client.js");
|
|
27
27
|
var import_secret_manager = require("../../../common/utils/secret-manager.js");
|
|
28
28
|
var import_logger = require("../../../common/logger/index.js");
|
|
29
|
-
var import_user = require("../modules/users/entities/user.entity
|
|
29
|
+
var import_user = require("../modules/users/entities/user.entity");
|
|
30
30
|
class CurrentUser extends import_user.User {
|
|
31
31
|
_isPremium = false;
|
|
32
32
|
static async asyncFromDB(userId) {
|
|
@@ -4,7 +4,7 @@ import { getTimezoneOffset } from "countries-and-currencies-utils";
|
|
|
4
4
|
import { getMongoDBClient } from "../../../common/repositories/mongo-db.client.js";
|
|
5
5
|
import { secretManager } from "../../../common/utils/secret-manager.js";
|
|
6
6
|
import { logger } from "../../../common/logger/index.js";
|
|
7
|
-
import { User, UserRole } from "../modules/users/entities/user.entity
|
|
7
|
+
import { User, UserRole } from "../modules/users/entities/user.entity";
|
|
8
8
|
class CurrentUser extends User {
|
|
9
9
|
_isPremium = false;
|
|
10
10
|
static async asyncFromDB(userId) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openloops",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Framework to build AI Agents",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Jose Barcos",
|
|
@@ -51,48 +51,47 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@mariozechner/pi-ai": "^0.73.1",
|
|
54
|
-
"@modelcontextprotocol/sdk": "^1.30.
|
|
55
|
-
"@sentry/node": "^
|
|
56
|
-
"axios": "^1.
|
|
54
|
+
"@modelcontextprotocol/sdk": "^1.30.1",
|
|
55
|
+
"@sentry/node": "^11.0.0",
|
|
56
|
+
"axios": "^1.20.0",
|
|
57
57
|
"bcryptjs": "^3.0.3",
|
|
58
58
|
"countries-and-currencies-utils": "^0.1.9",
|
|
59
59
|
"cryptr": "^6.4.0",
|
|
60
60
|
"dotenv": "^18.0.3",
|
|
61
|
-
"html-to-text": "^10.0.
|
|
61
|
+
"html-to-text": "^10.0.1",
|
|
62
62
|
"jsonwebtoken": "^9.0.3",
|
|
63
|
-
"langfuse": "^3.
|
|
64
|
-
"mongodb": "^6.
|
|
65
|
-
"openai": "^
|
|
66
|
-
"p-limit": "^7.
|
|
67
|
-
"pino": "^10.1
|
|
63
|
+
"langfuse": "^3.39.2",
|
|
64
|
+
"mongodb": "^7.6.0",
|
|
65
|
+
"openai": "^7.23.0",
|
|
66
|
+
"p-limit": "^7.3.3",
|
|
67
|
+
"pino": "^10.3.1",
|
|
68
68
|
"pino-pretty": "^13.1.3",
|
|
69
69
|
"reflect-metadata": "^0.2.2",
|
|
70
|
-
"sanitize-html": "^2.17.
|
|
71
|
-
"source-map-support": "^0.5.21",
|
|
70
|
+
"sanitize-html": "^2.17.7",
|
|
72
71
|
"tsyringe": "^4.10.0"
|
|
73
72
|
},
|
|
74
73
|
"devDependencies": {
|
|
75
74
|
"@types/jest": "^30.0.0",
|
|
76
|
-
"@types/node": "^
|
|
77
|
-
"@types/sanitize-html": "^2.16.
|
|
78
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
79
|
-
"@typescript-eslint/parser": "^8.
|
|
80
|
-
"eslint": "^
|
|
75
|
+
"@types/node": "^26.6.2",
|
|
76
|
+
"@types/sanitize-html": "^2.16.1",
|
|
77
|
+
"@typescript-eslint/eslint-plugin": "^8.70.1",
|
|
78
|
+
"@typescript-eslint/parser": "^8.70.1",
|
|
79
|
+
"eslint": "^10.11.0",
|
|
81
80
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
82
81
|
"eslint-config-airbnb-typescript": "^18.0.0",
|
|
83
82
|
"eslint-config-prettier": "^10.1.8",
|
|
84
|
-
"eslint-import-resolver-typescript": "^4.4.
|
|
83
|
+
"eslint-import-resolver-typescript": "^4.4.5",
|
|
85
84
|
"eslint-plugin-import": "^2.32.0",
|
|
86
|
-
"eslint-plugin-jest": "^29.
|
|
87
|
-
"eslint-plugin-prettier": "^5.5.
|
|
88
|
-
"eslint-plugin-promise": "^7.
|
|
89
|
-
"jest": "^30.2
|
|
90
|
-
"prettier": "^3.
|
|
91
|
-
"ts-jest": "^29.4.
|
|
85
|
+
"eslint-plugin-jest": "^29.16.6",
|
|
86
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
87
|
+
"eslint-plugin-promise": "^7.3.0",
|
|
88
|
+
"jest": "^30.5.2",
|
|
89
|
+
"prettier": "^3.9.9",
|
|
90
|
+
"ts-jest": "^29.4.13",
|
|
92
91
|
"tsc-alias": "^1.9.5",
|
|
93
92
|
"tsconfig-paths": "^4.2.0",
|
|
94
93
|
"tsup": "^8.5.1",
|
|
95
|
-
"typescript": "^
|
|
94
|
+
"typescript": "^6.0.3"
|
|
96
95
|
},
|
|
97
96
|
"engines": {
|
|
98
97
|
"node": ">=22.0.0"
|