@vida-global/apps-tools 1.0.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/index.js ADDED
@@ -0,0 +1,23 @@
1
+ const { AppHooksHandler, AppFunctionHandler } = require("./lib/actionHandlers");
2
+ const { AppFunctionResponse, AppHookResponse } = require('./lib/appResponses');
3
+ const { BaseProviderConfigurator, BaseProvider } = require('./lib/providers/provider');
4
+ const { AppServer } = require("./lib/server/server");
5
+ const { VaderUserContext } = require("./lib/userContext");
6
+ const { VidaApp } = require("./lib/apps/vidaApp");
7
+ const { VidaLiveAppManager } = require("./lib/apps/appManager/vidaLiveAppManager");
8
+ const { HttpClient, logger } = require("@vida-global/core");
9
+
10
+ module.exports = {
11
+ AppFunctionHandler,
12
+ AppFunctionResponse,
13
+ AppHooksHandler,
14
+ AppHookResponse,
15
+ AppServer,
16
+ BaseProvider,
17
+ BaseProviderConfigurator,
18
+ HttpClient,
19
+ logger,
20
+ VaderUserContext,
21
+ VidaApp,
22
+ VidaLiveAppManager
23
+ }
@@ -0,0 +1,7 @@
1
+ class AppFunctionHandler {
2
+ constructor(app) {
3
+ this.app = app
4
+ }
5
+ }
6
+
7
+ module.exports = { AppFunctionHandler };
@@ -0,0 +1,7 @@
1
+ class AppHooksHandler {
2
+ constructor(app) {
3
+ this.app = app
4
+ }
5
+ }
6
+
7
+ module.exports = { AppHooksHandler };
@@ -0,0 +1,4 @@
1
+ const { AppHooksHandler } = require("./appHooksHandler");
2
+ const { AppFunctionHandler } = require("./appFunctionHandler");
3
+
4
+ module.exports = { AppHooksHandler, AppFunctionHandler };
@@ -0,0 +1,23 @@
1
+ class AppFunctionResponse {
2
+ status = null;
3
+ data = null;
4
+ error = null;
5
+ message = null;
6
+ functionName = null;
7
+ functionArgs = null;
8
+ responseTime = null;
9
+
10
+ constructor () {
11
+ this.logger = console
12
+ }
13
+
14
+ log () {
15
+ if (this.status === 'error') {
16
+ this.logger.error(`App response error: ${this.status} - ${this.message}`)
17
+ } else {
18
+ this.logger.log(`App response: ${this.status}`)
19
+ }
20
+ }
21
+ }
22
+
23
+ module.exports = { AppFunctionResponse };
@@ -0,0 +1,21 @@
1
+ class AppHookResponse {
2
+ status = null;
3
+ error = null;
4
+ data = null;
5
+ message = null;
6
+ responseTime = null;
7
+
8
+ constructor () {
9
+ this.logger = console
10
+ }
11
+
12
+ log () {
13
+ if (this.status === 'error') {
14
+ this.logger.error(`App response error: ${this.status} - ${this.message}`)
15
+ } else {
16
+ this.logger.log(`App response: ${this.status}`)
17
+ }
18
+ }
19
+ }
20
+
21
+ module.exports = { AppHookResponse };
@@ -0,0 +1,6 @@
1
+ const { AppFunctionResponse } = require('./appFunctionResponse');
2
+
3
+ class CalendarAppResponse extends AppFunctionResponse {
4
+ }
5
+
6
+ module.exports = { CalendarAppResponse };
@@ -0,0 +1,9 @@
1
+ const { AppFunctionResponse } = require('./appFunctionResponse');
2
+ const { AppHookResponse } = require('./appHookResponse');
3
+ const { CalendarAppResponse } = require('./calendarAppResponse');
4
+
5
+ module.exports = {
6
+ AppFunctionResponse,
7
+ AppHookResponse,
8
+ CalendarAppResponse
9
+ }
@@ -0,0 +1,70 @@
1
+ const { logger } = require('@vida-global/core');
2
+ const { ProviderManager } = require('../../providers/providerManager');
3
+ const { VaderUserContextProxy } = require('../../userContext')
4
+
5
+
6
+ class AbstractAppManager {
7
+ #providerManager;
8
+
9
+
10
+ context(ctx) {
11
+ return new VaderUserContextProxy(this, ctx)
12
+ }
13
+
14
+
15
+ get logger() {
16
+ return logger;
17
+ }
18
+
19
+
20
+ get attachedToAppServer() {
21
+ return this.constructor.name == 'AppServerAppManager';
22
+ }
23
+
24
+
25
+ get providerManager() {
26
+ if (!this.#providerManager) {
27
+ this.#providerManager = new ProviderManager(this.redisClient, this.attachedToAppServer);
28
+ }
29
+ return this.#providerManager;
30
+ }
31
+
32
+
33
+ async _getApp(appClass, appId, appVersion, appManifest, userContext) {
34
+ const providerManager = this.providerManager;
35
+ const isServer = this.attachedToAppServer;
36
+ return await appClass.get(appClass,
37
+ { appId,
38
+ appVersion,
39
+ appManifest,
40
+ userContext,
41
+ providerManager },
42
+ { isServer });
43
+ }
44
+
45
+
46
+ /***********************************************************************************************
47
+ * MISC
48
+ ***********************************************************************************************/
49
+ debugPrintCalls(appId, appVersion, functionName, callContext, manifest, functionArgs) {
50
+ this.logger.info(`Handling call ${appId} ${appVersion} ${functionName}`)
51
+
52
+ // User: ${JSON.stringify(callContext.user, null, 2)}
53
+ // Agent: ${JSON.stringify(callContext.agent, null, 2)}
54
+ // Caller: ${JSON.stringify(callContext.caller, null, 2)}
55
+
56
+ this.logger.info(
57
+ `Function call details:
58
+ Request Sent Dependencies: ${JSON.stringify(callContext?.manifest?.dependencies, null, 2)}
59
+ App ID: ${appId}
60
+ App Version: ${appVersion}
61
+ Function name: ${functionName}
62
+ Function args: ${JSON.stringify(functionArgs, null, 2)}`
63
+ );
64
+ }
65
+ }
66
+
67
+
68
+ module.exports = {
69
+ AbstractAppManager
70
+ }
@@ -0,0 +1,237 @@
1
+ const { AbstractAppManager } = require('./abstractAppManager');
2
+ const fs = require('fs');
3
+ const { generateOpenApiSpec } = require('../../openApi');
4
+ const path = require('path');
5
+ const _ = require("lodash")
6
+
7
+
8
+ class AppServerAppManager extends AbstractAppManager {
9
+ #apps;
10
+ #useMocks;
11
+
12
+
13
+ constructor({ apps, useMocks }) {
14
+ super(...arguments);
15
+ this.#useMocks = useMocks;
16
+ this.#apps = apps.map(app => {
17
+ const [id, version] = app.split('/')
18
+ return {id, version}
19
+ })
20
+ this.#validateApps();
21
+ }
22
+
23
+
24
+ get apps() {
25
+ return structuredClone(this.#apps);
26
+ }
27
+
28
+
29
+ get appsDirectory() {
30
+ return `${process.cwd()}/apps`;
31
+ }
32
+
33
+
34
+ /***********************************************************************************************
35
+ * APP MANAGEMENT
36
+ ***********************************************************************************************/
37
+ #mergeMocks(appId, appVersion, appManifest) {
38
+ if (!this.#useMocks) return;
39
+ try {
40
+ const mockData = require(`${process.cwd()}/apps/${appId}/${appVersion}/test/mocks.js`)
41
+ appManifest.dependencies = _.merge(_.cloneDeep(appManifest.dependencies), mockData)
42
+ } catch (error) {
43
+ this.logger.warn(`No mocks found for app ${appId} ${appVersion} ${error}`)
44
+ }
45
+ }
46
+
47
+
48
+ async getApp(appId, appVersion, appManifest, userContext) {
49
+ if (!appManifest) {
50
+ this.logger.info('no manifest provided, getting vanilla manifest')
51
+ appManifest = this.fetchVanillaAppManifest(appId, appVersion, userContext)
52
+ }
53
+
54
+ this.#mergeMocks(appId, appVersion, appManifest);
55
+
56
+ const appClass = require(`${process.cwd()}/apps/${appId}/${appVersion}/app.js`);
57
+ return await this._getApp(appClass, appId, appVersion, appManifest, userContext);
58
+ }
59
+
60
+
61
+ fetchVanillaAppManifest(appId, appVersion) {
62
+ const manifest = require(`${process.cwd()}/apps/${appId}/${appVersion}/manifest.js`)
63
+ // Return a deep clone to avoid mutating the cached module object
64
+ return _.cloneDeep(manifest)
65
+ }
66
+
67
+
68
+ async fetchAllVanillaManifests(userContext = null) {
69
+ const manifests = {}
70
+ for (const {id, version} of this.apps) {
71
+ const appIdVersion = `${id}:${version}`
72
+ const manifest = require(`${process.cwd()}/apps/${id}/${version}/manifest.js`)
73
+ // Deep clone to avoid mutating the cached module export
74
+ manifests[appIdVersion] = _.cloneDeep(manifest)
75
+ }
76
+ return manifests
77
+ }
78
+
79
+
80
+ /***********************************************************************************************
81
+ * VALIDATION
82
+ ***********************************************************************************************/
83
+ #validateApps() {
84
+ for (const {id, version} of this.apps) {
85
+ this.#validateApp(id, version);
86
+ }
87
+ }
88
+
89
+
90
+ #validateApp(appId, version) {
91
+ const appPath = path.join(this.appsDirectory, appId, version);
92
+
93
+ // Check if directory exists
94
+ if (!fs.existsSync(appPath)) {
95
+ throw new Error(`Invalid app structure: Missing directory at ${appPath}`);
96
+ }
97
+
98
+ // Check for app.js file existence
99
+ const appJsPath = path.join(appPath, 'app.js');
100
+ if (!fs.existsSync(appJsPath)) {
101
+ throw new Error(`Invalid app structure: Missing app.js for ${appId}/${version} in ${appPath}`);
102
+ }
103
+
104
+ // Check for manifest.js file existence
105
+ const manifestJsPath = path.join(appPath, 'manifest.js');
106
+ if (!fs.existsSync(manifestJsPath)) {
107
+ throw new Error(`Invalid app structure: Missing manifest.js for ${appId}/${version} in ${appPath}`);
108
+ }
109
+ }
110
+
111
+
112
+ /***********************************************************************************************
113
+ * OPEN API
114
+ ***********************************************************************************************/
115
+ async generateOpenApiSpec () {
116
+ return await generateOpenApiSpec(this);
117
+ }
118
+
119
+
120
+ /***********************************************************************************************
121
+ * CALL HANDLERS
122
+ ***********************************************************************************************/
123
+ async handleFunctionCall(appId, appVersion, appManifest, functionName, functionArgs, userContext) {
124
+ const manifest = appManifest
125
+
126
+ this.debugPrintCalls(appId,
127
+ appVersion,
128
+ functionName,
129
+ userContext.toDict(),
130
+ manifest,
131
+ functionArgs);
132
+
133
+ this.logger.info(`Handling function call ${appId} ${appVersion} ${functionName}`)
134
+ const app = await this.getApp(appId, appVersion, manifest, userContext);
135
+ const hasFunction = await app.isFunctionInApp(functionName)
136
+
137
+ if (!hasFunction) throw new Error(`Function not found: ${functionName}`);
138
+
139
+ const result = await app.handleFunctionCall(functionName, functionArgs)
140
+ this.logger.info(`Function result: ${JSON.stringify(result, null, 2)}`)
141
+ return result
142
+ }
143
+
144
+
145
+ async handleHookCall(appId, appVersion, appManifest, hookName, hookArgs, userContext) {
146
+ let manifest = appManifest
147
+ this.debugPrintCalls(appId,
148
+ appVersion,
149
+ hookName,
150
+ userContext.toDict(),
151
+ manifest,
152
+ hookArgs);
153
+
154
+ this.logger.info(`Handling hook call ${appId} ${appVersion} ${hookName}`)
155
+ const app = await this.getApp(appId, appVersion, manifest, userContext);
156
+ const hasHook = await app.isHookInApp(hookName)
157
+
158
+ if (!hasHook) throw new Error(`Hook not found: ${hookName}`);
159
+
160
+ const result = await app.handleHookCall(hookName, hookArgs);
161
+ this.logger.info(`Hook result: ${JSON.stringify(result, null, 2)}`);
162
+ return result;
163
+ }
164
+
165
+
166
+ /***********************************************************************************************
167
+ * DATA FETCHERS
168
+ ***********************************************************************************************/
169
+ async getFunctions(onlyEnabled=false, userContext) {
170
+ let appFunctions = []
171
+ const appVersionIds = await userContext.getAppVersionIds()
172
+ this.logger.info('VADER: getFunctions', appVersionIds)
173
+
174
+ for (const appVersionId of appVersionIds) {
175
+ const [appId, appVersion] = appVersionId.split(':')
176
+ const app = await this.getApp(appId, appVersion, null, userContext);
177
+ appFunctions = await app.getFunctions(onlyEnabled)
178
+ }
179
+ return appFunctions
180
+ }
181
+
182
+
183
+ async getHooks(userContext) {
184
+ const responses = []
185
+ const appVersionIds = await userContext.getAppVersionIds()
186
+ this.logger.info('VADER: getHooks', appVersionIds)
187
+
188
+ for (let appVersionId of appVersionIds) {
189
+ const [appId, appVersion] = appVersionId.split(':')
190
+ const vanillaManifest = this.fetchVanillaAppManifest(appId, appVersion, userContext);
191
+ const app = await this.getApp(appId, appVersion, vanillaManifest, userContext);
192
+ const appHooks = await app.getHooks()
193
+
194
+ for (const hook of appHooks) {
195
+ const hasHook = await app.isHookInApp(hook.name)
196
+ if (hasHook) {
197
+ const result = await app.handleHookCall(hook.name, {})
198
+ this.logger.info(`Hook result: ${JSON.stringify(result, null, 2)}`)
199
+ responses.push(result)
200
+ } else {
201
+ this.logger.warn('VADER: getHooks', hook.name, 'not found')
202
+ }
203
+ }
204
+
205
+ this.logger.info('VADER: getHooks', appVersionId)
206
+ const appInstructions = await app.getAgentInstructions()
207
+ if (appInstructions) {
208
+ const appFunctions = await this.getFunctions(true, userContext)
209
+ const functionNameString = _.map(appFunctions, f => f.name).join(', ')
210
+ responses.push({
211
+ status: 'success',
212
+ message: `Instructions for using ${functionNameString} functions: ${appInstructions}`
213
+ })
214
+ }
215
+ }
216
+
217
+ return responses
218
+ }
219
+
220
+
221
+ async listApps(userContext) {
222
+ const apps = []
223
+ const allManifests = await this.fetchAllVanillaManifests(userContext)
224
+
225
+ for (const appIdVersion of Object.keys(allManifests)) {
226
+ const [appId, appVersion] = appIdVersion.split(':')
227
+ const vanillaManifest = this.fetchVanillaAppManifest(appId, appVersion, userContext)
228
+ const app = await this.getApp(appId, appVersion, vanillaManifest, userContext);
229
+ const compositeManifest = await app.getCompositeManifest()
230
+ apps.push(compositeManifest)
231
+ }
232
+ return apps
233
+ }
234
+ }
235
+
236
+
237
+ module.exports = { AppServerAppManager };
@@ -0,0 +1,81 @@
1
+ const { AppFunctionResponse } = require('../../appResponses/appFunctionResponse');
2
+ const { AppHookResponse } = require('../../appResponses/appHookResponse');
3
+ const { HttpClient } = require('@vida-global/core');
4
+
5
+
6
+ class VaderApiClient extends HttpClient {
7
+ #vaderServerUrl;
8
+ #vaderServerToken;
9
+
10
+
11
+ constructor(vaderServerUrl, vaderServerToken) {
12
+ super();
13
+ this.#vaderServerUrl = vaderServerUrl;
14
+ this.#vaderServerToken = vaderServerToken;
15
+ }
16
+
17
+
18
+ async invokeAppManager(functionName, functionArgs = [], userContext = null){
19
+ const endpoint = `/invoke/apps/manager/${functionName}`
20
+ const body = {
21
+ userContext: userContext?.toDict() || null,
22
+ functionArgs,
23
+ };
24
+
25
+ const response = await this.post(endpoint, userContext, body);
26
+ return response.data;
27
+ }
28
+
29
+
30
+ async invokeFunction(app, functionName, functionArgs, userContext = null){
31
+ return await this.#invokeAction('function',
32
+ AppFunctionResponse,
33
+ app,
34
+ functionName,
35
+ functionArgs,
36
+ userContext);
37
+ }
38
+
39
+
40
+ async invokeHook(app, hookName, hookArgs, userContext = null) {
41
+ return await this.#invokeAction('hook',
42
+ AppHookResponse,
43
+ app,
44
+ hookName,
45
+ hookArgs,
46
+ userContext);
47
+ }
48
+
49
+
50
+ async #invokeAction(actionType, responseCls, app, actionName, actionArgs, userContext) {
51
+ const endpoint = `/invoke/app/${actionType}/${app.id()}/${app.version()}/${actionName}`
52
+ const body = {
53
+ userContext: userContext?.toDict() || null,
54
+ appManifest: await app.getCompositeManifest(),
55
+ actionArgs,
56
+ };
57
+
58
+ try {
59
+ const response = await this.post(endpoint, userContext, body);
60
+ return response.data;
61
+ } catch(err) {
62
+ const appResponse = new responseCls();
63
+ appResponse.status = "error"
64
+ appResponse.message = await err.data();
65
+ return appResponse;
66
+ }
67
+ }
68
+
69
+
70
+ async post(endpoint, userContext, body) {
71
+ const vaderUrl = userContext?.get('customVaderUrl') || this.#vaderServerUrl;
72
+ const vaderToken = userContext?.get('customVaderToken') || this.#vaderServerToken;
73
+ const invokeUrl = `${vaderUrl}${endpoint}`;
74
+ const headers = {Authorization: `Bearer ${vaderToken}`};
75
+
76
+ return await super.post(invokeUrl, { body, headers });
77
+ }
78
+ }
79
+
80
+
81
+ module.exports = { VaderApiClient };
@@ -0,0 +1,187 @@
1
+ const { AbstractAppManager } = require('./abstractAppManager');
2
+ const { AppFunctionResponse } = require('../../appResponses/appFunctionResponse');
3
+ const { VaderApiClient } = require('./vaderApiClient');
4
+ const { VidaApp } = require('../vidaApp');
5
+
6
+
7
+ class VidaLiveAppManager extends AbstractAppManager {
8
+ #providersList;
9
+ #redisClient;
10
+ #vaderApiClient;
11
+
12
+ constructor({ redisClient, providersList, vaderServerUrl, vaderServerToken }) {
13
+ super(...arguments);
14
+ this.#vaderApiClient = new VaderApiClient(vaderServerUrl, vaderServerToken);
15
+ this.#providersList = providersList;
16
+ this.#redisClient = redisClient;
17
+ }
18
+
19
+
20
+ async initialize(server) {
21
+ await this.providerManager.buildRoutes(server, this.#providersList)
22
+ }
23
+
24
+
25
+ get redisClient() {
26
+ return this.#redisClient;
27
+ }
28
+
29
+
30
+ /***********************************************************************************************
31
+ * APP MANAGEMENT
32
+ ***********************************************************************************************/
33
+ async getApp(appId, appVersion, appManifest, userContext) {
34
+ const serverManifest = await this.#vaderApiClient.invokeAppManager('getApp',
35
+ [appId, appVersion, appManifest],
36
+ userContext);
37
+ return await this._getApp(VidaApp, appId, appVersion, serverManifest, userContext);
38
+ }
39
+
40
+
41
+
42
+ async fetchVanillaAppManifest(appId, appVersion) {
43
+ return await this.#vaderApiClient.invokeAppManager('fetchVanillaAppManifest',
44
+ [appId, appVersion],
45
+ userContext);
46
+
47
+ }
48
+
49
+
50
+ async fetchAllVanillaManifests(userContext = null) {
51
+ return await this.#vaderApiClient.invokeAppManager('fetchAllVanillaManifests',
52
+ [],
53
+ userContext);
54
+ }
55
+
56
+
57
+ async installApp(appId, appVersion, manifest = null, userContext) {
58
+ if (await this.isAppInstalled(appId, appVersion, userContext)) {
59
+ throw new Error(`App already installed: ${appId} ${appVersion}`);
60
+ }
61
+ if (!manifest) {
62
+ manifest = await this.fetchVanillaAppManifest(appId, appVersion, userContext);
63
+ }
64
+ const app = await this.getApp(appId, appVersion, manifest,userContext);
65
+ await app.install(manifest)
66
+ return app
67
+ }
68
+
69
+
70
+ async updateInstalledApp(appId, appVersion, manifest, userContext) {
71
+ if (!await this.isAppInstalled(appId, appVersion, userContext)) {
72
+ throw new Error(`App not installed: ${appId} ${appVersion}`)
73
+ }
74
+ const vanillaManifest = await this.fetchVanillaAppManifest(appId, appVersion, userContext);
75
+ const app = await this.getApp(appId, appVersion, vanillaManifest,userContext);
76
+ await app.update(manifest);
77
+ return app
78
+ }
79
+
80
+
81
+ async reloadInstalledApp(appId, appVersion, userContext) {
82
+ if (!await this.isAppInstalled(appId, appVersion, userContext)) {
83
+ throw new Error(`App not installed: ${appId} ${appVersion}`)
84
+ }
85
+ const vanillaManifest = await this.fetchVanillaAppManifest(appId, appVersion, userContext);
86
+ const app = await this.getApp(appId, appVersion, vanillaManifest,userContext);
87
+ await app.reload(vanillaManifest);
88
+ return app
89
+ }
90
+
91
+
92
+ async uninstallApp(appId, appVersion, userContext){
93
+ const vanillaManifest = await this.fetchVanillaAppManifest(appId, appVersion, userContext);
94
+ const app = await this.getApp(appId, appVersion, vanillaManifest, userContext);
95
+
96
+ if (!(await app.isInstalled())) return null;
97
+
98
+ this.logger.info(`Uninstalling app ${appId} ${appVersion}`)
99
+ await app.uninstall()
100
+ return app
101
+ }
102
+
103
+
104
+ async isAppInstalled(appId, appVersion, userContext) {
105
+ return await userContext.isAppInstalled(appId, appVersion)
106
+ }
107
+
108
+
109
+ /***********************************************************************************************
110
+ * INVOKERS
111
+ ***********************************************************************************************/
112
+ async invokeFunction(functionName, functionArgs, userContext) {
113
+ const appVersionIds = await userContext.getAppVersionIds()
114
+ for (const appVersionId of appVersionIds) {
115
+ const [appId, appVersion] = appVersionId.split(':')
116
+ const app = await this.getApp(appId, appVersion, null, userContext);
117
+
118
+ if (!app.isInstalled()) continue;
119
+
120
+ const hasFunction = await app.isFunctionInApp(functionName)
121
+ if (hasFunction) {
122
+ return await this.#vaderApiClient.invokeFunction(app,
123
+ functionName,
124
+ functionArgs,
125
+ userContext);
126
+ }
127
+ }
128
+
129
+ const resp = new AppFunctionResponse()
130
+ resp.status = 'notfound'
131
+ resp.data = null
132
+ resp.functionName = functionName
133
+ resp.functionArgs = functionArgs
134
+ resp.message = `Function not found: ${functionName}`
135
+ return resp
136
+ }
137
+
138
+
139
+ async invokeHook(app, hookName, hookArgs, userContext = null) {
140
+ const appVersionIds = await userContext.getAppVersionIds()
141
+ for (const appVersionId of appVersionIds) {
142
+ const [appId, appVersion] = appVersionId.split(':')
143
+ const app = await this.getApp(appId, appVersion, null, userContext);
144
+ if (!app.isInstalled()) continue;
145
+
146
+ const hasHook = await app.isHookInApp(hookName)
147
+ if (hasHook) {
148
+ this.logger.info('VADER: invokeHook', hookName, 'found')
149
+ return await this.#vaderApiClient.invokeHook(app,
150
+ hookName,
151
+ hookArgs,
152
+ userContext);
153
+ } else {
154
+ this.logger.info('VADER: invokeHook', hookName, 'not found')
155
+ }
156
+ }
157
+
158
+ return null
159
+ }
160
+
161
+
162
+ /***********************************************************************************************
163
+ * DATA FETCHERS
164
+ ***********************************************************************************************/
165
+ async getFunctions(onlyEnabled = false, userContext) {
166
+ return await this.#vaderApiClient.invokeAppManager('getFunctions',
167
+ [onlyEnabled],
168
+ userContext);
169
+ }
170
+
171
+
172
+ async getHooks(userContext) {
173
+ return await this.#vaderApiClient.invokeAppManager('getHooks',
174
+ [],
175
+ userContext);
176
+ }
177
+
178
+
179
+ async listApps(userContext) {
180
+ return await this.#vaderApiClient.invokeAppManager('listApps',
181
+ [],
182
+ userContext);
183
+ }
184
+ }
185
+
186
+
187
+ module.exports = { VidaLiveAppManager };