Merge branch 'langgenius:main' into fix/manual-metadata-conditon-in-agent

pull/20362/head
suntp 12 months ago committed by GitHub
commit 3a1a8c4a8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,25 +1,23 @@
# Summary > [!IMPORTANT]
>
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. > 1. Make sure you have read our [contribution guidelines](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md)
> 2. Ensure there is an associated issue and you have been assigned to it
> 3. Use the correct syntax to link this PR: `Fixes #<issue number>`.
> [!Tip] ## Summary
> Close issue syntax: `Fixes #<issue number>` or `Resolves #<issue number>`, see [documentation](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) for more details.
<!-- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. -->
# Screenshots ## Screenshots
| Before | After | | Before | After |
|--------|-------| |--------|-------|
| ... | ... | | ... | ... |
# Checklist ## Checklist
> [!IMPORTANT]
> Please review the checklist below before submitting your pull request.
- [ ] This change requires a documentation update, included: [Dify Document](https://github.com/langgenius/dify-docs) - [ ] This change requires a documentation update, included: [Dify Document](https://github.com/langgenius/dify-docs)
- [x] I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!) - [x] I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
- [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change. - [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
- [x] I've updated the documentation accordingly. - [x] I've updated the documentation accordingly.
- [x] I ran `dev/reformat`(backend) and `cd web && npx lint-staged`(frontend) to appease the lint gods - [x] I ran `dev/reformat`(backend) and `cd web && npx lint-staged`(frontend) to appease the lint gods

@ -9,13 +9,13 @@ from fields.annotation_fields import (
annotation_fields, annotation_fields,
) )
from libs.login import current_user from libs.login import current_user
from models.model import App, EndUser from models.model import App
from services.annotation_service import AppAnnotationService from services.annotation_service import AppAnnotationService
class AnnotationReplyActionApi(Resource): class AnnotationReplyActionApi(Resource):
@validate_app_token @validate_app_token
def post(self, app_model: App, end_user: EndUser, action): def post(self, app_model: App, action):
parser = reqparse.RequestParser() parser = reqparse.RequestParser()
parser.add_argument("score_threshold", required=True, type=float, location="json") parser.add_argument("score_threshold", required=True, type=float, location="json")
parser.add_argument("embedding_provider_name", required=True, type=str, location="json") parser.add_argument("embedding_provider_name", required=True, type=str, location="json")
@ -32,7 +32,7 @@ class AnnotationReplyActionApi(Resource):
class AnnotationReplyActionStatusApi(Resource): class AnnotationReplyActionStatusApi(Resource):
@validate_app_token @validate_app_token
def get(self, app_model: App, end_user: EndUser, job_id, action): def get(self, app_model: App, job_id, action):
job_id = str(job_id) job_id = str(job_id)
app_annotation_job_key = "{}_app_annotation_job_{}".format(action, str(job_id)) app_annotation_job_key = "{}_app_annotation_job_{}".format(action, str(job_id))
cache_result = redis_client.get(app_annotation_job_key) cache_result = redis_client.get(app_annotation_job_key)
@ -50,7 +50,7 @@ class AnnotationReplyActionStatusApi(Resource):
class AnnotationListApi(Resource): class AnnotationListApi(Resource):
@validate_app_token @validate_app_token
def get(self, app_model: App, end_user: EndUser): def get(self, app_model: App):
page = request.args.get("page", default=1, type=int) page = request.args.get("page", default=1, type=int)
limit = request.args.get("limit", default=20, type=int) limit = request.args.get("limit", default=20, type=int)
keyword = request.args.get("keyword", default="", type=str) keyword = request.args.get("keyword", default="", type=str)
@ -67,7 +67,7 @@ class AnnotationListApi(Resource):
@validate_app_token @validate_app_token
@marshal_with(annotation_fields) @marshal_with(annotation_fields)
def post(self, app_model: App, end_user: EndUser): def post(self, app_model: App):
parser = reqparse.RequestParser() parser = reqparse.RequestParser()
parser.add_argument("question", required=True, type=str, location="json") parser.add_argument("question", required=True, type=str, location="json")
parser.add_argument("answer", required=True, type=str, location="json") parser.add_argument("answer", required=True, type=str, location="json")
@ -79,7 +79,7 @@ class AnnotationListApi(Resource):
class AnnotationUpdateDeleteApi(Resource): class AnnotationUpdateDeleteApi(Resource):
@validate_app_token @validate_app_token
@marshal_with(annotation_fields) @marshal_with(annotation_fields)
def put(self, app_model: App, end_user: EndUser, annotation_id): def put(self, app_model: App, annotation_id):
if not current_user.is_editor: if not current_user.is_editor:
raise Forbidden() raise Forbidden()
@ -92,7 +92,7 @@ class AnnotationUpdateDeleteApi(Resource):
return annotation return annotation
@validate_app_token @validate_app_token
def delete(self, app_model: App, end_user: EndUser, annotation_id): def delete(self, app_model: App, annotation_id):
if not current_user.is_editor: if not current_user.is_editor:
raise Forbidden() raise Forbidden()

@ -63,7 +63,7 @@ class CotAgentRunner(BaseAgentRunner, ABC):
self._instruction = self._fill_in_inputs_from_external_data_tools(instruction, inputs) self._instruction = self._fill_in_inputs_from_external_data_tools(instruction, inputs)
iteration_step = 1 iteration_step = 1
max_iteration_steps = min(app_config.agent.max_iteration if app_config.agent else 5, 5) + 1 max_iteration_steps = min(app_config.agent.max_iteration, 99) + 1
# convert tools into ModelRuntime Tool format # convert tools into ModelRuntime Tool format
tool_instances, prompt_messages_tools = self._init_prompt_tools() tool_instances, prompt_messages_tools = self._init_prompt_tools()

@ -82,7 +82,7 @@ class AgentEntity(BaseModel):
strategy: Strategy strategy: Strategy
prompt: Optional[AgentPromptEntity] = None prompt: Optional[AgentPromptEntity] = None
tools: Optional[list[AgentToolEntity]] = None tools: Optional[list[AgentToolEntity]] = None
max_iteration: int = 5 max_iteration: int = 10
class AgentInvokeMessage(ToolInvokeMessage): class AgentInvokeMessage(ToolInvokeMessage):

@ -48,7 +48,7 @@ class FunctionCallAgentRunner(BaseAgentRunner):
assert app_config.agent assert app_config.agent
iteration_step = 1 iteration_step = 1
max_iteration_steps = min(app_config.agent.max_iteration, 5) + 1 max_iteration_steps = min(app_config.agent.max_iteration, 99) + 1
# continue to run until there is not any tool call # continue to run until there is not any tool call
function_call_state = True function_call_state = True

@ -75,7 +75,7 @@ class AgentConfigManager:
strategy=strategy, strategy=strategy,
prompt=agent_prompt_entity, prompt=agent_prompt_entity,
tools=agent_tools, tools=agent_tools,
max_iteration=agent_dict.get("max_iteration", 5), max_iteration=agent_dict.get("max_iteration", 10),
) )
return None return None

