feat(trigger): enhance plugin and trigger integration with updated naming conventions

- Refactored `PluginFetchDynamicSelectOptionsApi` to replace the `extra` argument with `credential_id`, improving clarity in dynamic option fetching.
- Updated `ProviderConfigEncrypter` to rename `mask_tool_credentials` to `mask_credentials` for consistency, and added a new method to maintain backward compatibility.
- Enhanced `PluginParameterService` to utilize `credential_id` for fetching subscriptions, improving the handling of trigger credentials.
- Adjusted various components and types in the frontend to replace `tool_name` with `trigger_name`, ensuring consistency across the application.
- Introduced `multiple` property in `TriggerParameter` to support multi-select functionality.

These changes improve the integration of triggers and plugins, enhance code clarity, and align naming conventions across the codebase.
This commit is contained in:
Harry
2025-09-08 23:14:50 +08:00
parent 01b2f9cff6
commit 2a3ce6baa9
40 changed files with 734 additions and 163 deletions

View File

@ -1,8 +1,8 @@
'use client'
import { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import type { BlockEnum } from '../types'
import type { ToolDefaultValue } from './types'
import type { BlockEnum, OnSelectBlock } from '../types'
import type { TriggerDefaultValue } from './types'
import StartBlocks from './start-blocks'
import TriggerPluginSelector from './trigger-plugin-selector'
import { ENTRY_NODE_TYPES } from './constants'
@ -16,7 +16,7 @@ import { SearchMenu } from '@/app/components/base/icons/src/vender/line/general'
type AllStartBlocksProps = {
className?: string
searchText: string
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
onSelect: (type: BlockEnum, trigger?: TriggerDefaultValue) => void
availableBlocksTypes?: BlockEnum[]
tags?: string[]
}
@ -75,7 +75,7 @@ const AllStartBlocks = ({
<>
<StartBlocks
searchText={searchText}
onSelect={onSelect}
onSelect={onSelect as OnSelectBlock}
availableBlocksTypes={ENTRY_NODE_TYPES as unknown as BlockEnum[]}
onContentStateChange={handleStartBlocksContentChange}
/>

View File

@ -86,9 +86,9 @@ const NodeSelector: FC<NodeSelectorProps> = ({
e.stopPropagation()
handleOpenChange(!open)
}, [handleOpenChange, open, disabled])
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
const handleSelect = useCallback<OnSelectBlock>((type, pluginDefaultValue) => {
handleOpenChange(false)
onSelect(type, toolDefaultValue)
onSelect(type, pluginDefaultValue)
}, [handleOpenChange, onSelect])
const [activeTab, setActiveTab] = useState(

View File

@ -3,7 +3,7 @@ import { memo } from 'react'
import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools } from '@/service/use-tools'
import type { BlockEnum } from '../types'
import { useTabs } from './hooks'
import type { ToolDefaultValue } from './types'
import type { PluginDefaultValue } from './types'
import { TabsEnum } from './types'
import Blocks from './blocks'
import AllStartBlocks from './all-start-blocks'
@ -15,7 +15,7 @@ export type TabsProps = {
onActiveTabChange: (activeTab: TabsEnum) => void
searchText: string
tags: string[]
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
onSelect: (type: BlockEnum, plugin?: PluginDefaultValue) => void
availableBlocksTypes?: BlockEnum[]
filterElem: React.ReactNode
noBlocks?: boolean

View File

@ -64,7 +64,7 @@ const ToolItem: FC<Props> = ({
provider_id: provider.id,
provider_type: provider.type,
provider_name: provider.name,
tool_name: payload.name,
trigger_name: payload.name,
tool_label: payload.label[language],
tool_description: payload.description[language],
title: payload.label[language],

View File

@ -165,7 +165,7 @@ const Tool: FC<Props> = ({
provider_id: payload.id,
provider_type: payload.type,
provider_name: payload.name,
tool_name: tool.name,
trigger_name: tool.name,
tool_label: tool.label[language],
tool_description: tool.description[language],
title: tool.label[language],

View File

@ -2,10 +2,10 @@
import { memo } from 'react'
import TriggerPluginList from './trigger-plugin/list'
import type { BlockEnum } from '../types'
import type { ToolDefaultValue } from './types'
import type { TriggerDefaultValue } from './types'
type TriggerPluginSelectorProps = {
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
onSelect: (type: BlockEnum, trigger?: TriggerDefaultValue) => void
searchText: string
onContentStateChange?: (hasContent: boolean) => void
tags?: string[]

View File

@ -2,9 +2,9 @@
import type { FC } from 'react'
import React from 'react'
import type { TriggerWithProvider } from '../types'
import type { Tool } from '@/app/components/tools/types'
import type { Trigger } from '@/app/components/tools/types'
import { BlockEnum } from '../../types'
import type { ToolDefaultValue } from '../types'
import type { TriggerDefaultValue } from '../types'
import Tooltip from '@/app/components/base/tooltip'
import { useGetLanguage } from '@/context/i18n'
import BlockIcon from '../../block-icon'
@ -13,10 +13,10 @@ import { useTranslation } from 'react-i18next'
type Props = {
provider: TriggerWithProvider
payload: Tool
payload: Trigger
disabled?: boolean
isAdded?: boolean
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
onSelect: (type: BlockEnum, trigger?: TriggerDefaultValue) => void
}
const TriggerPluginActionItem: FC<Props> = ({
@ -63,9 +63,9 @@ const TriggerPluginActionItem: FC<Props> = ({
provider_id: provider.id,
provider_type: provider.type as string,
provider_name: provider.name,
tool_name: payload.name,
tool_label: payload.label[language],
tool_description: payload.description[language],
trigger_name: payload.name,
trigger_label: payload.label[language],
trigger_description: payload.description[language],
title: payload.label[language],
is_team_authorization: provider.is_team_authorization,
output_schema: payload.output_schema || {},

View File

@ -1,22 +1,21 @@
'use client'
import type { FC } from 'react'
import React, { useEffect, useMemo, useRef } from 'react'
import { useGetLanguage } from '@/context/i18n'
import cn from '@/utils/classnames'
import { RiArrowDownSLine, RiArrowRightSLine } from '@remixicon/react'
import { useGetLanguage } from '@/context/i18n'
import { CollectionType } from '../../../tools/types'
import type { TriggerWithProvider } from '../types'
import { BlockEnum } from '../../types'
import type { ToolDefaultValue } from '../types'
import TriggerPluginActionItem from './action-item'
import BlockIcon from '../../block-icon'
import type { FC } from 'react'
import React, { useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { CollectionType } from '../../../tools/types'
import BlockIcon from '../../block-icon'
import { BlockEnum } from '../../types'
import type { TriggerDefaultValue, TriggerWithProvider } from '../types'
import TriggerPluginActionItem from './action-item'
type Props = {
className?: string
payload: TriggerWithProvider
hasSearchText: boolean
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
onSelect: (type: BlockEnum, trigger?: TriggerDefaultValue) => void
}
const TriggerPluginItem: FC<Props> = ({
@ -28,7 +27,7 @@ const TriggerPluginItem: FC<Props> = ({
const { t } = useTranslation()
const language = useGetLanguage()
const notShowProvider = payload.type === CollectionType.workflow
const actions = payload.tools
const actions = payload.triggers
const hasAction = !notShowProvider
const [isFold, setFold] = React.useState<boolean>(true)
const ref = useRef(null)
@ -72,10 +71,10 @@ const TriggerPluginItem: FC<Props> = ({
return
}
const tool = actions[0]
const trigger = actions[0]
const params: Record<string, string> = {}
if (tool.parameters) {
tool.parameters.forEach((item) => {
if (trigger.parameters) {
trigger.parameters.forEach((item) => {
params[item.name] = ''
})
}
@ -83,13 +82,13 @@ const TriggerPluginItem: FC<Props> = ({
provider_id: payload.id,
provider_type: payload.type,
provider_name: payload.name,
tool_name: tool.name,
tool_label: tool.label[language],
tool_description: tool.description[language],
title: tool.label[language],
trigger_name: trigger.name,
trigger_label: trigger.label[language],
trigger_description: trigger.description[language],
title: trigger.label[language],
is_team_authorization: payload.is_team_authorization,
output_schema: tool.output_schema || {},
paramSchemas: tool.parameters,
output_schema: trigger.output_schema || {},
paramSchemas: trigger.parameters,
params,
})
}}

View File

@ -3,11 +3,11 @@ import { memo, useEffect, useMemo } from 'react'
import { useAllTriggerPlugins } from '@/service/use-triggers'
import TriggerPluginItem from './item'
import type { BlockEnum } from '../../types'
import type { ToolDefaultValue } from '../types'
import type { TriggerDefaultValue } from '../types'
import { useGetLanguage } from '@/context/i18n'
type TriggerPluginListProps = {
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
onSelect: (type: BlockEnum, trigger?: TriggerDefaultValue) => void
searchText: string
onContentStateChange?: (hasContent: boolean) => void
tags?: string[]
@ -24,13 +24,13 @@ const TriggerPluginList = ({
const triggerPlugins = useMemo(() => {
// Follow exact same pattern as tools
return (triggerPluginsData || []).filter((toolWithProvider) => {
if (toolWithProvider.tools.length === 0) return false
return (triggerPluginsData || []).filter((triggerWithProvider) => {
if (triggerWithProvider.triggers.length === 0) return false
// Filter by search text
if (searchText) {
const matchesSearch = toolWithProvider.name.toLowerCase().includes(searchText.toLowerCase())
|| toolWithProvider.tools.some(tool =>
const matchesSearch = triggerWithProvider.name.toLowerCase().includes(searchText.toLowerCase())
|| triggerWithProvider.triggers.some(tool =>
tool.label[language].toLowerCase().includes(searchText.toLowerCase()),
)
if (!matchesSearch) return false

View File

@ -1,5 +1,5 @@
import type { PluginMeta } from '../../plugins/types'
import type { Collection, Tool } from '../../tools/types'
import type { Collection, Trigger } from '../../tools/types'
import type { TypeWithI18N } from '../../base/form/types'
export enum TabsEnum {
@ -24,11 +24,32 @@ export enum BlockClassificationEnum {
Utilities = 'utilities',
}
export type ToolDefaultValue = {
export type PluginDefaultValue = {
provider_id: string
provider_type: string
provider_name: string
tool_name: string
plugin_name: string
plugin_label: string
}
export type TriggerDefaultValue = PluginDefaultValue & {
trigger_name: string
trigger_label: string
trigger_description: string
title: string
is_team_authorization: boolean
params: Record<string, any>
paramSchemas: Record<string, any>[]
output_schema: Record<string, any>
credential_id?: string
meta?: PluginMeta
}
export type ToolDefaultValue = PluginDefaultValue & {
provider_id: string
provider_type: string
provider_name: string
trigger_name: string
tool_label: string
tool_description: string
title: string
@ -55,6 +76,7 @@ export type ToolValue = {
// Backend API types - exact match with Python definitions
export type TriggerParameter = {
multiple: boolean
name: string
label: TypeWithI18N
description?: TypeWithI18N
@ -141,7 +163,7 @@ export type TriggerProviderApiEntity = {
// Frontend types - compatible with ToolWithProvider
export type TriggerWithProvider = Collection & {
tools: Tool[] // Use existing Tool type for compatibility
triggers: Trigger[]
meta: PluginMeta
credentials_schema?: TriggerCredentialField[]
oauth_client_schema?: TriggerCredentialField[]