codeaura-embedded-runtime-agent 0.1.0

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.
@@ -0,0 +1,111 @@
1
+
2
+ const EventSchema = require("../../../core/events/EventSchema"),
3
+ sanitizeInputs = require("../../../utils/sanitizeInputs"),
4
+ executionContext = require("../../../utils/executionContext");
5
+
6
+ function createEvent(functionName, functionType, durationMs, executionId, args, result, error, controllerExecutionIdOverride, parentExecutionIdOverride) {
7
+ let meta = null,
8
+ inputs = null,
9
+ output = null,
10
+ req = null,
11
+ allParams = null,
12
+ path = null,
13
+ name = null,
14
+ lastSlashIndex = -1,
15
+ controllerExecutionId = null,
16
+ parentExecutionId = null;
17
+
18
+ meta = {
19
+ executionId,
20
+ argumentCount: args ? args.length : 0
21
+ };
22
+
23
+ path = functionName;
24
+ lastSlashIndex = functionName.lastIndexOf("/");
25
+
26
+ if (lastSlashIndex !== -1) {
27
+ name = functionName.substring(lastSlashIndex + 1);
28
+ } else {
29
+ name = functionName;
30
+ }
31
+
32
+ if (functionType === "controller" && args && args.length > 0) {
33
+ req = args[0];
34
+
35
+ if (req && typeof req.allParams === "function") {
36
+ try {
37
+ allParams = req.allParams();
38
+ inputs = sanitizeInputs(allParams);
39
+ } catch (unusedErr) {
40
+ inputs = null;
41
+ }
42
+ } else {
43
+ inputs = null;
44
+ }
45
+ } else if (functionType === "helper" && args && args.length > 0) {
46
+ inputs = sanitizeInputs(args[0]);
47
+ controllerExecutionId = controllerExecutionIdOverride !== undefined
48
+ ? controllerExecutionIdOverride
49
+ : executionContext.getControllerExecutionId();
50
+ parentExecutionId = parentExecutionIdOverride !== undefined
51
+ ? parentExecutionIdOverride
52
+ : executionContext.getCurrentExecutionId();
53
+ } else {
54
+ inputs = args && args.length > 0 ? sanitizeInputs(args[0]) : null;
55
+ controllerExecutionId = controllerExecutionIdOverride !== undefined
56
+ ? controllerExecutionIdOverride
57
+ : executionContext.getControllerExecutionId();
58
+ parentExecutionId = parentExecutionIdOverride !== undefined
59
+ ? parentExecutionIdOverride
60
+ : executionContext.getCurrentExecutionId();
61
+ }
62
+
63
+ if (!error && result !== undefined) {
64
+ output = sanitizeInputs(result);
65
+ } else {
66
+ output = null;
67
+ }
68
+
69
+ if (functionType === "controller") {
70
+ return EventSchema.createControllerEvent({
71
+ name: name,
72
+ durationMs,
73
+ meta,
74
+ inputs,
75
+ output,
76
+ path: path,
77
+ error,
78
+ controllerExecutionId: null,
79
+ parentExecutionId: null
80
+ });
81
+ }
82
+
83
+ if (functionType === "helper") {
84
+ return EventSchema.createHelperEvent({
85
+ name: name,
86
+ durationMs,
87
+ meta,
88
+ inputs,
89
+ output,
90
+ path: path,
91
+ error,
92
+ controllerExecutionId: controllerExecutionId,
93
+ parentExecutionId: parentExecutionId
94
+ });
95
+ }
96
+
97
+ return EventSchema.create({
98
+ type: functionType,
99
+ name: name,
100
+ durationMs,
101
+ meta,
102
+ inputs,
103
+ output,
104
+ path: path,
105
+ error,
106
+ controllerExecutionId: controllerExecutionId,
107
+ parentExecutionId: parentExecutionId
108
+ });
109
+ }
110
+
111
+ module.exports = createEvent;
@@ -0,0 +1,39 @@
1
+
2
+ const createEvent = require("./createEvent");
3
+
4
+ async function handleAsyncFunction(promise, startTime, executionId, functionName, functionType, args, buffer) {
5
+ try {
6
+ const result = await promise;
7
+
8
+ buffer.add(
9
+ createEvent(
10
+ functionName,
11
+ functionType,
12
+ Date.now() - startTime,
13
+ executionId,
14
+ args,
15
+ result,
16
+ null
17
+ )
18
+ );
19
+
20
+ return result;
21
+
22
+ } catch (error) {
23
+ buffer.add(
24
+ createEvent(
25
+ functionName,
26
+ functionType,
27
+ Date.now() - startTime,
28
+ executionId,
29
+ args,
30
+ undefined,
31
+ error
32
+ )
33
+ );
34
+
35
+ throw error;
36
+ }
37
+ }
38
+
39
+ module.exports = handleAsyncFunction;
@@ -0,0 +1,12 @@
1
+
2
+ const { wrapFunction, getCallStatistics, resetCallStatistics } = require("./wrapFunction"),
3
+ wrapController = require("./wrapController"),
4
+ wrapHelper = require("./wrapHelper");
5
+
6
+ module.exports = {
7
+ wrapFunction,
8
+ wrapController,
9
+ wrapHelper,
10
+ getCallStatistics,
11
+ resetCallStatistics
12
+ };
@@ -0,0 +1,42 @@
1
+
2
+ const { wrapFunction, WRAPPED_FLAG, ORIGINAL_FUNCTION } = require("./wrapFunction");
3
+
4
+ function isAlreadyWrapped(fn) {
5
+ return fn && fn[WRAPPED_FLAG] === true;
6
+ }
7
+
8
+ function wrapController(controller, controllerName, buffer, logger) {
9
+ let wrappedController = null;
10
+
11
+ if (controller && typeof controller === "object" && !isAlreadyWrapped(controller)) {
12
+ wrappedController = {};
13
+
14
+ for (const actionName of Object.keys(controller)) {
15
+ const action = controller[actionName];
16
+
17
+ wrappedController[actionName] =
18
+ typeof action === "function"
19
+ ? wrapFunction(
20
+ action,
21
+ `${controllerName}/${actionName}`,
22
+ "controller",
23
+ buffer,
24
+ logger
25
+ )
26
+ : action;
27
+ }
28
+
29
+ wrappedController[WRAPPED_FLAG] = true;
30
+ wrappedController[ORIGINAL_FUNCTION] = controller;
31
+ } else {
32
+ if (isAlreadyWrapped(controller)) {
33
+ logger.debug(`Controller ${controllerName} already wrapped`);
34
+ } else {
35
+
36
+ }
37
+ }
38
+
39
+ return wrappedController || controller;
40
+ }
41
+
42
+ module.exports = wrapController;
@@ -0,0 +1,108 @@
1
+
2
+ const EventSchema = require("../../../core/events/EventSchema"),
3
+ handleAsyncFunction = require("./handleAsyncFunction"),
4
+ createEvent = require("./createEvent"),
5
+ executionContext = require("../../../utils/executionContext"),
6
+ WRAPPED_FLAG = Symbol("__codeaura_wrapped__"),
7
+ ORIGINAL_FUNCTION = Symbol("__codeaura_original__");
8
+
9
+ let functionCallCounts = {};
10
+
11
+ function isAlreadyWrapped(fn) {
12
+ return fn && fn[WRAPPED_FLAG] === true;
13
+ }
14
+
15
+ function wrapFunction(originalFunction, functionName, functionType, buffer, unusedLogger) {
16
+ let wrappedFunction = null,
17
+ executionId = null,
18
+ startTime = 0,
19
+ result = null;
20
+
21
+ if (typeof originalFunction === "function" && !isAlreadyWrapped(originalFunction)) {
22
+ wrappedFunction = function (...args) {
23
+ executionId = EventSchema.generateId();
24
+ startTime = Date.now();
25
+
26
+ functionCallCounts[functionName] = (functionCallCounts[functionName] || 0) + 1;
27
+
28
+ try {
29
+ if (functionType === "controller") {
30
+ result = executionContext.runAsController(executionId, () => originalFunction.apply(this, args));
31
+ } else {
32
+ result = originalFunction.apply(this, args);
33
+ }
34
+
35
+ if (result && typeof result.then === "function") {
36
+ return handleAsyncFunction(
37
+ result,
38
+ startTime,
39
+ executionId,
40
+ functionName,
41
+ functionType,
42
+ args,
43
+ buffer
44
+ );
45
+ } else {
46
+
47
+ }
48
+
49
+ buffer.add(
50
+ createEvent(
51
+ functionName,
52
+ functionType,
53
+ Date.now() - startTime,
54
+ executionId,
55
+ args,
56
+ result,
57
+ null
58
+ )
59
+ );
60
+
61
+ return result;
62
+
63
+ } catch (error) {
64
+ buffer.add(
65
+ createEvent(
66
+ functionName,
67
+ functionType,
68
+ Date.now() - startTime,
69
+ executionId,
70
+ args,
71
+ undefined,
72
+ error
73
+ )
74
+ );
75
+
76
+ throw error;
77
+ }
78
+ };
79
+
80
+ wrappedFunction[WRAPPED_FLAG] = true;
81
+ wrappedFunction[ORIGINAL_FUNCTION] = originalFunction;
82
+
83
+ Object.defineProperty(wrappedFunction, "name", {
84
+ value: originalFunction.name || functionName,
85
+ configurable: true
86
+ });
87
+ } else {
88
+
89
+ }
90
+
91
+ return wrappedFunction || originalFunction;
92
+ }
93
+
94
+ function getCallStatistics() {
95
+ return Object.assign({}, functionCallCounts);
96
+ }
97
+
98
+ function resetCallStatistics() {
99
+ functionCallCounts = {};
100
+ }
101
+
102
+ module.exports = {
103
+ wrapFunction,
104
+ getCallStatistics,
105
+ resetCallStatistics,
106
+ WRAPPED_FLAG,
107
+ ORIGINAL_FUNCTION
108
+ };
@@ -0,0 +1,86 @@
1
+
2
+ const EventSchema = require("../../../core/events/EventSchema"),
3
+ { wrapFunction } = require("./wrapFunction"),
4
+ createEvent = require("./createEvent"),
5
+ executionContext = require("../../../utils/executionContext");
6
+
7
+ function wrapHelper(helper, helperName, buffer, logger) {
8
+ let wrappedHelper = null;
9
+
10
+ try {
11
+ if (typeof helper === "function") {
12
+ wrappedHelper = wrapFunction(
13
+ helper,
14
+ helperName,
15
+ "helper",
16
+ buffer,
17
+ logger
18
+ );
19
+
20
+ if (typeof helper.with === "function") {
21
+ wrappedHelper.with = async function (inputs) {
22
+ let executionId = null,
23
+ startTime = 0,
24
+ result = null,
25
+ controllerExecutionId = null,
26
+ parentExecutionId = null;
27
+
28
+ executionId = EventSchema.generateId();
29
+ startTime = Date.now();
30
+ controllerExecutionId = executionContext.getControllerExecutionId();
31
+ parentExecutionId = executionContext.getCurrentExecutionId();
32
+
33
+ try {
34
+ result = await helper.with(inputs);
35
+
36
+ buffer.add(
37
+ createEvent(
38
+ helperName,
39
+ "helper",
40
+ Date.now() - startTime,
41
+ executionId,
42
+ [inputs],
43
+ result,
44
+ null,
45
+ controllerExecutionId,
46
+ parentExecutionId
47
+ )
48
+ );
49
+
50
+ return result;
51
+
52
+ } catch (error) {
53
+ buffer.add(
54
+ createEvent(
55
+ helperName,
56
+ "helper",
57
+ Date.now() - startTime,
58
+ executionId,
59
+ [inputs],
60
+ undefined,
61
+ error,
62
+ controllerExecutionId,
63
+ parentExecutionId
64
+ )
65
+ );
66
+
67
+ throw error;
68
+ }
69
+ };
70
+ } else {
71
+
72
+ }
73
+ } else {
74
+
75
+ }
76
+
77
+ return wrappedHelper || helper;
78
+
79
+ } catch (err) {
80
+ logger.errorWithStack(`Error wrapping helper ${helperName}`, err);
81
+
82
+ return helper;
83
+ }
84
+ }
85
+
86
+ module.exports = wrapHelper;
@@ -0,0 +1,42 @@
1
+
2
+ const { AsyncLocalStorage } = require("async_hooks");
3
+
4
+ class ExecutionContext {
5
+
6
+ constructor() {
7
+ this.storage = new AsyncLocalStorage();
8
+ }
9
+
10
+ runAsController(controllerExecutionId, fn) {
11
+ return this.storage.run({
12
+ controllerExecutionId,
13
+ currentExecutionId: controllerExecutionId
14
+ }, fn);
15
+ }
16
+
17
+ runAsExecution(executionId, controllerExecutionId, fn) {
18
+ return this.storage.run({
19
+ controllerExecutionId,
20
+ currentExecutionId: executionId
21
+ }, fn);
22
+ }
23
+
24
+ getControllerExecutionId() {
25
+ let store = null;
26
+
27
+ store = this.storage.getStore();
28
+
29
+ return store ? store.controllerExecutionId : null;
30
+ }
31
+
32
+ getCurrentExecutionId() {
33
+ let store = null;
34
+
35
+ store = this.storage.getStore();
36
+
37
+ return store ? store.currentExecutionId : null;
38
+ }
39
+
40
+ }
41
+
42
+ module.exports = new ExecutionContext();
@@ -0,0 +1,150 @@
1
+
2
+ let instance = null;
3
+
4
+ class Logger {
5
+
6
+ constructor(config) {
7
+ config = config || {};
8
+
9
+ this.enabled = config.enabled !== false;
10
+ this.level = config.level || "info";
11
+ this.prefix = "[CodeAura Agent]";
12
+ this.levels = {
13
+ debug: 0,
14
+ info: 1,
15
+ warn: 2,
16
+ error: 3
17
+ };
18
+ }
19
+
20
+ shouldLog(level) {
21
+ const currentLevelPriority = this.levels[this.level] || 1,
22
+ messageLevelPriority = this.levels[level] || 1;
23
+
24
+ if (!this.enabled) {
25
+ return false;
26
+ } else {
27
+
28
+ }
29
+
30
+ return messageLevelPriority >= currentLevelPriority;
31
+ }
32
+
33
+ format(level, message, args) {
34
+ const timestamp = new Date().toISOString(),
35
+ levelStr = level.toUpperCase().padEnd(5),
36
+ formattedArgs = [`${this.prefix} [${timestamp}] ${levelStr}:`, message];
37
+
38
+ if (args && args.length > 0) {
39
+ return formattedArgs.concat(args);
40
+ } else {
41
+ return formattedArgs;
42
+ }
43
+ }
44
+
45
+ debug(message, ...args) {
46
+ const shouldLog = this.shouldLog("debug");
47
+
48
+ let formattedArgs = null;
49
+
50
+ if (shouldLog) {
51
+ formattedArgs = this.format("debug", message, args);
52
+
53
+ console.log(...formattedArgs);
54
+ } else {
55
+
56
+ }
57
+ }
58
+
59
+ info(message, ...args) {
60
+ const shouldLog = this.shouldLog("info");
61
+
62
+ let formattedArgs = null;
63
+
64
+ if (shouldLog) {
65
+ formattedArgs = this.format("info", message, args);
66
+
67
+ console.log(...formattedArgs);
68
+ } else {
69
+
70
+ }
71
+ }
72
+
73
+ warn(message, ...args) {
74
+ const shouldLog = this.shouldLog("warn");
75
+
76
+ let formattedArgs = null;
77
+
78
+ if (shouldLog) {
79
+ formattedArgs = this.format("warn", message, args);
80
+
81
+ console.warn(...formattedArgs);
82
+ } else {
83
+
84
+ }
85
+ }
86
+
87
+ error(message, ...args) {
88
+ const shouldLog = this.shouldLog("error");
89
+
90
+ let formattedArgs = null;
91
+
92
+ if (shouldLog) {
93
+ formattedArgs = this.format("error", message, args);
94
+
95
+ console.error(...formattedArgs);
96
+ } else {
97
+
98
+ }
99
+ }
100
+
101
+ errorWithStack(message, error) {
102
+ const shouldLog = this.shouldLog("error");
103
+
104
+ if (shouldLog) {
105
+ this.error(message);
106
+
107
+ if (error && error.stack) {
108
+ console.error(error.stack);
109
+ } else {
110
+
111
+ }
112
+ } else {
113
+
114
+ }
115
+ }
116
+
117
+ configure(config) {
118
+ if (config.enabled !== undefined) {
119
+ this.enabled = config.enabled;
120
+ } else {
121
+
122
+ }
123
+
124
+ if (config.level !== undefined) {
125
+ this.level = config.level;
126
+ } else {
127
+
128
+ }
129
+ }
130
+
131
+ }
132
+
133
+ const getLogger = (config) => {
134
+ if (!instance) {
135
+ instance = new Logger(config);
136
+ } else {
137
+
138
+ }
139
+
140
+ return instance;
141
+ },
142
+
143
+ createLogger = (config) => {
144
+ return new Logger(config);
145
+ };
146
+
147
+ module.exports = {
148
+ getLogger,
149
+ createLogger
150
+ };
@@ -0,0 +1,87 @@
1
+
2
+ const axios = require("axios");
3
+
4
+ module.exports = async (action, method, data, config) => {
5
+ const appUrl = config.apiUrl || "",
6
+ apiKey = config.apiKey || "",
7
+ requestMethod = (method || "POST").toUpperCase();
8
+
9
+ let options = null,
10
+ response = null;
11
+
12
+ options = {
13
+ method: requestMethod,
14
+ url: appUrl + action,
15
+ headers: {
16
+ "Accept": "application/json",
17
+ "Content-Type": "application/json",
18
+ "apiKey": apiKey
19
+ },
20
+ data: data,
21
+ timeout: config.timeout || 10000,
22
+ validateStatus: status => status >= 200 && status < 600
23
+ };
24
+
25
+ try {
26
+ response = await axios(options);
27
+
28
+ if (response.status >= 200 && response.status < 300) {
29
+ if (response.data && response.data.data) {
30
+ return {
31
+ data: response.data.data,
32
+ error: null
33
+ };
34
+ } else if (response.data) {
35
+ return {
36
+ data: response.data,
37
+ error: null
38
+ };
39
+ } else {
40
+ return {
41
+ data: null,
42
+ error: "Unexpected response format"
43
+ };
44
+ }
45
+ } else if (response.data && response.data.errors && response.data.errors[0]) {
46
+ return {
47
+ data: null,
48
+ error: response.data.errors[0].message || response.data.errors[0]
49
+ };
50
+ } else if (response.data && response.data.error) {
51
+ return {
52
+ data: null,
53
+ error: response.data.error
54
+ };
55
+ } else {
56
+ console.error("[CodeAura Agent] Unexpected response body for status " + response.status + ":", JSON.stringify(response.data));
57
+
58
+ return {
59
+ data: null,
60
+ error: `HTTP ${response.status} error`
61
+ };
62
+ }
63
+ } catch (error) {
64
+ let errorMessage = "Unknown error";
65
+
66
+ if (error.response && error.response.data) {
67
+ if (error.response.data.errors && error.response.data.errors[0]) {
68
+ errorMessage = error.response.data.errors[0].message || error.response.data.errors[0];
69
+ } else if (error.response.data.error) {
70
+ errorMessage = error.response.data.error;
71
+ } else {
72
+ errorMessage = `HTTP ${error.response.status} error`;
73
+ }
74
+ } else if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") {
75
+ errorMessage = `Request timeout after ${config.timeout || 10000}ms`;
76
+ } else if (error.code === "ECONNREFUSED" || error.code === "ENOTFOUND") {
77
+ errorMessage = `Cannot connect to API: ${error.code}`;
78
+ } else if (error.message) {
79
+ errorMessage = error.message;
80
+ }
81
+
82
+ return {
83
+ data: null,
84
+ error: errorMessage
85
+ };
86
+ }
87
+ };