Implemented [Dify.AI](https://dify.ai) Block - Dify Features: -- Can Create Multiple Chat Bots -- Assign Knowledge base/vector database to chat bots -- Variables send by client to be used in the prompt -- Options of custom and cloud AI LLMs to be changed with on click - Dify API Function/Action Implemented -- Create Chat Message (Takes in input variables, query, conversation id, user id and returns answer, usage metadata and conversation id) - Future Implantations with this block -- Streaming response -- File Upload for GPT Vision -- Speech to text action <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced the ability to create chat messages within the Dify platform. - Added secure authentication for Dify.AI accounts. - Implemented a new Dify.AI block with integrated chat message creation and logo display. - Enabled Dify.AI block in the repository for user access. - **Enhancements** - Enhanced security for API key input by changing it to a password field. - **Documentation** - Included new types to support Dify AI service responses. - **Refactor** - Updated schema imports and array listings to include the new Dify.AI block. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Baptiste Arnaud <baptiste.arnaud95@gmail.com>
148 lines
3.9 KiB
TypeScript
148 lines
3.9 KiB
TypeScript
import { ZodRawShape } from 'zod'
|
|
import { AuthDefinition, BlockDefinition, ActionDefinition } from './types'
|
|
import { z } from './zod'
|
|
|
|
export const variableStringSchema = z.custom<`{{${string}}}`>((val) =>
|
|
/^{{.+}}$/g.test(val as string)
|
|
)
|
|
|
|
export const createAuth = <A extends AuthDefinition>(authDefinition: A) =>
|
|
authDefinition
|
|
|
|
export const createBlock = <
|
|
I extends string,
|
|
A extends AuthDefinition,
|
|
O extends z.ZodObject<any>
|
|
>(
|
|
blockDefinition: BlockDefinition<I, A, O>
|
|
): BlockDefinition<I, A, O> => blockDefinition
|
|
|
|
export const createAction = <
|
|
A extends AuthDefinition,
|
|
BaseOptions extends z.ZodObject<ZodRawShape> = z.ZodObject<{}>,
|
|
O extends z.ZodObject<ZodRawShape> = z.ZodObject<{}>
|
|
>(
|
|
actionDefinition: {
|
|
auth?: A
|
|
baseOptions?: BaseOptions
|
|
} & ActionDefinition<A, BaseOptions, O>
|
|
) => actionDefinition
|
|
|
|
export const parseBlockSchema = <
|
|
I extends string,
|
|
A extends AuthDefinition,
|
|
O extends z.ZodObject<any>
|
|
>(
|
|
blockDefinition: BlockDefinition<I, A, O>
|
|
) => {
|
|
const options = z.discriminatedUnion('action', [
|
|
blockDefinition.options
|
|
? blockDefinition.options.extend({
|
|
credentialsId: z.string().optional(),
|
|
action: z.undefined(),
|
|
})
|
|
: z.object({
|
|
credentialsId: z.string().optional(),
|
|
action: z.undefined(),
|
|
}),
|
|
...blockDefinition.actions.map((action) =>
|
|
blockDefinition.options
|
|
? (blockDefinition.options
|
|
.extend({
|
|
credentialsId: z.string().optional(),
|
|
})
|
|
.extend({
|
|
action: z.literal(action.name),
|
|
})
|
|
.merge(action.options ?? z.object({})) as any)
|
|
: z
|
|
.object({
|
|
credentialsId: z.string().optional(),
|
|
})
|
|
.extend({
|
|
action: z.literal(action.name),
|
|
})
|
|
.merge(action.options ?? z.object({}))
|
|
),
|
|
])
|
|
return z.object({
|
|
id: z.string(),
|
|
outgoingEdgeId: z.string().optional(),
|
|
type: z.literal(blockDefinition.id),
|
|
options: options.optional(),
|
|
})
|
|
}
|
|
|
|
export const parseBlockCredentials = <
|
|
I extends string,
|
|
A extends AuthDefinition,
|
|
O extends z.ZodObject<any>
|
|
>(
|
|
blockDefinition: BlockDefinition<I, A, O>
|
|
) => {
|
|
if (!blockDefinition.auth) throw new Error('Block has no auth definition')
|
|
return z.object({
|
|
id: z.string(),
|
|
type: z.literal(blockDefinition.id),
|
|
createdAt: z.date(),
|
|
workspaceId: z.string(),
|
|
name: z.string(),
|
|
iv: z.string(),
|
|
data: blockDefinition.auth.schema,
|
|
})
|
|
}
|
|
|
|
export const option = {
|
|
object: <T extends z.ZodRawShape>(schema: T) => z.object(schema),
|
|
literal: <T extends string>(value: T) => z.literal(value),
|
|
string: z.string().optional(),
|
|
boolean: z.boolean().optional(),
|
|
enum: <T extends string>(values: readonly [T, ...T[]]) =>
|
|
z.enum(values).optional(),
|
|
number: z.number().or(variableStringSchema).optional(),
|
|
array: <T extends z.ZodTypeAny>(schema: T) => z.array(schema).optional(),
|
|
keyValueList: z
|
|
.array(
|
|
z.object({
|
|
key: z.string().optional().layout({
|
|
label: 'Key',
|
|
}),
|
|
value: z.string().optional().layout({
|
|
label: 'Value',
|
|
}),
|
|
})
|
|
)
|
|
.optional(),
|
|
discriminatedUnion: <
|
|
T extends string,
|
|
J extends [
|
|
z.ZodDiscriminatedUnionOption<T>,
|
|
...z.ZodDiscriminatedUnionOption<T>[]
|
|
]
|
|
>(
|
|
field: T,
|
|
schemas: J
|
|
) =>
|
|
// @ts-expect-error
|
|
z.discriminatedUnion<T, J>(field, [
|
|
z.object({ [field]: z.undefined() }),
|
|
...schemas,
|
|
]),
|
|
saveResponseArray: <I extends readonly [string, ...string[]]>(items: I) =>
|
|
z
|
|
.array(
|
|
z.object({
|
|
item: z.enum(items).optional().layout({
|
|
placeholder: 'Select a response',
|
|
defaultValue: items[0],
|
|
}),
|
|
variableId: z.string().optional().layout({
|
|
inputType: 'variableDropdown',
|
|
}),
|
|
})
|
|
)
|
|
.optional(),
|
|
}
|
|
|
|
export type * from './types'
|