@ -58,6 +58,7 @@ class PluginModelBackwardsInvocation(BaseBackwardsInvocation):
LLMNode.deduct_llm_quota( LLMNode.deduct_llm_quota(
tenant_id=tenant.id, model_instance=model_instance, usage=chunk.delta.usage tenant_id=tenant.id, model_instance=model_instance, usage=chunk.delta.usage
) )
chunk.prompt_messages = []
yield chunk yield chunk
return handle() return handle()
@ -68,7 +69,7 @@ class PluginModelBackwardsInvocation(BaseBackwardsInvocation):
def handle_non_streaming(response: LLMResult) -> Generator[LLMResultChunk, None, None]: def handle_non_streaming(response: LLMResult) -> Generator[LLMResultChunk, None, None]:
yield LLMResultChunk( yield LLMResultChunk(
model=response.model, model=response.model,
prompt_messages=response.prompt_messages, prompt_messages=[],
system_fingerprint=response.system_fingerprint, system_fingerprint=response.system_fingerprint,
delta=LLMResultChunkDelta( delta=LLMResultChunkDelta(
index=0, index=0,

@ -6,6 +6,7 @@ from typing import TypeVar
import requests import requests
from pydantic import BaseModel from pydantic import BaseModel
from requests.exceptions import HTTPError
from yarl import URL from yarl import URL
from configs import dify_config from configs import dify_config
@ -136,12 +137,31 @@ class BasePluginClient:
""" """
Make a request to the plugin daemon inner API and return the response as a model. Make a request to the plugin daemon inner API and return the response as a model.
""" """
try:
response = self._request(method, path, headers, data, params, files) response = self._request(method, path, headers, data, params, files)
response.raise_for_status()
except HTTPError as e:
msg = f"Failed to request plugin daemon, status: {e.response.status_code}, url: {path}"
logging.exception(msg)
raise e
except Exception as e:
msg = f"Failed to request plugin daemon, url: {path}"
logging.exception(msg)
raise ValueError(msg) from e
try:
json_response = response.json() json_response = response.json()
if transformer: if transformer:
json_response = transformer(json_response) json_response = transformer(json_response)
rep = PluginDaemonBasicResponse[type](**json_response) # type: ignore rep = PluginDaemonBasicResponse[type](**json_response) # type: ignore
except Exception:
msg = (
f"Failed to parse response from plugin daemon to PluginDaemonBasicResponse [{str(type.__name__)}],"
f" url: {path}"
)
logging.exception(msg)
raise ValueError(msg)
if rep.code != 0: if rep.code != 0:
try: try:
error = PluginDaemonError(**json.loads(rep.message)) error = PluginDaemonError(**json.loads(rep.message))

@ -802,7 +802,7 @@ MAX_TOOLS_NUM=10
MAX_PARALLEL_LIMIT=10 MAX_PARALLEL_LIMIT=10
# The maximum number of iterations for agent setting # The maximum number of iterations for agent setting
MAX_ITERATIONS_NUM=5 MAX_ITERATIONS_NUM=99
# ------------------------------ # ------------------------------
# Environment Variables for web Service # Environment Variables for web Service

@ -75,7 +75,7 @@ services:
LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100} LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100}
MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10} MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10}
MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10} MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10}
MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-5} MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-99}
ENABLE_WEBSITE_JINAREADER: ${ENABLE_WEBSITE_JINAREADER:-true} ENABLE_WEBSITE_JINAREADER: ${ENABLE_WEBSITE_JINAREADER:-true}
ENABLE_WEBSITE_FIRECRAWL: ${ENABLE_WEBSITE_FIRECRAWL:-true} ENABLE_WEBSITE_FIRECRAWL: ${ENABLE_WEBSITE_FIRECRAWL:-true}
ENABLE_WEBSITE_WATERCRAWL: ${ENABLE_WEBSITE_WATERCRAWL:-true} ENABLE_WEBSITE_WATERCRAWL: ${ENABLE_WEBSITE_WATERCRAWL:-true}

