This commit is contained in:
Stephen Zhou
2026-02-06 13:43:45 +08:00
parent 5b22d5026b
commit 97ecde5389
11 changed files with 144 additions and 206 deletions

View File

@@ -2,6 +2,7 @@
import type { FC } from 'react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { env } from '@/env'
import ParamItem from '.'
type Props = {
@@ -12,7 +13,7 @@ type Props = {
}
const maxTopK = (() => {
const configValue = Number.parseInt(globalThis.document?.body?.getAttribute('data-public-top-k-max-value') || '', 10)
const configValue = Number.parseInt(env.NEXT_PUBLIC_TOP_K_MAX_VALUE || '', 10)
if (configValue && !isNaN(configValue))
return configValue
return 10

View File

@@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import { InputNumber } from '@/app/components/base/input-number'
import Tooltip from '@/app/components/base/tooltip'
import { env } from '@/env'
const TextLabel: FC<PropsWithChildren> = (props) => {
return <label className="text-xs font-semibold leading-none text-text-secondary">{props.children}</label>
@@ -46,7 +47,7 @@ export const DelimiterInput: FC<InputProps & { tooltip?: string }> = (props) =>
}
export const MaxLengthInput: FC<InputNumberProps> = (props) => {
const maxValue = Number.parseInt(globalThis.document?.body?.getAttribute('data-public-indexing-max-segmentation-tokens-length') || '4000', 10)
const maxValue = Number.parseInt(env.NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH || '4000', 10)
const { t } = useTranslation()
return (

View File

@@ -1,5 +1,6 @@
import type { ParentMode, PreProcessingRule, ProcessRule, Rules, SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets'
import { useCallback, useRef, useState } from 'react'
import { env } from '@/env'
import { ChunkingMode, ProcessMode } from '@/models/datasets'
import escape from './escape'
import unescape from './unescape'
@@ -9,7 +10,7 @@ export const DEFAULT_SEGMENT_IDENTIFIER = '\\n\\n'
export const DEFAULT_MAXIMUM_CHUNK_LENGTH = 1024
export const DEFAULT_OVERLAP = 50
export const MAXIMUM_CHUNK_TOKEN_LENGTH = Number.parseInt(
globalThis.document?.body?.getAttribute('data-public-indexing-max-segmentation-tokens-length') || '4000',
env.NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH || '4000',
10,
)

View File

@@ -28,6 +28,7 @@ import { useGlobalPublicStore } from '@/context/global-public-context'
import { useDocLink } from '@/context/i18n'
import { useModalContext } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
import { env } from '@/env'
import { useLogout } from '@/service/use-common'
import { cn } from '@/utils/classnames'
import AccountAbout from '../account-about'
@@ -178,7 +179,7 @@ export default function AppSelector() {
</Link>
</MenuItem>
{
document?.body?.getAttribute('data-public-site-about') !== 'hide' && (
env.NEXT_PUBLIC_SITE_ABOUT !== 'hide' && (
<MenuItem>
<div
className={cn(itemClassName, 'justify-between', 'data-[active]:bg-state-base-hover')}

View File

@@ -4,15 +4,16 @@ import * as Sentry from '@sentry/react'
import { useEffect } from 'react'
import { IS_DEV } from '@/config'
import { env } from '@/env'
const SentryInitializer = ({
children,
}: { children: React.ReactElement }) => {
useEffect(() => {
const SENTRY_DSN = document?.body?.getAttribute('data-public-sentry-dsn')
if (!IS_DEV && SENTRY_DSN) {
const sentryDsn = env.NEXT_PUBLIC_SENTRY_DSN
if (!IS_DEV && sentryDsn) {
Sentry.init({
dsn: SENTRY_DSN,
dsn: sentryDsn,
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration(),

View File

@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'
import { InputNumber } from '@/app/components/base/input-number'
import Switch from '@/app/components/base/switch'
import Tooltip from '@/app/components/base/tooltip'
import { env } from '@/env'
export type TopKAndScoreThresholdProps = {
topK: number
@@ -16,7 +17,7 @@ export type TopKAndScoreThresholdProps = {
}
const maxTopK = (() => {
const configValue = Number.parseInt(globalThis.document?.body?.getAttribute('data-public-top-k-max-value') || '', 10)
const configValue = Number.parseInt(env.NEXT_PUBLIC_TOP_K_MAX_VALUE || '', 10)
if (configValue && !isNaN(configValue))
return configValue
return 10

View File

@@ -5,9 +5,8 @@ import { Instrument_Serif } from 'next/font/google'
import { NuqsAdapter } from 'nuqs/adapters/next/app'
import GlobalPublicStoreProvider from '@/context/global-public-context'
import { TanstackQueryInitializer } from '@/context/query-client'
import { env } from '@/env'
import { clientEnvKeys, env, getDatasetAttrKeyFromEnvKey } from '@/env'
import { getLocaleOnServer } from '@/i18n-config/server'
import { DatasetAttr } from '@/types/feature'
import { cn } from '@/utils/classnames'
import { ToastProvider } from './components/base/toast'
import BrowserInitializer from './components/browser-initializer'
@@ -40,40 +39,7 @@ const LocaleLayout = async ({
children: React.ReactNode
}) => {
const locale = await getLocaleOnServer()
const datasetMap: Record<DatasetAttr, string | undefined> = {
[DatasetAttr.DATA_API_PREFIX]: env.NEXT_PUBLIC_API_PREFIX,
[DatasetAttr.DATA_PUBLIC_API_PREFIX]: env.NEXT_PUBLIC_PUBLIC_API_PREFIX,
[DatasetAttr.DATA_MARKETPLACE_API_PREFIX]: env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX,
[DatasetAttr.DATA_MARKETPLACE_URL_PREFIX]: env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX,
[DatasetAttr.DATA_PUBLIC_EDITION]: env.NEXT_PUBLIC_EDITION,
[DatasetAttr.DATA_PUBLIC_AMPLITUDE_API_KEY]: env.NEXT_PUBLIC_AMPLITUDE_API_KEY,
[DatasetAttr.DATA_PUBLIC_COOKIE_DOMAIN]: env.NEXT_PUBLIC_COOKIE_DOMAIN,
[DatasetAttr.DATA_PUBLIC_SUPPORT_MAIL_LOGIN]: env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN,
[DatasetAttr.DATA_PUBLIC_SENTRY_DSN]: env.NEXT_PUBLIC_SENTRY_DSN,
[DatasetAttr.DATA_PUBLIC_MAINTENANCE_NOTICE]: env.NEXT_PUBLIC_MAINTENANCE_NOTICE,
[DatasetAttr.DATA_PUBLIC_SITE_ABOUT]: env.NEXT_PUBLIC_SITE_ABOUT,
[DatasetAttr.DATA_PUBLIC_TEXT_GENERATION_TIMEOUT_MS]: env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS,
[DatasetAttr.DATA_PUBLIC_MAX_TOOLS_NUM]: env.NEXT_PUBLIC_MAX_TOOLS_NUM,
[DatasetAttr.DATA_PUBLIC_MAX_PARALLEL_LIMIT]: env.NEXT_PUBLIC_MAX_PARALLEL_LIMIT,
[DatasetAttr.DATA_PUBLIC_TOP_K_MAX_VALUE]: env.NEXT_PUBLIC_TOP_K_MAX_VALUE,
[DatasetAttr.DATA_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH]: env.NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH,
[DatasetAttr.DATA_PUBLIC_LOOP_NODE_MAX_COUNT]: env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT,
[DatasetAttr.DATA_PUBLIC_MAX_ITERATIONS_NUM]: env.NEXT_PUBLIC_MAX_ITERATIONS_NUM,
[DatasetAttr.DATA_PUBLIC_MAX_TREE_DEPTH]: env.NEXT_PUBLIC_MAX_TREE_DEPTH,
[DatasetAttr.DATA_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME]: env.NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME,
[DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_JINAREADER]: env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER,
[DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_FIRECRAWL]: env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL,
[DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_WATERCRAWL]: env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL,
[DatasetAttr.DATA_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX]: env.NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX,
[DatasetAttr.NEXT_PUBLIC_ZENDESK_WIDGET_KEY]: env.NEXT_PUBLIC_ZENDESK_WIDGET_KEY,
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT]: env.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT,
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION]: env.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION,
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL]: env.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL,
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID]: env.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID,
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN]: env.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN,
[DatasetAttr.DATA_PUBLIC_BATCH_CONCURRENCY]: env.NEXT_PUBLIC_BATCH_CONCURRENCY,
}
const datasetMap = Object.fromEntries(clientEnvKeys.map(envKey => [getDatasetAttrKeyFromEnvKey(envKey), env[envKey]]))
return (
<html lang={locale ?? 'en'} className={cn('h-full', instrumentSerif.variable)} suppressHydrationWarning>

View File

@@ -4,25 +4,19 @@ import { env } from '@/env'
import { PromptRole } from '@/models/debug'
import { PipelineInputVarType } from '@/models/pipeline'
import { AgentStrategy } from '@/types/app'
import { DatasetAttr } from '@/types/feature'
import pkg from '../package.json'
const getBooleanConfig = (
envVar: string | undefined,
dataAttrKey: DatasetAttr,
defaultValue: boolean = true,
) => {
if (envVar !== undefined && envVar !== '')
return envVar === 'true'
const attrValue = globalThis.document?.body?.getAttribute(dataAttrKey)
if (attrValue !== undefined && attrValue !== '')
return attrValue === 'true'
return defaultValue
}
const getNumberConfig = (
envVar: string | undefined,
dataAttrKey: DatasetAttr,
defaultValue: number,
) => {
if (envVar) {
@@ -30,54 +24,37 @@ const getNumberConfig = (
if (!Number.isNaN(parsed) && parsed > 0)
return parsed
}
const attrValue = globalThis.document?.body?.getAttribute(dataAttrKey)
if (attrValue) {
const parsed = Number.parseInt(attrValue)
if (!Number.isNaN(parsed) && parsed > 0)
return parsed
}
return defaultValue
}
const getStringConfig = (
envVar: string | undefined,
dataAttrKey: DatasetAttr,
defaultValue: string,
) => {
if (envVar)
return envVar
const attrValue = globalThis.document?.body?.getAttribute(dataAttrKey)
if (attrValue)
return attrValue
return defaultValue
}
export const API_PREFIX = getStringConfig(
env.NEXT_PUBLIC_API_PREFIX,
DatasetAttr.DATA_API_PREFIX,
'http://localhost:5001/console/api',
)
export const PUBLIC_API_PREFIX = getStringConfig(
env.NEXT_PUBLIC_PUBLIC_API_PREFIX,
DatasetAttr.DATA_PUBLIC_API_PREFIX,
'http://localhost:5001/api',
)
export const MARKETPLACE_API_PREFIX = getStringConfig(
env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX,
DatasetAttr.DATA_MARKETPLACE_API_PREFIX,
'http://localhost:5002/api',
)
export const MARKETPLACE_URL_PREFIX = getStringConfig(
env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX,
DatasetAttr.DATA_MARKETPLACE_URL_PREFIX,
'',
)
const EDITION = getStringConfig(
env.NEXT_PUBLIC_EDITION,
DatasetAttr.DATA_PUBLIC_EDITION,
'SELF_HOSTED',
)
@@ -86,16 +63,15 @@ export const IS_CLOUD_EDITION = EDITION === 'CLOUD'
export const AMPLITUDE_API_KEY = getStringConfig(
env.NEXT_PUBLIC_AMPLITUDE_API_KEY,
DatasetAttr.DATA_PUBLIC_AMPLITUDE_API_KEY,
'',
)
export const IS_DEV = env.NODE_ENV === 'development'
export const IS_PROD = env.NODE_ENV === 'production'
export const SUPPORT_MAIL_LOGIN = !!(
env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN
|| globalThis.document?.body?.getAttribute('data-public-support-mail-login')
export const SUPPORT_MAIL_LOGIN = getBooleanConfig(
env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN,
false,
)
export const TONE_LIST = [
@@ -163,13 +139,11 @@ export const LOCALE_COOKIE_NAME = 'locale'
const COOKIE_DOMAIN = getStringConfig(
env.NEXT_PUBLIC_COOKIE_DOMAIN,
DatasetAttr.DATA_PUBLIC_COOKIE_DOMAIN,
'',
).trim()
export const BATCH_CONCURRENCY = getNumberConfig(
env.NEXT_PUBLIC_BATCH_CONCURRENCY,
DatasetAttr.DATA_PUBLIC_BATCH_CONCURRENCY,
5, // default
)
@@ -355,58 +329,47 @@ export const JSON_SCHEMA_MAX_DEPTH = 10
export const MAX_TOOLS_NUM = getNumberConfig(
env.NEXT_PUBLIC_MAX_TOOLS_NUM,
DatasetAttr.DATA_PUBLIC_MAX_TOOLS_NUM,
10,
)
export const MAX_PARALLEL_LIMIT = getNumberConfig(
env.NEXT_PUBLIC_MAX_PARALLEL_LIMIT,
DatasetAttr.DATA_PUBLIC_MAX_PARALLEL_LIMIT,
10,
)
export const TEXT_GENERATION_TIMEOUT_MS = getNumberConfig(
env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS,
DatasetAttr.DATA_PUBLIC_TEXT_GENERATION_TIMEOUT_MS,
60000,
)
export const LOOP_NODE_MAX_COUNT = getNumberConfig(
env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT,
DatasetAttr.DATA_PUBLIC_LOOP_NODE_MAX_COUNT,
100,
)
export const MAX_ITERATIONS_NUM = getNumberConfig(
env.NEXT_PUBLIC_MAX_ITERATIONS_NUM,
DatasetAttr.DATA_PUBLIC_MAX_ITERATIONS_NUM,
99,
)
export const MAX_TREE_DEPTH = getNumberConfig(
env.NEXT_PUBLIC_MAX_TREE_DEPTH,
DatasetAttr.DATA_PUBLIC_MAX_TREE_DEPTH,
50,
)
export const ALLOW_UNSAFE_DATA_SCHEME = getBooleanConfig(
env.NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME,
DatasetAttr.DATA_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME,
false,
)
export const ENABLE_WEBSITE_JINAREADER = getBooleanConfig(
env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER,
DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_JINAREADER,
true,
)
export const ENABLE_WEBSITE_FIRECRAWL = getBooleanConfig(
env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL,
DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_FIRECRAWL,
true,
)
export const ENABLE_WEBSITE_WATERCRAWL = getBooleanConfig(
env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL,
DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_WATERCRAWL,
false,
)
export const ENABLE_SINGLE_DOLLAR_LATEX = getBooleanConfig(
env.NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX,
DatasetAttr.DATA_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX,
false,
)
@@ -416,39 +379,33 @@ export const validPassword = /^(?=.*[a-z])(?=.*\d)\S{8,}$/i
export const ZENDESK_WIDGET_KEY = getStringConfig(
env.NEXT_PUBLIC_ZENDESK_WIDGET_KEY,
DatasetAttr.NEXT_PUBLIC_ZENDESK_WIDGET_KEY,
'',
)
export const ZENDESK_FIELD_IDS = {
ENVIRONMENT: getStringConfig(
env.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT,
DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT,
'',
),
VERSION: getStringConfig(
env.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION,
DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION,
'',
),
EMAIL: getStringConfig(
env.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL,
DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL,
'',
),
WORKSPACE_ID: getStringConfig(
env.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID,
DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID,
'',
),
PLAN: getStringConfig(
env.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN,
DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN,
'',
),
}
export const APP_VERSION = pkg.version
export const IS_MARKETPLACE = globalThis.document?.body?.getAttribute('data-is-marketplace') === 'true'
export const IS_MARKETPLACE = env.NEXT_PUBLIC_IS_MARKETPLACE === 'true'
export const RAG_PIPELINE_PREVIEW_CHUNK_NUM = 20

View File

@@ -10,6 +10,7 @@ import { setUserId, setUserProperties } from '@/app/components/base/amplitude'
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
import { ZENDESK_FIELD_IDS } from '@/config'
import { env } from '@/env'
import {
useCurrentWorkspace,
useLangGeniusVersion,
@@ -204,7 +205,7 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
}}
>
<div className="flex h-full flex-col overflow-y-auto">
{globalThis.document?.body?.getAttribute('data-public-maintenance-notice') && <MaintenanceNotice />}
{env.NEXT_PUBLIC_MAINTENANCE_NOTICE && <MaintenanceNotice />}
<div className="relative flex grow flex-col overflow-y-auto overflow-x-hidden bg-background-body">
{children}
</div>

View File

@@ -1,7 +1,88 @@
import { createEnv } from '@t3-oss/env-nextjs'
import { kebabCase, replace } from 'string-ts'
import { z } from 'zod'
const optionalString = z.string().optional()
const CLIENT_ENV_PREFIX = 'NEXT_PUBLIC_' as const
type ClientSchema = Record<`${typeof CLIENT_ENV_PREFIX}${string}`, z.ZodType>
const clientSchema = {
NEXT_PUBLIC_ALLOW_EMBED: optionalString,
NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME: optionalString,
NEXT_PUBLIC_AMPLITUDE_API_KEY: optionalString,
NEXT_PUBLIC_API_PREFIX: optionalString,
NEXT_PUBLIC_BASE_PATH: optionalString,
NEXT_PUBLIC_BATCH_CONCURRENCY: optionalString,
NEXT_PUBLIC_COOKIE_DOMAIN: optionalString,
NEXT_PUBLIC_CSP_WHITELIST: optionalString,
NEXT_PUBLIC_DEPLOY_ENV: optionalString,
NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON: optionalString,
NEXT_PUBLIC_EDITION: optionalString,
NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX: optionalString,
NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL: optionalString,
NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER: optionalString,
NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL: optionalString,
NEXT_PUBLIC_GITHUB_ACCESS_TOKEN: optionalString,
NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: optionalString,
NEXT_PUBLIC_IS_MARKETPLACE: optionalString,
NEXT_PUBLIC_LOOP_NODE_MAX_COUNT: optionalString,
NEXT_PUBLIC_MAINTENANCE_NOTICE: optionalString,
NEXT_PUBLIC_MARKETPLACE_API_PREFIX: optionalString,
NEXT_PUBLIC_MARKETPLACE_URL_PREFIX: optionalString,
NEXT_PUBLIC_MAX_ITERATIONS_NUM: optionalString,
NEXT_PUBLIC_MAX_PARALLEL_LIMIT: optionalString,
NEXT_PUBLIC_MAX_TOOLS_NUM: optionalString,
NEXT_PUBLIC_MAX_TREE_DEPTH: optionalString,
NEXT_PUBLIC_PUBLIC_API_PREFIX: optionalString,
NEXT_PUBLIC_SENTRY_DSN: optionalString,
NEXT_PUBLIC_SITE_ABOUT: optionalString,
NEXT_PUBLIC_SUPPORT_MAIL_LOGIN: optionalString,
NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS: optionalString,
NEXT_PUBLIC_TOP_K_MAX_VALUE: optionalString,
NEXT_PUBLIC_UPLOAD_IMAGE_AS_ICON: optionalString,
NEXT_PUBLIC_WEB_PREFIX: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID: optionalString,
NEXT_PUBLIC_ZENDESK_WIDGET_KEY: optionalString,
} satisfies ClientSchema
export type ClientEnvKey = keyof typeof clientSchema
type SnakeToKebabCase<S extends string> = S extends `${infer Head}_${infer Tail}`
? `${Lowercase<Head>}-${SnakeToKebabCase<Tail>}`
: Lowercase<S>
type DatasetAttrKeyFromEnvKey<K extends ClientEnvKey> = K extends `${typeof CLIENT_ENV_PREFIX}${infer Suffix}`
? `data-${SnakeToKebabCase<Suffix>}`
: never
export type ClientDatasetAttrKey = DatasetAttrKeyFromEnvKey<ClientEnvKey>
export const clientEnvKeys = Object.keys(clientSchema) as ReadonlyArray<ClientEnvKey>
const getClientEnvSuffix = (key: ClientEnvKey) => kebabCase(replace(key, CLIENT_ENV_PREFIX, ''))
export const getDatasetAttrKeyFromEnvKey = <K extends ClientEnvKey>(key: K) => {
const suffix = getClientEnvSuffix(key)
return `data-${suffix}` as const
}
const getRuntimeEnvFromBody = <K extends ClientEnvKey>(key: K) => {
if (typeof window === 'undefined')
return undefined
const body = globalThis.document?.body
if (!body)
return undefined
const value = body.getAttribute(getDatasetAttrKeyFromEnvKey(key))
if (value !== null && value !== '')
return value
return undefined
}
export const env = createEnv({
server: {
@@ -14,88 +95,49 @@ export const env = createEnv({
shared: {
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
},
client: {
NEXT_PUBLIC_ALLOW_EMBED: optionalString,
NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME: optionalString,
NEXT_PUBLIC_AMPLITUDE_API_KEY: optionalString,
NEXT_PUBLIC_API_PREFIX: optionalString,
NEXT_PUBLIC_BASE_PATH: optionalString,
NEXT_PUBLIC_BATCH_CONCURRENCY: optionalString,
NEXT_PUBLIC_COOKIE_DOMAIN: optionalString,
NEXT_PUBLIC_CSP_WHITELIST: optionalString,
NEXT_PUBLIC_DEPLOY_ENV: optionalString,
NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON: optionalString,
NEXT_PUBLIC_EDITION: optionalString,
NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX: optionalString,
NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL: optionalString,
NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER: optionalString,
NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL: optionalString,
NEXT_PUBLIC_GITHUB_ACCESS_TOKEN: optionalString,
NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: optionalString,
NEXT_PUBLIC_LOOP_NODE_MAX_COUNT: optionalString,
NEXT_PUBLIC_MAINTENANCE_NOTICE: optionalString,
NEXT_PUBLIC_MARKETPLACE_API_PREFIX: optionalString,
NEXT_PUBLIC_MARKETPLACE_URL_PREFIX: optionalString,
NEXT_PUBLIC_MAX_ITERATIONS_NUM: optionalString,
NEXT_PUBLIC_MAX_PARALLEL_LIMIT: optionalString,
NEXT_PUBLIC_MAX_TOOLS_NUM: optionalString,
NEXT_PUBLIC_MAX_TREE_DEPTH: optionalString,
NEXT_PUBLIC_PUBLIC_API_PREFIX: optionalString,
NEXT_PUBLIC_SENTRY_DSN: optionalString,
NEXT_PUBLIC_SITE_ABOUT: optionalString,
NEXT_PUBLIC_SUPPORT_MAIL_LOGIN: optionalString,
NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS: optionalString,
NEXT_PUBLIC_TOP_K_MAX_VALUE: optionalString,
NEXT_PUBLIC_UPLOAD_IMAGE_AS_ICON: optionalString,
NEXT_PUBLIC_WEB_PREFIX: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION: optionalString,
NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID: optionalString,
NEXT_PUBLIC_ZENDESK_WIDGET_KEY: optionalString,
},
client: clientSchema,
experimental__runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
NEXT_PUBLIC_ALLOW_EMBED: process.env.NEXT_PUBLIC_ALLOW_EMBED,
NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME: process.env.NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME,
NEXT_PUBLIC_AMPLITUDE_API_KEY: process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY,
NEXT_PUBLIC_API_PREFIX: process.env.NEXT_PUBLIC_API_PREFIX,
NEXT_PUBLIC_BASE_PATH: process.env.NEXT_PUBLIC_BASE_PATH,
NEXT_PUBLIC_BATCH_CONCURRENCY: process.env.NEXT_PUBLIC_BATCH_CONCURRENCY,
NEXT_PUBLIC_COOKIE_DOMAIN: process.env.NEXT_PUBLIC_COOKIE_DOMAIN,
NEXT_PUBLIC_CSP_WHITELIST: process.env.NEXT_PUBLIC_CSP_WHITELIST,
NEXT_PUBLIC_DEPLOY_ENV: process.env.NEXT_PUBLIC_DEPLOY_ENV,
NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON: process.env.NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON,
NEXT_PUBLIC_EDITION: process.env.NEXT_PUBLIC_EDITION,
NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX: process.env.NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX,
NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL,
NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER,
NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL,
NEXT_PUBLIC_GITHUB_ACCESS_TOKEN: process.env.NEXT_PUBLIC_GITHUB_ACCESS_TOKEN,
NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: process.env.NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH,
NEXT_PUBLIC_LOOP_NODE_MAX_COUNT: process.env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT,
NEXT_PUBLIC_MAINTENANCE_NOTICE: process.env.NEXT_PUBLIC_MAINTENANCE_NOTICE,
NEXT_PUBLIC_MARKETPLACE_API_PREFIX: process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX,
NEXT_PUBLIC_MARKETPLACE_URL_PREFIX: process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX,
NEXT_PUBLIC_MAX_ITERATIONS_NUM: process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM,
NEXT_PUBLIC_MAX_PARALLEL_LIMIT: process.env.NEXT_PUBLIC_MAX_PARALLEL_LIMIT,
NEXT_PUBLIC_MAX_TOOLS_NUM: process.env.NEXT_PUBLIC_MAX_TOOLS_NUM,
NEXT_PUBLIC_MAX_TREE_DEPTH: process.env.NEXT_PUBLIC_MAX_TREE_DEPTH,
NEXT_PUBLIC_PUBLIC_API_PREFIX: process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX,
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
NEXT_PUBLIC_SITE_ABOUT: process.env.NEXT_PUBLIC_SITE_ABOUT,
NEXT_PUBLIC_SUPPORT_MAIL_LOGIN: process.env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN,
NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS: process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS,
NEXT_PUBLIC_TOP_K_MAX_VALUE: process.env.NEXT_PUBLIC_TOP_K_MAX_VALUE,
NEXT_PUBLIC_UPLOAD_IMAGE_AS_ICON: process.env.NEXT_PUBLIC_UPLOAD_IMAGE_AS_ICON,
NEXT_PUBLIC_WEB_PREFIX: process.env.NEXT_PUBLIC_WEB_PREFIX,
NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL,
NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT,
NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN,
NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION,
NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID,
NEXT_PUBLIC_ZENDESK_WIDGET_KEY: process.env.NEXT_PUBLIC_ZENDESK_WIDGET_KEY,
NEXT_PUBLIC_ALLOW_EMBED: process.env.NEXT_PUBLIC_ALLOW_EMBED || getRuntimeEnvFromBody('NEXT_PUBLIC_ALLOW_EMBED'),
NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME: process.env.NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME || getRuntimeEnvFromBody('NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME'),
NEXT_PUBLIC_AMPLITUDE_API_KEY: process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY || getRuntimeEnvFromBody('NEXT_PUBLIC_AMPLITUDE_API_KEY'),
NEXT_PUBLIC_API_PREFIX: process.env.NEXT_PUBLIC_API_PREFIX || getRuntimeEnvFromBody('NEXT_PUBLIC_API_PREFIX'),
NEXT_PUBLIC_BASE_PATH: process.env.NEXT_PUBLIC_BASE_PATH || getRuntimeEnvFromBody('NEXT_PUBLIC_BASE_PATH'),
NEXT_PUBLIC_BATCH_CONCURRENCY: process.env.NEXT_PUBLIC_BATCH_CONCURRENCY || getRuntimeEnvFromBody('NEXT_PUBLIC_BATCH_CONCURRENCY'),
NEXT_PUBLIC_COOKIE_DOMAIN: process.env.NEXT_PUBLIC_COOKIE_DOMAIN || getRuntimeEnvFromBody('NEXT_PUBLIC_COOKIE_DOMAIN'),
NEXT_PUBLIC_CSP_WHITELIST: process.env.NEXT_PUBLIC_CSP_WHITELIST || getRuntimeEnvFromBody('NEXT_PUBLIC_CSP_WHITELIST'),
NEXT_PUBLIC_DEPLOY_ENV: process.env.NEXT_PUBLIC_DEPLOY_ENV || getRuntimeEnvFromBody('NEXT_PUBLIC_DEPLOY_ENV'),
NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON: process.env.NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON || getRuntimeEnvFromBody('NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON'),
NEXT_PUBLIC_EDITION: process.env.NEXT_PUBLIC_EDITION || getRuntimeEnvFromBody('NEXT_PUBLIC_EDITION'),
NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX: process.env.NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX || getRuntimeEnvFromBody('NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX'),
NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL || getRuntimeEnvFromBody('NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL'),
NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER || getRuntimeEnvFromBody('NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER'),
NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL || getRuntimeEnvFromBody('NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL'),
NEXT_PUBLIC_GITHUB_ACCESS_TOKEN: process.env.NEXT_PUBLIC_GITHUB_ACCESS_TOKEN || getRuntimeEnvFromBody('NEXT_PUBLIC_GITHUB_ACCESS_TOKEN'),
NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: process.env.NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH || getRuntimeEnvFromBody('NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH'),
NEXT_PUBLIC_IS_MARKETPLACE: process.env.NEXT_PUBLIC_IS_MARKETPLACE || getRuntimeEnvFromBody('NEXT_PUBLIC_IS_MARKETPLACE'),
NEXT_PUBLIC_LOOP_NODE_MAX_COUNT: process.env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT || getRuntimeEnvFromBody('NEXT_PUBLIC_LOOP_NODE_MAX_COUNT'),
NEXT_PUBLIC_MAINTENANCE_NOTICE: process.env.NEXT_PUBLIC_MAINTENANCE_NOTICE || getRuntimeEnvFromBody('NEXT_PUBLIC_MAINTENANCE_NOTICE'),
NEXT_PUBLIC_MARKETPLACE_API_PREFIX: process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX || getRuntimeEnvFromBody('NEXT_PUBLIC_MARKETPLACE_API_PREFIX'),
NEXT_PUBLIC_MARKETPLACE_URL_PREFIX: process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX || getRuntimeEnvFromBody('NEXT_PUBLIC_MARKETPLACE_URL_PREFIX'),
NEXT_PUBLIC_MAX_ITERATIONS_NUM: process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM || getRuntimeEnvFromBody('NEXT_PUBLIC_MAX_ITERATIONS_NUM'),
NEXT_PUBLIC_MAX_PARALLEL_LIMIT: process.env.NEXT_PUBLIC_MAX_PARALLEL_LIMIT || getRuntimeEnvFromBody('NEXT_PUBLIC_MAX_PARALLEL_LIMIT'),
NEXT_PUBLIC_MAX_TOOLS_NUM: process.env.NEXT_PUBLIC_MAX_TOOLS_NUM || getRuntimeEnvFromBody('NEXT_PUBLIC_MAX_TOOLS_NUM'),
NEXT_PUBLIC_MAX_TREE_DEPTH: process.env.NEXT_PUBLIC_MAX_TREE_DEPTH || getRuntimeEnvFromBody('NEXT_PUBLIC_MAX_TREE_DEPTH'),
NEXT_PUBLIC_PUBLIC_API_PREFIX: process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX || getRuntimeEnvFromBody('NEXT_PUBLIC_PUBLIC_API_PREFIX'),
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN || getRuntimeEnvFromBody('NEXT_PUBLIC_SENTRY_DSN'),
NEXT_PUBLIC_SITE_ABOUT: process.env.NEXT_PUBLIC_SITE_ABOUT || getRuntimeEnvFromBody('NEXT_PUBLIC_SITE_ABOUT'),
NEXT_PUBLIC_SUPPORT_MAIL_LOGIN: process.env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN || getRuntimeEnvFromBody('NEXT_PUBLIC_SUPPORT_MAIL_LOGIN'),
NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS: process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS || getRuntimeEnvFromBody('NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS'),
NEXT_PUBLIC_TOP_K_MAX_VALUE: process.env.NEXT_PUBLIC_TOP_K_MAX_VALUE || getRuntimeEnvFromBody('NEXT_PUBLIC_TOP_K_MAX_VALUE'),
NEXT_PUBLIC_UPLOAD_IMAGE_AS_ICON: process.env.NEXT_PUBLIC_UPLOAD_IMAGE_AS_ICON || getRuntimeEnvFromBody('NEXT_PUBLIC_UPLOAD_IMAGE_AS_ICON'),
NEXT_PUBLIC_WEB_PREFIX: process.env.NEXT_PUBLIC_WEB_PREFIX || getRuntimeEnvFromBody('NEXT_PUBLIC_WEB_PREFIX'),
NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL || getRuntimeEnvFromBody('NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL'),
NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT || getRuntimeEnvFromBody('NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT'),
NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN || getRuntimeEnvFromBody('NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN'),
NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION || getRuntimeEnvFromBody('NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION'),
NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID || getRuntimeEnvFromBody('NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID'),
NEXT_PUBLIC_ZENDESK_WIDGET_KEY: process.env.NEXT_PUBLIC_ZENDESK_WIDGET_KEY || getRuntimeEnvFromBody('NEXT_PUBLIC_ZENDESK_WIDGET_KEY'),
},
emptyStringAsUndefined: true,
})

View File

@@ -107,37 +107,3 @@ export const defaultSystemFeatures: SystemFeatures = {
enable_trial_app: false,
enable_explore_banner: false,
}
export enum DatasetAttr {
DATA_API_PREFIX = 'data-api-prefix',
DATA_PUBLIC_API_PREFIX = 'data-public-api-prefix',
DATA_MARKETPLACE_API_PREFIX = 'data-marketplace-api-prefix',
DATA_MARKETPLACE_URL_PREFIX = 'data-marketplace-url-prefix',
DATA_PUBLIC_EDITION = 'data-public-edition',
DATA_PUBLIC_AMPLITUDE_API_KEY = 'data-public-amplitude-api-key',
DATA_PUBLIC_COOKIE_DOMAIN = 'data-public-cookie-domain',
DATA_PUBLIC_SUPPORT_MAIL_LOGIN = 'data-public-support-mail-login',
DATA_PUBLIC_SENTRY_DSN = 'data-public-sentry-dsn',
DATA_PUBLIC_MAINTENANCE_NOTICE = 'data-public-maintenance-notice',
DATA_PUBLIC_SITE_ABOUT = 'data-public-site-about',
DATA_PUBLIC_TEXT_GENERATION_TIMEOUT_MS = 'data-public-text-generation-timeout-ms',
DATA_PUBLIC_MAX_TOOLS_NUM = 'data-public-max-tools-num',
DATA_PUBLIC_MAX_PARALLEL_LIMIT = 'data-public-max-parallel-limit',
DATA_PUBLIC_TOP_K_MAX_VALUE = 'data-public-top-k-max-value',
DATA_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH = 'data-public-indexing-max-segmentation-tokens-length',
DATA_PUBLIC_LOOP_NODE_MAX_COUNT = 'data-public-loop-node-max-count',
DATA_PUBLIC_MAX_ITERATIONS_NUM = 'data-public-max-iterations-num',
DATA_PUBLIC_MAX_TREE_DEPTH = 'data-public-max-tree-depth',
DATA_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME = 'data-public-allow-unsafe-data-scheme',
DATA_PUBLIC_ENABLE_WEBSITE_JINAREADER = 'data-public-enable-website-jinareader',
DATA_PUBLIC_ENABLE_WEBSITE_FIRECRAWL = 'data-public-enable-website-firecrawl',
DATA_PUBLIC_ENABLE_WEBSITE_WATERCRAWL = 'data-public-enable-website-watercrawl',
DATA_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX = 'data-public-enable-single-dollar-latex',
NEXT_PUBLIC_ZENDESK_WIDGET_KEY = 'next-public-zendesk-widget-key',
NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT = 'next-public-zendesk-field-id-environment',
NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION = 'next-public-zendesk-field-id-version',
NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL = 'next-public-zendesk-field-id-email',
NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID = 'next-public-zendesk-field-id-workspace-id',
NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN = 'next-public-zendesk-field-id-plan',
DATA_PUBLIC_BATCH_CONCURRENCY = 'data-public-batch-concurrency',
}