mirror of
https://gitee.com/dify_ai/dify.git
synced 2025-12-07 03:45:27 +08:00
Compare commits
21 Commits
fix/code-n
...
0.15.6-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa6fa730b5 | ||
|
|
94c08462a1 | ||
|
|
307ebbb4ff | ||
|
|
7ebae9e3c2 | ||
|
|
de627ca9fa | ||
|
|
193aaaeab6 | ||
|
|
8e75eb5c63 | ||
|
|
970508fcb6 | ||
|
|
9283a5414f | ||
|
|
2a2a0e9be9 | ||
|
|
061a765b7d | ||
|
|
acd7fead87 | ||
|
|
bbb080d5b2 | ||
|
|
c01d8a70f3 | ||
|
|
1ca15989e0 | ||
|
|
8b5a3a9424 | ||
|
|
42ddcf1edd | ||
|
|
21561df10f | ||
|
|
0e33a3aa5f | ||
|
|
d3895bcd6b | ||
|
|
eeb390650b |
4
.github/workflows/build-push.yml
vendored
4
.github/workflows/build-push.yml
vendored
@@ -5,8 +5,8 @@ on:
|
||||
branches:
|
||||
- "main"
|
||||
- "deploy/dev"
|
||||
release:
|
||||
types: [published]
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
concurrency:
|
||||
group: build-push-${{ github.head_ref || github.run_id }}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -175,6 +175,7 @@ docker/volumes/pgvector/data/*
|
||||
docker/volumes/pgvecto_rs/data/*
|
||||
docker/volumes/couchbase/*
|
||||
docker/volumes/oceanbase/*
|
||||
docker/volumes/plugin_daemon/*
|
||||
!docker/volumes/oceanbase/init.d
|
||||
|
||||
docker/nginx/conf.d/default.conf
|
||||
|
||||
@@ -9,7 +9,7 @@ class PackagingInfo(BaseSettings):
|
||||
|
||||
CURRENT_VERSION: str = Field(
|
||||
description="Dify version",
|
||||
default="0.15.3",
|
||||
default="0.15.6-alpha.1",
|
||||
)
|
||||
|
||||
COMMIT_SHA: str = Field(
|
||||
|
||||
@@ -537,7 +537,6 @@ if you are not sure about the structure.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def get_num_tokens(
|
||||
self,
|
||||
model: str,
|
||||
@@ -915,3 +914,7 @@ if you are not sure about the structure.
|
||||
filtered_model_parameters[parameter_name] = parameter_value
|
||||
|
||||
return filtered_model_parameters
|
||||
|
||||
def _get_num_tokens_by_gpt2(self, text: str) -> int:
|
||||
# Disable the token count in LLMs for profermance testing.
|
||||
return 0
|
||||
|
||||
@@ -77,5 +77,4 @@
|
||||
- onebot
|
||||
- regex
|
||||
- trello
|
||||
- vanna
|
||||
- fal
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.5 KiB |
@@ -1,134 +0,0 @@
|
||||
from typing import Any, Union
|
||||
|
||||
from vanna.remote import VannaDefault # type: ignore
|
||||
|
||||
from core.tools.entities.tool_entities import ToolInvokeMessage
|
||||
from core.tools.errors import ToolProviderCredentialValidationError
|
||||
from core.tools.tool.builtin_tool import BuiltinTool
|
||||
|
||||
|
||||
class VannaTool(BuiltinTool):
|
||||
def _invoke(
|
||||
self, user_id: str, tool_parameters: dict[str, Any]
|
||||
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
|
||||
"""
|
||||
invoke tools
|
||||
"""
|
||||
# Ensure runtime and credentials
|
||||
if not self.runtime or not self.runtime.credentials:
|
||||
raise ToolProviderCredentialValidationError("Tool runtime or credentials are missing")
|
||||
api_key = self.runtime.credentials.get("api_key", None)
|
||||
if not api_key:
|
||||
raise ToolProviderCredentialValidationError("Please input api key")
|
||||
|
||||
model = tool_parameters.get("model", "")
|
||||
if not model:
|
||||
return self.create_text_message("Please input RAG model")
|
||||
|
||||
prompt = tool_parameters.get("prompt", "")
|
||||
if not prompt:
|
||||
return self.create_text_message("Please input prompt")
|
||||
|
||||
url = tool_parameters.get("url", "")
|
||||
if not url:
|
||||
return self.create_text_message("Please input URL/Host/DSN")
|
||||
|
||||
db_name = tool_parameters.get("db_name", "")
|
||||
username = tool_parameters.get("username", "")
|
||||
password = tool_parameters.get("password", "")
|
||||
port = tool_parameters.get("port", 0)
|
||||
|
||||
base_url = self.runtime.credentials.get("base_url", None)
|
||||
vn = VannaDefault(model=model, api_key=api_key, config={"endpoint": base_url})
|
||||
|
||||
db_type = tool_parameters.get("db_type", "")
|
||||
if db_type in {"Postgres", "MySQL", "Hive", "ClickHouse"}:
|
||||
if not db_name:
|
||||
return self.create_text_message("Please input database name")
|
||||
if not username:
|
||||
return self.create_text_message("Please input username")
|
||||
if port < 1:
|
||||
return self.create_text_message("Please input port")
|
||||
|
||||
schema_sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS"
|
||||
match db_type:
|
||||
case "SQLite":
|
||||
schema_sql = "SELECT type, sql FROM sqlite_master WHERE sql is not null"
|
||||
vn.connect_to_sqlite(url)
|
||||
case "Postgres":
|
||||
vn.connect_to_postgres(host=url, dbname=db_name, user=username, password=password, port=port)
|
||||
case "DuckDB":
|
||||
vn.connect_to_duckdb(url=url)
|
||||
case "SQLServer":
|
||||
vn.connect_to_mssql(url)
|
||||
case "MySQL":
|
||||
vn.connect_to_mysql(host=url, dbname=db_name, user=username, password=password, port=port)
|
||||
case "Oracle":
|
||||
vn.connect_to_oracle(user=username, password=password, dsn=url)
|
||||
case "Hive":
|
||||
vn.connect_to_hive(host=url, dbname=db_name, user=username, password=password, port=port)
|
||||
case "ClickHouse":
|
||||
vn.connect_to_clickhouse(host=url, dbname=db_name, user=username, password=password, port=port)
|
||||
|
||||
enable_training = tool_parameters.get("enable_training", False)
|
||||
reset_training_data = tool_parameters.get("reset_training_data", False)
|
||||
if enable_training:
|
||||
if reset_training_data:
|
||||
existing_training_data = vn.get_training_data()
|
||||
if len(existing_training_data) > 0:
|
||||
for _, training_data in existing_training_data.iterrows():
|
||||
vn.remove_training_data(training_data["id"])
|
||||
|
||||
ddl = tool_parameters.get("ddl", "")
|
||||
question = tool_parameters.get("question", "")
|
||||
sql = tool_parameters.get("sql", "")
|
||||
memos = tool_parameters.get("memos", "")
|
||||
training_metadata = tool_parameters.get("training_metadata", False)
|
||||
|
||||
if training_metadata:
|
||||
if db_type == "SQLite":
|
||||
df_ddl = vn.run_sql(schema_sql)
|
||||
for ddl in df_ddl["sql"].to_list():
|
||||
vn.train(ddl=ddl)
|
||||
else:
|
||||
df_information_schema = vn.run_sql(schema_sql)
|
||||
plan = vn.get_training_plan_generic(df_information_schema)
|
||||
vn.train(plan=plan)
|
||||
|
||||
if ddl:
|
||||
vn.train(ddl=ddl)
|
||||
|
||||
if sql:
|
||||
if question:
|
||||
vn.train(question=question, sql=sql)
|
||||
else:
|
||||
vn.train(sql=sql)
|
||||
if memos:
|
||||
vn.train(documentation=memos)
|
||||
|
||||
#########################################################################################
|
||||
# Due to CVE-2024-5565, we have to disable the chart generation feature
|
||||
# The Vanna library uses a prompt function to present the user with visualized results,
|
||||
# it is possible to alter the prompt using prompt injection and run arbitrary Python code
|
||||
# instead of the intended visualization code.
|
||||
# Specifically - allowing external input to the library’s “ask” method
|
||||
# with "visualize" set to True (default behavior) leads to remote code execution.
|
||||
# Affected versions: <= 0.5.5
|
||||
#########################################################################################
|
||||
allow_llm_to_see_data = tool_parameters.get("allow_llm_to_see_data", False)
|
||||
res = vn.ask(
|
||||
prompt, print_results=False, auto_train=True, visualize=False, allow_llm_to_see_data=allow_llm_to_see_data
|
||||
)
|
||||
|
||||
result = []
|
||||
|
||||
if res is not None:
|
||||
result.append(self.create_text_message(res[0]))
|
||||
if len(res) > 1 and res[1] is not None:
|
||||
result.append(self.create_text_message(res[1].to_markdown()))
|
||||
if len(res) > 2 and res[2] is not None:
|
||||
result.append(
|
||||
self.create_blob_message(blob=res[2].to_image(format="svg"), meta={"mime_type": "image/svg+xml"})
|
||||
)
|
||||
|
||||
return result
|
||||
@@ -1,213 +0,0 @@
|
||||
identity:
|
||||
name: vanna
|
||||
author: QCTC
|
||||
label:
|
||||
en_US: Vanna.AI
|
||||
zh_Hans: Vanna.AI
|
||||
description:
|
||||
human:
|
||||
en_US: The fastest way to get actionable insights from your database just by asking questions.
|
||||
zh_Hans: 一个基于大模型和RAG的Text2SQL工具。
|
||||
llm: A tool for converting text to SQL.
|
||||
parameters:
|
||||
- name: prompt
|
||||
type: string
|
||||
required: true
|
||||
label:
|
||||
en_US: Prompt
|
||||
zh_Hans: 提示词
|
||||
pt_BR: Prompt
|
||||
human_description:
|
||||
en_US: used for generating SQL
|
||||
zh_Hans: 用于生成SQL
|
||||
llm_description: key words for generating SQL
|
||||
form: llm
|
||||
- name: model
|
||||
type: string
|
||||
required: true
|
||||
label:
|
||||
en_US: RAG Model
|
||||
zh_Hans: RAG模型
|
||||
human_description:
|
||||
en_US: RAG Model for your database DDL
|
||||
zh_Hans: 存储数据库训练数据的RAG模型
|
||||
llm_description: RAG Model for generating SQL
|
||||
form: llm
|
||||
- name: db_type
|
||||
type: select
|
||||
required: true
|
||||
options:
|
||||
- value: SQLite
|
||||
label:
|
||||
en_US: SQLite
|
||||
zh_Hans: SQLite
|
||||
- value: Postgres
|
||||
label:
|
||||
en_US: Postgres
|
||||
zh_Hans: Postgres
|
||||
- value: DuckDB
|
||||
label:
|
||||
en_US: DuckDB
|
||||
zh_Hans: DuckDB
|
||||
- value: SQLServer
|
||||
label:
|
||||
en_US: Microsoft SQL Server
|
||||
zh_Hans: 微软 SQL Server
|
||||
- value: MySQL
|
||||
label:
|
||||
en_US: MySQL
|
||||
zh_Hans: MySQL
|
||||
- value: Oracle
|
||||
label:
|
||||
en_US: Oracle
|
||||
zh_Hans: Oracle
|
||||
- value: Hive
|
||||
label:
|
||||
en_US: Hive
|
||||
zh_Hans: Hive
|
||||
- value: ClickHouse
|
||||
label:
|
||||
en_US: ClickHouse
|
||||
zh_Hans: ClickHouse
|
||||
default: SQLite
|
||||
label:
|
||||
en_US: DB Type
|
||||
zh_Hans: 数据库类型
|
||||
human_description:
|
||||
en_US: Database type.
|
||||
zh_Hans: 选择要链接的数据库类型。
|
||||
form: form
|
||||
- name: url
|
||||
type: string
|
||||
required: true
|
||||
label:
|
||||
en_US: URL/Host/DSN
|
||||
zh_Hans: URL/Host/DSN
|
||||
human_description:
|
||||
en_US: Please input depending on DB type, visit https://vanna.ai/docs/ for more specification
|
||||
zh_Hans: 请根据数据库类型,填入对应值,详情参考https://vanna.ai/docs/
|
||||
form: form
|
||||
- name: db_name
|
||||
type: string
|
||||
required: false
|
||||
label:
|
||||
en_US: DB name
|
||||
zh_Hans: 数据库名
|
||||
human_description:
|
||||
en_US: Database name
|
||||
zh_Hans: 数据库名
|
||||
form: form
|
||||
- name: username
|
||||
type: string
|
||||
required: false
|
||||
label:
|
||||
en_US: Username
|
||||
zh_Hans: 用户名
|
||||
human_description:
|
||||
en_US: Username
|
||||
zh_Hans: 用户名
|
||||
form: form
|
||||
- name: password
|
||||
type: secret-input
|
||||
required: false
|
||||
label:
|
||||
en_US: Password
|
||||
zh_Hans: 密码
|
||||
human_description:
|
||||
en_US: Password
|
||||
zh_Hans: 密码
|
||||
form: form
|
||||
- name: port
|
||||
type: number
|
||||
required: false
|
||||
label:
|
||||
en_US: Port
|
||||
zh_Hans: 端口
|
||||
human_description:
|
||||
en_US: Port
|
||||
zh_Hans: 端口
|
||||
form: form
|
||||
- name: ddl
|
||||
type: string
|
||||
required: false
|
||||
label:
|
||||
en_US: Training DDL
|
||||
zh_Hans: 训练DDL
|
||||
human_description:
|
||||
en_US: DDL statements for training data
|
||||
zh_Hans: 用于训练RAG Model的建表语句
|
||||
form: llm
|
||||
- name: question
|
||||
type: string
|
||||
required: false
|
||||
label:
|
||||
en_US: Training Question
|
||||
zh_Hans: 训练问题
|
||||
human_description:
|
||||
en_US: Question-SQL Pairs
|
||||
zh_Hans: Question-SQL中的问题
|
||||
form: llm
|
||||
- name: sql
|
||||
type: string
|
||||
required: false
|
||||
label:
|
||||
en_US: Training SQL
|
||||
zh_Hans: 训练SQL
|
||||
human_description:
|
||||
en_US: SQL queries to your training data
|
||||
zh_Hans: 用于训练RAG Model的SQL语句
|
||||
form: llm
|
||||
- name: memos
|
||||
type: string
|
||||
required: false
|
||||
label:
|
||||
en_US: Training Memos
|
||||
zh_Hans: 训练说明
|
||||
human_description:
|
||||
en_US: Sometimes you may want to add documentation about your business terminology or definitions
|
||||
zh_Hans: 添加更多关于数据库的业务说明
|
||||
form: llm
|
||||
- name: enable_training
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
label:
|
||||
en_US: Training Data
|
||||
zh_Hans: 训练数据
|
||||
human_description:
|
||||
en_US: You only need to train once. Do not train again unless you want to add more training data
|
||||
zh_Hans: 训练数据无更新时,训练一次即可
|
||||
form: form
|
||||
- name: reset_training_data
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
label:
|
||||
en_US: Reset Training Data
|
||||
zh_Hans: 重置训练数据
|
||||
human_description:
|
||||
en_US: Remove all training data in the current RAG Model
|
||||
zh_Hans: 删除当前RAG Model中的所有训练数据
|
||||
form: form
|
||||
- name: training_metadata
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
label:
|
||||
en_US: Training Metadata
|
||||
zh_Hans: 训练元数据
|
||||
human_description:
|
||||
en_US: If enabled, it will attempt to train on the metadata of that database
|
||||
zh_Hans: 是否自动从数据库获取元数据来训练
|
||||
form: form
|
||||
- name: allow_llm_to_see_data
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
label:
|
||||
en_US: Whether to allow the LLM to see the data
|
||||
zh_Hans: 是否允许LLM查看数据
|
||||
human_description:
|
||||
en_US: Whether to allow the LLM to see the data
|
||||
zh_Hans: 是否允许LLM查看数据
|
||||
form: form
|
||||
@@ -1,46 +0,0 @@
|
||||
import re
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from core.tools.errors import ToolProviderCredentialValidationError
|
||||
from core.tools.provider.builtin.vanna.tools.vanna import VannaTool
|
||||
from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
|
||||
|
||||
|
||||
class VannaProvider(BuiltinToolProviderController):
|
||||
def _get_protocol_and_main_domain(self, url):
|
||||
parsed_url = urlparse(url)
|
||||
protocol = parsed_url.scheme
|
||||
hostname = parsed_url.hostname
|
||||
port = f":{parsed_url.port}" if parsed_url.port else ""
|
||||
|
||||
# Check if the hostname is an IP address
|
||||
is_ip = re.match(r"^\d{1,3}(\.\d{1,3}){3}$", hostname) is not None
|
||||
|
||||
# Return the full hostname (with port if present) for IP addresses, otherwise return the main domain
|
||||
main_domain = f"{hostname}{port}" if is_ip else ".".join(hostname.split(".")[-2:]) + port
|
||||
return f"{protocol}://{main_domain}"
|
||||
|
||||
def _validate_credentials(self, credentials: dict[str, Any]) -> None:
|
||||
base_url = credentials.get("base_url")
|
||||
if not base_url:
|
||||
base_url = "https://ask.vanna.ai/rpc"
|
||||
else:
|
||||
base_url = base_url.removesuffix("/")
|
||||
credentials["base_url"] = base_url
|
||||
try:
|
||||
VannaTool().fork_tool_runtime(
|
||||
runtime={
|
||||
"credentials": credentials,
|
||||
}
|
||||
).invoke(
|
||||
user_id="",
|
||||
tool_parameters={
|
||||
"model": "chinook",
|
||||
"db_type": "SQLite",
|
||||
"url": f"{self._get_protocol_and_main_domain(credentials['base_url'])}/Chinook.sqlite",
|
||||
"query": "What are the top 10 customers by sales?",
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
raise ToolProviderCredentialValidationError(str(e))
|
||||
@@ -1,35 +0,0 @@
|
||||
identity:
|
||||
author: QCTC
|
||||
name: vanna
|
||||
label:
|
||||
en_US: Vanna.AI
|
||||
zh_Hans: Vanna.AI
|
||||
description:
|
||||
en_US: The fastest way to get actionable insights from your database just by asking questions.
|
||||
zh_Hans: 一个基于大模型和RAG的Text2SQL工具。
|
||||
icon: icon.png
|
||||
tags:
|
||||
- utilities
|
||||
- productivity
|
||||
credentials_for_provider:
|
||||
api_key:
|
||||
type: secret-input
|
||||
required: true
|
||||
label:
|
||||
en_US: API key
|
||||
zh_Hans: API key
|
||||
placeholder:
|
||||
en_US: Please input your API key
|
||||
zh_Hans: 请输入你的 API key
|
||||
pt_BR: Please input your API key
|
||||
help:
|
||||
en_US: Get your API key from Vanna.AI
|
||||
zh_Hans: 从 Vanna.AI 获取你的 API key
|
||||
url: https://vanna.ai/account/profile
|
||||
base_url:
|
||||
type: text-input
|
||||
required: false
|
||||
label:
|
||||
en_US: Vanna.AI Endpoint Base URL
|
||||
placeholder:
|
||||
en_US: https://ask.vanna.ai/rpc
|
||||
@@ -2,7 +2,7 @@ x-shared-env: &shared-api-worker-env
|
||||
services:
|
||||
# API service
|
||||
api:
|
||||
image: langgenius/dify-api:0.15.3
|
||||
image: langgenius/dify-api:0.15.6-alpha.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -25,7 +25,7 @@ services:
|
||||
# worker service
|
||||
# The Celery worker for processing the queue.
|
||||
worker:
|
||||
image: langgenius/dify-api:0.15.3
|
||||
image: langgenius/dify-api:0.15.6-alpha.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -47,7 +47,7 @@ services:
|
||||
|
||||
# Frontend web application.
|
||||
web:
|
||||
image: langgenius/dify-web:0.15.3
|
||||
image: langgenius/dify-web:0.15.6-alpha.1
|
||||
restart: always
|
||||
environment:
|
||||
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
|
||||
@@ -98,7 +98,7 @@ services:
|
||||
|
||||
# The DifySandbox
|
||||
sandbox:
|
||||
image: langgenius/dify-sandbox:0.2.10
|
||||
image: langgenius/dify-sandbox:0.2.11
|
||||
restart: always
|
||||
environment:
|
||||
# The DifySandbox configurations
|
||||
|
||||
@@ -43,7 +43,7 @@ services:
|
||||
|
||||
# The DifySandbox
|
||||
sandbox:
|
||||
image: langgenius/dify-sandbox:0.2.10
|
||||
image: langgenius/dify-sandbox:0.2.11
|
||||
restart: always
|
||||
environment:
|
||||
# The DifySandbox configurations
|
||||
|
||||
@@ -393,7 +393,7 @@ x-shared-env: &shared-api-worker-env
|
||||
services:
|
||||
# API service
|
||||
api:
|
||||
image: langgenius/dify-api:0.15.3
|
||||
image: langgenius/dify-api:0.15.5-alpha.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -416,7 +416,7 @@ services:
|
||||
# worker service
|
||||
# The Celery worker for processing the queue.
|
||||
worker:
|
||||
image: langgenius/dify-api:0.15.3
|
||||
image: langgenius/dify-api:0.15.5-alpha.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -438,7 +438,7 @@ services:
|
||||
|
||||
# Frontend web application.
|
||||
web:
|
||||
image: langgenius/dify-web:0.15.3
|
||||
image: langgenius/dify-web:0.15.5-alpha.1
|
||||
restart: always
|
||||
environment:
|
||||
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
|
||||
@@ -489,7 +489,7 @@ services:
|
||||
|
||||
# The DifySandbox
|
||||
sandbox:
|
||||
image: langgenius/dify-sandbox:0.2.10
|
||||
image: langgenius/dify-sandbox:0.2.11
|
||||
restart: always
|
||||
environment:
|
||||
# The DifySandbox configurations
|
||||
|
||||
@@ -312,7 +312,7 @@ function AppPreview({ mode }: { mode: AppMode }) {
|
||||
'chat': {
|
||||
title: t('app.types.chatbot'),
|
||||
description: t('app.newApp.chatbotUserDescription'),
|
||||
link: 'https://docs.dify.ai/guides/application-orchestrate/conversation-application?fallback=true',
|
||||
link: 'https://docs.dify.ai/guides/application-orchestrate#application_type',
|
||||
},
|
||||
'advanced-chat': {
|
||||
title: t('app.types.advanced'),
|
||||
|
||||
@@ -11,10 +11,12 @@ import { useLocalStorageState } from 'ahooks'
|
||||
import produce from 'immer'
|
||||
import type {
|
||||
ChatConfig,
|
||||
ChatItem,
|
||||
Feedback,
|
||||
} from '../types'
|
||||
import { CONVERSATION_ID_INFO } from '../constants'
|
||||
import { getPrevChatList, getProcessedInputsFromUrlParams } from '../utils'
|
||||
import { buildChatItemTree, getProcessedInputsFromUrlParams } from '../utils'
|
||||
import { getProcessedFilesFromResponse } from '../../file-uploader/utils'
|
||||
import {
|
||||
fetchAppInfo,
|
||||
fetchAppMeta,
|
||||
@@ -32,6 +34,33 @@ import { useToastContext } from '@/app/components/base/toast'
|
||||
import { changeLanguage } from '@/i18n/i18next-config'
|
||||
import { InputVarType } from '@/app/components/workflow/types'
|
||||
import { TransferMethod } from '@/types/app'
|
||||
import { addFileInfos, sortAgentSorts } from '@/app/components/tools/utils'
|
||||
|
||||
function getFormattedChatList(messages: any[]) {
|
||||
const newChatList: ChatItem[] = []
|
||||
messages.forEach((item) => {
|
||||
const questionFiles = item.message_files?.filter((file: any) => file.belongs_to === 'user') || []
|
||||
newChatList.push({
|
||||
id: `question-${item.id}`,
|
||||
content: item.query,
|
||||
isAnswer: false,
|
||||
message_files: getProcessedFilesFromResponse(questionFiles.map((item: any) => ({ ...item, related_id: item.id }))),
|
||||
parentMessageId: item.parent_message_id || undefined,
|
||||
})
|
||||
const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || []
|
||||
newChatList.push({
|
||||
id: item.id,
|
||||
content: item.answer,
|
||||
agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files),
|
||||
feedback: item.feedback,
|
||||
isAnswer: true,
|
||||
citation: item.retriever_resources,
|
||||
message_files: getProcessedFilesFromResponse(answerFiles.map((item: any) => ({ ...item, related_id: item.id }))),
|
||||
parentMessageId: `question-${item.id}`,
|
||||
})
|
||||
})
|
||||
return newChatList
|
||||
}
|
||||
|
||||
export const useEmbeddedChatbot = () => {
|
||||
const isInstalledApp = false
|
||||
@@ -77,7 +106,7 @@ export const useEmbeddedChatbot = () => {
|
||||
|
||||
const appPrevChatList = useMemo(
|
||||
() => (currentConversationId && appChatListData?.data.length)
|
||||
? getPrevChatList(appChatListData.data)
|
||||
? buildChatItemTree(getFormattedChatList(appChatListData.data))
|
||||
: [],
|
||||
[appChatListData, currentConversationId],
|
||||
)
|
||||
|
||||
@@ -10,6 +10,7 @@ import SyntaxHighlighter from 'react-syntax-highlighter'
|
||||
import { atelierHeathLight } from 'react-syntax-highlighter/dist/esm/styles/hljs'
|
||||
import { Component, memo, useMemo, useRef, useState } from 'react'
|
||||
import type { CodeComponent } from 'react-markdown/lib/ast-to-react'
|
||||
import SVGRenderer from './svg-gallery'
|
||||
import cn from '@/utils/classnames'
|
||||
import CopyBtn from '@/app/components/base/copy-btn'
|
||||
import SVGBtn from '@/app/components/base/svg'
|
||||
@@ -18,7 +19,7 @@ import ImageGallery from '@/app/components/base/image-gallery'
|
||||
import { useChatContext } from '@/app/components/base/chat/chat/context'
|
||||
import VideoGallery from '@/app/components/base/video-gallery'
|
||||
import AudioGallery from '@/app/components/base/audio-gallery'
|
||||
import SVGRenderer from '@/app/components/base/svg-gallery'
|
||||
// import SVGRenderer from '@/app/components/base/svg-gallery'
|
||||
import MarkdownButton from '@/app/components/base/markdown-blocks/button'
|
||||
import MarkdownForm from '@/app/components/base/markdown-blocks/form'
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
import DOMPurify from 'dompurify'
|
||||
import ImagePreview from '@/app/components/base/image-uploader/image-preview'
|
||||
|
||||
export const SVGRenderer = ({ content }: { content: string }) => {
|
||||
@@ -44,7 +45,7 @@ export const SVGRenderer = ({ content }: { content: string }) => {
|
||||
|
||||
svgRef.current.style.width = `${Math.min(originalWidth, 298)}px`
|
||||
|
||||
const rootElement = draw.svg(content)
|
||||
const rootElement = draw.svg(DOMPurify.sanitize(content))
|
||||
|
||||
rootElement.click(() => {
|
||||
setImagePreview(svgToDataURL(svgElement as Element))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dify-web",
|
||||
"version": "0.15.3",
|
||||
"version": "0.15.6-alpha.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=18.17.0"
|
||||
@@ -51,6 +51,7 @@
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"decimal.js": "^10.4.3",
|
||||
"dompurify": "^3.2.4",
|
||||
"echarts": "^5.5.1",
|
||||
"echarts-for-react": "^3.0.2",
|
||||
"elkjs": "^0.9.3",
|
||||
@@ -70,7 +71,7 @@
|
||||
"mermaid": "11.4.1",
|
||||
"mime": "^4.0.4",
|
||||
"negotiator": "^0.6.3",
|
||||
"next": "^14.2.10",
|
||||
"next": "^14.2.25",
|
||||
"pinyin-pro": "^3.23.0",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"qs": "^6.11.1",
|
||||
|
||||
115
web/yarn.lock
115
web/yarn.lock
@@ -2066,10 +2066,10 @@
|
||||
dependencies:
|
||||
"@monaco-editor/loader" "^1.4.0"
|
||||
|
||||
"@next/env@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.npmjs.org/@next/env/-/env-14.2.17.tgz"
|
||||
integrity sha512-MCgO7VHxXo8sYR/0z+sk9fGyJJU636JyRmkjc7ZJY8Hurl8df35qG5hoAh5KMs75FLjhlEo9bb2LGe89Y/scDA==
|
||||
"@next/env@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.25.tgz#936d10b967e103e49a4bcea1e97292d5605278dd"
|
||||
integrity sha512-JnzQ2cExDeG7FxJwqAksZ3aqVJrHjFwZQAEJ9gQZSoEhIow7SNoKZzju/AwQ+PLIR4NY8V0rhcVozx/2izDO0w==
|
||||
|
||||
"@next/eslint-plugin-next@14.0.4":
|
||||
version "14.0.4"
|
||||
@@ -2085,50 +2085,50 @@
|
||||
dependencies:
|
||||
source-map "^0.7.0"
|
||||
|
||||
"@next/swc-darwin-arm64@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.17.tgz"
|
||||
integrity sha512-WiOf5nElPknrhRMTipXYTJcUz7+8IAjOYw3vXzj3BYRcVY0hRHKWgTgQ5439EvzQyHEko77XK+yN9x9OJ0oOog==
|
||||
"@next/swc-darwin-arm64@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.25.tgz#7bcccfda0c0ff045c45fbe34c491b7368e373e3d"
|
||||
integrity sha512-09clWInF1YRd6le00vt750s3m7SEYNehz9C4PUcSu3bAdCTpjIV4aTYQZ25Ehrr83VR1rZeqtKUPWSI7GfuKZQ==
|
||||
|
||||
"@next/swc-darwin-x64@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.17.tgz#e29a17ef28d97c347c7d021f391e13b6c8e4c813"
|
||||
integrity sha512-29y425wYnL17cvtxrDQWC3CkXe/oRrdt8ie61S03VrpwpPRI0XsnTvtKO06XCisK4alaMnZlf8riwZIbJTaSHQ==
|
||||
"@next/swc-darwin-x64@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.25.tgz#b489e209d7b405260b73f69a38186ed150fb7a08"
|
||||
integrity sha512-V+iYM/QR+aYeJl3/FWWU/7Ix4b07ovsQ5IbkwgUK29pTHmq+5UxeDr7/dphvtXEq5pLB/PucfcBNh9KZ8vWbug==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.17.tgz#10e99c7aa60cc33f8b7633e045f74be9a43e7b0c"
|
||||
integrity sha512-SSHLZls3ZwNEHsc+d0ynKS+7Af0Nr8+KTUBAy9pm6xz9SHkJ/TeuEg6W3cbbcMSh6j4ITvrjv3Oi8n27VR+IPw==
|
||||
"@next/swc-linux-arm64-gnu@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.25.tgz#ba064fabfdce0190d9859493d8232fffa84ef2e2"
|
||||
integrity sha512-LFnV2899PJZAIEHQ4IMmZIgL0FBieh5keMnriMY1cK7ompR+JUd24xeTtKkcaw8QmxmEdhoE5Mu9dPSuDBgtTg==
|
||||
|
||||
"@next/swc-linux-arm64-musl@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.17.tgz#9a5bb809d3c6aef96c409959aedae28b4e5db53d"
|
||||
integrity sha512-VFge37us5LNPatB4F7iYeuGs9Dprqe4ZkW7lOEJM91r+Wf8EIdViWHLpIwfdDXinvCdLl6b4VyLpEBwpkctJHA==
|
||||
"@next/swc-linux-arm64-musl@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.25.tgz#bf0018267e4e0fbfa1524750321f8cae855144a3"
|
||||
integrity sha512-QC5y5PPTmtqFExcKWKYgUNkHeHE/z3lUsu83di488nyP0ZzQ3Yse2G6TCxz6nNsQwgAx1BehAJTZez+UQxzLfw==
|
||||
|
||||
"@next/swc-linux-x64-gnu@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.17.tgz#64e0ce01870e6dc45ae48f676d7cce82aedcdc62"
|
||||
integrity sha512-aaQlpxUVb9RZ41adlTYVQ3xvYEfBPUC8+6rDgmQ/0l7SvK8S1YNJzPmDPX6a4t0jLtIoNk7j+nroS/pB4nx7vQ==
|
||||
"@next/swc-linux-x64-gnu@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.25.tgz#64f5a6016a7148297ee80542e0fd788418a32472"
|
||||
integrity sha512-y6/ML4b9eQ2D/56wqatTJN5/JR8/xdObU2Fb1RBidnrr450HLCKr6IJZbPqbv7NXmje61UyxjF5kvSajvjye5w==
|
||||
|
||||
"@next/swc-linux-x64-musl@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.17.tgz#93114164b6ccfc533908193ab9065f0c3970abc3"
|
||||
integrity sha512-HSyEiFaEY3ay5iATDqEup5WAfrhMATNJm8dYx3ZxL+e9eKv10XKZCwtZByDoLST7CyBmyDz+OFJL1wigyXeaoA==
|
||||
"@next/swc-linux-x64-musl@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.25.tgz#58dc636d7c55828478159546f7b95ab1e902301c"
|
||||
integrity sha512-sPX0TSXHGUOZFvv96GoBXpB3w4emMqKeMgemrSxI7A6l55VBJp/RKYLwZIB9JxSqYPApqiREaIIap+wWq0RU8w==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.17.tgz#4b99dea02178c112e5c33c742f9ff2a49b3b2939"
|
||||
integrity sha512-h5qM9Btqv87eYH8ArrnLoAHLyi79oPTP2vlGNSg4CDvUiXgi7l0+5KuEGp5pJoMhjuv9ChRdm7mRlUUACeBt4w==
|
||||
"@next/swc-win32-arm64-msvc@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.25.tgz#93562d447c799bded1e89c1a62d5195a2a8c6c0d"
|
||||
integrity sha512-ReO9S5hkA1DU2cFCsGoOEp7WJkhFzNbU/3VUF6XxNGUCQChyug6hZdYL/istQgfT/GWE6PNIg9cm784OI4ddxQ==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.17.tgz#f1c23955405a259b6d45c65f918575b01bcf0106"
|
||||
integrity sha512-BD/G++GKSLexQjdyoEUgyo5nClU7er5rK0sE+HlEqnldJSm96CIr/+YOTT063LVTT/dUOeQsNgp5DXr86/K7/A==
|
||||
"@next/swc-win32-ia32-msvc@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.25.tgz#ad85a33466be1f41d083211ea21adc0d2c6e6554"
|
||||
integrity sha512-DZ/gc0o9neuCDyD5IumyTGHVun2dCox5TfPQI/BJTYwpSNYM3CZDI4i6TOdjeq1JMo+Ug4kPSMuZdwsycwFbAw==
|
||||
|
||||
"@next/swc-win32-x64-msvc@14.2.17":
|
||||
version "14.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.17.tgz#44f5a4fcd8df1396a8d4326510ca2d92fb809cb3"
|
||||
integrity sha512-vkQfN1+4V4KqDibkW2q0sJ6CxQuXq5l2ma3z0BRcfIqkAMZiiW67T9yCpwqJKP68QghBtPEFjPAlaqe38O6frw==
|
||||
"@next/swc-win32-x64-msvc@14.2.25":
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.25.tgz#3969c66609e683ec63a6a9f320a855f7be686a08"
|
||||
integrity sha512-KSznmS6eFjQ9RJ1nEc66kJvtGIL1iZMYmGEXsZPh2YtnLtqrgdVvKXJY2ScjjoFnG6nGLyPFR0UiEvDwVah4Tw==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
@@ -5864,6 +5864,13 @@ dompurify@^3.2.1:
|
||||
optionalDependencies:
|
||||
"@types/trusted-types" "^2.0.7"
|
||||
|
||||
dompurify@^3.2.4:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.4.tgz#af5a5a11407524431456cf18836c55d13441cd8e"
|
||||
integrity sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==
|
||||
optionalDependencies:
|
||||
"@types/trusted-types" "^2.0.7"
|
||||
|
||||
domutils@^2.5.2, domutils@^2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz"
|
||||
@@ -9911,12 +9918,12 @@ neo-async@^2.6.2:
|
||||
resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz"
|
||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||
|
||||
next@^14.2.10:
|
||||
version "14.2.17"
|
||||
resolved "https://registry.npmjs.org/next/-/next-14.2.17.tgz"
|
||||
integrity sha512-hNo/Zy701DDO3nzKkPmsLRlDfNCtb1OJxFUvjGEl04u7SFa3zwC6hqsOUzMajcaEOEV8ey1GjvByvrg0Qr5AiQ==
|
||||
next@^14.2.25:
|
||||
version "14.2.25"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-14.2.25.tgz#0657551fde6a97f697cf9870e9ccbdaa465c6008"
|
||||
integrity sha512-N5M7xMc4wSb4IkPvEV5X2BRRXUmhVHNyaXwEM86+voXthSZz8ZiRyQW4p9mwAoAPIm6OzuVZtn7idgEJeAJN3Q==
|
||||
dependencies:
|
||||
"@next/env" "14.2.17"
|
||||
"@next/env" "14.2.25"
|
||||
"@swc/helpers" "0.5.5"
|
||||
busboy "1.6.0"
|
||||
caniuse-lite "^1.0.30001579"
|
||||
@@ -9924,15 +9931,15 @@ next@^14.2.10:
|
||||
postcss "8.4.31"
|
||||
styled-jsx "5.1.1"
|
||||
optionalDependencies:
|
||||
"@next/swc-darwin-arm64" "14.2.17"
|
||||
"@next/swc-darwin-x64" "14.2.17"
|
||||
"@next/swc-linux-arm64-gnu" "14.2.17"
|
||||
"@next/swc-linux-arm64-musl" "14.2.17"
|
||||
"@next/swc-linux-x64-gnu" "14.2.17"
|
||||
"@next/swc-linux-x64-musl" "14.2.17"
|
||||
"@next/swc-win32-arm64-msvc" "14.2.17"
|
||||
"@next/swc-win32-ia32-msvc" "14.2.17"
|
||||
"@next/swc-win32-x64-msvc" "14.2.17"
|
||||
"@next/swc-darwin-arm64" "14.2.25"
|
||||
"@next/swc-darwin-x64" "14.2.25"
|
||||
"@next/swc-linux-arm64-gnu" "14.2.25"
|
||||
"@next/swc-linux-arm64-musl" "14.2.25"
|
||||
"@next/swc-linux-x64-gnu" "14.2.25"
|
||||
"@next/swc-linux-x64-musl" "14.2.25"
|
||||
"@next/swc-win32-arm64-msvc" "14.2.25"
|
||||
"@next/swc-win32-ia32-msvc" "14.2.25"
|
||||
"@next/swc-win32-x64-msvc" "14.2.25"
|
||||
|
||||
no-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
|
||||
Reference in New Issue
Block a user