@ -354,7 +354,7 @@ x-shared-env: &shared-api-worker-env
LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100} LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100}
MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10} MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10}
MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10} MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10}
MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-5} MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-99}
TEXT_GENERATION_TIMEOUT_MS: ${TEXT_GENERATION_TIMEOUT_MS:-60000} TEXT_GENERATION_TIMEOUT_MS: ${TEXT_GENERATION_TIMEOUT_MS:-60000}
PGUSER: ${PGUSER:-${DB_USERNAME}} PGUSER: ${PGUSER:-${DB_USERNAME}}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-${DB_PASSWORD}} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-${DB_PASSWORD}}
@ -574,7 +574,7 @@ services:
LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100} LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100}
MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10} MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10}
MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10} MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10}
MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-5} MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-99}
ENABLE_WEBSITE_JINAREADER: ${ENABLE_WEBSITE_JINAREADER:-true} ENABLE_WEBSITE_JINAREADER: ${ENABLE_WEBSITE_JINAREADER:-true}
ENABLE_WEBSITE_FIRECRAWL: ${ENABLE_WEBSITE_FIRECRAWL:-true} ENABLE_WEBSITE_FIRECRAWL: ${ENABLE_WEBSITE_FIRECRAWL:-true}
ENABLE_WEBSITE_WATERCRAWL: ${ENABLE_WEBSITE_WATERCRAWL:-true} ENABLE_WEBSITE_WATERCRAWL: ${ENABLE_WEBSITE_WATERCRAWL:-true}

