feat: 新增sandbox-full支持

This commit is contained in:
FamousMai
2025-03-28 15:18:33 +08:00
parent ca19bd31d4
commit b5aa970766
869 changed files with 99420 additions and 6830 deletions
+2
View File
@@ -68,6 +68,7 @@ from .provider import (
TenantDefaultModel,
TenantPreferredModelProvider,
)
from .system_extend import SystemIntegrationExtend # Extend System Integration
from .source import DataSourceApiKeyAuthBinding, DataSourceOauthBinding
from .task import CeleryTask, CeleryTaskSet
from .tools import (
@@ -184,4 +185,5 @@ __all__ = [
"WorkflowToolProvider",
"WorkflowType",
"db",
"SystemIntegrationExtend", # Extend System Integration
]
+34
View File
@@ -0,0 +1,34 @@
from extensions.ext_database import db
from .types import StringUUID
class AccountMoneyExtend(db.Model):
__tablename__ = "account_money_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="account_money_pkey"),
db.Index("idx_account_money_account_id", "account_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
account_id = db.Column(StringUUID, nullable=False)
total_quota = db.Column(db.Numeric(16, 7))
used_quota = db.Column(db.Numeric(16, 7))
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
class AccountLayoverRecordExtend(db.Model):
__tablename__ = "account_layover_record_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="account_layover_record_extend_pkey"),
db.Index("idx_account_layover_record_account_id", "account_id"),
db.Index("idx_account_layover_record_forwarding_id", "forwarding_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
account_id = db.Column(StringUUID, nullable=False)
forwarding_id = db.Column(StringUUID, nullable=False)
money = db.Column(db.Numeric(16, 7))
info = db.Column(db.JSON, default={})
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
@@ -0,0 +1,19 @@
from extensions.ext_database import db
from .types import StringUUID
class AccountMoneyMonthlyStatExtend(db.Model):
__tablename__ = "account_money_monthly_stat_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="account_money_monthly_stat_pkey"),
db.Index("idx_account_money_monthly_stat_account_id", "account_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
account_id = db.Column(StringUUID, nullable=False)
total_quota = db.Column(db.Numeric(16, 7))
used_quota = db.Column(db.Numeric(16, 7))
stat_at = db.Column(db.DateTime, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
+82
View File
@@ -0,0 +1,82 @@
from extensions.ext_database import db
from .types import StringUUID
class ApiTokenMoneyExtend(db.Model):
__tablename__ = "api_token_money_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="api_token_money_extend_pkey"),
db.Index("api_tokens_money_app_token_id_idx", "app_token_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
app_token_id = db.Column(StringUUID, nullable=True) # 密钥ID
accumulated_quota = db.Column(db.Numeric(16, 7)) # 已使用额度(累计不归零)
day_used_quota = db.Column(db.Numeric(16, 7)) # 当天使用额度(定时脚本每日更新)
month_used_quota = db.Column(db.Numeric(16, 7)) # 当月使用额度(定时脚本每月更新)
day_limit_quota = db.Column(db.Numeric(16, 7)) # 每天使用额度限制(创建密钥时设置)
month_limit_quota = db.Column(db.Numeric(16, 7)) # 每月使用额度限制(创建密钥时设置)
description = db.Column(db.String(50)) # 密钥描述
is_deleted = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
# 日快照统计表
class ApiTokenMoneyDailyStatExtend(db.Model):
__tablename__ = "api_token_money_daily_stat_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="api_token_money_daily_stat_pkey"),
db.Index("idx_api_token_money_daily_stat_app_token_id", "app_token_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
app_token_id = db.Column(StringUUID, nullable=False)
accumulated_quota = db.Column(db.Numeric(16, 7)) # 已使用额度(累计不归零)
day_used_quota = db.Column(db.Numeric(16, 7)) # 当天使用额度(定时脚本每日更新)
day_limit_quota = db.Column(db.Numeric(16, 7)) # 每天使用额度限制(创建密钥时设置)
stat_at = db.Column(db.DateTime, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
# 月快照统计表
class ApiTokenMoneyMonthlyStatExtend(db.Model):
__tablename__ = "api_token_money_monthly_stat_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="api_token_money_monthly_stat_pkey"),
db.Index("idx_api_token_money_monthly_stat_app_token_id", "app_token_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
app_token_id = db.Column(StringUUID, nullable=False)
accumulated_quota = db.Column(db.Numeric(16, 7)) # 已使用额度(累计不归零)
month_used_quota = db.Column(db.Numeric(16, 7)) # 当月使用额度(定时脚本每月更新)
month_limit_quota = db.Column(db.Numeric(16, 7)) # 每月使用额度限制(创建密钥时设置)
stat_at = db.Column(db.DateTime, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
# 密钥 - 对话消息关联表
class ApiTokenMessageJoinsExtend(db.Model):
__tablename__ = "api_token_message_joins_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="api_token_message_joins_extend_pkey"),
db.Index("api_token_message_joins_extend_app_token_id_idx", "app_token_id"),
db.Index("api_token_message_joins_extend_record_id_idx", "record_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
app_token_id = db.Column(StringUUID, nullable=True) # 密钥ID
record_id = db.Column(StringUUID, nullable=True) # 关联记录ID
app_mode = db.Column(db.String(255), nullable=True) # 应用类型
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
def add_app_token_record_id(self):
db.session.add(
ApiTokenMessageJoinsExtend(app_token_id=self.app_token_id, record_id=self.record_id, app_mode=self.app_mode)
)
db.session.commit()
+54 -2
View File
@@ -219,6 +219,18 @@ class App(db.Model): # type: ignore[name-defined]
return tags or []
class AppStatisticsExtend(db.Model):
__tablename__ = "app_statistics_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="app_statistics_extend_pkey"),
db.Index("app_statistics_extend_app_id_idx", "app_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
app_id = db.Column(StringUUID, nullable=False)
number = db.Column(db.Integer, nullable=False, default=0)
class AppModelConfig(db.Model): # type: ignore[name-defined]
__tablename__ = "app_model_configs"
__table_args__ = (db.PrimaryKeyConstraint("id", name="app_model_config_pkey"), db.Index("app_app_id_idx", "app_id"))
@@ -466,6 +478,32 @@ class AppModelConfig(db.Model): # type: ignore[name-defined]
return new_app_model_config
class RecommendedCategoryExtend(db.Model):
__tablename__ = "recommended_category_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="category_extend_id_pkey"),
db.Index("idx_extend_tag_bind_tag_id", "tag_id"),
db.Index("idx_extend_table", "table"),
)
id = db.Column(StringUUID, primary_key=True, server_default=db.text("uuid_generate_v4()"))
table = db.Column(db.String(255), nullable=False)
tag_id = db.Column(StringUUID, nullable=True)
class RecommendedAppsCategoryJoinExtend(db.Model):
__tablename__ = "recommended_apps_category_join_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="recommended_apps_category_id_pkey"),
db.Index("idx_recommended_id", "recommended_id"),
db.Index("idx_recommended_category_id", "category_id"),
)
id = db.Column(StringUUID, primary_key=True, server_default=db.text("uuid_generate_v4()"))
recommended_id = db.Column(StringUUID, nullable=False)
category_id = db.Column(StringUUID, nullable=False)
class RecommendedApp(db.Model): # type: ignore[name-defined]
__tablename__ = "recommended_apps"
__table_args__ = (
@@ -739,9 +777,23 @@ class Conversation(db.Model): # type: ignore[name-defined]
def from_end_user_session_id(self):
if self.from_end_user_id:
end_user = db.session.query(EndUser).filter(EndUser.id == self.from_end_user_id).first()
if end_user:
# Extend: start In the Log and Annotation User columns, the end_user displayed is changed to the
# associated username
if end_user is not None and (
end_user.external_user_id is None
or (end_user.external_user_id is not None and len(end_user.external_user_id) == 0)
):
return end_user.session_id
elif end_user is not None:
user: Account = db.session.query(Account).filter(Account.id == end_user.external_user_id).first()
if user:
return user.name
elif self.from_account_id:
user: Account = db.session.query(Account).filter(Account.id == self.from_account_id).first()
if user:
return user.name
# Extend: stop In the Log and Annotation User columns, the end_user displayed is changed to the
# associated username
return None
@property
+19
View File
@@ -0,0 +1,19 @@
from extensions.ext_database import db
from .types import StringUUID
class EndUserAccountJoinsExtend(db.Model):
__tablename__ = "end_user_account_joins_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="end_user_account_joins_pkey"),
db.Index("end_user_account_joins_account_id_idx", "account_id"),
db.Index("end_user_account_joins_end_user_id_app_id_idx", "end_user_id", "app_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
end_user_id = db.Column(StringUUID, nullable=False)
account_id = db.Column(StringUUID, nullable=False)
app_id = db.Column(StringUUID, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
+51
View File
@@ -0,0 +1,51 @@
from Crypto.Util.Padding import unpad
from Crypto.Cipher import Blowfish
from configs import dify_config
from .engine import db
import base64
class SystemIntegrationClassify:
SYSTEM_INTEGRATION_DINGTALK = 1 # 钉钉
SYSTEM_INTEGRATION_WEIXIN = 2 # 微信
SYSTEM_INTEGRATION_FEI_SU = 3 # 飞书
class SystemIntegrationExtend(db.Model):
__tablename__ = "system_integration_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="system_integration_joins_pkey"),
db.Index("system_integration_joins_classify_idx", "classify"),
)
id = db.Column(db.BigInteger, db.Sequence("system_integration_id_sequence"), primary_key=True, autoincrement=True)
classify = db.Column(db.Integer, nullable=False, server_default=db.text("1"))
status = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
corp_id = db.Column(db.String(120), nullable=True)
agent_id = db.Column(db.String(120), nullable=True)
app_key = db.Column(db.String(120), nullable=True)
app_secret = db.Column(db.Text, nullable=True)
def decodeSecret(self):
if len(self.app_secret) == 0:
return ""
# Decode the base64 encoded text
ciphertext = base64.b64decode(self.app_secret)
# Ensure the text length is sufficient
if len(ciphertext) < Blowfish.block_size:
raise ValueError("Invalid ciphertext")
# Extract the initialization vector (IV) from the beginning of the ciphertext
iv = ciphertext[:Blowfish.block_size]
ciphertext = ciphertext[Blowfish.block_size:]
# Create the cipher object and decrypt the plaintext
cipher = Blowfish.new(dify_config.SECRET_KEY.encode('utf-8'), Blowfish.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)
# Unpad the plaintext using PKCS7 unpadding
try:
plaintext = unpad(plaintext, Blowfish.block_size)
except ValueError as e:
raise ValueError("Invalid padding") from e
return plaintext.decode('utf-8')
+50
View File
@@ -0,0 +1,50 @@
from extensions.ext_database import db
from .types import StringUUID
class TenantModelSyncExtend(db.Model):
"""
模型-工作区同步关联
"""
__tablename__ = "tenant_model_sync_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="tenant_model_sync_extend_pkey"),
db.Index("tenant_model_sync_extend_tenant_idx", "tenant_id"),
db.Index("tenant_model_sync_extend_model_idx", "model_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
tenant_id = db.Column(StringUUID, nullable=False)
model_id = db.Column(StringUUID, nullable=False)
origin_model_id = db.Column(db.String(255), nullable=False)
is_all = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
def __repr__(self):
return f"<tenant_model_sync(id={self.id}, tenant_id={self.tenant_id}, model_id='{self.model_id}', is_all='{self.is_all}')>"
class ModelSyncConfigExtend(db.Model):
"""
模型-同步配置表
"""
__tablename__ = "model_sync_config_extend"
__table_args__ = (
db.PrimaryKeyConstraint("id", name="model_sync_config_extend_pkey"),
db.UniqueConstraint("model_id", name="unique_model_id"),
)
id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
model_id = db.Column(StringUUID, nullable=True)
is_all = db.Column(db.Boolean, nullable=True, server_default=db.text("true"))
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
def __repr__(self):
return f"<model_sync_config_extend(id={self.id}, model_id='{self.model_id}', is_all='{self.is_all}')>"
+44 -3
View File
@@ -771,10 +771,51 @@ class WorkflowAppLog(db.Model): # type: ignore[name-defined]
@property
def created_by_end_user(self):
from models.model import EndUser
from models.model_extend import EndUserAccountJoinsExtend
# Extend: start /apps/<uuid:app_id>/workflow-app-logs update end_user to account
created_by_role = CreatedByRole(self.created_by_role)
return db.session.get(EndUser, self.created_by) if created_by_role == CreatedByRole.END_USER else None
if created_by_role == CreatedByRole.END_USER:
end_user = db.session.query(EndUserAccountJoinsExtend).filter(
EndUserAccountJoinsExtend.end_user_id == self.created_by).first()
# associated username
if end_user is not None and (
end_user.account_id is None
or (end_user.account_id is not None and len(end_user.account_id) == 0)
):
return self.created_by
elif end_user is not None:
user: Account = db.session.query(Account).filter(Account.id == end_user.account_id).first()
if user:
return {
"id": user.id,
"type": user.status,
"is_anonymous": "true",
"session_id": user.name,
}
else:
from models.model import EndUser
end_user = db.session.query(EndUser).filter(EndUser.id == self.created_by).first()
if end_user is not None and len(end_user.external_user_id) > 0:
user: Account = db.session.query(Account).filter(Account.id == end_user.external_user_id).first()
if user:
return {
"id": user.id,
"type": user.status,
"is_anonymous": "true",
"session_id": user.name,
}
return end_user
elif len(self.created_by) > 0:
user: Account = db.session.query(Account).filter(Account.id == self.created_by).first()
if user:
return {
"id": user.id,
"type": user.status,
"is_anonymous": "true",
"session_id": user.name,
}
return None
# Extend: stop /apps/<uuid:app_id>/workflow-app-logs update end_user to account
class ConversationVariable(db.Model): # type: ignore[name-defined]