merge main

This commit is contained in:
zxhlyh
2025-07-21 17:45:26 +08:00
117 changed files with 1639 additions and 419 deletions

View File

@ -6,7 +6,7 @@ LABEL maintainer="takatost@gmail.com"
# RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add --no-cache tzdata
RUN npm install -g pnpm@10.11.1
RUN npm install -g pnpm@10.13.1
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"

View File

@ -0,0 +1,41 @@
'use client'
import { useTranslation } from 'react-i18next'
import {
RiAddLine,
RiArrowRightLine,
} from '@remixicon/react'
import Link from 'next/link'
type CreateAppCardProps = {
ref?: React.Ref<HTMLAnchorElement>
}
const CreateAppCard = ({ ref }: CreateAppCardProps) => {
const { t } = useTranslation()
return (
<div className='bg-background-default-dimm flex min-h-[160px] flex-col rounded-xl border-[0.5px]
border-components-panel-border transition-all duration-200 ease-in-out'
>
<Link ref={ref} className='group flex grow cursor-pointer items-start p-4' href='/datasets/create'>
<div className='flex items-center gap-3'>
<div className='flex h-10 w-10 items-center justify-center rounded-lg border border-dashed border-divider-regular bg-background-default-lighter
p-2 group-hover:border-solid group-hover:border-effects-highlight group-hover:bg-background-default-dodge'
>
<RiAddLine className='h-4 w-4 text-text-tertiary group-hover:text-text-accent' />
</div>
<div className='system-md-semibold text-text-secondary group-hover:text-text-accent'>{t('dataset.createDataset')}</div>
</div>
</Link>
<div className='system-xs-regular p-4 pt-0 text-text-tertiary'>{t('dataset.createDatasetIntro')}</div>
<Link className='group flex cursor-pointer items-center gap-1 rounded-b-xl border-t-[0.5px] border-divider-subtle p-4' href='/datasets/connect'>
<div className='system-xs-medium text-text-tertiary group-hover:text-text-accent'>{t('dataset.connectDataset')}</div>
<RiArrowRightLine className='h-3.5 w-3.5 text-text-tertiary group-hover:text-text-accent' />
</Link>
</div>
)
}
CreateAppCard.displayName = 'CreateAppCard'
export default CreateAppCard

View File

@ -1,6 +1,6 @@
import React from 'react'
import type { ReactNode } from 'react'
import SwrInitor from '@/app/components/swr-initor'
import SwrInitializer from '@/app/components/swr-initializer'
import { AppContextProvider } from '@/context/app-context'
import GA, { GaType } from '@/app/components/base/ga'
import HeaderWrapper from '@/app/components/header/header-wrapper'
@ -13,7 +13,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
return (
<>
<GA gaType={GaType.admin} />
<SwrInitor>
<SwrInitializer>
<AppContextProvider>
<EventEmitterContextProvider>
<ProviderContextProvider>
@ -26,7 +26,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
</ProviderContextProvider>
</EventEmitterContextProvider>
</AppContextProvider>
</SwrInitor>
</SwrInitializer>
</>
)
}

View File

@ -1,5 +1,6 @@
'use client'
import { useState } from 'react'
import useSWR from 'swr'
import { useTranslation } from 'react-i18next'
import {
RiGraduationCapFill,
@ -22,6 +23,8 @@ import PremiumBadge from '@/app/components/base/premium-badge'
import { useGlobalPublicStore } from '@/context/global-public-context'
import EmailChangeModal from './email-change-modal'
import { validPassword } from '@/config'
import { fetchAppList } from '@/service/apps'
import type { App } from '@/types/app'
const titleClassName = `
system-sm-semibold text-text-secondary
@ -33,7 +36,9 @@ const descriptionClassName = `
export default function AccountPage() {
const { t } = useTranslation()
const { systemFeatures } = useGlobalPublicStore()
const { mutateUserProfile, userProfile, apps } = useAppContext()
const { data: appList } = useSWR({ url: '/apps', params: { page: 1, limit: 100, name: '' } }, fetchAppList)
const apps = appList?.data || []
const { mutateUserProfile, userProfile } = useAppContext()
const { isEducationAccount } = useProviderContext()
const { notify } = useContext(ToastContext)
const [editNameModalVisible, setEditNameModalVisible] = useState(false)
@ -202,7 +207,7 @@ export default function AccountPage() {
{!!apps.length && (
<Collapse
title={`${t('common.account.showAppLength', { length: apps.length })}`}
items={apps.map(app => ({ ...app, key: app.id, name: app.name }))}
items={apps.map((app: App) => ({ ...app, key: app.id, name: app.name }))}
renderItem={renderAppItem}
wrapperClassName='mt-2'
/>

View File

@ -1,7 +1,7 @@
import React from 'react'
import type { ReactNode } from 'react'
import Header from './header'
import SwrInitor from '@/app/components/swr-initor'
import SwrInitor from '@/app/components/swr-initializer'
import { AppContextProvider } from '@/context/app-context'
import GA, { GaType } from '@/app/components/base/ga'
import HeaderWrapper from '@/app/components/header/header-wrapper'

View File

@ -1,6 +1,6 @@
import { useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation'
import { useContext, useContextSelector } from 'use-context-selector'
import { useContext } from 'use-context-selector'
import React, { useCallback, useState } from 'react'
import {
RiDeleteBinLine,
@ -15,7 +15,7 @@ import AppIcon from '../base/app-icon'
import cn from '@/utils/classnames'
import { useStore as useAppStore } from '@/app/components/app/store'
import { ToastContext } from '@/app/components/base/toast'
import AppsContext, { useAppContext } from '@/context/app-context'
import { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context'
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
@ -73,11 +73,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
const [showImportDSLModal, setShowImportDSLModal] = useState<boolean>(false)
const [secretEnvList, setSecretEnvList] = useState<EnvironmentVariable[]>([])
const mutateApps = useContextSelector(
AppsContext,
state => state.mutateApps,
)
const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({
name,
icon_type,
@ -106,12 +101,11 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
message: t('app.editDone'),
})
setAppDetail(app)
mutateApps()
}
catch {
notify({ type: 'error', message: t('app.editFailed') })
}
}, [appDetail, mutateApps, notify, setAppDetail, t])
}, [appDetail, notify, setAppDetail, t])
const onCopy: DuplicateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background }) => {
if (!appDetail)
@ -131,7 +125,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
message: t('app.newApp.appCreated'),
})
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
mutateApps()
onPlanInfoChanged()
getRedirection(true, newApp, replace)
}
@ -186,7 +179,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
try {
await deleteApp(appDetail.id)
notify({ type: 'success', message: t('app.appDeleted') })
mutateApps()
onPlanInfoChanged()
setAppDetail()
replace('/apps')
@ -198,7 +190,7 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
})
}
setShowConfirmDelete(false)
}, [appDetail, mutateApps, notify, onPlanInfoChanged, replace, setAppDetail, t])
}, [appDetail, notify, onPlanInfoChanged, replace, setAppDetail, t])
const { isCurrentWorkspaceEditor } = useAppContext()

View File

@ -13,7 +13,6 @@ import Loading from '@/app/components/base/loading'
import Badge from '@/app/components/base/badge'
import { useKnowledge } from '@/hooks/use-knowledge'
import cn from '@/utils/classnames'
import { basePath } from '@/utils/var'
import AppIcon from '@/app/components/base/app-icon'
export type ISelectDataSetProps = {
@ -113,7 +112,7 @@ const SelectDataSet: FC<ISelectDataSetProps> = ({
}}
>
<span className='text-text-tertiary'>{t('appDebug.feature.dataSet.noDataSet')}</span>
<Link href={`${basePath}/datasets/create`} className='font-normal text-text-accent'>{t('appDebug.feature.dataSet.toCreate')}</Link>
<Link href='/datasets/create' className='font-normal text-text-accent'>{t('appDebug.feature.dataSet.toCreate')}</Link>
</div>
)}

View File