@ -109,7 +109,7 @@ EXPOSE_PLUGIN_DEBUGGING_HOST=localhost
EXPOSE_PLUGIN_DEBUGGING_PORT=5003 EXPOSE_PLUGIN_DEBUGGING_PORT=5003
PLUGIN_DIFY_INNER_API_KEY=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1 PLUGIN_DIFY_INNER_API_KEY=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1
PLUGIN_DIFY_INNER_API_URL=http://api:5001 PLUGIN_DIFY_INNER_API_URL=http://host.docker.internal:5001
MARKETPLACE_ENABLED=true MARKETPLACE_ENABLED=true
MARKETPLACE_API_URL=https://marketplace.dify.ai MARKETPLACE_API_URL=https://marketplace.dify.ai

@ -50,7 +50,7 @@ NEXT_PUBLIC_MAX_TOOLS_NUM=10
NEXT_PUBLIC_MAX_PARALLEL_LIMIT=10 NEXT_PUBLIC_MAX_PARALLEL_LIMIT=10
# The maximum number of iterations for agent setting # The maximum number of iterations for agent setting
NEXT_PUBLIC_MAX_ITERATIONS_NUM=5 NEXT_PUBLIC_MAX_ITERATIONS_NUM=99
NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER=true NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER=true
NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL=true NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL=true

@ -6,10 +6,12 @@ import Button from '../components/base/button'
import Avatar from './avatar' import Avatar from './avatar'
import DifyLogo from '@/app/components/base/logo/dify-logo' import DifyLogo from '@/app/components/base/logo/dify-logo'
import { useCallback } from 'react' import { useCallback } from 'react'
import { useGlobalPublicStore } from '@/context/global-public-context'
const Header = () => { const Header = () => {
const { t } = useTranslation() const { t } = useTranslation()
const router = useRouter() const router = useRouter()
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
const back = useCallback(() => { const back = useCallback(() => {
router.back() router.back()
@ -19,7 +21,13 @@ const Header = () => {
<div className='flex flex-1 items-center justify-between px-4'> <div className='flex flex-1 items-center justify-between px-4'>
<div className='flex items-center gap-3'> <div className='flex items-center gap-3'>
<div className='flex cursor-pointer items-center' onClick={back}> <div className='flex cursor-pointer items-center' onClick={back}>
<DifyLogo /> {systemFeatures.branding.enabled && systemFeatures.branding.login_page_logo
? <img
src={systemFeatures.branding.login_page_logo}
className='block h-[22px] w-auto object-contain'
alt='Dify logo'
/>
: <DifyLogo />}
</div> </div>
<div className='h-4 w-[1px] origin-center rotate-[11.31deg] bg-divider-regular' /> <div className='h-4 w-[1px] origin-center rotate-[11.31deg] bg-divider-regular' />
<p className='title-3xl-semi-bold relative mt-[-2px] text-text-primary'>{t('common.account.account')}</p> <p className='title-3xl-semi-bold relative mt-[-2px] text-text-primary'>{t('common.account.account')}</p>

@ -148,10 +148,12 @@ const Sidebar = ({ isPanel }: Props) => {
'flex shrink-0 items-center gap-1.5 px-1', 'flex shrink-0 items-center gap-1.5 px-1',
)}> )}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div> <div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{systemFeatures.branding.enabled ? ( {
<img src={systemFeatures.branding.login_page_logo} alt='logo' className='block h-5 w-auto' /> systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
) : ( ? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
<DifyLogo size='small' />) : appData?.custom_config?.replace_webapp_logo
? <img src={`${appData?.custom_config?.replace_webapp_logo}`} alt='logo' className='block h-5 w-auto' />
: <DifyLogo size='small' />
} }
</div> </div>
)} )}

