strategy-detail.tsx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useMemo } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import {
  6. RiArrowLeftLine,
  7. RiCloseLine,
  8. } from '@remixicon/react'
  9. import Drawer from '@/app/components/base/drawer'
  10. import ActionButton from '@/app/components/base/action-button'
  11. import Icon from '@/app/components/plugins/card/base/card-icon'
  12. import Description from '@/app/components/plugins/card/base/description'
  13. import Divider from '@/app/components/base/divider'
  14. import type {
  15. StrategyDetail,
  16. } from '@/app/components/plugins/types'
  17. import type { Locale } from '@/i18n'
  18. import { useRenderI18nObject } from '@/hooks/use-i18n'
  19. import { API_PREFIX } from '@/config'
  20. import cn from '@/utils/classnames'
  21. type Props = {
  22. provider: {
  23. author: string
  24. name: string
  25. description: Record<Locale, string>
  26. tenant_id: string
  27. icon: string
  28. label: Record<Locale, string>
  29. tags: string[]
  30. }
  31. detail: StrategyDetail
  32. onHide: () => void
  33. }
  34. const StrategyDetail: FC<Props> = ({
  35. provider,
  36. detail,
  37. onHide,
  38. }) => {
  39. const getValueFromI18nObject = useRenderI18nObject()
  40. const { t } = useTranslation()
  41. const outputSchema = useMemo(() => {
  42. const res: any[] = []
  43. if (!detail.output_schema)
  44. return []
  45. Object.keys(detail.output_schema.properties).forEach((outputKey) => {
  46. const output = detail.output_schema.properties[outputKey]
  47. res.push({
  48. name: outputKey,
  49. type: output.type === 'array'
  50. ? `Array[${output.items?.type.slice(0, 1).toLocaleUpperCase()}${output.items?.type.slice(1)}]`
  51. : `${output.type.slice(0, 1).toLocaleUpperCase()}${output.type.slice(1)}`,
  52. description: output.description,
  53. })
  54. })
  55. return res
  56. }, [detail.output_schema])
  57. const getType = (type: string) => {
  58. if (type === 'number-input')
  59. return t('tools.setBuiltInTools.number')
  60. if (type === 'text-input')
  61. return t('tools.setBuiltInTools.string')
  62. if (type === 'file')
  63. return t('tools.setBuiltInTools.file')
  64. if (type === 'array[tools]')
  65. return 'multiple-tool-select'
  66. return type
  67. }
  68. return (
  69. <Drawer
  70. isOpen
  71. clickOutsideNotOpen={false}
  72. onClose={onHide}
  73. footer={null}
  74. mask={false}
  75. positionCenter={false}
  76. panelClassname={cn('justify-start mt-[64px] mr-2 mb-2 !w-[420px] !max-w-[420px] !p-0 !bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl')}
  77. >
  78. <>
  79. {/* header */}
  80. <div className='relative p-4 pb-3 border-b border-divider-subtle'>
  81. <div className='absolute top-3 right-3'>
  82. <ActionButton onClick={onHide}>
  83. <RiCloseLine className='w-4 h-4' />
  84. </ActionButton>
  85. </div>
  86. <div
  87. className='mb-2 flex items-center gap-1 text-text-accent-secondary system-xs-semibold-uppercase cursor-pointer'
  88. onClick={onHide}
  89. >
  90. <RiArrowLeftLine className='w-4 h-4' />
  91. BACK
  92. </div>
  93. <div className='flex items-center gap-1'>
  94. <Icon size='tiny' className='w-6 h-6' src={`${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${provider.tenant_id}&filename=${provider.icon}`} />
  95. <div className=''>{getValueFromI18nObject(provider.label)}</div>
  96. </div>
  97. <div className='mt-1 text-text-primary system-md-semibold'>{getValueFromI18nObject(detail.identity.label)}</div>
  98. <Description className='mt-3' text={getValueFromI18nObject(detail.description)} descriptionLineRows={2}></Description>
  99. </div>
  100. {/* form */}
  101. <div className='h-full'>
  102. <div className='flex flex-col h-full overflow-y-auto'>
  103. <div className='p-4 pb-1 text-text-primary system-sm-semibold-uppercase'>{t('tools.setBuiltInTools.parameters')}</div>
  104. <div className='px-4'>
  105. {detail.parameters.length > 0 && (
  106. <div className='py-2 space-y-1'>
  107. {detail.parameters.map((item: any, index) => (
  108. <div key={index} className='py-1'>
  109. <div className='flex items-center gap-2'>
  110. <div className='text-text-secondary code-sm-semibold'>{getValueFromI18nObject(item.label)}</div>
  111. <div className='text-text-tertiary system-xs-regular'>
  112. {getType(item.type)}
  113. </div>
  114. {item.required && (
  115. <div className='text-text-warning-secondary system-xs-medium'>{t('tools.setBuiltInTools.required')}</div>
  116. )}
  117. </div>
  118. {item.human_description && (
  119. <div className='mt-0.5 text-text-tertiary system-xs-regular'>
  120. {getValueFromI18nObject(item.human_description)}
  121. </div>
  122. )}
  123. </div>
  124. ))}
  125. </div>
  126. )}
  127. </div>
  128. {detail.output_schema && (
  129. <>
  130. <div className='px-4'>
  131. <Divider className="!mt-2" />
  132. </div>
  133. <div className='p-4 pb-1 text-text-primary system-sm-semibold-uppercase'>OUTPUT</div>
  134. {outputSchema.length > 0 && (
  135. <div className='px-4 py-2 space-y-1'>
  136. {outputSchema.map((outputItem, index) => (
  137. <div key={index} className='py-1'>
  138. <div className='flex items-center gap-2'>
  139. <div className='text-text-secondary code-sm-semibold'>{outputItem.name}</div>
  140. <div className='text-text-tertiary system-xs-regular'>{outputItem.type}</div>
  141. </div>
  142. {outputItem.description && (
  143. <div className='mt-0.5 text-text-tertiary system-xs-regular'>
  144. {outputItem.description}
  145. </div>
  146. )}
  147. </div>
  148. ))}
  149. </div>
  150. )}
  151. </>
  152. )}
  153. </div>
  154. </div>
  155. </>
  156. </Drawer>
  157. )
  158. }
  159. export default StrategyDetail