From bcfdd07f855323ac947f3f1138f67b1776d754d3 Mon Sep 17 00:00:00 2001 From: zhsama Date: Fri, 26 Sep 2025 23:27:27 +0800 Subject: [PATCH] feat(plugin): enhance trigger events list with dynamic tool integration - Refactor TriggerEventsList component to utilize provider information for dynamic tool rendering. - Implement locale-aware text handling for trigger descriptions and labels. - Introduce utility functions for better management of tool parameters and trigger descriptions. - Improve user experience by ensuring consistent display of trigger events based on available provider data. This update enhances the functionality and maintainability of the trigger events list, aligning with the project's metadata-driven approach. --- .../trigger-events-list.tsx | 158 ++++++++++++++++-- 1 file changed, 141 insertions(+), 17 deletions(-) diff --git a/web/app/components/plugins/plugin-detail-panel/trigger-events-list.tsx b/web/app/components/plugins/plugin-detail-panel/trigger-events-list.tsx index 4a3815e07b..c6fc510be5 100644 --- a/web/app/components/plugins/plugin-detail-panel/trigger-events-list.tsx +++ b/web/app/components/plugins/plugin-detail-panel/trigger-events-list.tsx @@ -1,39 +1,163 @@ -import React from 'react' +import React, { useContext, useMemo } from 'react' import { useTranslation } from 'react-i18next' +import I18n from '@/context/i18n' +import { getLanguage } from '@/i18n-config/language' import ToolItem from '@/app/components/tools/provider/tool-item' import { usePluginStore } from './store' +import { useTriggerProviderInfo } from '@/service/use-triggers' +import type { Tool, ToolParameter } from '@/app/components/tools/types' +import { CollectionType } from '@/app/components/tools/types' +import type { ToolWithProvider } from '@/app/components/workflow/types' +import type { TypeWithI18N } from '@/app/components/header/account-setting/model-provider-page/declarations' +import type { Trigger } from '@/app/components/plugins/types' + +type TriggerOption = { + value: string + label: TypeWithI18N + icon?: string | null +} + +const pickLocaleText = (value?: TypeWithI18N | string, fallback = '', language = 'en_US'): string => { + if (!value) + return fallback + if (typeof value === 'string') + return value + const typedValue = value as Record + return typedValue[language] ?? typedValue.en_US ?? Object.values(typedValue)[0] ?? fallback +} + +const getTriggerDescription = (description: TypeWithI18N | { human?: TypeWithI18N | string } | string | undefined, language = 'en_US'): string => { + if (!description) + return '' + + if (typeof description === 'string') + return description + + if (typeof description === 'object' && 'human' in description) { + const human = (description as { human?: TypeWithI18N | string }).human + return pickLocaleText(human, '', language) + } + + return pickLocaleText(description as TypeWithI18N, '', language) +} + +const toToolParameter = (parameter: any): ToolParameter => { + const paramLabel = parameter.label as TypeWithI18N + const paramDescription = parameter.description as TypeWithI18N | undefined + + return { + name: parameter.name, + label: paramLabel, + human_description: paramDescription || paramLabel, + type: parameter.type, + form: 'setting', + llm_description: typeof paramDescription === 'object' ? (paramDescription.en_US || '') : (paramDescription || ''), + required: parameter.required ?? false, + multiple: parameter.multiple ?? false, + default: parameter.default ?? '', + options: parameter.options?.map((option: TriggerOption) => ({ + label: option.label, + value: option.value, + })) || [], + } +} + +const toTool = (trigger: Trigger, fallbackAuthor: string): Tool => { + const name = trigger.identity?.name || '' + const label = trigger.identity?.label || { en_US: name } + const description = trigger.description?.human || trigger.description || { en_US: '' } + return { + name, + author: trigger.identity?.author || fallbackAuthor, + label: label as TypeWithI18N, + description: description as TypeWithI18N, + parameters: (trigger.parameters || []).map((param: any) => toToolParameter(param)), + labels: [], + output_schema: trigger.output_schema || {}, + } +} export const TriggerEventsList = () => { const { t } = useTranslation() + const { locale } = useContext(I18n) + const language = getLanguage(locale) const detail = usePluginStore(state => state.detail) const triggers = detail?.declaration.trigger?.triggers || [] + const providerKey = useMemo(() => { + if (!detail?.plugin_id || !detail?.declaration?.name) + return '' + return `${detail.plugin_id}/${detail.declaration.name}` + }, [detail?.plugin_id, detail?.declaration?.name]) + + const { data: providerInfo } = useTriggerProviderInfo(providerKey, !!providerKey) + + const collection = useMemo(() => { + if (!detail || !providerInfo) + return undefined + + const tools = (providerInfo.triggers || []).map((trigger: any) => toTool(trigger, providerInfo.author)) + + const metaVersion = detail.declaration.meta?.version || detail.version || '1.0' + + return { + id: providerInfo.plugin_id || providerInfo.name, + name: providerInfo.name, + author: providerInfo.author, + description: providerInfo.description, + icon: providerInfo.icon || providerInfo.icon_dark || '', + label: providerInfo.label, + type: CollectionType.builtIn, + team_credentials: {}, + is_team_authorization: false, + allow_delete: false, + labels: providerInfo.tags || [], + plugin_id: providerInfo.plugin_id || detail.plugin_id, + tools, + meta: { version: metaVersion }, + } + }, [detail, providerInfo]) if (!triggers.length) return null - // todo: add collection & update ToolItem return (
- {t('pluginTrigger.events.actionNum', { num: triggers.length, event: triggers.length > 1 ? 'events' : 'event' })} + {t('pluginTrigger.events.actionNum', { num: triggers.length, event: t(`pluginTrigger.events.${triggers.length > 1 ? 'events' : 'event'}`) })}
- {triggers.map(triggerEvent => ( - - tool={{ - label: triggerEvent.identity.label as any, - description: triggerEvent.description.human, - }} - isBuiltIn={false} - isModel={false} - /> - ))} + {collection + ? triggers.map((triggerEvent: Trigger) => { + const triggerName = triggerEvent.identity?.name || '' + const tool = collection.tools.find(item => item.name === triggerName) + || toTool(triggerEvent, collection.author) + + return ( + + ) + }) + : triggers.map((triggerEvent: Trigger) => ( +
+
+ {pickLocaleText(triggerEvent.identity?.label as TypeWithI18N, triggerEvent.identity?.name || '', language)} +
+
+ {getTriggerDescription(triggerEvent.description, language)} +
+
+ ))}
)