@ -13,6 +13,7 @@ import Divider from '@/app/components/base/divider'
import ViewFormDropdown from '@/app/components/base/chat/embedded-chatbot/inputs-form/view-form-dropdown' import ViewFormDropdown from '@/app/components/base/chat/embedded-chatbot/inputs-form/view-form-dropdown'
import DifyLogo from '@/app/components/base/logo/dify-logo' import DifyLogo from '@/app/components/base/logo/dify-logo'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useGlobalPublicStore } from '@/context/global-public-context'
export type IHeaderProps = { export type IHeaderProps = {
isMobile?: boolean isMobile?: boolean
@ -42,6 +43,7 @@ const Header: FC<IHeaderProps> = ({
const [parentOrigin, setParentOrigin] = useState('') const [parentOrigin, setParentOrigin] = useState('')
const [showToggleExpandButton, setShowToggleExpandButton] = useState(false) const [showToggleExpandButton, setShowToggleExpandButton] = useState(false)
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
const handleMessageReceived = useCallback((event: MessageEvent) => { const handleMessageReceived = useCallback((event: MessageEvent) => {
let currentParentOrigin = parentOrigin let currentParentOrigin = parentOrigin
@ -85,12 +87,13 @@ const Header: FC<IHeaderProps> = ({
'flex shrink-0 items-center gap-1.5 px-2', 'flex shrink-0 items-center gap-1.5 px-2',
)}> )}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div> <div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{appData?.custom_config?.replace_webapp_logo && ( {
<img src={appData?.custom_config?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' /> systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
)} ? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
{!appData?.custom_config?.replace_webapp_logo && ( : appData?.custom_config?.replace_webapp_logo
<DifyLogo size='small' /> ? <img src={`${appData?.custom_config?.replace_webapp_logo}`} alt='logo' className='block h-5 w-auto' />
)} : <DifyLogo size='small' />
}
</div> </div>
)} )}
</div> </div>

@ -22,6 +22,7 @@ import ChatWrapper from '@/app/components/base/chat/embedded-chatbot/chat-wrappe
import DifyLogo from '@/app/components/base/logo/dify-logo' import DifyLogo from '@/app/components/base/logo/dify-logo'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import useDocumentTitle from '@/hooks/use-document-title' import useDocumentTitle from '@/hooks/use-document-title'
import { useGlobalPublicStore } from '@/context/global-public-context'
const Chatbot = () => { const Chatbot = () => {
const { const {
@ -37,6 +38,7 @@ const Chatbot = () => {
themeBuilder, themeBuilder,
} = useEmbeddedChatbotContext() } = useEmbeddedChatbotContext()
const { t } = useTranslation() const { t } = useTranslation()
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
const customConfig = appData?.custom_config const customConfig = appData?.custom_config
const site = appData?.site const site = appData?.site
@ -115,12 +117,13 @@ const Chatbot = () => {
'flex shrink-0 items-center gap-1.5 px-2', 'flex shrink-0 items-center gap-1.5 px-2',
)}> )}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div> <div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{appData?.custom_config?.replace_webapp_logo && ( {
<img src={appData?.custom_config?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' /> systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
)} ? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
{!appData?.custom_config?.replace_webapp_logo && ( : appData?.custom_config?.replace_webapp_logo
<DifyLogo size='small' /> ? <img src={`${appData?.custom_config?.replace_webapp_logo}`} alt='logo' className='block h-5 w-auto' />
)} : <DifyLogo size='small' />
}
</div> </div>
)} )}
</div> </div>

