Skip to content

Commit

Permalink
fix(entities-plugins): ai-proxy-advanced form (#1769)
Browse files Browse the repository at this point in the history
  • Loading branch information
Leopoldthecoder authored Nov 8, 2024
1 parent 34dc09a commit 0485ca2
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 8 deletions.
27 changes: 19 additions & 8 deletions packages/entities/entities-plugins/src/components/PluginForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ import {
type PluginFormFields,
type PluginFormState,
type PluginOrdering,
type CustomSchemas,
} from '../types'
import PluginEntityForm from './PluginEntityForm.vue'
import PluginFormActionsWrapper from './PluginFormActionsWrapper.vue'
Expand Down Expand Up @@ -502,7 +503,7 @@ const getArrayType = (list: unknown[]): string => {
const buildFormSchema = (parentKey: string, response: Record<string, any>, initialFormSchema: Record<string, any>, arrayNested?: boolean) => {
let schema = (response && response.fields) || []
const pluginSchema = customSchemas[props.pluginType as keyof typeof customSchemas]
const pluginSchema = customSchemas[props.pluginType as keyof CustomSchemas]
const credentialSchema = CREDENTIAL_METADATA[props.pluginType]?.schema?.fields
// schema can either be an object or an array of objects. If it's an array, convert it to an object
Expand Down Expand Up @@ -1005,9 +1006,9 @@ const initScopeFields = (): void => {
}
// apply custom front-end schema if overwriteDefault is true
if (customSchemas[props.pluginType as keyof typeof customSchemas] && customSchemas[props.pluginType as keyof typeof customSchemas].overwriteDefault) {
if (Object.hasOwnProperty.call(customSchemas[props.pluginType as keyof typeof customSchemas], 'formSchema')) {
Object.assign(defaultFormSchema, customSchemas[props.pluginType as keyof typeof customSchemas].formSchema)
if (customSchemas[props.pluginType as keyof CustomSchemas] && customSchemas[props.pluginType as keyof CustomSchemas].overwriteDefault) {
if (Object.hasOwnProperty.call(customSchemas[props.pluginType as keyof CustomSchemas], 'formSchema')) {
Object.assign(defaultFormSchema, customSchemas[props.pluginType as keyof CustomSchemas].formSchema)
}
}
}
Expand Down Expand Up @@ -1176,21 +1177,31 @@ const saveFormData = async (): Promise<void> => {
let response: AxiosResponse | undefined
const payload = JSON.parse(JSON.stringify(getRequestBody.value))
const customSchema = customSchemas[props.pluginType as keyof CustomSchemas]
if (typeof customSchema?.shamefullyTransformPayload === 'function') {
customSchema.shamefullyTransformPayload({
originalModel: formFieldsOriginal,
model: form.fields,
payload,
})
}
// TODO: determine validate URL for credentials
// don't validate custom plugins
if (!treatAsCredential.value && !isCustomPlugin.value) {
await axiosInstance.post(validateSubmitUrl.value, getRequestBody.value)
await axiosInstance.post(validateSubmitUrl.value, payload)
}
if (formType.value === 'create') {
response = await axiosInstance.post(submitUrl.value, getRequestBody.value)
response = await axiosInstance.post(submitUrl.value, payload)
} else if (formType.value === 'edit') {
response = props.config.app === 'konnect'
// Note 1: Konnect currently uses PUT because PATCH is not fully supported in Koko
// If this changes, the `edit` form methods should be re-evaluated/updated accordingly
// Note 2: Because Konnect uses PUT, we need to include dynamic ordering in the request body
? await axiosInstance.put(submitUrl.value, Object.assign({ ordering: dynamicOrdering.value }, getRequestBody.value))
: await axiosInstance.patch(submitUrl.value, getRequestBody.value)
? await axiosInstance.put(submitUrl.value, Object.assign({ ordering: dynamicOrdering.value }, payload))
: await axiosInstance.patch(submitUrl.value, payload)
}
// Set initial state of `formFieldsOriginal` to these values in order to detect changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { customFields, getSharedFormName } from '@kong-ui-public/forms'
import { PLUGIN_METADATA } from '../definitions/metadata'
import { aiPromptDecoratorSchema } from '../definitions/schemas/AIPromptDecorator'
import { aiPromptTemplateSchema } from '../definitions/schemas/AIPromptTemplate'
import { aiProxyAdvancedSchema } from '../definitions/schemas/AIProxyAdvanced'
import { aiRateLimitingAdvancedSchema } from '../definitions/schemas/AIRateLimitingAdvanced'
import { applicationRegistrationSchema } from '../definitions/schemas/ApplicationRegistration'
import { ArrayInputFieldSchema } from '../definitions/schemas/ArrayInputFieldSchema'
Expand Down Expand Up @@ -127,6 +128,10 @@ export const useSchemas = (options?: UseSchemasOptions) => {
...aiPromptTemplateSchema,
},

'ai-proxy-advanced': {
...aiProxyAdvancedSchema,
},

'ai-rate-limiting-advanced': {
...aiRateLimitingAdvancedSchema,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { CommonSchemaFields } from '../../types/plugins/shared'

export const aiProxyAdvancedSchema: CommonSchemaFields = {
// For the ai-proxy-advanced plugin, 'config-embeddings' and 'config-vectordb' fields are non-required
// but they have nested fields that are required. If the nested fields are not provided, 'config-embeddings'
// and 'config-vectordb' should be set to null in the payload.
shamefullyTransformPayload: ({ originalModel, model, payload }) => {
const isDirty = (key: string) => {
// if the model value is the same as the original value
// the field is not dirty
if (originalModel[key] === model[key]) {
return false
}

// if the original value is null, and the model value is not empty or NaN
// the field is dirty
if (originalModel[key] === null) {
return model[key] !== '' && !Number.isNaN(model[key])
}

// if the original value is not null, and the model value is not the same as the original value
// the field is dirty
return true
}

const hasDirtyFields = (prefix: string) => Object.keys(originalModel)
.some(key => key.startsWith(prefix) && isDirty(key))

// If 'config-embeddings-*' fields are not dirty, set 'config-embeddings' to null in the payload
if (!hasDirtyFields('config-embeddings')) {
payload.config.embeddings = null
}
// If 'config-vectordb-*' fields are not dirty, set 'config-vectordb' to null in the payload
if (!hasDirtyFields('config-vectordb')) {
payload.config.vectordb = null
}
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export interface CustomSchemas {
'route-by-header': RouteByHeaderSchema
'ai-prompt-decorator': AIPromptDecoratorSchema
'ai-prompt-template': AIPromptTemplateSchema
'ai-proxy-advanced': CommonSchemaFields
'ai-rate-limiting-advanced': AIRateLimitingAdvancedSchema
'vault-auth': VaultAuthSchema
'graphql-rate-limiting-advanced': GraphQLRateLimitingAdvancedSchema
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ export interface CommonSchemaFields {
id?: string
overwriteDefault?: boolean
formSchema?: Record<string, any>
shamefullyTransformPayload?: (params: { payload: Record<string, any> } & Record<string, any>) => void
}

0 comments on commit 0485ca2

Please sign in to comment.