chore: display non-LLM settings in integration tool details (#39295)

This commit is contained in:
Joel 2026-07-20 17:52:54 +08:00 committed by GitHub
parent cb64446fa3
commit 79751f7622
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 58 additions and 10 deletions

View File

@ -61,8 +61,8 @@ const createParameter = (overrides?: Partial<ToolParameter>): ToolParameter => (
zh_Hans: 'Setting Param',
},
human_description: {
en_US: 'desc',
zh_Hans: 'desc',
en_US: 'Setting description',
zh_Hans: 'Setting description',
},
type: 'string',
form: 'config',
@ -91,6 +91,10 @@ const createTool = (overrides?: Partial<Tool>): Tool => ({
en_US: 'Info Param',
zh_Hans: 'Info Param',
},
human_description: {
en_US: 'Info description',
zh_Hans: 'Info description',
},
form: 'llm',
required: false,
}),
@ -181,6 +185,28 @@ describe('SettingBuiltInTool', () => {
expect(screen.getByTestId('mock-form')).toBeInTheDocument()
})
it('should keep the setting tab hidden when readonly by default', async () => {
renderComponent({ readonly: true })
expect(await screen.findByText('Info Param')).toBeInTheDocument()
expect(screen.queryByText('tools.setBuiltInTools.setting')).not.toBeInTheDocument()
})
it('should expose readonly setting details when explicitly enabled', async () => {
const user = userEvent.setup()
renderComponent({ readonly: true, showReadOnlySettingDetails: true })
expect(await screen.findByText('Info Param')).toBeInTheDocument()
await user.click(screen.getByText('tools.setBuiltInTools.setting'))
expect(screen.getByText('Setting Param')).toBeInTheDocument()
expect(screen.getByText('tools.setBuiltInTools.string')).toBeInTheDocument()
expect(screen.getByText('Setting description')).toBeInTheDocument()
expect(screen.queryByText('Info Param')).not.toBeInTheDocument()
expect(screen.queryByTestId('mock-form')).not.toBeInTheDocument()
expect(screen.queryByRole('button', { name: 'common.operation.save' })).not.toBeInTheDocument()
})
it('should render a masked drawer with balanced vertical offsets', async () => {
const { baseElement } = renderComponent()
await waitFor(() => {

View File

@ -44,6 +44,7 @@ type Props = Readonly<{
toolName: string
setting?: Record<string, any>
readonly?: boolean
showReadOnlySettingDetails?: boolean
onHide: () => void
onSave?: (value: Record<string, any>) => void
credentialId?: string
@ -58,6 +59,7 @@ const SettingBuiltInTool: FC<Props> = ({
toolName,
setting = {},
readonly,
showReadOnlySettingDetails = false,
onHide,
onSave,
credentialId,
@ -75,6 +77,8 @@ const SettingBuiltInTool: FC<Props> = ({
const infoSchemas = formSchemas.filter((item) => item.form === 'llm')
const settingSchemas = formSchemas.filter((item) => item.form !== 'llm')
const hasSetting = settingSchemas.length > 0
const showSettingTab = hasSetting && (!readonly || showReadOnlySettingDetails)
const showSettingAsDetails = readonly && showReadOnlySettingDetails
const [tempSetting, setTempSetting] = useState(setting)
const [currType, setCurrType] = useState('info')
const isInfoActive = currType === 'info'
@ -120,12 +124,12 @@ const SettingBuiltInTool: FC<Props> = ({
return type
}
const infoUI = (
const renderSchemaDetails = (schemas: typeof formSchemas) => (
<div className="">
{infoSchemas.length > 0 && (
{schemas.length > 0 && (
<div className="space-y-1 py-2">
{infoSchemas.map((item, index) => (
<div key={index} className="py-1">
{schemas.map((item) => (
<div key={item.name} 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)}</div>
@ -146,6 +150,8 @@ const SettingBuiltInTool: FC<Props> = ({
)}
</div>
)
const infoUI = renderSchemaDetails(infoSchemas)
const settingDetailsUI = renderSchemaDetails(settingSchemas)
const settingUI = (
<Form
@ -230,7 +236,7 @@ const SettingBuiltInTool: FC<Props> = ({
{/* form */}
<div className="h-full">
<div className="flex h-full flex-col">
{hasSetting && !readonly ? (
{showSettingTab ? (
<TabSlider
className="mt-1 shrink-0 px-4"
itemClassName="py-3"
@ -256,7 +262,9 @@ const SettingBuiltInTool: FC<Props> = ({
</div>
)}
<div className="h-0 grow overflow-y-auto px-4">
{isInfoActive ? infoUI : settingUI}
{isInfoActive && infoUI}
{!isInfoActive && showSettingAsDetails && settingDetailsUI}
{!isInfoActive && !showSettingAsDetails && settingUI}
{!readonly && !isInfoActive && (
<div className="flex shrink-0 justify-end space-x-2 rounded-b-[10px] bg-components-panel-bg py-2">
<Button

View File

@ -7,8 +7,17 @@ vi.mock('@/i18n-config/language', () => ({ getLanguage: () => 'en_US' }))
vi.mock(
'@/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool',
() => ({
default: ({ onHide }: { onHide: () => void }) => (
<div data-testid="tool-detail">
default: ({
onHide,
showReadOnlySettingDetails,
}: {
onHide: () => void
showReadOnlySettingDetails?: boolean
}) => (
<div
data-testid="tool-detail"
data-show-readonly-setting-details={showReadOnlySettingDetails}
>
<button onClick={onHide}>Close details</button>
</div>
),
@ -34,6 +43,10 @@ describe('ToolItem', () => {
fireEvent.click(screen.getByText('Tool label'))
expect(screen.getByTestId('tool-detail')).toBeInTheDocument()
expect(screen.getByTestId('tool-detail')).toHaveAttribute(
'data-show-readonly-setting-details',
'true',
)
fireEvent.click(screen.getByRole('button', { name: 'Close details' }))
expect(screen.queryByTestId('tool-detail')).not.toBeInTheDocument()

View File

@ -43,6 +43,7 @@ const ToolItem = ({ disabled, collection, tool, isBuiltIn, isModel }: Props) =>
collection={collection}
toolName={tool.name}
readonly
showReadOnlySettingDetails
onHide={() => {
setShowDetail(false)
}}