@ -3,7 +3,6 @@ import type { FC } from 'react'
import classNames from '@/utils/classnames' import classNames from '@/utils/classnames'
import useTheme from '@/hooks/use-theme' import useTheme from '@/hooks/use-theme'
import { basePath } from '@/utils/var' import { basePath } from '@/utils/var'
import { useGlobalPublicStore } from '@/context/global-public-context'
export type LogoStyle = 'default' | 'monochromeWhite' export type LogoStyle = 'default' | 'monochromeWhite'
export const logoPathMap: Record<LogoStyle, string> = { export const logoPathMap: Record<LogoStyle, string> = {
@ -32,18 +31,12 @@ const DifyLogo: FC<DifyLogoProps> = ({
}) => { }) => {
const { theme } = useTheme() const { theme } = useTheme()
const themedStyle = (theme === 'dark' && style === 'default') ? 'monochromeWhite' : style const themedStyle = (theme === 'dark' && style === 'default') ? 'monochromeWhite' : style
const { systemFeatures } = useGlobalPublicStore()
const hasBrandingLogo = Boolean(systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo)
let src = `${basePath}${logoPathMap[themedStyle]}`
if (hasBrandingLogo)
src = systemFeatures.branding.workspace_logo
return ( return (
<img <img
src={src} src={`${basePath}${logoPathMap[themedStyle]}`}
className={classNames('block object-contain', logoSizeMap[size], hasBrandingLogo && 'w-auto', className)} className={classNames('block object-contain', logoSizeMap[size], className)}
alt={hasBrandingLogo ? 'Logo' : 'Dify logo'} alt='Dify logo'
/> />
) )
} }

