mirror of
https://github.com/langgenius/dify.git
synced 2026-06-07 16:32:01 +08:00
chore: split trial models to a single API (#36796)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
20f62b9919
commit
ec5404cc9d
@ -16,11 +16,22 @@ from . import console_ns
|
||||
from .wraps import account_initialization_required, cloud_utm_record, setup_required, with_current_tenant_id
|
||||
|
||||
|
||||
class TrialModelsResponse(ResponseModel):
|
||||
trial_models: list[str]
|
||||
|
||||
|
||||
class AppDslVersionResponse(ResponseModel):
|
||||
app_dsl_version: str
|
||||
|
||||
|
||||
register_response_schema_models(console_ns, AppDslVersionResponse, FeatureModel, LimitationModel, SystemFeatureModel)
|
||||
register_response_schema_models(
|
||||
console_ns,
|
||||
AppDslVersionResponse,
|
||||
FeatureModel,
|
||||
LimitationModel,
|
||||
SystemFeatureModel,
|
||||
TrialModelsResponse,
|
||||
)
|
||||
|
||||
|
||||
@console_ns.route("/features")
|
||||
@ -66,6 +77,26 @@ class FeatureVectorSpaceApi(Resource):
|
||||
return FeatureService.get_vector_space(current_tenant_id).model_dump()
|
||||
|
||||
|
||||
@console_ns.route("/trial-models")
|
||||
class TrialModelsApi(Resource):
|
||||
@console_ns.doc("get_trial_models")
|
||||
@console_ns.doc(description="Get hosted trial model provider configuration")
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Success",
|
||||
console_ns.models[TrialModelsResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
def get(self):
|
||||
"""Get hosted trial model provider configuration for model-provider pages."""
|
||||
return dump_response(
|
||||
TrialModelsResponse,
|
||||
{"trial_models": FeatureService.get_trial_models()},
|
||||
)
|
||||
|
||||
|
||||
@console_ns.route("/app-dsl-version")
|
||||
class AppDslVersionApi(Resource):
|
||||
@console_ns.doc("get_app_dsl_version")
|
||||
|
||||
@ -8258,6 +8258,23 @@ Stop workflow task
|
||||
| ---- | ----------- |
|
||||
| 200 | Success |
|
||||
|
||||
### /trial-models
|
||||
|
||||
#### GET
|
||||
##### Summary
|
||||
|
||||
Get hosted trial model provider configuration for model-provider pages
|
||||
|
||||
##### Description
|
||||
|
||||
Get hosted trial model provider configuration
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | [TrialModelsResponse](#trialmodelsresponse) |
|
||||
|
||||
### /website/crawl
|
||||
|
||||
#### POST
|
||||
@ -15292,7 +15309,6 @@ Default configuration for form inputs.
|
||||
| plugin_manager | [PluginManagerModel](#pluginmanagermodel) | | Yes |
|
||||
| sso_enforced_for_signin | boolean | | Yes |
|
||||
| sso_enforced_for_signin_protocol | string | | Yes |
|
||||
| trial_models | [ string ] | | Yes |
|
||||
| webapp_auth | [WebAppAuthModel](#webappauthmodel) | | Yes |
|
||||
|
||||
#### Tag
|
||||
@ -15519,6 +15535,12 @@ Tag type
|
||||
| tool_name | string | | No |
|
||||
| type | string | | No |
|
||||
|
||||
#### TrialModelsResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| trial_models | [ string ] | | Yes |
|
||||
|
||||
#### TrialPipelineVariable
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|
||||
@ -1342,7 +1342,6 @@ Returns Server-Sent Events stream.
|
||||
| plugin_manager | [PluginManagerModel](#pluginmanagermodel) | | Yes |
|
||||
| sso_enforced_for_signin | boolean | | Yes |
|
||||
| sso_enforced_for_signin_protocol | string | | Yes |
|
||||
| trial_models | [ string ] | | Yes |
|
||||
| webapp_auth | [WebAppAuthModel](#webappauthmodel) | | Yes |
|
||||
|
||||
#### TextToAudioPayload
|
||||
|
||||
@ -177,7 +177,6 @@ class SystemFeatureModel(FeatureResponseModel):
|
||||
plugin_installation_permission: PluginInstallationPermissionModel = PluginInstallationPermissionModel()
|
||||
enable_change_email: bool = True
|
||||
plugin_manager: PluginManagerModel = PluginManagerModel()
|
||||
trial_models: list[str] = []
|
||||
enable_creators_platform: bool = False
|
||||
enable_trial_app: bool = False
|
||||
enable_explore_banner: bool = False
|
||||
@ -278,7 +277,6 @@ class FeatureService:
|
||||
system_features.is_allow_register = dify_config.ALLOW_REGISTER
|
||||
system_features.is_allow_create_workspace = dify_config.ALLOW_CREATE_WORKSPACE
|
||||
system_features.is_email_setup = dify_config.MAIL_TYPE is not None and dify_config.MAIL_TYPE != ""
|
||||
system_features.trial_models = cls._fulfill_trial_models_from_env()
|
||||
system_features.enable_trial_app = dify_config.ENABLE_TRIAL_APP
|
||||
system_features.enable_explore_banner = dify_config.ENABLE_EXPLORE_BANNER
|
||||
|
||||
@ -293,6 +291,11 @@ class FeatureService:
|
||||
)
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def get_trial_models(cls) -> list[str]:
|
||||
"""Return hosted trial provider ids without requiring the full system-features payload."""
|
||||
return cls._fulfill_trial_models_from_env()
|
||||
|
||||
@classmethod
|
||||
def _fulfill_params_from_env(cls, features: FeatureModel):
|
||||
features.can_replace_logo = dify_config.CAN_REPLACE_LOGO
|
||||
|
||||
@ -46,6 +46,22 @@ class TestFeatureVectorSpaceApi:
|
||||
get_vector_space.assert_called_once_with("tenant_123")
|
||||
|
||||
|
||||
class TestTrialModelsApi:
|
||||
def test_get_trial_models_success(self, mocker: MockerFixture):
|
||||
from controllers.console.feature import TrialModelsApi
|
||||
|
||||
get_trial_models = mocker.patch("controllers.console.feature.FeatureService.get_trial_models")
|
||||
get_trial_models.return_value = ["langgenius/openai/openai"]
|
||||
|
||||
api = TrialModelsApi()
|
||||
|
||||
raw_get = unwrap(TrialModelsApi.get)
|
||||
result = raw_get(api)
|
||||
|
||||
assert result == {"trial_models": ["langgenius/openai/openai"]}
|
||||
get_trial_models.assert_called_once_with()
|
||||
|
||||
|
||||
class TestAppDslVersionApi:
|
||||
def test_get_app_dsl_version_success(self, mocker: MockerFixture):
|
||||
from controllers.console.feature import AppDslVersionApi
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
import pytest
|
||||
|
||||
from enums.hosted_provider import HostedTrialProvider
|
||||
from services import feature_service as feature_service_module
|
||||
from services.feature_service import FeatureService
|
||||
|
||||
|
||||
def test_get_system_features_excludes_trial_models():
|
||||
result = FeatureService.get_system_features().model_dump()
|
||||
|
||||
assert "trial_models" not in result
|
||||
|
||||
|
||||
def test_get_trial_models_returns_providers_enabled_for_paid_and_trial(monkeypatch: pytest.MonkeyPatch):
|
||||
for provider in HostedTrialProvider:
|
||||
monkeypatch.setattr(
|
||||
feature_service_module.dify_config,
|
||||
f"HOSTED_{provider.config_key}_PAID_ENABLED",
|
||||
False,
|
||||
raising=False,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
feature_service_module.dify_config,
|
||||
f"HOSTED_{provider.config_key}_TRIAL_ENABLED",
|
||||
False,
|
||||
raising=False,
|
||||
)
|
||||
|
||||
monkeypatch.setattr(feature_service_module.dify_config, "HOSTED_OPENAI_PAID_ENABLED", True, raising=False)
|
||||
monkeypatch.setattr(feature_service_module.dify_config, "HOSTED_OPENAI_TRIAL_ENABLED", True, raising=False)
|
||||
monkeypatch.setattr(feature_service_module.dify_config, "HOSTED_ANTHROPIC_PAID_ENABLED", True, raising=False)
|
||||
monkeypatch.setattr(feature_service_module.dify_config, "HOSTED_ANTHROPIC_TRIAL_ENABLED", False, raising=False)
|
||||
monkeypatch.setattr(feature_service_module.dify_config, "HOSTED_GEMINI_PAID_ENABLED", False, raising=False)
|
||||
monkeypatch.setattr(feature_service_module.dify_config, "HOSTED_GEMINI_TRIAL_ENABLED", True, raising=False)
|
||||
|
||||
result = FeatureService.get_trial_models()
|
||||
|
||||
assert result == [HostedTrialProvider.OPENAI.value]
|
||||
@ -5537,11 +5537,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/types/feature.ts": {
|
||||
"erasable-syntax-only/enums": {
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"web/types/lamejs.d.ts": {
|
||||
"ts/no-explicit-any": {
|
||||
"count": 3
|
||||
|
||||
@ -44,6 +44,7 @@ import { tagBindings } from './tag-bindings/orpc.gen'
|
||||
import { tags } from './tags/orpc.gen'
|
||||
import { test } from './test/orpc.gen'
|
||||
import { trialApps } from './trial-apps/orpc.gen'
|
||||
import { trialModels } from './trial-models/orpc.gen'
|
||||
import { website } from './website/orpc.gen'
|
||||
import { workflow } from './workflow/orpc.gen'
|
||||
import { workspaces } from './workspaces/orpc.gen'
|
||||
@ -93,6 +94,7 @@ export const contract = {
|
||||
tags,
|
||||
test,
|
||||
trialApps,
|
||||
trialModels,
|
||||
website,
|
||||
workflow,
|
||||
workspaces,
|
||||
|
||||
@ -24,7 +24,6 @@ export type SystemFeatureModel = {
|
||||
plugin_manager: PluginManagerModel
|
||||
sso_enforced_for_signin: boolean
|
||||
sso_enforced_for_signin_protocol: string
|
||||
trial_models: Array<string>
|
||||
webapp_auth: WebAppAuthModel
|
||||
}
|
||||
|
||||
|
||||
@ -106,7 +106,6 @@ export const zSystemFeatureModel = z.object({
|
||||
plugin_manager: zPluginManagerModel,
|
||||
sso_enforced_for_signin: z.boolean().default(false),
|
||||
sso_enforced_for_signin_protocol: z.string().default(''),
|
||||
trial_models: z.array(z.string()).default([]),
|
||||
webapp_auth: zWebAppAuthModel,
|
||||
})
|
||||
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import { oc } from '@orpc/contract'
|
||||
|
||||
import { zGetTrialModelsResponse } from './zod.gen'
|
||||
|
||||
/**
|
||||
* Get hosted trial model provider configuration for model-provider pages
|
||||
*
|
||||
* Get hosted trial model provider configuration
|
||||
*/
|
||||
export const get = oc
|
||||
.route({
|
||||
description: 'Get hosted trial model provider configuration',
|
||||
inputStructure: 'detailed',
|
||||
method: 'GET',
|
||||
operationId: 'getTrialModels',
|
||||
path: '/trial-models',
|
||||
summary: 'Get hosted trial model provider configuration for model-provider pages',
|
||||
tags: ['console'],
|
||||
})
|
||||
.output(zGetTrialModelsResponse)
|
||||
|
||||
export const trialModels = {
|
||||
get,
|
||||
}
|
||||
|
||||
export const contract = {
|
||||
trialModels,
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
export type ClientOptions = {
|
||||
baseUrl: `${string}://${string}/console/api` | (string & {})
|
||||
}
|
||||
|
||||
export type TrialModelsResponse = {
|
||||
trial_models: Array<string>
|
||||
}
|
||||
|
||||
export type GetTrialModelsData = {
|
||||
body?: never
|
||||
path?: never
|
||||
query?: never
|
||||
url: '/trial-models'
|
||||
}
|
||||
|
||||
export type GetTrialModelsResponses = {
|
||||
200: TrialModelsResponse
|
||||
}
|
||||
|
||||
export type GetTrialModelsResponse = GetTrialModelsResponses[keyof GetTrialModelsResponses]
|
||||
@ -0,0 +1,15 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import * as z from 'zod'
|
||||
|
||||
/**
|
||||
* TrialModelsResponse
|
||||
*/
|
||||
export const zTrialModelsResponse = z.object({
|
||||
trial_models: z.array(z.string()),
|
||||
})
|
||||
|
||||
/**
|
||||
* Success
|
||||
*/
|
||||
export const zGetTrialModelsResponse = zTrialModelsResponse
|
||||
@ -237,7 +237,6 @@ export type SystemFeatureModel = {
|
||||
plugin_manager: PluginManagerModel
|
||||
sso_enforced_for_signin: boolean
|
||||
sso_enforced_for_signin_protocol: string
|
||||
trial_models: Array<string>
|
||||
webapp_auth: WebAppAuthModel
|
||||
}
|
||||
|
||||
|
||||
@ -383,7 +383,6 @@ export const zSystemFeatureModel = z.object({
|
||||
plugin_manager: zPluginManagerModel,
|
||||
sso_enforced_for_signin: z.boolean().default(false),
|
||||
sso_enforced_for_signin_protocol: z.string().default(''),
|
||||
trial_models: z.array(z.string()).default([]),
|
||||
webapp_auth: zWebAppAuthModel,
|
||||
})
|
||||
|
||||
|
||||
@ -6,28 +6,39 @@ import { render, renderHook } from '@testing-library/react'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { defaultSystemFeatures } from '@/types/feature'
|
||||
|
||||
type DeepPartial<T> = T extends Array<infer U>
|
||||
? Array<U>
|
||||
: T extends object
|
||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: T
|
||||
|
||||
type QueryKeyProvider = {
|
||||
queryKey: () => readonly unknown[]
|
||||
}
|
||||
|
||||
type TrialModelsQueryProvider = {
|
||||
get?: QueryKeyProvider
|
||||
}
|
||||
|
||||
type AppDslVersionQueryProvider = {
|
||||
get?: QueryKeyProvider
|
||||
}
|
||||
|
||||
const fallbackTrialModelsQueryKey = ['console', 'trialModels', 'get'] as const
|
||||
const fallbackAppDslVersionQueryKey = ['console', 'appDslVersion', 'get'] as const
|
||||
|
||||
const getTrialModelsQueryKey = () => {
|
||||
const trialModelsQuery = (consoleQuery as { trialModels?: TrialModelsQueryProvider }).trialModels
|
||||
|
||||
return trialModelsQuery?.get?.queryKey() ?? fallbackTrialModelsQueryKey
|
||||
}
|
||||
|
||||
const getAppDslVersionQueryKey = () => {
|
||||
const appDslVersionQuery = (consoleQuery as { appDslVersion?: AppDslVersionQueryProvider }).appDslVersion
|
||||
|
||||
return appDslVersionQuery?.get?.queryKey() ?? fallbackAppDslVersionQueryKey
|
||||
}
|
||||
|
||||
type DeepPartial<T> = T extends Array<infer U>
|
||||
? Array<U>
|
||||
: T extends object
|
||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: T
|
||||
|
||||
const buildSystemFeatures = (
|
||||
overrides: DeepPartial<SystemFeatures> = {},
|
||||
): SystemFeatures => {
|
||||
@ -86,6 +97,13 @@ export const seedSystemFeatures = (
|
||||
return data
|
||||
}
|
||||
|
||||
const seedTrialModels = (
|
||||
queryClient: QueryClient,
|
||||
trialModels: readonly string[] = [],
|
||||
) => {
|
||||
queryClient.setQueryData(getTrialModelsQueryKey(), { trial_models: [...trialModels] })
|
||||
}
|
||||
|
||||
export const seedAppDslVersion = (
|
||||
queryClient: QueryClient,
|
||||
appDslVersion = '0.6.0',
|
||||
@ -101,6 +119,7 @@ type SystemFeaturesTestOptions = {
|
||||
* keep the systemFeatures query in the pending state.
|
||||
*/
|
||||
systemFeatures?: DeepPartial<SystemFeatures> | null
|
||||
trialModels?: readonly string[] | null
|
||||
/**
|
||||
* Seed the workflow clipboard DSL version query only for tests that need it.
|
||||
* Omit or pass `null` to leave it unseeded.
|
||||
@ -122,6 +141,8 @@ export const createSystemFeaturesWrapper = (
|
||||
const systemFeatures = options.systemFeatures === null
|
||||
? null
|
||||
: seedSystemFeatures(queryClient, options.systemFeatures)
|
||||
if (options.trialModels !== undefined && options.trialModels !== null)
|
||||
seedTrialModels(queryClient, options.trialModels)
|
||||
if (options.appDslVersion !== undefined && options.appDslVersion !== null)
|
||||
seedAppDslVersion(queryClient, options.appDslVersion)
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
@ -134,9 +155,10 @@ export const renderWithSystemFeatures = (
|
||||
ui: ReactElement,
|
||||
options: SystemFeaturesTestOptions & Omit<RenderOptions, 'wrapper'> = {},
|
||||
): RenderResult & { queryClient: QueryClient, systemFeatures: SystemFeatures | null } => {
|
||||
const { systemFeatures: sf, appDslVersion, queryClient: qc, ...renderOptions } = options
|
||||
const { systemFeatures: sf, trialModels, appDslVersion, queryClient: qc, ...renderOptions } = options
|
||||
const { wrapper, queryClient, systemFeatures } = createSystemFeaturesWrapper({
|
||||
systemFeatures: sf,
|
||||
trialModels,
|
||||
appDslVersion,
|
||||
queryClient: qc,
|
||||
})
|
||||
@ -148,9 +170,10 @@ export const renderHookWithSystemFeatures = <Result, Props = void>(
|
||||
callback: (props: Props) => Result,
|
||||
options: SystemFeaturesTestOptions & Omit<RenderHookOptions<Props>, 'wrapper'> = {},
|
||||
): RenderHookResult<Result, Props> & { queryClient: QueryClient, systemFeatures: SystemFeatures | null } => {
|
||||
const { systemFeatures: sf, appDslVersion, queryClient: qc, ...hookOptions } = options
|
||||
const { systemFeatures: sf, trialModels, appDslVersion, queryClient: qc, ...hookOptions } = options
|
||||
const { wrapper, queryClient, systemFeatures } = createSystemFeaturesWrapper({
|
||||
systemFeatures: sf,
|
||||
trialModels,
|
||||
appDslVersion,
|
||||
queryClient: qc,
|
||||
})
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import type { ReactElement } from 'react'
|
||||
import type { Model, ModelItem, ModelProvider } from '../../declarations'
|
||||
import type { PopupProps } from '../popup'
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import { Combobox } from '@langgenius/dify-ui/combobox'
|
||||
import { fireEvent, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
@ -105,7 +104,7 @@ function PopupHarness(props: PopupTestProps) {
|
||||
}
|
||||
|
||||
const renderPopup = (ui: ReactElement<PopupTestProps>) => renderWithSystemFeatures(ui, {
|
||||
systemFeatures: { trial_models: mockTrialModels.current as unknown as SystemFeatures['trial_models'] },
|
||||
trialModels: mockTrialModels.current,
|
||||
})
|
||||
|
||||
const mockTrialCredits = vi.hoisted(() => ({
|
||||
|
||||
@ -3,17 +3,18 @@ import type { ModelSelectorPreviewPayload } from './popup-item'
|
||||
import type { ModelProviderQuotaGetPaid } from '@/types/model-provider'
|
||||
import { ComboboxList } from '@langgenius/dify-ui/combobox'
|
||||
import { createPreviewCardHandle, PreviewCard, PreviewCardContent } from '@langgenius/dify-ui/preview-card'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ACCOUNT_SETTING_MODAL_ACTION, ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
|
||||
import checkTaskStatus from '@/app/components/plugins/install-plugin/base/check-task-status'
|
||||
import useRefreshPluginList from '@/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list'
|
||||
import { IS_CLOUD_EDITION } from '@/config'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useSearchParams } from '@/next/navigation'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { useInstallPackageFromMarketPlace } from '@/service/use-plugins'
|
||||
import { CustomConfigurationStatusEnum, ModelFeatureEnum, ModelStatusEnum, ModelTypeEnum } from '../declarations'
|
||||
import { useLanguage, useMarketplaceAllPlugins } from '../hooks'
|
||||
@ -62,8 +63,10 @@ function Popup({
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
const [installingProvider, setInstallingProvider] = useState<ModelProviderQuotaGetPaid | null>(null)
|
||||
const { isExhausted: isCreditsExhausted } = useTrialCredits()
|
||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||
const trialModels = systemFeatures.trial_models
|
||||
const { data: trialModels = [] } = useQuery(consoleQuery.trialModels.get.queryOptions({
|
||||
enabled: IS_CLOUD_EDITION,
|
||||
select: data => data.trial_models,
|
||||
}))
|
||||
const installedProviderMap = useMemo(() => new Map(
|
||||
modelProviders.map(provider => [provider.provider, provider]),
|
||||
), [modelProviders])
|
||||
|
||||
@ -111,7 +111,7 @@ const createProvider = (overrides: Partial<ModelProvider> = {}): ModelProvider =
|
||||
|
||||
const renderWithQueryClient = (provider: ModelProvider) => {
|
||||
return renderWithSystemFeatures(<CredentialPanel provider={provider} />, {
|
||||
systemFeatures: { trial_models: ['langgenius/openai/openai'] as never },
|
||||
trialModels: ['langgenius/openai/openai'],
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ vi.mock('../use-trial-credits', () => ({
|
||||
}))
|
||||
|
||||
const renderQuotaPanel = (ui: ReactElement) => renderWithSystemFeatures(ui, {
|
||||
systemFeatures: mockTrialModels === undefined ? null : { trial_models: mockTrialModels as never },
|
||||
trialModels: mockTrialModels ?? [],
|
||||
})
|
||||
|
||||
vi.mock('../../hooks', () => ({
|
||||
|
||||
@ -22,7 +22,7 @@ vi.mock('@/config', async (importOriginal) => {
|
||||
|
||||
const renderPanelHook = (provider: ModelProvider | undefined) =>
|
||||
renderHookWithSystemFeatures(() => useCredentialPanelState(provider), {
|
||||
systemFeatures: { trial_models: mockTrialModels as never },
|
||||
trialModels: mockTrialModels,
|
||||
})
|
||||
|
||||
const createProvider = (overrides: Partial<ModelProvider> = {}): ModelProvider => ({
|
||||
|
||||
@ -4,7 +4,7 @@ import type { Plugin } from '@/app/components/plugins/types'
|
||||
import type { ModelProviderQuotaGetPaid } from '@/types/model-provider'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
@ -12,8 +12,9 @@ import { useTranslation } from 'react-i18next'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
|
||||
import { IS_CLOUD_EDITION } from '@/config'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { formatNumber } from '@/utils/format'
|
||||
import { PreferredProviderTypeEnum } from '../declarations'
|
||||
import { useMarketplaceAllPlugins } from '../hooks'
|
||||
@ -34,8 +35,10 @@ const QuotaPanel: FC<QuotaPanelProps> = ({
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { credits, isExhausted, isLoading, nextCreditResetDate } = useTrialCredits()
|
||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||
const trialModels = systemFeatures.trial_models
|
||||
const { data: trialModels = [] } = useQuery(consoleQuery.trialModels.get.queryOptions({
|
||||
enabled: IS_CLOUD_EDITION,
|
||||
select: data => data.trial_models,
|
||||
}))
|
||||
const providerMap = useMemo(() => new Map(
|
||||
providers.map(p => [p.provider, p.preferred_provider_type]),
|
||||
), [providers])
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import type { ModelProvider } from '../declarations'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useCredentialStatus } from '@/app/components/header/account-setting/model-provider-page/model-auth/hooks'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { IS_CLOUD_EDITION } from '@/config'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import {
|
||||
PreferredProviderTypeEnum,
|
||||
} from '../declarations'
|
||||
@ -80,8 +81,10 @@ export function useCredentialPanelState(provider: ModelProvider | undefined): Cr
|
||||
current_credential_name,
|
||||
} = useCredentialStatus(provider)
|
||||
|
||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||
const trialModels = systemFeatures.trial_models
|
||||
const { data: trialModels = [] } = useQuery(consoleQuery.trialModels.get.queryOptions({
|
||||
enabled: IS_CLOUD_EDITION,
|
||||
select: data => data.trial_models,
|
||||
}))
|
||||
|
||||
const preferredType = provider?.preferred_provider_type
|
||||
|
||||
|
||||
@ -1,26 +1,30 @@
|
||||
import type { ModelProviderQuotaGetPaid } from './model-provider'
|
||||
export const SSOProtocol = {
|
||||
SAML: 'saml',
|
||||
OIDC: 'oidc',
|
||||
OAuth2: 'oauth2',
|
||||
} as const
|
||||
|
||||
export enum SSOProtocol {
|
||||
SAML = 'saml',
|
||||
OIDC = 'oidc',
|
||||
OAuth2 = 'oauth2',
|
||||
}
|
||||
export type SSOProtocol = typeof SSOProtocol[keyof typeof SSOProtocol]
|
||||
|
||||
export enum LicenseStatus {
|
||||
NONE = 'none',
|
||||
INACTIVE = 'inactive',
|
||||
ACTIVE = 'active',
|
||||
EXPIRING = 'expiring',
|
||||
EXPIRED = 'expired',
|
||||
LOST = 'lost',
|
||||
}
|
||||
export const LicenseStatus = {
|
||||
NONE: 'none',
|
||||
INACTIVE: 'inactive',
|
||||
ACTIVE: 'active',
|
||||
EXPIRING: 'expiring',
|
||||
EXPIRED: 'expired',
|
||||
LOST: 'lost',
|
||||
} as const
|
||||
|
||||
export enum InstallationScope {
|
||||
ALL = 'all',
|
||||
NONE = 'none',
|
||||
OFFICIAL_ONLY = 'official_only',
|
||||
OFFICIAL_AND_PARTNER = 'official_and_specific_partners',
|
||||
}
|
||||
export type LicenseStatus = typeof LicenseStatus[keyof typeof LicenseStatus]
|
||||
|
||||
export const InstallationScope = {
|
||||
ALL: 'all',
|
||||
NONE: 'none',
|
||||
OFFICIAL_ONLY: 'official_only',
|
||||
OFFICIAL_AND_PARTNER: 'official_and_specific_partners',
|
||||
} as const
|
||||
|
||||
export type InstallationScope = typeof InstallationScope[keyof typeof InstallationScope]
|
||||
|
||||
type License = {
|
||||
status: LicenseStatus
|
||||
@ -28,7 +32,6 @@ type License = {
|
||||
}
|
||||
|
||||
export type SystemFeatures = {
|
||||
trial_models: ModelProviderQuotaGetPaid[]
|
||||
plugin_installation_permission: {
|
||||
plugin_installation_scope: InstallationScope
|
||||
restrict_to_marketplace_only: boolean
|
||||
@ -69,7 +72,6 @@ export type SystemFeatures = {
|
||||
}
|
||||
|
||||
export const defaultSystemFeatures: SystemFeatures = {
|
||||
trial_models: [],
|
||||
plugin_installation_permission: {
|
||||
plugin_installation_scope: InstallationScope.ALL,
|
||||
restrict_to_marketplace_only: false,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user