@ -4,7 +4,7 @@ import { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation'
import { useContext, useContextSelector } from 'use-context-selector'
import { useContext } from 'use-context-selector'
import { RiArrowRightLine, RiArrowRightSLine, RiCommandLine, RiCornerDownLeftLine, RiExchange2Fill } from '@remixicon/react'
import Link from 'next/link'
import { useDebounceFn, useKeyPress } from 'ahooks'
@ -15,7 +15,7 @@ import Button from '@/app/components/base/button'
import Divider from '@/app/components/base/divider'
import cn from '@/utils/classnames'
import { basePath } from '@/utils/var'
import AppsContext, { useAppContext } from '@/context/app-context'
import { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context'
import { ToastContext } from '@/app/components/base/toast'
import type { AppMode } from '@/types/app'
@ -41,7 +41,6 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
const { t } = useTranslation()
const { push } = useRouter()
const { notify } = useContext(ToastContext)
const mutateApps = useContextSelector(AppsContext, state => state.mutateApps)
const [appMode, setAppMode] = useState<AppMode>('advanced-chat')
const [appIcon, setAppIcon] = useState<AppIconSelection>({ type: 'emoji', icon: '🤖', background: '#FFEAD5' })
@ -80,7 +79,6 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
notify({ type: 'success', message: t('app.newApp.appCreated') })
onSuccess()
onClose()
mutateApps()
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
getRedirection(isCurrentWorkspaceEditor, app, push)
}
@ -88,7 +86,7 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
}
isCreatingRef.current = false
}, [name, notify, t, appMode, appIcon, description, onSuccess, onClose, mutateApps, push, isCurrentWorkspaceEditor])
}, [name, notify, t, appMode, appIcon, description, onSuccess, onClose, push, isCurrentWorkspaceEditor])
const { run: handleCreateApp } = useDebounceFn(onCreate, { wait: 300 })
useKeyPress(['meta.enter', 'ctrl.enter'], () => {
@ -298,7 +296,7 @@ function AppTypeCard({ icon, title, description, active, onClick }: AppTypeCardP
>
{icon}
<div className='system-sm-semibold mb-0.5 mt-2 text-text-secondary'>{title}</div>
<div className='system-xs-regular text-text-tertiary'>{description}</div>
<div className='system-xs-regular line-clamp-2 text-text-tertiary' title={description}>{description}</div>
</div>
}

View File

@ -90,10 +90,10 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, classNam
const [option, setOption] = useState<Option>('iframe')
const [isCopied, setIsCopied] = useState<OptionStatus>({ iframe: false, scripts: false, chromePlugin: false })
const { langeniusVersionInfo } = useAppContext()
const { langGeniusVersionInfo } = useAppContext()
const themeBuilder = useThemeContext()
themeBuilder.buildTheme(siteInfo?.chat_color_theme ?? null, siteInfo?.chat_color_theme_inverted ?? false)
const isTestEnv = langeniusVersionInfo.current_env === 'TESTING' || langeniusVersionInfo.current_env === 'DEVELOPMENT'
const isTestEnv = langGeniusVersionInfo.current_env === 'TESTING' || langGeniusVersionInfo.current_env === 'DEVELOPMENT'
const onClickCopy = () => {
if (option === 'chromePlugin') {
const splitUrl = OPTION_MAP[option].getContent(appBaseUrl, accessToken).split(': ')

View File

@ -1,7 +1,7 @@
'use client'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useContext, useContextSelector } from 'use-context-selector'
import { useContext } from 'use-context-selector'
import { useRouter } from 'next/navigation'
import { useTranslation } from 'react-i18next'
import { RiBuildingLine, RiGlobalLine, RiLockLine, RiMoreFill, RiVerifiedBadgeLine } from '@remixicon/react'
@ -11,7 +11,7 @@ import Toast, { ToastContext } from '@/app/components/base/toast'
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
import AppIcon from '@/app/components/base/app-icon'
import AppsContext, { useAppContext } from '@/context/app-context'
import { useAppContext } from '@/context/app-context'
import type { HtmlContentProps } from '@/app/components/base/popover'
import CustomPopover from '@/app/components/base/popover'
import Divider from '@/app/components/base/divider'
@ -65,11 +65,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
const { onPlanInfoChanged } = useProviderContext()
const { push } = useRouter()
const mutateApps = useContextSelector(
AppsContext,
state => state.mutateApps,
)
const [showEditModal, setShowEditModal] = useState(false)
const [showDuplicateModal, setShowDuplicateModal] = useState(false)
const [showSwitchModal, setShowSwitchModal] = useState<boolean>(false)
@ -83,7 +78,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
notify({ type: 'success', message: t('app.appDeleted') })
if (onRefresh)
onRefresh()
mutateApps()
onPlanInfoChanged()
}
catch (e: any) {
@ -93,7 +87,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
})
}
setShowConfirmDelete(false)
}, [app.id, mutateApps, notify, onPlanInfoChanged, onRefresh, t])
}, [app.id, notify, onPlanInfoChanged, onRefresh, t])
const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({
name,
@ -122,12 +116,11 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
})
if (onRefresh)
onRefresh()
mutateApps()
}
catch {
notify({ type: 'error', message: t('app.editFailed') })
}
}, [app.id, mutateApps, notify, onRefresh, t])
}, [app.id, notify, onRefresh, t])
const onCopy: DuplicateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background }) => {
try {
@ -147,7 +140,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
if (onRefresh)
onRefresh()
mutateApps()
onPlanInfoChanged()
getRedirection(isCurrentWorkspaceEditor, newApp, push)
}
@ -195,16 +187,14 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
const onSwitch = () => {
if (onRefresh)
onRefresh()
mutateApps()
setShowSwitchModal(false)
}
const onUpdateAccessControl = useCallback(() => {
if (onRefresh)
onRefresh()
mutateApps()
setShowAccessControl(false)
}, [onRefresh, mutateApps, setShowAccessControl])
}, [onRefresh, setShowAccessControl])
const Operations = (props: HtmlContentProps) => {
const { data: userCanAccessApp, isLoading: isGettingUserCanAccessApp } = useGetUserCanAccessApp({ appId: app?.id, enabled: (!!props?.open && systemFeatures.webapp_auth.enabled) })
@ -325,7 +315,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
dateFormat: `${t('datasetDocuments.segment.dateTimeFormat')}`,
})
return `${t('datasetDocuments.segment.editedAt')} ${timeText}`
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [app.updated_at, app.created_at])
return (

View File

@ -45,7 +45,7 @@ const Avatar = ({
className={cn(textClassName, 'scale-[0.4] text-center text-white')}
style={style}
>
{name[0].toLocaleUpperCase()}
{name && name[0].toLocaleUpperCase()}
</div>
</div>
)

View File

@ -117,7 +117,7 @@ const Question: FC<QuestionProps> = ({
</div>
<div
ref={contentRef}
className='bg-background-gradient-bg-fill-chat-bubble-bg-3 w-full rounded-2xl px-4 py-3 text-sm text-text-primary'
className='w-full rounded-2xl bg-background-gradient-bg-fill-chat-bubble-bg-3 px-4 py-3 text-sm text-text-primary'
style={theme?.chatBubbleColorStyle ? CssTransform(theme.chatBubbleColorStyle) : {}}
>
{

View File

@ -21,7 +21,7 @@ const AppsFull: FC<{ loc: string; className?: string; }> = ({
}) => {
const { t } = useTranslation()
const { plan } = useProviderContext()
const { userProfile, langeniusVersionInfo } = useAppContext()
const { userProfile, langGeniusVersionInfo } = useAppContext()
const isTeam = plan.type === Plan.team
const usage = plan.usage.buildApps
const total = plan.total.buildApps
@ -62,7 +62,7 @@ const AppsFull: FC<{ loc: string; className?: string; }> = ({
)}
{plan.type !== Plan.sandbox && plan.type !== Plan.professional && (
<Button variant='secondary-accent'>
<a target='_blank' rel='noopener noreferrer' href={mailToSupport(userProfile.email, plan.type, langeniusVersionInfo.current_version)}>
<a target='_blank' rel='noopener noreferrer' href={mailToSupport(userProfile.email, plan.type, langGeniusVersionInfo.current_version)}>
{t('billing.apps.contactUs')}
</a>
</Button>

View File

@ -43,10 +43,10 @@ Object.defineProperty(globalThis, 'sessionStorage', {
value: sessionStorage,
})
const BrowserInitor = ({
const BrowserInitializer = ({
children,
}: { children: React.ReactNode }) => {
}: { children: React.ReactElement }) => {
return children
}
export default BrowserInitor
export default BrowserInitializer

View File

@ -83,7 +83,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty, PropertyInstructi
- <code>subchunk_segmentation</code> (object) 子チャンクルール
- <code>separator</code> セグメンテーション識別子。現在は 1 つの区切り文字のみ許可。デフォルトは <code>***</code>
- <code>max_tokens</code> 最大長 (トークン) は親チャンクの長さより短いことを検証する必要があります
- <code>chunk_overlap</code> 隣接するチャンク間の重を定義 (オプション)
- <code>chunk_overlap</code> 隣接するチャンク間の重なりを定義 (オプション)
</Property>
<PropertyInstruction>ナレッジベースにパラメータが設定されていない場合、最初のアップロードには以下のパラメータを提供する必要があります。提供されない場合、デフォルトパラメータが使用されます。</PropertyInstruction>
<Property name='retrieval_model' type='object' key='retrieval_model'>
@ -218,7 +218,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty, PropertyInstructi
- <code>subchunk_segmentation</code> (object) 子チャンクルール
- <code>separator</code> セグメンテーション識別子。現在は 1 つの区切り文字のみ許可。デフォルトは <code>***</code>
- <code>max_tokens</code> 最大長 (トークン) は親チャンクの長さより短いことを検証する必要があります
- <code>chunk_overlap</code> 隣接するチャンク間の重を定義 (オプション)
- <code>chunk_overlap</code> 隣接するチャンク間の重なりを定義 (オプション)
</Property>
<Property name='file' type='multipart/form-data' key='file'>
アップロードする必要があるファイル。
@ -555,7 +555,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty, PropertyInstructi
- <code>subchunk_segmentation</code> (object) 子チャンクルール
- <code>separator</code> セグメンテーション識別子。現在は 1 つの区切り文字のみ許可。デフォルトは <code>***</code>
- <code>max_tokens</code> 最大長 (トークン) は親チャンクの長さより短いことを検証する必要があります
- <code>chunk_overlap</code> 隣接するチャンク間の重を定義 (オプション)
- <code>chunk_overlap</code> 隣接するチャンク間の重なりを定義 (オプション)
</Property>
</Properties>
</Col>
@ -657,7 +657,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty, PropertyInstructi
- <code>subchunk_segmentation</code> (object) 子チャンクルール
- <code>separator</code> セグメンテーション識別子。現在は 1 つの区切り文字のみ許可。デフォルトは <code>***</code>
- <code>max_tokens</code> 最大長 (トークン) は親チャンクの長さより短いことを検証する必要があります
- <code>chunk_overlap</code> 隣接するチャンク間の重を定義 (オプション)
- <code>chunk_overlap</code> 隣接するチャンク間の重なりを定義 (オプション)
</Property>
</Properties>
</Col>

View File

@ -333,7 +333,7 @@ Workflow 应用无会话支持,适合用于翻译/文章写作/总结 AI 等
<Col>
根据 workflow 执行 ID 获取 workflow 任务当前执行结果
### Path
- `workflow_run_id` (string) workflow_run_id,可在流式返回 Chunk 中获取
- `workflow_run_id` (string) workflow 执行 ID,可在流式返回 Chunk 中获取
### Response
- `id` (string) workflow 执行 ID
- `workflow_id` (string) 关联的 Workflow ID

View File

@ -12,16 +12,16 @@ import { noop } from 'lodash-es'
import { useGlobalPublicStore } from '@/context/global-public-context'
type IAccountSettingProps = {
langeniusVersionInfo: LangGeniusVersionResponse
langGeniusVersionInfo: LangGeniusVersionResponse
onCancel: () => void
}
export default function AccountAbout({
langeniusVersionInfo,
langGeniusVersionInfo,
onCancel,
}: IAccountSettingProps) {
const { t } = useTranslation()
const isLatest = langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version
const isLatest = langGeniusVersionInfo.current_version === langGeniusVersionInfo.latest_version
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
return (
@ -43,7 +43,7 @@ export default function AccountAbout({
/>
: <DifyLogo size='large' className='mx-auto' />}
<div className='text-center text-xs font-normal text-text-tertiary'>Version {langeniusVersionInfo?.current_version}</div>
<div className='text-center text-xs font-normal text-text-tertiary'>Version {langGeniusVersionInfo?.current_version}</div>
<div className='flex flex-col items-center gap-2 text-center text-xs font-normal text-text-secondary'>
<div>© {dayjs().year()} LangGenius, Inc., Contributors.</div>
<div className='text-text-accent'>
@ -63,8 +63,8 @@ export default function AccountAbout({
<div className='text-xs font-medium text-text-tertiary'>
{
isLatest
? t('common.about.latestAvailable', { version: langeniusVersionInfo.latest_version })
: t('common.about.nowAvailable', { version: langeniusVersionInfo.latest_version })
? t('common.about.latestAvailable', { version: langGeniusVersionInfo.latest_version })
: t('common.about.nowAvailable', { version: langGeniusVersionInfo.latest_version })
}
</div>
<div className='flex items-center'>
@ -80,7 +80,7 @@ export default function AccountAbout({
!isLatest && !IS_CE_EDITION && (
<Button variant='primary' size='small'>
<Link
href={langeniusVersionInfo.release_notes}
href={langGeniusVersionInfo.release_notes}
target='_blank' rel='noopener noreferrer'
>
{t('common.about.updateNow')}

View File

@ -45,7 +45,7 @@ export default function AppSelector() {
const { t } = useTranslation()
const docLink = useDocLink()
const { userProfile, langeniusVersionInfo, isCurrentWorkspaceOwner } = useAppContext()
const { userProfile, langGeniusVersionInfo, isCurrentWorkspaceOwner } = useAppContext()
const { isEducationAccount } = useProviderContext()
const { setShowAccountSettingModal } = useModalContext()
@ -180,8 +180,8 @@ export default function AppSelector() {
<RiInformation2Line className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.about')}</div>
<div className='flex shrink-0 items-center'>
<div className='system-xs-regular mr-2 text-text-tertiary'>{langeniusVersionInfo.current_version}</div>
<Indicator color={langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version ? 'green' : 'orange'} />
<div className='system-xs-regular mr-2 text-text-tertiary'>{langGeniusVersionInfo.current_version}</div>
<Indicator color={langGeniusVersionInfo.current_version === langGeniusVersionInfo.latest_version ? 'green' : 'orange'} />
</div>
</div>
</MenuItem>
@ -217,7 +217,7 @@ export default function AppSelector() {
}
</Menu>
{
aboutVisible && <AccountAbout onCancel={() => setAboutVisible(false)} langeniusVersionInfo={langeniusVersionInfo} />
aboutVisible && <AccountAbout onCancel={() => setAboutVisible(false)} langGeniusVersionInfo={langGeniusVersionInfo} />
}
</div >
)

View File

@ -16,7 +16,7 @@ export default function Support() {
`
const { t } = useTranslation()
const { plan } = useProviderContext()
const { userProfile, langeniusVersionInfo } = useAppContext()
const { userProfile, langGeniusVersionInfo } = useAppContext()
const canEmailSupport = plan.type === Plan.professional || plan.type === Plan.team || plan.type === Plan.enterprise
return <Menu as="div" className="relative h-full w-full">
@ -53,7 +53,7 @@ export default function Support() {
className={cn(itemClassName, 'group justify-between',
'data-[active]:bg-state-base-hover',
)}
href={mailToSupport(userProfile.email, plan.type, langeniusVersionInfo.current_version)}
href={mailToSupport(userProfile.email, plan.type, langGeniusVersionInfo.current_version)}
target='_blank' rel='noopener noreferrer'>
<RiMailSendLine className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.emailSupport')}</div>

View File

@ -12,8 +12,8 @@ const headerEnvClassName: { [k: string]: string } = {
const EnvNav = () => {
const { t } = useTranslation()
const { langeniusVersionInfo } = useAppContext()
const showEnvTag = langeniusVersionInfo.current_env === 'TESTING' || langeniusVersionInfo.current_env === 'DEVELOPMENT'
const { langGeniusVersionInfo } = useAppContext()
const showEnvTag = langGeniusVersionInfo.current_env === 'TESTING' || langGeniusVersionInfo.current_env === 'DEVELOPMENT'
if (!showEnvTag)
return null
@ -21,10 +21,10 @@ const EnvNav = () => {
return (
<div className={`
mr-1 flex h-[22px] items-center rounded-md border px-2 text-xs font-medium
${headerEnvClassName[langeniusVersionInfo.current_env]}
${headerEnvClassName[langGeniusVersionInfo.current_env]}
`}>
{
langeniusVersionInfo.current_env === 'TESTING' && (
langGeniusVersionInfo.current_env === 'TESTING' && (
<>
<Beaker02 className='h-3 w-3' />
<div className='ml-1 max-[1280px]:hidden'>{t('common.environment.testing')}</div>
@ -32,7 +32,7 @@ const EnvNav = () => {
)
}
{
langeniusVersionInfo.current_env === 'DEVELOPMENT' && (
langGeniusVersionInfo.current_env === 'DEVELOPMENT' && (
<>
<TerminalSquare className='h-3 w-3' />
<div className='ml-1 max-[1280px]:hidden'>{t('common.environment.development')}</div>

View File

@ -48,7 +48,6 @@ const Installed: FC<Props> = ({
useEffect(() => {
if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier)
onInstalled()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hasInstalled])
const [isInstalling, setIsInstalling] = React.useState(false)
@ -105,12 +104,12 @@ const Installed: FC<Props> = ({
}
}
const { langeniusVersionInfo } = useAppContext()
const { langGeniusVersionInfo } = useAppContext()
const isDifyVersionCompatible = useMemo(() => {
if (!langeniusVersionInfo.current_version)
if (!langGeniusVersionInfo.current_version)
return true
return gte(langeniusVersionInfo.current_version, payload.meta.minimum_dify_version ?? '0.0.0')
}, [langeniusVersionInfo.current_version, payload.meta.minimum_dify_version])
return gte(langGeniusVersionInfo.current_version, payload.meta.minimum_dify_version ?? '0.0.0')
}, [langGeniusVersionInfo.current_version, payload.meta.minimum_dify_version])
return (
<>

View File

@ -59,7 +59,6 @@ const Installed: FC<Props> = ({
useEffect(() => {
if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier)
onInstalled()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hasInstalled])
const handleCancel = () => {
@ -120,12 +119,12 @@ const Installed: FC<Props> = ({
}
}
const { langeniusVersionInfo } = useAppContext()
const { langGeniusVersionInfo } = useAppContext()
const { data: pluginDeclaration } = usePluginDeclarationFromMarketPlace(uniqueIdentifier)
const isDifyVersionCompatible = useMemo(() => {
if (!pluginDeclaration || !langeniusVersionInfo.current_version) return true
return gte(langeniusVersionInfo.current_version, pluginDeclaration?.manifest.meta.minimum_dify_version ?? '0.0.0')
}, [langeniusVersionInfo.current_version, pluginDeclaration])
if (!pluginDeclaration || !langGeniusVersionInfo.current_version) return true
return gte(langGeniusVersionInfo.current_version, pluginDeclaration?.manifest.meta.minimum_dify_version ?? '0.0.0')
}, [langGeniusVersionInfo.current_version, pluginDeclaration])
const { canInstall } = useInstallPluginLimit({ ...payload, from: 'marketplace' })
return (

View File

@ -265,7 +265,7 @@ const ToolSelector: FC<Props> = ({
/>
)}
</PortalToFollowElemTrigger>
<PortalToFollowElemContent>
<PortalToFollowElemContent className='z-10'>
<div className={cn('relative max-h-[642px] min-h-20 w-[361px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur pb-4 shadow-lg backdrop-blur-sm', 'overflow-y-auto pb-2')}>
<>
<div className='system-xl-semibold px-4 pb-1 pt-3.5 text-text-primary'>{t(`plugin.detailPanel.toolSelector.${isEdit ? 'toolSetting' : 'title'}`)}</div>
@ -309,15 +309,15 @@ const ToolSelector: FC<Props> = ({
{currentProvider && currentProvider.type === CollectionType.builtIn && currentProvider.allow_delete && (
<>
<Divider className='my-1 w-full' />
<div className='px-4 py-2'>
<PluginAuthInAgent
pluginPayload={{
provider: currentProvider.name,
category: AuthCategory.tool,
}}
credentialId={value?.credential_id}
onAuthorizationItemClick={handleAuthorizationItemClick}
/>
<div className='px-4 py-2'>
<PluginAuthInAgent
pluginPayload={{
provider: currentProvider.name,
category: AuthCategory.tool,
}}
credentialId={value?.credential_id}
onAuthorizationItemClick={handleAuthorizationItemClick}
/>
</div>
</>
)}

View File

@ -62,13 +62,13 @@ const PluginItem: FC<Props> = ({
return [PluginSource.github, PluginSource.marketplace].includes(source) ? author : ''
}, [source, author])
const { langeniusVersionInfo } = useAppContext()
const { langGeniusVersionInfo } = useAppContext()
const isDifyVersionCompatible = useMemo(() => {
if (!langeniusVersionInfo.current_version)
if (!langGeniusVersionInfo.current_version)
return true
return gte(langeniusVersionInfo.current_version, declarationMeta.minimum_dify_version ?? '0.0.0')
}, [declarationMeta.minimum_dify_version, langeniusVersionInfo.current_version])
return gte(langGeniusVersionInfo.current_version, declarationMeta.minimum_dify_version ?? '0.0.0')
}, [declarationMeta.minimum_dify_version, langGeniusVersionInfo.current_version])
const handleDelete = () => {
refreshPluginList({ category } as any)

View File

@ -5,9 +5,9 @@ import * as Sentry from '@sentry/react'
const isDevelopment = process.env.NODE_ENV === 'development'
const SentryInit = ({
const SentryInitializer = ({
children,
}: { children: React.ReactNode }) => {
}: { children: React.ReactElement }) => {
useEffect(() => {
const SENTRY_DSN = document?.body?.getAttribute('data-public-sentry-dsn')
if (!isDevelopment && SENTRY_DSN) {
@ -26,4 +26,4 @@ const SentryInit = ({
return children
}
export default SentryInit
export default SentryInitializer

View File

@ -10,12 +10,12 @@ import {
EDUCATION_VERIFY_URL_SEARCHPARAMS_ACTION,
} from '@/app/education-apply/constants'
type SwrInitorProps = {
type SwrInitializerProps = {
children: ReactNode
}
const SwrInitor = ({
const SwrInitializer = ({
children,
}: SwrInitorProps) => {
}: SwrInitializerProps) => {
const router = useRouter()
const searchParams = useSearchParams()
const consoleToken = decodeURIComponent(searchParams.get('access_token') || '')
@ -86,4 +86,4 @@ const SwrInitor = ({
: null
}
export default SwrInitor
export default SwrInitializer

View File

@ -697,7 +697,7 @@ const getIterationItemType = ({
case VarType.arrayObject:
return VarType.object
case VarType.array:
return VarType.any
return VarType.arrayObject // Use more specific type instead of any
case VarType.arrayFile:
return VarType.file
default:

View File

@ -13,7 +13,7 @@ const metaData = genNodeMetaData({
const nodeDefault: NodeDefault<AgentNodeType> = {
metaData,
defaultValue: {
version: '2',
tool_node_version: '2',
},
checkValid(payload, t, moreDataForCheckValid: {
strategyProvider?: StrategyPluginDetail,
@ -58,27 +58,29 @@ const nodeDefault: NodeDefault<AgentNodeType> = {
const userSettings = toolValue.settings
const reasoningConfig = toolValue.parameters
const version = payload.version
const toolNodeVersion = payload.tool_node_version
const mergeVersion = version || toolNodeVersion
schemas.forEach((schema: any) => {
if (schema?.required) {
if (schema.form === 'form' && !version && !userSettings[schema.name]?.value) {
if (schema.form === 'form' && !mergeVersion && !userSettings[schema.name]?.value) {
return {
isValid: false,
errorMessage: t('workflow.errorMsg.toolParameterRequired', { field: renderI18nObject(param.label, language), param: renderI18nObject(schema.label, language) }),
}
}
if (schema.form === 'form' && version && !userSettings[schema.name]?.value.value) {
if (schema.form === 'form' && mergeVersion && !userSettings[schema.name]?.value.value) {
return {
isValid: false,
errorMessage: t('workflow.errorMsg.toolParameterRequired', { field: renderI18nObject(param.label, language), param: renderI18nObject(schema.label, language) }),
}
}
if (schema.form === 'llm' && !version && reasoningConfig[schema.name].auto === 0 && !reasoningConfig[schema.name]?.value) {
if (schema.form === 'llm' && !mergeVersion && reasoningConfig[schema.name].auto === 0 && !reasoningConfig[schema.name]?.value) {
return {
isValid: false,
errorMessage: t('workflow.errorMsg.toolParameterRequired', { field: renderI18nObject(param.label, language), param: renderI18nObject(schema.label, language) }),
}
}
if (schema.form === 'llm' && version && reasoningConfig[schema.name].auto === 0 && !reasoningConfig[schema.name]?.value.value) {
if (schema.form === 'llm' && mergeVersion && reasoningConfig[schema.name].auto === 0 && !reasoningConfig[schema.name]?.value.value) {
return {
isValid: false,
errorMessage: t('workflow.errorMsg.toolParameterRequired', { field: renderI18nObject(param.label, language), param: renderI18nObject(schema.label, language) }),

View File

@ -12,6 +12,7 @@ export type AgentNodeType = CommonNodeType & {
plugin_unique_identifier?: string
memory?: Memory
version?: string
tool_node_version?: string
}
export enum AgentFeature {

View File

@ -129,7 +129,7 @@ const useConfig = (id: string, payload: AgentNodeType) => {
}
const formattingLegacyData = () => {
if (inputs.version)
if (inputs.version || inputs.tool_node_version)
return inputs
const newData = produce(inputs, (draft) => {
const schemas = currentStrategy?.parameters || []
@ -140,7 +140,7 @@ const useConfig = (id: string, payload: AgentNodeType) => {
if (targetSchema?.type === FormTypeEnum.multiToolSelector)
draft.agent_parameters![key].value = draft.agent_parameters![key].value.map((tool: any) => formattingToolData(tool))
})
draft.version = '2'
draft.tool_node_version = '2'
})
return newData
}
@ -151,7 +151,6 @@ const useConfig = (id: string, payload: AgentNodeType) => {
return
const newData = formattingLegacyData()
setInputs(newData)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentStrategy])
// vars

View File

@ -16,7 +16,7 @@ const nodeDefault: NodeDefault<ToolNodeType> = {
defaultValue: {
tool_parameters: {},
tool_configurations: {},
version: '2',
tool_node_version: '2',
},
checkValid(payload: ToolNodeType, t: any, moreDataForCheckValid: any) {
const { toolInputsSchema, toolSettingSchema, language, notAuthed } = moreDataForCheckValid

View File

@ -23,4 +23,5 @@ export type ToolNodeType = CommonNodeType & {
output_schema: Record<string, any>
paramSchemas?: Record<string, any>[]
version?: string
tool_node_version?: string
}

View File

@ -286,8 +286,8 @@ export const initialNodes = (originNodes: Node[], originEdges: Edge[]) => {
}
}
if (node.data.type === BlockEnum.Tool && !(node as Node<ToolNodeType>).data.version) {
(node as Node<ToolNodeType>).data.version = '2'
if (node.data.type === BlockEnum.Tool && !(node as Node<ToolNodeType>).data.version && !(node as Node<ToolNodeType>).data.tool_node_version) {
(node as Node<ToolNodeType>).data.tool_node_version = '2'
const toolConfigurations = (node as Node<ToolNodeType>).data.tool_configurations
if (toolConfigurations && Object.keys(toolConfigurations).length > 0) {

View File

@ -1,10 +1,10 @@
import RoutePrefixHandle from './routePrefixHandle'
import type { Viewport } from 'next'
import I18nServer from './components/i18n-server'
import BrowserInitor from './components/browser-initor'
import SentryInitor from './components/sentry-initor'
import BrowserInitializer from './components/browser-initializer'
import SentryInitializer from './components/sentry-initializer'
import { getLocaleOnServer } from '@/i18n/server'
import { TanstackQueryIniter } from '@/context/query-client'
import { TanstackQueryInitializer } from '@/context/query-client'
import { ThemeProvider } from 'next-themes'
import './styles/globals.css'
import './styles/markdown.scss'
@ -62,9 +62,9 @@ const LocaleLayout = async ({
className="color-scheme h-full select-auto"
{...datasetMap}
>
<BrowserInitor>
<SentryInitor>
<TanstackQueryIniter>
<BrowserInitializer>
<SentryInitializer>
<TanstackQueryInitializer>
<ThemeProvider
attribute='data-theme'
defaultTheme='system'
@ -77,9 +77,9 @@ const LocaleLayout = async ({
</GlobalPublicStoreProvider>
</I18nServer>
</ThemeProvider>
</TanstackQueryIniter>
</SentryInitor>
</BrowserInitor>
</TanstackQueryInitializer>
</SentryInitializer>
</BrowserInitializer>
<RoutePrefixHandle />
</body>
</html>

View File

@ -1,20 +1,15 @@
'use client'
import { createRef, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import useSWR from 'swr'
import { createContext, useContext, useContextSelector } from 'use-context-selector'
import type { FC, ReactNode } from 'react'
import { fetchAppList } from '@/service/apps'
import Loading from '@/app/components/base/loading'
import { fetchCurrentWorkspace, fetchLanggeniusVersion, fetchUserProfile } from '@/service/common'
import type { App } from '@/types/app'
import { fetchCurrentWorkspace, fetchLangGeniusVersion, fetchUserProfile } from '@/service/common'
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
import { noop } from 'lodash-es'
export type AppContextValue = {
apps: App[]
mutateApps: VoidFunction
userProfile: UserProfileResponse
mutateUserProfile: VoidFunction
currentWorkspace: ICurrentWorkspace
@ -23,13 +18,21 @@ export type AppContextValue = {
isCurrentWorkspaceEditor: boolean
isCurrentWorkspaceDatasetOperator: boolean
mutateCurrentWorkspace: VoidFunction
pageContainerRef: React.RefObject<HTMLDivElement>
langeniusVersionInfo: LangGeniusVersionResponse
langGeniusVersionInfo: LangGeniusVersionResponse
useSelector: typeof useSelector
isLoadingCurrentWorkspace: boolean
}
const initialLangeniusVersionInfo = {
const userProfilePlaceholder = {
id: '',
name: '',
email: '',
avatar: '',
avatar_url: '',
is_password_set: false,
}
const initialLangGeniusVersionInfo = {
current_env: '',
current_version: '',
latest_version: '',
@ -50,16 +53,7 @@ const initialWorkspaceInfo: ICurrentWorkspace = {
}
const AppContext = createContext<AppContextValue>({
apps: [],
mutateApps: noop,
userProfile: {
id: '',
name: '',
email: '',
avatar: '',
avatar_url: '',
is_password_set: false,
},
userProfile: userProfilePlaceholder,
currentWorkspace: initialWorkspaceInfo,
isCurrentWorkspaceManager: false,
isCurrentWorkspaceOwner: false,
@ -67,8 +61,7 @@ const AppContext = createContext<AppContextValue>({
isCurrentWorkspaceDatasetOperator: false,
mutateUserProfile: noop,
mutateCurrentWorkspace: noop,
pageContainerRef: createRef(),
langeniusVersionInfo: initialLangeniusVersionInfo,
langGeniusVersionInfo: initialLangGeniusVersionInfo,
useSelector,
isLoadingCurrentWorkspace: false,
})
@ -82,14 +75,11 @@ export type AppContextProviderProps = {
}
export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) => {
const pageContainerRef = useRef<HTMLDivElement>(null)
const { data: appList, mutate: mutateApps } = useSWR({ url: '/apps', params: { page: 1, limit: 30, name: '' } }, fetchAppList)
const { data: userProfileResponse, mutate: mutateUserProfile } = useSWR({ url: '/account/profile', params: {} }, fetchUserProfile)
const { data: currentWorkspaceResponse, mutate: mutateCurrentWorkspace, isLoading: isLoadingCurrentWorkspace } = useSWR({ url: '/workspaces/current', params: {} }, fetchCurrentWorkspace)
const [userProfile, setUserProfile] = useState<UserProfileResponse>()
const [langeniusVersionInfo, setLangeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangeniusVersionInfo)
const [userProfile, setUserProfile] = useState<UserProfileResponse>(userProfilePlaceholder)
const [langGeniusVersionInfo, setLangGeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangGeniusVersionInfo)
const [currentWorkspace, setCurrentWorkspace] = useState<ICurrentWorkspace>(initialWorkspaceInfo)
const isCurrentWorkspaceManager = useMemo(() => ['owner', 'admin'].includes(currentWorkspace.role), [currentWorkspace.role])
const isCurrentWorkspaceOwner = useMemo(() => currentWorkspace.role === 'owner', [currentWorkspace.role])
@ -101,8 +91,8 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
setUserProfile(result)
const current_version = userProfileResponse.headers.get('x-version')
const current_env = process.env.NODE_ENV === 'development' ? 'DEVELOPMENT' : userProfileResponse.headers.get('x-env')
const versionData = await fetchLanggeniusVersion({ url: '/version', params: { current_version } })
setLangeniusVersionInfo({ ...versionData, current_version, latest_version: versionData.version, current_env })
const versionData = await fetchLangGeniusVersion({ url: '/version', params: { current_version } })
setLangGeniusVersionInfo({ ...versionData, current_version, latest_version: versionData.version, current_env })
}
}, [userProfileResponse])
@ -115,17 +105,11 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
setCurrentWorkspace(currentWorkspaceResponse)
}, [currentWorkspaceResponse])
if (!appList || !userProfile)
return <Loading type='app' />
return (
<AppContext.Provider value={{
apps: appList.data,
mutateApps,
userProfile,
mutateUserProfile,
pageContainerRef,
langeniusVersionInfo,
langGeniusVersionInfo,
useSelector,
currentWorkspace,
isCurrentWorkspaceManager,
@ -137,7 +121,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 />}
<div ref={pageContainerRef} className='relative flex grow flex-col overflow-y-auto overflow-x-hidden bg-background-body'>
<div className='relative flex grow flex-col overflow-y-auto overflow-x-hidden bg-background-body'>
{children}
</div>
</div>

View File

@ -14,7 +14,7 @@ const client = new QueryClient({
},
})
export const TanstackQueryIniter: FC<PropsWithChildren> = (props) => {
export const TanstackQueryInitializer: FC<PropsWithChildren> = (props) => {
const { children } = props
return <QueryClientProvider client={client}>
{children}

View File

@ -8,6 +8,7 @@ import storybook from 'eslint-plugin-storybook'
import tailwind from 'eslint-plugin-tailwindcss'
import reactHooks from 'eslint-plugin-react-hooks'
import sonar from 'eslint-plugin-sonarjs'
import oxlint from 'eslint-plugin-oxlint'
// import reactRefresh from 'eslint-plugin-react-refresh'
@ -245,4 +246,5 @@ export default combine(
'tailwindcss/migration-from-tailwind-2': 'warn',
},
},
oxlint.configs['flat/recommended'],
)

View File

@ -78,7 +78,7 @@ const translation = {
optional: 'Wahlfrei',
noTemplateFound: 'Keine Vorlagen gefunden',
workflowUserDescription: 'Autonome KI-Arbeitsabläufe visuell per Drag-and-Drop erstellen.',
foundResults: '{{Anzahl}} Befund',
foundResults: '{{count}} Befund',
chatbotShortDescription: 'LLM-basierter Chatbot mit einfacher Einrichtung',
completionUserDescription: 'Erstellen Sie schnell einen KI-Assistenten für Textgenerierungsaufgaben mit einfacher Konfiguration.',
noAppsFound: 'Keine Apps gefunden',
@ -92,7 +92,7 @@ const translation = {
noTemplateFoundTip: 'Versuchen Sie, mit verschiedenen Schlüsselwörtern zu suchen.',
advancedUserDescription: 'Workflow mit Speicherfunktionen und Chatbot-Oberfläche.',
chatbotUserDescription: 'Erstellen Sie schnell einen LLM-basierten Chatbot mit einfacher Konfiguration. Sie können später zu Chatflow wechseln.',
foundResult: '{{Anzahl}} Ergebnis',
foundResult: '{{count}} Ergebnis',
agentUserDescription: 'Ein intelligenter Agent, der in der Lage ist, iteratives Denken zu führen und autonome Werkzeuge zu verwenden, um Aufgabenziele zu erreichen.',
agentShortDescription: 'Intelligenter Agent mit logischem Denken und autonomer Werkzeugnutzung',
dropDSLToCreateApp: 'Ziehen Sie die DSL-Datei hierher, um die App zu erstellen',

View File

@ -77,10 +77,10 @@ const translation = {
appCreateDSLErrorPart1: 'تفاوت قابل توجهی در نسخه های DSL مشاهده شده است. اجبار به واردات ممکن است باعث اختلال در عملکرد برنامه شود.',
appCreateDSLWarning: 'احتیاط: تفاوت نسخه DSL ممکن است بر ویژگی های خاصی تأثیر بگذارد',
completionShortDescription: 'دستیار هوش مصنوعی برای تسک های تولید متن',
foundResult: '{{تعداد}} نتیجه',
foundResult: '{{count}} نتیجه',
chatbotUserDescription: 'به سرعت یک چت بات مبتنی بر LLM با پیکربندی ساده بسازید. بعدا می توانید به Chatflow بروید.',
chooseAppType: 'انتخاب نوع برنامه',
foundResults: '{{تعداد}} نتیجه',
foundResults: '{{count}} نتیجه',
noIdeaTip: 'ایده ای ندارید؟ قالب های ما را بررسی کنید',
forBeginners: 'انواع برنامه‌های پایه‌تر',
noAppsFound: 'هیچ برنامه ای یافت نشد',

View File

@ -74,12 +74,12 @@ const translation = {
appCreateDSLErrorPart2: 'क्या आप जारी रखना चाहते हैं?',
learnMore: 'और जानो',
forBeginners: 'नए उपयोगकर्ताओं के लिए बुनियादी ऐप प्रकार',
foundResults: '{{गिनती}} परिणाम',
foundResults: '{{count}} परिणाम',
forAdvanced: 'उन्नत उपयोगकर्ताओं के लिए',
agentUserDescription: 'पुनरावृत्त तर्क और स्वायत्त उपकरण में सक्षम एक बुद्धिमान एजेंट कार्य लक्ष्यों को प्राप्त करने के लिए उपयोग करता है।',
optional: 'वैकल्पिक',
chatbotShortDescription: 'सरल सेटअप के साथ एलएलएम-आधारित चैटबॉट',
foundResult: '{{गिनती}} परिणाम',
foundResult: '{{count}} परिणाम',
completionUserDescription: 'सरल कॉन्फ़िगरेशन के साथ पाठ निर्माण कार्यों के लिए त्वरित रूप से AI सहायक बनाएं।',
noIdeaTip: 'कोई विचार नहीं? हमारे टेम्प्लेट देखें',
noTemplateFound: 'कोई टेम्पलेट नहीं मिला',

View File

@ -79,11 +79,11 @@ const translation = {
appCreateDSLErrorTitle: 'バージョンの非互換性',
appCreateDSLWarning: '注意:DSL のバージョンの違いは、特定の機能に影響を与える可能性があります',
appCreateDSLErrorPart1: 'DSL バージョンに大きな違いが検出されました。インポートを強制すると、アプリケーションが誤動作する可能性があります。',
optional: '意',
optional: '意',
forBeginners: '初心者向けの基本的なアプリタイプ',
noTemplateFoundTip: '別のキーワードを使用して検索してみてください。',
agentShortDescription: '推論と自律的なツールの使用を備えたインテリジェントエージェント',
foundResults: '{{カウント}}業績',
foundResults: '{{count}}件の結果',
noTemplateFound: 'テンプレートが見つかりません',
noAppsFound: 'アプリが見つかりませんでした',
workflowShortDescription: 'インテリジェントな自動化のためのエージェントフロー',
@ -91,7 +91,7 @@ const translation = {
advancedUserDescription: '追加のメモリ機能とチャットボットインターフェースを備えたワークフロー',
advancedShortDescription: 'メモリを使用した複雑なマルチターン対話のワークフロー',
agentUserDescription: 'タスクの目標を達成するために反復的な推論と自律的なツールを使用できるインテリジェントエージェント。',
foundResult: '{{カウント}}結果',
foundResult: '{{count}}件の結果',
forAdvanced: '上級ユーザー向け',
chooseAppType: 'アプリタイプを選択',
learnMore: '詳細情報',

View File

@ -43,7 +43,7 @@ const translation = {
log: 'ログ',
learnMore: '詳細はこちら',
params: 'パラメータ',
duplicate: '複',
duplicate: '複',
rename: '名前の変更',
audioSourceUnavailable: 'AudioSource が利用できません',
zoomIn: 'ズームインする',
@ -229,7 +229,7 @@ const translation = {
permanentlyDeleteButton: 'アカウントを完全に削除',
feedbackTitle: 'フィードバック',
feedbackLabel: 'アカウントを削除した理由を教えてください。',
feedbackPlaceholder: '意',
feedbackPlaceholder: '意',
sendVerificationButton: '確認コードの送信',
editWorkspaceInfo: 'ワークスペース情報を編集',
workspaceName: 'ワークスペース名',

View File

@ -2,7 +2,7 @@ const translation = {
category: {
extensions: '拡張機能',
all: 'すべて',
tools: '道具',
tools: 'ツール',
bundles: 'バンドル',
agents: 'エージェント戦略',
models: 'モデル',
@ -11,7 +11,7 @@ const translation = {
agent: 'エージェント戦略',
model: 'モデル',
bundle: 'バンドル',
tool: '道具',
tool: 'ツール',
extension: '拡張',
},
list: {
@ -60,7 +60,7 @@ const translation = {
uninstalledTitle: 'ツールがインストールされていません',
empty: 'ツールを追加するには「+」ボタンをクリックしてください。複数のツールを追加できます。',
paramsTip1: 'LLM 推論パラメータを制御します。',
toolLabel: '道具',
toolLabel: 'ツール',
unsupportedTitle: 'サポートされていないアクション',
toolSetting: 'ツール設定',
unsupportedMCPTool: '現在選択されているエージェント戦略プラグインのバージョンはMCPツールをサポートしていません。',

View File

@ -887,7 +887,7 @@ const translation = {
modelNotSelected: 'モデルが選択されていません',
toolNotAuthorizedTooltip: '{{tool}} 認可されていません',
toolNotInstallTooltip: '{{tool}}はインストールされていません',
tools: '道具',
tools: 'ツール',
learnMore: 'もっと学ぶ',
configureModel: 'モデルを設定する',
model: 'モデル',

View File

@ -90,12 +90,12 @@ const translation = {
noTemplateFound: '템플릿을 찾을 수 없습니다.',
completionShortDescription: '텍스트 생성 작업을 위한 AI 도우미',
learnMore: '더 알아보세요',
foundResults: '{{개수}} 결과',
foundResults: '{{count}} 결과',
agentShortDescription:
'추론 및 자율적인 도구 사용 기능이 있는 지능형 에이전트',
advancedShortDescription: '다중 대화를 위해 강화된 워크플로우',
noAppsFound: '앱을 찾을 수 없습니다.',
foundResult: '{{개수}} 결과',
foundResult: '{{count}} 결과',
completionUserDescription:
'간단한 구성으로 텍스트 생성 작업을 위한 AI 도우미를 빠르게 구축합니다.',
chatbotUserDescription:

View File

@ -80,7 +80,7 @@ const translation = {
appCreateDSLErrorPart1: 'Wykryto istotną różnicę w wersjach DSL. Wymuszenie importu może spowodować nieprawidłowe działanie aplikacji.',
noTemplateFoundTip: 'Spróbuj wyszukać za pomocą różnych słów kluczowych.',
noAppsFound: 'Nie znaleziono aplikacji',
foundResults: '{{liczba}} Wyniki',
foundResults: '{{count}} Wyniki',
noTemplateFound: 'Nie znaleziono szablonów',
chatbotUserDescription: 'Szybko zbuduj chatbota opartego na LLM z prostą konfiguracją. Możesz przełączyć się na Chatflow później.',
optional: 'Fakultatywny',
@ -91,7 +91,7 @@ const translation = {
completionShortDescription: 'Asystent AI do zadań generowania tekstu',
noIdeaTip: 'Nie masz pomysłów? Sprawdź nasze szablony',
forAdvanced: 'DLA ZAAWANSOWANYCH UŻYTKOWNIKÓW',
foundResult: '{{liczba}} Wynik',
foundResult: '{{count}} Wynik',
advancedShortDescription: 'Przepływ ulepszony dla wieloturowych czatów',
learnMore: 'Dowiedz się więcej',
chatbotShortDescription: 'Chatbot oparty na LLM z prostą konfiguracją',

View File

@ -84,8 +84,8 @@ const translation = {
advancedShortDescription: 'Flux de lucru îmbunătățit pentru conversații multi-tur',
advancedUserDescription: 'Flux de lucru cu funcții suplimentare de memorie și interfață de chatbot.',
noTemplateFoundTip: 'Încercați să căutați folosind cuvinte cheie diferite.',
foundResults: '{{număr}} Rezultatele',
foundResult: '{{număr}} Rezultat',
foundResults: '{{count}} Rezultatele',
foundResult: '{{count}} Rezultat',
noIdeaTip: 'Nicio idee? Consultați șabloanele noastre',
noAppsFound: 'Nu s-au găsit aplicații',
workflowShortDescription: 'Flux agentic pentru automatizări inteligente',

View File

@ -78,11 +78,11 @@ const translation = {
appCreateDSLErrorPart1: 'Обнаружена существенная разница в версиях DSL. Принудительный импорт может привести к сбою в работе приложения.',
learnMore: 'Подробнее',
forAdvanced: 'ДЛЯ ПРОДВИНУТЫХ ПОЛЬЗОВАТЕЛЕЙ',
foundResults: '{{Количество}} Результаты',
foundResults: '{{count}} Результаты',
optional: 'Необязательный',
chatbotShortDescription: 'Чат-бот на основе LLM с простой настройкой',
advancedShortDescription: 'Рабочий процесс, улучшенный для многоходовых чатов',
foundResult: '{{Количество}} Результат',
foundResult: '{{count}} Результат',
workflowShortDescription: 'Агентный поток для интеллектуальных автоматизаций',
advancedUserDescription: 'Рабочий процесс с дополнительными функциями памяти и интерфейсом чат-бота.',
noAppsFound: 'Приложения не найдены',

View File

@ -79,8 +79,8 @@ const translation = {
advancedShortDescription: 'Potek dela izboljšan za večkratne pogovore',
noAppsFound: 'Ni bilo najdenih aplikacij',
agentShortDescription: 'Inteligentni agent z razmišljanjem in avtonomno uporabo orodij',
foundResult: '{{štetje}} Rezultat',
foundResults: '{{štetje}} Rezultati',
foundResult: '{{count}} Rezultat',
foundResults: '{{count}} Rezultati',
noTemplateFoundTip: 'Poskusite iskati z različnimi ključnimi besedami.',
optional: 'Neobvezno',
forBeginners: 'Bolj osnovne vrste aplikacij',

View File

@ -73,7 +73,7 @@ const translation = {
appCreateDSLErrorPart4: 'เวอร์ชัน DSL ที่ระบบรองรับ:',
appCreateFailed: 'สร้างโปรเจกต์ไม่สําเร็จ',
learnMore: 'ศึกษาเพิ่มเติม',
foundResults: '{{นับ}} ผลลัพธ์',
foundResults: '{{count}} ผลลัพธ์',
noTemplateFoundTip: 'ลองค้นหาโดยใช้คีย์เวิร์ดอื่น',
chatbotShortDescription: 'แชทบอทที่ใช้ LLM พร้อมการตั้งค่าที่ง่ายดาย',
optional: 'เสริม',
@ -83,7 +83,7 @@ const translation = {
completionShortDescription: 'ผู้ช่วย AI สําหรับงานสร้างข้อความ',
agentUserDescription: 'ตัวแทนอัจฉริยะที่สามารถให้เหตุผลซ้ําๆ และใช้เครื่องมืออัตโนมัติเพื่อให้บรรลุเป้าหมายของงาน',
noIdeaTip: 'ไม่มีความคิด? ดูเทมเพลตของเรา',
foundResult: '{{นับ}} ผล',
foundResult: '{{count}} ผล',
noAppsFound: 'ไม่พบแอป',
workflowShortDescription: 'โฟลว์อัตโนมัติสำหรับระบบอัจฉริยะ',
forAdvanced: 'สําหรับผู้ใช้ขั้นสูง',

View File

@ -72,11 +72,11 @@ const translation = {
appCreateDSLErrorPart3: 'Geçerli uygulama DSL sürümü:',
appCreateDSLErrorTitle: 'Sürüm Uyumsuzluğu',
Confirm: 'Onaylamak',
foundResults: '{{sayı}} Sonuç -ları',
foundResults: '{{count}} Sonuç -ları',
noAppsFound: 'Uygulama bulunamadı',
chatbotUserDescription: 'Basit yapılandırmayla hızlı bir şekilde LLM tabanlı bir sohbet botu oluşturun. Daha sonra Chatflow\'a geçebilirsiniz.',
optional: 'Opsiyonel',
foundResult: '{{sayı}} Sonuç',
foundResult: '{{count}} Sonuç',
noTemplateFound: 'Şablon bulunamadı',
workflowUserDescription: 'Sürükle-bırak kolaylığıyla görsel olarak otonom yapay zeka iş akışları oluşturun.',
advancedUserDescription: 'Ek bellek özellikleri ve sohbet robotu arayüzü ile iş akışı.',

View File

@ -80,13 +80,13 @@ const translation = {
optional: 'Tùy chọn',
advancedShortDescription: 'Quy trình làm việc cho các cuộc đối thoại nhiều lượt phức tạp với bộ nhớ',
workflowUserDescription: 'Xây dựng trực quan quy trình AI tự động bằng kéo thả đơn giản.',
foundResults: '{{đếm}} Kết quả',
foundResults: '{{count}} Kết quả',
chatbotUserDescription: 'Nhanh chóng xây dựng chatbot dựa trên LLM với cấu hình đơn giản. Bạn có thể chuyển sang Chatflow sau.',
agentUserDescription: 'Một tác nhân thông minh có khả năng suy luận lặp đi lặp lại và sử dụng công cụ tự động để đạt được mục tiêu nhiệm vụ.',
noIdeaTip: 'Không có ý tưởng? Kiểm tra các mẫu của chúng tôi',
advancedUserDescription: 'Quy trình với tính năng bộ nhớ bổ sung và giao diện chatbot.',
forAdvanced: 'DÀNH CHO NGƯỜI DÙNG NÂNG CAO',
foundResult: '{{đếm}} Kết quả',
foundResult: '{{count}} Kết quả',
agentShortDescription: 'Quy trình nâng cao cho hội thoại nhiều lượt',
noTemplateFound: 'Không tìm thấy mẫu',
noAppsFound: 'Không tìm thấy ứng dụng nào',

View File

@ -21,8 +21,8 @@
"dev": "cross-env NODE_OPTIONS='--inspect' next dev",
"build": "next build",
"start": "cp -r .next/static .next/standalone/.next/static && cp -r public .next/standalone/public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next/standalone/server.js",
"lint": "pnpm eslint --cache --cache-location node_modules/.cache/eslint/.eslint-cache",
"lint-only-show-error": "pnpm eslint --cache --cache-location node_modules/.cache/eslint/.eslint-cache --quiet",
"lint": "pnpx oxlint && pnpm eslint --cache --cache-location node_modules/.cache/eslint/.eslint-cache",
"lint-only-show-error": "pnpx oxlint && pnpm eslint --cache --cache-location node_modules/.cache/eslint/.eslint-cache --quiet",
"fix": "next lint --fix",
"eslint-fix": "eslint --cache --cache-location node_modules/.cache/eslint/.eslint-cache --fix",
"eslint-fix-only-show-error": "eslint --cache --cache-location node_modules/.cache/eslint/.eslint-cache --fix --quiet",
@ -85,7 +85,6 @@
"elkjs": "^0.9.3",
"emoji-mart": "^5.5.2",
"fast-deep-equal": "^3.1.3",
"globals": "^15.11.0",
"html-to-image": "1.11.11",
"i18next": "^23.16.4",
"i18next-resources-to-backend": "^1.2.1",
@ -199,11 +198,13 @@
"cross-env": "^7.0.3",
"eslint": "^9.20.1",
"eslint-config-next": "~15.3.5",
"eslint-plugin-oxlint": "^1.6.0",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.19",
"eslint-plugin-sonarjs": "^3.0.2",
"eslint-plugin-storybook": "^0.11.2",
"eslint-plugin-tailwindcss": "^3.18.0",
"globals": "^15.11.0",
"husky": "^9.1.6",
"jest": "^29.7.0",
"lint-staged": "^15.2.10",

21
web/pnpm-lock.yaml generated
View File

@ -182,9 +182,6 @@ importers:
fast-deep-equal:
specifier: ^3.1.3
version: 3.1.3
globals:
specifier: ^15.11.0
version: 15.15.0
html-to-image:
specifier: 1.11.11
version: 1.11.11
@ -519,6 +516,9 @@ importers:
eslint-config-next:
specifier: ~15.3.5
version: 15.3.5(eslint@9.31.0(jiti@1.21.7))(typescript@5.8.3)
eslint-plugin-oxlint:
specifier: ^1.6.0
version: 1.6.0
eslint-plugin-react-hooks:
specifier: ^5.1.0
version: 5.2.0(eslint@9.31.0(jiti@1.21.7))
@ -534,6 +534,9 @@ importers:
eslint-plugin-tailwindcss:
specifier: ^3.18.0
version: 3.18.2(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@18.15.0)(typescript@5.8.3)))
globals:
specifier: ^15.11.0
version: 15.15.0
husky:
specifier: ^9.1.6
version: 9.1.7
@ -4775,6 +4778,9 @@ packages:
resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==}
engines: {node: '>=5.0.0'}
eslint-plugin-oxlint@1.6.0:
resolution: {integrity: sha512-DH5p3sCf0nIAPscl3yGnBWXXraV0bdl66hpLxvfnabvg/GzpgXf+pOCWpGK3qDb0+AIUkh1R/7A8GkOXtlj0oA==}
eslint-plugin-perfectionist@4.15.0:
resolution: {integrity: sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==}
engines: {node: ^18.0.0 || >=20.0.0}
@ -5832,6 +5838,9 @@ packages:
resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
jsonc-parser@3.3.1:
resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
jsonfile@6.1.0:
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
@ -13169,6 +13178,10 @@ snapshots:
eslint-plugin-no-only-tests@3.3.0: {}
eslint-plugin-oxlint@1.6.0:
dependencies:
jsonc-parser: 3.3.1
eslint-plugin-perfectionist@4.15.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.8.3):
dependencies:
'@typescript-eslint/types': 8.37.0
@ -14650,6 +14663,8 @@ snapshots:
espree: 9.6.1
semver: 7.7.2
jsonc-parser@3.3.1: {}
jsonfile@6.1.0:
dependencies:
universalify: 2.0.1

View File

@ -88,7 +88,7 @@ export const logout: Fetcher<CommonResponse, { url: string; params: Record<strin
return get<CommonResponse>(url, params)
}
export const fetchLanggeniusVersion: Fetcher<LangGeniusVersionResponse, { url: string; params: Record<string, any> }> = ({ url, params }) => {
export const fetchLangGeniusVersion: Fetcher<LangGeniusVersionResponse, { url: string; params: Record<string, any> }> = ({ url, params }) => {
return get<LangGeniusVersionResponse>(url, { params })
}