import React from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import userService from '../api/services/userService'; import ArrowLeft from '../assets/arrow-left.svg'; import ChevronRight from '../assets/chevron-right.svg'; import CircleCheck from '../assets/circle-check.svg'; import CircleX from '../assets/circle-x.svg'; import NoFilesDarkIcon from '../assets/no-files-dark.svg'; import NoFilesIcon from '../assets/no-files.svg'; import Trash from '../assets/trash.svg'; import Dropdown from '../components/Dropdown'; import Input from '../components/Input'; import ToggleSwitch from '../components/ToggleSwitch'; import { useDarkTheme } from '../hooks'; import AddActionModal from '../modals/AddActionModal'; import ConfirmationModal from '../modals/ConfirmationModal'; import ImportSpecModal from '../modals/ImportSpecModal'; import { ActiveState } from '../models/misc'; import { selectToken } from '../preferences/preferenceSlice'; import { areObjectsEqual } from '../utils/objectUtils'; import { APIActionType, APIToolType, UserToolType } from './types'; const METHOD_COLORS: Record = { GET: 'bg-[#D1FAE5] text-[#065F46] dark:bg-[#064E3B]/60 dark:text-[#6EE7B7]', POST: 'bg-[#DBEAFE] text-[#1E40AF] dark:bg-[#1E3A8A]/60 dark:text-[#93C5FD]', PUT: 'bg-[#FEF3C7] text-[#92400E] dark:bg-[#78350F]/60 dark:text-[#FCD34D]', DELETE: 'bg-[#FEE2E2] text-[#991B1B] dark:bg-[#7F1D1D]/60 dark:text-[#FCA5A5]', PATCH: 'bg-[#EDE9FE] text-[#5B21B6] dark:bg-[#4C1D95]/60 dark:text-[#C4B5FD]', HEAD: 'bg-[#F3F4F6] text-[#374151] dark:bg-[#374151]/60 dark:text-[#D1D5DB]', OPTIONS: 'bg-[#F3F4F6] text-[#374151] dark:bg-[#374151]/60 dark:text-[#D1D5DB]', }; export default function ToolConfig({ tool, setTool, handleGoBack, }: { tool: UserToolType | APIToolType; setTool: (tool: UserToolType | APIToolType) => void; handleGoBack: () => void; }) { const token = useSelector(selectToken); const [authKey, setAuthKey] = React.useState(() => { if (tool.name === 'mcp_tool') { const config = tool.config as any; if (config.auth_type === 'api_key') { return config.api_key || ''; } else if (config.auth_type === 'bearer') { return config.encrypted_token || ''; } else if (config.auth_type === 'basic') { return config.password || ''; } return ''; } else if ('token' in tool.config) { return tool.config.token; } return ''; }); const [customName, setCustomName] = React.useState( tool.customName || '', ); const [actionModalState, setActionModalState] = React.useState('INACTIVE'); const [importModalState, setImportModalState] = React.useState('INACTIVE'); const [initialState, setInitialState] = React.useState({ customName: tool.customName || '', authKey: 'token' in tool.config ? tool.config.token : '', config: tool.config, actions: 'actions' in tool ? tool.actions : [], }); const [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false); const [showUnsavedModal, setShowUnsavedModal] = React.useState(false); const [userActionsSearch, setUserActionsSearch] = React.useState(''); const [expandedUserActions, setExpandedUserActions] = React.useState< Set >(new Set()); const { t } = useTranslation(); const [isDarkTheme] = useDarkTheme(); const toggleUserActionExpand = (index: number) => { setExpandedUserActions((prev) => { const newSet = new Set(prev); if (newSet.has(index)) { newSet.delete(index); } else { newSet.add(index); } return newSet; }); }; const filteredUserActions = React.useMemo(() => { if (!('actions' in tool) || !tool.actions) return []; const query = userActionsSearch.toLowerCase(); return tool.actions .map((action, index) => ({ action, originalIndex: index })) .filter( ({ action }) => action.name.toLowerCase().includes(query) || action.description?.toLowerCase().includes(query), ) .sort((a, b) => a.action.name.localeCompare(b.action.name)); }, [tool, userActionsSearch]); const handleBackClick = () => { if (hasUnsavedChanges) { setShowUnsavedModal(true); } else { handleGoBack(); } }; React.useEffect(() => { const currentState = { customName, authKey, config: tool.config, actions: 'actions' in tool ? tool.actions : [], }; setHasUnsavedChanges(!areObjectsEqual(initialState, currentState)); }, [customName, authKey, tool]); const handleCheckboxChange = (actionIndex: number, property: string) => { setTool({ ...tool, actions: 'actions' in tool ? tool.actions.map((action, index) => { if (index === actionIndex) { const newFilledByLlm = !action.parameters.properties[property].filled_by_llm; return { ...action, parameters: { ...action.parameters, properties: { ...action.parameters.properties, [property]: { ...action.parameters.properties[property], filled_by_llm: newFilledByLlm, required: newFilledByLlm, }, }, }, }; } return action; }) : [], }); }; const handleSaveChanges = () => { let configToSave; if (tool.name === 'api_tool') { configToSave = tool.config; } else if (tool.name === 'mcp_tool') { configToSave = { ...tool.config } as any; const mcpConfig = tool.config as any; if (authKey.trim()) { if (mcpConfig.auth_type === 'api_key') { configToSave.api_key = authKey; } else if (mcpConfig.auth_type === 'bearer') { configToSave.encrypted_token = authKey; } else if (mcpConfig.auth_type === 'basic') { configToSave.password = authKey; } } } else { configToSave = { token: authKey }; } userService .updateTool( { id: tool.id, name: tool.name, displayName: tool.displayName, customName: customName, description: tool.description, config: configToSave, actions: 'actions' in tool ? tool.actions : [], status: tool.status, }, token, ) .then(() => { // Update initialState to match current state setInitialState({ customName, authKey, config: tool.config, actions: 'actions' in tool ? tool.actions : [], }); setHasUnsavedChanges(false); handleGoBack(); }); }; const handleDelete = () => { userService.deleteTool({ id: tool.id }, token).then(() => { handleGoBack(); }); }; const handleAddNewAction = (actionName: string) => { const toolCopy = tool as APIToolType; if (toolCopy.config.actions && toolCopy.config.actions[actionName]) { alert(t('settings.tools.actionAlreadyExists')); return; } const newAction: APIActionType = { name: actionName, method: 'GET', url: '', description: '', body: { properties: {}, type: 'object', }, headers: { properties: {}, type: 'object', }, query_params: { properties: {}, type: 'object', }, active: true, body_content_type: 'application/json', body_encoding_rules: {}, }; setTool({ ...toolCopy, config: { ...toolCopy.config, actions: { ...toolCopy.config.actions, [actionName]: newAction }, }, }); }; const handleImportActions = (actions: APIActionType[]) => { const toolCopy = tool as APIToolType; const existingActions = toolCopy.config.actions || {}; const newActions: { [key: string]: APIActionType } = {}; actions.forEach((action) => { let actionName = action.name; let counter = 1; while (existingActions[actionName] || newActions[actionName]) { actionName = `${action.name}_${counter}`; counter++; } newActions[actionName] = { ...action, name: actionName }; }); setTool({ ...toolCopy, config: { ...toolCopy.config, actions: { ...existingActions, ...newActions }, }, }); }; return (

{t('settings.tools.backToAllTools')}

{/* Custom name section */}

{t('settings.tools.customName')}

setCustomName(e.target.value)} borderVariant="thin" placeholder={t('settings.tools.customNamePlaceholder')} />
{Object.keys(tool?.config).length !== 0 && tool.name !== 'api_tool' && (

{tool.name === 'mcp_tool' ? (tool.config as any)?.auth_type === 'bearer' ? 'Bearer Token' : (tool.config as any)?.auth_type === 'api_key' ? 'API Key' : (tool.config as any)?.auth_type === 'basic' ? 'Password' : t('settings.tools.authentication') : t('settings.tools.authentication')}

)}
{Object.keys(tool?.config).length !== 0 && tool.name !== 'api_tool' && (
setAuthKey(e.target.value)} borderVariant="thin" placeholder={ tool.name === 'mcp_tool' ? (tool.config as any)?.auth_type === 'bearer' ? 'Bearer Token' : (tool.config as any)?.auth_type === 'api_key' ? 'API Key' : (tool.config as any)?.auth_type === 'basic' ? 'Password' : t('modals.configTool.apiKeyPlaceholder') : t('modals.configTool.apiKeyPlaceholder') } />
)}

{t('settings.tools.actions')}

{tool.name === 'api_tool' && (
)}
{tool.name === 'api_tool' ? ( <> {tool.config.actions && Object.keys(tool.config.actions).length > 0 ? ( ) : (
No actions found

{t('settings.tools.noActionsFound')}

)} ) : (
{'actions' in tool && tool.actions && tool.actions.length > 0 ? ( <>
setUserActionsSearch(e.target.value)} placeholder={t('settings.tools.searchActions')} className="border-silver dark:border-silver/40 dark:bg-raisin-black w-full rounded-full border px-4 py-2 pl-10 text-sm outline-none focus:border-purple-500 dark:text-white dark:placeholder-gray-500" />
{filteredUserActions.length === 0 && userActionsSearch && (

{t('settings.tools.noActionsMatch')}

)} {filteredUserActions.map(({ action, originalIndex }) => { const isExpanded = expandedUserActions.has(originalIndex); return (
toggleUserActionExpand(originalIndex)} >
expand

{action.name}

{action.description && (

{action.description}

)}
e.stopPropagation()} > { setTool({ ...tool, actions: tool.actions.map((act, index) => { if (index === originalIndex) { return { ...act, active: checked }; } return act; }), }); }} size="small" id={`actionToggle-${originalIndex}`} />
{isExpanded && ( <>
{ setTool({ ...tool, actions: tool.actions.map((act, index) => { if (index === originalIndex) { return { ...act, description: e.target.value, }; } return act; }), }); }} borderVariant="thin" />
{Object.entries( action.parameters?.properties, ).map((param, paramIndex) => { const uniqueKey = `${originalIndex}-${param[0]}`; return ( ); })}
{t('settings.tools.fieldName')} {t('settings.tools.fieldType')} {t('settings.tools.filledByLLM')} {t('settings.tools.fieldDescription')} {t('settings.tools.value')}
{param[0]} {param[1].type} { setTool({ ...tool, actions: tool.actions.map( (act, index) => { if (index === originalIndex) { return { ...act, parameters: { ...act.parameters, properties: { ...act.parameters .properties, [param[0]]: { ...act.parameters .properties[ param[0] ], description: e.target.value, }, }, }, }; } return act; }, ), }); }} > { setTool({ ...tool, actions: tool.actions.map( (act, index) => { if (index === originalIndex) { return { ...act, parameters: { ...act.parameters, properties: { ...act.parameters .properties, [param[0]]: { ...act.parameters .properties[ param[0] ], value: e.target.value, }, }, }, }; } return act; }, ), }); }} >
)}
); })} ) : (
No actions found

{t('settings.tools.noActionsFound')}

)}
)} {showUnsavedModal && ( setShowUnsavedModal(state === 'ACTIVE')} submitLabel={t('settings.tools.saveAndLeave')} handleSubmit={() => { let configToSave; if (tool.name === 'api_tool') { configToSave = tool.config; } else if (tool.name === 'mcp_tool') { configToSave = { ...tool.config } as any; const mcpConfig = tool.config as any; if (authKey.trim()) { if (mcpConfig.auth_type === 'api_key') { configToSave.api_key = authKey; } else if (mcpConfig.auth_type === 'bearer') { configToSave.encrypted_token = authKey; } else if (mcpConfig.auth_type === 'basic') { configToSave.password = authKey; } } } else { configToSave = { token: authKey }; } userService .updateTool( { id: tool.id, name: tool.name, displayName: tool.displayName, customName: customName, description: tool.description, config: configToSave, actions: 'actions' in tool ? tool.actions : [], status: tool.status, }, token, ) .then(() => { setShowUnsavedModal(false); handleGoBack(); }); }} cancelLabel={t('settings.tools.leaveWithoutSaving')} handleCancel={() => { setShowUnsavedModal(false); handleGoBack(); }} /> )}
); } function APIToolConfig({ tool, setTool, }: { tool: APIToolType; setTool: (tool: APIToolType) => void; }) { const [apiTool, setApiTool] = React.useState(tool); const { t } = useTranslation(); const [actionToDelete, setActionToDelete] = React.useState( null, ); const [deleteModalState, setDeleteModalState] = React.useState('INACTIVE'); const [searchQuery, setSearchQuery] = React.useState(''); const [expandedActions, setExpandedActions] = React.useState>( new Set(), ); const toggleActionExpand = (actionName: string) => { setExpandedActions((prev) => { const newSet = new Set(prev); if (newSet.has(actionName)) { newSet.delete(actionName); } else { newSet.add(actionName); } return newSet; }); }; const filteredActions = React.useMemo(() => { if (!apiTool.config.actions) return []; const entries = Object.entries(apiTool.config.actions); const filtered = entries.filter(([actionName, action]) => { const query = searchQuery.toLowerCase(); return ( actionName.toLowerCase().includes(query) || action.name.toLowerCase().includes(query) || action.description?.toLowerCase().includes(query) || action.url?.toLowerCase().includes(query) ); }); return filtered.sort((a, b) => a[0].localeCompare(b[0])); }, [apiTool.config.actions, searchQuery]); const handleDeleteActionClick = (actionName: string) => { setActionToDelete(actionName); setDeleteModalState('ACTIVE'); }; const handleConfirmedDelete = () => { if (actionToDelete) { setApiTool((prevApiTool) => { const { [actionToDelete]: deletedAction, ...remainingActions } = prevApiTool.config.actions; return { ...prevApiTool, config: { ...prevApiTool.config, actions: remainingActions, }, }; }); setActionToDelete(null); setDeleteModalState('INACTIVE'); } }; const handleActionChange = ( actionName: string, updatedAction: APIActionType, ) => { setApiTool((prevApiTool) => { const updatedActions = { ...prevApiTool.config.actions }; updatedActions[actionName] = updatedAction; return { ...prevApiTool, config: { ...prevApiTool.config, actions: updatedActions }, }; }); }; const handleActionToggle = (actionName: string) => { setApiTool((prevApiTool) => { const updatedActions = { ...prevApiTool.config.actions }; const updatedAction = { ...updatedActions[actionName] }; updatedAction.active = !updatedAction.active; updatedActions[actionName] = updatedAction; return { ...prevApiTool, config: { ...prevApiTool.config, actions: updatedActions }, }; }); }; React.useEffect(() => { setApiTool(tool); }, [tool]); React.useEffect(() => { setTool(apiTool); }, [apiTool]); const getMethodColor = (method: string) => { return METHOD_COLORS[method.toUpperCase()] || METHOD_COLORS.GET; }; return (
setSearchQuery(e.target.value)} placeholder={t('settings.tools.searchActions')} className="border-silver dark:border-silver/40 dark:bg-raisin-black w-full rounded-full border px-4 py-2 pl-10 text-sm outline-none focus:border-purple-500 dark:text-white dark:placeholder-gray-500" />
{filteredActions.length === 0 && searchQuery && (

{t('settings.tools.noActionsMatch')}

)}
{filteredActions.map(([actionName, action], actionIndex) => { const isExpanded = expandedActions.has(actionName); return (
toggleActionExpand(actionName)} >
expand {action.method}

{action.name}

{action.description && (

{action.description}

)}
e.stopPropagation()} > handleActionToggle(actionName)} size="small" id={`actionToggle-${actionIndex}`} />
{isExpanded && ( <>
{ setApiTool((prevApiTool) => { const updatedActions = { ...prevApiTool.config.actions, }; const updatedAction = { ...updatedActions[actionName], }; updatedAction.url = e.target.value; updatedActions[actionName] = updatedAction; return { ...prevApiTool, config: { ...prevApiTool.config, actions: updatedActions, }, }; }); }} borderVariant="thin" placeholder={t('settings.tools.urlPlaceholder')} />
{t('settings.tools.method')} { setApiTool((prevApiTool) => { const updatedActions = { ...prevApiTool.config.actions, }; const updatedAction = { ...updatedActions[actionName], }; updatedAction.method = value as | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'; updatedActions[actionName] = updatedAction; return { ...prevApiTool, config: { ...prevApiTool.config, actions: updatedActions, }, }; }); }} size="w-56" rounded="3xl" border="border" />
{ setApiTool((prevApiTool) => { const updatedActions = { ...prevApiTool.config.actions, }; const updatedAction = { ...updatedActions[actionName], }; updatedAction.description = e.target.value; updatedActions[actionName] = updatedAction; return { ...prevApiTool, config: { ...prevApiTool.config, actions: updatedActions, }, }; }); }} borderVariant="thin" placeholder={t('settings.tools.descriptionPlaceholder')} />
{(action.method === 'POST' || action.method === 'PUT' || action.method === 'PATCH' || action.method === 'HEAD' || action.method === 'OPTIONS') && (
{t('settings.tools.bodyContentType')} { setApiTool((prevApiTool) => { const updatedActions = { ...prevApiTool.config.actions, }; const updatedAction = { ...updatedActions[actionName], }; updatedAction.body_content_type = value as | 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'text/plain' | 'application/xml' | 'application/octet-stream'; updatedActions[actionName] = updatedAction; return { ...prevApiTool, config: { ...prevApiTool.config, actions: updatedActions, }, }; }); }} size="w-56" rounded="3xl" border="border" />

{action.body_content_type === 'multipart/form-data' && 'For APIs requiring multipart format. File uploads not supported through LLM.'} {action.body_content_type === 'application/octet-stream' && 'Raw binary data, base64-encoded for transmission.'} {action.body_content_type === 'application/x-www-form-urlencoded' && 'Standard form submission format. Best for legacy APIs and login forms.'} {action.body_content_type === 'application/xml' && 'Structured XML format. Use for SOAP and enterprise APIs.'} {action.body_content_type === 'text/plain' && 'Raw text data. Each field on a new line.'} {(!action.body_content_type || action.body_content_type === 'application/json') && 'Most common format. Use for modern REST APIs.'}

)}
)}
); })}
{/* Confirmation Modal */} {deleteModalState === 'ACTIVE' && actionToDelete && ( { setDeleteModalState('INACTIVE'); setActionToDelete(null); }} submitLabel={t('convTile.delete')} variant="danger" /> )}
); } function APIActionTable({ apiAction, handleActionChange, }: { apiAction: APIActionType; handleActionChange: ( actionName: string, updatedAction: APIActionType, ) => void; }) { const { t } = useTranslation(); const [action, setAction] = React.useState(apiAction); const [newPropertyKey, setNewPropertyKey] = React.useState(''); const [newPropertyType, setNewPropertyType] = React.useState< 'string' | 'integer' >('string'); const [addingPropertySection, setAddingPropertySection] = React.useState< 'headers' | 'query_params' | 'body' | null >(null); const [editingPropertyKey, setEditingPropertyKey] = React.useState<{ section: 'headers' | 'query_params' | 'body' | null; oldKey: string | null; }>({ section: null, oldKey: null }); const handlePropertyChange = ( section: 'headers' | 'query_params' | 'body', key: string, field: 'value' | 'description' | 'filled_by_llm', value: string | number | boolean, ) => { setAction((prevAction) => { const currentProperty = prevAction[section].properties[key]; const updatedProperty: typeof currentProperty = { ...currentProperty, [field]: value, ...(field === 'filled_by_llm' && typeof value === 'boolean' ? { required: value } : {}), }; const updatedProperties = { ...prevAction[section].properties, [key]: updatedProperty, }; return { ...prevAction, [section]: { ...prevAction[section], properties: updatedProperties, }, }; }); }; const handleAddPropertyStart = ( section: 'headers' | 'query_params' | 'body', ) => { setEditingPropertyKey({ section: null, oldKey: null }); setAddingPropertySection(section); setNewPropertyKey(''); setNewPropertyType('string'); }; const handleAddPropertyCancel = () => { setAddingPropertySection(null); setNewPropertyKey(''); setNewPropertyType('string'); }; const handleAddProperty = () => { if (addingPropertySection && newPropertyKey.trim() !== '') { setAction((prevAction) => { const updatedProperties = { ...prevAction[addingPropertySection].properties, [newPropertyKey.trim()]: { type: newPropertyType, description: '', value: '', filled_by_llm: false, required: false, }, }; return { ...prevAction, [addingPropertySection]: { ...prevAction[addingPropertySection], properties: updatedProperties, }, }; }); setNewPropertyKey(''); setNewPropertyType('string'); setAddingPropertySection(null); } }; const handleRenamePropertyStart = ( section: 'headers' | 'query_params' | 'body', oldKey: string, ) => { setAddingPropertySection(null); setEditingPropertyKey({ section, oldKey }); setNewPropertyKey(oldKey); }; const handleRenamePropertyCancel = () => { setEditingPropertyKey({ section: null, oldKey: null }); setNewPropertyKey(''); setNewPropertyType('string'); }; const handleRenameProperty = () => { if ( editingPropertyKey.section && editingPropertyKey.oldKey && newPropertyKey.trim() !== '' && newPropertyKey.trim() !== editingPropertyKey.oldKey ) { setAction((prevAction) => { const { section, oldKey } = editingPropertyKey; if (section && oldKey) { const { [oldKey]: oldProperty, ...restProperties } = prevAction[section].properties; const updatedProperties = { ...restProperties, [newPropertyKey.trim()]: oldProperty, }; return { ...prevAction, [section]: { ...prevAction[section], properties: updatedProperties, }, }; } return prevAction; }); setEditingPropertyKey({ section: null, oldKey: null }); setNewPropertyKey(''); setNewPropertyType('string'); } }; const handlePorpertyDelete = ( section: 'headers' | 'query_params' | 'body', key: string, ) => { setAction((prevAction) => { const { [key]: deletedProperty, ...restProperties } = prevAction[section].properties; return { ...prevAction, [section]: { ...prevAction[section], properties: restProperties, }, }; }); }; const handlePropertyTypeChange = ( section: 'headers' | 'query_params' | 'body', key: string, newType: 'string' | 'integer', ) => { setAction((prevAction) => { const updatedProperties = { ...prevAction[section].properties, [key]: { ...prevAction[section].properties[key], type: newType, }, }; return { ...prevAction, [section]: { ...prevAction[section], properties: updatedProperties, }, }; }); }; React.useEffect(() => { setAction(apiAction); }, [apiAction]); React.useEffect(() => { handleActionChange(action.name, action); }, [action]); const renderPropertiesTable = ( section: 'headers' | 'query_params' | 'body', ) => { return ( <> {Object.entries(action[section].properties).map( ([key, param], index) => ( {editingPropertyKey.section === section && editingPropertyKey.oldKey === key ? (
setNewPropertyKey(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') { handleRenameProperty(); } }} />
) : ( handleRenamePropertyStart(section, key)} readOnly /> )} handlePropertyChange( section, key, 'description', e.target.value, ) } > handlePropertyChange(section, key, 'value', e.target.value) } className={`border-silver dark:border-silver/40 rounded-lg border bg-transparent px-2 py-1 text-sm outline-hidden ${param.filled_by_llm ? 'opacity-50' : ''}`} > ), )} {addingPropertySection === section ? ( setNewPropertyKey(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') { handleAddProperty(); } }} placeholder={t('settings.tools.propertyName')} className="border-silver dark:border-silver/40 flex w-full min-w-[130.5px] items-start rounded-lg border bg-transparent px-2 py-1 text-sm outline-hidden" /> ) : ( )} ); }; const renderHeadersTable = () => { return ( <> {Object.entries(action.headers.properties).map( ([key, param], index) => ( {editingPropertyKey.section === 'headers' && editingPropertyKey.oldKey === key ? (
setNewPropertyKey(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') { handleRenameProperty(); } }} />
) : ( handleRenamePropertyStart('headers', key)} readOnly /> )} handlePropertyChange( 'headers', key, 'value', e.target.value, ) } placeholder="e.g., application/json" className="border-silver dark:border-silver/40 w-full rounded-lg border bg-transparent px-2 py-1 text-sm outline-hidden" /> handlePropertyChange( 'headers', key, 'description', e.target.value, ) } /> ), )} {addingPropertySection === 'headers' ? ( setNewPropertyKey(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') { handleAddProperty(); } }} placeholder={t('settings.tools.propertyName')} className="border-silver dark:border-silver/40 flex w-full min-w-[130.5px] items-start rounded-lg border bg-transparent px-2 py-1 text-sm outline-hidden" /> ) : ( )} ); }; return (

{t('settings.tools.headers')}

{renderHeadersTable()}
{t('settings.tools.name')} {t('settings.tools.value')} {t('settings.tools.description')}

{t('settings.tools.queryParameters')}

{renderPropertiesTable('query_params')}
{t('settings.tools.name')} {t('settings.tools.type')} {t('settings.tools.filledByLLM')} {t('settings.tools.description')} {t('settings.tools.value')}

{t('settings.tools.body')}

{renderPropertiesTable('body')}
{t('settings.tools.name')} {t('settings.tools.type')} {t('settings.tools.filledByLLM')} {t('settings.tools.description')} {t('settings.tools.value')}
); }