From a430284aa21e3ae1f0d5654e55b2ad2852519cc2 Mon Sep 17 00:00:00 2001
From: wwf <yearningwang@iqtogether.com>
Date: 星期三, 04 六月 2025 15:17:49 +0800
Subject: [PATCH] 初始化

---
 app/components/app/configuration/config/agent/agent-tools/index.tsx |  289 ++++++++++++++++++++-------------------------------------
 1 files changed, 103 insertions(+), 186 deletions(-)

diff --git a/app/components/app/configuration/config/agent/agent-tools/index.tsx b/app/components/app/configuration/config/agent/agent-tools/index.tsx
index 4b773c0..52e5d5d 100644
--- a/app/components/app/configuration/config/agent/agent-tools/index.tsx
+++ b/app/components/app/configuration/config/agent/agent-tools/index.tsx
@@ -1,24 +1,21 @@
 'use client'
 import type { FC } from 'react'
-import React, { useMemo, useState } from 'react'
+import React, { useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import { useContext } from 'use-context-selector'
-import copy from 'copy-to-clipboard'
 import produce from 'immer'
 import {
   RiDeleteBinLine,
-  RiEqualizer2Line,
-  RiInformation2Line,
+  RiHammerFill,
 } from '@remixicon/react'
 import { useFormattingChangedDispatcher } from '../../../debug/hooks'
 import SettingBuiltInTool from './setting-built-in-tool'
+import cn from '@/utils/classnames'
 import Panel from '@/app/components/app/configuration/base/feature-panel'
+import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
 import OperationBtn from '@/app/components/app/configuration/base/operation-btn'
 import AppIcon from '@/app/components/base/app-icon'
-import Button from '@/app/components/base/button'
-import Indicator from '@/app/components/header/indicator'
 import Switch from '@/app/components/base/switch'
-import Toast from '@/app/components/base/toast'
 import ConfigContext from '@/context/debug-configuration'
 import type { AgentTool } from '@/types/app'
 import { type Collection, CollectionType } from '@/app/components/tools/types'
@@ -26,12 +23,7 @@
 import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
 import Tooltip from '@/app/components/base/tooltip'
 import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other'
-import ConfigCredential from '@/app/components/tools/setting/build-in/config-credentials'
-import { updateBuiltInToolCredential } from '@/service/tools'
-import cn from '@/utils/classnames'
-import ToolPicker from '@/app/components/workflow/block-selector/tool-picker'
-import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types'
-import { canFindTool } from '@/utils'
+import AddToolModal from '@/app/components/tools/add-tool-modal'
 
 type AgentToolWithMoreInfo = AgentTool & { icon: any; collection?: Collection } | null
 const AgentTools: FC = () => {
@@ -41,19 +33,9 @@
   const formattingChangedDispatcher = useFormattingChangedDispatcher()
 
   const [currentTool, setCurrentTool] = useState<AgentToolWithMoreInfo>(null)
-  const currentCollection = useMemo(() => {
-    if (!currentTool) return null
-    const collection = collectionList.find(collection => canFindTool(collection.id, currentTool?.provider_id) && collection.type === currentTool?.provider_type)
-    return collection
-  }, [currentTool, collectionList])
   const [isShowSettingTool, setIsShowSettingTool] = useState(false)
-  const [isShowSettingAuth, setShowSettingAuth] = useState(false)
   const tools = (modelConfig?.agentConfig?.tools as AgentTool[] || []).map((item) => {
-    const collection = collectionList.find(
-      collection =>
-        canFindTool(collection.id, item.provider_id)
-        && collection.type === item.provider_type,
-    )
+    const collection = collectionList.find(collection => collection.id === item.provider_id && collection.type === item.provider_type)
     const icon = collection?.icon
     return {
       ...item,
@@ -73,40 +55,14 @@
     formattingChangedDispatcher()
   }
 
-  const handleToolAuthSetting = (value: AgentToolWithMoreInfo) => {
-    const newModelConfig = produce(modelConfig, (draft) => {
-      const tool = (draft.agentConfig.tools).find((item: any) => item.provider_id === value?.collection?.id && item.tool_name === value?.tool_name)
-      if (tool)
-        (tool as AgentTool).notAuthor = false
-    })
-    setModelConfig(newModelConfig)
-    setIsShowSettingTool(false)
-    formattingChangedDispatcher()
-  }
-
-  const [isDeleting, setIsDeleting] = useState<number>(-1)
-
-  const handleSelectTool = (tool: ToolDefaultValue) => {
-    const newModelConfig = produce(modelConfig, (draft) => {
-      draft.agentConfig.tools.push({
-        provider_id: tool.provider_id,
-        provider_type: tool.provider_type as CollectionType,
-        provider_name: tool.provider_name,
-        tool_name: tool.tool_name,
-        tool_label: tool.tool_label,
-        tool_parameters: tool.params,
-        notAuthor: !tool.is_team_authorization,
-        enabled: true,
-      })
-    })
-    setModelConfig(newModelConfig)
-  }
-
   return (
     <>
       <Panel
-        className={cn('mt-2', tools.length === 0 && 'pb-2')}
+        className="mt-2"
         noBodySpacing={tools.length === 0}
+        headerIcon={
+          <RiHammerFill className='w-4 h-4 text-primary-500' />
+        }
         title={
           <div className='flex items-center'>
             <div className='mr-1'>{t('appDebug.agent.tools.name')}</div>
@@ -121,181 +77,142 @@
         }
         headerRight={
           <div className='flex items-center'>
-            <div className='text-xs font-normal leading-[18px] text-text-tertiary'>{tools.filter(item => !!item.enabled).length}/{tools.length}&nbsp;{t('appDebug.agent.tools.enabled')}</div>
+            <div className='leading-[18px] text-xs font-normal text-gray-500'>{tools.filter((item: any) => !!item.enabled).length}/{tools.length}&nbsp;{t('appDebug.agent.tools.enabled')}</div>
             {tools.length < MAX_TOOLS_NUM && (
               <>
-                <div className='ml-3 mr-1 h-3.5 w-px bg-divider-regular'></div>
-                <ToolPicker
-                  trigger={<OperationBtn type="add" />}
-                  isShow={isShowChooseTool}
-                  onShowChange={setIsShowChooseTool}
-                  disabled={false}
-                  supportAddCustomTool
-                  onSelect={handleSelectTool}
-                  selectedTools={tools}
-                />
+                <div className='ml-3 mr-1 h-3.5 w-px bg-gray-200'></div>
+                <OperationBtn type="add" onClick={() => setIsShowChooseTool(true)} />
               </>
             )}
           </div>
         }
       >
-        <div className='grid grid-cols-1 flex-wrap items-center justify-between gap-1 2xl:grid-cols-2'>
+        <div className='grid gap-1 grid-cols-1 2xl:grid-cols-2 items-center flex-wrap justify-between'>
           {tools.map((item: AgentTool & { icon: any; collection?: Collection }, index) => (
             <div key={index}
-              className={cn(
-                'cursor group relative flex w-full items-center justify-between rounded-lg border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg p-1.5 pr-2 shadow-xs last-of-type:mb-0 hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm',
-                isDeleting === index && 'border-state-destructive-border hover:bg-state-destructive-hover',
-              )}
+              className={cn((item.isDeleted || item.notAuthor) ? 'bg-white/50' : 'bg-white', (item.enabled && !item.isDeleted && !item.notAuthor) && 'shadow-xs', index > 1 && 'mt-1', 'group relative flex justify-between items-center last-of-type:mb-0  pl-2.5 py-2 pr-3 w-full  rounded-lg border-[0.5px] border-gray-200 ')}
             >
-              <div className='flex w-0 grow items-center'>
-                {item.isDeleted && <DefaultToolIcon className='h-5 w-5' />}
-                {!item.isDeleted && (
-                  <div className={cn((item.notAuthor || !item.enabled) && 'opacity-50')}>
-                    {typeof item.icon === 'string' && <div className='h-5 w-5 rounded-md bg-cover bg-center' style={{ backgroundImage: `url(${item.icon})` }} />}
-                    {typeof item.icon !== 'string' && <AppIcon className='rounded-md' size='xs' icon={item.icon?.content} background={item.icon?.background} />}
-                  </div>
-                )}
+              <div className='grow w-0 flex items-center'>
+                {(item.isDeleted || item.notAuthor)
+                  ? (
+                    <DefaultToolIcon className='w-6 h-6' />
+                  )
+                  : (
+                    typeof item.icon === 'string'
+                      ? (
+                        <div
+                          className='w-6 h-6 bg-cover bg-center rounded-md'
+                          style={{
+                            backgroundImage: `url(${item.icon})`,
+                          }}
+                        ></div>
+                      )
+                      : (
+                        <AppIcon
+                          className='rounded-md'
+                          size='tiny'
+                          icon={item.icon?.content}
+                          background={item.icon?.background}
+                        />
+                      ))}
                 <div
-                  className={cn(
-                    'system-xs-regular ml-1.5 flex w-0 grow items-center truncate',
-                    (item.isDeleted || item.notAuthor || !item.enabled) ? 'opacity-50' : '',
-                  )}
+                  className={cn((item.isDeleted || item.notAuthor) ? 'line-through opacity-50' : '', 'grow w-0 ml-2 leading-[18px] text-[13px] font-medium text-gray-800  truncate')}
                 >
-                  <span className='system-xs-medium pr-1.5 text-text-secondary'>{item.provider_type === CollectionType.builtIn ? item.provider_name.split('/').pop() : item.tool_label}</span>
-                  <span className='text-text-tertiary'>{item.tool_label}</span>
-                  {!item.isDeleted && (
-                    <Tooltip
-                      needsDelay
-                      popupContent={
-                        <div className='w-[180px]'>
-                          <div className='mb-1.5 text-text-secondary'>{item.tool_name}</div>
-                          <div className='mb-1.5 text-text-tertiary'>{t('tools.toolNameUsageTip')}</div>
-                          <div className='cursor-pointer text-text-accent' onClick={() => copy(item.tool_name)}>{t('tools.copyToolName')}</div>
-                        </div>
-                      }
-                    >
-                      <div className='h-4 w-4'>
-                        <div className='ml-0.5 hidden group-hover:inline-block'>
-                          <RiInformation2Line className='h-4 w-4 text-text-tertiary' />
-                        </div>
-                      </div>
-                    </Tooltip>
-                  )}
+                  <span className='text-gray-800 pr-2'>{item.provider_type === CollectionType.builtIn ? item.provider_name : item.tool_label}</span>
+                  <Tooltip
+                    popupContent={t('tools.toolNameUsageTip')}
+                  >
+                    <span className='text-gray-500'>{item.tool_name}</span>
+                  </Tooltip>
                 </div>
               </div>
-              <div className='ml-1 flex shrink-0 items-center'>
-                {item.isDeleted && (
-                  <div className='mr-2 flex items-center'>
-                    <Tooltip
-                      popupContent={t('tools.toolRemoved')}
-                      needsDelay
-                    >
-                      <div className='mr-1 cursor-pointer rounded-md p-1 hover:bg-black/5'>
-                        <AlertTriangle className='h-4 w-4 text-[#F79009]' />
-                      </div>
-                    </Tooltip>
-                    <div
-                      className='cursor-pointer rounded-md p-1 text-text-tertiary hover:text-text-destructive'
-                      onClick={() => {
+              <div className='shrink-0 ml-1 flex items-center'>
+                {(item.isDeleted || item.notAuthor)
+                  ? (
+                    <div className='flex items-center'>
+                      <Tooltip
+                        popupContent={t(`tools.${item.isDeleted ? 'toolRemoved' : 'notAuthorized'}`)}
+                        needsDelay
+                      >
+                        <div className='mr-1 p-1 rounded-md hover:bg-black/5  cursor-pointer' onClick={() => {
+                          if (item.notAuthor)
+                            setIsShowChooseTool(true)
+                        }}>
+                          <AlertTriangle className='w-4 h-4 text-[#F79009]' />
+                        </div>
+                      </Tooltip>
+
+                      <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
                         const newModelConfig = produce(modelConfig, (draft) => {
                           draft.agentConfig.tools.splice(index, 1)
                         })
                         setModelConfig(newModelConfig)
                         formattingChangedDispatcher()
-                      }}
-                      onMouseOver={() => setIsDeleting(index)}
-                      onMouseLeave={() => setIsDeleting(-1)}
-                    >
-                      <RiDeleteBinLine className='h-4 w-4' />
+                      }}>
+                        <RiDeleteBinLine className='w-4 h-4 text-gray-500' />
+                      </div>
+                      <div className='ml-2 mr-3 w-px h-3.5 bg-gray-200'></div>
                     </div>
-                  </div>
-                )}
-                {!item.isDeleted && (
-                  <div className='mr-2 hidden items-center gap-1 group-hover:flex'>
-                    {!item.notAuthor && (
+                  )
+                  : (
+                    <div className='hidden group-hover:flex items-center'>
                       <Tooltip
                         popupContent={t('tools.setBuiltInTools.infoAndSetting')}
                         needsDelay
                       >
-                        <div className='cursor-pointer rounded-md p-1  hover:bg-black/5' onClick={() => {
+                        <div className='p-1 rounded-md hover:bg-black/5  cursor-pointer' onClick={() => {
                           setCurrentTool(item)
                           setIsShowSettingTool(true)
                         }}>
-                          <RiEqualizer2Line className='h-4 w-4 text-text-tertiary' />
+                          <InfoCircle className='w-4 h-4 text-gray-500' />
                         </div>
                       </Tooltip>
-                    )}
-                    <div
-                      className='cursor-pointer rounded-md p-1 text-text-tertiary hover:text-text-destructive'
-                      onClick={() => {
+
+                      <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
                         const newModelConfig = produce(modelConfig, (draft) => {
                           draft.agentConfig.tools.splice(index, 1)
                         })
                         setModelConfig(newModelConfig)
                         formattingChangedDispatcher()
-                      }}
-                      onMouseOver={() => setIsDeleting(index)}
-                      onMouseLeave={() => setIsDeleting(-1)}
-                    >
-                      <RiDeleteBinLine className='h-4 w-4' />
+                      }}>
+                        <RiDeleteBinLine className='w-4 h-4 text-gray-500' />
+                      </div>
+                      <div className='ml-2 mr-3 w-px h-3.5 bg-gray-200'></div>
                     </div>
-                  </div>
-                )}
-                <div className={cn(item.isDeleted && 'opacity-50')}>
-                  {!item.notAuthor && (
-                    <Switch
-                      defaultValue={item.isDeleted ? false : item.enabled}
-                      disabled={item.isDeleted}
-                      size='md'
-                      onChange={(enabled) => {
-                        const newModelConfig = produce(modelConfig, (draft) => {
-                          (draft.agentConfig.tools[index] as any).enabled = enabled
-                        })
-                        setModelConfig(newModelConfig)
-                        formattingChangedDispatcher()
-                      }} />
                   )}
-                  {item.notAuthor && (
-                    <Button variant='secondary' size='small' onClick={() => {
-                      setCurrentTool(item)
-                      setShowSettingAuth(true)
-                    }}>
-                      {t('tools.notAuthorized')}
-                      <Indicator className='ml-2' color='orange' />
-                    </Button>
-                  )}
+                <div className={cn((item.isDeleted || item.notAuthor) && 'opacity-50')}>
+                  <Switch
+                    defaultValue={(item.isDeleted || item.notAuthor) ? false : item.enabled}
+                    disabled={(item.isDeleted || item.notAuthor)}
+                    size='md'
+                    onChange={(enabled) => {
+                      const newModelConfig = produce(modelConfig, (draft) => {
+                        (draft.agentConfig.tools[index] as any).enabled = enabled
+                      })
+                      setModelConfig(newModelConfig)
+                      formattingChangedDispatcher()
+                    }} />
                 </div>
               </div>
             </div>
           ))}
         </div >
       </Panel >
-      {isShowSettingTool && (
-        <SettingBuiltInTool
-          toolName={currentTool?.tool_name as string}
-          setting={currentTool?.tool_parameters}
-          collection={currentTool?.collection as Collection}
-          isBuiltIn={currentTool?.collection?.type === CollectionType.builtIn}
-          isModel={currentTool?.collection?.type === CollectionType.model}
-          onSave={handleToolSettingChange}
-          onHide={() => setIsShowSettingTool(false)}
-        />
+      {isShowChooseTool && (
+        <AddToolModal onHide={() => setIsShowChooseTool(false)} />
       )}
-      {isShowSettingAuth && (
-        <ConfigCredential
-          collection={currentCollection as any}
-          onCancel={() => setShowSettingAuth(false)}
-          onSaved={async (value) => {
-            await updateBuiltInToolCredential((currentCollection as any).name, value)
-            Toast.notify({
-              type: 'success',
-              message: t('common.api.actionSuccess'),
-            })
-            handleToolAuthSetting(currentTool)
-            setShowSettingAuth(false)
-          }}
-        />
-      )}
+      {
+        isShowSettingTool && (
+          <SettingBuiltInTool
+            toolName={currentTool?.tool_name as string}
+            setting={currentTool?.tool_parameters as any}
+            collection={currentTool?.collection as Collection}
+            isBuiltIn={currentTool?.collection?.type === CollectionType.builtIn}
+            isModel={currentTool?.collection?.type === CollectionType.model}
+            onSave={handleToolSettingChange}
+            onHide={() => setIsShowSettingTool(false)}
+          />)
+      }
     </>
   )
 }

--
Gitblit v1.8.0