chore: generate fastopenapi console contracts (#38580)

This commit is contained in:
Stephen Zhou 2026-07-09 11:52:42 +08:00 committed by GitHub
parent cee88de684
commit c5cef80ea4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 561 additions and 47 deletions

View File

@ -0,0 +1,45 @@
// This file is auto-generated by @hey-api/openapi-ts
import { oc } from '@orpc/contract'
import * as z from 'zod'
import { zGetInitResponse, zPostInitBody, zPostInitResponse } from './zod.gen'
/**
* Get initialization validation status.
*/
export const get = oc
.route({
inputStructure: 'detailed',
method: 'GET',
operationId: 'getInit',
path: '/init',
summary: 'Get initialization validation status.',
tags: ['console'],
})
.output(zGetInitResponse)
/**
* Validate initialization password.
*/
export const post = oc
.route({
inputStructure: 'detailed',
method: 'POST',
operationId: 'postInit',
path: '/init',
successStatus: 201,
summary: 'Validate initialization password.',
tags: ['console'],
})
.input(z.object({ body: zPostInitBody }))
.output(zPostInitResponse)
export const init = {
get,
post,
}
export const contract = {
init,
}

View File

@ -0,0 +1,43 @@
// This file is auto-generated by @hey-api/openapi-ts
export type ClientOptions = {
baseUrl: `${string}://${string}/console/api` | (string & {})
}
export type InitStatusResponse = {
status: 'finished' | 'not_started'
}
export type InitValidatePayload = {
password: string
}
export type InitValidateResponse = {
result: string
}
export type GetInitData = {
body?: never
path?: never
query?: never
url: '/init'
}
export type GetInitResponses = {
200: InitStatusResponse
}
export type GetInitResponse = GetInitResponses[keyof GetInitResponses]
export type PostInitData = {
body: InitValidatePayload
path?: never
query?: never
url: '/init'
}
export type PostInitResponses = {
201: InitValidateResponse
}
export type PostInitResponse = PostInitResponses[keyof PostInitResponses]

View File

@ -0,0 +1,36 @@
// This file is auto-generated by @hey-api/openapi-ts
import * as z from 'zod'
/**
* InitStatusResponse
*/
export const zInitStatusResponse = z.object({
status: z.enum(['finished', 'not_started']),
})
/**
* InitValidatePayload
*/
export const zInitValidatePayload = z.object({
password: z.string().max(30),
})
/**
* InitValidateResponse
*/
export const zInitValidateResponse = z.object({
result: z.string(),
})
/**
* OK
*/
export const zGetInitResponse = zInitStatusResponse
export const zPostInitBody = zInitValidatePayload
/**
* Created
*/
export const zPostInitResponse = zInitValidateResponse

View File

@ -35,6 +35,7 @@ export const contractLoaders = {
import('./forgot-password/orpc.gen').then(({ forgotPassword }) => ({ forgotPassword })),
form: () => import('./form/orpc.gen').then(({ form }) => ({ form })),
info: () => import('./info/orpc.gen').then(({ info }) => ({ info })),
init: () => import('./init/orpc.gen').then(({ init }) => ({ init })),
installedApps: () =>
import('./installed-apps/orpc.gen').then(({ installedApps }) => ({ installedApps })),
instructionGenerate: () =>
@ -47,6 +48,7 @@ export const contractLoaders = {
import('./notification/orpc.gen').then(({ notification }) => ({ notification })),
notion: () => import('./notion/orpc.gen').then(({ notion }) => ({ notion })),
oauth: () => import('./oauth/orpc.gen').then(({ oauth }) => ({ oauth })),
ping: () => import('./ping/orpc.gen').then(({ ping }) => ({ ping })),
rag: () => import('./rag/orpc.gen').then(({ rag }) => ({ rag })),
refreshToken: () =>
import('./refresh-token/orpc.gen').then(({ refreshToken }) => ({ refreshToken })),
@ -61,6 +63,7 @@ export const contractLoaders = {
import('./rule-structured-output-generate/orpc.gen').then(
({ ruleStructuredOutputGenerate }) => ({ ruleStructuredOutputGenerate }),
),
setup: () => import('./setup/orpc.gen').then(({ setup }) => ({ setup })),
snippets: () => import('./snippets/orpc.gen').then(({ snippets }) => ({ snippets })),
spec: () => import('./spec/orpc.gen').then(({ spec }) => ({ spec })),
systemFeatures: () =>
@ -70,6 +73,7 @@ export const contractLoaders = {
test: () => import('./test/orpc.gen').then(({ test }) => ({ test })),
trialApps: () => import('./trial-apps/orpc.gen').then(({ trialApps }) => ({ trialApps })),
trialModels: () => import('./trial-models/orpc.gen').then(({ trialModels }) => ({ trialModels })),
version: () => import('./version/orpc.gen').then(({ version }) => ({ version })),
website: () => import('./website/orpc.gen').then(({ website }) => ({ website })),
workflow: () => import('./workflow/orpc.gen').then(({ workflow }) => ({ workflow })),
workflowGenerate: () =>

View File

@ -0,0 +1,27 @@
// This file is auto-generated by @hey-api/openapi-ts
import { oc } from '@orpc/contract'
import { zGetPingResponse } from './zod.gen'
/**
* Health check endpoint for connection testing.
*/
export const get = oc
.route({
inputStructure: 'detailed',
method: 'GET',
operationId: 'getPing',
path: '/ping',
summary: 'Health check endpoint for connection testing.',
tags: ['console'],
})
.output(zGetPingResponse)
export const ping = {
get,
}
export const contract = {
ping,
}

View File

@ -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 PingResponse = {
result: string
}
export type GetPingData = {
body?: never
path?: never
query?: never
url: '/ping'
}
export type GetPingResponses = {
200: PingResponse
}
export type GetPingResponse = GetPingResponses[keyof GetPingResponses]

View File

@ -0,0 +1,15 @@
// This file is auto-generated by @hey-api/openapi-ts
import * as z from 'zod'
/**
* PingResponse
*/
export const zPingResponse = z.object({
result: z.string(),
})
/**
* OK
*/
export const zGetPingResponse = zPingResponse

View File

@ -24,6 +24,7 @@ import { files } from './files/orpc.gen'
import { forgotPassword } from './forgot-password/orpc.gen'
import { form } from './form/orpc.gen'
import { info } from './info/orpc.gen'
import { init } from './init/orpc.gen'
import { installedApps } from './installed-apps/orpc.gen'
import { instructionGenerate } from './instruction-generate/orpc.gen'
import { login } from './login/orpc.gen'
@ -31,6 +32,7 @@ import { logout } from './logout/orpc.gen'
import { notification } from './notification/orpc.gen'
import { notion } from './notion/orpc.gen'
import { oauth } from './oauth/orpc.gen'
import { ping } from './ping/orpc.gen'
import { rag } from './rag/orpc.gen'
import { refreshToken } from './refresh-token/orpc.gen'
import { remoteFiles } from './remote-files/orpc.gen'
@ -38,6 +40,7 @@ import { resetPassword } from './reset-password/orpc.gen'
import { ruleCodeGenerate } from './rule-code-generate/orpc.gen'
import { ruleGenerate } from './rule-generate/orpc.gen'
import { ruleStructuredOutputGenerate } from './rule-structured-output-generate/orpc.gen'
import { setup } from './setup/orpc.gen'
import { snippets } from './snippets/orpc.gen'
import { spec } from './spec/orpc.gen'
import { systemFeatures } from './system-features/orpc.gen'
@ -46,6 +49,7 @@ 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 { version } from './version/orpc.gen'
import { website } from './website/orpc.gen'
import { workflowGenerate } from './workflow-generate/orpc.gen'
import { workflow } from './workflow/orpc.gen'
@ -75,6 +79,7 @@ const communityContract = {
forgotPassword,
form,
info,
init,
installedApps,
instructionGenerate,
login,
@ -82,6 +87,7 @@ const communityContract = {
notification,
notion,
oauth,
ping,
rag,
refreshToken,
remoteFiles,
@ -89,6 +95,7 @@ const communityContract = {
ruleCodeGenerate,
ruleGenerate,
ruleStructuredOutputGenerate,
setup,
snippets,
spec,
systemFeatures,
@ -97,6 +104,7 @@ const communityContract = {
test,
trialApps,
trialModels,
version,
website,
workflow,
workflowGenerate,

View File

@ -0,0 +1,60 @@
// This file is auto-generated by @hey-api/openapi-ts
import { oc } from '@orpc/contract'
import * as z from 'zod'
import { zGetSetupResponse, zPostSetupBody, zPostSetupResponse } from './zod.gen'
/**
* Get system setup status.
*
* NOTE: This endpoint is unauthenticated by design.
*
* During first-time bootstrap there is no admin account yet, so frontend initialization must be
* able to query setup progress before any login flow exists.
*
* Only bootstrap-safe status information should be returned by this endpoint.
*
*/
export const get = oc
.route({
inputStructure: 'detailed',
method: 'GET',
operationId: 'getSetup',
path: '/setup',
summary:
'Get system setup status.\n\n NOTE: This endpoint is unauthenticated by design.\n\n During first-time bootstrap there is no admin account yet, so frontend initialization must be\n able to query setup progress before any login flow exists.\n\n Only bootstrap-safe status information should be returned by this endpoint.\n ',
tags: ['console'],
})
.output(zGetSetupResponse)
/**
* Initialize system setup with admin account.
*
* NOTE: This endpoint is unauthenticated by design for first-time bootstrap.
* Access is restricted by deployment mode (`SELF_HOSTED`), one-time setup guards,
* and init-password validation rather than user session authentication.
*
*/
export const post = oc
.route({
inputStructure: 'detailed',
method: 'POST',
operationId: 'postSetup',
path: '/setup',
successStatus: 201,
summary:
'Initialize system setup with admin account.\n\n NOTE: This endpoint is unauthenticated by design for first-time bootstrap.\n Access is restricted by deployment mode (`SELF_HOSTED`), one-time setup guards,\n and init-password validation rather than user session authentication.\n ',
tags: ['console'],
})
.input(z.object({ body: zPostSetupBody }))
.output(zPostSetupResponse)
export const setup = {
get,
post,
}
export const contract = {
setup,
}

View File

@ -0,0 +1,47 @@
// This file is auto-generated by @hey-api/openapi-ts
export type ClientOptions = {
baseUrl: `${string}://${string}/console/api` | (string & {})
}
export type SetupStatusResponse = {
setup_at?: string | null
step: 'finished' | 'not_started'
}
export type SetupRequestPayload = {
email: string
language?: string | null
name: string
password: string
}
export type SetupResponse = {
result: string
}
export type GetSetupData = {
body?: never
path?: never
query?: never
url: '/setup'
}
export type GetSetupResponses = {
200: SetupStatusResponse
}
export type GetSetupResponse = GetSetupResponses[keyof GetSetupResponses]
export type PostSetupData = {
body: SetupRequestPayload
path?: never
query?: never
url: '/setup'
}
export type PostSetupResponses = {
201: SetupResponse
}
export type PostSetupResponse = PostSetupResponses[keyof PostSetupResponses]

View File

@ -0,0 +1,40 @@
// This file is auto-generated by @hey-api/openapi-ts
import * as z from 'zod'
/**
* SetupStatusResponse
*/
export const zSetupStatusResponse = z.object({
setup_at: z.string().nullish(),
step: z.enum(['finished', 'not_started']),
})
/**
* SetupRequestPayload
*/
export const zSetupRequestPayload = z.object({
email: z.string(),
language: z.string().nullish(),
name: z.string().max(30),
password: z.string(),
})
/**
* SetupResponse
*/
export const zSetupResponse = z.object({
result: z.string(),
})
/**
* OK
*/
export const zGetSetupResponse = zSetupStatusResponse
export const zPostSetupBody = zSetupRequestPayload
/**
* Created
*/
export const zPostSetupResponse = zSetupResponse

View File

@ -0,0 +1,29 @@
// This file is auto-generated by @hey-api/openapi-ts
import { oc } from '@orpc/contract'
import * as z from 'zod'
import { zGetVersionQuery, zGetVersionResponse } from './zod.gen'
/**
* Check for application version updates.
*/
export const get = oc
.route({
inputStructure: 'detailed',
method: 'GET',
operationId: 'getVersion',
path: '/version',
summary: 'Check for application version updates.',
tags: ['console'],
})
.input(z.object({ query: zGetVersionQuery }))
.output(zGetVersionResponse)
export const version = {
get,
}
export const contract = {
version,
}

View File

@ -0,0 +1,33 @@
// This file is auto-generated by @hey-api/openapi-ts
export type ClientOptions = {
baseUrl: `${string}://${string}/console/api` | (string & {})
}
export type VersionResponse = {
can_auto_update: boolean
features: VersionFeatures
release_date: string
release_notes: string
version: string
}
export type VersionFeatures = {
can_replace_logo: boolean
model_load_balancing_enabled: boolean
}
export type GetVersionData = {
body?: never
path?: never
query: {
current_version: string
}
url: '/version'
}
export type GetVersionResponses = {
200: VersionResponse
}
export type GetVersionResponse = GetVersionResponses[keyof GetVersionResponses]

View File

@ -0,0 +1,31 @@
// This file is auto-generated by @hey-api/openapi-ts
import * as z from 'zod'
/**
* VersionFeatures
*/
export const zVersionFeatures = z.object({
can_replace_logo: z.boolean(),
model_load_balancing_enabled: z.boolean(),
})
/**
* VersionResponse
*/
export const zVersionResponse = z.object({
can_auto_update: z.boolean(),
features: zVersionFeatures,
release_date: z.string(),
release_notes: z.string(),
version: z.string(),
})
export const zGetVersionQuery = z.object({
current_version: z.string(),
})
/**
* OK
*/
export const zGetVersionResponse = zVersionResponse

View File

@ -62,6 +62,8 @@ const apiOpenApiDir = path.resolve(currentDir, 'openapi')
const operationMethods = new Set(['delete', 'get', 'patch', 'post', 'put'])
const pydanticDecimalStringPattern = '^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$'
const codegenSafeDecimalStringPattern = '^(?![-+.]*$)[+-]?0*\\d*\\.?\\d*$'
const fastOpenApiConsoleSpecFilename = 'fastopenapi-console-openapi.json'
const fastOpenApiConsolePathPrefix = '/console/api'
const apiSpecs: ApiSpec[] = [
{ filename: 'console-openapi.json', name: 'console' },
@ -276,6 +278,33 @@ const normalizeApiSwagger = (document: SwaggerDocument) => {
return document
}
const mergeFastOpenApiConsoleSwagger = (document: SwaggerDocument) => {
const fastOpenApiDocument = readApiSwagger(fastOpenApiConsoleSpecFilename)
const targetPaths = document.paths ??= {}
for (const [routePath, pathItem] of Object.entries(fastOpenApiDocument.paths ?? {})) {
const contractPath = routePath.startsWith(fastOpenApiConsolePathPrefix)
? routePath.slice(fastOpenApiConsolePathPrefix.length) || '/'
: routePath
if (targetPaths[contractPath])
throw new Error(`Duplicate console API path after FastOpenAPI merge: ${contractPath}`)
targetPaths[contractPath] = pathItem
}
const targetSchemas = getDocumentSchemas(document)
const sourceSchemas = getDocumentSchemas(fastOpenApiDocument)
for (const [schemaName, schema] of Object.entries(sourceSchemas)) {
if (targetSchemas[schemaName])
throw new Error(`Duplicate console API schema after FastOpenAPI merge: ${schemaName}`)
targetSchemas[schemaName] = schema
}
return document
}
const topLevelPathSegment = (routePath: string) => {
return routePath.split('/').filter(Boolean)[0] ?? 'root'
}
@ -435,7 +464,11 @@ const splitConsoleDocument = (document: SwaggerDocument) => {
}
const createApiJobs = (spec: ApiSpec): ApiJob[] => {
const document = normalizeApiSwagger(readApiSwagger(spec.filename))
const document = normalizeApiSwagger(
spec.name === 'console'
? mergeFastOpenApiConsoleSwagger(readApiSwagger(spec.filename))
: readApiSwagger(spec.filename),
)
if (spec.name === 'console')
return splitConsoleDocument(document)

View File

@ -18,9 +18,7 @@
}
},
"scripts": {
"gen-api-contract": "pnpm gen-api-openapi && pnpm gen-api-contract-from-openapi",
"gen-api-contract-from-openapi": "node -e \"fs.rmSync('generated/api', { recursive: true, force: true })\" && openapi-ts -f openapi-ts.api.config.ts && vp fmt generated/api && eslint --fix generated/api",
"gen-api-openapi": "uv run --project ../../api ../../api/dev/generate_swagger_specs.py --output-dir openapi",
"gen-api-contract": "uv run --project ../../api ../../api/dev/generate_swagger_specs.py --output-dir openapi && uv run --project ../../api ../../api/dev/generate_fastopenapi_specs.py --output-dir openapi && node -e \"fs.rmSync('generated/api', { recursive: true, force: true })\" && openapi-ts -f openapi-ts.api.config.ts && vp fmt generated/api && eslint --fix generated/api",
"gen-enterprise-contract": "openapi-ts -f openapi-ts.enterprise.config.ts",
"type-check": "tsc"
},

View File

@ -1,4 +1,5 @@
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
import type { LangGeniusVersionInfo } from '@/context/app-context-types'
import type { ICurrentWorkspace } from '@/models/common'
const APP_CONTEXT_STATE_ATOM_KIND = Symbol('app-context-state-atom-kind')
@ -22,7 +23,7 @@ export type AppContextStateMockState = {
isLoadingCurrentWorkspace?: boolean
isLoadingWorkspacePermissionKeys?: boolean
workspacePermissionKeys?: string[]
langGeniusVersionInfo?: Partial<LangGeniusVersionResponse>
langGeniusVersionInfo?: Partial<LangGeniusVersionInfo>
refreshUserProfile?: () => void
refreshCurrentWorkspace?: () => void
mutateUserProfile?: () => void
@ -85,8 +86,12 @@ const defaultLangGeniusVersionInfo = {
version: '',
release_date: '',
release_notes: '',
features: {
can_replace_logo: false,
model_load_balancing_enabled: false,
},
can_auto_update: false,
} satisfies LangGeniusVersionResponse
} satisfies LangGeniusVersionInfo
let appContextStateMockRegistry: AppContextStateMockRegistry | undefined
@ -110,7 +115,7 @@ const getCurrentWorkspace = (state: AppContextStateMockState): ICurrentWorkspace
...state.currentWorkspace,
})
const getLangGeniusVersionInfo = (state: AppContextStateMockState): LangGeniusVersionResponse => ({
const getLangGeniusVersionInfo = (state: AppContextStateMockState): LangGeniusVersionInfo => ({
...defaultLangGeniusVersionInfo,
...state.langGeniusVersionInfo,
})

View File

@ -2,8 +2,9 @@ import type { GetAccountProfileResponse } from '@dify/contracts/api/console/acco
import type { Mock } from 'vitest'
import type { AppContextStateMockState } from '@/__tests__/utils/mock-app-context-state'
import type { UsagePlanInfo } from '@/app/components/billing/type'
import type { LangGeniusVersionInfo } from '@/context/app-context-types'
import type { ProviderContextState } from '@/context/provider-context'
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
import type { ICurrentWorkspace } from '@/models/common'
import { render, screen } from '@testing-library/react'
import { Plan } from '@/app/components/billing/type'
import { mailToSupport } from '@/app/components/header/utils/util'
@ -96,13 +97,17 @@ const buildAppContext = (overrides: Partial<AppContextStateMockState> = {}): App
trial_credits_used: 0,
next_credit_reset_date: 0,
}
const langGeniusVersionInfo: LangGeniusVersionResponse = {
const langGeniusVersionInfo: LangGeniusVersionInfo = {
current_env: '',
current_version: '1.0.0',
latest_version: '',
release_date: '',
release_notes: '',
version: '',
features: {
can_replace_logo: false,
model_load_balancing_enabled: false,
},
can_auto_update: false,
}
const base: AppContextStateMockState = {

View File

@ -1,4 +1,4 @@
import type { LangGeniusVersionResponse } from '@/models/common'
import type { LangGeniusVersionInfo } from '@/context/app-context-types'
import { fireEvent, screen } from '@testing-library/react'
import { renderWithSystemFeatures } from '@/__tests__/utils/mock-system-features'
import AccountAbout from '../index'
@ -13,12 +13,16 @@ vi.mock('@/config', async (importOriginal) => {
})
describe('AccountAbout', () => {
const mockVersionInfo: LangGeniusVersionResponse = {
const mockVersionInfo: LangGeniusVersionInfo = {
current_version: '0.6.0',
latest_version: '0.6.0',
release_notes: 'https://github.com/langgenius/dify/releases/tag/0.6.0',
version: '0.6.0',
release_date: '2024-01-01',
features: {
can_replace_logo: false,
model_load_balancing_enabled: false,
},
can_auto_update: false,
current_env: 'production',
}

View File

@ -1,5 +1,5 @@
'use client'
import type { LangGeniusVersionResponse } from '@/models/common'
import type { LangGeniusVersionInfo } from '@/context/app-context-types'
import { Button } from '@langgenius/dify-ui/button'
import { Dialog, DialogContent } from '@langgenius/dify-ui/dialog'
import { RiCloseLine } from '@remixicon/react'
@ -13,7 +13,7 @@ import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import Link from '@/next/link'
type IAccountSettingProps = {
langGeniusVersionInfo: LangGeniusVersionResponse
langGeniusVersionInfo: LangGeniusVersionInfo
onCancel: () => void
}

View File

@ -1,6 +1,6 @@
// Import mocks for assertions
import type { AppContextStateMockState } from '@/__tests__/utils/mock-app-context-state'
import type { LangGeniusVersionResponse } from '@/models/common'
import type { LangGeniusVersionInfo } from '@/context/app-context-types'
import { toast } from '@langgenius/dify-ui/toast'
import { waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
@ -10,18 +10,22 @@ import { useInvalidateReferenceSettings, useMutationPluginPermissionSettings, us
import { PermissionType, PluginCategoryEnum } from '../../types'
import useReferenceSetting, { useCanInstallPluginFromMarketplace } from '../use-reference-setting'
const defaultLangGeniusVersionInfo: LangGeniusVersionResponse = {
const defaultLangGeniusVersionInfo: LangGeniusVersionInfo = {
current_env: '',
current_version: '1.0.0',
latest_version: '',
release_date: '',
release_notes: '',
version: '',
features: {
can_replace_logo: false,
model_load_balancing_enabled: false,
},
can_auto_update: false,
}
type MockAppContextState = Omit<AppContextStateMockState, 'langGeniusVersionInfo'> & {
langGeniusVersionInfo?: Partial<LangGeniusVersionResponse>
langGeniusVersionInfo?: Partial<LangGeniusVersionInfo>
}
let mockAppContextState: AppContextStateMockState = {}

View File

@ -85,11 +85,19 @@ const mockLangGeniusVersionState = vi.hoisted(() => ({
version: '1.0.1',
release_date: '',
release_notes: '',
features: {
can_replace_logo: false,
model_load_balancing_enabled: false,
},
can_auto_update: false,
} as {
version: string
release_date: string
release_notes: string
features: {
can_replace_logo: boolean
model_load_balancing_enabled: boolean
}
can_auto_update: boolean
} | undefined,
}))
@ -142,6 +150,22 @@ vi.mock('@/service/client', () => ({
},
},
},
version: {
get: {
queryOptions: (options: {
enabled?: boolean
input?: {
query: {
current_version: string
}
}
}) => ({
queryKey: ['version', options.input?.query.current_version],
queryFn: async () => mockLangGeniusVersionState.data,
...options,
}),
},
},
},
}))
@ -311,6 +335,10 @@ describe('Console bootstrap', () => {
version: '1.0.1',
release_date: '',
release_notes: '',
features: {
can_replace_logo: false,
model_load_balancing_enabled: false,
},
can_auto_update: false,
}
mockGetRequest.mockImplementation((url: string) => {

View File

@ -1,12 +1,17 @@
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
import type { LangGeniusVersionInfo } from './app-context-types'
import type { ICurrentWorkspace } from '@/models/common'
export const initialLangGeniusVersionInfo: LangGeniusVersionResponse = {
export const initialLangGeniusVersionInfo: LangGeniusVersionInfo = {
current_env: '',
current_version: '',
latest_version: '',
release_date: '',
release_notes: '',
version: '',
features: {
can_replace_logo: false,
model_load_balancing_enabled: false,
},
can_auto_update: false,
}

View File

@ -1,5 +1,7 @@
import type { GetVersionResponse } from '@dify/contracts/api/console/version/types.gen'
import type { PostWorkspacesCurrentResponse } from '@dify/contracts/api/console/workspaces/types.gen'
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
import type { LangGeniusVersionInfo } from './app-context-types'
import type { ICurrentWorkspace } from '@/models/common'
import { initialLangGeniusVersionInfo, initialWorkspaceInfo } from './app-context-defaults'
const workspaceRoles = new Set<ICurrentWorkspace['role']>(['owner', 'admin', 'editor', 'dataset_operator', 'normal'])
@ -64,8 +66,8 @@ export function getLangGeniusVersionInfo({
versionData,
}: {
meta: ProfileMeta
versionData?: Omit<LangGeniusVersionResponse, 'current_version' | 'latest_version' | 'current_env'>
}): LangGeniusVersionResponse {
versionData?: GetVersionResponse
}): LangGeniusVersionInfo {
if (!meta.currentVersion || !versionData)
return initialLangGeniusVersionInfo

View File

@ -6,7 +6,6 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { workspacePermissionKeysQueryOptions } from '@/service/access-control/use-permission-keys'
import { consoleQuery } from '@/service/client'
import { langGeniusVersionQueryOptions } from '@/service/lang-genius-version'
import { atomWithResolvedSuspenseQuery } from '@/utils/query-atoms'
import {
initialLangGeniusVersionInfo,
@ -108,7 +107,14 @@ const versionQueryAtom = atomWithQuery((get) => {
const systemFeaturesQuery = get(systemFeaturesQueryAtom)
const enabled = Boolean(meta.currentVersion && !systemFeaturesQuery.data.branding.enabled)
return langGeniusVersionQueryOptions(meta.currentVersion, enabled)
return consoleQuery.version.get.queryOptions({
input: {
query: {
current_version: meta.currentVersion ?? '',
},
},
enabled,
})
})
export const langGeniusVersionInfoAtom = atom((get) => {

View File

@ -0,0 +1,7 @@
import type { GetVersionResponse } from '@dify/contracts/api/console/version/types.gen'
export type LangGeniusVersionInfo = GetVersionResponse & {
current_version: string
latest_version: string
current_env: string
}

View File

@ -16,16 +16,6 @@ export type InitValidateStatusResponse = {
status: 'finished' | 'not_started'
}
export type LangGeniusVersionResponse = {
current_version: string
latest_version: string
version: string
release_date: string
release_notes: string
can_auto_update: boolean
current_env: string
}
export type Member = Pick<GetAccountProfileResponse, 'id' | 'name' | 'email' | 'avatar_url'> & {
avatar: string
last_login_at?: string

View File

@ -1,13 +0,0 @@
import type { LangGeniusVersionResponse } from '@/models/common'
import { queryOptions } from '@tanstack/react-query'
// eslint-disable-next-line no-restricted-imports
import { get } from './base'
import { commonQueryKeys } from './use-common'
export const langGeniusVersionQueryOptions = (currentVersion?: string | null, enabled?: boolean) => {
return queryOptions<LangGeniusVersionResponse>({
queryKey: commonQueryKeys.langGeniusVersion(currentVersion || undefined),
queryFn: () => get<LangGeniusVersionResponse>('/version', { params: { current_version: currentVersion } }),
enabled: !!currentVersion && (enabled ?? true),
})
}