@eko-ai/eko 1.1.4 → 1.2.1
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/log.d.ts +2 -0
- package/dist/core/eko.d.ts +1 -0
- package/dist/extension/content/index.d.ts +1 -16
- package/dist/extension.cjs.js +778 -149
- package/dist/extension.esm.js +778 -149
- package/dist/extension_content_script.js +634 -6
- package/dist/index.cjs.js +787 -80
- package/dist/index.esm.js +787 -80
- package/dist/models/action.d.ts +1 -0
- package/dist/nodejs.cjs.js +712 -88
- package/dist/nodejs.esm.js +648 -24
- package/dist/types/action.types.d.ts +4 -0
- package/dist/types/eko.types.d.ts +6 -0
- package/dist/types/llm.types.d.ts +2 -0
- package/dist/web.cjs.js +651 -23
- package/dist/web.esm.js +651 -23
- package/package.json +5 -2
package/dist/nodejs.esm.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import require$$0$3, { hostname } from 'os';
|
|
2
|
+
import require$$1, { normalize, resolve } from 'path';
|
|
3
|
+
import require$$1$1, { types as types$2, formatWithOptions, promisify } from 'util';
|
|
1
4
|
import require$$2$2, { createInterface } from 'readline';
|
|
2
5
|
import require$$0$4, { exec } from 'child_process';
|
|
3
|
-
import require$$1$1, { promisify } from 'util';
|
|
4
6
|
import { readFile, access, appendFile, writeFile } from 'fs/promises';
|
|
5
|
-
import require$$1, { resolve } from 'path';
|
|
6
7
|
import require$$0$2, { constants } from 'fs';
|
|
7
8
|
import require$$0$5 from 'events';
|
|
8
9
|
import require$$8 from 'net';
|
|
9
10
|
import require$$5 from 'crypto';
|
|
10
|
-
import require$$0$3 from 'os';
|
|
11
11
|
import require$$2$1 from 'tty';
|
|
12
12
|
import require$$6 from 'url';
|
|
13
13
|
import require$$9 from 'tls';
|
|
@@ -23,6 +23,630 @@ import require$$1$2 from 'http2';
|
|
|
23
23
|
import require$$0$6 from 'async_hooks';
|
|
24
24
|
import require$$10$2 from 'inspector';
|
|
25
25
|
|
|
26
|
+
const prettyLogStyles = {
|
|
27
|
+
reset: [0, 0],
|
|
28
|
+
bold: [1, 22],
|
|
29
|
+
dim: [2, 22],
|
|
30
|
+
italic: [3, 23],
|
|
31
|
+
underline: [4, 24],
|
|
32
|
+
overline: [53, 55],
|
|
33
|
+
inverse: [7, 27],
|
|
34
|
+
hidden: [8, 28],
|
|
35
|
+
strikethrough: [9, 29],
|
|
36
|
+
black: [30, 39],
|
|
37
|
+
red: [31, 39],
|
|
38
|
+
green: [32, 39],
|
|
39
|
+
yellow: [33, 39],
|
|
40
|
+
blue: [34, 39],
|
|
41
|
+
magenta: [35, 39],
|
|
42
|
+
cyan: [36, 39],
|
|
43
|
+
white: [37, 39],
|
|
44
|
+
blackBright: [90, 39],
|
|
45
|
+
redBright: [91, 39],
|
|
46
|
+
greenBright: [92, 39],
|
|
47
|
+
yellowBright: [93, 39],
|
|
48
|
+
blueBright: [94, 39],
|
|
49
|
+
magentaBright: [95, 39],
|
|
50
|
+
cyanBright: [96, 39],
|
|
51
|
+
whiteBright: [97, 39],
|
|
52
|
+
bgBlack: [40, 49],
|
|
53
|
+
bgRed: [41, 49],
|
|
54
|
+
bgGreen: [42, 49],
|
|
55
|
+
bgYellow: [43, 49],
|
|
56
|
+
bgBlue: [44, 49],
|
|
57
|
+
bgMagenta: [45, 49],
|
|
58
|
+
bgCyan: [46, 49],
|
|
59
|
+
bgWhite: [47, 49],
|
|
60
|
+
bgBlackBright: [100, 49],
|
|
61
|
+
bgRedBright: [101, 49],
|
|
62
|
+
bgGreenBright: [102, 49],
|
|
63
|
+
bgYellowBright: [103, 49],
|
|
64
|
+
bgBlueBright: [104, 49],
|
|
65
|
+
bgMagentaBright: [105, 49],
|
|
66
|
+
bgCyanBright: [106, 49],
|
|
67
|
+
bgWhiteBright: [107, 49],
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function formatTemplate(settings, template, values, hideUnsetPlaceholder = false) {
|
|
71
|
+
const templateString = String(template);
|
|
72
|
+
const ansiColorWrap = (placeholderValue, code) => `\u001b[${code[0]}m${placeholderValue}\u001b[${code[1]}m`;
|
|
73
|
+
const styleWrap = (value, style) => {
|
|
74
|
+
if (style != null && typeof style === "string") {
|
|
75
|
+
return ansiColorWrap(value, prettyLogStyles[style]);
|
|
76
|
+
}
|
|
77
|
+
else if (style != null && Array.isArray(style)) {
|
|
78
|
+
return style.reduce((prevValue, thisStyle) => styleWrap(prevValue, thisStyle), value);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
if (style != null && style[value.trim()] != null) {
|
|
82
|
+
return styleWrap(value, style[value.trim()]);
|
|
83
|
+
}
|
|
84
|
+
else if (style != null && style["*"] != null) {
|
|
85
|
+
return styleWrap(value, style["*"]);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const defaultStyle = null;
|
|
93
|
+
return templateString.replace(/{{(.+?)}}/g, (_, placeholder) => {
|
|
94
|
+
const value = values[placeholder] != null ? String(values[placeholder]) : hideUnsetPlaceholder ? "" : _;
|
|
95
|
+
return settings.stylePrettyLogs
|
|
96
|
+
? styleWrap(value, settings?.prettyLogStyles?.[placeholder] ?? defaultStyle) + ansiColorWrap("", prettyLogStyles.reset)
|
|
97
|
+
: value;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function formatNumberAddZeros(value, digits = 2, addNumber = 0) {
|
|
102
|
+
if (value != null && isNaN(value)) {
|
|
103
|
+
return "";
|
|
104
|
+
}
|
|
105
|
+
value = value != null ? value + addNumber : value;
|
|
106
|
+
return digits === 2
|
|
107
|
+
? value == null
|
|
108
|
+
? "--"
|
|
109
|
+
: value < 10
|
|
110
|
+
? "0" + value
|
|
111
|
+
: value.toString()
|
|
112
|
+
: value == null
|
|
113
|
+
? "---"
|
|
114
|
+
: value < 10
|
|
115
|
+
? "00" + value
|
|
116
|
+
: value < 100
|
|
117
|
+
? "0" + value
|
|
118
|
+
: value.toString();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function urlToObject(url) {
|
|
122
|
+
return {
|
|
123
|
+
href: url.href,
|
|
124
|
+
protocol: url.protocol,
|
|
125
|
+
username: url.username,
|
|
126
|
+
password: url.password,
|
|
127
|
+
host: url.host,
|
|
128
|
+
hostname: url.hostname,
|
|
129
|
+
port: url.port,
|
|
130
|
+
pathname: url.pathname,
|
|
131
|
+
search: url.search,
|
|
132
|
+
searchParams: [...url.searchParams].map(([key, value]) => ({ key, value })),
|
|
133
|
+
hash: url.hash,
|
|
134
|
+
origin: url.origin,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
var Runtime = {
|
|
139
|
+
getCallerStackFrame,
|
|
140
|
+
getErrorTrace,
|
|
141
|
+
getMeta,
|
|
142
|
+
transportJSON,
|
|
143
|
+
transportFormatted: transportFormatted$1,
|
|
144
|
+
isBuffer,
|
|
145
|
+
isError,
|
|
146
|
+
prettyFormatLogObj,
|
|
147
|
+
prettyFormatErrorObj,
|
|
148
|
+
};
|
|
149
|
+
const meta = {
|
|
150
|
+
runtime: "Nodejs",
|
|
151
|
+
runtimeVersion: process?.version,
|
|
152
|
+
hostname: hostname ? hostname() : undefined,
|
|
153
|
+
};
|
|
154
|
+
function getMeta(logLevelId, logLevelName, stackDepthLevel, hideLogPositionForPerformance, name, parentNames) {
|
|
155
|
+
return Object.assign({}, meta, {
|
|
156
|
+
name,
|
|
157
|
+
parentNames,
|
|
158
|
+
date: new Date(),
|
|
159
|
+
logLevelId,
|
|
160
|
+
logLevelName,
|
|
161
|
+
path: !hideLogPositionForPerformance ? getCallerStackFrame(stackDepthLevel) : undefined,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function getCallerStackFrame(stackDepthLevel, error = Error()) {
|
|
165
|
+
return stackLineToStackFrame(error?.stack?.split("\n")?.filter((thisLine) => thisLine.includes(" at "))?.[stackDepthLevel]);
|
|
166
|
+
}
|
|
167
|
+
function getErrorTrace(error) {
|
|
168
|
+
return error?.stack?.split("\n")?.reduce((result, line) => {
|
|
169
|
+
if (line.includes(" at ")) {
|
|
170
|
+
result.push(stackLineToStackFrame(line));
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
}, []);
|
|
174
|
+
}
|
|
175
|
+
function stackLineToStackFrame(line) {
|
|
176
|
+
const pathResult = {
|
|
177
|
+
fullFilePath: undefined,
|
|
178
|
+
fileName: undefined,
|
|
179
|
+
fileNameWithLine: undefined,
|
|
180
|
+
fileColumn: undefined,
|
|
181
|
+
fileLine: undefined,
|
|
182
|
+
filePath: undefined,
|
|
183
|
+
filePathWithLine: undefined,
|
|
184
|
+
method: undefined,
|
|
185
|
+
};
|
|
186
|
+
if (line != null && line.includes(" at ")) {
|
|
187
|
+
line = line.replace(/^\s+at\s+/gm, "");
|
|
188
|
+
const errorStackLine = line.split(" (");
|
|
189
|
+
const fullFilePath = line?.slice(-1) === ")" ? line?.match(/\(([^)]+)\)/)?.[1] : line;
|
|
190
|
+
const pathArray = fullFilePath?.includes(":") ? fullFilePath?.replace("file://", "")?.replace(process.cwd(), "")?.split(":") : undefined;
|
|
191
|
+
const fileColumn = pathArray?.pop();
|
|
192
|
+
const fileLine = pathArray?.pop();
|
|
193
|
+
const filePath = pathArray?.pop();
|
|
194
|
+
const filePathWithLine = normalize(`${filePath}:${fileLine}`);
|
|
195
|
+
const fileName = filePath?.split("/")?.pop();
|
|
196
|
+
const fileNameWithLine = `${fileName}:${fileLine}`;
|
|
197
|
+
if (filePath != null && filePath.length > 0) {
|
|
198
|
+
pathResult.fullFilePath = fullFilePath;
|
|
199
|
+
pathResult.fileName = fileName;
|
|
200
|
+
pathResult.fileNameWithLine = fileNameWithLine;
|
|
201
|
+
pathResult.fileColumn = fileColumn;
|
|
202
|
+
pathResult.fileLine = fileLine;
|
|
203
|
+
pathResult.filePath = filePath;
|
|
204
|
+
pathResult.filePathWithLine = filePathWithLine;
|
|
205
|
+
pathResult.method = errorStackLine?.[1] != null ? errorStackLine?.[0] : undefined;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return pathResult;
|
|
209
|
+
}
|
|
210
|
+
function isError(e) {
|
|
211
|
+
return types$2?.isNativeError != null ? types$2.isNativeError(e) : e instanceof Error;
|
|
212
|
+
}
|
|
213
|
+
function prettyFormatLogObj(maskedArgs, settings) {
|
|
214
|
+
return maskedArgs.reduce((result, arg) => {
|
|
215
|
+
isError(arg) ? result.errors.push(prettyFormatErrorObj(arg, settings)) : result.args.push(arg);
|
|
216
|
+
return result;
|
|
217
|
+
}, { args: [], errors: [] });
|
|
218
|
+
}
|
|
219
|
+
function prettyFormatErrorObj(error, settings) {
|
|
220
|
+
const errorStackStr = getErrorTrace(error).map((stackFrame) => {
|
|
221
|
+
return formatTemplate(settings, settings.prettyErrorStackTemplate, { ...stackFrame }, true);
|
|
222
|
+
});
|
|
223
|
+
const placeholderValuesError = {
|
|
224
|
+
errorName: ` ${error.name} `,
|
|
225
|
+
errorMessage: Object.getOwnPropertyNames(error)
|
|
226
|
+
.reduce((result, key) => {
|
|
227
|
+
if (key !== "stack") {
|
|
228
|
+
result.push(error[key]);
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}, [])
|
|
232
|
+
.join(", "),
|
|
233
|
+
errorStack: errorStackStr.join("\n"),
|
|
234
|
+
};
|
|
235
|
+
return formatTemplate(settings, settings.prettyErrorTemplate, placeholderValuesError);
|
|
236
|
+
}
|
|
237
|
+
function transportFormatted$1(logMetaMarkup, logArgs, logErrors, settings) {
|
|
238
|
+
const logErrorsStr = (logErrors.length > 0 && logArgs.length > 0 ? "\n" : "") + logErrors.join("\n");
|
|
239
|
+
settings.prettyInspectOptions.colors = settings.stylePrettyLogs;
|
|
240
|
+
console.log(logMetaMarkup + formatWithOptions(settings.prettyInspectOptions, ...logArgs) + logErrorsStr);
|
|
241
|
+
}
|
|
242
|
+
function transportJSON(json) {
|
|
243
|
+
console.log(jsonStringifyRecursive(json));
|
|
244
|
+
function jsonStringifyRecursive(obj) {
|
|
245
|
+
const cache = new Set();
|
|
246
|
+
return JSON.stringify(obj, (key, value) => {
|
|
247
|
+
if (typeof value === "object" && value !== null) {
|
|
248
|
+
if (cache.has(value)) {
|
|
249
|
+
return "[Circular]";
|
|
250
|
+
}
|
|
251
|
+
cache.add(value);
|
|
252
|
+
}
|
|
253
|
+
if (typeof value === "bigint") {
|
|
254
|
+
return `${value}`;
|
|
255
|
+
}
|
|
256
|
+
if (typeof value === "undefined") {
|
|
257
|
+
return "[undefined]";
|
|
258
|
+
}
|
|
259
|
+
return value;
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function isBuffer(arg) {
|
|
264
|
+
return Buffer.isBuffer(arg);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
class BaseLogger {
|
|
268
|
+
constructor(settings, logObj, stackDepthLevel = 4) {
|
|
269
|
+
this.logObj = logObj;
|
|
270
|
+
this.stackDepthLevel = stackDepthLevel;
|
|
271
|
+
this.runtime = Runtime;
|
|
272
|
+
this.settings = {
|
|
273
|
+
type: settings?.type ?? "pretty",
|
|
274
|
+
name: settings?.name,
|
|
275
|
+
parentNames: settings?.parentNames,
|
|
276
|
+
minLevel: settings?.minLevel ?? 0,
|
|
277
|
+
argumentsArrayName: settings?.argumentsArrayName,
|
|
278
|
+
hideLogPositionForProduction: settings?.hideLogPositionForProduction ?? false,
|
|
279
|
+
prettyLogTemplate: settings?.prettyLogTemplate ??
|
|
280
|
+
"{{yyyy}}.{{mm}}.{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}\t{{logLevelName}}\t{{filePathWithLine}}{{nameWithDelimiterPrefix}}\t",
|
|
281
|
+
prettyErrorTemplate: settings?.prettyErrorTemplate ?? "\n{{errorName}} {{errorMessage}}\nerror stack:\n{{errorStack}}",
|
|
282
|
+
prettyErrorStackTemplate: settings?.prettyErrorStackTemplate ?? " • {{fileName}}\t{{method}}\n\t{{filePathWithLine}}",
|
|
283
|
+
prettyErrorParentNamesSeparator: settings?.prettyErrorParentNamesSeparator ?? ":",
|
|
284
|
+
prettyErrorLoggerNameDelimiter: settings?.prettyErrorLoggerNameDelimiter ?? "\t",
|
|
285
|
+
stylePrettyLogs: settings?.stylePrettyLogs ?? true,
|
|
286
|
+
prettyLogTimeZone: settings?.prettyLogTimeZone ?? "UTC",
|
|
287
|
+
prettyLogStyles: settings?.prettyLogStyles ?? {
|
|
288
|
+
logLevelName: {
|
|
289
|
+
"*": ["bold", "black", "bgWhiteBright", "dim"],
|
|
290
|
+
SILLY: ["bold", "white"],
|
|
291
|
+
TRACE: ["bold", "whiteBright"],
|
|
292
|
+
DEBUG: ["bold", "green"],
|
|
293
|
+
INFO: ["bold", "blue"],
|
|
294
|
+
WARN: ["bold", "yellow"],
|
|
295
|
+
ERROR: ["bold", "red"],
|
|
296
|
+
FATAL: ["bold", "redBright"],
|
|
297
|
+
},
|
|
298
|
+
dateIsoStr: "white",
|
|
299
|
+
filePathWithLine: "white",
|
|
300
|
+
name: ["white", "bold"],
|
|
301
|
+
nameWithDelimiterPrefix: ["white", "bold"],
|
|
302
|
+
nameWithDelimiterSuffix: ["white", "bold"],
|
|
303
|
+
errorName: ["bold", "bgRedBright", "whiteBright"],
|
|
304
|
+
fileName: ["yellow"],
|
|
305
|
+
fileNameWithLine: "white",
|
|
306
|
+
},
|
|
307
|
+
prettyInspectOptions: settings?.prettyInspectOptions ?? {
|
|
308
|
+
colors: true,
|
|
309
|
+
compact: false,
|
|
310
|
+
depth: Infinity,
|
|
311
|
+
},
|
|
312
|
+
metaProperty: settings?.metaProperty ?? "_meta",
|
|
313
|
+
maskPlaceholder: settings?.maskPlaceholder ?? "[***]",
|
|
314
|
+
maskValuesOfKeys: settings?.maskValuesOfKeys ?? ["password"],
|
|
315
|
+
maskValuesOfKeysCaseInsensitive: settings?.maskValuesOfKeysCaseInsensitive ?? false,
|
|
316
|
+
maskValuesRegEx: settings?.maskValuesRegEx,
|
|
317
|
+
prefix: [...(settings?.prefix ?? [])],
|
|
318
|
+
attachedTransports: [...(settings?.attachedTransports ?? [])],
|
|
319
|
+
overwrite: {
|
|
320
|
+
mask: settings?.overwrite?.mask,
|
|
321
|
+
toLogObj: settings?.overwrite?.toLogObj,
|
|
322
|
+
addMeta: settings?.overwrite?.addMeta,
|
|
323
|
+
addPlaceholders: settings?.overwrite?.addPlaceholders,
|
|
324
|
+
formatMeta: settings?.overwrite?.formatMeta,
|
|
325
|
+
formatLogObj: settings?.overwrite?.formatLogObj,
|
|
326
|
+
transportFormatted: settings?.overwrite?.transportFormatted,
|
|
327
|
+
transportJSON: settings?.overwrite?.transportJSON,
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
log(logLevelId, logLevelName, ...args) {
|
|
332
|
+
if (logLevelId < this.settings.minLevel) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const logArgs = [...this.settings.prefix, ...args];
|
|
336
|
+
const maskedArgs = this.settings.overwrite?.mask != null
|
|
337
|
+
? this.settings.overwrite?.mask(logArgs)
|
|
338
|
+
: this.settings.maskValuesOfKeys != null && this.settings.maskValuesOfKeys.length > 0
|
|
339
|
+
? this._mask(logArgs)
|
|
340
|
+
: logArgs;
|
|
341
|
+
const thisLogObj = this.logObj != null ? this._recursiveCloneAndExecuteFunctions(this.logObj) : undefined;
|
|
342
|
+
const logObj = this.settings.overwrite?.toLogObj != null ? this.settings.overwrite?.toLogObj(maskedArgs, thisLogObj) : this._toLogObj(maskedArgs, thisLogObj);
|
|
343
|
+
const logObjWithMeta = this.settings.overwrite?.addMeta != null
|
|
344
|
+
? this.settings.overwrite?.addMeta(logObj, logLevelId, logLevelName)
|
|
345
|
+
: this._addMetaToLogObj(logObj, logLevelId, logLevelName);
|
|
346
|
+
let logMetaMarkup;
|
|
347
|
+
let logArgsAndErrorsMarkup = undefined;
|
|
348
|
+
if (this.settings.overwrite?.formatMeta != null) {
|
|
349
|
+
logMetaMarkup = this.settings.overwrite?.formatMeta(logObjWithMeta?.[this.settings.metaProperty]);
|
|
350
|
+
}
|
|
351
|
+
if (this.settings.overwrite?.formatLogObj != null) {
|
|
352
|
+
logArgsAndErrorsMarkup = this.settings.overwrite?.formatLogObj(maskedArgs, this.settings);
|
|
353
|
+
}
|
|
354
|
+
if (this.settings.type === "pretty") {
|
|
355
|
+
logMetaMarkup = logMetaMarkup ?? this._prettyFormatLogObjMeta(logObjWithMeta?.[this.settings.metaProperty]);
|
|
356
|
+
logArgsAndErrorsMarkup = logArgsAndErrorsMarkup ?? this.runtime.prettyFormatLogObj(maskedArgs, this.settings);
|
|
357
|
+
}
|
|
358
|
+
if (logMetaMarkup != null && logArgsAndErrorsMarkup != null) {
|
|
359
|
+
this.settings.overwrite?.transportFormatted != null
|
|
360
|
+
? this.settings.overwrite?.transportFormatted(logMetaMarkup, logArgsAndErrorsMarkup.args, logArgsAndErrorsMarkup.errors, this.settings)
|
|
361
|
+
: this.runtime.transportFormatted(logMetaMarkup, logArgsAndErrorsMarkup.args, logArgsAndErrorsMarkup.errors, this.settings);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
this.settings.overwrite?.transportJSON != null
|
|
365
|
+
? this.settings.overwrite?.transportJSON(logObjWithMeta)
|
|
366
|
+
: this.settings.type !== "hidden"
|
|
367
|
+
? this.runtime.transportJSON(logObjWithMeta)
|
|
368
|
+
: undefined;
|
|
369
|
+
}
|
|
370
|
+
if (this.settings.attachedTransports != null && this.settings.attachedTransports.length > 0) {
|
|
371
|
+
this.settings.attachedTransports.forEach((transportLogger) => {
|
|
372
|
+
transportLogger(logObjWithMeta);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
return logObjWithMeta;
|
|
376
|
+
}
|
|
377
|
+
attachTransport(transportLogger) {
|
|
378
|
+
this.settings.attachedTransports.push(transportLogger);
|
|
379
|
+
}
|
|
380
|
+
getSubLogger(settings, logObj) {
|
|
381
|
+
const subLoggerSettings = {
|
|
382
|
+
...this.settings,
|
|
383
|
+
...settings,
|
|
384
|
+
parentNames: this.settings?.parentNames != null && this.settings?.name != null
|
|
385
|
+
? [...this.settings.parentNames, this.settings.name]
|
|
386
|
+
: this.settings?.name != null
|
|
387
|
+
? [this.settings.name]
|
|
388
|
+
: undefined,
|
|
389
|
+
prefix: [...this.settings.prefix, ...(settings?.prefix ?? [])],
|
|
390
|
+
};
|
|
391
|
+
const subLogger = new this.constructor(subLoggerSettings, logObj ?? this.logObj, this.stackDepthLevel);
|
|
392
|
+
return subLogger;
|
|
393
|
+
}
|
|
394
|
+
_mask(args) {
|
|
395
|
+
const maskValuesOfKeys = this.settings.maskValuesOfKeysCaseInsensitive !== true ? this.settings.maskValuesOfKeys : this.settings.maskValuesOfKeys.map((key) => key.toLowerCase());
|
|
396
|
+
return args?.map((arg) => {
|
|
397
|
+
return this._recursiveCloneAndMaskValuesOfKeys(arg, maskValuesOfKeys);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
_recursiveCloneAndMaskValuesOfKeys(source, keys, seen = []) {
|
|
401
|
+
if (seen.includes(source)) {
|
|
402
|
+
return { ...source };
|
|
403
|
+
}
|
|
404
|
+
if (typeof source === "object" && source !== null) {
|
|
405
|
+
seen.push(source);
|
|
406
|
+
}
|
|
407
|
+
if (this.runtime.isError(source) || this.runtime.isBuffer(source)) {
|
|
408
|
+
return source;
|
|
409
|
+
}
|
|
410
|
+
else if (source instanceof Map) {
|
|
411
|
+
return new Map(source);
|
|
412
|
+
}
|
|
413
|
+
else if (source instanceof Set) {
|
|
414
|
+
return new Set(source);
|
|
415
|
+
}
|
|
416
|
+
else if (Array.isArray(source)) {
|
|
417
|
+
return source.map((item) => this._recursiveCloneAndMaskValuesOfKeys(item, keys, seen));
|
|
418
|
+
}
|
|
419
|
+
else if (source instanceof Date) {
|
|
420
|
+
return new Date(source.getTime());
|
|
421
|
+
}
|
|
422
|
+
else if (source instanceof URL) {
|
|
423
|
+
return urlToObject(source);
|
|
424
|
+
}
|
|
425
|
+
else if (source !== null && typeof source === "object") {
|
|
426
|
+
const baseObject = this.runtime.isError(source) ? this._cloneError(source) : Object.create(Object.getPrototypeOf(source));
|
|
427
|
+
return Object.getOwnPropertyNames(source).reduce((o, prop) => {
|
|
428
|
+
o[prop] = keys.includes(this.settings?.maskValuesOfKeysCaseInsensitive !== true ? prop : prop.toLowerCase())
|
|
429
|
+
? this.settings.maskPlaceholder
|
|
430
|
+
: (() => {
|
|
431
|
+
try {
|
|
432
|
+
return this._recursiveCloneAndMaskValuesOfKeys(source[prop], keys, seen);
|
|
433
|
+
}
|
|
434
|
+
catch (e) {
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
})();
|
|
438
|
+
return o;
|
|
439
|
+
}, baseObject);
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
if (typeof source === "string") {
|
|
443
|
+
let modifiedSource = source;
|
|
444
|
+
for (const regEx of this.settings?.maskValuesRegEx || []) {
|
|
445
|
+
modifiedSource = modifiedSource.replace(regEx, this.settings?.maskPlaceholder || "");
|
|
446
|
+
}
|
|
447
|
+
return modifiedSource;
|
|
448
|
+
}
|
|
449
|
+
return source;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
_recursiveCloneAndExecuteFunctions(source, seen = []) {
|
|
453
|
+
if (this.isObjectOrArray(source) && seen.includes(source)) {
|
|
454
|
+
return this.shallowCopy(source);
|
|
455
|
+
}
|
|
456
|
+
if (this.isObjectOrArray(source)) {
|
|
457
|
+
seen.push(source);
|
|
458
|
+
}
|
|
459
|
+
if (Array.isArray(source)) {
|
|
460
|
+
return source.map((item) => this._recursiveCloneAndExecuteFunctions(item, seen));
|
|
461
|
+
}
|
|
462
|
+
else if (source instanceof Date) {
|
|
463
|
+
return new Date(source.getTime());
|
|
464
|
+
}
|
|
465
|
+
else if (this.isObject(source)) {
|
|
466
|
+
return Object.getOwnPropertyNames(source).reduce((o, prop) => {
|
|
467
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, prop);
|
|
468
|
+
if (descriptor) {
|
|
469
|
+
Object.defineProperty(o, prop, descriptor);
|
|
470
|
+
const value = source[prop];
|
|
471
|
+
o[prop] = typeof value === "function" ? value() : this._recursiveCloneAndExecuteFunctions(value, seen);
|
|
472
|
+
}
|
|
473
|
+
return o;
|
|
474
|
+
}, Object.create(Object.getPrototypeOf(source)));
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
return source;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
isObjectOrArray(value) {
|
|
481
|
+
return typeof value === "object" && value !== null;
|
|
482
|
+
}
|
|
483
|
+
isObject(value) {
|
|
484
|
+
return typeof value === "object" && !Array.isArray(value) && value !== null;
|
|
485
|
+
}
|
|
486
|
+
shallowCopy(source) {
|
|
487
|
+
if (Array.isArray(source)) {
|
|
488
|
+
return [...source];
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
return { ...source };
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
_toLogObj(args, clonedLogObj = {}) {
|
|
495
|
+
args = args?.map((arg) => (this.runtime.isError(arg) ? this._toErrorObject(arg) : arg));
|
|
496
|
+
if (this.settings.argumentsArrayName == null) {
|
|
497
|
+
if (args.length === 1 && !Array.isArray(args[0]) && this.runtime.isBuffer(args[0]) !== true && !(args[0] instanceof Date)) {
|
|
498
|
+
clonedLogObj = typeof args[0] === "object" && args[0] != null ? { ...args[0], ...clonedLogObj } : { 0: args[0], ...clonedLogObj };
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
clonedLogObj = { ...clonedLogObj, ...args };
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
clonedLogObj = {
|
|
506
|
+
...clonedLogObj,
|
|
507
|
+
[this.settings.argumentsArrayName]: args,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
return clonedLogObj;
|
|
511
|
+
}
|
|
512
|
+
_cloneError(error) {
|
|
513
|
+
const cloned = new error.constructor();
|
|
514
|
+
Object.getOwnPropertyNames(error).forEach((key) => {
|
|
515
|
+
cloned[key] = error[key];
|
|
516
|
+
});
|
|
517
|
+
return cloned;
|
|
518
|
+
}
|
|
519
|
+
_toErrorObject(error) {
|
|
520
|
+
return {
|
|
521
|
+
nativeError: error,
|
|
522
|
+
name: error.name ?? "Error",
|
|
523
|
+
message: error.message,
|
|
524
|
+
stack: this.runtime.getErrorTrace(error),
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
_addMetaToLogObj(logObj, logLevelId, logLevelName) {
|
|
528
|
+
return {
|
|
529
|
+
...logObj,
|
|
530
|
+
[this.settings.metaProperty]: this.runtime.getMeta(logLevelId, logLevelName, this.stackDepthLevel, this.settings.hideLogPositionForProduction, this.settings.name, this.settings.parentNames),
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
_prettyFormatLogObjMeta(logObjMeta) {
|
|
534
|
+
if (logObjMeta == null) {
|
|
535
|
+
return "";
|
|
536
|
+
}
|
|
537
|
+
let template = this.settings.prettyLogTemplate;
|
|
538
|
+
const placeholderValues = {};
|
|
539
|
+
if (template.includes("{{yyyy}}.{{mm}}.{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}")) {
|
|
540
|
+
template = template.replace("{{yyyy}}.{{mm}}.{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}", "{{dateIsoStr}}");
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
if (this.settings.prettyLogTimeZone === "UTC") {
|
|
544
|
+
placeholderValues["yyyy"] = logObjMeta?.date?.getUTCFullYear() ?? "----";
|
|
545
|
+
placeholderValues["mm"] = formatNumberAddZeros(logObjMeta?.date?.getUTCMonth(), 2, 1);
|
|
546
|
+
placeholderValues["dd"] = formatNumberAddZeros(logObjMeta?.date?.getUTCDate(), 2);
|
|
547
|
+
placeholderValues["hh"] = formatNumberAddZeros(logObjMeta?.date?.getUTCHours(), 2);
|
|
548
|
+
placeholderValues["MM"] = formatNumberAddZeros(logObjMeta?.date?.getUTCMinutes(), 2);
|
|
549
|
+
placeholderValues["ss"] = formatNumberAddZeros(logObjMeta?.date?.getUTCSeconds(), 2);
|
|
550
|
+
placeholderValues["ms"] = formatNumberAddZeros(logObjMeta?.date?.getUTCMilliseconds(), 3);
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
placeholderValues["yyyy"] = logObjMeta?.date?.getFullYear() ?? "----";
|
|
554
|
+
placeholderValues["mm"] = formatNumberAddZeros(logObjMeta?.date?.getMonth(), 2, 1);
|
|
555
|
+
placeholderValues["dd"] = formatNumberAddZeros(logObjMeta?.date?.getDate(), 2);
|
|
556
|
+
placeholderValues["hh"] = formatNumberAddZeros(logObjMeta?.date?.getHours(), 2);
|
|
557
|
+
placeholderValues["MM"] = formatNumberAddZeros(logObjMeta?.date?.getMinutes(), 2);
|
|
558
|
+
placeholderValues["ss"] = formatNumberAddZeros(logObjMeta?.date?.getSeconds(), 2);
|
|
559
|
+
placeholderValues["ms"] = formatNumberAddZeros(logObjMeta?.date?.getMilliseconds(), 3);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
const dateInSettingsTimeZone = this.settings.prettyLogTimeZone === "UTC" ? logObjMeta?.date : new Date(logObjMeta?.date?.getTime() - logObjMeta?.date?.getTimezoneOffset() * 60000);
|
|
563
|
+
placeholderValues["rawIsoStr"] = dateInSettingsTimeZone?.toISOString();
|
|
564
|
+
placeholderValues["dateIsoStr"] = dateInSettingsTimeZone?.toISOString().replace("T", " ").replace("Z", "");
|
|
565
|
+
placeholderValues["logLevelName"] = logObjMeta?.logLevelName;
|
|
566
|
+
placeholderValues["fileNameWithLine"] = logObjMeta?.path?.fileNameWithLine ?? "";
|
|
567
|
+
placeholderValues["filePathWithLine"] = logObjMeta?.path?.filePathWithLine ?? "";
|
|
568
|
+
placeholderValues["fullFilePath"] = logObjMeta?.path?.fullFilePath ?? "";
|
|
569
|
+
let parentNamesString = this.settings.parentNames?.join(this.settings.prettyErrorParentNamesSeparator);
|
|
570
|
+
parentNamesString = parentNamesString != null && logObjMeta?.name != null ? parentNamesString + this.settings.prettyErrorParentNamesSeparator : undefined;
|
|
571
|
+
placeholderValues["name"] = logObjMeta?.name != null || parentNamesString != null ? (parentNamesString ?? "") + logObjMeta?.name ?? "" : "";
|
|
572
|
+
placeholderValues["nameWithDelimiterPrefix"] =
|
|
573
|
+
placeholderValues["name"].length > 0 ? this.settings.prettyErrorLoggerNameDelimiter + placeholderValues["name"] : "";
|
|
574
|
+
placeholderValues["nameWithDelimiterSuffix"] =
|
|
575
|
+
placeholderValues["name"].length > 0 ? placeholderValues["name"] + this.settings.prettyErrorLoggerNameDelimiter : "";
|
|
576
|
+
if (this.settings.overwrite?.addPlaceholders != null) {
|
|
577
|
+
this.settings.overwrite?.addPlaceholders(logObjMeta, placeholderValues);
|
|
578
|
+
}
|
|
579
|
+
return formatTemplate(this.settings, template, placeholderValues);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
class Logger extends BaseLogger {
|
|
584
|
+
constructor(settings, logObj) {
|
|
585
|
+
const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
|
|
586
|
+
const isBrowserBlinkEngine = isBrowser ? window.chrome !== undefined && window.CSS !== undefined && window.CSS.supports("color", "green") : false;
|
|
587
|
+
const isSafari = isBrowser ? /^((?!chrome|android).)*safari/i.test(navigator.userAgent) : false;
|
|
588
|
+
settings = settings || {};
|
|
589
|
+
settings.stylePrettyLogs = settings.stylePrettyLogs && isBrowser && !isBrowserBlinkEngine ? false : settings.stylePrettyLogs;
|
|
590
|
+
super(settings, logObj, isSafari ? 4 : 5);
|
|
591
|
+
}
|
|
592
|
+
log(logLevelId, logLevelName, ...args) {
|
|
593
|
+
return super.log(logLevelId, logLevelName, ...args);
|
|
594
|
+
}
|
|
595
|
+
silly(...args) {
|
|
596
|
+
return super.log(0, "SILLY", ...args);
|
|
597
|
+
}
|
|
598
|
+
trace(...args) {
|
|
599
|
+
return super.log(1, "TRACE", ...args);
|
|
600
|
+
}
|
|
601
|
+
debug(...args) {
|
|
602
|
+
return super.log(2, "DEBUG", ...args);
|
|
603
|
+
}
|
|
604
|
+
info(...args) {
|
|
605
|
+
return super.log(3, "INFO", ...args);
|
|
606
|
+
}
|
|
607
|
+
warn(...args) {
|
|
608
|
+
return super.log(4, "WARN", ...args);
|
|
609
|
+
}
|
|
610
|
+
error(...args) {
|
|
611
|
+
return super.log(5, "ERROR", ...args);
|
|
612
|
+
}
|
|
613
|
+
fatal(...args) {
|
|
614
|
+
return super.log(6, "FATAL", ...args);
|
|
615
|
+
}
|
|
616
|
+
getSubLogger(settings, logObj) {
|
|
617
|
+
return super.getSubLogger(settings, logObj);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function transportFormatted(logMetaMarkup, logArgs, logErrors, settings) {
|
|
622
|
+
const logErrorsStr = (logErrors.length > 0 && logArgs.length > 0 ? "\n" : "") + logErrors.join("\n");
|
|
623
|
+
settings.prettyInspectOptions.colors = settings.stylePrettyLogs;
|
|
624
|
+
console.log(logMetaMarkup, ...logArgs, logErrorsStr);
|
|
625
|
+
}
|
|
626
|
+
function formatMeta(logObjMeta) {
|
|
627
|
+
if (!logObjMeta) {
|
|
628
|
+
return '';
|
|
629
|
+
}
|
|
630
|
+
const { date, logLevelName } = logObjMeta;
|
|
631
|
+
const year = date.getFullYear();
|
|
632
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
633
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
634
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
|
635
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
636
|
+
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
637
|
+
const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
|
|
638
|
+
const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`;
|
|
639
|
+
const loggerName = logObjMeta.name;
|
|
640
|
+
return `${formattedDate} ${logLevelName} ${loggerName}`;
|
|
641
|
+
}
|
|
642
|
+
const logger = new Logger({
|
|
643
|
+
name: "ekoLogger",
|
|
644
|
+
overwrite: {
|
|
645
|
+
transportFormatted,
|
|
646
|
+
formatMeta,
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
|
|
26
650
|
class CancelWorkflow {
|
|
27
651
|
constructor() {
|
|
28
652
|
this.name = 'cancel_workflow';
|
|
@@ -44,7 +668,7 @@ class CancelWorkflow {
|
|
|
44
668
|
throw new Error('Invalid parameters. Expected an object with a "reason" property.');
|
|
45
669
|
}
|
|
46
670
|
const reason = params.reason;
|
|
47
|
-
|
|
671
|
+
logger.info("The workflow has been cancelled because: " + reason);
|
|
48
672
|
await ((_a = context.workflow) === null || _a === void 0 ? void 0 : _a.cancel());
|
|
49
673
|
return;
|
|
50
674
|
}
|
|
@@ -71,7 +695,7 @@ class HumanInputText {
|
|
|
71
695
|
throw new Error('Invalid parameters. Expected an object with a "question" property.');
|
|
72
696
|
}
|
|
73
697
|
const question = params.question;
|
|
74
|
-
|
|
698
|
+
logger.debug("question: " + question);
|
|
75
699
|
let onHumanInputText = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks.onHumanInputText;
|
|
76
700
|
if (onHumanInputText) {
|
|
77
701
|
let answer;
|
|
@@ -79,14 +703,14 @@ class HumanInputText {
|
|
|
79
703
|
answer = await onHumanInputText(question);
|
|
80
704
|
}
|
|
81
705
|
catch (e) {
|
|
82
|
-
|
|
706
|
+
logger.warn(e);
|
|
83
707
|
return { status: "Error: Cannot get user's answer.", answer: "" };
|
|
84
708
|
}
|
|
85
|
-
|
|
709
|
+
logger.debug("answer: " + answer);
|
|
86
710
|
return { status: "OK", answer: answer };
|
|
87
711
|
}
|
|
88
712
|
else {
|
|
89
|
-
|
|
713
|
+
logger.error("`onHumanInputText` not implemented");
|
|
90
714
|
return { status: "Error: Cannot get user's answer.", answer: "" };
|
|
91
715
|
}
|
|
92
716
|
}
|
|
@@ -125,8 +749,8 @@ class HumanInputSingleChoice {
|
|
|
125
749
|
}
|
|
126
750
|
const question = params.question;
|
|
127
751
|
const choices = params.choices.map((e) => e.choice);
|
|
128
|
-
|
|
129
|
-
|
|
752
|
+
logger.debug("question: " + question);
|
|
753
|
+
logger.debug("choices: " + choices);
|
|
130
754
|
let onHumanInputSingleChoice = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks.onHumanInputSingleChoice;
|
|
131
755
|
if (onHumanInputSingleChoice) {
|
|
132
756
|
let answer;
|
|
@@ -134,14 +758,14 @@ class HumanInputSingleChoice {
|
|
|
134
758
|
answer = await onHumanInputSingleChoice(question, choices);
|
|
135
759
|
}
|
|
136
760
|
catch (e) {
|
|
137
|
-
|
|
761
|
+
logger.warn(e);
|
|
138
762
|
return { status: "Error: Cannot get user's answer.", answer: "" };
|
|
139
763
|
}
|
|
140
|
-
|
|
764
|
+
logger.debug("answer: " + answer);
|
|
141
765
|
return { status: "OK", answer: answer };
|
|
142
766
|
}
|
|
143
767
|
else {
|
|
144
|
-
|
|
768
|
+
logger.error("`onHumanInputSingleChoice` not implemented");
|
|
145
769
|
return { status: "Error: Cannot get user's answer.", answer: "" };
|
|
146
770
|
}
|
|
147
771
|
}
|
|
@@ -180,8 +804,8 @@ class HumanInputMultipleChoice {
|
|
|
180
804
|
}
|
|
181
805
|
const question = params.question;
|
|
182
806
|
const choices = params.choices.map((e) => e.choice);
|
|
183
|
-
|
|
184
|
-
|
|
807
|
+
logger.debug("question: " + question);
|
|
808
|
+
logger.debug("choices: " + choices);
|
|
185
809
|
let onHumanInputMultipleChoice = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks.onHumanInputMultipleChoice;
|
|
186
810
|
if (onHumanInputMultipleChoice) {
|
|
187
811
|
let answer;
|
|
@@ -189,14 +813,14 @@ class HumanInputMultipleChoice {
|
|
|
189
813
|
answer = await onHumanInputMultipleChoice(question, choices);
|
|
190
814
|
}
|
|
191
815
|
catch (e) {
|
|
192
|
-
|
|
193
|
-
return { status: "
|
|
816
|
+
logger.warn(e);
|
|
817
|
+
return { status: "Error: Cannot get user's answer.", answer: [] };
|
|
194
818
|
}
|
|
195
|
-
|
|
819
|
+
logger.debug("answer: " + answer);
|
|
196
820
|
return { status: "OK", answer: answer };
|
|
197
821
|
}
|
|
198
822
|
else {
|
|
199
|
-
|
|
823
|
+
logger.error("`onHumanInputMultipleChoice` not implemented");
|
|
200
824
|
return { status: "Error: Cannot get user's answer.", answer: [] };
|
|
201
825
|
}
|
|
202
826
|
}
|
|
@@ -230,7 +854,7 @@ When calling this tool to transfer control to the user, please explain in detail
|
|
|
230
854
|
throw new Error('Invalid parameters. Expected an object with a "reason" property.');
|
|
231
855
|
}
|
|
232
856
|
const reason = params.reason;
|
|
233
|
-
|
|
857
|
+
logger.debug("reason: " + reason);
|
|
234
858
|
let onHumanOperate = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks.onHumanOperate;
|
|
235
859
|
if (onHumanOperate) {
|
|
236
860
|
let userOperation;
|
|
@@ -238,10 +862,10 @@ When calling this tool to transfer control to the user, please explain in detail
|
|
|
238
862
|
userOperation = await onHumanOperate(reason);
|
|
239
863
|
}
|
|
240
864
|
catch (e) {
|
|
241
|
-
|
|
242
|
-
return { status: "
|
|
865
|
+
logger.warn(e);
|
|
866
|
+
return { status: "Error: Cannot get user's operation.", userOperation: "" };
|
|
243
867
|
}
|
|
244
|
-
|
|
868
|
+
logger.debug("userOperation: " + userOperation);
|
|
245
869
|
if (userOperation == "") {
|
|
246
870
|
return { status: "OK", userOperation: "Done. Please take a screenshot to ensure the result." };
|
|
247
871
|
}
|
|
@@ -250,7 +874,7 @@ When calling this tool to transfer control to the user, please explain in detail
|
|
|
250
874
|
}
|
|
251
875
|
}
|
|
252
876
|
else {
|
|
253
|
-
|
|
877
|
+
logger.error("`onHumanOperate` not implemented");
|
|
254
878
|
return { status: "Error: Cannot get user's operation.", userOperation: "" };
|
|
255
879
|
}
|
|
256
880
|
}
|