mirror of https://github.com/langgenius/dify.git
Merge branch 'main' into feat/queue-based-graph-engine
This commit is contained in:
commit
b46858d87d
|
|
@ -8,37 +8,44 @@ from flask_restx import reqparse
|
|||
from pydantic import BaseModel
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from core.file.constants import DEFAULT_SERVICE_API_USER_ID
|
||||
from extensions.ext_database import db
|
||||
from libs.login import _get_user
|
||||
from models.account import Account, Tenant
|
||||
from models.account import Tenant
|
||||
from models.model import EndUser
|
||||
from services.account_service import AccountService
|
||||
|
||||
|
||||
def get_user(tenant_id: str, user_id: str | None) -> Account | EndUser:
|
||||
def get_user(tenant_id: str, user_id: str | None) -> EndUser:
|
||||
"""
|
||||
Get current user
|
||||
|
||||
NOTE: user_id is not trusted, it could be maliciously set to any value.
|
||||
As a result, it could only be considered as an end user id.
|
||||
"""
|
||||
try:
|
||||
with Session(db.engine) as session:
|
||||
if not user_id:
|
||||
user_id = "DEFAULT-USER"
|
||||
user_id = DEFAULT_SERVICE_API_USER_ID
|
||||
|
||||
user_model = (
|
||||
session.query(EndUser)
|
||||
.where(
|
||||
EndUser.session_id == user_id,
|
||||
EndUser.tenant_id == tenant_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not user_model:
|
||||
user_model = EndUser(
|
||||
tenant_id=tenant_id,
|
||||
type="service_api",
|
||||
is_anonymous=user_id == DEFAULT_SERVICE_API_USER_ID,
|
||||
session_id=user_id,
|
||||
)
|
||||
session.add(user_model)
|
||||
session.commit()
|
||||
session.refresh(user_model)
|
||||
|
||||
if user_id == "DEFAULT-USER":
|
||||
user_model = session.query(EndUser).where(EndUser.session_id == "DEFAULT-USER").first()
|
||||
if not user_model:
|
||||
user_model = EndUser(
|
||||
tenant_id=tenant_id,
|
||||
type="service_api",
|
||||
is_anonymous=True if user_id == "DEFAULT-USER" else False,
|
||||
session_id=user_id,
|
||||
)
|
||||
session.add(user_model)
|
||||
session.commit()
|
||||
session.refresh(user_model)
|
||||
else:
|
||||
user_model = AccountService.load_user(user_id)
|
||||
if not user_model:
|
||||
user_model = session.query(EndUser).where(EndUser.id == user_id).first()
|
||||
if not user_model:
|
||||
raise ValueError("user not found")
|
||||
except Exception:
|
||||
raise ValueError("user not found")
|
||||
|
||||
|
|
@ -63,7 +70,7 @@ def get_user_tenant(view: Optional[Callable] = None):
|
|||
raise ValueError("tenant_id is required")
|
||||
|
||||
if not user_id:
|
||||
user_id = "DEFAULT-USER"
|
||||
user_id = DEFAULT_SERVICE_API_USER_ID
|
||||
|
||||
del kwargs["tenant_id"]
|
||||
del kwargs["user_id"]
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from sqlalchemy import select, update
|
|||
from sqlalchemy.orm import Session
|
||||
from werkzeug.exceptions import Forbidden, NotFound, Unauthorized
|
||||
|
||||
from core.file.constants import DEFAULT_SERVICE_API_USER_ID
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
|
|
@ -271,7 +272,7 @@ def create_or_update_end_user_for_user_id(app_model: App, user_id: Optional[str]
|
|||
Create or update session terminal based on user ID.
|
||||
"""
|
||||
if not user_id:
|
||||
user_id = "DEFAULT-USER"
|
||||
user_id = DEFAULT_SERVICE_API_USER_ID
|
||||
|
||||
with Session(db.engine, expire_on_commit=False) as session:
|
||||
end_user = (
|
||||
|
|
@ -290,7 +291,7 @@ def create_or_update_end_user_for_user_id(app_model: App, user_id: Optional[str]
|
|||
tenant_id=app_model.tenant_id,
|
||||
app_id=app_model.id,
|
||||
type="service_api",
|
||||
is_anonymous=user_id == "DEFAULT-USER",
|
||||
is_anonymous=user_id == DEFAULT_SERVICE_API_USER_ID,
|
||||
session_id=user_id,
|
||||
)
|
||||
session.add(end_user)
|
||||
|
|
|
|||
|
|
@ -9,3 +9,7 @@ FILE_MODEL_IDENTITY = "__dify__file__"
|
|||
|
||||
def maybe_file_object(o: Any) -> bool:
|
||||
return isinstance(o, dict) and o.get("dify_model_identity") == FILE_MODEL_IDENTITY
|
||||
|
||||
|
||||
# The default user ID for service API calls.
|
||||
DEFAULT_SERVICE_API_USER_ID = "DEFAULT-USER"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import os
|
|||
import time
|
||||
|
||||
from configs import dify_config
|
||||
from core.file.constants import DEFAULT_SERVICE_API_USER_ID
|
||||
|
||||
|
||||
def get_signed_file_url(upload_file_id: str) -> str:
|
||||
|
|
@ -26,7 +27,7 @@ def get_signed_file_url_for_plugin(filename: str, mimetype: str, tenant_id: str,
|
|||
url = f"{base_url}/files/upload/for-plugin"
|
||||
|
||||
if user_id is None:
|
||||
user_id = "DEFAULT-USER"
|
||||
user_id = DEFAULT_SERVICE_API_USER_ID
|
||||
|
||||
timestamp = str(int(time.time()))
|
||||
nonce = os.urandom(16).hex()
|
||||
|
|
@ -42,7 +43,7 @@ def verify_plugin_file_signature(
|
|||
*, filename: str, mimetype: str, tenant_id: str, user_id: str | None, timestamp: str, nonce: str, sign: str
|
||||
) -> bool:
|
||||
if user_id is None:
|
||||
user_id = "DEFAULT-USER"
|
||||
user_id = DEFAULT_SERVICE_API_USER_ID
|
||||
|
||||
data_to_sign = f"upload|{filename}|{mimetype}|{tenant_id}|{user_id}|{timestamp}|{nonce}"
|
||||
secret_key = dify_config.SECRET_KEY.encode()
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class Dataset(Base):
|
|||
INDEXING_TECHNIQUE_LIST = ["high_quality", "economy", None]
|
||||
PROVIDER_LIST = ["vendor", "external", None]
|
||||
|
||||
id = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()"))
|
||||
id: Mapped[str] = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()"))
|
||||
tenant_id: Mapped[str] = mapped_column(StringUUID)
|
||||
name: Mapped[str] = mapped_column(String(255))
|
||||
description = mapped_column(sa.Text, nullable=True)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,144 @@
|
|||
{
|
||||
"plugins": [
|
||||
"unicorn",
|
||||
"typescript",
|
||||
"oxc"
|
||||
],
|
||||
"categories": {},
|
||||
"rules": {
|
||||
"for-direction": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
"no-caller": "error",
|
||||
"no-class-assign": "error",
|
||||
"no-compare-neg-zero": "error",
|
||||
"no-cond-assign": "warn",
|
||||
"no-const-assign": "warn",
|
||||
"no-constant-binary-expression": "error",
|
||||
"no-constant-condition": "warn",
|
||||
"no-control-regex": "warn",
|
||||
"no-debugger": "warn",
|
||||
"no-delete-var": "warn",
|
||||
"no-dupe-class-members": "warn",
|
||||
"no-dupe-else-if": "warn",
|
||||
"no-dupe-keys": "warn",
|
||||
"no-duplicate-case": "warn",
|
||||
"no-empty-character-class": "warn",
|
||||
"no-empty-pattern": "warn",
|
||||
"no-empty-static-block": "warn",
|
||||
"no-eval": "warn",
|
||||
"no-ex-assign": "warn",
|
||||
"no-extra-boolean-cast": "warn",
|
||||
"no-func-assign": "warn",
|
||||
"no-global-assign": "warn",
|
||||
"no-import-assign": "warn",
|
||||
"no-invalid-regexp": "warn",
|
||||
"no-irregular-whitespace": "warn",
|
||||
"no-loss-of-precision": "warn",
|
||||
"no-new-native-nonconstructor": "warn",
|
||||
"no-nonoctal-decimal-escape": "warn",
|
||||
"no-obj-calls": "warn",
|
||||
"no-self-assign": "warn",
|
||||
"no-setter-return": "warn",
|
||||
"no-shadow-restricted-names": "warn",
|
||||
"no-sparse-arrays": "warn",
|
||||
"no-this-before-super": "warn",
|
||||
"no-unassigned-vars": "warn",
|
||||
"no-unsafe-finally": "warn",
|
||||
"no-unsafe-negation": "warn",
|
||||
"no-unsafe-optional-chaining": "warn",
|
||||
"no-unused-labels": "warn",
|
||||
"no-unused-private-class-members": "warn",
|
||||
"no-unused-vars": "warn",
|
||||
"no-useless-backreference": "warn",
|
||||
"no-useless-catch": "error",
|
||||
"no-useless-escape": "warn",
|
||||
"no-useless-rename": "warn",
|
||||
"no-with": "warn",
|
||||
"require-yield": "warn",
|
||||
"use-isnan": "warn",
|
||||
"valid-typeof": "warn",
|
||||
"oxc/bad-array-method-on-arguments": "warn",
|
||||
"oxc/bad-char-at-comparison": "warn",
|
||||
"oxc/bad-comparison-sequence": "warn",
|
||||
"oxc/bad-min-max-func": "warn",
|
||||
"oxc/bad-object-literal-comparison": "warn",
|
||||
"oxc/bad-replace-all-arg": "warn",
|
||||
"oxc/const-comparisons": "warn",
|
||||
"oxc/double-comparisons": "warn",
|
||||
"oxc/erasing-op": "warn",
|
||||
"oxc/missing-throw": "warn",
|
||||
"oxc/number-arg-out-of-range": "warn",
|
||||
"oxc/only-used-in-recursion": "warn",
|
||||
"oxc/uninvoked-array-callback": "warn",
|
||||
"typescript/await-thenable": "warn",
|
||||
"typescript/no-array-delete": "warn",
|
||||
"typescript/no-base-to-string": "warn",
|
||||
"typescript/no-confusing-void-expression": "warn",
|
||||
"typescript/no-duplicate-enum-values": "warn",
|
||||
"typescript/no-duplicate-type-constituents": "warn",
|
||||
"typescript/no-extra-non-null-assertion": "warn",
|
||||
"typescript/no-floating-promises": "warn",
|
||||
"typescript/no-for-in-array": "warn",
|
||||
"typescript/no-implied-eval": "warn",
|
||||
"typescript/no-meaningless-void-operator": "warn",
|
||||
"typescript/no-misused-new": "warn",
|
||||
"typescript/no-misused-spread": "warn",
|
||||
"typescript/no-non-null-asserted-optional-chain": "warn",
|
||||
"typescript/no-redundant-type-constituents": "warn",
|
||||
"typescript/no-this-alias": "warn",
|
||||
"typescript/no-unnecessary-parameter-property-assignment": "warn",
|
||||
"typescript/no-unsafe-declaration-merging": "warn",
|
||||
"typescript/no-unsafe-unary-minus": "warn",
|
||||
"typescript/no-useless-empty-export": "warn",
|
||||
"typescript/no-wrapper-object-types": "warn",
|
||||
"typescript/prefer-as-const": "warn",
|
||||
"typescript/require-array-sort-compare": "warn",
|
||||
"typescript/restrict-template-expressions": "warn",
|
||||
"typescript/triple-slash-reference": "warn",
|
||||
"typescript/unbound-method": "warn",
|
||||
"unicorn/no-await-in-promise-methods": "warn",
|
||||
"unicorn/no-empty-file": "warn",
|
||||
"unicorn/no-invalid-fetch-options": "warn",
|
||||
"unicorn/no-invalid-remove-event-listener": "warn",
|
||||
"unicorn/no-new-array": "warn",
|
||||
"unicorn/no-single-promise-in-promise-methods": "warn",
|
||||
"unicorn/no-thenable": "warn",
|
||||
"unicorn/no-unnecessary-await": "warn",
|
||||
"unicorn/no-useless-fallback-in-spread": "warn",
|
||||
"unicorn/no-useless-length-check": "warn",
|
||||
"unicorn/no-useless-spread": "warn",
|
||||
"unicorn/prefer-set-size": "warn",
|
||||
"unicorn/prefer-string-starts-ends-with": "warn"
|
||||
},
|
||||
"settings": {
|
||||
"jsx-a11y": {
|
||||
"polymorphicPropName": null,
|
||||
"components": {},
|
||||
"attributes": {}
|
||||
},
|
||||
"next": {
|
||||
"rootDir": []
|
||||
},
|
||||
"react": {
|
||||
"formComponents": [],
|
||||
"linkComponents": []
|
||||
},
|
||||
"jsdoc": {
|
||||
"ignorePrivate": false,
|
||||
"ignoreInternal": false,
|
||||
"ignoreReplacesDocs": true,
|
||||
"overrideReplacesDocs": true,
|
||||
"augmentsExtendsReplacesDocs": false,
|
||||
"implementsReplacesDocs": false,
|
||||
"exemptDestructuredRootsFromChecks": false,
|
||||
"tagNamePreference": {}
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"builtin": true
|
||||
},
|
||||
"globals": {},
|
||||
"ignorePatterns": [
|
||||
"**/*.js"
|
||||
]
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ export default function CheckCode() {
|
|||
<form action="">
|
||||
<input type='text' className='hidden' />
|
||||
<label htmlFor="code" className='system-md-semibold mb-1 text-text-secondary'>{t('login.checkCode.verificationCode')}</label>
|
||||
<Input value={code} onChange={e => setVerifyCode(e.target.value)} max-length={6} className='mt-1' placeholder={t('login.checkCode.verificationCodePlaceholder') as string} />
|
||||
<Input value={code} onChange={e => setVerifyCode(e.target.value)} maxLength={6} className='mt-1' placeholder={t('login.checkCode.verificationCodePlaceholder') || ''} />
|
||||
<Button loading={loading} disabled={loading} className='my-3 w-full' variant='primary' onClick={verify}>{t('login.checkCode.verify')}</Button>
|
||||
<Countdown onResend={resendCode} />
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export default function CheckCode() {
|
|||
|
||||
<form action="">
|
||||
<label htmlFor="code" className='system-md-semibold mb-1 text-text-secondary'>{t('login.checkCode.verificationCode')}</label>
|
||||
<Input value={code} onChange={e => setVerifyCode(e.target.value)} max-length={6} className='mt-1' placeholder={t('login.checkCode.verificationCodePlaceholder') as string} />
|
||||
<Input value={code} onChange={e => setVerifyCode(e.target.value)} maxLength={6} className='mt-1' placeholder={t('login.checkCode.verificationCodePlaceholder') || ''} />
|
||||
<Button loading={loading} disabled={loading} className='my-3 w-full' variant='primary' onClick={verify}>{t('login.checkCode.verify')}</Button>
|
||||
<Countdown onResend={resendCode} />
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
|||
}
|
||||
}
|
||||
if (item.number) {
|
||||
const convertedNumber = Number(initInputs[item.number.variable]) ?? undefined
|
||||
const convertedNumber = Number(initInputs[item.number.variable])
|
||||
return {
|
||||
...item.number,
|
||||
default: convertedNumber || item.default || item.number.default,
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ export const useEmbeddedChatbot = () => {
|
|||
}
|
||||
}
|
||||
if (item.number) {
|
||||
const convertedNumber = Number(initInputs[item.number.variable]) ?? undefined
|
||||
const convertedNumber = Number(initInputs[item.number.variable])
|
||||
return {
|
||||
...item.number,
|
||||
default: convertedNumber || item.default || item.number.default,
|
||||
|
|
|
|||
|
|
@ -9,17 +9,34 @@ import { isValidUrl } from './utils'
|
|||
|
||||
const Link = ({ node, children, ...props }: any) => {
|
||||
const { onSend } = useChatContext()
|
||||
const commonClassName = 'cursor-pointer underline !decoration-primary-700 decoration-dashed'
|
||||
if (node.properties?.href && node.properties.href?.toString().startsWith('abbr')) {
|
||||
const hidden_text = decodeURIComponent(node.properties.href.toString().split('abbr:')[1])
|
||||
|
||||
return <abbr className="cursor-pointer underline !decoration-primary-700 decoration-dashed" onClick={() => onSend?.(hidden_text)} title={node.children[0]?.value || ''}>{node.children[0]?.value || ''}</abbr>
|
||||
return <abbr className={commonClassName} onClick={() => onSend?.(hidden_text)} title={node.children[0]?.value || ''}>{node.children[0]?.value || ''}</abbr>
|
||||
}
|
||||
else {
|
||||
const href = props.href || node.properties?.href
|
||||
if(!href || !isValidUrl(href))
|
||||
if (href && /^#[a-zA-Z0-9_\-]+$/.test(href.toString())) {
|
||||
const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault()
|
||||
// scroll to target element if exists within the answer container
|
||||
const answerContainer = e.currentTarget.closest('.chat-answer-container')
|
||||
|
||||
if (answerContainer) {
|
||||
const targetId = CSS.escape(href.toString().substring(1))
|
||||
const targetElement = answerContainer.querySelector(`[id="${targetId}"]`)
|
||||
if (targetElement)
|
||||
targetElement.scrollIntoView({ behavior: 'smooth' })
|
||||
}
|
||||
}
|
||||
return <a href={href} onClick={handleClick} className={commonClassName}>{children || 'ScrollView'}</a>
|
||||
}
|
||||
|
||||
if (!href || !isValidUrl(href))
|
||||
return <span>{children}</span>
|
||||
|
||||
return <a href={href} target="_blank" className="cursor-pointer underline !decoration-primary-700 decoration-dashed">{children || 'Download'}</a>
|
||||
return <a href={href} target="_blank" rel="noopener noreferrer" className={commonClassName}>{children || 'Download'}</a>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -186,12 +186,12 @@ const ParameterItem: FC<ParameterItemProps> = ({
|
|||
if (parameterRule.type === 'boolean') {
|
||||
return (
|
||||
<Radio.Group
|
||||
className='flex w-[178px] items-center'
|
||||
className='flex w-[150px] items-center'
|
||||
value={renderValue as boolean}
|
||||
onChange={handleRadioChange}
|
||||
>
|
||||
<Radio value={true} className='w-[83px]'>True</Radio>
|
||||
<Radio value={false} className='w-[83px]'>False</Radio>
|
||||
<Radio value={true} className='w-[70px] px-[18px]'>True</Radio>
|
||||
<Radio value={false} className='w-[70px] px-[18px]'>False</Radio>
|
||||
</Radio.Group>
|
||||
)
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
|
|||
if (parameterRule.type === 'string' && !parameterRule.options?.length) {
|
||||
return (
|
||||
<input
|
||||
className={cn(isInWorkflow ? 'w-[178px]' : 'w-full', 'system-sm-regular ml-4 flex h-8 appearance-none items-center rounded-lg bg-components-input-bg-normal px-3 text-components-input-text-filled outline-none')}
|
||||
className={cn(isInWorkflow ? 'w-[150px]' : 'w-full', 'system-sm-regular ml-4 flex h-8 appearance-none items-center rounded-lg bg-components-input-bg-normal px-3 text-components-input-text-filled outline-none')}
|
||||
value={renderValue as string}
|
||||
onChange={handleStringInputChange}
|
||||
/>
|
||||
|
|
@ -270,7 +270,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
|
|||
parameterRule.help && (
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className='w-[178px] whitespace-pre-wrap'>{parameterRule.help[language] || parameterRule.help.en_US}</div>
|
||||
<div className='w-[150px] whitespace-pre-wrap'>{parameterRule.help[language] || parameterRule.help.en_US}</div>
|
||||
)}
|
||||
popupClassName='mr-1'
|
||||
triggerClassName='mr-1 w-4 h-4 shrink-0'
|
||||
|
|
@ -280,7 +280,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
|
|||
</div>
|
||||
{
|
||||
parameterRule.type === 'tag' && (
|
||||
<div className={cn(!isInWorkflow && 'w-[178px]', 'system-xs-regular text-text-tertiary')}>
|
||||
<div className={cn(!isInWorkflow && 'w-[150px]', 'system-xs-regular text-text-tertiary')}>
|
||||
{parameterRule?.tagPlaceholder?.[language]}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ const nodeDefault: NodeDefault<ListFilterNodeType> = {
|
|||
if (!errorMessages && !filter_by.conditions[0]?.comparison_operator)
|
||||
errorMessages = t(`${i18nPrefix}.fieldRequired`, { field: t('workflow.nodes.listFilter.filterConditionComparisonOperator') })
|
||||
|
||||
if (!errorMessages && !comparisonOperatorNotRequireValue(filter_by.conditions[0]?.comparison_operator) && (item_var_type === VarType.boolean ? !filter_by.conditions[0]?.value === undefined : !filter_by.conditions[0]?.value))
|
||||
if (!errorMessages && !comparisonOperatorNotRequireValue(filter_by.conditions[0]?.comparison_operator) && (item_var_type === VarType.boolean ? filter_by.conditions[0]?.value === undefined : !filter_by.conditions[0]?.value))
|
||||
errorMessages = t(`${i18nPrefix}.fieldRequired`, { field: t('workflow.nodes.listFilter.filterConditionComparisonValue') })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export default function CheckCode() {
|
|||
<form action="">
|
||||
<input type='text' className='hidden' />
|
||||
<label htmlFor="code" className='system-md-semibold mb-1 text-text-secondary'>{t('login.checkCode.verificationCode')}</label>
|
||||
<Input value={code} onChange={e => setVerifyCode(e.target.value)} max-length={6} className='mt-1' placeholder={t('login.checkCode.verificationCodePlaceholder') as string} />
|
||||
<Input value={code} onChange={e => setVerifyCode(e.target.value)} maxLength={6} className='mt-1' placeholder={t('login.checkCode.verificationCodePlaceholder') as string} />
|
||||
<Button loading={loading} disabled={loading} className='my-3 w-full' variant='primary' onClick={verify}>{t('login.checkCode.verify')}</Button>
|
||||
<Countdown onResend={resendCode} />
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ export default function CheckCode() {
|
|||
|
||||
<form action="">
|
||||
<label htmlFor="code" className='system-md-semibold mb-1 text-text-secondary'>{t('login.checkCode.verificationCode')}</label>
|
||||
<Input value={code} onChange={e => setVerifyCode(e.target.value)} max-length={6} className='mt-1' placeholder={t('login.checkCode.verificationCodePlaceholder') as string} />
|
||||
<Input value={code} onChange={e => setVerifyCode(e.target.value)} maxLength={6} className='mt-1' placeholder={t('login.checkCode.verificationCodePlaceholder') as string} />
|
||||
<Button loading={loading} disabled={loading} className='my-3 w-full' variant='primary' onClick={verify}>{t('login.checkCode.verify')}</Button>
|
||||
<Countdown onResend={resendCode} />
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -193,15 +193,15 @@ const translation = {
|
|||
confirm: 'افزودن و مجوزدهی',
|
||||
timeout: 'مهلت',
|
||||
sseReadTimeout: 'زمان.out خواندن SSE',
|
||||
headers: 'عناوین',
|
||||
timeoutPlaceholder: 'سی',
|
||||
headers: 'هدرها',
|
||||
timeoutPlaceholder: '30',
|
||||
headerKey: 'نام هدر',
|
||||
headerValue: 'مقدار هدر',
|
||||
addHeader: 'هدر اضافه کنید',
|
||||
headerKeyPlaceholder: 'به عنوان مثال، مجوز',
|
||||
headerValuePlaceholder: 'مثلاً، توکن حامل ۱۲۳',
|
||||
headerKeyPlaceholder: 'Authorization',
|
||||
headerValuePlaceholder: 'مثلاً، Bearer 123',
|
||||
noHeaders: 'هیچ هدر سفارشی پیکربندی نشده است',
|
||||
headersTip: 'سرفصلهای اضافی HTTP برای ارسال با درخواستهای سرور MCP',
|
||||
headersTip: 'هدرهای HTTP اضافی برای ارسال با درخواستهای سرور MCP',
|
||||
maskedHeadersTip: 'مقدارهای هدر به خاطر امنیت مخفی شدهاند. تغییرات مقادیر واقعی را بهروزرسانی خواهد کرد.',
|
||||
},
|
||||
delete: 'حذف سرور MCP',
|
||||
|
|
|
|||
|
|
@ -176,13 +176,13 @@ const translation = {
|
|||
serverIdentifierPlaceholder: 'Pengidentifikasi unik, misalnya, my-mcp-server',
|
||||
serverUrl: 'Server URL',
|
||||
headers: 'Header',
|
||||
timeoutPlaceholder: 'tiga puluh',
|
||||
timeoutPlaceholder: '30',
|
||||
addHeader: 'Tambahkan Judul',
|
||||
headerKey: 'Nama Header',
|
||||
headerValue: 'Nilai Header',
|
||||
headersTip: 'Header HTTP tambahan untuk dikirim bersama permintaan server MCP',
|
||||
headerKeyPlaceholder: 'misalnya, Otorisasi',
|
||||
headerValuePlaceholder: 'misalnya, Token Pengganti 123',
|
||||
headerKeyPlaceholder: 'Authorization',
|
||||
headerValuePlaceholder: 'Bearer 123',
|
||||
noHeaders: 'Tidak ada header kustom yang dikonfigurasi',
|
||||
maskedHeadersTip: 'Nilai header disembunyikan untuk keamanan. Perubahan akan memperbarui nilai yang sebenarnya.',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -193,15 +193,15 @@ const translation = {
|
|||
confirm: 'Dodaj in avtoriziraj',
|
||||
timeout: 'Časovna omejitev',
|
||||
sseReadTimeout: 'SSE časovna omejitev branja',
|
||||
timeoutPlaceholder: 'trideset',
|
||||
headers: 'Naslovi',
|
||||
headerKeyPlaceholder: 'npr., Pooblastitev',
|
||||
timeoutPlaceholder: '30',
|
||||
headers: 'Glave',
|
||||
headerKeyPlaceholder: 'npr., Authorization',
|
||||
headerValue: 'Vrednost glave',
|
||||
headerKey: 'Ime glave',
|
||||
addHeader: 'Dodaj naslov',
|
||||
addHeader: 'Dodaj glavo',
|
||||
headersTip: 'Dodatni HTTP glavi za poslati z zahtevami MCP strežnika',
|
||||
headerValuePlaceholder: 'npr., nosilec žeton123',
|
||||
noHeaders: 'Nobenih prilagojenih glave ni konfiguriranih',
|
||||
headerValuePlaceholder: 'npr., Bearer žeton123',
|
||||
noHeaders: 'Nobena prilagojena glava ni konfigurirana',
|
||||
maskedHeadersTip: 'Vrednosti glave so zakrite zaradi varnosti. Spremembe bodo posodobile dejanske vrednosti.',
|
||||
},
|
||||
delete: 'Odstrani strežnik MCP',
|
||||
|
|
|
|||
Loading…
Reference in New Issue