Skip to content

Commit 9556f73

Browse files
Merge branch 'v2' into pr@v2@fix_resource_authorization_modify
2 parents 0a89927 + 63abffe commit 9556f73

File tree

12 files changed

+100
-61
lines changed

12 files changed

+100
-61
lines changed

apps/models_provider/serializers/model_serializer.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,15 @@ def model_to_dict(model: Model):
107107
class Operate(serializers.Serializer):
108108
id = serializers.UUIDField(required=True, label=_("model id"))
109109
user_id = serializers.UUIDField(required=False, label=_("user id"))
110+
workspace_id = serializers.CharField(required=False, label=_("workspace id"))
110111

111112
def is_valid(self, *, raise_exception=False):
112113
super().is_valid(raise_exception=True)
113-
model = QuerySet(Model).filter(
114-
id=self.data.get("id")
115-
).first()
114+
workspace_id = self.data.get("workspace_id")
115+
model_query = QuerySet(Model).filter(id=self.data.get("id"))
116+
if workspace_id is not None:
117+
model_query = model_query.filter(workspace_id=workspace_id)
118+
model = model_query.first()
116119
if model is None:
117120
raise AppApiException(500, _('Model does not exist'))
118121
if model.workspace_id == 'None':
@@ -122,21 +125,23 @@ def one(self, with_valid=False):
122125
if with_valid:
123126
super().is_valid(raise_exception=True)
124127
model = QuerySet(Model).get(
125-
id=self.data.get('id')
128+
id=self.data.get('id'), workspace_id=self.data.get('workspace_id')
126129
)
127130
return ModelSerializer.model_to_dict(model)
128131

129132
def one_meta(self, with_valid=False):
130133
model = None
131134
if with_valid:
132135
super().is_valid(raise_exception=True)
133-
model = QuerySet(Model).filter(id=self.data.get("id")).first()
136+
model = QuerySet(Model).filter(id=self.data.get("id"),
137+
workspace_id=self.data.get('workspace_id')).first()
134138
if model is None:
135139
raise AppApiException(500, _('Model does not exist'))
136140
return {'id': str(model.id), 'provider': model.provider, 'name': model.name, 'model_type': model.model_type,
137141
'model_name': model.model_name,
138142
'status': model.status,
139-
'meta': model.meta
143+
'meta': model.meta,
144+
'workspace_id': model.workspace_id,
140145
}
141146

142147
def pause_download(self, with_valid=True):

apps/models_provider/views/model.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,9 @@ class Operate(APIView):
121121
)
122122
def put(self, request: Request, workspace_id, model_id: str):
123123
return result.success(
124-
ModelSerializer.Operate(data={'id': model_id, 'user_id': request.user.id}).edit(request.data,
125-
str(request.user.id)))
124+
ModelSerializer.Operate(
125+
data={'id': model_id, 'user_id': request.user.id, 'workspace_id': workspace_id}).edit(request.data,
126+
str(request.user.id)))
126127

127128
@extend_schema(methods=['DELETE'],
128129
summary=_('Delete model'),
@@ -138,7 +139,8 @@ def put(self, request: Request, workspace_id, model_id: str):
138139
)
139140
def delete(self, request: Request, workspace_id: str, model_id: str):
140141
return result.success(
141-
ModelSerializer.Operate(data={'id': model_id, 'user_id': request.user.id}).delete())
142+
ModelSerializer.Operate(
143+
data={'id': model_id, 'user_id': request.user.id, 'workspace_id': workspace_id}).delete())
142144

143145
@extend_schema(methods=['GET'],
144146
summary=_('Query model details'),
@@ -151,7 +153,9 @@ def delete(self, request: Request, workspace_id: str, model_id: str):
151153
RoleConstants.WORKSPACE_MANAGE.get_workspace_role())
152154
def get(self, request: Request, workspace_id: str, model_id: str):
153155
return result.success(
154-
ModelSerializer.Operate(data={'id': model_id, 'user_id': request.user.id}).one(with_valid=True))
156+
ModelSerializer.Operate(
157+
data={'id': model_id, 'user_id': request.user.id, 'workspace_id': workspace_id}).one(
158+
with_valid=True))
155159

156160
class ModelParamsForm(APIView):
157161
authentication_classes = [TokenAuth]
@@ -203,7 +207,7 @@ class ModelMeta(APIView):
203207
RoleConstants.WORKSPACE_MANAGE.get_workspace_role())
204208
def get(self, request: Request, workspace_id: str, model_id: str):
205209
return result.success(
206-
ModelSerializer.Operate(data={'id': model_id}).one_meta(with_valid=True))
210+
ModelSerializer.Operate(data={'id': model_id, 'workspace_id': workspace_id}).one_meta(with_valid=True))
207211

