mirror of https://github.com/langgenius/dify.git
fix(trigger): show event output
This commit is contained in:
parent
5edfbd5305
commit
2c8c1860ca
|
|
@ -193,7 +193,7 @@ const SettingBuiltInTool: FC<Props> = ({
|
|||
onClick={onHide}
|
||||
>
|
||||
<RiArrowLeftLine className='h-4 w-4' />
|
||||
BACK
|
||||
{t('plugin.detailPanel.operation.back')}
|
||||
</div>
|
||||
)}
|
||||
<div className='flex items-center gap-1'>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export type DividerProps = {
|
|||
|
||||
const Divider: FC<DividerProps> = ({ type, bgStyle, className = '', style }) => {
|
||||
return (
|
||||
<div className={classNames(dividerVariants({ type, bgStyle }), className)} style={style}></div>
|
||||
<div className={classNames(dividerVariants({ type, bgStyle }), 'shrink-0', className)} style={style}></div>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const PluginDetailPanel: FC<Props> = ({
|
|||
useEffect(() => {
|
||||
setDetail(!detail ? undefined : {
|
||||
plugin_id: detail.plugin_id,
|
||||
provider: `${detail.plugin_id}/${detail.declaration.trigger.identity.name}`,
|
||||
provider: `${detail.plugin_id}/${detail.declaration.name}`,
|
||||
declaration: detail.declaration,
|
||||
name: detail.name,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from 'zustand'
|
||||
import type { PluginDetail } from '../../types'
|
||||
|
||||
type SimpleDetail = Pick<PluginDetail, 'plugin_id' | 'declaration' | 'name'> & { provider: string }
|
||||
export type SimpleDetail = Pick<PluginDetail, 'plugin_id' | 'declaration' | 'name'> & { provider: string }
|
||||
|
||||
type Shape = {
|
||||
detail: SimpleDetail | undefined
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
'use client'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import Icon from '@/app/components/plugins/card/base/card-icon'
|
||||
|
|
@ -7,8 +8,7 @@ import Description from '@/app/components/plugins/card/base/description'
|
|||
import OrgInfo from '@/app/components/plugins/card/base/org-info'
|
||||
import { triggerEventParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
|
||||
import type { TriggerProviderApiEntity } from '@/app/components/workflow/block-selector/types'
|
||||
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
|
||||
// import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/show/field'
|
||||
import cn from '@/utils/classnames'
|
||||
import {
|
||||
RiArrowLeftLine,
|
||||
|
|
@ -37,16 +37,48 @@ const getType = (type: string, t: TFunction) => {
|
|||
return type
|
||||
}
|
||||
|
||||
// Convert JSON Schema to StructuredOutput format
|
||||
const convertSchemaToField = (schema: any): any => {
|
||||
const field: any = {
|
||||
type: Array.isArray(schema.type) ? schema.type[0] : schema.type || 'string',
|
||||
}
|
||||
|
||||
if (schema.description)
|
||||
field.description = schema.description
|
||||
|
||||
if (schema.properties) {
|
||||
field.properties = Object.entries(schema.properties).reduce((acc, [key, value]: [string, any]) => ({
|
||||
...acc,
|
||||
[key]: convertSchemaToField(value),
|
||||
}), {})
|
||||
}
|
||||
|
||||
if (schema.required)
|
||||
field.required = schema.required
|
||||
|
||||
if (schema.items)
|
||||
field.items = convertSchemaToField(schema.items)
|
||||
|
||||
if (schema.enum)
|
||||
field.enum = schema.enum
|
||||
|
||||
return field
|
||||
}
|
||||
|
||||
export const EventDetailDrawer: FC<EventDetailDrawerProps> = (props) => {
|
||||
const { eventInfo, providerInfo, onClose } = props
|
||||
const language = useLanguage()
|
||||
const { t } = useTranslation()
|
||||
const parametersSchemas = triggerEventParametersToFormSchemas(eventInfo.parameters)
|
||||
const outputVars = Object.entries(eventInfo.output_schema?.properties || {}).map(([name, schema]: [string, any]) => ({
|
||||
name,
|
||||
type: schema.type || 'string',
|
||||
description: schema.description || '',
|
||||
}))
|
||||
|
||||
// Convert output_schema properties to array for direct rendering
|
||||
const outputFields = eventInfo.output_schema?.properties
|
||||
? Object.entries(eventInfo.output_schema.properties).map(([name, schema]: [string, any]) => ({
|
||||
name,
|
||||
field: convertSchemaToField(schema),
|
||||
required: eventInfo.output_schema.required?.includes(name) || false,
|
||||
}))
|
||||
: []
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
|
|
@ -69,7 +101,7 @@ export const EventDetailDrawer: FC<EventDetailDrawerProps> = (props) => {
|
|||
onClick={onClose}
|
||||
>
|
||||
<RiArrowLeftLine className='h-4 w-4' />
|
||||
BACK
|
||||
{t('plugin.detailPanel.operation.back')}
|
||||
</div>
|
||||
<div className='flex items-center gap-1'>
|
||||
<Icon size='tiny' className='h-6 w-6' src={providerInfo.icon!} />
|
||||
|
|
@ -82,45 +114,43 @@ export const EventDetailDrawer: FC<EventDetailDrawerProps> = (props) => {
|
|||
<div className='system-md-semibold mt-1 text-text-primary'>{eventInfo?.identity?.label[language]}</div>
|
||||
<Description className='mb-2 mt-3 h-auto' text={eventInfo.description[language]} descriptionLineRows={2}></Description>
|
||||
</div>
|
||||
<div className='flex h-full flex-col'>
|
||||
<div className='system-sm-semibold-uppercase p-4 pb-1 text-text-primary'>{t('tools.setBuiltInTools.parameters')}</div>
|
||||
<div className='h-0 grow overflow-y-auto px-4'>
|
||||
{parametersSchemas.length > 0 && (
|
||||
<div className='space-y-1 py-2'>
|
||||
{parametersSchemas.map((item, index) => (
|
||||
<div key={index} className='py-1'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='code-sm-semibold text-text-secondary'>{item.label[language]}</div>
|
||||
<div className='system-xs-regular text-text-tertiary'>
|
||||
{getType(item.type, t)}
|
||||
</div>
|
||||
{item.required && (
|
||||
<div className='system-xs-medium text-text-warning-secondary'>{t('tools.setBuiltInTools.required')}</div>
|
||||
)}
|
||||
</div>
|
||||
{item.description && (
|
||||
<div className='system-xs-regular mt-0.5 text-text-tertiary'>
|
||||
{item.description?.[language]}
|
||||
</div>
|
||||
)}
|
||||
<div className='flex h-full flex-col gap-2 overflow-y-auto px-4 pb-2 pt-4'>
|
||||
<div className='system-sm-semibold-uppercase text-text-secondary'>{t('tools.setBuiltInTools.parameters')}</div>
|
||||
{parametersSchemas.length > 0 ? (
|
||||
parametersSchemas.map((item, index) => (
|
||||
<div key={index} className='py-1'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='code-sm-semibold text-text-secondary'>{item.label[language]}</div>
|
||||
<div className='system-xs-regular text-text-tertiary'>
|
||||
{getType(item.type, t)}
|
||||
</div>
|
||||
))}
|
||||
{item.required && (
|
||||
<div className='system-xs-medium text-text-warning-secondary'>{t('tools.setBuiltInTools.required')}</div>
|
||||
)}
|
||||
</div>
|
||||
{item.description && (
|
||||
<div className='system-xs-regular mt-0.5 text-text-tertiary'>
|
||||
{item.description?.[language]}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
))
|
||||
) : <div className='system-xs-regular text-text-tertiary'>{t('pluginTrigger.events.item.noParameters')}</div>}
|
||||
<Divider className='mb-2 mt-1 h-px' />
|
||||
<div className='flex flex-col gap-2'>
|
||||
<div className='system-sm-semibold-uppercase text-text-secondary'>{t('pluginTrigger.events.output')}</div>
|
||||
<div className='relative left-[-7px]'>
|
||||
{outputFields.map(item => (
|
||||
<Field
|
||||
key={item.name}
|
||||
name={item.name}
|
||||
payload={item.field}
|
||||
required={item.required}
|
||||
rootClassName='code-sm-semibold text-text-secondary'
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{/* <Split /> */}
|
||||
<div className='system-sm-semibold-uppercase p-4 pb-1 pt-0 text-text-primary'>{t('pluginTrigger.events.output')}</div>
|
||||
<OutputVars collapsed={false}>
|
||||
{outputVars.map(varItem => (
|
||||
<VarItem
|
||||
key={varItem.name}
|
||||
name={varItem.name}
|
||||
type={varItem.type}
|
||||
description={varItem.description}
|
||||
// isIndent={hasObjectOutput}
|
||||
/>
|
||||
))}
|
||||
</OutputVars>
|
||||
</div>
|
||||
</Drawer>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
'use client'
|
||||
import cn from '@/utils/classnames'
|
||||
import { RiArrowDropDownLine } from '@remixicon/react'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { Field as FieldType } from '../../../../../llm/types'
|
||||
import { Type } from '../../../../../llm/types'
|
||||
import { getFieldType } from '../../../../../llm/utils'
|
||||
import type { Field as FieldType } from '../../../../../llm/types'
|
||||
import cn from '@/utils/classnames'
|
||||
import TreeIndentLine from '../tree-indent-line'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { RiArrowDropDownLine } from '@remixicon/react'
|
||||
|
||||
type Props = {
|
||||
name: string,
|
||||
|
|
@ -28,6 +28,7 @@ const Field: FC<Props> = ({
|
|||
const { t } = useTranslation()
|
||||
const isRoot = depth === 1
|
||||
const hasChildren = payload.type === Type.object && payload.properties
|
||||
const hasEnum = payload.enum && payload.enum.length > 0
|
||||
const [fold, {
|
||||
toggle: toggleFold,
|
||||
}] = useBoolean(false)
|
||||
|
|
@ -44,7 +45,10 @@ const Field: FC<Props> = ({
|
|||
/>
|
||||
)}
|
||||
<div className={cn('system-sm-medium ml-[7px] h-6 truncate leading-6 text-text-secondary', isRoot && rootClassName)}>{name}</div>
|
||||
<div className='system-xs-regular ml-3 shrink-0 leading-6 text-text-tertiary'>{getFieldType(payload)}{(payload.schemaType && payload.schemaType !== 'file' && ` (${payload.schemaType})`)}</div>
|
||||
<div className='system-xs-regular ml-3 shrink-0 leading-6 text-text-tertiary'>
|
||||
{getFieldType(payload)}
|
||||
{(payload.schemaType && payload.schemaType !== 'file' && ` (${payload.schemaType})`)}
|
||||
</div>
|
||||
{required && <div className='system-2xs-medium-uppercase ml-3 leading-6 text-text-warning'>{t('app.structOutput.required')}</div>}
|
||||
</div>
|
||||
{payload.description && (
|
||||
|
|
@ -52,6 +56,18 @@ const Field: FC<Props> = ({
|
|||
<div className='system-xs-regular w-0 grow truncate text-text-tertiary'>{payload.description}</div>
|
||||
</div>
|
||||
)}
|
||||
{hasEnum && (
|
||||
<div className='ml-[7px] flex'>
|
||||
<div className='system-xs-regular w-0 grow text-text-quaternary'>
|
||||
{payload.enum!.map((value, index) => (
|
||||
<span key={index}>
|
||||
{typeof value === 'string' ? `"${value}"` : value}
|
||||
{index < payload.enum!.length - 1 && ' | '}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ export enum Type {
|
|||
arrayNumber = 'array[number]',
|
||||
arrayObject = 'array[object]',
|
||||
file = 'file',
|
||||
enumType = 'enum',
|
||||
}
|
||||
|
||||
export enum ArrayType {
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ export const checkNodeValid = (_payload: LLMNodeType) => {
|
|||
}
|
||||
|
||||
export const getFieldType = (field: Field) => {
|
||||
const { type, items } = field
|
||||
if(field.schemaType === 'file') return Type.file
|
||||
const { type, items, enum: enums } = field
|
||||
if (field.schemaType === 'file') return Type.file
|
||||
if (enums && enums.length > 0) return Type.enumType
|
||||
if (type !== Type.array || !items)
|
||||
return type
|
||||
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ const translation = {
|
|||
actionNum: '{{num}} {{event}} INCLUDED',
|
||||
item: {
|
||||
parameters: '{{count}} parameters',
|
||||
noParameters: 'No parameters',
|
||||
},
|
||||
output: 'Output',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ const translation = {
|
|||
checkUpdate: 'Check Update',
|
||||
viewDetail: 'View Detail',
|
||||
remove: 'Remove',
|
||||
back: 'Back',
|
||||
},
|
||||
actionNum: '{{num}} {{action}} INCLUDED',
|
||||
strategyNum: '{{num}} {{strategy}} INCLUDED',
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ const translation = {
|
|||
actionNum: '包含 {{num}} 个 {{event}}',
|
||||
item: {
|
||||
parameters: '{{count}}个参数',
|
||||
noParameters: '暂无参数',
|
||||
},
|
||||
output: '输出',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ const translation = {
|
|||
checkUpdate: '检查更新',
|
||||
viewDetail: '查看详情',
|
||||
remove: '移除',
|
||||
back: '返回',
|
||||
},
|
||||
actionNum: '包含 {{num}} 个 {{action}}',
|
||||
strategyNum: '包含 {{num}} 个 {{strategy}}',
|
||||
|
|
@ -79,7 +80,7 @@ const translation = {
|
|||
endpointModalDesc: '完成配置后可使用插件 API 端点提供的功能',
|
||||
serviceOk: '服务正常',
|
||||
disabled: '停用',
|
||||
modelNum: '{{num}} 模型已包含',
|
||||
modelNum: '包含 {{num}} 个模型',
|
||||
toolSelector: {
|
||||
title: '添加工具',
|
||||
toolSetting: '工具设置',
|
||||
|
|
|
|||
Loading…
Reference in New Issue