@ -24,6 +24,7 @@ import {
} from '@/service/common' } from '@/service/common'
import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useGlobalPublicStore } from '@/context/global-public-context'
const ALLOW_FILE_EXTENSIONS = ['svg', 'png'] const ALLOW_FILE_EXTENSIONS = ['svg', 'png']
@ -39,6 +40,7 @@ const CustomWebAppBrand = () => {
const [fileId, setFileId] = useState('') const [fileId, setFileId] = useState('')
const [imgKey, setImgKey] = useState(Date.now()) const [imgKey, setImgKey] = useState(Date.now())
const [uploadProgress, setUploadProgress] = useState(0) const [uploadProgress, setUploadProgress] = useState(0)
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
const isSandbox = enableBilling && plan.type === Plan.sandbox const isSandbox = enableBilling && plan.type === Plan.sandbox
const uploading = uploadProgress > 0 && uploadProgress < 100 const uploading = uploadProgress > 0 && uploadProgress < 100
const webappLogo = currentWorkspace.custom_config?.replace_webapp_logo || '' const webappLogo = currentWorkspace.custom_config?.replace_webapp_logo || ''
@ -128,7 +130,7 @@ const CustomWebAppBrand = () => {
<div className='system-xs-regular text-text-tertiary'>{t('custom.webapp.changeLogoTip')}</div> <div className='system-xs-regular text-text-tertiary'>{t('custom.webapp.changeLogoTip')}</div>
</div> </div>
<div className='flex items-center'> <div className='flex items-center'>
{(uploadDisabled || (!webappLogo && !webappBrandRemoved)) && ( {(!uploadDisabled && webappLogo && !webappBrandRemoved) && (
<> <>
<Button <Button
variant='ghost' variant='ghost'
@ -244,7 +246,10 @@ const CustomWebAppBrand = () => {
{!webappBrandRemoved && ( {!webappBrandRemoved && (
<> <>
<div className='system-2xs-medium-uppercase text-text-tertiary'>POWERED BY</div> <div className='system-2xs-medium-uppercase text-text-tertiary'>POWERED BY</div>
{webappLogo {
systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
: webappLogo
? <img src={`${webappLogo}?hash=${imgKey}`} alt='logo' className='block h-5 w-auto' /> ? <img src={`${webappLogo}?hash=${imgKey}`} alt='logo' className='block h-5 w-auto' />
: <DifyLogo size='small' /> : <DifyLogo size='small' />
} }
@ -303,7 +308,10 @@ const CustomWebAppBrand = () => {
{!webappBrandRemoved && ( {!webappBrandRemoved && (
<> <>
<div className='system-2xs-medium-uppercase text-text-tertiary'>POWERED BY</div> <div className='system-2xs-medium-uppercase text-text-tertiary'>POWERED BY</div>
{webappLogo {
systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
: webappLogo
? <img src={`${webappLogo}?hash=${imgKey}`} alt='logo' className='block h-5 w-auto' /> ? <img src={`${webappLogo}?hash=${imgKey}`} alt='logo' className='block h-5 w-auto' />
: <DifyLogo size='small' /> : <DifyLogo size='small' />
} }

@ -9,6 +9,7 @@ import type { LangGeniusVersionResponse } from '@/models/common'
import { IS_CE_EDITION } from '@/config' import { IS_CE_EDITION } from '@/config'
import DifyLogo from '@/app/components/base/logo/dify-logo' import DifyLogo from '@/app/components/base/logo/dify-logo'
import { noop } from 'lodash-es' import { noop } from 'lodash-es'
import { useGlobalPublicStore } from '@/context/global-public-context'
type IAccountSettingProps = { type IAccountSettingProps = {
langeniusVersionInfo: LangGeniusVersionResponse langeniusVersionInfo: LangGeniusVersionResponse
@ -21,6 +22,7 @@ export default function AccountAbout({
}: IAccountSettingProps) { }: IAccountSettingProps) {
const { t } = useTranslation() const { t } = useTranslation()
const isLatest = langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version const isLatest = langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
return ( return (
<Modal <Modal
@ -33,7 +35,14 @@ export default function AccountAbout({
<RiCloseLine className='h-4 w-4 text-text-tertiary' /> <RiCloseLine className='h-4 w-4 text-text-tertiary' />
</div> </div>
<div className='flex flex-col items-center gap-4 py-8'> <div className='flex flex-col items-center gap-4 py-8'>
<DifyLogo size='large' className='mx-auto' /> {systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img
src={systemFeatures.branding.workspace_logo}
className='block h-7 w-auto object-contain'
alt='logo'
/>
: <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 {langeniusVersionInfo?.current_version}</div>
<div className='flex flex-col items-center gap-2 text-center text-xs font-normal text-text-secondary'> <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>© {dayjs().year()} LangGenius, Inc., Contributors.</div>

@ -21,6 +21,7 @@ import { useModalContext } from '@/context/modal-context'
import PlanBadge from './plan-badge' import PlanBadge from './plan-badge'
import LicenseNav from './license-env' import LicenseNav from './license-env'
import { Plan } from '../billing/type' import { Plan } from '../billing/type'
import { useGlobalPublicStore } from '@/context/global-public-context'
const navClassName = ` const navClassName = `
flex items-center relative mr-0 sm:mr-3 px-3 h-8 rounded-xl flex items-center relative mr-0 sm:mr-3 px-3 h-8 rounded-xl
@ -36,6 +37,7 @@ const Header = () => {
const [isShowNavMenu, { toggle, setFalse: hideNavMenu }] = useBoolean(false) const [isShowNavMenu, { toggle, setFalse: hideNavMenu }] = useBoolean(false)
const { enableBilling, plan } = useProviderContext() const { enableBilling, plan } = useProviderContext()
const { setShowPricingModal, setShowAccountSettingModal } = useModalContext() const { setShowPricingModal, setShowAccountSettingModal } = useModalContext()
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
const isFreePlan = plan.type === Plan.sandbox const isFreePlan = plan.type === Plan.sandbox
const handlePlanClick = useCallback(() => { const handlePlanClick = useCallback(() => {
if (isFreePlan) if (isFreePlan)
@ -61,7 +63,13 @@ const Header = () => {
!isMobile !isMobile
&& <div className='flex shrink-0 items-center gap-1.5 self-stretch pl-3'> && <div className='flex shrink-0 items-center gap-1.5 self-stretch pl-3'>
<Link href="/apps" className='flex h-8 shrink-0 items-center justify-center gap-2 px-0.5'> <Link href="/apps" className='flex h-8 shrink-0 items-center justify-center gap-2 px-0.5'>
<DifyLogo /> {systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img
src={systemFeatures.branding.workspace_logo}
className='block h-[22px] w-auto object-contain'
alt='logo'
/>
: <DifyLogo />}
</Link> </Link>
<div className='font-light text-divider-deep'>/</div> <div className='font-light text-divider-deep'>/</div>
<div className='flex items-center gap-0.5'> <div className='flex items-center gap-0.5'>
@ -76,7 +84,13 @@ const Header = () => {
{isMobile && ( {isMobile && (
<div className='flex'> <div className='flex'>
<Link href="/apps" className='mr-4 flex items-center'> <Link href="/apps" className='mr-4 flex items-center'>
<DifyLogo /> {systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img
src={systemFeatures.branding.workspace_logo}
className='block h-[22px] w-auto object-contain'
alt='logo'
/>
: <DifyLogo />}
</Link> </Link>
<div className='font-light text-divider-deep'>/</div> <div className='font-light text-divider-deep'>/</div>
{enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />} {enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />}

@ -641,11 +641,13 @@ const TextGeneration: FC<IMainProps> = ({
!isPC && resultExisted && 'rounded-b-2xl border-b-[0.5px] border-divider-regular', !isPC && resultExisted && 'rounded-b-2xl border-b-[0.5px] border-divider-regular',
)}> )}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div> <div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{systemFeatures.branding.enabled ? ( {
<img src={systemFeatures.branding.login_page_logo} alt='logo' className='block h-5 w-auto' /> systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
) : ( ? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
<DifyLogo size='small' /> : customConfig?.replace_webapp_logo
)} ? <img src={`${customConfig?.replace_webapp_logo}`} alt='logo' className='block h-5 w-auto' />
: <DifyLogo size='small' />
}
</div> </div>
)} )}
</div> </div>

@ -7,6 +7,7 @@ import { languages } from '@/i18n/language'
import type { Locale } from '@/i18n' import type { Locale } from '@/i18n'
import I18n from '@/context/i18n' import I18n from '@/context/i18n'
import dynamic from 'next/dynamic' import dynamic from 'next/dynamic'
import { useGlobalPublicStore } from '@/context/global-public-context'
// Avoid rendering the logo and theme selector on the server // Avoid rendering the logo and theme selector on the server
const DifyLogo = dynamic(() => import('@/app/components/base/logo/dify-logo'), { const DifyLogo = dynamic(() => import('@/app/components/base/logo/dify-logo'), {
@ -20,10 +21,17 @@ const ThemeSelector = dynamic(() => import('@/app/components/base/theme-selector
const Header = () => { const Header = () => {
const { locale, setLocaleOnClient } = useContext(I18n) const { locale, setLocaleOnClient } = useContext(I18n)
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
return ( return (
<div className='flex w-full items-center justify-between p-6'> <div className='flex w-full items-center justify-between p-6'>
<DifyLogo size='large' /> {systemFeatures.branding.enabled && systemFeatures.branding.login_page_logo
? <img
src={systemFeatures.branding.login_page_logo}
className='block h-7 w-auto object-contain'
alt='logo'
/>
: <DifyLogo size='large' />}
<div className='flex items-center gap-1'> <div className='flex items-center gap-1'>
<Select <Select
value={locale} value={locale}

@ -173,7 +173,7 @@ export const MAX_TOOLS_NUM = maxToolsNum
export const DEFAULT_AGENT_SETTING = { export const DEFAULT_AGENT_SETTING = {
enabled: false, enabled: false,
max_iteration: 5, max_iteration: 10,
strategy: AgentStrategy.functionCall, strategy: AgentStrategy.functionCall,
tools: [], tools: [],
} }
@ -295,7 +295,7 @@ else if (globalThis.document?.body?.getAttribute('data-public-loop-node-max-coun
export const LOOP_NODE_MAX_COUNT = loopNodeMaxCount export const LOOP_NODE_MAX_COUNT = loopNodeMaxCount
let maxIterationsNum = 5 let maxIterationsNum = 99
if (process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM && process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM !== '') 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) maxIterationsNum = Number.parseInt(process.env.NEXT_PUBLIC_MAX_ITERATIONS_NUM)

Loading…
Cancel
Save