fix: handle trailing slashes in API URLs for image generation (#12492)

fix: normalize provider apiHost at source to handle trailing slashes

Normalize provider apiHost by removing trailing slashes in useProvider.ts
selectors. This ensures consistent URL concatenation across the entire
application, including image generation pages, without modifying each
usage point individually.

Fixes #12485

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
SuYao 2026-01-16 23:05:13 +08:00 committed by GitHub
parent 0880435c06
commit 8186d4fa29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -13,12 +13,28 @@ import {
} from '@renderer/store/llm'
import type { Assistant, Model, Provider } from '@renderer/types'
import { isSystemProvider } from '@renderer/types'
import { withoutTrailingSlash } from '@renderer/utils/api'
import { useDefaultModel } from './useAssistant'
/**
* Normalizes provider apiHost by removing trailing slashes.
* This ensures consistent URL concatenation across the application.
*/
function normalizeProvider<T extends Provider>(provider: T): T {
return {
...provider,
apiHost: withoutTrailingSlash(provider.apiHost)
}
}
const selectEnabledProviders = createSelector(
(state) => state.llm.providers,
(providers) => providers.filter((p) => p.enabled).concat(CHERRYAI_PROVIDER)
(providers) =>
providers
.map(normalizeProvider)
.filter((p) => p.enabled)
.concat(CHERRYAI_PROVIDER)
)
export function useProviders() {
@ -35,21 +51,25 @@ export function useProviders() {
}
export function useSystemProviders() {
return useAppSelector((state) => state.llm.providers.filter((p) => isSystemProvider(p)))
return useAppSelector((state) => state.llm.providers.filter((p) => isSystemProvider(p)).map(normalizeProvider))
}
export function useUserProviders() {
return useAppSelector((state) => state.llm.providers.filter((p) => !isSystemProvider(p)))
return useAppSelector((state) => state.llm.providers.filter((p) => !isSystemProvider(p)).map(normalizeProvider))
}
export function useAllProviders() {
return useAppSelector((state) => state.llm.providers)
return useAppSelector((state) => state.llm.providers.map(normalizeProvider))
}
export function useProvider(id: string) {
const provider =
useAppSelector((state) => state.llm.providers.concat([CHERRYAI_PROVIDER]).find((p) => p.id === id)) ||
getDefaultProvider()
useAppSelector((state) =>
state.llm.providers
.concat([CHERRYAI_PROVIDER])
.map(normalizeProvider)
.find((p) => p.id === id)
) || getDefaultProvider()
const dispatch = useAppDispatch()
return {