| "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", | "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, | "is_listed": true, | ||||
| "position": 0, | "position": 0, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "Code interpreter, clarifying the syntax and semantics of the code.", | "description": "Code interpreter, clarifying the syntax and semantics of the code.", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 13, | "position": 13, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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. ", | "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, | "is_listed": true, | ||||
| "position": 4, | "position": 4, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "Fully SEO Optimized Article including FAQs", | "description": "Fully SEO Optimized Article including FAQs", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 1, | "position": 1, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "Generate Flat Style Image", | "description": "Generate Flat Style Image", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 10, | "position": 10, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "A multilingual translator that provides translation capabilities in multiple languages. Input the text you need to translate and select the target language.", | "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, | "is_listed": true, | ||||
| "position": 10, | "position": 10, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "I am a YouTube Channel Data Analysis Copilot, I am here to provide expert data analysis tailored to your needs. ", | "description": "I am a YouTube Channel Data Analysis Copilot, I am here to provide expert data analysis tailored to your needs. ", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 2, | "position": 2, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "Meeting minutes generator", | "description": "Meeting minutes generator", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 0, | "position": 0, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "Tell me the main elements, I will generate a cyberpunk style image for you. ", | "description": "Tell me the main elements, I will generate a cyberpunk style image for you. ", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 10, | "position": 10, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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.", | "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, | "is_listed": true, | ||||
| "position": 13, | "position": 13, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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. ", | "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, | "is_listed": true, | ||||
| "position": 3, | "position": 3, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "I can answer your questions related to strategic marketing.", | "description": "I can answer your questions related to strategic marketing.", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 10, | "position": 10, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "A simulated front-end interviewer that tests the skill level of front-end development through questioning.", | "description": "A simulated front-end interviewer that tests the skill level of front-end development through questioning.", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 19, | "position": 19, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "I'm here to hear about your feature request about Dify and help you flesh it out further. What's on your mind?", | "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, | "is_listed": true, | ||||
| "position": 6, | "position": 6, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| } | } | ||||
| ] | ] | ||||
| }, | }, | ||||
| "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", | "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, | "is_listed": true, | ||||
| "position": 20, | "position": 20, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "\u8f93\u5165\u76f8\u5173\u5143\u7d20\uff0c\u4e3a\u4f60\u751f\u6210\u6241\u5e73\u63d2\u753b\u98ce\u683c\u7684\u5c01\u9762\u56fe\u7247", | "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, | "is_listed": true, | ||||
| "position": 10, | "position": 10, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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", | "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, | "is_listed": true, | ||||
| "position": 10, | "position": 10, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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", | "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, | "is_listed": true, | ||||
| "position": 12, | "position": 12, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "\u9610\u660e\u4ee3\u7801\u7684\u8bed\u6cd5\u548c\u8bed\u4e49\u3002", | "description": "\u9610\u660e\u4ee3\u7801\u7684\u8bed\u6cd5\u548c\u8bed\u4e49\u3002", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 2, | "position": 2, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "\u8f93\u5165\u76f8\u5173\u5143\u7d20\uff0c\u4e3a\u4f60\u751f\u6210\u8d5b\u535a\u670b\u514b\u98ce\u683c\u7684\u63d2\u753b", | "description": "\u8f93\u5165\u76f8\u5173\u5143\u7d20\uff0c\u4e3a\u4f60\u751f\u6210\u8d5b\u535a\u670b\u514b\u98ce\u683c\u7684\u63d2\u753b", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 10, | "position": 10, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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", | "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, | "is_listed": true, | ||||
| "position": 10, | "position": 10, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "\u5e2e\u4f60\u91cd\u65b0\u7ec4\u7ec7\u548c\u8f93\u51fa\u6df7\u4e71\u590d\u6742\u7684\u4f1a\u8bae\u7eaa\u8981\u3002", | "description": "\u5e2e\u4f60\u91cd\u65b0\u7ec4\u7ec7\u548c\u8f93\u51fa\u6df7\u4e71\u590d\u6742\u7684\u4f1a\u8bae\u7eaa\u8981\u3002", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 6, | "position": 6, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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", | "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, | "is_listed": true, | ||||
| "position": 0, | "position": 0, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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", | "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, | "is_listed": true, | ||||
| "position": 4, | "position": 4, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "\u7ffb\u8bd1\u4e13\u5bb6\uff1a\u63d0\u4f9b\u4e2d\u82f1\u6587\u4e92\u8bd1", | "description": "\u7ffb\u8bd1\u4e13\u5bb6\uff1a\u63d0\u4f9b\u4e2d\u82f1\u6587\u4e92\u8bd1", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 4, | "position": 4, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "\u60a8\u7684\u79c1\u4eba\u5b66\u4e60\u5bfc\u5e08\uff0c\u5e2e\u60a8\u5236\u5b9a\u5b66\u4e60\u8ba1\u5212\u5e76\u8f85\u5bfc", | "description": "\u60a8\u7684\u79c1\u4eba\u5b66\u4e60\u5bfc\u5e08\uff0c\u5e2e\u60a8\u5236\u5b9a\u5b66\u4e60\u8ba1\u5212\u5e76\u8f85\u5bfc", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 26, | "position": 26, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "description": "\u5e2e\u4f60\u64b0\u5199\u8bba\u6587\u6587\u732e\u7efc\u8ff0", | "description": "\u5e2e\u4f60\u64b0\u5199\u8bba\u6587\u6587\u732e\u7efc\u8ff0", | ||||
| "is_listed": true, | "is_listed": true, | ||||
| "position": 7, | "position": 7, | ||||
| "privacy_policy": "https://dify.ai" | |||||
| "privacy_policy": "https://dify.ai", | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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", | "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, | "is_listed": true, | ||||
| "position": 0, | "position": 0, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| }, | }, | ||||
| { | { | ||||
| "app": { | "app": { | ||||
| "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", | "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, | "is_listed": true, | ||||
| "position": 0, | "position": 0, | ||||
| "privacy_policy": null | |||||
| "privacy_policy": null, | |||||
| "custom_disclaimer": null | |||||
| } | } | ||||
| ] | ] | ||||
| }, | }, |
| parser.add_argument('desc', type=str, location='json') | parser.add_argument('desc', type=str, location='json') | ||||
| parser.add_argument('copyright', type=str, location='json') | parser.add_argument('copyright', type=str, location='json') | ||||
| parser.add_argument('privacy_policy', 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('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('category', type=str, required=True, nullable=False, location='json') | ||||
| parser.add_argument('position', type=int, required=True, nullable=False, location='json') | parser.add_argument('position', type=int, required=True, nullable=False, location='json') | ||||
| desc = args['desc'] if args['desc'] else '' | desc = args['desc'] if args['desc'] else '' | ||||
| copy_right = args['copyright'] if args['copyright'] else '' | copy_right = args['copyright'] if args['copyright'] else '' | ||||
| privacy_policy = args['privacy_policy'] if args['privacy_policy'] else '' | privacy_policy = args['privacy_policy'] if args['privacy_policy'] else '' | ||||
| custom_disclaimer = args['custom_disclaimer'] if args['custom_disclaimer'] else '' | |||||
| else: | else: | ||||
| desc = site.description if site.description else \ | desc = site.description if site.description else \ | ||||
| args['desc'] if args['desc'] else '' | args['desc'] if args['desc'] else '' | ||||
| args['copyright'] if args['copyright'] else '' | args['copyright'] if args['copyright'] else '' | ||||
| privacy_policy = site.privacy_policy if site.privacy_policy else \ | privacy_policy = site.privacy_policy if site.privacy_policy else \ | ||||
| args['privacy_policy'] if args['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() | recommended_app = RecommendedApp.query.filter(RecommendedApp.app_id == args['app_id']).first() | ||||
| description=desc, | description=desc, | ||||
| copyright=copy_right, | copyright=copy_right, | ||||
| privacy_policy=privacy_policy, | privacy_policy=privacy_policy, | ||||
| custom_disclaimer=custom_disclaimer, | |||||
| language=args['language'], | language=args['language'], | ||||
| category=args['category'], | category=args['category'], | ||||
| position=args['position'] | position=args['position'] | ||||
| recommended_app.description = desc | recommended_app.description = desc | ||||
| recommended_app.copyright = copy_right | recommended_app.copyright = copy_right | ||||
| recommended_app.privacy_policy = privacy_policy | recommended_app.privacy_policy = privacy_policy | ||||
| recommended_app.custom_disclaimer = custom_disclaimer | |||||
| recommended_app.language = args['language'] | recommended_app.language = args['language'] | ||||
| recommended_app.category = args['category'] | recommended_app.category = args['category'] | ||||
| recommended_app.position = args['position'] | recommended_app.position = args['position'] |
| parser.add_argument('customize_domain', type=str, required=False, location='json') | parser.add_argument('customize_domain', type=str, required=False, location='json') | ||||
| parser.add_argument('copyright', 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('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'], | parser.add_argument('customize_token_strategy', type=str, choices=['must', 'allow', 'not_allow'], | ||||
| required=False, | required=False, | ||||
| location='json') | location='json') | ||||
| 'customize_domain', | 'customize_domain', | ||||
| 'copyright', | 'copyright', | ||||
| 'privacy_policy', | 'privacy_policy', | ||||
| 'custom_disclaimer', | |||||
| 'customize_token_strategy', | 'customize_token_strategy', | ||||
| 'prompt_public' | 'prompt_public' | ||||
| ]: | ]: |
| 'description': fields.String(attribute='description'), | 'description': fields.String(attribute='description'), | ||||
| 'copyright': fields.String, | 'copyright': fields.String, | ||||
| 'privacy_policy': fields.String, | 'privacy_policy': fields.String, | ||||
| 'custom_disclaimer': fields.String, | |||||
| 'category': fields.String, | 'category': fields.String, | ||||
| 'position': fields.Integer, | 'position': fields.Integer, | ||||
| 'is_listed': fields.Boolean | 'is_listed': fields.Boolean |
| parser.add_argument('provider', type=str, required=True, nullable=False, location='json') | 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('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('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() | args = parser.parse_args() | ||||
| args['schema_type'], | args['schema_type'], | ||||
| args['schema'], | args['schema'], | ||||
| args.get('privacy_policy', ''), | args.get('privacy_policy', ''), | ||||
| args.get('custom_disclaimer', ''), | |||||
| ) | ) | ||||
| class ToolApiProviderGetRemoteSchemaApi(Resource): | class ToolApiProviderGetRemoteSchemaApi(Resource): | ||||
| parser.add_argument('original_provider', type=str, required=True, nullable=False, location='json') | 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('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('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() | args = parser.parse_args() | ||||
| args['schema_type'], | args['schema_type'], | ||||
| args['schema'], | args['schema'], | ||||
| args['privacy_policy'], | args['privacy_policy'], | ||||
| args['custom_disclaimer'], | |||||
| ) | ) | ||||
| class ToolApiProviderDeleteApi(Resource): | class ToolApiProviderDeleteApi(Resource): |
| 'description': fields.String, | 'description': fields.String, | ||||
| 'copyright': fields.String, | 'copyright': fields.String, | ||||
| 'privacy_policy': fields.String, | 'privacy_policy': fields.String, | ||||
| 'custom_disclaimer': fields.String, | |||||
| 'default_language': fields.String, | 'default_language': fields.String, | ||||
| 'prompt_public': fields.Boolean | 'prompt_public': fields.Boolean | ||||
| } | } |
| 'icon': icon, | 'icon': icon, | ||||
| 'description': provider.description, | 'description': provider.description, | ||||
| 'credentials': masked_credentials, | 'credentials': masked_credentials, | ||||
| 'privacy_policy': provider.privacy_policy | |||||
| 'privacy_policy': provider.privacy_policy, | |||||
| 'custom_disclaimer': provider.custom_disclaimer | |||||
| }) | }) | ||||
| @classmethod | @classmethod |
| 'customize_domain': fields.String, | 'customize_domain': fields.String, | ||||
| 'copyright': fields.String, | 'copyright': fields.String, | ||||
| 'privacy_policy': fields.String, | 'privacy_policy': fields.String, | ||||
| 'custom_disclaimer': fields.String, | |||||
| 'customize_token_strategy': fields.String, | 'customize_token_strategy': fields.String, | ||||
| 'prompt_public': fields.Boolean, | 'prompt_public': fields.Boolean, | ||||
| 'app_base_url': fields.String, | 'app_base_url': fields.String, | ||||
| 'customize_domain': fields.String, | 'customize_domain': fields.String, | ||||
| 'copyright': fields.String, | 'copyright': fields.String, | ||||
| 'privacy_policy': fields.String, | 'privacy_policy': fields.String, | ||||
| 'custom_disclaimer': fields.String, | |||||
| 'customize_token_strategy': fields.String, | 'customize_token_strategy': fields.String, | ||||
| 'prompt_public': fields.Boolean | 'prompt_public': fields.Boolean | ||||
| } | } |
| """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 ### |
| description = db.Column(db.JSON, nullable=False) | description = db.Column(db.JSON, nullable=False) | ||||
| copyright = db.Column(db.String(255), nullable=False) | copyright = db.Column(db.String(255), nullable=False) | ||||
| privacy_policy = 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) | category = db.Column(db.String(255), nullable=False) | ||||
| position = db.Column(db.Integer, nullable=False, default=0) | position = db.Column(db.Integer, nullable=False, default=0) | ||||
| is_listed = db.Column(db.Boolean, nullable=False, default=True) | is_listed = db.Column(db.Boolean, nullable=False, default=True) | ||||
| default_language = db.Column(db.String(255), nullable=False) | default_language = db.Column(db.String(255), nullable=False) | ||||
| copyright = db.Column(db.String(255)) | copyright = db.Column(db.String(255)) | ||||
| privacy_policy = 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_domain = db.Column(db.String(255)) | ||||
| customize_token_strategy = db.Column(db.String(255), nullable=False) | customize_token_strategy = db.Column(db.String(255), nullable=False) | ||||
| prompt_public = db.Column(db.Boolean, nullable=False, server_default=db.text('false')) | prompt_public = db.Column(db.Boolean, nullable=False, server_default=db.text('false')) |
| credentials_str = db.Column(db.Text, nullable=False) | credentials_str = db.Column(db.Text, nullable=False) | ||||
| # privacy policy | # privacy policy | ||||
| privacy_policy = db.Column(db.String(255), nullable=True) | 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)')) | 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)')) | updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)')) |
| 'description': site.description, | 'description': site.description, | ||||
| 'copyright': site.copyright, | 'copyright': site.copyright, | ||||
| 'privacy_policy': site.privacy_policy, | 'privacy_policy': site.privacy_policy, | ||||
| 'custom_disclaimer': site.custom_disclaimer, | |||||
| 'category': recommended_app.category, | 'category': recommended_app.category, | ||||
| 'position': recommended_app.position, | 'position': recommended_app.position, | ||||
| 'is_listed': recommended_app.is_listed | 'is_listed': recommended_app.is_listed |
| @staticmethod | @staticmethod | ||||
| def create_api_tool_provider( | def create_api_tool_provider( | ||||
| user_id: str, tenant_id: str, provider_name: str, icon: dict, credentials: dict, | 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 | create api tool provider | ||||
| schema_type_str=schema_type, | schema_type_str=schema_type, | ||||
| tools_str=json.dumps(jsonable_encoder(tool_bundles)), | tools_str=json.dumps(jsonable_encoder(tool_bundles)), | ||||
| credentials_str={}, | credentials_str={}, | ||||
| privacy_policy=privacy_policy | |||||
| privacy_policy=privacy_policy, | |||||
| custom_disclaimer=custom_disclaimer | |||||
| ) | ) | ||||
| if 'auth_type' not in credentials: | if 'auth_type' not in credentials: | ||||
| @staticmethod | @staticmethod | ||||
| def update_api_tool_provider( | def update_api_tool_provider( | ||||
| user_id: str, tenant_id: str, provider_name: str, original_provider: str, icon: dict, credentials: dict, | 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 | update api tool provider | ||||
| provider.schema_type_str = ApiProviderSchemaType.OPENAPI.value | provider.schema_type_str = ApiProviderSchemaType.OPENAPI.value | ||||
| provider.tools_str = json.dumps(jsonable_encoder(tool_bundles)) | provider.tools_str = json.dumps(jsonable_encoder(tool_bundles)) | ||||
| provider.privacy_policy = privacy_policy | provider.privacy_policy = privacy_policy | ||||
| provider.custom_disclaimer = custom_disclaimer | |||||
| if 'auth_type' not in credentials: | if 'auth_type' not in credentials: | ||||
| raise ValueError('auth_type is required') | raise ValueError('auth_type is required') |
| visionConfig?: VisionSettings | visionConfig?: VisionSettings | ||||
| supportAnnotation?: boolean | supportAnnotation?: boolean | ||||
| allToolIcons?: Record<string, string | Emoji> | allToolIcons?: Record<string, string | Emoji> | ||||
| customDisclaimer?: string | |||||
| } | } | ||||
| const Chat: FC<IChatProps> = ({ | const Chat: FC<IChatProps> = ({ | ||||
| supportAnnotation, | supportAnnotation, | ||||
| onChatListChange, | onChatListChange, | ||||
| allToolIcons, | allToolIcons, | ||||
| customDisclaimer, | |||||
| }) => { | }) => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const { notify } = useContext(ToastContext) | const { notify } = useContext(ToastContext) | ||||
| </div> | </div> | ||||
| </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="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> | <div className={`${s.count} mr-4 h-5 leading-5 text-sm bg-gray-50 text-gray-500`}>{query.trim().length}</div> | ||||
| { | { | ||||
| /> | /> | ||||
| )} | )} | ||||
| </div> | </div> | ||||
| {customDisclaimer && <div className='text-xs text-gray-500 mt-1 text-center'> | |||||
| {customDisclaimer} | |||||
| </div>} | |||||
| </div> | </div> | ||||
| )} | )} | ||||
| </div> | </div> |
| prompt_public: boolean | prompt_public: boolean | ||||
| copyright: string | copyright: string | ||||
| privacy_policy: string | privacy_policy: string | ||||
| custom_disclaimer: string | |||||
| icon: string | icon: string | ||||
| icon_background: string | icon_background: string | ||||
| } | } | ||||
| const { notify } = useToastContext() | const { notify } = useToastContext() | ||||
| const [isShowMore, setIsShowMore] = useState(false) | const [isShowMore, setIsShowMore] = useState(false) | ||||
| const { icon, icon_background } = appInfo | 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 [language, setLanguage] = useState(default_language) | ||||
| const [saveLoading, setSaveLoading] = useState(false) | const [saveLoading, setSaveLoading] = useState(false) | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const [emoji, setEmoji] = useState({ icon, icon_background }) | const [emoji, setEmoji] = useState({ icon, icon_background }) | ||||
| useEffect(() => { | useEffect(() => { | ||||
| setInputInfo({ title, desc: description, copyright, privacyPolicy: privacy_policy }) | |||||
| setInputInfo({ title, desc: description, copyright, privacyPolicy: privacy_policy, customDisclaimer: custom_disclaimer }) | |||||
| setLanguage(default_language) | setLanguage(default_language) | ||||
| setEmoji({ icon, icon_background }) | setEmoji({ icon, icon_background }) | ||||
| }, [appInfo]) | }, [appInfo]) | ||||
| prompt_public: false, | prompt_public: false, | ||||
| copyright: inputInfo.copyright, | copyright: inputInfo.copyright, | ||||
| privacy_policy: inputInfo.privacyPolicy, | privacy_policy: inputInfo.privacyPolicy, | ||||
| custom_disclaimer: inputInfo.customDisclaimer, | |||||
| icon: emoji.icon, | icon: emoji.icon, | ||||
| icon_background: emoji.icon_background, | icon_background: emoji.icon_background, | ||||
| } | } | ||||
| onChange={onChange('privacyPolicy')} | onChange={onChange('privacyPolicy')} | ||||
| placeholder={t(`${prefixSettings}.more.privacyPolicyPlaceholder`) as string} | 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'> | <div className='mt-10 flex justify-end'> | ||||
| <Button className='mr-2 flex-shrink-0 !text-sm' onClick={onHide}>{t('common.operation.cancel')}</Button> | <Button className='mr-2 flex-shrink-0 !text-sm' onClick={onHide}>{t('common.operation.cancel')}</Button> |
| VisionConfig, | VisionConfig, | ||||
| } from '../types' | } from '../types' | ||||
| import { TransferMethod } from '../types' | import { TransferMethod } from '../types' | ||||
| import { useChatWithHistoryContext } from '../chat-with-history/context' | |||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | import TooltipPlus from '@/app/components/base/tooltip-plus' | ||||
| import { ToastContext } from '@/app/components/base/toast' | import { ToastContext } from '@/app/components/base/toast' | ||||
| import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | ||||
| speechToTextConfig, | speechToTextConfig, | ||||
| onSend, | onSend, | ||||
| }) => { | }) => { | ||||
| const { appData } = useChatWithHistoryContext() | |||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const { notify } = useContext(ToastContext) | const { notify } = useContext(ToastContext) | ||||
| const [voiceInputShow, setVoiceInputShow] = useState(false) | const [voiceInputShow, setVoiceInputShow] = useState(false) | ||||
| ) | ) | ||||
| return ( | 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={` | 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> | </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> | </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> | </div> | ||||
| { | |||||
| voiceInputShow && ( | |||||
| <VoiceInput | |||||
| onCancel={() => setVoiceInputShow(false)} | |||||
| onConverted={text => setQuery(text)} | |||||
| /> | |||||
| ) | |||||
| } | |||||
| </div> | </div> | ||||
| </div> | |||||
| {appData?.site?.custom_disclaimer && <div className='text-xs text-gray-500 mt-1 text-center'> | |||||
| {appData.site.custom_disclaimer} | |||||
| </div>} | |||||
| </> | |||||
| ) | ) | ||||
| } | } | ||||
| image_file_size_limit: fileUploadConfigResponse ? fileUploadConfigResponse.image_file_size_limit : visionConfig.image_file_size_limit, | image_file_size_limit: fileUploadConfigResponse ? fileUploadConfigResponse.image_file_size_limit : visionConfig.image_file_size_limit, | ||||
| }} | }} | ||||
| allToolIcons={appMeta?.tool_icons || {}} | allToolIcons={appMeta?.tool_icons || {}} | ||||
| customDisclaimer={siteInfo.custom_disclaimer} | |||||
| /> | /> | ||||
| </div> | </div> | ||||
| </div>) | </div>) |
| answerIcon={<LogoAvatar className='relative shrink-0' />} | answerIcon={<LogoAvatar className='relative shrink-0' />} | ||||
| visionConfig={visionConfig} | visionConfig={visionConfig} | ||||
| allToolIcons={appMeta?.tool_icons || {}} | allToolIcons={appMeta?.tool_icons || {}} | ||||
| customDisclaimer={siteInfo.custom_disclaimer} | |||||
| /> | /> | ||||
| </div> | </div> | ||||
| </div>) | </div>) |
| className='w-full h-10 px-3 text-sm font-normal bg-gray-100 rounded-lg grow' placeholder={t('tools.createTool.privacyPolicyPlaceholder') || ''} /> | 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> | |||||
| <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> | ||||
| <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')} > | <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')} > | ||||
| { | { |
| schema_type: string | schema_type: string | ||||
| schema: string | schema: string | ||||
| privacy_policy: string | privacy_policy: string | ||||
| custom_disclaimer: string | |||||
| tools?: ParamItem[] | tools?: ParamItem[] | ||||
| } | } | ||||
| privacyPolicy: 'Datenschutzrichtlinie', | privacyPolicy: 'Datenschutzrichtlinie', | ||||
| privacyPolicyPlaceholder: 'Geben Sie den Link zur Datenschutzrichtlinie ein', | privacyPolicyPlaceholder: 'Geben Sie den Link zur Datenschutzrichtlinie ein', | ||||
| privacyPolicyTip: 'Hilft Besuchern zu verstehen, welche Daten die Anwendung sammelt, siehe Difys <privacyPolicyLink>Datenschutzrichtlinie</privacyPolicyLink>.', | 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: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: 'Datenschutzrichtlinie', | privacyPolicy: 'Datenschutzrichtlinie', | ||||
| privacyPolicyPlaceholder: 'Bitte Datenschutzrichtlinie eingeben', | privacyPolicyPlaceholder: 'Bitte Datenschutzrichtlinie eingeben', | ||||
| customDisclaimer: 'Benutzer Haftungsausschluss', | |||||
| customDisclaimerPlaceholder: 'Bitte benutzerdefinierten Haftungsausschluss eingeben', | |||||
| }, | }, | ||||
| test: { | test: { | ||||
| title: 'Test', | title: 'Test', |
| privacyPolicy: 'Privacy Policy', | privacyPolicy: 'Privacy Policy', | ||||
| privacyPolicyPlaceholder: 'Enter the privacy policy link', | privacyPolicyPlaceholder: 'Enter the privacy policy link', | ||||
| privacyPolicyTip: 'Helps visitors understand the data the application collects, see Dify\'s <privacyPolicyLink>Privacy Policy</privacyPolicyLink>.', | 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: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: 'Privacy policy', | privacyPolicy: 'Privacy policy', | ||||
| privacyPolicyPlaceholder: 'Please enter privacy policy', | privacyPolicyPlaceholder: 'Please enter privacy policy', | ||||
| customDisclaimer: 'Custom disclaimer', | |||||
| customDisclaimerPlaceholder: 'Please enter custom disclaimer', | |||||
| }, | }, | ||||
| test: { | test: { | ||||
| title: 'Test', | title: 'Test', |
| privacyPolicy: 'Politique de confidentialité', | privacyPolicy: 'Politique de confidentialité', | ||||
| privacyPolicyPlaceholder: 'Entrez le lien de la 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.', | 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: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: 'Politique de confidentialité', | privacyPolicy: 'Politique de confidentialité', | ||||
| privacyPolicyPlaceholder: 'Veuillez entrer la 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: { | test: { | ||||
| title: 'Test', | title: 'Test', |
| privacyPolicy: 'プライバシーポリシー', | privacyPolicy: 'プライバシーポリシー', | ||||
| privacyPolicyPlaceholder: 'プライバシーポリシーリンクを入力してください', | privacyPolicyPlaceholder: 'プライバシーポリシーリンクを入力してください', | ||||
| privacyPolicyTip: '訪問者がアプリケーションが収集するデータを理解し、Difyの<privacyPolicyLink>プライバシーポリシー</privacyPolicyLink>を参照できるようにします。', | privacyPolicyTip: '訪問者がアプリケーションが収集するデータを理解し、Difyの<privacyPolicyLink>プライバシーポリシー</privacyPolicyLink>を参照できるようにします。', | ||||
| customDisclaimer: 'カスタム免責事項', | |||||
| customDisclaimerPlaceholder: '免責事項を入力してください', | |||||
| customDisclaimerTip: 'アプリケーションの使用に関する免責事項を提供します。', | |||||
| }, | }, | ||||
| }, | }, | ||||
| embedded: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: 'プライバシーポリシー', | privacyPolicy: 'プライバシーポリシー', | ||||
| privacyPolicyPlaceholder: 'プライバシーポリシーを入力してください', | privacyPolicyPlaceholder: 'プライバシーポリシーを入力してください', | ||||
| customDisclaimer: 'カスタム免責事項', | |||||
| customDisclaimerPlaceholder: 'カスタム免責事項を入力してください', | |||||
| }, | }, | ||||
| test: { | test: { | ||||
| title: 'テスト', | title: 'テスト', |
| privacyPolicyPlaceholder: 'Wprowadź link do polityki prywatności', | privacyPolicyPlaceholder: 'Wprowadź link do polityki prywatności', | ||||
| privacyPolicyTip: | privacyPolicyTip: | ||||
| 'Pomaga odwiedzającym zrozumieć, jakie dane zbiera aplikacja, zobacz <privacyPolicyLink>Politykę prywatności Dify</privacyPolicyLink>.', | '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: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: 'Polityka prywatności', | privacyPolicy: 'Polityka prywatności', | ||||
| privacyPolicyPlaceholder: 'Proszę wprowadzić politykę prywatności', | privacyPolicyPlaceholder: 'Proszę wprowadzić politykę prywatności', | ||||
| customDisclaimer: 'Oświadczenie niestandardowe', | |||||
| customDisclaimerPlaceholder: 'Proszę wprowadzić oświadczenie niestandardowe', | |||||
| }, | }, | ||||
| test: { | test: { | ||||
| title: 'Test', | title: 'Test', |
| privacyPolicy: 'Política de Privacidade', | privacyPolicy: 'Política de Privacidade', | ||||
| privacyPolicyPlaceholder: 'Insira o link da 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.', | 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: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: 'Política de Privacidade', | privacyPolicy: 'Política de Privacidade', | ||||
| privacyPolicyPlaceholder: 'Digite a política de privacidade', | privacyPolicyPlaceholder: 'Digite a política de privacidade', | ||||
| customDisclaimer: 'Aviso Personalizado', | |||||
| customDisclaimerPlaceholder: 'Digite o aviso personalizado', | |||||
| }, | }, | ||||
| test: { | test: { | ||||
| title: 'Testar', | title: 'Testar', |
| privacyPolicy: 'Політика конфіденційності', | privacyPolicy: 'Політика конфіденційності', | ||||
| privacyPolicyPlaceholder: 'Введіть посилання на політику конфіденційності', | privacyPolicyPlaceholder: 'Введіть посилання на політику конфіденційності', | ||||
| privacyPolicyTip: 'Допомагає відвідувачам зрозуміти дані, зібрані додатком, див. <privacyPolicyLink>Політику конфіденційності</privacyPolicyLink> Dify.', | privacyPolicyTip: 'Допомагає відвідувачам зрозуміти дані, зібрані додатком, див. <privacyPolicyLink>Політику конфіденційності</privacyPolicyLink> Dify.', | ||||
| customDisclaimer: 'Відмова від відповідальності', | |||||
| customDisclaimerPlaceholder: 'Введіть відмову від відповідальності', | |||||
| customDisclaimerTip: 'Відображається на клієнтському боці, щоб визначити відповідальність за використання додатка', | |||||
| }, | }, | ||||
| }, | }, | ||||
| embedded: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: 'Політика конфіденційності', | privacyPolicy: 'Політика конфіденційності', | ||||
| privacyPolicyPlaceholder: 'Введіть політику конфіденційності', | privacyPolicyPlaceholder: 'Введіть політику конфіденційності', | ||||
| customDisclaimer: 'Власний відомості', | |||||
| customDisclaimerPlaceholder: 'Введіть власні відомості', | |||||
| }, | }, | ||||
| test: { | test: { |
| privacyPolicy: 'Chính sách bảo mật', | privacyPolicy: 'Chính sách bảo mật', | ||||
| privacyPolicyPlaceholder: 'Nhập liên kết 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.', | 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: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: 'Chính sách bảo mật', | privacyPolicy: 'Chính sách bảo mật', | ||||
| privacyPolicyPlaceholder: 'Vui lòng nhập 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: { | test: { | ||||
| title: 'Kiểm tra', | title: 'Kiểm tra', |
| privacyPolicy: '隐私政策', | privacyPolicy: '隐私政策', | ||||
| privacyPolicyPlaceholder: '请输入隐私政策链接', | privacyPolicyPlaceholder: '请输入隐私政策链接', | ||||
| privacyPolicyTip: '帮助访问者了解该应用收集的数据,可参考 Dify 的<privacyPolicyLink>隐私政策</privacyPolicyLink>。', | privacyPolicyTip: '帮助访问者了解该应用收集的数据,可参考 Dify 的<privacyPolicyLink>隐私政策</privacyPolicyLink>。', | ||||
| customDisclaimer: '自定义免责声明', | |||||
| customDisclaimerPlaceholder: '请输入免责声明', | |||||
| customDisclaimerTip: '在应用中展示免责声明,可用于告知用户 AI 的局限性。', | |||||
| }, | }, | ||||
| }, | }, | ||||
| embedded: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: '隐私协议', | privacyPolicy: '隐私协议', | ||||
| privacyPolicyPlaceholder: '请输入隐私协议', | privacyPolicyPlaceholder: '请输入隐私协议', | ||||
| customDisclaimer: '自定义免责声明', | |||||
| customDisclaimerPlaceholder: '请输入自定义免责声明', | |||||
| }, | }, | ||||
| test: { | test: { | ||||
| title: '测试', | title: '测试', |
| privacyPolicy: '隱私政策', | privacyPolicy: '隱私政策', | ||||
| privacyPolicyPlaceholder: '請輸入隱私政策連結', | privacyPolicyPlaceholder: '請輸入隱私政策連結', | ||||
| privacyPolicyTip: '幫助訪問者瞭解該應用收集的資料,可參考 Dify 的<privacyPolicyLink>隱私政策</privacyPolicyLink>。', | privacyPolicyTip: '幫助訪問者瞭解該應用收集的資料,可參考 Dify 的<privacyPolicyLink>隱私政策</privacyPolicyLink>。', | ||||
| customDisclaimer: '自定義免責聲明', | |||||
| customDisclaimerPlaceholder: '請輸入免責聲明', | |||||
| customDisclaimerTip: '客製化的免責聲明文字將在客戶端顯示,提供有關應用程式的額外資訊。', | |||||
| }, | }, | ||||
| }, | }, | ||||
| embedded: { | embedded: { |
| }, | }, | ||||
| privacyPolicy: '隱私協議', | privacyPolicy: '隱私協議', | ||||
| privacyPolicyPlaceholder: '請輸入隱私協議', | privacyPolicyPlaceholder: '請輸入隱私協議', | ||||
| customDisclaimer: '自定義免責聲明', | |||||
| customDisclaimerPlaceholder: '請輸入自定義免責聲明', | |||||
| }, | }, | ||||
| test: { | test: { | ||||
| title: '測試', | title: '測試', |
| description: string | description: string | ||||
| copyright: string | copyright: string | ||||
| privacy_policy: string | null | privacy_policy: string | null | ||||
| custom_disclaimer: string | null | |||||
| category: AppCategory | category: AppCategory | ||||
| position: number | position: number | ||||
| is_listed: boolean | is_listed: boolean |
| prompt_public?: boolean | prompt_public?: boolean | ||||
| copyright?: string | copyright?: string | ||||
| privacy_policy?: string | privacy_policy?: string | ||||
| custom_disclaimer?: string | |||||
| } | } | ||||
| export type AppMeta = { | export type AppMeta = { |
| copyright: string | copyright: string | ||||
| /** Privacy Policy */ | /** Privacy Policy */ | ||||
| privacy_policy: string | privacy_policy: string | ||||
| /** Custom Disclaimer */ | |||||
| custom_disclaimer: string | |||||
| icon: string | icon: string | ||||
| icon_background: string | icon_background: string |