Merge pull request #14846 from Budibase/ai-fixes-3.0
BB AI QA testing fixes
This commit is contained in:
commit
e938a41fde
|
@ -31,10 +31,7 @@
|
||||||
|
|
||||||
async function fetchAIConfig() {
|
async function fetchAIConfig() {
|
||||||
try {
|
try {
|
||||||
const aiDoc = await API.getConfig(ConfigTypes.AI)
|
fullAIConfig = await API.getConfig(ConfigTypes.AI)
|
||||||
if (aiDoc._id) {
|
|
||||||
fullAIConfig = aiDoc
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Error fetching AI config")
|
notifications.error("Error fetching AI config")
|
||||||
}
|
}
|
||||||
|
@ -66,6 +63,7 @@
|
||||||
}
|
}
|
||||||
// Add new or update existing custom AI Config
|
// Add new or update existing custom AI Config
|
||||||
fullAIConfig.config[id] = editingAIConfig
|
fullAIConfig.config[id] = editingAIConfig
|
||||||
|
fullAIConfig.type = ConfigTypes.AI
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 297fdc937e9c650b4964fc1a942b60022b195865
|
Subproject commit 60411963053b98e0415a1e9285b721fc26c628c8
|
|
@ -18,6 +18,7 @@ import * as loop from "./steps/loop"
|
||||||
import * as collect from "./steps/collect"
|
import * as collect from "./steps/collect"
|
||||||
import * as branch from "./steps/branch"
|
import * as branch from "./steps/branch"
|
||||||
import * as triggerAutomationRun from "./steps/triggerAutomationRun"
|
import * as triggerAutomationRun from "./steps/triggerAutomationRun"
|
||||||
|
import * as openai from "./steps/openai"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import {
|
import {
|
||||||
PluginType,
|
PluginType,
|
||||||
|
@ -50,6 +51,7 @@ const ACTION_IMPLS: ActionImplType = {
|
||||||
QUERY_ROWS: queryRow.run,
|
QUERY_ROWS: queryRow.run,
|
||||||
COLLECT: collect.run,
|
COLLECT: collect.run,
|
||||||
TRIGGER_AUTOMATION_RUN: triggerAutomationRun.run,
|
TRIGGER_AUTOMATION_RUN: triggerAutomationRun.run,
|
||||||
|
OPENAI: openai.run,
|
||||||
// these used to be lowercase step IDs, maintain for backwards compat
|
// these used to be lowercase step IDs, maintain for backwards compat
|
||||||
discord: discord.run,
|
discord: discord.run,
|
||||||
slack: slack.run,
|
slack: slack.run,
|
||||||
|
@ -89,21 +91,25 @@ export const BUILTIN_ACTION_DEFINITIONS: Record<
|
||||||
// ran at all
|
// ran at all
|
||||||
if (env.SELF_HOSTED) {
|
if (env.SELF_HOSTED) {
|
||||||
const bash = require("./steps/bash")
|
const bash = require("./steps/bash")
|
||||||
const openai = require("./steps/openai")
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
ACTION_IMPLS["EXECUTE_BASH"] = bash.run
|
ACTION_IMPLS["EXECUTE_BASH"] = bash.run
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
BUILTIN_ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
|
BUILTIN_ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
|
||||||
// @ts-ignore
|
|
||||||
ACTION_IMPLS.OPENAI = openai.run
|
|
||||||
BUILTIN_ACTION_DEFINITIONS.OPENAI = openai.definition
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getActionDefinitions() {
|
export async function getActionDefinitions() {
|
||||||
if (await features.flags.isEnabled(FeatureFlag.AUTOMATION_BRANCHING)) {
|
if (await features.flags.isEnabled(FeatureFlag.AUTOMATION_BRANCHING)) {
|
||||||
BUILTIN_ACTION_DEFINITIONS["BRANCH"] = branch.definition
|
BUILTIN_ACTION_DEFINITIONS["BRANCH"] = branch.definition
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
env.SELF_HOSTED ||
|
||||||
|
(await features.flags.isEnabled(FeatureFlag.BUDIBASE_AI)) ||
|
||||||
|
(await features.flags.isEnabled(FeatureFlag.AI_CUSTOM_CONFIGS))
|
||||||
|
) {
|
||||||
|
BUILTIN_ACTION_DEFINITIONS["OPENAI"] = openai.definition
|
||||||
|
}
|
||||||
|
|
||||||
const actionDefinitions = BUILTIN_ACTION_DEFINITIONS
|
const actionDefinitions = BUILTIN_ACTION_DEFINITIONS
|
||||||
if (env.SELF_HOSTED) {
|
if (env.SELF_HOSTED) {
|
||||||
const plugins = await sdk.plugins.fetch(PluginType.AUTOMATION)
|
const plugins = await sdk.plugins.fetch(PluginType.AUTOMATION)
|
||||||
|
|
|
@ -126,16 +126,16 @@ export type ActionImplementations<T extends Hosting> = {
|
||||||
n8nStepInputs,
|
n8nStepInputs,
|
||||||
ExternalAppStepOutputs
|
ExternalAppStepOutputs
|
||||||
>
|
>
|
||||||
|
[AutomationActionStepId.OPENAI]: ActionImplementation<
|
||||||
|
OpenAIStepInputs,
|
||||||
|
OpenAIStepOutputs
|
||||||
|
>
|
||||||
} & (T extends "self"
|
} & (T extends "self"
|
||||||
? {
|
? {
|
||||||
[AutomationActionStepId.EXECUTE_BASH]: ActionImplementation<
|
[AutomationActionStepId.EXECUTE_BASH]: ActionImplementation<
|
||||||
BashStepInputs,
|
BashStepInputs,
|
||||||
BashStepOutputs
|
BashStepOutputs
|
||||||
>
|
>
|
||||||
[AutomationActionStepId.OPENAI]: ActionImplementation<
|
|
||||||
OpenAIStepInputs,
|
|
||||||
OpenAIStepOutputs
|
|
||||||
>
|
|
||||||
}
|
}
|
||||||
: {})
|
: {})
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,7 @@ const getEventFns = async (config: Config, existing?: Config) => {
|
||||||
fns.push(events.email.SMTPCreated)
|
fns.push(events.email.SMTPCreated)
|
||||||
} else if (isAIConfig(config)) {
|
} else if (isAIConfig(config)) {
|
||||||
fns.push(() => events.ai.AIConfigCreated)
|
fns.push(() => events.ai.AIConfigCreated)
|
||||||
fns.push(() =>
|
fns.push(() => pro.quotas.addCustomAIConfig())
|
||||||
pro.quotas.updateCustomAIConfigCount(Object.keys(config.config).length)
|
|
||||||
)
|
|
||||||
} else if (isGoogleConfig(config)) {
|
} else if (isGoogleConfig(config)) {
|
||||||
fns.push(() => events.auth.SSOCreated(ConfigType.GOOGLE))
|
fns.push(() => events.auth.SSOCreated(ConfigType.GOOGLE))
|
||||||
if (config.config.activated) {
|
if (config.config.activated) {
|
||||||
|
@ -85,9 +83,6 @@ const getEventFns = async (config: Config, existing?: Config) => {
|
||||||
fns.push(events.email.SMTPUpdated)
|
fns.push(events.email.SMTPUpdated)
|
||||||
} else if (isAIConfig(config)) {
|
} else if (isAIConfig(config)) {
|
||||||
fns.push(() => events.ai.AIConfigUpdated)
|
fns.push(() => events.ai.AIConfigUpdated)
|
||||||
fns.push(() =>
|
|
||||||
pro.quotas.updateCustomAIConfigCount(Object.keys(config.config).length)
|
|
||||||
)
|
|
||||||
} else if (isGoogleConfig(config)) {
|
} else if (isGoogleConfig(config)) {
|
||||||
fns.push(() => events.auth.SSOUpdated(ConfigType.GOOGLE))
|
fns.push(() => events.auth.SSOUpdated(ConfigType.GOOGLE))
|
||||||
if (!existing.config.activated && config.config.activated) {
|
if (!existing.config.activated && config.config.activated) {
|
||||||
|
@ -253,7 +248,7 @@ export async function save(ctx: UserCtx<Config>) {
|
||||||
if (existingConfig) {
|
if (existingConfig) {
|
||||||
await verifyAIConfig(config, existingConfig)
|
await verifyAIConfig(config, existingConfig)
|
||||||
}
|
}
|
||||||
await pro.quotas.updateCustomAIConfigCount(Object.keys(config).length)
|
await pro.quotas.addCustomAIConfig()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
@ -342,29 +337,43 @@ export async function find(ctx: UserCtx) {
|
||||||
let scopedConfig = await configs.getConfig(type)
|
let scopedConfig = await configs.getConfig(type)
|
||||||
|
|
||||||
if (scopedConfig) {
|
if (scopedConfig) {
|
||||||
if (type === ConfigType.OIDC_LOGOS) {
|
await handleConfigType(type, scopedConfig)
|
||||||
enrichOIDCLogos(scopedConfig)
|
} else if (type === ConfigType.AI) {
|
||||||
}
|
scopedConfig = { config: {} } as AIConfig
|
||||||
|
await handleAIConfig(scopedConfig)
|
||||||
if (type === ConfigType.AI) {
|
|
||||||
await pro.sdk.ai.enrichAIConfig(scopedConfig)
|
|
||||||
// Strip out the API Keys from the response so they don't show in the UI
|
|
||||||
for (const key in scopedConfig.config) {
|
|
||||||
if (scopedConfig.config[key].apiKey) {
|
|
||||||
scopedConfig.config[key].apiKey = PASSWORD_REPLACEMENT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx.body = scopedConfig
|
|
||||||
} else {
|
} else {
|
||||||
// don't throw an error, there simply is nothing to return
|
// If no config found and not AI type, just return an empty body
|
||||||
ctx.body = {}
|
ctx.body = {}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.body = scopedConfig
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
ctx.throw(err?.status || 400, err)
|
ctx.throw(err?.status || 400, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleConfigType(type: ConfigType, config: Config) {
|
||||||
|
if (type === ConfigType.OIDC_LOGOS) {
|
||||||
|
enrichOIDCLogos(config)
|
||||||
|
} else if (type === ConfigType.AI) {
|
||||||
|
await handleAIConfig(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleAIConfig(config: AIConfig) {
|
||||||
|
await pro.sdk.ai.enrichAIConfig(config)
|
||||||
|
stripApiKeys(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
function stripApiKeys(config: AIConfig) {
|
||||||
|
for (const key in config?.config) {
|
||||||
|
if (config.config[key].apiKey) {
|
||||||
|
config.config[key].apiKey = PASSWORD_REPLACEMENT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function publicOidc(ctx: Ctx<void, GetPublicOIDCConfigResponse>) {
|
export async function publicOidc(ctx: Ctx<void, GetPublicOIDCConfigResponse>) {
|
||||||
try {
|
try {
|
||||||
// Find the config with the most granular scope based on context
|
// Find the config with the most granular scope based on context
|
||||||
|
@ -508,6 +517,9 @@ export async function destroy(ctx: UserCtx) {
|
||||||
try {
|
try {
|
||||||
await db.remove(id, rev)
|
await db.remove(id, rev)
|
||||||
await cache.destroy(cache.CacheKey.CHECKLIST)
|
await cache.destroy(cache.CacheKey.CHECKLIST)
|
||||||
|
if (id === configs.generateConfigID(ConfigType.AI)) {
|
||||||
|
await pro.quotas.removeCustomAIConfig()
|
||||||
|
}
|
||||||
ctx.body = { message: "Config deleted successfully" }
|
ctx.body = { message: "Config deleted successfully" }
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
ctx.throw(err.status, err)
|
ctx.throw(err.status, err)
|
||||||
|
|
|
@ -13,10 +13,6 @@ describe("Global configs controller", () => {
|
||||||
await config.afterAll()
|
await config.afterAll()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.resetAllMocks()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Should strip secrets when pulling AI config", async () => {
|
it("Should strip secrets when pulling AI config", async () => {
|
||||||
const data = structures.configs.ai()
|
const data = structures.configs.ai()
|
||||||
await config.api.configs.saveConfig(data)
|
await config.api.configs.saveConfig(data)
|
||||||
|
|
Loading…
Reference in New Issue