208212
class PauseDownload(APIView):
209213
authentication_classes = [TokenAuth]
@@ -220,7 +224,7 @@ class PauseDownload(APIView):
220224
RoleConstants.WORKSPACE_MANAGE.get_workspace_role())
221225
def put(self, request: Request, workspace_id: str, model_id: str):
222226
return result.success(
223-
ModelSerializer.Operate(data={'id': model_id}).pause_download())
227+
ModelSerializer.Operate(data={'id': model_id, 'workspace_id': workspace_id}).pause_download())
224228

225229

226230
class SharedModel(APIView):

apps/tools/migrations/0001_initial.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
# Generated by Django 5.2 on 2025-05-15 04:04
2-
import os
32

43
import django.db.models.deletion
54
import mptt.fields
65
import uuid_utils.compat
76
from django.db import migrations, models
87

9-
from common.utils.common import get_file_content
10-
from maxkb.conf import PROJECT_DIR
8+
119
from tools.models import ToolFolder
1210

1311

@@ -71,5 +69,4 @@ class Migration(migrations.Migration):
7169
'db_table': 'tool',
7270
},
7371
),
74-
# migrations.RunSQL(get_file_content(os.path.join(PROJECT_DIR, "apps", "tools", 'migrations', 'internal_tool.sql')))
7572
]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Generated by Django 5.2.3 on 2025-06-20 03:43
2+
import os
3+
4+
from django.db import migrations, models
5+
from common.utils.common import get_file_content
6+
from maxkb.conf import PROJECT_DIR
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('tools', '0001_initial'),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name='tool',
17+
name='label',
18+
field=models.CharField(max_length=128, null=True, verbose_name='标签'),
19+
),
20+
migrations.RunSQL(get_file_content(os.path.join(PROJECT_DIR, "apps", "tools", 'migrations', 'internal_tool.sql')))
21+
]

