main
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">Introducing Dify Workflow File Upload: Recreate Google NotebookLM Podcast</a>
|
||||
@ -87,8 +87,6 @@ Please refer to our [FAQ](https://docs.dify.ai/getting-started/install-self-host
|
||||
**1. Workflow**:
|
||||
Build and test powerful AI workflows on a visual canvas, leveraging all the following features and beyond.
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
**2. Comprehensive model support**:
|
||||
Seamless integration with hundreds of proprietary / open-source LLMs from dozens of inference providers and self-hosted solutions, covering GPT, Mistral, Llama3, and any OpenAI API-compatible models. A full list of supported model providers can be found [here](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
|
||||
@ -54,8 +54,6 @@
|
||||
|
||||
**1. سير العمل**: قم ببناء واختبار سير عمل الذكاء الاصطناعي القوي على قماش بصري، مستفيدًا من جميع الميزات التالية وأكثر.
|
||||
|
||||
<https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa>
|
||||
|
||||
**2. الدعم الشامل للنماذج**: تكامل سلس مع مئات من LLMs الخاصة / مفتوحة المصدر من عشرات من موفري التحليل والحلول المستضافة ذاتيًا، مما يغطي GPT و Mistral و Llama3 وأي نماذج متوافقة مع واجهة OpenAI API. يمكن العثور على قائمة كاملة بمزودي النموذج المدعومين [هنا](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||

|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">ডিফাই ওয়ার্কফ্লো ফাইল আপলোড পরিচিতি: গুগল নোটবুক-এলএম পডকাস্ট পুনর্নির্মাণ</a>
|
||||
@ -84,8 +84,6 @@ docker compose up -d
|
||||
**১. ওয়ার্কফ্লো**:
|
||||
ভিজ্যুয়াল ক্যানভাসে AI ওয়ার্কফ্লো তৈরি এবং পরীক্ষা করুন, নিম্নলিখিত সব ফিচার এবং তার বাইরেও আরও অনেক কিছু ব্যবহার করে।
|
||||
|
||||
<https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa>
|
||||
|
||||
**২. মডেল সাপোর্ট**:
|
||||
GPT, Mistral, Llama3, এবং যেকোনো OpenAI API-সামঞ্জস্যপূর্ণ মডেলসহ, কয়েক ডজন ইনফারেন্স প্রদানকারী এবং সেল্ফ-হোস্টেড সমাধান থেকে শুরু করে প্রোপ্রাইটরি/ওপেন-সোর্স LLM-এর সাথে সহজে ইন্টিগ্রেশন। সমর্থিত মডেল প্রদানকারীদের একটি সম্পূর্ণ তালিকা পাওয়া যাবে [এখানে](https://docs.dify.ai/getting-started/readme/model-providers)।
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<div align="center">
|
||||
<a href="https://cloud.dify.ai">Dify 云服务</a> ·
|
||||
@ -61,11 +61,6 @@ Dify 是一个开源的 LLM 应用开发平台。其直观的界面结合了 AI
|
||||
**1. 工作流**:
|
||||
在画布上构建和测试功能强大的 AI 工作流程,利用以下所有功能以及更多功能。
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. 全面的模型支持**:
|
||||
与数百种专有/开源 LLMs 以及数十种推理提供商和自托管解决方案无缝集成,涵盖 GPT、Mistral、Llama3 以及任何与 OpenAI API 兼容的模型。完整的支持模型提供商列表可在[此处](https://docs.dify.ai/getting-started/readme/model-providers)找到。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">Einführung in Dify Workflow File Upload: Google NotebookLM Podcast nachbilden</a>
|
||||
@ -83,11 +83,6 @@ Bitte beachten Sie unsere [FAQ](https://docs.dify.ai/getting-started/install-sel
|
||||
**1. Workflow**:
|
||||
Erstellen und testen Sie leistungsstarke KI-Workflows auf einer visuellen Oberfläche, wobei Sie alle der folgenden Funktionen und darüber hinaus nutzen können.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. Umfassende Modellunterstützung**:
|
||||
Nahtlose Integration mit Hunderten von proprietären und Open-Source-LLMs von Dutzenden Inferenzanbietern und selbstgehosteten Lösungen, die GPT, Mistral, Llama3 und alle mit der OpenAI API kompatiblen Modelle abdecken. Eine vollständige Liste der unterstützten Modellanbieter finden Sie [hier](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
|
||||
@ -59,11 +59,6 @@ Dify es una plataforma de desarrollo de aplicaciones de LLM de código abierto.
|
||||
**1. Flujo de trabajo**:
|
||||
Construye y prueba potentes flujos de trabajo de IA en un lienzo visual, aprovechando todas las siguientes características y más.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. Soporte de modelos completo**:
|
||||
Integración perfecta con cientos de LLMs propietarios / de código abierto de docenas de proveedores de inferencia y soluciones auto-alojadas, que cubren GPT, Mistral, Llama3 y cualquier modelo compatible con la API de OpenAI. Se puede encontrar una lista completa de proveedores de modelos admitidos [aquí](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
|
||||
@ -59,11 +59,6 @@ Dify est une plateforme de développement d'applications LLM open source. Son in
|
||||
**1. Flux de travail** :
|
||||
Construisez et testez des flux de travail d'IA puissants sur un canevas visuel, en utilisant toutes les fonctionnalités suivantes et plus encore.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. Prise en charge complète des modèles** :
|
||||
Intégration transparente avec des centaines de LLM propriétaires / open source provenant de dizaines de fournisseurs d'inférence et de solutions auto-hébergées, couvrant GPT, Mistral, Llama3, et tous les modèles compatibles avec l'API OpenAI. Une liste complète des fournisseurs de modèles pris en charge se trouve [ici](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
|
||||
@ -60,11 +60,6 @@ DifyはオープンソースのLLMアプリケーション開発プラットフ
|
||||
**1. ワークフロー**:
|
||||
強力なAIワークフローをビジュアルキャンバス上で構築し、テストできます。すべての機能、および以下の機能を使用できます。
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. 総合的なモデルサポート**:
|
||||
数百ものプロプライエタリ/オープンソースのLLMと、数十もの推論プロバイダーおよびセルフホスティングソリューションとのシームレスな統合を提供します。GPT、Mistral、Llama3、OpenAI APIと互換性のあるすべてのモデルを統合されています。サポートされているモデルプロバイダーの完全なリストは[こちら](https://docs.dify.ai/getting-started/readme/model-providers)をご覧ください。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
|
||||
@ -59,11 +59,6 @@ Dify is an open-source LLM app development platform. Its intuitive interface com
|
||||
**1. Workflow**:
|
||||
Build and test powerful AI workflows on a visual canvas, leveraging all the following features and beyond.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. Comprehensive model support**:
|
||||
Seamless integration with hundreds of proprietary / open-source LLMs from dozens of inference providers and self-hosted solutions, covering GPT, Mistral, Llama3, and any OpenAI API-compatible models. A full list of supported model providers can be found [here](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify 클라우드</a> ·
|
||||
@ -54,11 +54,6 @@
|
||||
**1. 워크플로우**:
|
||||
다음 기능들을 비롯한 다양한 기능을 활용하여 시각적 캔버스에서 강력한 AI 워크플로우를 구축하고 테스트하세요.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. 포괄적인 모델 지원:**:
|
||||
|
||||
수십 개의 추론 제공업체와 자체 호스팅 솔루션에서 제공하는 수백 개의 독점 및 오픈 소스 LLM과 원활하게 통합되며, GPT, Mistral, Llama3 및 모든 OpenAI API 호환 모델을 포함합니다. 지원되는 모델 제공업체의 전체 목록은 [여기](https://docs.dify.ai/getting-started/readme/model-providers)에서 확인할 수 있습니다.
|
||||
|
@ -1,5 +1,4 @@
|
||||

|
||||
|
||||

|
||||
<p align="center">
|
||||
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">Introduzindo o Dify Workflow com Upload de Arquivo: Recrie o Podcast Google NotebookLM</a>
|
||||
</p>
|
||||
@ -59,11 +58,6 @@ Dify é uma plataforma de desenvolvimento de aplicativos LLM de código aberto.
|
||||
**1. Workflow**:
|
||||
Construa e teste workflows poderosos de IA em uma interface visual, aproveitando todos os recursos a seguir e muito mais.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. Suporte abrangente a modelos**:
|
||||
Integração perfeita com centenas de LLMs proprietários e de código aberto de diversas provedoras e soluções auto-hospedadas, abrangendo GPT, Mistral, Llama3 e qualquer modelo compatível com a API da OpenAI. A lista completa de provedores suportados pode ser encontrada [aqui](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">Predstavljamo nalaganje datotek Dify Workflow: znova ustvarite Google NotebookLM Podcast</a>
|
||||
@ -81,11 +81,6 @@ Prosimo, glejte naša pogosta vprašanja [FAQ](https://docs.dify.ai/getting-star
|
||||
**1. Potek dela**:
|
||||
Zgradite in preizkusite zmogljive poteke dela AI na vizualnem platnu, pri čemer izkoristite vse naslednje funkcije in več.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. Celovita podpora za modele**:
|
||||
Brezhibna integracija s stotinami lastniških/odprtokodnih LLM-jev ducatov ponudnikov sklepanja in samostojnih rešitev, ki pokrivajo GPT, Mistral, Llama3 in vse modele, združljive z API-jem OpenAI. Celoten seznam podprtih ponudnikov modelov najdete [tukaj](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Bulut</a> ·
|
||||
@ -55,11 +55,6 @@ Dify, açık kaynaklı bir LLM uygulama geliştirme platformudur. Sezgisel aray
|
||||
**1. Workflow**:
|
||||
Görsel bir arayüz üzerinde güçlü AI iş akışları oluşturun ve test edin, aşağıdaki tüm özellikleri ve daha fazlasını kullanarak.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. Kapsamlı model desteği**:
|
||||
Çok sayıda çıkarım sağlayıcısı ve kendi kendine barındırılan çözümlerden yüzlerce özel / açık kaynaklı LLM ile sorunsuz entegrasyon sağlar. GPT, Mistral, Llama3 ve OpenAI API uyumlu tüm modelleri kapsar. Desteklenen model sağlayıcılarının tam listesine [buradan](https://docs.dify.ai/getting-started/readme/model-providers) ulaşabilirsiniz.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">介紹 Dify 工作流程檔案上傳功能:重現 Google NotebookLM Podcast</a>
|
||||
@ -86,8 +86,6 @@ docker compose up -d
|
||||
**1. 工作流程**:
|
||||
在視覺化畫布上建立和測試強大的 AI 工作流程,利用以下所有功能及更多。
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
**2. 全面的模型支援**:
|
||||
無縫整合來自數十個推理提供商和自託管解決方案的數百個專有/開源 LLM,涵蓋 GPT、Mistral、Llama3 和任何與 OpenAI API 兼容的模型。您可以在[此處](https://docs.dify.ai/getting-started/readme/model-providers)找到支援的模型提供商完整列表。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
|
||||
@ -55,11 +55,6 @@ Dify là một nền tảng phát triển ứng dụng LLM mã nguồn mở. Gia
|
||||
**1. Quy trình làm việc**:
|
||||
Xây dựng và kiểm tra các quy trình làm việc AI mạnh mẽ trên một canvas trực quan, tận dụng tất cả các tính năng sau đây và hơn thế nữa.
|
||||
|
||||
|
||||
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
|
||||
|
||||
|
||||
|
||||
**2. Hỗ trợ mô hình toàn diện**:
|
||||
Tích hợp liền mạch với hàng trăm mô hình LLM độc quyền / mã nguồn mở từ hàng chục nhà cung cấp suy luận và giải pháp tự lưu trữ, bao gồm GPT, Mistral, Llama3, và bất kỳ mô hình tương thích API OpenAI nào. Danh sách đầy đủ các nhà cung cấp mô hình được hỗ trợ có thể được tìm thấy [tại đây](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||
|
@ -9,7 +9,7 @@ class PackagingInfo(BaseSettings):
|
||||
|
||||
CURRENT_VERSION: str = Field(
|
||||
description="Dify version",
|
||||
default="1.3.1",
|
||||
default="1.4.0",
|
||||
)
|
||||
|
||||
COMMIT_SHA: str = Field(
|
||||
|
6
api/core/plugin/endpoint/exc.py
Normal file
@ -0,0 +1,6 @@
|
||||
class EndpointSetupFailedError(ValueError):
|
||||
"""
|
||||
Endpoint setup failed error
|
||||
"""
|
||||
|
||||
pass
|
@ -17,6 +17,7 @@ from core.model_runtime.errors.invoke import (
|
||||
InvokeServerUnavailableError,
|
||||
)
|
||||
from core.model_runtime.errors.validate import CredentialsValidateFailedError
|
||||
from core.plugin.endpoint.exc import EndpointSetupFailedError
|
||||
from core.plugin.entities.plugin_daemon import PluginDaemonBasicResponse, PluginDaemonError, PluginDaemonInnerError
|
||||
from core.plugin.impl.exc import (
|
||||
PluginDaemonBadRequestError,
|
||||
@ -219,6 +220,8 @@ class BasePluginClient:
|
||||
raise InvokeServerUnavailableError(description=args.get("description"))
|
||||
case CredentialsValidateFailedError.__name__:
|
||||
raise CredentialsValidateFailedError(error_object.get("message"))
|
||||
case EndpointSetupFailedError.__name__:
|
||||
raise EndpointSetupFailedError(error_object.get("message"))
|
||||
case _:
|
||||
raise PluginInvokeError(description=message)
|
||||
case PluginDaemonInternalServerError.__name__:
|
||||
|
@ -1,3 +1,4 @@
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import uuid
|
||||
@ -61,12 +62,12 @@ CREATE TABLE IF NOT EXISTS {table_name} (
|
||||
"""
|
||||
|
||||
SQL_CREATE_INDEX = """
|
||||
CREATE INDEX IF NOT EXISTS embedding_cosine_v1_idx ON {table_name}
|
||||
CREATE INDEX IF NOT EXISTS embedding_cosine_v1_idx_{index_hash} ON {table_name}
|
||||
USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);
|
||||
"""
|
||||
|
||||
SQL_CREATE_INDEX_PG_BIGM = """
|
||||
CREATE INDEX IF NOT EXISTS bigm_idx ON {table_name}
|
||||
CREATE INDEX IF NOT EXISTS bigm_idx_{index_hash} ON {table_name}
|
||||
USING gin (text gin_bigm_ops);
|
||||
"""
|
||||
|
||||
@ -76,6 +77,7 @@ class PGVector(BaseVector):
|
||||
super().__init__(collection_name)
|
||||
self.pool = self._create_connection_pool(config)
|
||||
self.table_name = f"embedding_{collection_name}"
|
||||
self.index_hash = hashlib.md5(self.table_name.encode()).hexdigest()[:8]
|
||||
self.pg_bigm = config.pg_bigm
|
||||
|
||||
def get_type(self) -> str:
|
||||
@ -256,10 +258,9 @@ class PGVector(BaseVector):
|
||||
# PG hnsw index only support 2000 dimension or less
|
||||
# ref: https://github.com/pgvector/pgvector?tab=readme-ov-file#indexing
|
||||
if dimension <= 2000:
|
||||
cur.execute(SQL_CREATE_INDEX.format(table_name=self.table_name))
|
||||
cur.execute(SQL_CREATE_INDEX.format(table_name=self.table_name, index_hash=self.index_hash))
|
||||
if self.pg_bigm:
|
||||
cur.execute("CREATE EXTENSION IF NOT EXISTS pg_bigm")
|
||||
cur.execute(SQL_CREATE_INDEX_PG_BIGM.format(table_name=self.table_name))
|
||||
cur.execute(SQL_CREATE_INDEX_PG_BIGM.format(table_name=self.table_name, index_hash=self.index_hash))
|
||||
redis_client.set(collection_exist_cache_key, 1, ex=3600)
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ IMPORT_INFO_REDIS_KEY_PREFIX = "app_import_info:"
|
||||
CHECK_DEPENDENCIES_REDIS_KEY_PREFIX = "app_check_dependencies:"
|
||||
IMPORT_INFO_REDIS_EXPIRY = 10 * 60 # 10 minutes
|
||||
DSL_MAX_SIZE = 10 * 1024 * 1024 # 10MB
|
||||
CURRENT_DSL_VERSION = "0.2.0"
|
||||
CURRENT_DSL_VERSION = "0.3.0"
|
||||
|
||||
|
||||
class ImportMode(StrEnum):
|
||||
|
@ -69,7 +69,7 @@
|
||||
<div class="email-container">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<img src="https://img.mailinblue.com/6365111/images/content_library/original/64cb67ca60532312c211dc72.png" alt="Dify Logo">
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo">
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
|
@ -99,7 +99,7 @@
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<!-- Optional: Add a logo or a header image here -->
|
||||
<img src="https://cloud.dify.ai/logo/logo-site.png" alt="Dify Logo" />
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo" />
|
||||
</div>
|
||||
<p class="title">Dify.AI Account Deletion and Verification</p>
|
||||
<p class="typography">We received a request to delete your Dify account. To ensure the security of your account and
|
||||
|
@ -88,7 +88,7 @@
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<!-- Optional: Add a logo or a header image here -->
|
||||
<img src="https://cloud.dify.ai/logo/logo-site.png" alt="Dify Logo" />
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo" />
|
||||
</div>
|
||||
<p class="title">Your Dify.AI Account Has Been Successfully Deleted</p>
|
||||
<p class="typography">We're writing to confirm that your Dify.AI account has been successfully deleted as per your request. Your
|
||||
|
@ -61,7 +61,7 @@
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<!-- Optional: Add a logo or a header image here -->
|
||||
<img src="https://cloud.dify.ai/logo/logo-site.png" alt="Dify Logo" />
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo" />
|
||||
</div>
|
||||
<p class="title">Your login code for Dify</p>
|
||||
<p class="description">Copy and paste this code, this code will only be valid for the next 5 minutes.</p>
|
||||
|
@ -61,7 +61,7 @@
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<!-- Optional: Add a logo or a header image here -->
|
||||
<img src="https://cloud.dify.ai/logo/logo-site.png" alt="Dify Logo" />
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo" />
|
||||
</div>
|
||||
<p class="title">Dify 的登录验证码</p>
|
||||
<p class="description">复制并粘贴此验证码,注意验证码仅在接下来的 5 分钟内有效。</p>
|
||||
|
@ -54,7 +54,7 @@
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<!-- Optional: Add a logo or a header image here -->
|
||||
<img src="https://cloud.dify.ai/logo/logo-site.png" alt="Dify Logo">
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo">
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>Dear {{ to }},</p>
|
||||
|
@ -54,7 +54,7 @@
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="https://cloud.dify.ai/logo/logo-site.png" alt="Dify Logo">
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo">
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>尊敬的 {{ to }},</p>
|
||||
|
@ -61,7 +61,7 @@
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<!-- Optional: Add a logo or a header image here -->
|
||||
<img src="https://cloud.dify.ai/logo/logo-site.png" alt="Dify Logo" />
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo" />
|
||||
</div>
|
||||
<p class="title">Set your Dify password</p>
|
||||
<p class="description">Copy and paste this code, this code will only be valid for the next 5 minutes.</p>
|
||||
|
@ -61,7 +61,7 @@
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<!-- Optional: Add a logo or a header image here -->
|
||||
<img src="https://cloud.dify.ai/logo/logo-site.png" alt="Dify Logo" />
|
||||
<img src="https://assets.dify.ai/images/logo.png" alt="Dify Logo" />
|
||||
</div>
|
||||
<p class="title">设置您的 Dify 账户密码</p>
|
||||
<p class="description">复制并粘贴此验证码,注意验证码仅在接下来的 5 分钟内有效。</p>
|
||||
|
@ -478,7 +478,7 @@ ANALYTICDB_PORT=5432
|
||||
ANALYTICDB_MIN_CONNECTION=1
|
||||
ANALYTICDB_MAX_CONNECTION=5
|
||||
|
||||
# TiDB vector configurations, only available when VECTOR_STORE is `tidb`
|
||||
# TiDB vector configurations, only available when VECTOR_STORE is `tidb_vector`
|
||||
TIDB_VECTOR_HOST=tidb
|
||||
TIDB_VECTOR_PORT=4000
|
||||
TIDB_VECTOR_USER=
|
||||
|
@ -2,7 +2,7 @@ x-shared-env: &shared-api-worker-env
|
||||
services:
|
||||
# API service
|
||||
api:
|
||||
image: langgenius/dify-api:1.3.1
|
||||
image: langgenius/dify-api:1.4.0
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@ -31,7 +31,7 @@ services:
|
||||
# worker service
|
||||
# The Celery worker for processing the queue.
|
||||
worker:
|
||||
image: langgenius/dify-api:1.3.1
|
||||
image: langgenius/dify-api:1.4.0
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@ -57,7 +57,7 @@ services:
|
||||
|
||||
# Frontend web application.
|
||||
web:
|
||||
image: langgenius/dify-web:1.3.1
|
||||
image: langgenius/dify-web:1.4.0
|
||||
restart: always
|
||||
environment:
|
||||
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
|
||||
@ -118,7 +118,7 @@ services:
|
||||
|
||||
# The DifySandbox
|
||||
sandbox:
|
||||
image: langgenius/dify-sandbox:0.2.11
|
||||
image: langgenius/dify-sandbox:0.2.12
|
||||
restart: always
|
||||
environment:
|
||||
# The DifySandbox configurations
|
||||
@ -142,7 +142,7 @@ services:
|
||||
|
||||
# plugin daemon
|
||||
plugin_daemon:
|
||||
image: langgenius/dify-plugin-daemon:0.0.9-local
|
||||
image: langgenius/dify-plugin-daemon:0.0.10-local
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
|
@ -45,7 +45,7 @@ services:
|
||||
|
||||
# The DifySandbox
|
||||
sandbox:
|
||||
image: langgenius/dify-sandbox:0.2.11
|
||||
image: langgenius/dify-sandbox:0.2.12
|
||||
restart: always
|
||||
env_file:
|
||||
- ./middleware.env
|
||||
@ -71,7 +71,7 @@ services:
|
||||
|
||||
# plugin daemon
|
||||
plugin_daemon:
|
||||
image: langgenius/dify-plugin-daemon:0.0.9-local
|
||||
image: langgenius/dify-plugin-daemon:0.0.10-local
|
||||
restart: always
|
||||
env_file:
|
||||
- ./middleware.env
|
||||
|
@ -492,7 +492,7 @@ x-shared-env: &shared-api-worker-env
|
||||
services:
|
||||
# API service
|
||||
api:
|
||||
image: langgenius/dify-api:1.3.1
|
||||
image: langgenius/dify-api:1.4.0
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@ -521,7 +521,7 @@ services:
|
||||
# worker service
|
||||
# The Celery worker for processing the queue.
|
||||
worker:
|
||||
image: langgenius/dify-api:1.3.1
|
||||
image: langgenius/dify-api:1.4.0
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@ -547,7 +547,7 @@ services:
|
||||
|
||||
# Frontend web application.
|
||||
web:
|
||||
image: langgenius/dify-web:1.3.1
|
||||
image: langgenius/dify-web:1.4.0
|
||||
restart: always
|
||||
environment:
|
||||
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
|
||||
@ -608,7 +608,7 @@ services:
|
||||
|
||||
# The DifySandbox
|
||||
sandbox:
|
||||
image: langgenius/dify-sandbox:0.2.11
|
||||
image: langgenius/dify-sandbox:0.2.12
|
||||
restart: always
|
||||
environment:
|
||||
# The DifySandbox configurations
|
||||
@ -632,7 +632,7 @@ services:
|
||||
|
||||
# plugin daemon
|
||||
plugin_daemon:
|
||||
image: langgenius/dify-plugin-daemon:0.0.9-local
|
||||
image: langgenius/dify-plugin-daemon:0.0.10-local
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
|
Before Width: | Height: | Size: 1.3 MiB |
BIN
images/GitHub_README_if.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
images/demo.png
Before Width: | Height: | Size: 790 KiB |
BIN
images/describe.png
Normal file
After Width: | Height: | Size: 722 KiB |
@ -4,23 +4,25 @@ import { RiArrowRightUpLine, RiRobot2Line } from '@remixicon/react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import Button from '../components/base/button'
|
||||
import Avatar from './avatar'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
const Header = () => {
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
|
||||
const back = () => {
|
||||
const back = useCallback(() => {
|
||||
router.back()
|
||||
}
|
||||
}, [router])
|
||||
|
||||
return (
|
||||
<div className='flex flex-1 items-center justify-between px-4'>
|
||||
<div className='flex items-center gap-3'>
|
||||
<div className='flex cursor-pointer items-center' onClick={back}>
|
||||
<LogoSite className='object-contain' />
|
||||
<DifyLogo />
|
||||
</div>
|
||||
<div className='h-4 w-[1px] bg-divider-regular' />
|
||||
<p className='title-3xl-semi-bold text-text-primary'>{t('common.account.account')}</p>
|
||||
<div className='h-4 w-[1px] origin-center rotate-[11.31deg] bg-divider-regular' />
|
||||
<p className='title-3xl-semi-bold relative mt-[-2px] text-text-primary'>{t('common.account.account')}</p>
|
||||
</div>
|
||||
<div className='flex shrink-0 items-center gap-3'>
|
||||
<Button className='system-sm-medium gap-2 px-3 py-2' onClick={back}>
|
||||
|
@ -12,6 +12,7 @@ import { DataSourceType } from '@/models/datasets'
|
||||
import FileIcon from '@/app/components/base/file-icon'
|
||||
import { Folder } from '@/app/components/base/icons/src/vender/solid/files'
|
||||
import { Globe06 } from '@/app/components/base/icons/src/vender/solid/mapsAndTravel'
|
||||
import ActionButton, { ActionButtonState } from '@/app/components/base/action-button'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
@ -47,56 +48,66 @@ const Item: FC<ItemProps> = ({
|
||||
const [isDeleting, setIsDeleting] = useState(false)
|
||||
|
||||
return (
|
||||
<div className={cn('group relative mb-1 flex w-full items-center rounded-lg border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg py-2 pl-2.5 pr-3 shadow-xs last-of-type:mb-0 hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm', isDeleting && 'border-state-destructive-border hover:bg-state-destructive-hover')}>
|
||||
{
|
||||
config.data_source_type === DataSourceType.FILE && (
|
||||
<div className='mr-2 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border-[0.5px] border-[#E0EAFF] bg-[#F5F8FF]'>
|
||||
<Folder className='h-4 w-4 text-[#444CE7]' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
config.data_source_type === DataSourceType.NOTION && (
|
||||
<div className='mr-2 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border-[0.5px] border-[#EAECF5]'>
|
||||
<FileIcon type='notion' className='h-4 w-4' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
config.data_source_type === DataSourceType.WEB && (
|
||||
<div className='mr-2 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border-[0.5px] border-blue-100 bg-[#F5FAFF]'>
|
||||
<Globe06 className='h-4 w-4 text-blue-600' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className='grow'>
|
||||
<div className='flex h-[18px] items-center'>
|
||||
<div className='grow truncate text-[13px] font-medium text-text-secondary' title={config.name}>{config.name}</div>
|
||||
{config.provider === 'external'
|
||||
? <Badge text={t('dataset.externalTag') as string} />
|
||||
: <Badge
|
||||
text={formatIndexingTechniqueAndMethod(config.indexing_technique, config.retrieval_model_dict?.search_method)}
|
||||
/>}
|
||||
</div>
|
||||
</div >
|
||||
<div className='absolute bottom-0 right-0 top-0 hidden w-[124px] items-center justify-end rounded-lg bg-gradient-to-r from-white/50 to-white to-50% pr-2 group-hover:flex'>
|
||||
<div className={cn(
|
||||
'group relative mb-1 flex h-10 w-full cursor-pointer items-center justify-between rounded-lg border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg px-2 last-of-type:mb-0 hover:bg-components-panel-on-panel-item-bg-hover',
|
||||
isDeleting && 'border-state-destructive-border hover:bg-state-destructive-hover',
|
||||
)}>
|
||||
<div className='flex w-0 grow items-center space-x-1.5'>
|
||||
{
|
||||
editable && <div
|
||||
className='mr-1 flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-black/5'
|
||||
onClick={() => setShowSettingsModal(true)}
|
||||
>
|
||||
<RiEditLine className='h-4 w-4 text-text-tertiary' />
|
||||
</div>
|
||||
config.data_source_type === DataSourceType.FILE && (
|
||||
<div className='mr-2 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border-[0.5px] border-[#E0EAFF] bg-[#F5F8FF]'>
|
||||
<Folder className='h-4 w-4 text-[#444CE7]' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div
|
||||
className='flex h-6 w-6 cursor-pointer items-center justify-center text-text-tertiary hover:text-text-destructive'
|
||||
{
|
||||
config.data_source_type === DataSourceType.NOTION && (
|
||||
<div className='mr-2 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border-[0.5px] border-[#EAECF5]'>
|
||||
<FileIcon type='notion' className='h-4 w-4' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
config.data_source_type === DataSourceType.WEB && (
|
||||
<div className='mr-2 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border-[0.5px] border-blue-100 bg-[#F5FAFF]'>
|
||||
<Globe06 className='h-4 w-4 text-blue-600' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className='system-sm-medium w-0 grow truncate text-text-secondary' title={config.name}>{config.name}</div>
|
||||
</div>
|
||||
<div className='ml-2 hidden shrink-0 items-center space-x-1 group-hover:flex'>
|
||||
{
|
||||
editable && <ActionButton
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowSettingsModal(true)
|
||||
}}
|
||||
>
|
||||
<RiEditLine className='h-4 w-4 shrink-0 text-text-tertiary' />
|
||||
</ActionButton>
|
||||
}
|
||||
<ActionButton
|
||||
onClick={() => onRemove(config.id)}
|
||||
onMouseOver={() => setIsDeleting(true)}
|
||||
state={isDeleting ? ActionButtonState.Destructive : ActionButtonState.Default}
|
||||
onMouseEnter={() => setIsDeleting(true)}
|
||||
onMouseLeave={() => setIsDeleting(false)}
|
||||
>
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</div>
|
||||
<RiDeleteBinLine className={cn('h-4 w-4 shrink-0 text-text-tertiary', isDeleting && 'text-text-destructive')} />
|
||||
</ActionButton>
|
||||
</div>
|
||||
{
|
||||
config.indexing_technique && <Badge
|
||||
className='shrink-0 group-hover:hidden'
|
||||
text={formatIndexingTechniqueAndMethod(config.indexing_technique, config.retrieval_model_dict?.search_method)}
|
||||
/>
|
||||
}
|
||||
{
|
||||
config.provider === 'external' && <Badge
|
||||
className='shrink-0 group-hover:hidden'
|
||||
text={t('dataset.externalTag') as string}
|
||||
/>
|
||||
}
|
||||
<Drawer isOpen={showSettingsModal} onClose={() => setShowSettingsModal(false)} footer={null} mask={isMobile} panelClassName='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl'>
|
||||
<SettingsModal
|
||||
currentDataset={config}
|
||||
|
@ -16,7 +16,7 @@ import List from '@/app/components/base/chat/chat-with-history/sidebar/list'
|
||||
import MenuDropdown from '@/app/components/share/text-generation/menu-dropdown'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import RenameModal from '@/app/components/base/chat/chat-with-history/sidebar/rename-modal'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import type { ConversationItem } from '@/models/share'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
@ -141,14 +141,14 @@ const Sidebar = ({ isPanel }: Props) => {
|
||||
<div className='shrink-0'>
|
||||
{!appData?.custom_config?.remove_webapp_brand && (
|
||||
<div className={cn(
|
||||
'flex shrink-0 items-center gap-1.5 px-2',
|
||||
'flex shrink-0 items-center gap-1.5 px-1',
|
||||
)}>
|
||||
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
|
||||
{appData?.custom_config?.replace_webapp_logo && (
|
||||
<img src={appData?.custom_config?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' />
|
||||
)}
|
||||
{!appData?.custom_config?.replace_webapp_logo && (
|
||||
<LogoSite className='!h-5' />
|
||||
<DifyLogo size='small' />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
@ -11,7 +11,7 @@ import Tooltip from '@/app/components/base/tooltip'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import ViewFormDropdown from '@/app/components/base/chat/embedded-chatbot/inputs-form/view-form-dropdown'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type IHeaderProps = {
|
||||
@ -89,7 +89,7 @@ const Header: FC<IHeaderProps> = ({
|
||||
<img src={appData?.custom_config?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' />
|
||||
)}
|
||||
{!appData?.custom_config?.replace_webapp_logo && (
|
||||
<LogoSite className='!h-5' />
|
||||
<DifyLogo size='small' />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@ -132,7 +132,7 @@ const Header: FC<IHeaderProps> = ({
|
||||
return (
|
||||
<div
|
||||
className={cn('flex h-14 shrink-0 items-center justify-between rounded-t-2xl px-3')}
|
||||
style={Object.assign({}, CssTransform(theme?.backgroundHeaderColorStyle ?? ''), CssTransform(theme?.headerBorderBottomStyle ?? '')) }
|
||||
style={Object.assign({}, CssTransform(theme?.backgroundHeaderColorStyle ?? ''), CssTransform(theme?.headerBorderBottomStyle ?? ''))}
|
||||
>
|
||||
<div className="flex grow items-center space-x-3">
|
||||
{customerIcon}
|
||||
|
@ -19,7 +19,7 @@ import Loading from '@/app/components/base/loading'
|
||||
import LogoHeader from '@/app/components/base/logo/logo-embedded-chat-header'
|
||||
import Header from '@/app/components/base/chat/embedded-chatbot/header'
|
||||
import ChatWrapper from '@/app/components/base/chat/embedded-chatbot/chat-wrapper'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
const Chatbot = () => {
|
||||
@ -118,7 +118,7 @@ const Chatbot = () => {
|
||||
<img src={appData?.custom_config?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' />
|
||||
)}
|
||||
{!appData?.custom_config?.replace_webapp_logo && (
|
||||
<LogoSite className='!h-5' />
|
||||
<DifyLogo size='small' />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
45
web/app/components/base/logo/dify-logo.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import { WEB_PREFIX } from '@/config'
|
||||
import classNames from '@/utils/classnames'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
|
||||
export type LogoStyle = 'default' | 'monochromeWhite'
|
||||
|
||||
export const logoPathMap: Record<LogoStyle, string> = {
|
||||
default: '/logo/logo.svg',
|
||||
monochromeWhite: '/logo/logo-monochrome-white.svg',
|
||||
}
|
||||
|
||||
export type LogoSize = 'large' | 'medium' | 'small'
|
||||
|
||||
export const logoSizeMap: Record<LogoSize, string> = {
|
||||
large: 'w-16 h-7',
|
||||
medium: 'w-12 h-[22px]',
|
||||
small: 'w-9 h-4',
|
||||
}
|
||||
|
||||
type DifyLogoProps = {
|
||||
style?: LogoStyle
|
||||
size?: LogoSize
|
||||
className?: string
|
||||
}
|
||||
|
||||
const DifyLogo: FC<DifyLogoProps> = ({
|
||||
style = 'default',
|
||||
size = 'medium',
|
||||
className,
|
||||
}) => {
|
||||
const { theme } = useTheme()
|
||||
const themedStyle = (theme === 'dark' && style === 'default') ? 'monochromeWhite' : style
|
||||
|
||||
return (
|
||||
<img
|
||||
src={`${WEB_PREFIX}${logoPathMap[themedStyle]}`}
|
||||
className={classNames('block object-contain', logoSizeMap[size], className)}
|
||||
alt='Dify logo'
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default DifyLogo
|
@ -1,22 +0,0 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import { WEB_PREFIX } from '@/config'
|
||||
import classNames from '@/utils/classnames'
|
||||
|
||||
type LogoSiteProps = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
const LogoSite: FC<LogoSiteProps> = ({
|
||||
className,
|
||||
}) => {
|
||||
return (
|
||||
<img
|
||||
src={`${WEB_PREFIX}/logo/logo.png`}
|
||||
className={classNames('block w-[22.651px] h-[24.5px]', className)}
|
||||
alt='logo'
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default LogoSite
|
@ -2,7 +2,7 @@
|
||||
|
||||
@layer components {
|
||||
.premium-badge {
|
||||
@apply shrink-0 relative inline-flex justify-center items-center rounded-md box-border border border-transparent text-white shadow-xs hover:shadow-lg bg-origin-border overflow-hidden;
|
||||
@apply shrink-0 relative inline-flex justify-center items-center rounded-md box-border border border-transparent text-white shadow-xs hover:shadow-lg bg-origin-border overflow-hidden transition-all duration-100 ease-out;
|
||||
background-clip: padding-box, border-box;
|
||||
}
|
||||
.allowHover {
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
RiLoader2Line,
|
||||
RiPlayLargeLine,
|
||||
} from '@remixicon/react'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
@ -246,7 +246,7 @@ const CustomWebAppBrand = () => {
|
||||
<div className='system-2xs-medium-uppercase text-text-tertiary'>POWERED BY</div>
|
||||
{webappLogo
|
||||
? <img src={`${webappLogo}?hash=${imgKey}`} alt='logo' className='block h-5 w-auto' />
|
||||
: <LogoSite className='!h-5' />
|
||||
: <DifyLogo size='small' />
|
||||
}
|
||||
</>
|
||||
)}
|
||||
@ -305,7 +305,7 @@ const CustomWebAppBrand = () => {
|
||||
<div className='system-2xs-medium-uppercase text-text-tertiary'>POWERED BY</div>
|
||||
{webappLogo
|
||||
? <img src={`${webappLogo}?hash=${imgKey}`} alt='logo' className='block h-5 w-auto' />
|
||||
: <LogoSite className='!h-5' />
|
||||
: <DifyLogo size='small' />
|
||||
}
|
||||
</>
|
||||
)}
|
||||
|
@ -7,7 +7,7 @@ import Modal from '@/app/components/base/modal'
|
||||
import Button from '@/app/components/base/button'
|
||||
import type { LangGeniusVersionResponse } from '@/models/common'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import { noop } from 'lodash-es'
|
||||
|
||||
type IAccountSettingProps = {
|
||||
@ -28,21 +28,21 @@ export default function AccountAbout({
|
||||
onClose={noop}
|
||||
className='!w-[480px] !max-w-[480px] !px-6 !py-4'
|
||||
>
|
||||
<div className='relative pt-4'>
|
||||
<div className='absolute -right-4 -top-2 flex h-8 w-8 cursor-pointer items-center justify-center' onClick={onCancel}>
|
||||
<div>
|
||||
<div className='absolute right-4 top-4 flex h-8 w-8 cursor-pointer items-center justify-center' onClick={onCancel}>
|
||||
<RiCloseLine className='h-4 w-4 text-text-tertiary' />
|
||||
</div>
|
||||
<div>
|
||||
<LogoSite className='mx-auto mb-2' />
|
||||
<div className='mb-3 text-center text-xs font-normal text-text-tertiary'>Version {langeniusVersionInfo?.current_version}</div>
|
||||
<div className='mb-4 text-center text-xs font-normal text-text-secondary'>
|
||||
<div className='flex flex-col items-center gap-4 py-8'>
|
||||
<DifyLogo size='large' className='mx-auto' />
|
||||
<div className='text-center text-xs font-normal text-text-tertiary'>Version {langeniusVersionInfo?.current_version}</div>
|
||||
<div className='flex flex-col items-center gap-2 text-center text-xs font-normal text-text-secondary'>
|
||||
<div>© {dayjs().year()} LangGenius, Inc., Contributors.</div>
|
||||
<div className='text-text-accent'>
|
||||
{
|
||||
IS_CE_EDITION
|
||||
? <Link href={'https://github.com/langgenius/dify/blob/main/LICENSE'} target='_blank' rel='noopener noreferrer'>Open Source License</Link>
|
||||
: <>
|
||||
<Link href='https://dify.ai/privacy' target='_blank' rel='noopener noreferrer'>Privacy Policy</Link>,<span> </span>
|
||||
<Link href='https://dify.ai/privacy' target='_blank' rel='noopener noreferrer'>Privacy Policy</Link>,
|
||||
<Link href='https://dify.ai/terms' target='_blank' rel='noopener noreferrer'>Terms of Service</Link>
|
||||
</>
|
||||
}
|
||||
@ -51,7 +51,7 @@ export default function AccountAbout({
|
||||
</div>
|
||||
<div className='-mx-8 mb-4 h-[0.5px] bg-divider-regular' />
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='text-xs font-medium text-text-primary'>
|
||||
<div className='text-xs font-medium text-text-tertiary'>
|
||||
{
|
||||
isLatest
|
||||
? t('common.about.latestAvailable', { version: langeniusVersionInfo.latest_version })
|
||||
@ -59,7 +59,7 @@ export default function AccountAbout({
|
||||
}
|
||||
</div>
|
||||
<div className='flex items-center'>
|
||||
<Button className='mr-2'>
|
||||
<Button className='mr-2' size='small'>
|
||||
<Link
|
||||
href={'https://github.com/langgenius/dify/releases'}
|
||||
target='_blank' rel='noopener noreferrer'
|
||||
@ -69,7 +69,7 @@ export default function AccountAbout({
|
||||
</Button>
|
||||
{
|
||||
!isLatest && !IS_CE_EDITION && (
|
||||
<Button variant='primary'>
|
||||
<Button variant='primary' size='small'>
|
||||
<Link
|
||||
href={langeniusVersionInfo.release_notes}
|
||||
target='_blank' rel='noopener noreferrer'
|
||||
|
@ -13,7 +13,7 @@ import ExploreNav from './explore-nav'
|
||||
import ToolsNav from './tools-nav'
|
||||
import { WorkspaceProvider } from '@/context/workspace-context'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import WorkplaceSelector from '@/app/components/header/account-dropdown/workplace-selector'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
@ -60,8 +60,8 @@ const Header = () => {
|
||||
{
|
||||
!isMobile
|
||||
&& <div className='flex shrink-0 items-center gap-1.5 self-stretch pl-3'>
|
||||
<Link href="/apps" className='flex h-8 w-8 shrink-0 items-center justify-center gap-2'>
|
||||
<LogoSite className='object-contain' />
|
||||
<Link href="/apps" className='flex h-8 w-[52px] shrink-0 items-center justify-center gap-2'>
|
||||
<DifyLogo />
|
||||
</Link>
|
||||
<div className='font-light text-divider-deep'>/</div>
|
||||
<div className='flex items-center gap-0.5'>
|
||||
@ -76,7 +76,7 @@ const Header = () => {
|
||||
{isMobile && (
|
||||
<div className='flex'>
|
||||
<Link href="/apps" className='mr-4 flex items-center'>
|
||||
<LogoSite />
|
||||
<DifyLogo />
|
||||
</Link>
|
||||
<div className='font-light text-divider-deep'>/</div>
|
||||
{enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />}
|
||||
|
@ -47,14 +47,14 @@ const Empty = () => {
|
||||
))}
|
||||
</div>
|
||||
{/* mask */}
|
||||
<div className='absolute z-20 h-full w-full bg-gradient-to-b from-background-gradient-mask-transparent to-white' />
|
||||
<div className='absolute z-20 h-full w-full bg-gradient-to-b from-components-panel-bg-transparent to-components-panel-bg' />
|
||||
<div className='relative z-30 flex h-full items-center justify-center'>
|
||||
<div className='flex flex-col items-center gap-y-3'>
|
||||
<div className='relative -z-10 flex h-[52px] w-[52px] items-center justify-center rounded-xl
|
||||
border-[1px] border-dashed border-divider-deep bg-components-card-bg shadow-xl shadow-shadow-shadow-5'>
|
||||
<Group className='h-5 w-5 text-text-tertiary' />
|
||||
<Line className='absolute -right-[1px] top-1/2 -translate-y-1/2' />
|
||||
<Line className='absolute -left-[1px] top-1/2 -translate-y-1/2' />
|
||||
<Line className='absolute right-[-1px] top-1/2 -translate-y-1/2' />
|
||||
<Line className='absolute left-[-1px] top-1/2 -translate-y-1/2' />
|
||||
<Line className='absolute left-1/2 top-0 -translate-x-1/2 -translate-y-1/2 rotate-90' />
|
||||
<Line className='absolute left-1/2 top-full -translate-x-1/2 -translate-y-1/2 rotate-90' />
|
||||
</div>
|
||||
|
@ -36,7 +36,7 @@ import Toast from '@/app/components/base/toast'
|
||||
import type { VisionFile, VisionSettings } from '@/types/app'
|
||||
import { Resolution, TransferMethod } from '@/types/app'
|
||||
import { useAppFavicon } from '@/hooks/use-app-favicon'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
const GROUP_SIZE = 5 // to avoid RPM(Request per minute) limit. The group task finished then the next group.
|
||||
@ -635,7 +635,7 @@ const TextGeneration: FC<IMainProps> = ({
|
||||
<img src={customConfig?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' />
|
||||
)}
|
||||
{!customConfig?.replace_webapp_logo && (
|
||||
<LogoSite className='!h-5' />
|
||||
<DifyLogo size='small' />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@ -664,7 +664,7 @@ const TextGeneration: FC<IMainProps> = ({
|
||||
showResultPanel()
|
||||
}}
|
||||
>
|
||||
<div className='h-1 w-8 cursor-grab rounded bg-divider-solid'/>
|
||||
<div className='h-1 w-8 cursor-grab rounded bg-divider-solid' />
|
||||
</div>
|
||||
)}
|
||||
{renderResWrap}
|
||||
|
@ -32,7 +32,6 @@ type NodesExtraData = {
|
||||
getAvailableNextNodes: (isChatMode: boolean) => BlockEnum[]
|
||||
checkValid: any
|
||||
defaultRunInputData?: Record<string, any>
|
||||
checkVarValid?: any
|
||||
}
|
||||
export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
[BlockEnum.Start]: {
|
||||
@ -61,7 +60,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: AnswerDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: AnswerDefault.getAvailableNextNodes,
|
||||
checkValid: AnswerDefault.checkValid,
|
||||
checkVarValid: AnswerDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.LLM]: {
|
||||
author: 'Dify',
|
||||
@ -72,7 +70,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailableNextNodes: LLMDefault.getAvailableNextNodes,
|
||||
checkValid: LLMDefault.checkValid,
|
||||
defaultRunInputData: LLMDefault.defaultRunInputData,
|
||||
checkVarValid: LLMDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.KnowledgeRetrieval]: {
|
||||
author: 'Dify',
|
||||
@ -82,7 +79,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: KnowledgeRetrievalDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: KnowledgeRetrievalDefault.getAvailableNextNodes,
|
||||
checkValid: KnowledgeRetrievalDefault.checkValid,
|
||||
checkVarValid: KnowledgeRetrievalDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.IfElse]: {
|
||||
author: 'Dify',
|
||||
@ -92,7 +88,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: IfElseDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: IfElseDefault.getAvailableNextNodes,
|
||||
checkValid: IfElseDefault.checkValid,
|
||||
checkVarValid: IfElseDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.Iteration]: {
|
||||
author: 'Dify',
|
||||
@ -102,7 +97,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: IterationDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: IterationDefault.getAvailableNextNodes,
|
||||
checkValid: IterationDefault.checkValid,
|
||||
checkVarValid: IterationDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.IterationStart]: {
|
||||
author: 'Dify',
|
||||
@ -148,7 +142,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: CodeDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: CodeDefault.getAvailableNextNodes,
|
||||
checkValid: CodeDefault.checkValid,
|
||||
checkVarValid: CodeDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.TemplateTransform]: {
|
||||
author: 'Dify',
|
||||
@ -158,7 +151,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: TemplateTransformDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: TemplateTransformDefault.getAvailableNextNodes,
|
||||
checkValid: TemplateTransformDefault.checkValid,
|
||||
checkVarValid: TemplateTransformDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.QuestionClassifier]: {
|
||||
author: 'Dify',
|
||||
@ -168,7 +160,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: QuestionClassifierDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: QuestionClassifierDefault.getAvailableNextNodes,
|
||||
checkValid: QuestionClassifierDefault.checkValid,
|
||||
checkVarValid: QuestionClassifierDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.HttpRequest]: {
|
||||
author: 'Dify',
|
||||
@ -178,7 +169,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: HttpRequestDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: HttpRequestDefault.getAvailableNextNodes,
|
||||
checkValid: HttpRequestDefault.checkValid,
|
||||
checkVarValid: HttpRequestDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.VariableAssigner]: {
|
||||
author: 'Dify',
|
||||
@ -197,7 +187,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: AssignerDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: AssignerDefault.getAvailableNextNodes,
|
||||
checkValid: AssignerDefault.checkValid,
|
||||
checkVarValid: AssignerDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.VariableAggregator]: {
|
||||
author: 'Dify',
|
||||
@ -207,7 +196,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: VariableAssignerDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: VariableAssignerDefault.getAvailableNextNodes,
|
||||
checkValid: VariableAssignerDefault.checkValid,
|
||||
checkVarValid: VariableAssignerDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.ParameterExtractor]: {
|
||||
author: 'Dify',
|
||||
@ -217,7 +205,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: ParameterExtractorDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: ParameterExtractorDefault.getAvailableNextNodes,
|
||||
checkValid: ParameterExtractorDefault.checkValid,
|
||||
checkVarValid: ParameterExtractorDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.Tool]: {
|
||||
author: 'Dify',
|
||||
@ -227,7 +214,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: ToolDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: ToolDefault.getAvailableNextNodes,
|
||||
checkValid: ToolDefault.checkValid,
|
||||
checkVarValid: ToolDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.DocExtractor]: {
|
||||
author: 'Dify',
|
||||
@ -237,7 +223,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: DocExtractorDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: DocExtractorDefault.getAvailableNextNodes,
|
||||
checkValid: DocExtractorDefault.checkValid,
|
||||
checkVarValid: DocExtractorDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.ListFilter]: {
|
||||
author: 'Dify',
|
||||
@ -247,7 +232,6 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||
getAvailablePrevNodes: ListFilterDefault.getAvailablePrevNodes,
|
||||
getAvailableNextNodes: ListFilterDefault.getAvailableNextNodes,
|
||||
checkValid: ListFilterDefault.checkValid,
|
||||
checkVarValid: ListFilterDefault.checkVarValid,
|
||||
},
|
||||
[BlockEnum.Agent]: {
|
||||
author: 'Dify',
|
||||
|
@ -140,16 +140,6 @@ const WorkflowChecklist = ({
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
node.varErrorMessage?.map((errorMessage: string) => (
|
||||
<div className='rounded-b-lg bg-gray-25 px-3 py-2'>
|
||||
<div className='flex text-xs leading-[18px] text-gray-500'>
|
||||
<AlertTriangle className='mr-2 mt-[3px] h-3 w-3 text-[#F79009]' />
|
||||
{errorMessage}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
|
@ -15,7 +15,6 @@ import { useStore } from '../store'
|
||||
import {
|
||||
getToolCheckParams,
|
||||
getValidTreeNodes,
|
||||
transformStartNodeVariables,
|
||||
} from '../utils'
|
||||
import {
|
||||
CUSTOM_NODE,
|
||||
@ -46,9 +45,6 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
||||
const { data: strategyProviders } = useStrategyProviders()
|
||||
const datasetsDetail = useDatasetsDetailStore(s => s.datasetsDetail)
|
||||
|
||||
const chatVarList = useStore(s => s.conversationVariables)
|
||||
const environmentVariables = useStore(s => s.environmentVariables)
|
||||
|
||||
const getCheckData = useCallback((data: CommonNodeType<{}>) => {
|
||||
let checkData = data
|
||||
if (data.type === BlockEnum.KnowledgeRetrieval) {
|
||||
@ -68,10 +64,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
||||
|
||||
const needWarningNodes = useMemo(() => {
|
||||
const list = []
|
||||
const { validNodes } = getValidTreeNodes(nodes.filter(node => node.type === CUSTOM_NODE), edges, true)
|
||||
|
||||
const allVariablesMap = transformStartNodeVariables(chatVarList, environmentVariables)
|
||||
const errMessageMap = new Map()
|
||||
const { validNodes } = getValidTreeNodes(nodes.filter(node => node.type === CUSTOM_NODE), edges)
|
||||
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i]
|
||||
@ -117,32 +110,8 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
||||
toolIcon,
|
||||
unConnected: !validNodes.find(n => n.id === node.id),
|
||||
errorMessage,
|
||||
varErrorMessage: [],
|
||||
})
|
||||
}
|
||||
errMessageMap.set(node.id, list[list.length - 1])
|
||||
if (nodesExtraData[node.data.type as BlockEnum].checkVarValid) {
|
||||
const { errorMessage: varErrorMessages } = nodesExtraData[node.data.type as BlockEnum].checkVarValid(node.data, { ...allVariablesMap, ...node._parentOutputVarMap }, t)
|
||||
|
||||
if (varErrorMessages?.length) {
|
||||
const errMessage = errMessageMap.get(node.id)
|
||||
if (errMessage) {
|
||||
errMessage.varErrorMessage = varErrorMessages
|
||||
}
|
||||
else {
|
||||
list.push({
|
||||
id: node.id,
|
||||
type: node.data.type,
|
||||
title: node.data.title,
|
||||
toolIcon,
|
||||
unConnected: !validNodes.find(n => n.id === node.id),
|
||||
errorMessage: '',
|
||||
varErrorMessage: varErrorMessages,
|
||||
})
|
||||
errMessageMap.set(node.id, list[list.length - 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,13 +133,8 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
||||
})
|
||||
}
|
||||
|
||||
for (let i = 0; i < validNodes.length; i++) {
|
||||
const node = validNodes[i]
|
||||
delete node._parentOutputVarMap
|
||||
}
|
||||
|
||||
return list
|
||||
}, [nodes, edges, isChatMode, buildInTools, customTools, workflowTools, language, nodesExtraData, t, strategyProviders, getCheckData, chatVarList, environmentVariables])
|
||||
}, [nodes, edges, isChatMode, buildInTools, customTools, workflowTools, language, nodesExtraData, t, strategyProviders, getCheckData])
|
||||
|
||||
return needWarningNodes
|
||||
}
|
||||
@ -189,9 +153,6 @@ export const useChecklistBeforePublish = () => {
|
||||
const updateDatasetsDetail = useDatasetsDetailStore(s => s.updateDatasetsDetail)
|
||||
const updateTime = useRef(0)
|
||||
|
||||
const chatVarList = useStore(s => s.conversationVariables)
|
||||
const environmentVariables = useStore(s => s.environmentVariables)
|
||||
|
||||
const getCheckData = useCallback((data: CommonNodeType<{}>, datasets: DataSet[]) => {
|
||||
let checkData = data
|
||||
if (data.type === BlockEnum.KnowledgeRetrieval) {
|
||||
@ -222,15 +183,12 @@ export const useChecklistBeforePublish = () => {
|
||||
const {
|
||||
validNodes,
|
||||
maxDepth,
|
||||
} = getValidTreeNodes(nodes.filter(node => node.type === CUSTOM_NODE), edges, true)
|
||||
} = getValidTreeNodes(nodes.filter(node => node.type === CUSTOM_NODE), edges)
|
||||
|
||||
if (maxDepth > MAX_TREE_DEPTH) {
|
||||
notify({ type: 'error', message: t('workflow.common.maxTreeDepth', { depth: MAX_TREE_DEPTH }) })
|
||||
return false
|
||||
}
|
||||
|
||||
const allVariablesMap = transformStartNodeVariables(chatVarList, environmentVariables)
|
||||
|
||||
// Before publish, we need to fetch datasets detail, in case of the settings of datasets have been changed
|
||||
const knowledgeRetrievalNodes = nodes.filter(node => node.data.type === BlockEnum.KnowledgeRetrieval)
|
||||
const allDatasetIds = knowledgeRetrievalNodes.reduce<string[]>((acc, node) => {
|
||||
@ -281,14 +239,6 @@ export const useChecklistBeforePublish = () => {
|
||||
notify({ type: 'error', message: `[${node.data.title}] ${t('workflow.common.needConnectTip')}` })
|
||||
return false
|
||||
}
|
||||
|
||||
if (nodesExtraData[node.data.type as BlockEnum].checkVarValid) {
|
||||
const { errorMessage: varErrorMessage } = nodesExtraData[node.data.type as BlockEnum].checkVarValid(node.data, { ...allVariablesMap, ...node._parentOutputVarMap }, t)
|
||||
if (varErrorMessage?.length) {
|
||||
notify({ type: 'error', message: `[${node.data.title}] ${varErrorMessage[0]}` })
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isChatMode && !nodes.find(node => node.data.type === BlockEnum.Answer)) {
|
||||
@ -302,7 +252,7 @@ export const useChecklistBeforePublish = () => {
|
||||
}
|
||||
|
||||
return true
|
||||
}, [store, isChatMode, notify, t, buildInTools, customTools, workflowTools, language, nodesExtraData, strategyProviders, updateDatasetsDetail, getCheckData, chatVarList, environmentVariables])
|
||||
}, [store, isChatMode, notify, t, buildInTools, customTools, workflowTools, language, nodesExtraData, strategyProviders, updateDatasetsDetail, getCheckData])
|
||||
|
||||
return {
|
||||
handleCheckBeforePublish,
|
||||
|
@ -164,7 +164,7 @@ const findExceptVarInObject = (obj: any, filterVar: (payload: Var, selector: Val
|
||||
return res
|
||||
}
|
||||
|
||||
export const formatItem = (
|
||||
const formatItem = (
|
||||
item: any,
|
||||
isChatMode: boolean,
|
||||
filterVar: (payload: Var, selector: ValueSelector) => boolean,
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByText } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import type { AnswerNodeType } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
|
||||
@ -32,19 +31,6 @@ const nodeDefault: NodeDefault<AnswerNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: AnswerNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
|
||||
const answer_warnings = getNotExistVariablesByText(payload.answer || '', varMap)
|
||||
if (answer_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.answer.answer')} ${t('workflow.common.referenceVar')}${answer_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: [...answer_warnings],
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import { type AssignerNodeType, WriteMode } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
const i18nPrefix = 'workflow.errorMsg'
|
||||
@ -48,23 +47,6 @@ const nodeDefault: NodeDefault<AssignerNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
|
||||
checkVarValid(payload: AssignerNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr: string[] = []
|
||||
const variables_warnings = getNotExistVariablesByArray(payload.items.map(item => item.variable_selector ?? []) ?? [], varMap)
|
||||
if (variables_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.assigner.assignedVariable')} ${t('workflow.common.referenceVar')}${variables_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
const value_warnings = getNotExistVariablesByArray(payload.items.map(item => item.value ?? []) ?? [], varMap)
|
||||
if (value_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.assigner.setVariable')} ${t('workflow.common.referenceVar')}${value_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: [...variables_warnings, ...value_warnings],
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import { CodeLanguage, type CodeNodeType } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
|
||||
@ -38,20 +37,7 @@ const nodeDefault: NodeDefault<CodeNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: CodeNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
|
||||
const variables_selector = payload.variables.map(v => v.value_selector)
|
||||
const variables_selector_warnings = getNotExistVariablesByArray(variables_selector, varMap)
|
||||
if (variables_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.code.inputVars')} ${t('workflow.common.referenceVar')}${variables_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: variables_selector_warnings,
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import type { DocExtractorNodeType } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
const i18nPrefix = 'workflow.errorMsg'
|
||||
@ -32,19 +31,6 @@ const nodeDefault: NodeDefault<DocExtractorNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: DocExtractorNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr: string[] = []
|
||||
|
||||
const variables_warnings = getNotExistVariablesByArray([payload.variable_selector], varMap)
|
||||
if (variables_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.docExtractor.inputVar')} ${t('workflow.common.referenceVar')}${variables_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: variables_warnings,
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import { AuthorizationType, BodyType, Method } from './types'
|
||||
import type { BodyPayload, HttpNodeType } from './types'
|
||||
import {
|
||||
@ -51,8 +50,8 @@ const nodeDefault: NodeDefault<HttpNodeType> = {
|
||||
errorMessages = t('workflow.errorMsg.fieldRequired', { field: t('workflow.nodes.http.api') })
|
||||
|
||||
if (!errorMessages
|
||||
&& payload.body.type === BodyType.binary
|
||||
&& ((!(payload.body.data as BodyPayload)[0]?.file) || (payload.body.data as BodyPayload)[0]?.file?.length === 0)
|
||||
&& payload.body.type === BodyType.binary
|
||||
&& ((!(payload.body.data as BodyPayload)[0]?.file) || (payload.body.data as BodyPayload)[0]?.file?.length === 0)
|
||||
)
|
||||
errorMessages = t('workflow.errorMsg.fieldRequired', { field: t('workflow.nodes.http.binaryFileVariable') })
|
||||
|
||||
@ -61,53 +60,6 @@ const nodeDefault: NodeDefault<HttpNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: HttpNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr: string[] = []
|
||||
const url_warnings = getNotExistVariablesByText(payload.url, varMap)
|
||||
if (url_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.http.api')} ${t('workflow.common.referenceVar')}${url_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
const headers_warnings = getNotExistVariablesByText(payload.headers, varMap)
|
||||
if (headers_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.http.headers')} ${t('workflow.common.referenceVar')}${headers_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
const params_warnings = getNotExistVariablesByText(payload.params, varMap)
|
||||
if (params_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.http.params')} ${t('workflow.common.referenceVar')}${params_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
const body_warnings: string[] = []
|
||||
|
||||
if ([BodyType.binary].includes(payload.body.type)) {
|
||||
const body_data = payload.body.data as BodyPayload
|
||||
body_data.forEach((item) => {
|
||||
const key_warnings = getNotExistVariablesByText(item.key || '', varMap)
|
||||
if (key_warnings.length)
|
||||
body_warnings.push(...key_warnings)
|
||||
const warnings = getNotExistVariablesByArray([item.file || []], varMap)
|
||||
if (warnings.length)
|
||||
body_warnings.push(...warnings)
|
||||
})
|
||||
}
|
||||
else {
|
||||
const body_data = payload.body.data as BodyPayload
|
||||
body_data.forEach((item) => {
|
||||
const key_warnings = getNotExistVariablesByText(item.key || '', varMap)
|
||||
if (key_warnings.length)
|
||||
body_warnings.push(...key_warnings)
|
||||
const value_warnings = getNotExistVariablesByText(item.value || '', varMap)
|
||||
if (value_warnings.length)
|
||||
body_warnings.push(...value_warnings)
|
||||
})
|
||||
}
|
||||
if (body_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.http.body')} ${t('workflow.common.referenceVar')}${body_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: [...url_warnings, ...headers_warnings, ...params_warnings, ...body_warnings],
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,4 @@
|
||||
import type { Var } from '../../types'
|
||||
import { BlockEnum, type NodeDefault } from '../../types'
|
||||
import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow'
|
||||
import { type IfElseNodeType, LogicalOperator } from './types'
|
||||
import { isEmptyRelatedOperator } from './utils'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
@ -77,41 +75,6 @@ const nodeDefault: NodeDefault<IfElseNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: IfElseNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
|
||||
const condition_variable_selector_warnings: string[] = []
|
||||
const condition_value_warnings: string[] = []
|
||||
payload.cases.forEach((caseItem) => {
|
||||
caseItem.conditions.forEach((condition) => {
|
||||
if (!condition.variable_selector)
|
||||
return
|
||||
const selector_warnings = getNotExistVariablesByArray([condition.variable_selector], varMap)
|
||||
if (selector_warnings.length)
|
||||
condition_variable_selector_warnings.push(...selector_warnings)
|
||||
const value_warnings = Array.isArray(condition.value) ? getNotExistVariablesByArray([condition.value], varMap) : getNotExistVariablesByText(condition.value, varMap)
|
||||
if (value_warnings.length)
|
||||
condition_value_warnings.push(...value_warnings)
|
||||
condition.sub_variable_condition?.conditions.forEach((subCondition) => {
|
||||
const sub_variable_value_warnings = Array.isArray(subCondition.value) ? getNotExistVariablesByArray([subCondition.value], varMap) : getNotExistVariablesByText(subCondition.value, varMap)
|
||||
if (sub_variable_value_warnings.length)
|
||||
condition_value_warnings.push(...sub_variable_value_warnings)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
if (condition_variable_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.ifElse.condition')} ${t('workflow.common.referenceVar')}${condition_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
if (condition_value_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.ifElse.enterValue')} ${t('workflow.common.referenceVar')}${condition_value_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: condition_variable_selector_warnings,
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum, ErrorHandleMode } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import type { IterationNodeType } from './types'
|
||||
import {
|
||||
ALL_CHAT_AVAILABLE_BLOCKS,
|
||||
@ -59,19 +58,6 @@ const nodeDefault: NodeDefault<IterationNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: IterationNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr: string[] = []
|
||||
|
||||
const iterator_selector_warnings = getNotExistVariablesByArray([payload.iterator_selector], varMap)
|
||||
if (iterator_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.iteration.input')} ${t('workflow.common.referenceVar')}${iterator_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: iterator_selector_warnings,
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -55,7 +55,7 @@ const DatasetItem: FC<Props> = ({
|
||||
}, [onRemove])
|
||||
|
||||
return (
|
||||
<div className={`group/dataset-item flex h-10 cursor-pointer items-center justify-between rounded-xl
|
||||
<div className={`group/dataset-item flex h-10 cursor-pointer items-center justify-between rounded-lg
|
||||
border-[0.5px] border-components-panel-border-subtle px-2
|
||||
${isDeleteHovered
|
||||
? 'border-state-destructive-border bg-state-destructive-hover'
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import type { KnowledgeRetrievalNodeType } from './types'
|
||||
import { checkoutRerankModelConfigedInRetrievalSettings } from './utils'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
@ -53,19 +52,6 @@ const nodeDefault: NodeDefault<KnowledgeRetrievalNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: KnowledgeRetrievalNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
|
||||
const query_variable_selector_warnings = getNotExistVariablesByArray([payload.query_variable_selector], varMap)
|
||||
if (query_variable_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.knowledgeRetrieval.queryVariable')} ${t('workflow.common.referenceVar')}${query_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: [...query_variable_selector_warnings],
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum, VarType } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import { comparisonOperatorNotRequireValue } from '../if-else/utils'
|
||||
import { type ListFilterNodeType, OrderBy } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
@ -61,18 +60,6 @@ const nodeDefault: NodeDefault<ListFilterNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: ListFilterNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
|
||||
const variable_warnings = getNotExistVariablesByArray([payload.variable], varMap)
|
||||
if (variable_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.listFilter.inputVar')} ${t('workflow.common.referenceVar')}${variable_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: variable_warnings,
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,8 +1,6 @@
|
||||
// import { RETRIEVAL_OUTPUT_STRUCT } from '../../constants'
|
||||
import type { Var } from '../../types'
|
||||
import { BlockEnum, EditionType, VarType } from '../../types'
|
||||
import { BlockEnum, EditionType } from '../../types'
|
||||
import { type NodeDefault, type PromptItem, PromptRole } from '../../types'
|
||||
import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow'
|
||||
import type { LLMNodeType } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
|
||||
@ -113,37 +111,6 @@ const nodeDefault: NodeDefault<LLMNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: LLMNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
const prompt_templates_warnings: string[] = []
|
||||
if (payload.context?.enabled && payload.context?.variable_selector?.length) {
|
||||
const context_variable_selector_warnings = getNotExistVariablesByArray([payload.context.variable_selector], varMap)
|
||||
if (context_variable_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.llm.context')} ${t('workflow.common.referenceVar')}${context_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
}
|
||||
const prompt_templates = Array.isArray(payload.prompt_template) ? payload.prompt_template : [payload.prompt_template] as PromptItem[]
|
||||
prompt_templates.forEach((v) => {
|
||||
prompt_templates_warnings.push(...getNotExistVariablesByText(v.text, { context: { variable: 'context', type: VarType.string }, ...varMap }))
|
||||
})
|
||||
if (prompt_templates_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.llm.prompt')} ${t('workflow.common.referenceVar')}${prompt_templates_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
const memory_query_prompt_template_warnings = getNotExistVariablesByText(payload.memory?.query_prompt_template || '', varMap)
|
||||
if (memory_query_prompt_template_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.common.memories.title')}USER ${t('workflow.common.referenceVar')}${memory_query_prompt_template_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
if (payload.vision?.enabled && payload.vision?.configs?.variable_selector?.length) {
|
||||
const vision_variable_selector_warnings = getNotExistVariablesByArray([payload.vision.configs.variable_selector], varMap)
|
||||
if (vision_variable_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.llm.vision')} ${t('workflow.common.referenceVar')}${vision_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: [...prompt_templates_warnings, ...memory_query_prompt_template_warnings],
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import { type ParameterExtractorNodeType, ReasoningModeType } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
const i18nPrefix = 'workflow'
|
||||
@ -65,30 +64,6 @@ const nodeDefault: NodeDefault<ParameterExtractorNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: ParameterExtractorNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr: string[] = []
|
||||
|
||||
const variables_warnings = getNotExistVariablesByArray([payload.query], varMap)
|
||||
if (variables_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.parameterExtractor.inputVar')} ${t('workflow.common.referenceVar')}${variables_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
let vision_variable_warnings: string[] = []
|
||||
if (payload.vision?.configs?.variable_selector?.length) {
|
||||
vision_variable_warnings = getNotExistVariablesByArray([payload.vision.configs.variable_selector], varMap)
|
||||
if (vision_variable_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.llm.vision')} ${t('workflow.common.referenceVar')}${vision_variable_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
}
|
||||
|
||||
const instruction_warnings = getNotExistVariablesByText(payload.instruction, varMap)
|
||||
if (instruction_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.parameterExtractor.instruction')} ${t('workflow.common.referenceVar')}${instruction_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: [...variables_warnings, ...vision_variable_warnings, ...instruction_warnings],
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import { BlockEnum } from '../../types'
|
||||
import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow'
|
||||
import type { QuestionClassifierNodeType } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
|
||||
@ -72,30 +71,6 @@ const nodeDefault: NodeDefault<QuestionClassifierNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: QuestionClassifierNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
|
||||
const query_variable_selector_warnings = getNotExistVariablesByArray([payload.query_variable_selector], varMap)
|
||||
if (query_variable_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.questionClassifiers.inputVars')} ${t('workflow.common.referenceVar')}${query_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
let vision_variable_selector_warnings: string[] = []
|
||||
if (payload.vision?.configs?.variable_selector?.length) {
|
||||
vision_variable_selector_warnings = getNotExistVariablesByArray([payload.vision?.configs?.variable_selector], varMap)
|
||||
if (vision_variable_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.llm.vision')} ${t('workflow.common.referenceVar')}${vision_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
}
|
||||
|
||||
const instruction_warnings: string[] = getNotExistVariablesByText(payload.instruction, varMap)
|
||||
if (instruction_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.questionClassifiers.advancedSetting')}-${t('workflow.nodes.questionClassifiers.instruction')} ${t('workflow.common.referenceVar')}${instruction_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: [...query_variable_selector_warnings, ...vision_variable_selector_warnings, ...instruction_warnings],
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import { getNotExistVariablesByArray } from '../../utils/workflow'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import type { TemplateTransformNodeType } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
const i18nPrefix = 'workflow.errorMsg'
|
||||
@ -34,19 +33,6 @@ const nodeDefault: NodeDefault<TemplateTransformNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: TemplateTransformNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
|
||||
const variables_selector = payload.variables.map(v => v.value_selector)
|
||||
const variables_selector_warnings = getNotExistVariablesByArray(variables_selector, varMap)
|
||||
if (variables_selector_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.templateTransform.inputVars')} ${t('workflow.common.referenceVar')}${variables_selector_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { NodeDefault, Var } from '../../types'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import type { ToolNodeType } from './types'
|
||||
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow'
|
||||
|
||||
const i18nPrefix = 'workflow.errorMsg'
|
||||
|
||||
@ -64,35 +63,6 @@ const nodeDefault: NodeDefault<ToolNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: ToolNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr = []
|
||||
const tool_parametersMap = payload.tool_parameters
|
||||
const tool_parameters_array = Object.values(tool_parametersMap)
|
||||
const tool_parameters_warnings: string[] = []
|
||||
tool_parameters_array?.forEach((item) => {
|
||||
if (!item.value)
|
||||
return
|
||||
if (Array.isArray(item.value)) {
|
||||
const warnings = getNotExistVariablesByArray([item.value], varMap)
|
||||
if (warnings.length)
|
||||
tool_parameters_warnings.push(...warnings)
|
||||
return
|
||||
}
|
||||
if (typeof item.value === 'string') {
|
||||
const warnings = getNotExistVariablesByText(item.value, varMap)
|
||||
if (warnings.length)
|
||||
tool_parameters_warnings.push(...warnings)
|
||||
}
|
||||
})
|
||||
if (tool_parameters_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.tool.inputVars')} ${t('workflow.common.referenceVar')}${tool_parameters_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: tool_parameters_warnings,
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -1,7 +1,5 @@
|
||||
import type { Var } from '../../types'
|
||||
import { type NodeDefault, VarType } from '../../types'
|
||||
import { BlockEnum } from '../../types'
|
||||
import { getNotExistVariablesByArray } from '../../utils/workflow'
|
||||
import type { VariableAssignerNodeType } from './types'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
|
||||
@ -56,18 +54,6 @@ const nodeDefault: NodeDefault<VariableAssignerNodeType> = {
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
checkVarValid(payload: VariableAssignerNodeType, varMap: Record<string, Var>, t: any) {
|
||||
const errorMessageArr: string[] = []
|
||||
const variables_warnings = getNotExistVariablesByArray(payload.variables ?? [], varMap)
|
||||
if (variables_warnings.length)
|
||||
errorMessageArr.push(`${t('workflow.nodes.variableAssigner.title')} ${t('workflow.common.referenceVar')}${variables_warnings.join('、')}${t('workflow.common.noExist')}`)
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
warning_vars: variables_warnings,
|
||||
errorMessage: errorMessageArr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
@ -299,7 +299,6 @@ export type NodeDefault<T> = {
|
||||
getAvailablePrevNodes: (isChatMode: boolean) => BlockEnum[]
|
||||
getAvailableNextNodes: (isChatMode: boolean) => BlockEnum[]
|
||||
checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string }
|
||||
checkVarValid?: (payload: T, varMap: Record<string, Var>, t: any,) => { isValid: boolean; errorMessage?: string[] }
|
||||
}
|
||||
|
||||
export type OnSelectBlock = (type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => void
|
||||
|
@ -5,18 +5,6 @@ import type {
|
||||
} from '@/app/components/workflow/types'
|
||||
import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants'
|
||||
|
||||
jest.mock('ky', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
create: jest.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock('lodash-es/groupBy', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(),
|
||||
}))
|
||||
|
||||
describe('preprocessNodesAndEdges', () => {
|
||||
it('process nodes without iteration node or loop node should return origin nodes and edges.', () => {
|
||||
const nodes = [
|
||||
|
@ -10,20 +10,14 @@ import {
|
||||
uniqBy,
|
||||
} from 'lodash-es'
|
||||
import type {
|
||||
ConversationVariable,
|
||||
Edge,
|
||||
EnvironmentVariable,
|
||||
Node,
|
||||
Var,
|
||||
} from '../types'
|
||||
import {
|
||||
BlockEnum,
|
||||
} from '../types'
|
||||
import type { IterationNodeType } from '../nodes/iteration/types'
|
||||
import type { LoopNodeType } from '../nodes/loop/types'
|
||||
import { VAR_REGEX_TEXT } from '@/config'
|
||||
import { formatItem } from '../nodes/_base/components/variable/utils'
|
||||
import type { StructuredOutput } from '../nodes/llm/types'
|
||||
|
||||
export const canRunBySingle = (nodeType: BlockEnum) => {
|
||||
return nodeType === BlockEnum.LLM
|
||||
@ -95,17 +89,7 @@ export const getNodesConnectedSourceOrTargetHandleIdsMap = (changes: ConnectedSo
|
||||
return nodesConnectedSourceOrTargetHandleIdsMap
|
||||
}
|
||||
|
||||
function getParentOutputVarMap(item: Var, path: string, varMap: Record<string, Var>) {
|
||||
if (!item.children || (Array.isArray(item.children) && !item.children.length) || ((item.children as StructuredOutput).schema))
|
||||
return
|
||||
(item.children as Var[]).forEach((child) => {
|
||||
const newPath = `${path}.${child.variable}`
|
||||
varMap[newPath] = child
|
||||
getParentOutputVarMap(child, newPath, varMap)
|
||||
})
|
||||
}
|
||||
|
||||
export const getValidTreeNodes = (nodes: Node[], edges: Edge[], isCollectVar?: boolean) => {
|
||||
export const getValidTreeNodes = (nodes: Node[], edges: Edge[]) => {
|
||||
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
|
||||
if (!startNode) {
|
||||
@ -128,19 +112,6 @@ export const getValidTreeNodes = (nodes: Node[], edges: Edge[], isCollectVar?: b
|
||||
outgoers.forEach((outgoer) => {
|
||||
list.push(outgoer)
|
||||
|
||||
if (isCollectVar) {
|
||||
const nodeObj = formatItem(root, false, () => true)
|
||||
const varMap = {} as Record<string, Var>
|
||||
nodeObj.vars.forEach((item) => {
|
||||
if (item.variable.startsWith('sys.'))
|
||||
return
|
||||
const newPath = `${nodeObj.nodeId}.${item.variable}`
|
||||
varMap[newPath] = item
|
||||
getParentOutputVarMap(item, newPath, varMap)
|
||||
})
|
||||
outgoer._parentOutputVarMap = { ...(root._parentOutputVarMap ?? {}), ...varMap }
|
||||
}
|
||||
|
||||
if (outgoer.data.type === BlockEnum.Iteration)
|
||||
list.push(...nodes.filter(node => node.parentId === outgoer.id))
|
||||
if (outgoer.data.type === BlockEnum.Loop)
|
||||
@ -359,48 +330,3 @@ export const getParallelInfo = (nodes: Node[], edges: Edge[], parentNodeId?: str
|
||||
export const hasErrorHandleNode = (nodeType?: BlockEnum) => {
|
||||
return nodeType === BlockEnum.LLM || nodeType === BlockEnum.Tool || nodeType === BlockEnum.HttpRequest || nodeType === BlockEnum.Code
|
||||
}
|
||||
|
||||
export const transformStartNodeVariables = (chatVarList: ConversationVariable[], environmentVariables: EnvironmentVariable[]) => {
|
||||
const variablesMap: Record<string, ConversationVariable | EnvironmentVariable> = {}
|
||||
chatVarList.forEach((variable) => {
|
||||
variablesMap[`conversation.${variable.name}`] = variable
|
||||
})
|
||||
environmentVariables.forEach((variable) => {
|
||||
variablesMap[`env.${variable.name}`] = variable
|
||||
})
|
||||
return variablesMap
|
||||
}
|
||||
|
||||
export const getNotExistVariablesByText = (text: string, varMap: Record<string, Var>) => {
|
||||
const var_warnings: string[] = []
|
||||
text?.replace(VAR_REGEX_TEXT, (str, id_name) => {
|
||||
if (id_name.startsWith('sys.'))
|
||||
return str
|
||||
if (varMap[id_name])
|
||||
return str
|
||||
const arr = id_name.split('.')
|
||||
arr.shift()
|
||||
var_warnings.push(arr.join('.'))
|
||||
return str
|
||||
})
|
||||
return var_warnings
|
||||
}
|
||||
|
||||
export const getNotExistVariablesByArray = (array: string[][], varMap: Record<string, Var>) => {
|
||||
if (!array.length)
|
||||
return []
|
||||
const var_warnings: string[] = []
|
||||
array.forEach((item) => {
|
||||
if (!item.length)
|
||||
return
|
||||
if (['sys'].includes(item[0]))
|
||||
return
|
||||
const var_warning = varMap[item.join('.')]
|
||||
if (var_warning)
|
||||
return
|
||||
const arr = [...item]
|
||||
arr.shift()
|
||||
var_warnings.push(arr.join('.'))
|
||||
})
|
||||
return var_warnings
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import { useToastContext } from '@/app/components/base/toast'
|
||||
import { EDUCATION_VERIFYING_LOCALSTORAGE_ITEM } from '@/app/education-apply/constants'
|
||||
import { getLocaleOnClient } from '@/i18n'
|
||||
import { noop } from 'lodash-es'
|
||||
import DifyLogo from '../components/base/logo/dify-logo'
|
||||
|
||||
const EducationApplyAge = () => {
|
||||
const { t } = useTranslation()
|
||||
@ -93,12 +94,8 @@ const EducationApplyAge = () => {
|
||||
}}
|
||||
>
|
||||
</div>
|
||||
<div className='mt-[-349px] flex h-[88px] items-center justify-between px-8 py-6'>
|
||||
<img
|
||||
src='/logo/logo-site-dark.png'
|
||||
alt='dify logo'
|
||||
className='h-10'
|
||||
/>
|
||||
<div className='mt-[-349px] box-content flex h-7 items-center justify-between p-6'>
|
||||
<DifyLogo size='large' style='monochromeWhite' />
|
||||
</div>
|
||||
<div className='mx-auto max-w-[720px] px-8 pb-[180px]'>
|
||||
<div className='mb-2 flex h-[192px] flex-col justify-end pb-4 pt-3 text-text-primary-on-surface'>
|
||||
|
@ -2,19 +2,28 @@
|
||||
import React from 'react'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import Select from '@/app/components/base/select/locale'
|
||||
import ThemeSelector from '@/app/components/base/theme-selector'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { languages } from '@/i18n/language'
|
||||
import type { Locale } from '@/i18n'
|
||||
import I18n from '@/context/i18n'
|
||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// Avoid rendering the logo and theme selector on the server
|
||||
const DifyLogo = dynamic(() => import('@/app/components/base/logo/dify-logo'), {
|
||||
ssr: false,
|
||||
loading: () => <div className='h-7 w-16 bg-transparent' />,
|
||||
})
|
||||
const ThemeSelector = dynamic(() => import('@/app/components/base/theme-selector'), {
|
||||
ssr: false,
|
||||
loading: () => <div className='size-8 bg-transparent' />,
|
||||
})
|
||||
|
||||
const Header = () => {
|
||||
const { locale, setLocaleOnClient } = useContext(I18n)
|
||||
|
||||
return (
|
||||
<div className='flex w-full items-center justify-between p-6'>
|
||||
<LogoSite />
|
||||
<DifyLogo size='large' />
|
||||
<div className='flex items-center gap-1'>
|
||||
<Select
|
||||
value={locale}
|
||||
|
@ -282,8 +282,6 @@ Thought: {{agent_scratchpad}}
|
||||
|
||||
export const VAR_REGEX = /\{\{(#[a-zA-Z0-9_-]{1,50}(\.[a-zA-Z_]\w{0,29}){1,10}#)\}\}/gi
|
||||
|
||||
export const VAR_REGEX_TEXT = /\{\{#([a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*)#\}\}/gi
|
||||
|
||||
export const resetReg = () => VAR_REGEX.lastIndex = 0
|
||||
|
||||
export let textGenerationTimeoutMs = 60000
|
||||
|
@ -113,8 +113,6 @@ const translation = {
|
||||
addFailureBranch: 'Add Fail Branch',
|
||||
loadMore: 'Load More',
|
||||
noHistory: 'No History',
|
||||
referenceVar: 'Reference Variable',
|
||||
noExist: 'No such variable',
|
||||
},
|
||||
env: {
|
||||
envPanelTitle: 'Environment Variables',
|
||||
@ -598,7 +596,6 @@ const translation = {
|
||||
selectVariable: 'Select variable...',
|
||||
addSubVariable: 'Sub Variable',
|
||||
select: 'Select',
|
||||
condition: 'Condition',
|
||||
},
|
||||
variableAssigner: {
|
||||
title: 'Assign variables',
|
||||
|
@ -113,8 +113,6 @@ const translation = {
|
||||
addFailureBranch: '失敗ブランチを追加',
|
||||
loadMore: 'さらに読み込む',
|
||||
noHistory: '履歴がありません',
|
||||
referenceVar: '参照変数',
|
||||
noExist: '存在しません',
|
||||
},
|
||||
env: {
|
||||
envPanelTitle: '環境変数',
|
||||
@ -600,7 +598,6 @@ const translation = {
|
||||
},
|
||||
select: '選ぶ',
|
||||
addSubVariable: 'サブ変数',
|
||||
condition: '条件',
|
||||
},
|
||||
variableAssigner: {
|
||||
title: '変数を代入する',
|
||||
|
@ -113,8 +113,6 @@ const translation = {
|
||||
openInExplore: '在“探索”中打开',
|
||||
loadMore: '加载更多',
|
||||
noHistory: '没有历史版本',
|
||||
referenceVar: '引用变量',
|
||||
noExist: '不存在',
|
||||
},
|
||||
env: {
|
||||
envPanelTitle: '环境变量',
|
||||
@ -599,7 +597,6 @@ const translation = {
|
||||
selectVariable: '选择变量',
|
||||
addSubVariable: '添加子变量',
|
||||
select: '选择',
|
||||
condition: '条件',
|
||||
},
|
||||
variableAssigner: {
|
||||
title: '变量赋值',
|
||||
|
@ -37,7 +37,7 @@ export function middleware(request: NextRequest) {
|
||||
style-src 'self' 'unsafe-inline' ${scheme_source} ${whiteList};
|
||||
worker-src 'self' ${scheme_source} ${csp} ${whiteList};
|
||||
media-src 'self' ${scheme_source} ${csp} ${whiteList};
|
||||
img-src *;
|
||||
img-src * data:;
|
||||
font-src 'self';
|
||||
object-src 'none';
|
||||
base-uri 'self';
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dify-web",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.0",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=v22.11.0"
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
12
web/public/logo/logo-monochrome-white.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg width="48" height="22" viewBox="0 0 48 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="White=True">
|
||||
<g id="if">
|
||||
<path d="M21.2002 4.0695C22.5633 4.0695 23.0666 3.23413 23.0666 2.20309C23.0666 1.17204 22.5623 0.33667 21.2002 0.33667C19.838 0.33667 19.3337 1.17204 19.3337 2.20309C19.3337 3.23413 19.838 4.0695 21.2002 4.0695Z" fill="white"/>
|
||||
<path d="M27.7336 4.46931V5.66969H24.6668V8.33667H27.7336V15.0037H22.6668V5.67063H15.9998V8.33761H19.7336V15.0046H15.3337V17.6716H35.3337V15.0046H30.6668V8.33761H35.3337V5.67063H30.6668V3.00365H35.3337V0.33667H31.8671C29.5877 0.33667 27.7336 2.19086 27.7336 4.47025V4.46931Z" fill="white"/>
|
||||
</g>
|
||||
<g id="Dy">
|
||||
<path d="M5.66698 0.335902H0V17.6689H5.66698C12.667 17.6689 14.667 13.6689 14.667 9.00194C14.667 4.33496 12.667 0.334961 5.66698 0.334961V0.335902ZM5.73377 15.0029H3.20038V3.00288H5.73377C9.75823 3.00288 11.4666 4.97842 11.4666 9.00288C11.4666 13.0273 9.75823 15.0029 5.73377 15.0029Z" fill="white"/>
|
||||
<path d="M44.8335 5.66986L42.1665 14.3368L39.4995 5.66986H36.333L40.2013 16.8815C40.604 18.049 39.9229 19.0029 38.6886 19.0029H37.333V21.6699H39.3255C41.063 21.6699 42.6265 20.5711 43.2145 18.9361L48 5.66986H44.8335Z" fill="white"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 6.1 KiB |
12
web/public/logo/logo.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg width="48" height="22" viewBox="0 0 48 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="White=False">
|
||||
<g id="if">
|
||||
<path d="M21.2002 3.73454C22.5633 3.73454 23.0666 2.89917 23.0666 1.86812C23.0666 0.837081 22.5623 0.00170898 21.2002 0.00170898C19.838 0.00170898 19.3337 0.837081 19.3337 1.86812C19.3337 2.89917 19.838 3.73454 21.2002 3.73454Z" fill="#0033FF"/>
|
||||
<path d="M27.7336 4.13435V5.33473H24.6668V8.00171H27.7336V14.6687H22.6668V5.33567H15.9998V8.00265H19.7336V14.6696H15.3337V17.3366H35.3337V14.6696H30.6668V8.00265H35.3337V5.33567H30.6668V2.66869H35.3337V0.00170898H31.8671C29.5877 0.00170898 27.7336 1.8559 27.7336 4.13529V4.13435Z" fill="#0033FF"/>
|
||||
</g>
|
||||
<g id="Dy">
|
||||
<path d="M5.66698 0.000940576H0V17.334H5.66698C12.667 17.334 14.667 13.334 14.667 8.66698C14.667 4 12.667 0 5.66698 0V0.000940576ZM5.73377 14.6679H3.20038V2.66792H5.73377C9.75823 2.66792 11.4666 4.64346 11.4666 8.66792C11.4666 12.6924 9.75823 14.6679 5.73377 14.6679Z" fill="black"/>
|
||||
<path d="M44.8335 5.3349L42.1665 14.0019L39.4995 5.3349H36.333L40.2013 16.5466C40.604 17.714 39.9229 18.6679 38.6886 18.6679H37.333V21.3349H39.3255C41.063 21.3349 42.6265 20.2361 43.2145 18.6011L48 5.3349H44.8335Z" fill="black"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |