Unverified Commit dbfc79d7 authored by John Wang's avatar John Wang Committed by GitHub

Merge branch 'main' into feat/claude-api-support

parents 50615341 51038990
......@@ -2,6 +2,8 @@
import os
from datetime import datetime
from werkzeug.exceptions import Forbidden
if not os.environ.get("DEBUG") or os.environ.get("DEBUG").lower() != 'true':
from gevent import monkey
monkey.patch_all()
......@@ -27,7 +29,7 @@ from events import event_handlers
import core
from config import Config, CloudEditionConfig
from commands import register_commands
from models.account import TenantAccountJoin
from models.account import TenantAccountJoin, AccountStatus
from models.model import Account, EndUser, App
import warnings
......@@ -101,6 +103,9 @@ def load_user(user_id):
account = db.session.query(Account).filter(Account.id == account_id).first()
if account:
if account.status == AccountStatus.BANNED.value or account.status == AccountStatus.CLOSED.value:
raise Forbidden('Account is banned or closed.')
workspace_id = session.get('workspace_id')
if workspace_id:
tenant_account_join = db.session.query(TenantAccountJoin).filter(
......
......@@ -53,6 +53,7 @@ DEFAULTS = {
'DEFAULT_LLM_PROVIDER': 'openai',
'OPENAI_HOSTED_QUOTA_LIMIT': 200,
'ANTHROPIC_HOSTED_QUOTA_LIMIT': 1000,
'TENANT_DOCUMENT_COUNT': 100
}
......@@ -213,6 +214,8 @@ class Config:
self.NOTION_INTERNAL_SECRET = get_env('NOTION_INTERNAL_SECRET')
self.NOTION_INTEGRATION_TOKEN = get_env('NOTION_INTEGRATION_TOKEN')
self.TENANT_DOCUMENT_COUNT = get_env('TENANT_DOCUMENT_COUNT')
class CloudEditionConfig(Config):
......
......@@ -4,6 +4,9 @@ import datetime
import time
import random
from typing import Optional, List
from flask import current_app
from extensions.ext_redis import redis_client
from flask_login import current_user
......@@ -374,6 +377,12 @@ class DocumentService:
def save_document_with_dataset_id(dataset: Dataset, document_data: dict,
account: Account, dataset_process_rule: Optional[DatasetProcessRule] = None,
created_from: str = 'web'):
# check document limit
if current_app.config['EDITION'] == 'CLOUD':
documents_count = DocumentService.get_tenant_documents_count()
tenant_document_count = int(current_app.config['TENANT_DOCUMENT_COUNT'])
if documents_count > tenant_document_count:
raise ValueError(f"over document limit {tenant_document_count}.")
# if dataset is empty, update dataset data_source_type
if not dataset.data_source_type:
dataset.data_source_type = document_data["data_source"]["type"]
......@@ -521,6 +530,14 @@ class DocumentService:
)
return document
@staticmethod
def get_tenant_documents_count():
documents_count = Document.query.filter(Document.completed_at.isnot(None),
Document.enabled == True,
Document.archived == False,
Document.tenant_id == current_user.current_tenant_id).count()
return documents_count
@staticmethod
def update_document_with_dataset_id(dataset: Dataset, document_data: dict,
account: Account, dataset_process_rule: Optional[DatasetProcessRule] = None,
......@@ -616,6 +633,12 @@ class DocumentService:
@staticmethod
def save_document_without_dataset_id(tenant_id: str, document_data: dict, account: Account):
# check document limit
if current_app.config['EDITION'] == 'CLOUD':
documents_count = DocumentService.get_tenant_documents_count()
tenant_document_count = int(current_app.config['TENANT_DOCUMENT_COUNT'])
if documents_count > tenant_document_count:
raise ValueError(f"over document limit {tenant_document_count}.")
# save dataset
dataset = Dataset(
tenant_id=tenant_id,
......
......@@ -65,6 +65,7 @@ export type IChatProps = {
isShowSuggestion?: boolean
suggestionList?: string[]
isShowSpeechToText?: boolean
answerIconClassName?: string
}
export type MessageMore = {
......@@ -174,10 +175,11 @@ type IAnswerProps = {
onSubmitAnnotation?: SubmitAnnotationFunc
displayScene: DisplayScene
isResponsing?: boolean
answerIconClassName?: string
}
// The component needs to maintain its own state to control whether to display input component
const Answer: FC<IAnswerProps> = ({ item, feedbackDisabled = false, isHideFeedbackEdit = false, onFeedback, onSubmitAnnotation, displayScene = 'web', isResponsing }) => {
const Answer: FC<IAnswerProps> = ({ item, feedbackDisabled = false, isHideFeedbackEdit = false, onFeedback, onSubmitAnnotation, displayScene = 'web', isResponsing, answerIconClassName }) => {
const { id, content, more, feedback, adminFeedback, annotation: initAnnotation } = item
const [showEdit, setShowEdit] = useState(false)
const [loading, setLoading] = useState(false)
......@@ -292,7 +294,7 @@ const Answer: FC<IAnswerProps> = ({ item, feedbackDisabled = false, isHideFeedba
return (
<div key={id}>
<div className='flex items-start'>
<div className={`${s.answerIcon} w-10 h-10 shrink-0`}>
<div className={`${s.answerIcon} ${answerIconClassName} w-10 h-10 shrink-0`}>
{isResponsing
&& <div className={s.typeingIcon}>
<LoadingAnim type='avatar' />
......@@ -428,6 +430,7 @@ const Chat: FC<IChatProps> = ({
isShowSuggestion,
suggestionList,
isShowSpeechToText,
answerIconClassName,
}) => {
const { t } = useTranslation()
const { notify } = useContext(ToastContext)
......@@ -520,6 +523,7 @@ const Chat: FC<IChatProps> = ({
onSubmitAnnotation={onSubmitAnnotation}
displayScene={displayScene ?? 'web'}
isResponsing={isResponsing && isLast}
answerIconClassName={answerIconClassName}
/>
}
return <Question key={item.id} id={item.id} content={item.content} more={item.more} useCurrentUserAvatar={useCurrentUserAvatar} />
......
......@@ -184,7 +184,11 @@ const GenerationItem: FC<IGenerationItemProps> = ({
{taskId}
</div>)
}
<Markdown content={content} />
<div className='flex'>
<div className='grow w-0'>
<Markdown content={content} />
</div>
</div>
{messageId && (
<div className='flex items-center justify-between mt-3'>
<div className='flex items-center'>
......
......@@ -93,7 +93,7 @@ const ProviderPage = () => {
))
}
</div>
<div className='absolute bottom-0 w-full h-[42px] flex items-center bg-white text-xs text-gray-500'>
<div className='fixed bottom-0 w-[472px] h-[42px] flex items-center bg-white text-xs text-gray-500'>
<LockClosedIcon className='w-3 h-3 mr-1' />
{t('common.provider.encrypted.front')}
<Link
......
This diff is collapsed.
This diff is collapsed.
......@@ -552,6 +552,10 @@ const Main: FC<IMainProps> = ({
)
}
const difyIcon = (
<div className={s.difyHeader}></div>
)
if (appUnavailable)
return <AppUnavailable isUnknwonReason={isUnknwonReason} />
......@@ -562,7 +566,8 @@ const Main: FC<IMainProps> = ({
<div>
<Header
title={siteInfo.title}
icon={siteInfo.icon || ''}
icon=''
customerIcon={difyIcon}
icon_background={siteInfo.icon_background}
isEmbedScene={true}
isMobile={isMobile}
......@@ -624,6 +629,7 @@ const Main: FC<IMainProps> = ({
suggestionList={suggestQuestions}
displayScene='web'
isShowSpeechToText={speechToTextConfig?.enabled}
answerIconClassName={s.difyIcon}
/>
</div>
</div>)
......
.installedApp {
height: calc(100vh - 74px);
}
.difyIcon {
background-image: url(./icons/dify.svg);
}
.difyHeader {
width: 24px;
height: 24px;
background: url(./icons/dify-header.svg) center center no-repeat;
background-size: contain;
}
\ No newline at end of file
......@@ -307,7 +307,7 @@ const Welcome: FC<IWelcomeProps> = ({
}
return (
<div className='relative mobile:min-h-[48px] tablet:min-h-[64px]'>
<div className='relative tablet:min-h-[64px]'>
{/* {hasSetInputs && renderHeader()} */}
<div className='mx-auto pc:w-[794px] max-w-full mobile:w-full px-3.5'>
{/* Has't set inputs */}
......
......@@ -3,6 +3,7 @@ import React from 'react'
import AppIcon from '@/app/components/base/app-icon'
export type IHeaderProps = {
title: string
customerIcon?: React.ReactNode
icon: string
icon_background: string
isMobile?: boolean
......@@ -11,6 +12,7 @@ export type IHeaderProps = {
const Header: FC<IHeaderProps> = ({
title,
isMobile,
customerIcon,
icon,
icon_background,
isEmbedScene = false,
......@@ -25,7 +27,7 @@ const Header: FC<IHeaderProps> = ({
>
<div></div>
<div className="flex items-center space-x-2">
<AppIcon size="small" icon={icon} background={icon_background} />
{customerIcon || <AppIcon size="small" icon={icon} background={icon_background} />}
<div
className={`text-sm text-gray-800 font-bold ${
isEmbedScene ? 'text-white' : ''
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment