| NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL=true | NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL=true | ||||
| NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL=true | NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL=true | ||||
| # The maximum number of tree node depth for workflow | |||||
| NEXT_PUBLIC_MAX_TREE_DEPTH=50 |
| import { useCallback } from 'react' | import { useCallback } from 'react' | ||||
| import { apiPrefix } from '@/config' | |||||
| import { API_PREFIX } from '@/config' | |||||
| import { useSelector } from '@/context/app-context' | import { useSelector } from '@/context/app-context' | ||||
| const useGetIcon = () => { | const useGetIcon = () => { | ||||
| const currentWorkspace = useSelector(s => s.currentWorkspace) | const currentWorkspace = useSelector(s => s.currentWorkspace) | ||||
| const getIconUrl = useCallback((fileName: string) => { | const getIconUrl = useCallback((fileName: string) => { | ||||
| return `${apiPrefix}/workspaces/current/plugin/icon?tenant_id=${currentWorkspace.id}&filename=${fileName}` | |||||
| return `${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${currentWorkspace.id}&filename=${fileName}` | |||||
| }, [currentWorkspace.id]) | }, [currentWorkspace.id]) | ||||
| return { | return { |
| import { sleep } from '@/utils' | import { sleep } from '@/utils' | ||||
| import { getDocsUrl } from '@/app/components/plugins/utils' | import { getDocsUrl } from '@/app/components/plugins/utils' | ||||
| import { fetchBundleInfoFromMarketPlace, fetchManifestFromMarketPlace } from '@/service/plugins' | import { fetchBundleInfoFromMarketPlace, fetchManifestFromMarketPlace } from '@/service/plugins' | ||||
| import { marketplaceApiPrefix } from '@/config' | |||||
| import { MARKETPLACE_API_PREFIX } from '@/config' | |||||
| import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config' | import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config' | ||||
| import I18n from '@/context/i18n' | import I18n from '@/context/i18n' | ||||
| import { noop } from 'lodash-es' | import { noop } from 'lodash-es' | ||||
| setManifest({ | setManifest({ | ||||
| ...plugin, | ...plugin, | ||||
| version: version.version, | version: version.version, | ||||
| icon: `${marketplaceApiPrefix}/plugins/${plugin.org}/${plugin.name}/icon`, | |||||
| icon: `${MARKETPLACE_API_PREFIX}/plugins/${plugin.org}/${plugin.name}/icon`, | |||||
| }) | }) | ||||
| showInstallFromMarketplace() | showInstallFromMarketplace() | ||||
| return | return |
| import type { Plugin } from '@/app/components/plugins/types.ts' | import type { Plugin } from '@/app/components/plugins/types.ts' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import Link from 'next/link' | import Link from 'next/link' | ||||
| import { marketplaceUrlPrefix } from '@/config' | |||||
| import { MARKETPLACE_URL_PREFIX } from '@/config' | |||||
| import { RiArrowRightUpLine, RiSearchLine } from '@remixicon/react' | import { RiArrowRightUpLine, RiSearchLine } from '@remixicon/react' | ||||
| import { noop } from 'lodash-es' | import { noop } from 'lodash-es' | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const hasFilter = !searchText | const hasFilter = !searchText | ||||
| const hasRes = list.length > 0 | const hasRes = list.length > 0 | ||||
| const urlWithSearchText = `${marketplaceUrlPrefix}/?q=${searchText}&tags=${tags.join(',')}` | |||||
| const urlWithSearchText = `${MARKETPLACE_URL_PREFIX}/?q=${searchText}&tags=${tags.join(',')}` | |||||
| const nextToStickyELemRef = useRef<HTMLDivElement>(null) | const nextToStickyELemRef = useRef<HTMLDivElement>(null) | ||||
| const { handleScroll, scrollPosition } = useStickyScroll({ | const { handleScroll, scrollPosition } = useStickyScroll({ | ||||
| return ( | return ( | ||||
| <Link | <Link | ||||
| className='system-sm-medium sticky bottom-0 z-10 flex h-8 cursor-pointer items-center rounded-b-lg border-[0.5px] border-t border-components-panel-border bg-components-panel-bg-blur px-4 py-1 text-text-accent-light-mode-only shadow-lg' | className='system-sm-medium sticky bottom-0 z-10 flex h-8 cursor-pointer items-center rounded-b-lg border-[0.5px] border-t border-components-panel-border bg-components-panel-bg-blur px-4 py-1 text-text-accent-light-mode-only shadow-lg' | ||||
| href={`${marketplaceUrlPrefix}/`} | |||||
| href={`${MARKETPLACE_URL_PREFIX}/`} | |||||
| target='_blank' | target='_blank' | ||||
| > | > | ||||
| <span>{t('plugin.findMoreInMarketplace')}</span> | <span>{t('plugin.findMoreInMarketplace')}</span> |
| export const X_OFFSET = 60 | export const X_OFFSET = 60 | ||||
| export const NODE_WIDTH_X_OFFSET = NODE_WIDTH + X_OFFSET | export const NODE_WIDTH_X_OFFSET = NODE_WIDTH + X_OFFSET | ||||
| export const Y_OFFSET = 39 | export const Y_OFFSET = 39 | ||||
| export const MAX_TREE_DEPTH = 50 | |||||
| export const START_INITIAL_POSITION = { x: 80, y: 282 } | export const START_INITIAL_POSITION = { x: 80, y: 282 } | ||||
| export const AUTO_LAYOUT_OFFSET = { | export const AUTO_LAYOUT_OFFSET = { | ||||
| x: -42, | x: -42, |
| } from '../utils' | } from '../utils' | ||||
| import { | import { | ||||
| CUSTOM_NODE, | CUSTOM_NODE, | ||||
| MAX_TREE_DEPTH, | |||||
| } from '../constants' | } from '../constants' | ||||
| import type { ToolNodeType } from '../nodes/tool/types' | import type { ToolNodeType } from '../nodes/tool/types' | ||||
| import { useIsChatMode } from './use-workflow' | import { useIsChatMode } from './use-workflow' | ||||
| import type { KnowledgeRetrievalNodeType } from '../nodes/knowledge-retrieval/types' | import type { KnowledgeRetrievalNodeType } from '../nodes/knowledge-retrieval/types' | ||||
| import type { DataSet } from '@/models/datasets' | import type { DataSet } from '@/models/datasets' | ||||
| import { fetchDatasets } from '@/service/datasets' | import { fetchDatasets } from '@/service/datasets' | ||||
| import { MAX_TREE_DEPTH } from '@/config' | |||||
| export const useChecklist = (nodes: Node[], edges: Edge[]) => { | export const useChecklist = (nodes: Node[], edges: Edge[]) => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() |
| import { Badge as Badge2, BadgeState } from '@/app/components/base/badge/index' | import { Badge as Badge2, BadgeState } from '@/app/components/base/badge/index' | ||||
| import Link from 'next/link' | import Link from 'next/link' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { marketplaceUrlPrefix } from '@/config' | |||||
| import { MARKETPLACE_URL_PREFIX } from '@/config' | |||||
| export type SwitchPluginVersionProps = { | export type SwitchPluginVersionProps = { | ||||
| uniqueIdentifier: string | uniqueIdentifier: string | ||||
| modalBottomLeft={ | modalBottomLeft={ | ||||
| <Link | <Link | ||||
| className='flex items-center justify-center gap-1' | className='flex items-center justify-center gap-1' | ||||
| href={`${marketplaceUrlPrefix}/plugins/${pluginDetail.declaration.author}/${pluginDetail.declaration.name}`} | |||||
| href={`${MARKETPLACE_URL_PREFIX}/plugins/${pluginDetail.declaration.author}/${pluginDetail.declaration.name}`} | |||||
| target='_blank' | target='_blank' | ||||
| > | > | ||||
| <span className='system-xs-regular text-xs text-text-accent'> | <span className='system-xs-regular text-xs text-text-accent'> |
| import './styles/globals.css' | import './styles/globals.css' | ||||
| import './styles/markdown.scss' | import './styles/markdown.scss' | ||||
| import GlobalPublicStoreProvider from '@/context/global-public-context' | import GlobalPublicStoreProvider from '@/context/global-public-context' | ||||
| import { DatasetAttr } from '@/types/feature' | |||||
| export const viewport: Viewport = { | export const viewport: Viewport = { | ||||
| width: 'device-width', | width: 'device-width', | ||||
| }) => { | }) => { | ||||
| const locale = await getLocaleOnServer() | const locale = await getLocaleOnServer() | ||||
| const datasetMap: Record<DatasetAttr, string | undefined> = { | |||||
| [DatasetAttr.DATA_API_PREFIX]: process.env.NEXT_PUBLIC_API_PREFIX, | |||||
| [DatasetAttr.DATA_PUBLIC_API_PREFIX]: process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX, | |||||
| [DatasetAttr.DATA_MARKETPLACE_API_PREFIX]: process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX, | |||||
| [DatasetAttr.DATA_MARKETPLACE_URL_PREFIX]: process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX, | |||||
| [DatasetAttr.DATA_PUBLIC_EDITION]: process.env.NEXT_PUBLIC_EDITION, | |||||
| [DatasetAttr.DATA_PUBLIC_SUPPORT_MAIL_LOGIN]: process.env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN, | |||||
| [DatasetAttr.DATA_PUBLIC_SENTRY_DSN]: process.env.NEXT_PUBLIC_SENTRY_DSN, | |||||
| [DatasetAttr.DATA_PUBLIC_MAINTENANCE_NOTICE]: process.env.NEXT_PUBLIC_MAINTENANCE_NOTICE, | |||||
| [DatasetAttr.DATA_PUBLIC_SITE_ABOUT]: process.env.NEXT_PUBLIC_SITE_ABOUT, | |||||
| [DatasetAttr.DATA_PUBLIC_TEXT_GENERATION_TIMEOUT_MS]: process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS, | |||||
| [DatasetAttr.DATA_PUBLIC_MAX_TOOLS_NUM]: process.env.NEXT_PUBLIC_MAX_TOOLS_NUM, | |||||
| [DatasetAttr.DATA_PUBLIC_MAX_PARALLEL_LIMIT]: process.env.NEXT_PUBLIC_MAX_PARALLEL_LIMIT, | |||||
| [DatasetAttr.DATA_PUBLIC_TOP_K_MAX_VALUE]: process.env.NEXT_PUBLIC_TOP_K_MAX_VALUE, | |||||
| [DatasetAttr.DATA_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH]: process.env.NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH, | |||||
| [DatasetAttr.DATA_PUBLIC_LOOP_NODE_MAX_COUNT]: process.env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT, | |||||
| [DatasetAttr.DATA_PUBLIC_MAX_ITERATIONS_NUM]: process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM, | |||||
| [DatasetAttr.DATA_PUBLIC_MAX_TREE_DEPTH]: process.env.NEXT_PUBLIC_MAX_TREE_DEPTH, | |||||
| [DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_JINAREADER]: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER, | |||||
| [DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_FIRECRAWL]: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL, | |||||
| [DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_WATERCRAWL]: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL, | |||||
| } | |||||
| return ( | return ( | ||||
| <html lang={locale ?? 'en'} className="h-full" suppressHydrationWarning> | <html lang={locale ?? 'en'} className="h-full" suppressHydrationWarning> | ||||
| <head> | <head> | ||||
| </head> | </head> | ||||
| <body | <body | ||||
| className="color-scheme h-full select-auto" | className="color-scheme h-full select-auto" | ||||
| data-api-prefix={process.env.NEXT_PUBLIC_API_PREFIX} | |||||
| data-pubic-api-prefix={process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX} | |||||
| data-marketplace-api-prefix={process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX} | |||||
| data-marketplace-url-prefix={process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX} | |||||
| data-public-edition={process.env.NEXT_PUBLIC_EDITION} | |||||
| data-public-support-mail-login={process.env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN} | |||||
| data-public-sentry-dsn={process.env.NEXT_PUBLIC_SENTRY_DSN} | |||||
| data-public-maintenance-notice={process.env.NEXT_PUBLIC_MAINTENANCE_NOTICE} | |||||
| data-public-site-about={process.env.NEXT_PUBLIC_SITE_ABOUT} | |||||
| data-public-text-generation-timeout-ms={process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS} | |||||
| data-public-max-tools-num={process.env.NEXT_PUBLIC_MAX_TOOLS_NUM} | |||||
| data-public-max-parallel-limit={process.env.NEXT_PUBLIC_MAX_PARALLEL_LIMIT} | |||||
| data-public-top-k-max-value={process.env.NEXT_PUBLIC_TOP_K_MAX_VALUE} | |||||
| data-public-indexing-max-segmentation-tokens-length={process.env.NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH} | |||||
| data-public-loop-node-max-count={process.env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT} | |||||
| data-public-max-iterations-num={process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM} | |||||
| data-public-enable-website-jinareader={process.env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER} | |||||
| data-public-enable-website-firecrawl={process.env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL} | |||||
| data-public-enable-website-watercrawl={process.env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL} | |||||
| {...datasetMap} | |||||
| > | > | ||||
| <BrowserInitor> | <BrowserInitor> | ||||
| <SentryInitor> | <SentryInitor> |
| import { useSearchParams } from 'next/navigation' | import { useSearchParams } from 'next/navigation' | ||||
| import style from '../page.module.css' | import style from '../page.module.css' | ||||
| import Button from '@/app/components/base/button' | import Button from '@/app/components/base/button' | ||||
| import { apiPrefix } from '@/config' | |||||
| import { API_PREFIX } from '@/config' | |||||
| import classNames from '@/utils/classnames' | import classNames from '@/utils/classnames' | ||||
| import { getPurifyHref } from '@/utils' | import { getPurifyHref } from '@/utils' | ||||
| const searchParams = useSearchParams() | const searchParams = useSearchParams() | ||||
| const getOAuthLink = (href: string) => { | const getOAuthLink = (href: string) => { | ||||
| const url = getPurifyHref(`${apiPrefix}${href}`) | |||||
| const url = getPurifyHref(`${API_PREFIX}${href}`) | |||||
| if (searchParams.has('invite_token')) | if (searchParams.has('invite_token')) | ||||
| return `${url}?${searchParams.toString()}` | return `${url}?${searchParams.toString()}` | ||||
| import { InputVarType } from '@/app/components/workflow/types' | import { InputVarType } from '@/app/components/workflow/types' | ||||
| import { AgentStrategy } from '@/types/app' | import { AgentStrategy } from '@/types/app' | ||||
| import { PromptRole } from '@/models/debug' | import { PromptRole } from '@/models/debug' | ||||
| import { DatasetAttr } from '@/types/feature' | |||||
| export let apiPrefix = '' | |||||
| export let publicApiPrefix = '' | |||||
| export let marketplaceApiPrefix = '' | |||||
| export let marketplaceUrlPrefix = '' | |||||
| // NEXT_PUBLIC_API_PREFIX=/console/api NEXT_PUBLIC_PUBLIC_API_PREFIX=/api npm run start | |||||
| if (process.env.NEXT_PUBLIC_API_PREFIX && process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX) { | |||||
| apiPrefix = process.env.NEXT_PUBLIC_API_PREFIX | |||||
| publicApiPrefix = process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX | |||||
| } | |||||
| else if ( | |||||
| globalThis.document?.body?.getAttribute('data-api-prefix') | |||||
| && globalThis.document?.body?.getAttribute('data-pubic-api-prefix') | |||||
| ) { | |||||
| // Not build can not get env from process.env.NEXT_PUBLIC_ in browser https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser | |||||
| apiPrefix = globalThis.document.body.getAttribute('data-api-prefix') as string | |||||
| publicApiPrefix = globalThis.document.body.getAttribute('data-pubic-api-prefix') as string | |||||
| } | |||||
| else { | |||||
| // const domainParts = globalThis.location?.host?.split('.'); | |||||
| // in production env, the host is dify.app . In other env, the host is [dev].dify.app | |||||
| // const env = domainParts.length === 2 ? 'ai' : domainParts?.[0]; | |||||
| apiPrefix = 'http://localhost:5001/console/api' | |||||
| publicApiPrefix = 'http://localhost:5001/api' // avoid browser private mode api cross origin | |||||
| marketplaceApiPrefix = 'http://localhost:5002/api' | |||||
| 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 | |||||
| } | } | ||||
| if (process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX && process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX) { | |||||
| marketplaceApiPrefix = process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX | |||||
| marketplaceUrlPrefix = process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX | |||||
| const getNumberConfig = (envVar: string | undefined, dataAttrKey: DatasetAttr, defaultValue: number) => { | |||||
| if (envVar) | |||||
| return Number.parseInt(envVar) | |||||
| const attrValue = globalThis.document?.body?.getAttribute(dataAttrKey) | |||||
| if (attrValue) | |||||
| return Number.parseInt(attrValue) | |||||
| return defaultValue | |||||
| } | } | ||||
| else { | |||||
| marketplaceApiPrefix = globalThis.document?.body?.getAttribute('data-marketplace-api-prefix') || '' | |||||
| marketplaceUrlPrefix = globalThis.document?.body?.getAttribute('data-marketplace-url-prefix') || '' | |||||
| 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: string = apiPrefix | |||||
| export const PUBLIC_API_PREFIX: string = publicApiPrefix | |||||
| export const MARKETPLACE_API_PREFIX: string = marketplaceApiPrefix | |||||
| export const MARKETPLACE_URL_PREFIX: string = marketplaceUrlPrefix | |||||
| export const API_PREFIX = getStringConfig(process.env.NEXT_PUBLIC_API_PREFIX, DatasetAttr.DATA_API_PREFIX, 'http://localhost:5001/console/api') | |||||
| export const PUBLIC_API_PREFIX = getStringConfig(process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX, DatasetAttr.DATA_PUBLIC_API_PREFIX, 'http://localhost:5001/api') | |||||
| export const MARKETPLACE_API_PREFIX = getStringConfig(process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX, DatasetAttr.DATA_MARKETPLACE_API_PREFIX, 'http://localhost:5002/api') | |||||
| export const MARKETPLACE_URL_PREFIX = getStringConfig(process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX, DatasetAttr.DATA_MARKETPLACE_URL_PREFIX, '') | |||||
| const EDITION = getStringConfig(process.env.NEXT_PUBLIC_EDITION, DatasetAttr.DATA_PUBLIC_EDITION, 'SELF_HOSTED') | |||||
| const EDITION = process.env.NEXT_PUBLIC_EDITION || globalThis.document?.body?.getAttribute('data-public-edition') || 'SELF_HOSTED' | |||||
| export const IS_CE_EDITION = EDITION === 'SELF_HOSTED' | export const IS_CE_EDITION = EDITION === 'SELF_HOSTED' | ||||
| export const IS_CLOUD_EDITION = EDITION === 'CLOUD' | export const IS_CLOUD_EDITION = EDITION === 'CLOUD' | ||||
| score_threshold: 0.9, | score_threshold: 0.9, | ||||
| } | } | ||||
| export let maxToolsNum = 10 | |||||
| if (process.env.NEXT_PUBLIC_MAX_TOOLS_NUM && process.env.NEXT_PUBLIC_MAX_TOOLS_NUM !== '') | |||||
| maxToolsNum = Number.parseInt(process.env.NEXT_PUBLIC_MAX_TOOLS_NUM) | |||||
| else if (globalThis.document?.body?.getAttribute('data-public-max-tools-num') && globalThis.document.body.getAttribute('data-public-max-tools-num') !== '') | |||||
| maxToolsNum = Number.parseInt(globalThis.document.body.getAttribute('data-public-max-tools-num') as string) | |||||
| export const MAX_TOOLS_NUM = maxToolsNum | |||||
| export const DEFAULT_AGENT_SETTING = { | export const DEFAULT_AGENT_SETTING = { | ||||
| enabled: false, | enabled: false, | ||||
| max_iteration: 10, | max_iteration: 10, | ||||
| export const resetReg = () => VAR_REGEX.lastIndex = 0 | export const resetReg = () => VAR_REGEX.lastIndex = 0 | ||||
| export let textGenerationTimeoutMs = 60000 | |||||
| if (process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS && process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS !== '') | |||||
| textGenerationTimeoutMs = Number.parseInt(process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS) | |||||
| else if (globalThis.document?.body?.getAttribute('data-public-text-generation-timeout-ms') && globalThis.document.body.getAttribute('data-public-text-generation-timeout-ms') !== '') | |||||
| textGenerationTimeoutMs = Number.parseInt(globalThis.document.body.getAttribute('data-public-text-generation-timeout-ms') as string) | |||||
| export const TEXT_GENERATION_TIMEOUT_MS = textGenerationTimeoutMs | |||||
| export const DISABLE_UPLOAD_IMAGE_AS_ICON = process.env.NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON === 'true' | export const DISABLE_UPLOAD_IMAGE_AS_ICON = process.env.NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON === 'true' | ||||
| export const GITHUB_ACCESS_TOKEN = process.env.NEXT_PUBLIC_GITHUB_ACCESS_TOKEN || '' | export const GITHUB_ACCESS_TOKEN = process.env.NEXT_PUBLIC_GITHUB_ACCESS_TOKEN || '' | ||||
| export const FULL_DOC_PREVIEW_LENGTH = 50 | export const FULL_DOC_PREVIEW_LENGTH = 50 | ||||
| export const JSON_SCHEMA_MAX_DEPTH = 10 | export const JSON_SCHEMA_MAX_DEPTH = 10 | ||||
| let loopNodeMaxCount = 100 | |||||
| if (process.env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT && process.env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT !== '') | |||||
| loopNodeMaxCount = Number.parseInt(process.env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT) | |||||
| else if (globalThis.document?.body?.getAttribute('data-public-loop-node-max-count') && globalThis.document.body.getAttribute('data-public-loop-node-max-count') !== '') | |||||
| loopNodeMaxCount = Number.parseInt(globalThis.document.body.getAttribute('data-public-loop-node-max-count') as string) | |||||
| export const LOOP_NODE_MAX_COUNT = loopNodeMaxCount | |||||
| let maxIterationsNum = 99 | |||||
| if (process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM && process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM !== '') | |||||
| maxIterationsNum = Number.parseInt(process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM) | |||||
| else if (globalThis.document?.body?.getAttribute('data-public-max-iterations-num') && globalThis.document.body.getAttribute('data-public-max-iterations-num') !== '') | |||||
| maxIterationsNum = Number.parseInt(globalThis.document.body.getAttribute('data-public-max-iterations-num') as string) | |||||
| export const MAX_ITERATIONS_NUM = maxIterationsNum | |||||
| let enableWebsiteJinaReader = true | |||||
| let enableWebsiteFireCrawl = true | |||||
| let enableWebsiteWaterCrawl = false | |||||
| const getBooleanConfig = (envVar: string | undefined, attr: string) => { | |||||
| if (envVar !== undefined && envVar !== '') | |||||
| return envVar === 'true' | |||||
| const attrValue = globalThis.document?.body?.getAttribute(attr) | |||||
| if (attrValue !== undefined && attrValue !== '') | |||||
| return attrValue === 'true' | |||||
| return false | |||||
| } | |||||
| export const MAX_TOOLS_NUM = getNumberConfig(process.env.NEXT_PUBLIC_MAX_TOOLS_NUM, DatasetAttr.DATA_PUBLIC_MAX_TOOLS_NUM, 10) | |||||
| export const TEXT_GENERATION_TIMEOUT_MS = getNumberConfig(process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS, DatasetAttr.DATA_PUBLIC_TEXT_GENERATION_TIMEOUT_MS, 60000) | |||||
| export const LOOP_NODE_MAX_COUNT = getNumberConfig(process.env.NEXT_PUBLIC_LOOP_NODE_MAX_COUNT, DatasetAttr.DATA_PUBLIC_LOOP_NODE_MAX_COUNT, 100) | |||||
| export const MAX_ITERATIONS_NUM = getNumberConfig(process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM, DatasetAttr.DATA_PUBLIC_MAX_ITERATIONS_NUM, 99) | |||||
| export const MAX_TREE_DEPTH = getNumberConfig(process.env.NEXT_PUBLIC_MAX_TREE_DEPTH, DatasetAttr.DATA_PUBLIC_MAX_TREE_DEPTH, 50) | |||||
| enableWebsiteJinaReader = getBooleanConfig(process.env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER, 'data-public-enable-website-jinareader') | |||||
| enableWebsiteFireCrawl = getBooleanConfig(process.env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL, 'data-public-enable-website-firecrawl') | |||||
| enableWebsiteWaterCrawl = getBooleanConfig(process.env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL, 'data-public-enable-website-watercrawl') | |||||
| export const ENABLE_WEBSITE_JINAREADER = enableWebsiteJinaReader | |||||
| export const ENABLE_WEBSITE_FIRECRAWL = enableWebsiteFireCrawl | |||||
| export const ENABLE_WEBSITE_WATERCRAWL = enableWebsiteWaterCrawl | |||||
| export const ENABLE_WEBSITE_JINAREADER = getBooleanConfig(process.env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER, DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_JINAREADER, true) | |||||
| export const ENABLE_WEBSITE_FIRECRAWL = getBooleanConfig(process.env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL, DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_FIRECRAWL, true) | |||||
| export const ENABLE_WEBSITE_WATERCRAWL = getBooleanConfig(process.env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL, DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_WATERCRAWL, false) |
| export NEXT_PUBLIC_LOOP_NODE_MAX_COUNT=${LOOP_NODE_MAX_COUNT} | export NEXT_PUBLIC_LOOP_NODE_MAX_COUNT=${LOOP_NODE_MAX_COUNT} | ||||
| export NEXT_PUBLIC_MAX_PARALLEL_LIMIT=${MAX_PARALLEL_LIMIT} | export NEXT_PUBLIC_MAX_PARALLEL_LIMIT=${MAX_PARALLEL_LIMIT} | ||||
| export NEXT_PUBLIC_MAX_ITERATIONS_NUM=${MAX_ITERATIONS_NUM} | export NEXT_PUBLIC_MAX_ITERATIONS_NUM=${MAX_ITERATIONS_NUM} | ||||
| export NEXT_PUBLIC_MAX_TREE_DEPTH=${MAX_TREE_DEPTH} | |||||
| pm2 start /app/web/server.js --name dify-web --cwd /app/web -i ${PM2_INSTANCES} --no-daemon | pm2 start /app/web/server.js --name dify-web --cwd /app/web -i ${PM2_INSTANCES} --no-daemon |
| import { apiPrefix } from '@/config' | |||||
| import { API_PREFIX } from '@/config' | |||||
| import { fetchWithRetry } from '@/utils' | import { fetchWithRetry } from '@/utils' | ||||
| const LOCAL_STORAGE_KEY = 'is_other_tab_refreshing' | const LOCAL_STORAGE_KEY = 'is_other_tab_refreshing' | ||||
| // it can lead to an infinite loop if the refresh attempt also returns 401. | // it can lead to an infinite loop if the refresh attempt also returns 401. | ||||
| // To avoid this, handle token refresh separately in a dedicated function | // To avoid this, handle token refresh separately in a dedicated function | ||||
| // that does not call baseFetch and uses a single retry mechanism. | // that does not call baseFetch and uses a single retry mechanism. | ||||
| const [error, ret] = await fetchWithRetry(globalThis.fetch(`${apiPrefix}/refresh-token`, { | |||||
| const [error, ret] = await fetchWithRetry(globalThis.fetch(`${API_PREFIX}/refresh-token`, { | |||||
| method: 'POST', | method: 'POST', | ||||
| headers: { | headers: { | ||||
| 'Content-Type': 'application/json;utf-8', | 'Content-Type': 'application/json;utf-8', |
| allow_email_password_login: false, | allow_email_password_login: 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_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_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', | |||||
| } |