mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-12 10:28:59 +08:00
Feat/chat custom disclaimer (#4306)
This commit is contained in:
parent
b1f003646b
commit
aa13d14019
@ -24,7 +24,8 @@
|
||||
"description": "Welcome to your personalized Investment Analysis Copilot service, where we delve into the depths of stock analysis to provide you with comprehensive insights. \n",
|
||||
"is_listed": true,
|
||||
"position": 0,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -40,7 +41,8 @@
|
||||
"description": "Code interpreter, clarifying the syntax and semantics of the code.",
|
||||
"is_listed": true,
|
||||
"position": 13,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -56,7 +58,8 @@
|
||||
"description": "Hello, I am your creative partner in bringing ideas to vivid life! I can assist you in creating stunning designs by leveraging abilities of DALL\u00b7E 3. ",
|
||||
"is_listed": true,
|
||||
"position": 4,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -72,7 +75,8 @@
|
||||
"description": "Fully SEO Optimized Article including FAQs",
|
||||
"is_listed": true,
|
||||
"position": 1,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -88,7 +92,8 @@
|
||||
"description": "Generate Flat Style Image",
|
||||
"is_listed": true,
|
||||
"position": 10,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -104,7 +109,8 @@
|
||||
"description": "A multilingual translator that provides translation capabilities in multiple languages. Input the text you need to translate and select the target language.",
|
||||
"is_listed": true,
|
||||
"position": 10,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -120,7 +126,8 @@
|
||||
"description": "I am a YouTube Channel Data Analysis Copilot, I am here to provide expert data analysis tailored to your needs. ",
|
||||
"is_listed": true,
|
||||
"position": 2,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -136,7 +143,8 @@
|
||||
"description": "Meeting minutes generator",
|
||||
"is_listed": true,
|
||||
"position": 0,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -152,7 +160,8 @@
|
||||
"description": "Tell me the main elements, I will generate a cyberpunk style image for you. ",
|
||||
"is_listed": true,
|
||||
"position": 10,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -168,7 +177,8 @@
|
||||
"description": "Write SQL from natural language by pasting in your schema with the request.Please describe your query requirements in natural language and select the target database type.",
|
||||
"is_listed": true,
|
||||
"position": 13,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -184,7 +194,8 @@
|
||||
"description": "Welcome to your personalized travel service with Consultant! \ud83c\udf0d\u2708\ufe0f Ready to embark on a journey filled with adventure and relaxation? Let's dive into creating your unforgettable travel experience. ",
|
||||
"is_listed": true,
|
||||
"position": 3,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -200,7 +211,8 @@
|
||||
"description": "I can answer your questions related to strategic marketing.",
|
||||
"is_listed": true,
|
||||
"position": 10,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -216,7 +228,8 @@
|
||||
"description": "A simulated front-end interviewer that tests the skill level of front-end development through questioning.",
|
||||
"is_listed": true,
|
||||
"position": 19,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -232,7 +245,8 @@
|
||||
"description": "I'm here to hear about your feature request about Dify and help you flesh it out further. What's on your mind?",
|
||||
"is_listed": true,
|
||||
"position": 6,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -261,7 +275,8 @@
|
||||
"description": "\u4e00\u4e2a\u6a21\u62df\u7684\u524d\u7aef\u9762\u8bd5\u5b98\uff0c\u901a\u8fc7\u63d0\u95ee\u7684\u65b9\u5f0f\u5bf9\u524d\u7aef\u5f00\u53d1\u7684\u6280\u80fd\u6c34\u5e73\u8fdb\u884c\u68c0\u9a8c\u3002",
|
||||
"is_listed": true,
|
||||
"position": 20,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -277,7 +292,8 @@
|
||||
"description": "\u8f93\u5165\u76f8\u5173\u5143\u7d20\uff0c\u4e3a\u4f60\u751f\u6210\u6241\u5e73\u63d2\u753b\u98ce\u683c\u7684\u5c01\u9762\u56fe\u7247",
|
||||
"is_listed": true,
|
||||
"position": 10,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -293,7 +309,8 @@
|
||||
"description": "\u4e00\u4e2a\u591a\u8bed\u8a00\u7ffb\u8bd1\u5668\uff0c\u63d0\u4f9b\u591a\u79cd\u8bed\u8a00\u7ffb\u8bd1\u80fd\u529b\uff0c\u8f93\u5165\u4f60\u9700\u8981\u7ffb\u8bd1\u7684\u6587\u672c\uff0c\u9009\u62e9\u76ee\u6807\u8bed\u8a00\u5373\u53ef\u3002\u63d0\u793a\u8bcd\u6765\u81ea\u5b9d\u7389\u3002",
|
||||
"is_listed": true,
|
||||
"position": 10,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -309,7 +326,8 @@
|
||||
"description": "\u6211\u5c06\u5e2e\u52a9\u4f60\u628a\u81ea\u7136\u8bed\u8a00\u8f6c\u5316\u6210\u6307\u5b9a\u7684\u6570\u636e\u5e93\u67e5\u8be2 SQL \u8bed\u53e5\uff0c\u8bf7\u5728\u4e0b\u65b9\u8f93\u5165\u4f60\u9700\u8981\u67e5\u8be2\u7684\u6761\u4ef6\uff0c\u5e76\u9009\u62e9\u76ee\u6807\u6570\u636e\u5e93\u7c7b\u578b\u3002",
|
||||
"is_listed": true,
|
||||
"position": 12,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -325,7 +343,8 @@
|
||||
"description": "\u9610\u660e\u4ee3\u7801\u7684\u8bed\u6cd5\u548c\u8bed\u4e49\u3002",
|
||||
"is_listed": true,
|
||||
"position": 2,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -341,7 +360,8 @@
|
||||
"description": "\u8f93\u5165\u76f8\u5173\u5143\u7d20\uff0c\u4e3a\u4f60\u751f\u6210\u8d5b\u535a\u670b\u514b\u98ce\u683c\u7684\u63d2\u753b",
|
||||
"is_listed": true,
|
||||
"position": 10,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -357,7 +377,8 @@
|
||||
"description": "\u6211\u662f\u4e00\u540dSEO\u4e13\u5bb6\uff0c\u53ef\u4ee5\u6839\u636e\u60a8\u63d0\u4f9b\u7684\u6807\u9898\u3001\u5173\u952e\u8bcd\u3001\u76f8\u5173\u4fe1\u606f\u6765\u6279\u91cf\u751f\u6210SEO\u6587\u7ae0\u3002",
|
||||
"is_listed": true,
|
||||
"position": 10,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -373,7 +394,8 @@
|
||||
"description": "\u5e2e\u4f60\u91cd\u65b0\u7ec4\u7ec7\u548c\u8f93\u51fa\u6df7\u4e71\u590d\u6742\u7684\u4f1a\u8bae\u7eaa\u8981\u3002",
|
||||
"is_listed": true,
|
||||
"position": 6,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -389,7 +411,8 @@
|
||||
"description": "\u6b22\u8fce\u4f7f\u7528\u60a8\u7684\u4e2a\u6027\u5316\u7f8e\u80a1\u6295\u8d44\u5206\u6790\u52a9\u624b\uff0c\u5728\u8fd9\u91cc\u6211\u4eec\u6df1\u5165\u7684\u8fdb\u884c\u80a1\u7968\u5206\u6790\uff0c\u4e3a\u60a8\u63d0\u4f9b\u5168\u9762\u7684\u6d1e\u5bdf\u3002",
|
||||
"is_listed": true,
|
||||
"position": 0,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -405,7 +428,8 @@
|
||||
"description": "\u60a8\u597d\uff0c\u6211\u662f\u60a8\u7684\u521b\u610f\u4f19\u4f34\uff0c\u5c06\u5e2e\u52a9\u60a8\u5c06\u60f3\u6cd5\u751f\u52a8\u5730\u5b9e\u73b0\uff01\u6211\u53ef\u4ee5\u534f\u52a9\u60a8\u5229\u7528DALL\u00b7E 3\u7684\u80fd\u529b\u521b\u9020\u51fa\u4ee4\u4eba\u60ca\u53f9\u7684\u8bbe\u8ba1\u3002",
|
||||
"is_listed": true,
|
||||
"position": 4,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -421,7 +445,8 @@
|
||||
"description": "\u7ffb\u8bd1\u4e13\u5bb6\uff1a\u63d0\u4f9b\u4e2d\u82f1\u6587\u4e92\u8bd1",
|
||||
"is_listed": true,
|
||||
"position": 4,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -437,7 +462,8 @@
|
||||
"description": "\u60a8\u7684\u79c1\u4eba\u5b66\u4e60\u5bfc\u5e08\uff0c\u5e2e\u60a8\u5236\u5b9a\u5b66\u4e60\u8ba1\u5212\u5e76\u8f85\u5bfc",
|
||||
"is_listed": true,
|
||||
"position": 26,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -453,7 +479,8 @@
|
||||
"description": "\u5e2e\u4f60\u64b0\u5199\u8bba\u6587\u6587\u732e\u7efc\u8ff0",
|
||||
"is_listed": true,
|
||||
"position": 7,
|
||||
"privacy_policy": "https://dify.ai"
|
||||
"privacy_policy": "https://dify.ai",
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -469,7 +496,8 @@
|
||||
"description": "\u4f60\u597d\uff0c\u544a\u8bc9\u6211\u60a8\u60f3\u5206\u6790\u7684 YouTube \u9891\u9053\uff0c\u6211\u5c06\u4e3a\u60a8\u6574\u7406\u4e00\u4efd\u5b8c\u6574\u7684\u6570\u636e\u5206\u6790\u62a5\u544a\u3002",
|
||||
"is_listed": true,
|
||||
"position": 0,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
},
|
||||
{
|
||||
"app": {
|
||||
@ -485,7 +513,8 @@
|
||||
"description": "\u6b22\u8fce\u4f7f\u7528\u60a8\u7684\u4e2a\u6027\u5316\u65c5\u884c\u670d\u52a1\u987e\u95ee\uff01\ud83c\udf0d\u2708\ufe0f \u51c6\u5907\u597d\u8e0f\u4e0a\u4e00\u6bb5\u5145\u6ee1\u5192\u9669\u4e0e\u653e\u677e\u7684\u65c5\u7a0b\u4e86\u5417\uff1f\u8ba9\u6211\u4eec\u4e00\u8d77\u6df1\u5165\u6253\u9020\u60a8\u96be\u5fd8\u7684\u65c5\u884c\u4f53\u9a8c\u5427\u3002",
|
||||
"is_listed": true,
|
||||
"position": 0,
|
||||
"privacy_policy": null
|
||||
"privacy_policy": null,
|
||||
"custom_disclaimer": null
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -48,6 +48,7 @@ class InsertExploreAppListApi(Resource):
|
||||
parser.add_argument('desc', type=str, location='json')
|
||||
parser.add_argument('copyright', type=str, location='json')
|
||||
parser.add_argument('privacy_policy', type=str, location='json')
|
||||
parser.add_argument('custom_disclaimer', type=str, location='json')
|
||||
parser.add_argument('language', type=supported_language, required=True, nullable=False, location='json')
|
||||
parser.add_argument('category', type=str, required=True, nullable=False, location='json')
|
||||
parser.add_argument('position', type=int, required=True, nullable=False, location='json')
|
||||
@ -62,6 +63,7 @@ class InsertExploreAppListApi(Resource):
|
||||
desc = args['desc'] if args['desc'] else ''
|
||||
copy_right = args['copyright'] if args['copyright'] else ''
|
||||
privacy_policy = args['privacy_policy'] if args['privacy_policy'] else ''
|
||||
custom_disclaimer = args['custom_disclaimer'] if args['custom_disclaimer'] else ''
|
||||
else:
|
||||
desc = site.description if site.description else \
|
||||
args['desc'] if args['desc'] else ''
|
||||
@ -69,6 +71,8 @@ class InsertExploreAppListApi(Resource):
|
||||
args['copyright'] if args['copyright'] else ''
|
||||
privacy_policy = site.privacy_policy if site.privacy_policy else \
|
||||
args['privacy_policy'] if args['privacy_policy'] else ''
|
||||
custom_disclaimer = site.custom_disclaimer if site.custom_disclaimer else \
|
||||
args['custom_disclaimer'] if args['custom_disclaimer'] else ''
|
||||
|
||||
recommended_app = RecommendedApp.query.filter(RecommendedApp.app_id == args['app_id']).first()
|
||||
|
||||
@ -78,6 +82,7 @@ class InsertExploreAppListApi(Resource):
|
||||
description=desc,
|
||||
copyright=copy_right,
|
||||
privacy_policy=privacy_policy,
|
||||
custom_disclaimer=custom_disclaimer,
|
||||
language=args['language'],
|
||||
category=args['category'],
|
||||
position=args['position']
|
||||
@ -93,6 +98,7 @@ class InsertExploreAppListApi(Resource):
|
||||
recommended_app.description = desc
|
||||
recommended_app.copyright = copy_right
|
||||
recommended_app.privacy_policy = privacy_policy
|
||||
recommended_app.custom_disclaimer = custom_disclaimer
|
||||
recommended_app.language = args['language']
|
||||
recommended_app.category = args['category']
|
||||
recommended_app.position = args['position']
|
||||
|
@ -23,6 +23,7 @@ def parse_app_site_args():
|
||||
parser.add_argument('customize_domain', type=str, required=False, location='json')
|
||||
parser.add_argument('copyright', type=str, required=False, location='json')
|
||||
parser.add_argument('privacy_policy', type=str, required=False, location='json')
|
||||
parser.add_argument('custom_disclaimer', type=str, required=False, location='json')
|
||||
parser.add_argument('customize_token_strategy', type=str, choices=['must', 'allow', 'not_allow'],
|
||||
required=False,
|
||||
location='json')
|
||||
@ -56,6 +57,7 @@ class AppSite(Resource):
|
||||
'customize_domain',
|
||||
'copyright',
|
||||
'privacy_policy',
|
||||
'custom_disclaimer',
|
||||
'customize_token_strategy',
|
||||
'prompt_public'
|
||||
]:
|
||||
|
@ -21,6 +21,7 @@ recommended_app_fields = {
|
||||
'description': fields.String(attribute='description'),
|
||||
'copyright': fields.String,
|
||||
'privacy_policy': fields.String,
|
||||
'custom_disclaimer': fields.String,
|
||||
'category': fields.String,
|
||||
'position': fields.Integer,
|
||||
'is_listed': fields.Boolean
|
||||
|
@ -116,6 +116,7 @@ class ToolApiProviderAddApi(Resource):
|
||||
parser.add_argument('provider', type=str, required=True, nullable=False, location='json')
|
||||
parser.add_argument('icon', type=dict, required=True, nullable=False, location='json')
|
||||
parser.add_argument('privacy_policy', type=str, required=False, nullable=True, location='json')
|
||||
parser.add_argument('custom_disclaimer', type=str, required=False, nullable=True, location='json')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@ -128,6 +129,7 @@ class ToolApiProviderAddApi(Resource):
|
||||
args['schema_type'],
|
||||
args['schema'],
|
||||
args.get('privacy_policy', ''),
|
||||
args.get('custom_disclaimer', ''),
|
||||
)
|
||||
|
||||
class ToolApiProviderGetRemoteSchemaApi(Resource):
|
||||
@ -186,6 +188,7 @@ class ToolApiProviderUpdateApi(Resource):
|
||||
parser.add_argument('original_provider', type=str, required=True, nullable=False, location='json')
|
||||
parser.add_argument('icon', type=dict, required=True, nullable=False, location='json')
|
||||
parser.add_argument('privacy_policy', type=str, required=True, nullable=True, location='json')
|
||||
parser.add_argument('custom_disclaimer', type=str, required=True, nullable=True, location='json')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@ -199,6 +202,7 @@ class ToolApiProviderUpdateApi(Resource):
|
||||
args['schema_type'],
|
||||
args['schema'],
|
||||
args['privacy_policy'],
|
||||
args['custom_disclaimer'],
|
||||
)
|
||||
|
||||
class ToolApiProviderDeleteApi(Resource):
|
||||
|
@ -31,6 +31,7 @@ class AppSiteApi(WebApiResource):
|
||||
'description': fields.String,
|
||||
'copyright': fields.String,
|
||||
'privacy_policy': fields.String,
|
||||
'custom_disclaimer': fields.String,
|
||||
'default_language': fields.String,
|
||||
'prompt_public': fields.Boolean
|
||||
}
|
||||
|
@ -487,7 +487,8 @@ class ToolManager:
|
||||
'icon': icon,
|
||||
'description': provider.description,
|
||||
'credentials': masked_credentials,
|
||||
'privacy_policy': provider.privacy_policy
|
||||
'privacy_policy': provider.privacy_policy,
|
||||
'custom_disclaimer': provider.custom_disclaimer
|
||||
})
|
||||
|
||||
@classmethod
|
||||
|
@ -113,6 +113,7 @@ site_fields = {
|
||||
'customize_domain': fields.String,
|
||||
'copyright': fields.String,
|
||||
'privacy_policy': fields.String,
|
||||
'custom_disclaimer': fields.String,
|
||||
'customize_token_strategy': fields.String,
|
||||
'prompt_public': fields.Boolean,
|
||||
'app_base_url': fields.String,
|
||||
@ -146,6 +147,7 @@ app_site_fields = {
|
||||
'customize_domain': fields.String,
|
||||
'copyright': fields.String,
|
||||
'privacy_policy': fields.String,
|
||||
'custom_disclaimer': fields.String,
|
||||
'customize_token_strategy': fields.String,
|
||||
'prompt_public': fields.Boolean
|
||||
}
|
||||
|
45
api/migrations/versions/5fda94355fce_custom_disclaimer.py
Normal file
45
api/migrations/versions/5fda94355fce_custom_disclaimer.py
Normal file
@ -0,0 +1,45 @@
|
||||
"""Custom Disclaimer
|
||||
|
||||
Revision ID: 5fda94355fce
|
||||
Revises: 47cc7df8c4f3
|
||||
Create Date: 2024-05-10 20:04:45.806549
|
||||
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
import models as models
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '5fda94355fce'
|
||||
down_revision = '47cc7df8c4f3'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('recommended_apps', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('custom_disclaimer', sa.String(length=255), nullable=False))
|
||||
|
||||
with op.batch_alter_table('sites', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('custom_disclaimer', sa.String(length=255), nullable=True))
|
||||
|
||||
with op.batch_alter_table('tool_api_providers', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('custom_disclaimer', sa.String(length=255), nullable=True))
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('tool_api_providers', schema=None) as batch_op:
|
||||
batch_op.drop_column('custom_disclaimer')
|
||||
|
||||
with op.batch_alter_table('sites', schema=None) as batch_op:
|
||||
batch_op.drop_column('custom_disclaimer')
|
||||
|
||||
with op.batch_alter_table('recommended_apps', schema=None) as batch_op:
|
||||
batch_op.drop_column('custom_disclaimer')
|
||||
|
||||
# ### end Alembic commands ###
|
@ -435,6 +435,7 @@ class RecommendedApp(db.Model):
|
||||
description = db.Column(db.JSON, nullable=False)
|
||||
copyright = db.Column(db.String(255), nullable=False)
|
||||
privacy_policy = db.Column(db.String(255), nullable=False)
|
||||
custom_disclaimer = db.Column(db.String(255), nullable=False)
|
||||
category = db.Column(db.String(255), nullable=False)
|
||||
position = db.Column(db.Integer, nullable=False, default=0)
|
||||
is_listed = db.Column(db.Boolean, nullable=False, default=True)
|
||||
@ -1042,6 +1043,7 @@ class Site(db.Model):
|
||||
default_language = db.Column(db.String(255), nullable=False)
|
||||
copyright = db.Column(db.String(255))
|
||||
privacy_policy = db.Column(db.String(255))
|
||||
custom_disclaimer = db.Column(db.String(255))
|
||||
customize_domain = db.Column(db.String(255))
|
||||
customize_token_strategy = db.Column(db.String(255), nullable=False)
|
||||
prompt_public = db.Column(db.Boolean, nullable=False, server_default=db.text('false'))
|
||||
|
@ -107,6 +107,8 @@ class ApiToolProvider(db.Model):
|
||||
credentials_str = db.Column(db.Text, nullable=False)
|
||||
# privacy policy
|
||||
privacy_policy = db.Column(db.String(255), nullable=True)
|
||||
# custom_disclaimer
|
||||
custom_disclaimer = db.Column(db.String(255), nullable=True)
|
||||
|
||||
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
|
||||
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
|
||||
|
@ -86,6 +86,7 @@ class RecommendedAppService:
|
||||
'description': site.description,
|
||||
'copyright': site.copyright,
|
||||
'privacy_policy': site.privacy_policy,
|
||||
'custom_disclaimer': site.custom_disclaimer,
|
||||
'category': recommended_app.category,
|
||||
'position': recommended_app.position,
|
||||
'is_listed': recommended_app.is_listed
|
||||
|
@ -177,7 +177,7 @@ class ToolManageService:
|
||||
@staticmethod
|
||||
def create_api_tool_provider(
|
||||
user_id: str, tenant_id: str, provider_name: str, icon: dict, credentials: dict,
|
||||
schema_type: str, schema: str, privacy_policy: str
|
||||
schema_type: str, schema: str, privacy_policy: str, custom_disclaimer: str
|
||||
):
|
||||
"""
|
||||
create api tool provider
|
||||
@ -213,7 +213,8 @@ class ToolManageService:
|
||||
schema_type_str=schema_type,
|
||||
tools_str=json.dumps(jsonable_encoder(tool_bundles)),
|
||||
credentials_str={},
|
||||
privacy_policy=privacy_policy
|
||||
privacy_policy=privacy_policy,
|
||||
custom_disclaimer=custom_disclaimer
|
||||
)
|
||||
|
||||
if 'auth_type' not in credentials:
|
||||
@ -364,7 +365,7 @@ class ToolManageService:
|
||||
@staticmethod
|
||||
def update_api_tool_provider(
|
||||
user_id: str, tenant_id: str, provider_name: str, original_provider: str, icon: dict, credentials: dict,
|
||||
schema_type: str, schema: str, privacy_policy: str
|
||||
schema_type: str, schema: str, privacy_policy: str, custom_disclaimer: str
|
||||
):
|
||||
"""
|
||||
update api tool provider
|
||||
@ -394,6 +395,7 @@ class ToolManageService:
|
||||
provider.schema_type_str = ApiProviderSchemaType.OPENAPI.value
|
||||
provider.tools_str = json.dumps(jsonable_encoder(tool_bundles))
|
||||
provider.privacy_policy = privacy_policy
|
||||
provider.custom_disclaimer = custom_disclaimer
|
||||
|
||||
if 'auth_type' not in credentials:
|
||||
raise ValueError('auth_type is required')
|
||||
|
@ -67,6 +67,7 @@ export type IChatProps = {
|
||||
visionConfig?: VisionSettings
|
||||
supportAnnotation?: boolean
|
||||
allToolIcons?: Record<string, string | Emoji>
|
||||
customDisclaimer?: string
|
||||
}
|
||||
|
||||
const Chat: FC<IChatProps> = ({
|
||||
@ -102,6 +103,7 @@ const Chat: FC<IChatProps> = ({
|
||||
supportAnnotation,
|
||||
onChatListChange,
|
||||
allToolIcons,
|
||||
customDisclaimer,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
@ -358,44 +360,46 @@ const Chat: FC<IChatProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={cn('p-[5.5px] max-h-[150px] bg-white border-[1.5px] border-gray-200 rounded-xl overflow-y-auto', isDragActive && 'border-primary-600')}>
|
||||
{visionConfig?.enabled && (
|
||||
<>
|
||||
<div className='absolute bottom-2 left-2 flex items-center'>
|
||||
<ChatImageUploader
|
||||
settings={visionConfig}
|
||||
onUpload={onUpload}
|
||||
disabled={files.length >= visionConfig.number_limits}
|
||||
/>
|
||||
<div className='mx-1 w-[1px] h-4 bg-black/5' />
|
||||
</div>
|
||||
<div className='pl-[52px]'>
|
||||
<ImageList
|
||||
list={files}
|
||||
onRemove={onRemove}
|
||||
onReUpload={onReUpload}
|
||||
onImageLinkLoadSuccess={onImageLinkLoadSuccess}
|
||||
onImageLinkLoadError={onImageLinkLoadError}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Textarea
|
||||
className={`
|
||||
block w-full px-2 pr-[118px] py-[7px] leading-5 max-h-none text-sm text-gray-700 outline-none appearance-none resize-none
|
||||
${visionConfig?.enabled && 'pl-12'}
|
||||
`}
|
||||
value={query}
|
||||
onChange={handleContentChange}
|
||||
onKeyUp={handleKeyUp}
|
||||
onKeyDown={handleKeyDown}
|
||||
onPaste={onPaste}
|
||||
onDragEnter={onDragEnter}
|
||||
onDragLeave={onDragLeave}
|
||||
onDragOver={onDragOver}
|
||||
onDrop={onDrop}
|
||||
autoSize
|
||||
/>
|
||||
<div className='relative'>
|
||||
<div className={cn('relative p-[5.5px] max-h-[150px] bg-white border-[1.5px] border-gray-200 rounded-xl overflow-y-auto', isDragActive && 'border-primary-600')}>
|
||||
{visionConfig?.enabled && (
|
||||
<>
|
||||
<div className='absolute bottom-2 left-2 flex items-center'>
|
||||
<ChatImageUploader
|
||||
settings={visionConfig}
|
||||
onUpload={onUpload}
|
||||
disabled={files.length >= visionConfig.number_limits}
|
||||
/>
|
||||
<div className='mx-1 w-[1px] h-4 bg-black/5' />
|
||||
</div>
|
||||
<div className='pl-[52px]'>
|
||||
<ImageList
|
||||
list={files}
|
||||
onRemove={onRemove}
|
||||
onReUpload={onReUpload}
|
||||
onImageLinkLoadSuccess={onImageLinkLoadSuccess}
|
||||
onImageLinkLoadError={onImageLinkLoadError}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Textarea
|
||||
className={`
|
||||
block w-full px-2 pr-[118px] py-[7px] leading-5 max-h-none text-sm text-gray-700 outline-none appearance-none resize-none
|
||||
${visionConfig?.enabled && 'pl-12'}
|
||||
`}
|
||||
value={query}
|
||||
onChange={handleContentChange}
|
||||
onKeyUp={handleKeyUp}
|
||||
onKeyDown={handleKeyDown}
|
||||
onPaste={onPaste}
|
||||
onDragEnter={onDragEnter}
|
||||
onDragLeave={onDragLeave}
|
||||
onDragOver={onDragOver}
|
||||
onDrop={onDrop}
|
||||
autoSize
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute bottom-2 right-2 flex items-center h-8">
|
||||
<div className={`${s.count} mr-4 h-5 leading-5 text-sm bg-gray-50 text-gray-500`}>{query.trim().length}</div>
|
||||
{
|
||||
@ -440,6 +444,9 @@ const Chat: FC<IChatProps> = ({
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{customDisclaimer && <div className='text-xs text-gray-500 mt-1 text-center'>
|
||||
{customDisclaimer}
|
||||
</div>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -31,6 +31,7 @@ export type ConfigParams = {
|
||||
prompt_public: boolean
|
||||
copyright: string
|
||||
privacy_policy: string
|
||||
custom_disclaimer: string
|
||||
icon: string
|
||||
icon_background: string
|
||||
}
|
||||
@ -46,8 +47,8 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
||||
const { notify } = useToastContext()
|
||||
const [isShowMore, setIsShowMore] = useState(false)
|
||||
const { icon, icon_background } = appInfo
|
||||
const { title, description, copyright, privacy_policy, default_language } = appInfo.site
|
||||
const [inputInfo, setInputInfo] = useState({ title, desc: description, copyright, privacyPolicy: privacy_policy })
|
||||
const { title, description, copyright, privacy_policy, custom_disclaimer, default_language } = appInfo.site
|
||||
const [inputInfo, setInputInfo] = useState({ title, desc: description, copyright, privacyPolicy: privacy_policy, customDisclaimer: custom_disclaimer })
|
||||
const [language, setLanguage] = useState(default_language)
|
||||
const [saveLoading, setSaveLoading] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
@ -56,7 +57,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
||||
const [emoji, setEmoji] = useState({ icon, icon_background })
|
||||
|
||||
useEffect(() => {
|
||||
setInputInfo({ title, desc: description, copyright, privacyPolicy: privacy_policy })
|
||||
setInputInfo({ title, desc: description, copyright, privacyPolicy: privacy_policy, customDisclaimer: custom_disclaimer })
|
||||
setLanguage(default_language)
|
||||
setEmoji({ icon, icon_background })
|
||||
}, [appInfo])
|
||||
@ -81,6 +82,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
||||
prompt_public: false,
|
||||
copyright: inputInfo.copyright,
|
||||
privacy_policy: inputInfo.privacyPolicy,
|
||||
custom_disclaimer: inputInfo.customDisclaimer,
|
||||
icon: emoji.icon,
|
||||
icon_background: emoji.icon_background,
|
||||
}
|
||||
@ -161,6 +163,13 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
||||
onChange={onChange('privacyPolicy')}
|
||||
placeholder={t(`${prefixSettings}.more.privacyPolicyPlaceholder`) as string}
|
||||
/>
|
||||
<div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.customDisclaimer`)}</div>
|
||||
<p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.more.customDisclaimerTip`)}</p>
|
||||
<input className={`w-full mt-2 rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
||||
value={inputInfo.customDisclaimer}
|
||||
onChange={onChange('customDisclaimer')}
|
||||
placeholder={t(`${prefixSettings}.more.customDisclaimerPlaceholder`) as string}
|
||||
/>
|
||||
</>}
|
||||
<div className='mt-10 flex justify-end'>
|
||||
<Button className='mr-2 flex-shrink-0 !text-sm' onClick={onHide}>{t('common.operation.cancel')}</Button>
|
||||
|
@ -14,6 +14,7 @@ import type {
|
||||
VisionConfig,
|
||||
} from '../types'
|
||||
import { TransferMethod } from '../types'
|
||||
import { useChatWithHistoryContext } from '../chat-with-history/context'
|
||||
import TooltipPlus from '@/app/components/base/tooltip-plus'
|
||||
import { ToastContext } from '@/app/components/base/toast'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
@ -40,6 +41,7 @@ const ChatInput: FC<ChatInputProps> = ({
|
||||
speechToTextConfig,
|
||||
onSend,
|
||||
}) => {
|
||||
const { appData } = useChatWithHistoryContext()
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
const [voiceInputShow, setVoiceInputShow] = useState(false)
|
||||
@ -127,101 +129,106 @@ const ChatInput: FC<ChatInputProps> = ({
|
||||
)
|
||||
|
||||
return (
|
||||
<div className='relative'>
|
||||
<div
|
||||
className={`
|
||||
p-[5.5px] max-h-[150px] bg-white border-[1.5px] border-gray-200 rounded-xl overflow-y-auto
|
||||
${isDragActive && 'border-primary-600'}
|
||||
`}
|
||||
>
|
||||
{
|
||||
visionConfig?.enabled && (
|
||||
<>
|
||||
<div className='absolute bottom-2 left-2 flex items-center'>
|
||||
<ChatImageUploader
|
||||
settings={visionConfig}
|
||||
onUpload={onUpload}
|
||||
disabled={files.length >= visionConfig.number_limits}
|
||||
/>
|
||||
<div className='mx-1 w-[1px] h-4 bg-black/5' />
|
||||
</div>
|
||||
<div className='pl-[52px]'>
|
||||
<ImageList
|
||||
list={files}
|
||||
onRemove={onRemove}
|
||||
onReUpload={onReUpload}
|
||||
onImageLinkLoadSuccess={onImageLinkLoadSuccess}
|
||||
onImageLinkLoadError={onImageLinkLoadError}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
<Textarea
|
||||
<>
|
||||
<div className='relative'>
|
||||
<div
|
||||
className={`
|
||||
block w-full px-2 pr-[118px] py-[7px] leading-5 max-h-none text-sm text-gray-700 outline-none appearance-none resize-none
|
||||
${visionConfig?.enabled && 'pl-12'}
|
||||
p-[5.5px] max-h-[150px] bg-white border-[1.5px] border-gray-200 rounded-xl overflow-y-auto
|
||||
${isDragActive && 'border-primary-600'} mb-2
|
||||
`}
|
||||
value={query}
|
||||
onChange={handleContentChange}
|
||||
onKeyUp={handleKeyUp}
|
||||
onKeyDown={handleKeyDown}
|
||||
onPaste={onPaste}
|
||||
onDragEnter={onDragEnter}
|
||||
onDragLeave={onDragLeave}
|
||||
onDragOver={onDragOver}
|
||||
onDrop={onDrop}
|
||||
autoSize
|
||||
/>
|
||||
<div className='absolute bottom-[7px] right-2 flex items-center h-8'>
|
||||
<div className='flex items-center px-1 h-5 rounded-md bg-gray-100 text-xs font-medium text-gray-500'>
|
||||
{query.trim().length}
|
||||
</div>
|
||||
>
|
||||
{
|
||||
query
|
||||
? (
|
||||
<div className='flex justify-center items-center ml-2 w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg' onClick={() => setQuery('')}>
|
||||
<XCircle className='w-4 h-4 text-[#98A2B3]' />
|
||||
visionConfig?.enabled && (
|
||||
<>
|
||||
<div className='absolute bottom-2 left-2 flex items-center'>
|
||||
<ChatImageUploader
|
||||
settings={visionConfig}
|
||||
onUpload={onUpload}
|
||||
disabled={files.length >= visionConfig.number_limits}
|
||||
/>
|
||||
<div className='mx-1 w-[1px] h-4 bg-black/5' />
|
||||
</div>
|
||||
)
|
||||
: speechToTextConfig?.enabled
|
||||
<div className='pl-[52px]'>
|
||||
<ImageList
|
||||
list={files}
|
||||
onRemove={onRemove}
|
||||
onReUpload={onReUpload}
|
||||
onImageLinkLoadSuccess={onImageLinkLoadSuccess}
|
||||
onImageLinkLoadError={onImageLinkLoadError}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
<Textarea
|
||||
className={`
|
||||
block w-full px-2 pr-[118px] py-[7px] leading-5 max-h-none text-sm text-gray-700 outline-none appearance-none resize-none
|
||||
${visionConfig?.enabled && 'pl-12'}
|
||||
`}
|
||||
value={query}
|
||||
onChange={handleContentChange}
|
||||
onKeyUp={handleKeyUp}
|
||||
onKeyDown={handleKeyDown}
|
||||
onPaste={onPaste}
|
||||
onDragEnter={onDragEnter}
|
||||
onDragLeave={onDragLeave}
|
||||
onDragOver={onDragOver}
|
||||
onDrop={onDrop}
|
||||
autoSize
|
||||
/>
|
||||
<div className='absolute bottom-[7px] right-2 flex items-center h-8'>
|
||||
<div className='flex items-center px-1 h-5 rounded-md bg-gray-100 text-xs font-medium text-gray-500'>
|
||||
{query.trim().length}
|
||||
</div>
|
||||
{
|
||||
query
|
||||
? (
|
||||
<div
|
||||
className='group flex justify-center items-center ml-2 w-8 h-8 hover:bg-primary-50 rounded-lg cursor-pointer'
|
||||
onClick={handleVoiceInputShow}
|
||||
>
|
||||
<Microphone01 className='block w-4 h-4 text-gray-500 group-hover:hidden' />
|
||||
<Microphone01Solid className='hidden w-4 h-4 text-primary-600 group-hover:block' />
|
||||
<div className='flex justify-center items-center ml-2 w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg' onClick={() => setQuery('')}>
|
||||
<XCircle className='w-4 h-4 text-[#98A2B3]' />
|
||||
</div>
|
||||
)
|
||||
: null
|
||||
: speechToTextConfig?.enabled
|
||||
? (
|
||||
<div
|
||||
className='group flex justify-center items-center ml-2 w-8 h-8 hover:bg-primary-50 rounded-lg cursor-pointer'
|
||||
onClick={handleVoiceInputShow}
|
||||
>
|
||||
<Microphone01 className='block w-4 h-4 text-gray-500 group-hover:hidden' />
|
||||
<Microphone01Solid className='hidden w-4 h-4 text-primary-600 group-hover:block' />
|
||||
</div>
|
||||
)
|
||||
: null
|
||||
}
|
||||
<div className='mx-2 w-[1px] h-4 bg-black opacity-5' />
|
||||
{isMobile
|
||||
? sendBtn
|
||||
: (
|
||||
<TooltipPlus
|
||||
popupContent={
|
||||
<div>
|
||||
<div>{t('common.operation.send')} Enter</div>
|
||||
<div>{t('common.operation.lineBreak')} Shift Enter</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{sendBtn}
|
||||
</TooltipPlus>
|
||||
)}
|
||||
</div>
|
||||
{
|
||||
voiceInputShow && (
|
||||
<VoiceInput
|
||||
onCancel={() => setVoiceInputShow(false)}
|
||||
onConverted={text => setQuery(text)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
<div className='mx-2 w-[1px] h-4 bg-black opacity-5' />
|
||||
{isMobile
|
||||
? sendBtn
|
||||
: (
|
||||
<TooltipPlus
|
||||
popupContent={
|
||||
<div>
|
||||
<div>{t('common.operation.send')} Enter</div>
|
||||
<div>{t('common.operation.lineBreak')} Shift Enter</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{sendBtn}
|
||||
</TooltipPlus>
|
||||
)}
|
||||
</div>
|
||||
{
|
||||
voiceInputShow && (
|
||||
<VoiceInput
|
||||
onCancel={() => setVoiceInputShow(false)}
|
||||
onConverted={text => setQuery(text)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{appData?.site?.custom_disclaimer && <div className='text-xs text-gray-500 mt-1 text-center'>
|
||||
{appData.site.custom_disclaimer}
|
||||
</div>}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -929,6 +929,7 @@ const Main: FC<IMainProps> = ({
|
||||
image_file_size_limit: fileUploadConfigResponse ? fileUploadConfigResponse.image_file_size_limit : visionConfig.image_file_size_limit,
|
||||
}}
|
||||
allToolIcons={appMeta?.tool_icons || {}}
|
||||
customDisclaimer={siteInfo.custom_disclaimer}
|
||||
/>
|
||||
</div>
|
||||
</div>)
|
||||
|
@ -800,6 +800,7 @@ const Main: FC<IMainProps> = ({
|
||||
answerIcon={<LogoAvatar className='relative shrink-0' />}
|
||||
visionConfig={visionConfig}
|
||||
allToolIcons={appMeta?.tool_icons || {}}
|
||||
customDisclaimer={siteInfo.custom_disclaimer}
|
||||
/>
|
||||
</div>
|
||||
</div>)
|
||||
|
@ -267,6 +267,19 @@ const EditCustomCollectionModal: FC<Props> = ({
|
||||
className='w-full h-10 px-3 text-sm font-normal bg-gray-100 rounded-lg grow' placeholder={t('tools.createTool.privacyPolicyPlaceholder') || ''} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={fieldNameClassNames}>{t('tools.createTool.customDisclaimer')}</div>
|
||||
<input
|
||||
value={customCollection.custom_disclaimer}
|
||||
onChange={(e) => {
|
||||
const newCollection = produce(customCollection, (draft) => {
|
||||
draft.custom_disclaimer = e.target.value
|
||||
})
|
||||
setCustomCollection(newCollection)
|
||||
}}
|
||||
className='w-full h-10 px-3 text-sm font-normal bg-gray-100 rounded-lg grow' placeholder={t('tools.createTool.customDisclaimerPlaceholder') || ''} />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className={cn(isEdit ? 'justify-between' : 'justify-end', 'mt-2 shrink-0 flex py-4 px-6 rounded-b-[10px] bg-gray-50 border-t border-black/5')} >
|
||||
{
|
||||
|
@ -89,6 +89,7 @@ export type CustomCollectionBackend = {
|
||||
schema_type: string
|
||||
schema: string
|
||||
privacy_policy: string
|
||||
custom_disclaimer: string
|
||||
tools?: ParamItem[]
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: 'Datenschutzrichtlinie',
|
||||
privacyPolicyPlaceholder: 'Geben Sie den Link zur Datenschutzrichtlinie ein',
|
||||
privacyPolicyTip: 'Hilft Besuchern zu verstehen, welche Daten die Anwendung sammelt, siehe Difys <privacyPolicyLink>Datenschutzrichtlinie</privacyPolicyLink>.',
|
||||
customDisclaimer: 'Benutzerdefinierte Haftungsausschluss',
|
||||
customDisclaimerPlaceholder: 'Geben Sie den benutzerdefinierten Haftungsausschluss-Text ein',
|
||||
customDisclaimerTip: 'Der ben userdefinierte Haftungsausschluss-Text wird auf der Clientseite angezeigt und bietet zusätzliche Informationen über die Anwendung',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -71,6 +71,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: 'Datenschutzrichtlinie',
|
||||
privacyPolicyPlaceholder: 'Bitte Datenschutzrichtlinie eingeben',
|
||||
customDisclaimer: 'Benutzer Haftungsausschluss',
|
||||
customDisclaimerPlaceholder: 'Bitte benutzerdefinierten Haftungsausschluss eingeben',
|
||||
},
|
||||
test: {
|
||||
title: 'Test',
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: 'Privacy Policy',
|
||||
privacyPolicyPlaceholder: 'Enter the privacy policy link',
|
||||
privacyPolicyTip: 'Helps visitors understand the data the application collects, see Dify\'s <privacyPolicyLink>Privacy Policy</privacyPolicyLink>.',
|
||||
customDisclaimer: 'Custom Disclaimer',
|
||||
customDisclaimerPlaceholder: 'Enter the custom disclaimer text',
|
||||
customDisclaimerTip: 'Custom disclaimer text will be displayed on the client side, providing additional information about the application',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -71,6 +71,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: 'Privacy policy',
|
||||
privacyPolicyPlaceholder: 'Please enter privacy policy',
|
||||
customDisclaimer: 'Custom disclaimer',
|
||||
customDisclaimerPlaceholder: 'Please enter custom disclaimer',
|
||||
},
|
||||
test: {
|
||||
title: 'Test',
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: 'Politique de confidentialité',
|
||||
privacyPolicyPlaceholder: 'Entrez le lien de la politique de confidentialité',
|
||||
privacyPolicyTip: 'Aide les visiteurs à comprendre les données collectées par l\'application, voir la <privacyPolicyLink>Politique de confidentialité</privacyPolicyLink> de Dify.',
|
||||
customDisclaimer: 'Clause de non-responsabilité personnalisée',
|
||||
customDisclaimerPlaceholder: 'Entrez le texte de la clause de non-responsabilité personnalisée',
|
||||
customDisclaimerTip: 'Le texte de la clause de non-responsabilité personnalisée sera affiché côté client, fournissant des informations supplémentaires sur l\'application',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -71,6 +71,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: 'Politique de confidentialité',
|
||||
privacyPolicyPlaceholder: 'Veuillez entrer la politique de confidentialité',
|
||||
customDisclaimer: 'Clause de non-responsabilité personnalisée',
|
||||
customDisclaimerPlaceholder: 'Entrez le texte de la clause de non-responsabilité personnalisée',
|
||||
},
|
||||
test: {
|
||||
title: 'Test',
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: 'プライバシーポリシー',
|
||||
privacyPolicyPlaceholder: 'プライバシーポリシーリンクを入力してください',
|
||||
privacyPolicyTip: '訪問者がアプリケーションが収集するデータを理解し、Difyの<privacyPolicyLink>プライバシーポリシー</privacyPolicyLink>を参照できるようにします。',
|
||||
customDisclaimer: 'カスタム免責事項',
|
||||
customDisclaimerPlaceholder: '免責事項を入力してください',
|
||||
customDisclaimerTip: 'アプリケーションの使用に関する免責事項を提供します。',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -71,6 +71,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: 'プライバシーポリシー',
|
||||
privacyPolicyPlaceholder: 'プライバシーポリシーを入力してください',
|
||||
customDisclaimer: 'カスタム免責事項',
|
||||
customDisclaimerPlaceholder: 'カスタム免責事項を入力してください',
|
||||
},
|
||||
test: {
|
||||
title: 'テスト',
|
||||
|
@ -55,6 +55,9 @@ const translation = {
|
||||
privacyPolicyPlaceholder: 'Wprowadź link do polityki prywatności',
|
||||
privacyPolicyTip:
|
||||
'Pomaga odwiedzającym zrozumieć, jakie dane zbiera aplikacja, zobacz <privacyPolicyLink>Politykę prywatności Dify</privacyPolicyLink>.',
|
||||
customDisclaimer: 'Oświadczenie o ochronie danych',
|
||||
customDisclaimerPlaceholder: 'Wprowadź oświadczenie o ochronie danych',
|
||||
customDisclaimerTip: 'Niestandardowy tekst oświadczenia będzie wyświetlany po stronie klienta, dostarczając dodatkowych informacji o aplikacji.',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -73,6 +73,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: 'Polityka prywatności',
|
||||
privacyPolicyPlaceholder: 'Proszę wprowadzić politykę prywatności',
|
||||
customDisclaimer: 'Oświadczenie niestandardowe',
|
||||
customDisclaimerPlaceholder: 'Proszę wprowadzić oświadczenie niestandardowe',
|
||||
},
|
||||
test: {
|
||||
title: 'Test',
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: 'Política de Privacidade',
|
||||
privacyPolicyPlaceholder: 'Insira o link da política de privacidade',
|
||||
privacyPolicyTip: 'Ajuda os visitantes a entender os dados coletados pelo aplicativo, consulte a <privacyPolicyLink>Política de Privacidade</privacyPolicyLink> do Dify.',
|
||||
customDisclaimer: 'Aviso Legal Personalizado',
|
||||
customDisclaimerPlaceholder: 'Insira o texto do aviso legal',
|
||||
customDisclaimerTip: 'O texto do aviso legal personalizado será exibido no lado do cliente, fornecendo informações adicionais sobre o aplicativo',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -71,6 +71,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: 'Política de Privacidade',
|
||||
privacyPolicyPlaceholder: 'Digite a política de privacidade',
|
||||
customDisclaimer: 'Aviso Personalizado',
|
||||
customDisclaimerPlaceholder: 'Digite o aviso personalizado',
|
||||
},
|
||||
test: {
|
||||
title: 'Testar',
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: 'Політика конфіденційності',
|
||||
privacyPolicyPlaceholder: 'Введіть посилання на політику конфіденційності',
|
||||
privacyPolicyTip: 'Допомагає відвідувачам зрозуміти дані, зібрані додатком, див. <privacyPolicyLink>Політику конфіденційності</privacyPolicyLink> Dify.',
|
||||
customDisclaimer: 'Відмова від відповідальності',
|
||||
customDisclaimerPlaceholder: 'Введіть відмову від відповідальності',
|
||||
customDisclaimerTip: 'Відображається на клієнтському боці, щоб визначити відповідальність за використання додатка',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -70,6 +70,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: 'Політика конфіденційності',
|
||||
privacyPolicyPlaceholder: 'Введіть політику конфіденційності',
|
||||
customDisclaimer: 'Власний відомості',
|
||||
customDisclaimerPlaceholder: 'Введіть власні відомості',
|
||||
},
|
||||
|
||||
test: {
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: 'Chính sách bảo mật',
|
||||
privacyPolicyPlaceholder: 'Nhập liên kết chính sách bảo mật',
|
||||
privacyPolicyTip: 'Giúp khách truy cập hiểu được dữ liệu mà ứng dụng thu thập, xem <privacyPolicyLink>Chính sách bảo mật</privacyPolicyLink> của Dify.',
|
||||
customDisclaimer: 'Tùy chỉnh từ chối trách nhiệm',
|
||||
customDisclaimerPlaceholder: 'Nhập liên kết từ chối trách nhiệm',
|
||||
customDisclaimerTip: 'Liên kết này sẽ được hiển thị ở phía máy khách, cung cấp thông tin về trách nhiệm của ứng dụng',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -71,6 +71,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: 'Chính sách bảo mật',
|
||||
privacyPolicyPlaceholder: 'Vui lòng nhập chính sách bảo mật',
|
||||
customDisclaimer: 'Tuyên bố Tùy chỉnh',
|
||||
customDisclaimerPlaceholder: 'Vui lòng nhập tuyên bố tùy chỉnh',
|
||||
},
|
||||
test: {
|
||||
title: 'Kiểm tra',
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: '隐私政策',
|
||||
privacyPolicyPlaceholder: '请输入隐私政策链接',
|
||||
privacyPolicyTip: '帮助访问者了解该应用收集的数据,可参考 Dify 的<privacyPolicyLink>隐私政策</privacyPolicyLink>。',
|
||||
customDisclaimer: '自定义免责声明',
|
||||
customDisclaimerPlaceholder: '请输入免责声明',
|
||||
customDisclaimerTip: '在应用中展示免责声明,可用于告知用户 AI 的局限性。',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -71,6 +71,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: '隐私协议',
|
||||
privacyPolicyPlaceholder: '请输入隐私协议',
|
||||
customDisclaimer: '自定义免责声明',
|
||||
customDisclaimerPlaceholder: '请输入自定义免责声明',
|
||||
},
|
||||
test: {
|
||||
title: '测试',
|
||||
|
@ -50,6 +50,9 @@ const translation = {
|
||||
privacyPolicy: '隱私政策',
|
||||
privacyPolicyPlaceholder: '請輸入隱私政策連結',
|
||||
privacyPolicyTip: '幫助訪問者瞭解該應用收集的資料,可參考 Dify 的<privacyPolicyLink>隱私政策</privacyPolicyLink>。',
|
||||
customDisclaimer: '自定義免責聲明',
|
||||
customDisclaimerPlaceholder: '請輸入免責聲明',
|
||||
customDisclaimerTip: '客製化的免責聲明文字將在客戶端顯示,提供有關應用程式的額外資訊。',
|
||||
},
|
||||
},
|
||||
embedded: {
|
||||
|
@ -71,6 +71,8 @@ const translation = {
|
||||
},
|
||||
privacyPolicy: '隱私協議',
|
||||
privacyPolicyPlaceholder: '請輸入隱私協議',
|
||||
customDisclaimer: '自定義免責聲明',
|
||||
customDisclaimerPlaceholder: '請輸入自定義免責聲明',
|
||||
},
|
||||
test: {
|
||||
title: '測試',
|
||||
|
@ -16,6 +16,7 @@ export type App = {
|
||||
description: string
|
||||
copyright: string
|
||||
privacy_policy: string | null
|
||||
custom_disclaimer: string | null
|
||||
category: AppCategory
|
||||
position: number
|
||||
is_listed: boolean
|
||||
|
@ -18,6 +18,7 @@ export type SiteInfo = {
|
||||
prompt_public?: boolean
|
||||
copyright?: string
|
||||
privacy_policy?: string
|
||||
custom_disclaimer?: string
|
||||
}
|
||||
|
||||
export type AppMeta = {
|
||||
|
@ -269,6 +269,8 @@ export type SiteConfig = {
|
||||
copyright: string
|
||||
/** Privacy Policy */
|
||||
privacy_policy: string
|
||||
/** Custom Disclaimer */
|
||||
custom_disclaimer: string
|
||||
|
||||
icon: string
|
||||
icon_background: string
|
||||
|
Loading…
x
Reference in New Issue
Block a user