fix: preserve Swagger tool authorization after refresh (#41656)

This commit is contained in:
Joel authored and GitHub committed 2026-09-02 09:13:51 +00:00
1 parent e577c007a0
commit 6ae40b1f15
2 files changed
+81 -4

No files matched your search

@@ -24,6 +24,7 @@ import { AgentTools } from '../index'
const toolProviderState = vi.hoisted(() => ({
builtInTools: [] as ToolWithProvider[] | undefined,
customTools: [] as ToolWithProvider[] | undefined,
}))
const pluginAuthState = vi.hoisted(() => ({
canOAuth: true as boolean | undefined,
@@ -159,7 +160,7 @@ vi.mock('@/app/components/header/account-setting/model-provider-page/model-modal
vi.mock('@/service/use-tools', () => ({
useAllBuiltInTools: () => ({ data: toolProviderState.builtInTools }),
useAllCustomTools: () => ({ data: [] }),
useAllCustomTools: () => ({ data: toolProviderState.customTools }),
useAllWorkflowTools: () => ({ data: [] }),
useAllMCPTools: () => ({ data: [] }),
useInvalidateAllBuiltInTools: () => pluginInstallState.invalidateBuiltInTools,
@@ -292,6 +293,29 @@ const reflectedUnauthorizedOAuthCredentialTypeDraft = {
],
} satisfies AgentSoulConfigFormState
const reflectedAuthorizedSwaggerDraft = {
...defaultAgentSoulConfigFormState,
tools: [
{
id: 'weather-api',
kind: 'provider',
name: 'weather-api',
iconClassName: 'i-custom-public-other-default-tool-icon',
providerType: CollectionType.custom,
credentialType: 'unauthorized',
credentialVariant: 'unauthorized',
actions: [
{
id: 'weather-api:forecast',
name: 'forecast',
toolName: 'forecast',
description: '',
},
],
},
],
} satisfies AgentSoulConfigFormState
const googleProvider = {
id: 'google',
name: 'google',
@@ -384,6 +408,40 @@ const duckDuckGoProvider = {
],
} satisfies ToolWithProvider
const authorizedSwaggerProvider = {
...googleProvider,
id: 'weather-api',
name: 'weather-api',
label: {
en_US: 'Weather API',
zh_Hans: '天气 API',
},
type: CollectionType.custom,
team_credentials: {
api_key: {
type: 'secret-input',
},
},
is_team_authorization: true,
tools: [
{
name: 'forecast',
author: 'Weather API',
label: {
en_US: 'Forecast',
zh_Hans: '天气预报',
},
description: {
en_US: 'Get the weather forecast.',
zh_Hans: '获取天气预报。',
},
parameters: [],
labels: [],
output_schema: {},
},
],
} satisfies ToolWithProvider
function renderAgentTools(initialDraft: AgentSoulConfigFormState = agentToolsDraft) {
const queryClient = new QueryClient({
defaultOptions: {
@@ -464,6 +522,7 @@ describe('AgentTools', () => {
cleanup()
vi.clearAllMocks()
toolProviderState.builtInTools = []
toolProviderState.customTools = []
pluginAuthState.canOAuth = true
pluginAuthState.canApiKey = false
pluginAuthState.credentials = []
@@ -724,6 +783,22 @@ describe('AgentTools', () => {
expect(screen.queryByText('tools.notAuthorized')).not.toBeInTheDocument()
})
it('should use current team authorization for reflected Swagger API tools', () => {
toolProviderState.customTools = [authorizedSwaggerProvider]
renderAgentTools(reflectedAuthorizedSwaggerDraft)
expect(
screen.getByRole('button', {
name: 'Weather API',
}),
).toBeInTheDocument()
expect(
screen.queryByRole('button', {
name: 'tools.notAuthorized',
}),
).not.toBeInTheDocument()
})
it('should keep provider credential metadata display-only without dirtying the composer draft', () => {
toolProviderState.builtInTools = [duckDuckGoProvider]
const { store } = renderAgentToolsWithStore(reflectedUnauthorizedNoCredentialDraft)
@@ -215,11 +215,13 @@ export function getProviderCredentialVariant(
) {
if (!providerCredentialType) return 'none' as const
// Team-scoped credentials have no credential reference in the saved agent config,
// so the current provider authorization must override a reflected unauthorized state.
if (tool.credentialId || provider.is_team_authorization) return 'authorized' as const
if (tool.credentialVariant !== 'none') return tool.credentialVariant
return tool.credentialId || provider.is_team_authorization
? ('authorized' as const)
: ('unauthorized' as const)
return 'unauthorized' as const
}
export type AgentToolPublishIssue = {