@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 +23 -0
- package/lib/actionHandlers/appFunctionHandler.js +7 -0
- package/lib/actionHandlers/appHooksHandler.js +7 -0
- package/lib/actionHandlers/index.js +4 -0
- package/lib/appResponses/appFunctionResponse.js +23 -0
- package/lib/appResponses/appHookResponse.js +21 -0
- package/lib/appResponses/calendarAppResponse.js +6 -0
- package/lib/appResponses/index.js +9 -0
- package/lib/apps/appManager/abstractAppManager.js +70 -0
- package/lib/apps/appManager/appServerAppManager.js +237 -0
- package/lib/apps/appManager/vaderApiClient.js +81 -0
- package/lib/apps/appManager/vidaLiveAppManager.js +187 -0
- package/lib/apps/vidaApp.js +345 -0
- package/lib/errors/illegalAppInvocationError.js +8 -0
- package/lib/openApi/baseApiSpec.js +10 -0
- package/lib/openApi/index.js +150 -0
- package/lib/providers/provider.js +141 -0
- package/lib/providers/providerManager.js +73 -0
- package/lib/providers/providers/auth/generic/index.js +60 -0
- package/lib/providers/providers/auth/google/index.js +251 -0
- package/lib/providers/providers/auth/hubspot/index.js +313 -0
- package/lib/providers/providers/auth/mcp/index.js +99 -0
- package/lib/providers/providers/auth/outlook/index.js +257 -0
- package/lib/providers/providers/auth/squareUp/index.js +111 -0
- package/lib/providers/providers/mock.js +51 -0
- package/lib/server/appController.js +112 -0
- package/lib/server/server.js +73 -0
- package/lib/userContext.js +218 -0
- package/package.json +33 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
const { logger } = require('@vida-global/core');
|
|
2
|
+
const _ = require("lodash");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class VaderUserContext {
|
|
6
|
+
constructor(
|
|
7
|
+
manager
|
|
8
|
+
) {
|
|
9
|
+
this.manager = manager;
|
|
10
|
+
this.context = {};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
APPID_VERSION_KEY (appId, appVersion) {
|
|
14
|
+
return `${appId}:${appVersion}`
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
USER_CONFIG_KEY () {
|
|
18
|
+
return `vader:user:${this.get('user').id}:config`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
USER_APPS_KEY(user) {
|
|
22
|
+
return `vader:user:${this.get('user').id}:installed`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async load(ctx) {
|
|
26
|
+
ctx = ctx || {}
|
|
27
|
+
for (const [key, value] of Object.entries(ctx)) {
|
|
28
|
+
this.set(key, value)
|
|
29
|
+
}
|
|
30
|
+
if (ctx.user && !this.manager.attachedToAppServer) {
|
|
31
|
+
const userConfig = await this.manager.redisClient.hgetall(this.USER_CONFIG_KEY())
|
|
32
|
+
if (userConfig) {
|
|
33
|
+
for (const [key, value] of Object.entries(userConfig)) {
|
|
34
|
+
try {
|
|
35
|
+
this.set(key, JSON.parse(value))
|
|
36
|
+
} catch (e) {
|
|
37
|
+
this.set(key, value)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Load installed apps
|
|
42
|
+
const userAppsKey = this.USER_APPS_KEY()
|
|
43
|
+
const installedApps = await this.manager.redisClient.hgetall(userAppsKey) || {}
|
|
44
|
+
const installedAppIds = Object.keys(installedApps)
|
|
45
|
+
this.set('installedApps', installedAppIds)
|
|
46
|
+
|
|
47
|
+
// Load appVersionIds
|
|
48
|
+
const appVersionIds = await this.getAppVersionIds()
|
|
49
|
+
this.set('appVersionIds', appVersionIds)
|
|
50
|
+
|
|
51
|
+
// Load enabled functions for each installed app
|
|
52
|
+
const enabledFunctions = {}
|
|
53
|
+
for (const appVersionId of installedAppIds) {
|
|
54
|
+
const [appId, appVersion] = appVersionId.split(':')
|
|
55
|
+
enabledFunctions[appVersionId] = this.getEnabledFunctions(appId, appVersion)
|
|
56
|
+
}
|
|
57
|
+
this.set('enabledFunctions', enabledFunctions)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get(name) {
|
|
62
|
+
// && name !== 'customVaderUrl' && name !== 'customVaderToken'
|
|
63
|
+
if (!this.context.hasOwnProperty(name)) {
|
|
64
|
+
// logger.warn(`VADER: User Context Missing Key: ${name}`);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return this.context[name];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
set(name, value) {
|
|
71
|
+
this.context[name] = value;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
toDict() {
|
|
75
|
+
return {...this.context}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
toJSON() {
|
|
79
|
+
return JSON.stringify(this.context)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async getProviderConfig (providerType, providerName, appId = null, appVersion = null) {
|
|
83
|
+
let providerKey = `${providerType}:${providerName}`
|
|
84
|
+
if (appId && appVersion) {
|
|
85
|
+
providerKey = `${appId}:${appVersion}:${providerKey}`
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Only local context is available
|
|
89
|
+
if (this.manager.attachedToAppServer) {
|
|
90
|
+
return this.context[providerKey];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const config = await this.manager.redisClient.hget(
|
|
94
|
+
this.USER_CONFIG_KEY(), providerKey
|
|
95
|
+
) || '{}'
|
|
96
|
+
const parsedConfig = JSON.parse(config);
|
|
97
|
+
this.context[providerKey] = parsedConfig;
|
|
98
|
+
return parsedConfig;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async setProviderConfig (providerType, providerName, config, appId = null, appVersion = null) {
|
|
102
|
+
let providerKey = `${providerType}:${providerName}`
|
|
103
|
+
if (appId && appVersion) {
|
|
104
|
+
providerKey = `${appId}:${appVersion}:${providerKey}`
|
|
105
|
+
}
|
|
106
|
+
return await this.manager.redisClient.hset(
|
|
107
|
+
this.USER_CONFIG_KEY(), providerKey, JSON.stringify(config)
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async deleteProviderConfig (providerType, providerName, appId = null, appVersion = null) {
|
|
112
|
+
let providerKey = `${providerType}:${providerName}`
|
|
113
|
+
if (appId && appVersion) {
|
|
114
|
+
providerKey = `${appId}:${appVersion}:${providerKey}`
|
|
115
|
+
}
|
|
116
|
+
return await this.manager.redisClient.hdel(
|
|
117
|
+
this.USER_CONFIG_KEY(), providerKey
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async fetchAgentAppManifest(appId, appVersion) {
|
|
122
|
+
const agent = this.get('agent')
|
|
123
|
+
const manifest = _.find(agent.apps, a => a.appId === appId && a.version === appVersion)
|
|
124
|
+
return manifest ? manifest : null
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async installApp(appId, appVersion) {
|
|
128
|
+
// Store the installed app manifest
|
|
129
|
+
const appVersionKey = this.APPID_VERSION_KEY(appId, appVersion)
|
|
130
|
+
const userAppsKey = this.USER_APPS_KEY()
|
|
131
|
+
|
|
132
|
+
await this.manager.redisClient.hset(userAppsKey, appVersionKey, 1)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async uninstallApp (appId, appVersion) {
|
|
136
|
+
const appVersionKey = this.APPID_VERSION_KEY(appId, appVersion)
|
|
137
|
+
await this.manager.redisClient.hdel(this.USER_APPS_KEY(), appVersionKey)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async isAppInstalled (appId, appVersion) {
|
|
141
|
+
if (this.manager.attachedToAppServer) {
|
|
142
|
+
return (this.get('installedApps') || []).includes(`${appId}:${appVersion}`)
|
|
143
|
+
}
|
|
144
|
+
const appVersionKey = this.APPID_VERSION_KEY(appId, appVersion)
|
|
145
|
+
return !!await this.manager.redisClient.hexists(this.USER_APPS_KEY(), appVersionKey)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async getAppVersionIds() {
|
|
149
|
+
if (this.manager.attachedToAppServer) {
|
|
150
|
+
return this.get('appVersionIds')
|
|
151
|
+
}
|
|
152
|
+
let appVersionIds
|
|
153
|
+
let agent = this.get('agent')
|
|
154
|
+
if (agent) {
|
|
155
|
+
appVersionIds = _.map(agent.apps, a => `${a.appId}:${a.version}`)
|
|
156
|
+
} else {
|
|
157
|
+
const userToAppsKey = this.USER_APPS_KEY()
|
|
158
|
+
appVersionIds = await this.manager.redisClient.hkeys(userToAppsKey)
|
|
159
|
+
if (!appVersionIds) {
|
|
160
|
+
appVersionIds = []
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return appVersionIds
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
getEnabledFunctions (appId, appVersion) {
|
|
167
|
+
if (this.manager.attachedToAppServer) {
|
|
168
|
+
return this.get('enabledFunctions')[this.APPID_VERSION_KEY(appId, appVersion)] || []
|
|
169
|
+
}
|
|
170
|
+
const agent = this.get('agent')
|
|
171
|
+
const apps = agent?.apps || []
|
|
172
|
+
const appVersionKey = this.APPID_VERSION_KEY(appId, appVersion)
|
|
173
|
+
if (agent && apps.some(a => a.appId === appId && a.version === appVersion)) {
|
|
174
|
+
const enabledFunctions = agent['enabledFunctions'] || {}
|
|
175
|
+
return enabledFunctions[appVersionKey] || []
|
|
176
|
+
} else {
|
|
177
|
+
return []
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* A proxy class that adds vader user context to manager function calls
|
|
184
|
+
*/
|
|
185
|
+
class VaderUserContextProxy {
|
|
186
|
+
constructor(target, context) {
|
|
187
|
+
this.target = target;
|
|
188
|
+
this.context = context;
|
|
189
|
+
|
|
190
|
+
// Create a proxy to intercept function calls
|
|
191
|
+
return new Proxy(this, {
|
|
192
|
+
get: (obj, prop) => {
|
|
193
|
+
// If the property exists on the target and is a function
|
|
194
|
+
if (typeof this.target[prop] === 'function') {
|
|
195
|
+
return this._wrapFunction(prop);
|
|
196
|
+
}
|
|
197
|
+
// For non-function properties, return the target's property
|
|
198
|
+
return this.target[prop];
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
_wrapFunction(functionName) {
|
|
203
|
+
return async (...args) => {
|
|
204
|
+
const vaderUserContext = new VaderUserContext(this.target);
|
|
205
|
+
await vaderUserContext.load(this.context)
|
|
206
|
+
return await this.target[functionName](
|
|
207
|
+
...args,
|
|
208
|
+
vaderUserContext,
|
|
209
|
+
);
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = {
|
|
215
|
+
VaderUserContext,
|
|
216
|
+
VaderUserContextProxy
|
|
217
|
+
}
|
|
218
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vida-global/apps-tools",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Classes for creating vida apps",
|
|
5
|
+
"author": "",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"main": "index.js",
|
|
8
|
+
"directories": {
|
|
9
|
+
"doc": "lib",
|
|
10
|
+
"test": "test"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules node_modules/jest/bin/jest.js"
|
|
14
|
+
},
|
|
15
|
+
"jest": {
|
|
16
|
+
"collectCoverage": true,
|
|
17
|
+
"coveragePathIgnorePatterns": [
|
|
18
|
+
"/test/helpers"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"axios": "^1.8.1",
|
|
23
|
+
"googleapis": "^146.0.0",
|
|
24
|
+
"lodash": "^4.17.21",
|
|
25
|
+
"mcp-client": "^1.13.1",
|
|
26
|
+
"swagger-ui-express": "^5.0.1",
|
|
27
|
+
"@vida-global/core": "^1.1.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"jest": "^29.6.2"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|