apps/tools/migrations/internal_tool.sql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
INSERT INTO tool (create_time, update_time, id, name, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-03-10 06:20:35.945414 +00:00', '2025-03-10 09:19:23.608026 +00:00', 'c75cb48e-fd77-11ef-84d2-5618c4394482', '博查搜索', '从博查搜索任何信息和网页URL', e'def bocha_search(query, apikey):
1+
INSERT INTO tool (create_time, update_time, id, name, label, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-03-10 06:20:35.945414 +00:00', '2025-03-10 09:19:23.608026 +00:00', 'c75cb48e-fd77-11ef-84d2-5618c4394482', '博查搜索', 'Web Search', '从博查搜索任何信息和网页URL', e'def bocha_search(query, apikey):
22
import requests
33
import json
44
url = "https://api.bochaai.com/v1/web-search"
@@ -19,7 +19,7 @@ INSERT INTO tool (create_time, update_time, id, name, "desc", code, input_field_
1919
else:
2020
raise Exception(f"API请求失败: {response.status_code}, 错误信息: {response.text}")
2121
return (response.text)', '[{"name": "query", "type": "string", "source": "reference", "is_required": true}]', '[{"attrs": {"type": "password", "maxlength": 200, "minlength": 1, "show-password": true, "show-word-limit": true}, "field": "apikey", "label": "API Key", "required": true, "input_type": "PasswordInput", "props_info": {"rules": [{"message": "API Key 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "API Key 长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}]', '/ui/fx/bochaai/icon.png', true, 'INTERNAL', 'INTERNAL', null, 'None', '', 'f0dd8f71-e4ee-11ee-8c84-a8a1595801ab', 'default');
22-
INSERT INTO tool (create_time, update_time, id, name, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-02-26 03:36:48.187286 +00:00', '2025-03-11 07:23:46.123972 +00:00', 'e89ad2ae-f3f2-11ef-ad09-0242ac110002', 'Google Search', 'Google Web Search', e'def google_search(query, apikey, cx):
22+
INSERT INTO tool (create_time, update_time, id, name, label, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-02-26 03:36:48.187286 +00:00', '2025-03-11 07:23:46.123972 +00:00', 'e89ad2ae-f3f2-11ef-ad09-0242ac110002', 'Google Search','Web Search', 'Google Web Search', e'def google_search(query, apikey, cx):
2323
import requests
2424
import json
2525
url = "https://customsearch.googleapis.com/customsearch/v1"
@@ -36,7 +36,7 @@ INSERT INTO tool (create_time, update_time, id, name, "desc", code, input_field_
3636
else:
3737
raise Exception(f"API请求失败: {response.status_code}, 错误信息: {response.text}")
3838
return (response.text)', '[{"name": "query", "type": "string", "source": "reference", "is_required": true}]', '[{"attrs": {"type": "password", "maxlength": 200, "minlength": 1, "show-password": true, "show-word-limit": true}, "field": "apikey", "label": "API Key", "required": true, "input_type": "PasswordInput", "props_info": {"rules": [{"message": "API Key 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "API Key 长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}, {"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "cx", "label": "cx", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "cx 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "cx长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}]', '/ui/fx/google_search/icon.png', true, 'INTERNAL', 'INTERNAL', null, 'None', '', 'f0dd8f71-e4ee-11ee-8c84-a8a1595801ab', 'default');
39-
INSERT INTO tool (create_time, update_time, id, name, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-02-25 07:44:40.141515 +00:00', '2025-03-11 06:33:53.248495 +00:00', '5e912f00-f34c-11ef-8a9c-5618c4394482', 'LangSearch', e'A Web Search tool supporting natural language search
39+
INSERT INTO tool (create_time, update_time, id, name, label, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-02-25 07:44:40.141515 +00:00', '2025-03-11 06:33:53.248495 +00:00', '5e912f00-f34c-11ef-8a9c-5618c4394482', 'LangSearch','Web Search', e'A Web Search tool supporting natural language search
4040
', e'
4141
def langsearch(query, apikey):
4242
import json
@@ -61,7 +61,7 @@ def langsearch(query, apikey):
6161
else:
6262
raise Exception(f"API请求失败: {response.status_code}, 错误信息: {response.text}")
6363
return (response.text)', '[{"name": "query", "type": "string", "source": "reference", "is_required": true}]', '[{"attrs": {"type": "password", "maxlength": 200, "minlength": 1, "show-password": true, "show-word-limit": true}, "field": "apikey", "label": "API Key", "required": true, "input_type": "PasswordInput", "props_info": {"rules": [{"message": "API Key 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "API Key 长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}]', '/ui/fx/langsearch/icon.png', true, 'INTERNAL', 'INTERNAL', null, 'None', '', 'f0dd8f71-e4ee-11ee-8c84-a8a1595801ab', 'default');
64-
INSERT INTO tool (create_time, update_time, id, name, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-03-17 08:16:32.626245 +00:00', '2025-03-17 08:16:32.626308 +00:00', '22c21b76-0308-11f0-9694-5618c4394482', 'MySQL 查询', '一个连接MySQL数据库执行SQL查询的工具', e'
64+
INSERT INTO tool (create_time, update_time, id, name, label, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-03-17 08:16:32.626245 +00:00', '2025-03-17 08:16:32.626308 +00:00', '22c21b76-0308-11f0-9694-5618c4394482', 'MySQL 查询','Database Search', '一个连接MySQL数据库执行SQL查询的工具', e'
6565
def query_mysql(host,port, user, password, database, sql):
6666
import pymysql
6767
import json
@@ -103,7 +103,7 @@ def query_mysql(host,port, user, password, database, sql):
103103
except Exception as e:
104104
print(f"Error while connecting to MySQL: {e}")
105105
raise e', '[{"name": "sql", "type": "string", "source": "reference", "is_required": true}]', '[{"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "host", "label": "host", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "host 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "host长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}, {"attrs": {"maxlength": 20, "minlength": 1, "show-word-limit": true}, "field": "port", "label": "port", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "port 为必填属性", "required": true}, {"max": 20, "min": 1, "message": "port长度在 1 到 20 个字符", "trigger": "blur"}]}, "default_value": "3306", "show_default_value": false}, {"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "user", "label": "user", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "user 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "user长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "root", "show_default_value": false}, {"attrs": {"type": "password", "maxlength": 200, "minlength": 1, "show-password": true, "show-word-limit": true}, "field": "password", "label": "password", "required": true, "input_type": "PasswordInput", "props_info": {"rules": [{"message": "password 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "password长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}, {"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "database", "label": "database", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "database 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "database长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}]', '/ui/fx/mysql/icon.png', true, 'INTERNAL', 'INTERNAL', null, 'None', null, 'f0dd8f71-e4ee-11ee-8c84-a8a1595801ab', 'default');
106-
INSERT INTO tool (create_time, update_time, id, name, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-03-17 07:37:54.620836 +00:00', '2025-03-17 07:37:54.620887 +00:00', 'bd1e8b88-0302-11f0-87bb-5618c4394482', 'PostgreSQL 查询', '一个连接PostgreSQL数据库执行SQL查询的工具', e'
106+
INSERT INTO tool (create_time, update_time, id, name, label, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-03-17 07:37:54.620836 +00:00', '2025-03-17 07:37:54.620887 +00:00', 'bd1e8b88-0302-11f0-87bb-5618c4394482', 'PostgreSQL 查询','Database Search', '一个连接PostgreSQL数据库执行SQL查询的工具', e'
107107
def queryPgSQL(database, user, password, host, port, query):
108108
import psycopg2
109109
import json

apps/tools/models/tool.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class Tool(AppModelMixin):
5151
folder = models.ForeignKey(ToolFolder, on_delete=models.DO_NOTHING, verbose_name="文件夹id", default='default')
5252
workspace_id = models.CharField(max_length=64, verbose_name="工作空间id", default="default", db_index=True)
5353
init_params = models.CharField(max_length=102400, verbose_name="初始化参数", null=True)
54+
label = models.CharField(max_length=128, verbose_name="标签", null=True)
5455

5556
class Meta:
5657
db_table = "tool"

apps/tools/serializers/tool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class ToolModelSerializer(serializers.ModelSerializer):
102102
class Meta:
103103
model = Tool
104104
fields = ['id', 'name', 'icon', 'desc', 'code', 'input_field_list', 'init_field_list', 'init_params',
105-
'scope', 'is_active', 'user_id', 'template_id', 'workspace_id', 'folder_id', 'tool_type',
105+
'scope', 'is_active', 'user_id', 'template_id', 'workspace_id', 'folder_id', 'tool_type', 'label',
106106
'create_time', 'update_time']
107107

108108

apps/tools/sql/list_tool.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ from (select tool."id"::text,
1010
tool."user_id",
1111
"user".nick_name as "nick_name",
1212
tool."icon",
13+
tool.label,
1314
tool."template_id"::text,
1415
tool."create_time",
1516
tool."update_time",
@@ -30,6 +31,7 @@ from (select tool."id"::text,
3031
tool_folder."user_id",
3132
"user".nick_name as "nick_name",
3233
'' as "icon",
34+
'' as label,
3335
'' as "template_id",
3436
tool_folder."create_time",
3537
tool_folder."update_time",

pyproject.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ package-mode = false
1010
python = "^3.11"
1111
django = "5.2.3"
1212
drf-spectacular = { extras = ["sidecar"], version = "0.28.0" }
13-
django-redis = "5.4.0"
13+
django-redis = "6.0.0"
1414
django-db-connection-pool = "1.2.6"
1515
django-mptt = "0.17.0"
1616
psycopg = { extras = ["binary"], version = "3.2.9" }
1717
python-dotenv = "1.1.0"
1818
uuid-utils = "0.11.0"
1919
diskcache2 = "1.0.0"
2020
captcha = "0.7.1"
21-
langchain-openai = "0.3.23"
21+
langchain-openai = "0.3.24"
2222
langchain-anthropic = "0.3.15"
2323
langchain-community = "0.3.25"
2424
langchain-deepseek = "0.1.3"
@@ -30,11 +30,11 @@ langgraph = "0.4.8"
3030
torch = "2.7.1"
3131
qianfan = "0.4.12.3"
3232
zhipuai = "2.1.5.20250611"
33-
boto3 = "1.38.36"
34-
tencentcloud-sdk-python = "3.0.1402"
33+
boto3 = "1.38.39"
34+
tencentcloud-sdk-python = "3.0.1405"
3535
xinference-client = "1.7.0.post1"
3636
anthropic = "0.54.0"
37-
dashscope = "1.23.4"
37+
dashscope = "1.23.5"
3838
pylint = "3.3.7"
3939
pydub = "0.25.1"
4040
cffi = "1.17.1"
@@ -49,15 +49,15 @@ beautifulsoup4 = "4.13.4"
4949
html2text = "2025.4.15"
5050
jieba = "0.42.1"
5151
openpyxl = "3.1.5"
52-
python-docx = "1.1.2"
52+
python-docx = "1.2.0"
5353
xlrd = "2.0.2"
5454
xlwt = "1.3.0"
5555
pymupdf = "1.24.9"
5656
pypdf = "5.6.0"
5757
gunicorn = "23.0.0"
5858
python-daemon = "3.1.2"
5959
pytz = "2025.2"
60-
django-apscheduler = "0.6.2"
60+
django-apscheduler = "0.7.0"
6161

6262
[build-system]
6363
requires = ["poetry-core"]

ui/src/components/app-icon/KnowledgeIcon.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<template>
2-
<el-avatar v-if="type === 1" class="avatar-purple" shape="square" :size="size">
2+
<el-avatar v-if="type == 1" class="avatar-purple" shape="square" :size="size">
33
<img src="@/assets/knowledge/icon_web.svg" style="width: 58%" alt="" />
44
</el-avatar>
55
<el-avatar
6-
v-else-if="type === 2"
6+
v-else-if="type == 2"
77
class="avatar-purple"
88
shape="square"
99
:size="size"

0 commit comments

Comments
 (0)