Files
dify/web/contract/router.ts
yyh 45c96dc254 feat(model-provider): add plugin update indicators and migrate to oRPC contracts
Problem: Model provider settings page (/plugins?action=showSettings&tab=provider)
was missing plugin update indicators (red dot badge, Update button) that the
/plugins page correctly displayed, because it only fetched installation data
without querying for latest marketplace versions.

Decision: Extract a shared usePluginsWithLatestVersion hook and migrate plugin
API endpoints to oRPC contracts, ensuring both pages use identical data flows.

Model: Both pages now follow the same pattern — fetch installed plugins via
consoleQuery.plugins.checkInstalled, enrich with latest version metadata via
usePluginsWithLatestVersion, then pass complete PluginDetail objects downstream
where useDetailHeaderState computes hasNewVersion for UI indicators.

Impact:
- Update badge red dot and Update button now appear on provider settings page
- Shared hook eliminates 15 lines of duplicate enrichment logic in plugins-panel
- oRPC contracts replace legacy post() calls for plugin endpoints
- Operation dropdown uses auto-width to prevent "View on Marketplace" text wrapping
- Version badge aligned to use Badge component consistently across both pages
- Update button tooltip added with bilingual i18n support
- Deprecated Tooltip migrated to Base UI Tooltip in detail-header
2026-03-10 23:28:09 +08:00

100 lines
3.9 KiB
TypeScript

import type { InferContractRouterInputs } from '@orpc/contract'
import { appDeleteContract } from './console/apps'
import { bindPartnerStackContract, invoicesContract } from './console/billing'
import {
exploreAppDetailContract,
exploreAppsContract,
exploreBannersContract,
exploreInstalledAppAccessModeContract,
exploreInstalledAppMetaContract,
exploreInstalledAppParametersContract,
exploreInstalledAppPinContract,
exploreInstalledAppsContract,
exploreInstalledAppUninstallContract,
} from './console/explore'
import { changePreferredProviderTypeContract, modelProvidersModelsContract } from './console/model-providers'
import { pluginCheckInstalledContract, pluginLatestVersionsContract } from './console/plugins'
import { systemFeaturesContract } from './console/system'
import {
triggerOAuthConfigContract,
triggerOAuthConfigureContract,
triggerOAuthDeleteContract,
triggerOAuthInitiateContract,
triggerProviderInfoContract,
triggersContract,
triggerSubscriptionBuildContract,
triggerSubscriptionBuilderCreateContract,
triggerSubscriptionBuilderLogsContract,
triggerSubscriptionBuilderUpdateContract,
triggerSubscriptionBuilderVerifyUpdateContract,
triggerSubscriptionDeleteContract,
triggerSubscriptionsContract,
triggerSubscriptionUpdateContract,
triggerSubscriptionVerifyContract,
} from './console/trigger'
import { trialAppDatasetsContract, trialAppInfoContract, trialAppParametersContract, trialAppWorkflowsContract } from './console/try-app'
import { collectionPluginsContract, collectionsContract, searchAdvancedContract } from './marketplace'
export const marketplaceRouterContract = {
collections: collectionsContract,
collectionPlugins: collectionPluginsContract,
searchAdvanced: searchAdvancedContract,
}
export type MarketPlaceInputs = InferContractRouterInputs<typeof marketplaceRouterContract>
export const consoleRouterContract = {
systemFeatures: systemFeaturesContract,
apps: {
deleteApp: appDeleteContract,
},
explore: {
apps: exploreAppsContract,
appDetail: exploreAppDetailContract,
installedApps: exploreInstalledAppsContract,
uninstallInstalledApp: exploreInstalledAppUninstallContract,
updateInstalledApp: exploreInstalledAppPinContract,
appAccessMode: exploreInstalledAppAccessModeContract,
installedAppParameters: exploreInstalledAppParametersContract,
installedAppMeta: exploreInstalledAppMetaContract,
banners: exploreBannersContract,
},
trialApps: {
info: trialAppInfoContract,
datasets: trialAppDatasetsContract,
parameters: trialAppParametersContract,
workflows: trialAppWorkflowsContract,
},
modelProviders: {
models: modelProvidersModelsContract,
changePreferredProviderType: changePreferredProviderTypeContract,
},
plugins: {
checkInstalled: pluginCheckInstalledContract,
latestVersions: pluginLatestVersionsContract,
},
billing: {
invoices: invoicesContract,
bindPartnerStack: bindPartnerStackContract,
},
triggers: {
list: triggersContract,
providerInfo: triggerProviderInfoContract,
subscriptions: triggerSubscriptionsContract,
subscriptionBuilderCreate: triggerSubscriptionBuilderCreateContract,
subscriptionBuilderUpdate: triggerSubscriptionBuilderUpdateContract,
subscriptionBuilderVerifyUpdate: triggerSubscriptionBuilderVerifyUpdateContract,
subscriptionVerify: triggerSubscriptionVerifyContract,
subscriptionBuild: triggerSubscriptionBuildContract,
subscriptionDelete: triggerSubscriptionDeleteContract,
subscriptionUpdate: triggerSubscriptionUpdateContract,
subscriptionBuilderLogs: triggerSubscriptionBuilderLogsContract,
oauthConfig: triggerOAuthConfigContract,
oauthConfigure: triggerOAuthConfigureContract,
oauthDelete: triggerOAuthDeleteContract,
oauthInitiate: triggerOAuthInitiateContract,
},
}
export type ConsoleInputs = InferContractRouterInputs<typeof consoleRouterContract>