@budibase/worker 3.31.9 → 3.32.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.
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/worker",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.32.0",
|
|
5
5
|
"description": "Budibase background service",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"supertest": "6.3.3",
|
|
92
92
|
"timekeeper": "2.2.0"
|
|
93
93
|
},
|
|
94
|
-
"gitHead": "
|
|
94
|
+
"gitHead": "53fe38782b652197983a8ec2da7761f3135047b6"
|
|
95
95
|
}
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
filterValidTranslationOverrides,
|
|
16
16
|
} from "@budibase/shared-core"
|
|
17
17
|
import {
|
|
18
|
-
AIInnerConfig,
|
|
19
18
|
Config,
|
|
20
19
|
ConfigChecklistResponse,
|
|
21
20
|
ConfigType,
|
|
@@ -27,7 +26,6 @@ import {
|
|
|
27
26
|
GetPublicTranslationsResponse,
|
|
28
27
|
GoogleInnerConfig,
|
|
29
28
|
TranslationOverrides,
|
|
30
|
-
isAIConfig,
|
|
31
29
|
isGoogleConfig,
|
|
32
30
|
isOIDCConfig,
|
|
33
31
|
isRecaptchaConfig,
|
|
@@ -62,8 +60,6 @@ const getEventFns = async (config: Config, existing?: Config) => {
|
|
|
62
60
|
if (!existing) {
|
|
63
61
|
if (isSMTPConfig(config)) {
|
|
64
62
|
fns.push(events.email.SMTPCreated)
|
|
65
|
-
} else if (isAIConfig(config)) {
|
|
66
|
-
fns.push(() => events.ai.AIConfigCreated)
|
|
67
63
|
} else if (isGoogleConfig(config)) {
|
|
68
64
|
fns.push(() => events.auth.SSOCreated(ConfigType.GOOGLE))
|
|
69
65
|
if (config.config.activated) {
|
|
@@ -100,8 +96,6 @@ const getEventFns = async (config: Config, existing?: Config) => {
|
|
|
100
96
|
} else {
|
|
101
97
|
if (isSMTPConfig(config)) {
|
|
102
98
|
fns.push(events.email.SMTPUpdated)
|
|
103
|
-
} else if (isAIConfig(config)) {
|
|
104
|
-
fns.push(() => events.ai.AIConfigUpdated)
|
|
105
99
|
} else if (isGoogleConfig(config)) {
|
|
106
100
|
fns.push(() => events.auth.SSOUpdated(ConfigType.GOOGLE))
|
|
107
101
|
if (!existing.config.activated && config.config.activated) {
|
|
@@ -266,33 +260,6 @@ async function processOIDCConfig(config: OIDCConfigs, existing?: OIDCConfigs) {
|
|
|
266
260
|
}
|
|
267
261
|
}
|
|
268
262
|
|
|
269
|
-
export async function processAIConfig(
|
|
270
|
-
newConfig: AIInnerConfig,
|
|
271
|
-
existingConfig: AIInnerConfig
|
|
272
|
-
) {
|
|
273
|
-
for (const key in existingConfig) {
|
|
274
|
-
if (newConfig[key]?.apiKey === PASSWORD_REPLACEMENT) {
|
|
275
|
-
newConfig[key].apiKey = existingConfig[key].apiKey
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
let numBudibaseAI = 0
|
|
280
|
-
for (const config of Object.values(newConfig)) {
|
|
281
|
-
if (config.provider === "BudibaseAI") {
|
|
282
|
-
numBudibaseAI++
|
|
283
|
-
if (numBudibaseAI > 1) {
|
|
284
|
-
throw new BadRequestError("Only one Budibase AI provider is allowed")
|
|
285
|
-
}
|
|
286
|
-
} else {
|
|
287
|
-
if (!config.apiKey) {
|
|
288
|
-
throw new BadRequestError(
|
|
289
|
-
`API key is required for provider ${config.provider}`
|
|
290
|
-
)
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
263
|
export async function processRecaptchaConfig(
|
|
297
264
|
config: RecaptchaInnerConfig,
|
|
298
265
|
existingConfig?: RecaptchaInnerConfig
|
|
@@ -407,11 +374,6 @@ export async function save(
|
|
|
407
374
|
case ConfigType.OIDC:
|
|
408
375
|
await processOIDCConfig(config, existingConfig?.config)
|
|
409
376
|
break
|
|
410
|
-
case ConfigType.AI:
|
|
411
|
-
if (existingConfig) {
|
|
412
|
-
await processAIConfig(config, existingConfig.config)
|
|
413
|
-
}
|
|
414
|
-
break
|
|
415
377
|
case ConfigType.RECAPTCHA:
|
|
416
378
|
await processRecaptchaConfig(config, existingConfig?.config)
|
|
417
379
|
break
|
|
@@ -521,7 +483,7 @@ export async function find(ctx: UserCtx<void, FindConfigResponse>) {
|
|
|
521
483
|
}
|
|
522
484
|
|
|
523
485
|
function stripSecrets(config: Config, ctx?: UserCtx) {
|
|
524
|
-
if (
|
|
486
|
+
if (config.type === ConfigType.AI) {
|
|
525
487
|
for (const key in config.config) {
|
|
526
488
|
if (config.config[key].apiKey) {
|
|
527
489
|
config.config[key].apiKey = PASSWORD_REPLACEMENT
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
tenancy,
|
|
8
8
|
utils,
|
|
9
9
|
} from "@budibase/backend-core"
|
|
10
|
-
import {
|
|
10
|
+
import { groups } from "@budibase/pro"
|
|
11
11
|
import {
|
|
12
12
|
DevInfo,
|
|
13
13
|
FetchAPIKeyResponse,
|
|
@@ -116,13 +116,6 @@ export async function getSelf(ctx: UserCtx<void, GetGlobalSelfResponse>) {
|
|
|
116
116
|
|
|
117
117
|
// add the feature flags for this tenant
|
|
118
118
|
const flags = await features.flags.fetch()
|
|
119
|
-
const llmConfig = await ai.getLLMConfig()
|
|
120
|
-
const sanitisedLLMConfig = llmConfig
|
|
121
|
-
? {
|
|
122
|
-
provider: llmConfig.provider,
|
|
123
|
-
model: llmConfig.model,
|
|
124
|
-
}
|
|
125
|
-
: undefined
|
|
126
119
|
|
|
127
120
|
const settingsConfig = await configs.getSettingsConfig()
|
|
128
121
|
|
|
@@ -130,7 +123,6 @@ export async function getSelf(ctx: UserCtx<void, GetGlobalSelfResponse>) {
|
|
|
130
123
|
...enrichedUser,
|
|
131
124
|
...sessionAttributes,
|
|
132
125
|
flags,
|
|
133
|
-
llm: sanitisedLLMConfig,
|
|
134
126
|
lockedBy: settingsConfig?.lockedBy,
|
|
135
127
|
}
|
|
136
128
|
}
|
|
@@ -64,22 +64,6 @@ function scimValidation() {
|
|
|
64
64
|
}).unknown(true)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
function aiValidation() {
|
|
68
|
-
// prettier-ignore
|
|
69
|
-
return Joi.object().pattern(
|
|
70
|
-
Joi.string(),
|
|
71
|
-
Joi.object({
|
|
72
|
-
provider: Joi.string().required(),
|
|
73
|
-
isDefault: Joi.boolean().required(),
|
|
74
|
-
name: Joi.string().required(),
|
|
75
|
-
active: Joi.boolean().required(),
|
|
76
|
-
baseUrl: Joi.string().optional().allow("", null),
|
|
77
|
-
apiKey: Joi.string().optional(),
|
|
78
|
-
defaultModel: Joi.string().optional(),
|
|
79
|
-
}).required()
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
67
|
function recaptchaValidation() {
|
|
84
68
|
return Joi.object({
|
|
85
69
|
siteKey: Joi.string().required(),
|
|
@@ -124,7 +108,6 @@ function buildConfigSaveValidation() {
|
|
|
124
108
|
{ is: ConfigType.GOOGLE, then: googleValidation() },
|
|
125
109
|
{ is: ConfigType.OIDC, then: oidcValidation() },
|
|
126
110
|
{ is: ConfigType.SCIM, then: scimValidation() },
|
|
127
|
-
{ is: ConfigType.AI, then: aiValidation() },
|
|
128
111
|
{ is: ConfigType.RECAPTCHA, then: recaptchaValidation() },
|
|
129
112
|
{ is: ConfigType.TRANSLATIONS, then: translationsValidation() },
|
|
130
113
|
],
|
package/src/tests/api/configs.ts
CHANGED
|
@@ -32,10 +32,6 @@ export class ConfigAPI extends TestAPI {
|
|
|
32
32
|
.expect("Content-Type", /json/)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
getAIConfig = async () => {
|
|
36
|
-
return await this.getConfig(ConfigType.AI)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
35
|
getConfig = async <T extends ConfigType>(type: T) => {
|
|
40
36
|
const resp = await this.request
|
|
41
37
|
.get(`/api/global/configs/${type}`)
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { TestConfiguration } from "../../../../tests"
|
|
2
|
-
import { AIConfig, ConfigType } from "@budibase/types"
|
|
3
|
-
import { configs, context } from "@budibase/backend-core"
|
|
4
|
-
|
|
5
|
-
const BASE_CONFIG: AIConfig = {
|
|
6
|
-
type: ConfigType.AI,
|
|
7
|
-
config: {
|
|
8
|
-
ai: {
|
|
9
|
-
provider: "OpenAI",
|
|
10
|
-
isDefault: false,
|
|
11
|
-
name: "Test",
|
|
12
|
-
active: true,
|
|
13
|
-
defaultModel: "gpt4",
|
|
14
|
-
apiKey: "myapikey",
|
|
15
|
-
baseUrl: "https://api.example.com",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
describe("Global configs controller", () => {
|
|
21
|
-
const config = new TestConfiguration()
|
|
22
|
-
|
|
23
|
-
beforeAll(async () => {
|
|
24
|
-
await config.beforeAll()
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
afterAll(async () => {
|
|
28
|
-
await config.afterAll()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it("should strip secrets when pulling AI config", async () => {
|
|
32
|
-
await config.api.configs.saveConfig(BASE_CONFIG)
|
|
33
|
-
const response = await config.api.configs.getAIConfig()
|
|
34
|
-
expect(response.config.ai.apiKey).toEqual("--secret-value--")
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it("should not update existing secrets when updating an existing AI Config", async () => {
|
|
38
|
-
await config.api.configs.saveConfig(BASE_CONFIG)
|
|
39
|
-
|
|
40
|
-
const savedConfig = await config.api.configs.getAIConfig()
|
|
41
|
-
delete savedConfig._id
|
|
42
|
-
delete savedConfig._rev
|
|
43
|
-
delete savedConfig.createdAt
|
|
44
|
-
delete savedConfig.updatedAt
|
|
45
|
-
|
|
46
|
-
await config.api.configs.saveConfig(savedConfig)
|
|
47
|
-
|
|
48
|
-
await context.doInTenant(config.tenantId, async () => {
|
|
49
|
-
const aiConfig = await configs.getAIConfig()
|
|
50
|
-
expect(aiConfig!.config.ai.apiKey).toEqual(BASE_CONFIG.config.ai.apiKey)
|
|
51
|
-
})
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it("should allow BudibaseAI to save without an apiKey", async () => {
|
|
55
|
-
await config.api.configs.saveConfig({
|
|
56
|
-
type: ConfigType.AI,
|
|
57
|
-
config: {
|
|
58
|
-
ai: {
|
|
59
|
-
name: "Budibase AI",
|
|
60
|
-
active: true,
|
|
61
|
-
provider: "BudibaseAI",
|
|
62
|
-
isDefault: true,
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
const aiConfig = await config.api.configs.getAIConfig()
|
|
68
|
-
expect(aiConfig.config.ai).toEqual({
|
|
69
|
-
name: "Budibase AI",
|
|
70
|
-
provider: "BudibaseAI",
|
|
71
|
-
active: true,
|
|
72
|
-
isDefault: true,
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it("should not allow OpenAI to save without an apiKey", async () => {
|
|
77
|
-
await config.api.configs.saveConfig(
|
|
78
|
-
{
|
|
79
|
-
type: ConfigType.AI,
|
|
80
|
-
config: {
|
|
81
|
-
ai: {
|
|
82
|
-
name: "OpenAI",
|
|
83
|
-
active: true,
|
|
84
|
-
provider: "OpenAI",
|
|
85
|
-
isDefault: true,
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
status: 400,
|
|
91
|
-
body: {
|
|
92
|
-
message: /API key is required for provider OpenAI/,
|
|
93
|
-
},
|
|
94
|
-
}
|
|
95
|
-
)
|
|
96
|
-
})
|
|
97
|
-
})
|