Skip to content

Commit efbca29

Browse files
committed
feat: add tool record retrieval and UI components for execution details
1 parent 834d4e3 commit efbca29

7 files changed

Lines changed: 738 additions & 8 deletions

File tree

apps/tools/serializers/tool.py

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import uuid_utils.compat as uuid
1414
from django.core import validators
1515
from django.db import transaction
16-
from django.db.models import QuerySet, Q
16+
from django.db.models import QuerySet, Q, Subquery, OuterRef, CharField, Value, When, Case
1717
from django.http import HttpResponse
1818
from django.utils import timezone
1919
from django.utils.translation import gettext_lazy as _
@@ -22,6 +22,7 @@
2222
from pylint.reporters import JSON2Reporter
2323
from rest_framework import serializers, status
2424

25+
from application.models import Application
2526
from common.database_model_manage.database_model_manage import DatabaseModelManage
2627
from common.db.search import page_search, native_page_search, native_search
2728
from common.exception.app_exception import AppApiException
@@ -31,14 +32,15 @@
3132
from common.utils.logger import maxkb_logger
3233
from common.utils.rsa_util import rsa_long_decrypt, rsa_long_encrypt
3334
from common.utils.tool_code import ToolExecutor
35+
from knowledge.models import File, FileSourceType, Knowledge
36+
from maxkb.const import PROJECT_DIR
37+
from role_setting.models import Workspace
38+
from system_manage.models import AuthTargetType, WorkspaceUserResourcePermission
3439
from system_manage.models.resource_mapping import ResourceMapping
3540
from system_manage.serializers.resource_mapping_serializers import ResourceMappingSerializer
36-
from knowledge.models import File, FileSourceType
37-
from maxkb.const import CONFIG, PROJECT_DIR
38-
from system_manage.models import AuthTargetType, WorkspaceUserResourcePermission
3941
from system_manage.serializers.user_resource_permission import UserResourcePermissionSerializer
40-
from tools.models import Tool, ToolScope, ToolFolder, ToolType
41-
from trigger.models import TriggerTask
42+
from tools.models import Tool, ToolScope, ToolFolder, ToolType, ToolRecord
43+
from trigger.models import TriggerTask, Trigger
4244
from users.serializers.user import is_workspace_manage
4345

4446
tool_executor = ToolExecutor()
@@ -133,6 +135,13 @@ class Meta:
133135
'version', 'create_time', 'update_time']
134136

135137

138+
class ToolRecordModelSerializer(serializers.ModelSerializer):
139+
class Meta:
140+
model = ToolRecord
141+
fields = ['id', 'workspace_id', 'tool_id', 'source_type', 'source_id', 'meta', 'state', 'run_time',
142+
'create_time', 'update_time']
143+
144+
136145
class ToolExportModelSerializer(serializers.ModelSerializer):
137146
class Meta:
138147
model = Tool
@@ -876,6 +885,63 @@ def update_tool(self, with_valid=True):
876885
maxkb_logger.error(f"callback appstore tool download error: {e}")
877886
return ToolModelSerializer(tool).data
878887

888+
class ToolRecord(serializers.Serializer):
889+
workspace_id = serializers.CharField(required=True, label=_('workspace id'))
890+
tool_id = serializers.UUIDField(required=True, label=_('tool id'))
891+
record_id = serializers.UUIDField(required=False, allow_null=True, label=_('record id'))
892+
source_name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('source name'))
893+
source_type = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('source type'))
894+
state = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('state'))
895+
896+
def one(self):
897+
self.is_valid(raise_exception=True)
898+
if self.data.get('record_id'):
899+
page = self.get_tool_records(1, 1)
900+
return page.get('records')[0]
901+
902+
return None
903+
904+
def get_tool_records(self, current_page: int, page_size: int):
905+
self.is_valid(raise_exception=True)
906+
application_subquery = Application.objects.filter(id=OuterRef('source_id')).values('name')[:1]
907+
knowledge_subquery = Knowledge.objects.filter(id=OuterRef('source_id')).values('name')[:1]
908+
trigger_subquery = Trigger.objects.filter(id=OuterRef('source_id')).values('name')[:1]
909+
workspace_subquery = Workspace.objects.filter(id=OuterRef('workspace_id')).values('name')[:1]
910+
911+
query_set = QuerySet(ToolRecord)
912+
query_set = query_set.filter(
913+
workspace_id=self.data.get('workspace_id'),
914+
tool_id=self.data.get('tool_id')
915+
).annotate(
916+
source_name=Case(
917+
When(source_type='APPLICATION', then=Subquery(application_subquery)),
918+
When(source_type='KNOWLEDGE', then=Subquery(knowledge_subquery)),
919+
When(source_type='TRIGGER', then=Subquery(trigger_subquery)),
920+
default=Value(''),
921+
output_field=CharField()
922+
)
923+
).annotate(
924+
workspace_name=Subquery(workspace_subquery)
925+
)
926+
if self.data.get('source_type'):
927+
query_set = query_set.filter(Q(source_type=self.data.get('source_type', '')))
928+
if self.data.get('state'):
929+
query_set = query_set.filter(Q(state=self.data.get('state', '')))
930+
if self.data.get('source_name'):
931+
query_set = query_set.filter(Q(source_name__icontains=self.data.get('source_name', '')))
932+
if self.data.get('record_id'):
933+
query_set = query_set.filter(Q(id=self.data.get('record_id')))
934+
query_set = query_set.order_by('-create_time')
935+
936+
return page_search(
937+
current_page, page_size, query_set,
938+
lambda record: {
939+
**ToolRecordModelSerializer(record).data,
940+
'source_name': record.source_name,
941+
'workspace_name': record.workspace_name,
942+
}
943+
)
944+
879945

880946
class ToolTreeSerializer(serializers.Serializer):
881947
class Query(serializers.Serializer):

apps/tools/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@
1919
path('workspace/<str:workspace_id>/tool/<str:tool_id>/add_internal_tool', views.ToolView.AddInternalTool.as_view()),
2020
path('workspace/<str:workspace_id>/tool/<str:tool_id>/add_store_tool', views.ToolView.AddStoreTool.as_view()),
2121
path('workspace/<str:workspace_id>/tool/<str:tool_id>/update_store_tool', views.ToolView.UpdateStoreTool.as_view()),
22+
path('workspace/<str:workspace_id>/tool/<str:tool_id>/tool_record/<str:record_id>', views.ToolView.ToolRecord.as_view()),
23+
path('workspace/<str:workspace_id>/tool/<str:tool_id>/tool_record/<int:current_page>/<int:page_size>', views.ToolView.PageToolRecord.as_view()),
2224
path('workspace/<str:workspace_id>/tool/<int:current_page>/<int:page_size>', views.ToolView.Page.as_view()),
2325
]

apps/tools/views/tool.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,4 +512,60 @@ def post(self, request: Request, tool_id: str, workspace_id: str):
512512
'download_callback_url': request.data.get('download_callback_url'),
513513
'icon': request.data.get('icon'),
514514
'versions': request.data.get('versions'),
515-
}).update_tool(request.data))
515+
}).update_tool(request.data))
516+
517+
class PageToolRecord(APIView):
518+
authentication_classes = [TokenAuth]
519+
520+
@extend_schema(
521+
methods=['GET'],
522+
description=_("Get tool records"),
523+
summary=_("Get tool records"),
524+
operation_id=_("Get tool records"), # type: ignore
525+
parameters=AddInternalToolAPI.get_parameters(),
526+
responses=AddInternalToolAPI.get_response(),
527+
tags=[_("Tool")] # type: ignore
528+
)
529+
@has_permissions(
530+
PermissionConstants.TOOL_READ.get_workspace_tool_permission(),
531+
PermissionConstants.TOOL_READ.get_workspace_permission_workspace_manage_role(),
532+
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
533+
ViewPermission([RoleConstants.USER.get_workspace_role()],
534+
[PermissionConstants.TOOL.get_workspace_tool_permission()],
535+
CompareConstants.AND),
536+
)
537+
def get(self, request: Request, tool_id: str, workspace_id: str, current_page: int, page_size: int):
538+
return result.success(ToolSerializer.ToolRecord(data={
539+
'tool_id': tool_id,
540+
'workspace_id': workspace_id,
541+
'source_name': request.query_params.get('source_name'),
542+
'source_type': request.query_params.get('source_type'),
543+
'state': request.query_params.get('state'),
544+
}).get_tool_records(current_page, page_size))
545+
546+
class ToolRecord(APIView):
547+
authentication_classes = [TokenAuth]
548+
549+
@extend_schema(
550+
methods=['GET'],
551+
description=_("Get tool record"),
552+
summary=_("Get tool record"),
553+
operation_id=_("Get tool record"), # type: ignore
554+
parameters=AddInternalToolAPI.get_parameters(),
555+
responses=AddInternalToolAPI.get_response(),
556+
tags=[_("Tool")] # type: ignore
557+
)
558+
@has_permissions(
559+
PermissionConstants.TOOL_READ.get_workspace_tool_permission(),
560+
PermissionConstants.TOOL_READ.get_workspace_permission_workspace_manage_role(),
561+
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
562+
ViewPermission([RoleConstants.USER.get_workspace_role()],
563+
[PermissionConstants.TOOL.get_workspace_tool_permission()],
564+
CompareConstants.AND),
565+
)
566+
def get(self, request: Request, tool_id: str, workspace_id: str, record_id: str):
567+
return result.success(ToolSerializer.ToolRecord(data={
568+
'tool_id': tool_id,
569+
'workspace_id': workspace_id,
570+
'record_id': record_id,
571+
}).one())

ui/src/api/tool/tool.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,27 @@ const updateStoreTool: (
179179
return post(`${prefix.value}/${tool_id}/update_store_tool`, param, undefined, loading)
180180
}
181181

182+
const pageToolRecord = (
183+
tool_id: string,
184+
page: pageRequest,
185+
param: any,
186+
loading?: Ref<boolean>,
187+
) => {
188+
return get(
189+
`${prefix.value}/${tool_id}/tool_record/${page.current_page}/${page.page_size}`,
190+
param,
191+
loading,
192+
)
193+
}
194+
195+
const getToolRecordDetail = (
196+
tool_id: string,
197+
record_id: string
198+
) => {
199+
return get(`${prefix.value}/${tool_id}/tool_record/${record_id}`)
200+
}
201+
202+
182203

183204
export default {
184205
getToolList,
@@ -196,5 +217,7 @@ export default {
196217
addInternalTool,
197218
addStoreTool,
198219
updateStoreTool,
199-
postToolTestConnection
220+
postToolTestConnection,
221+
pageToolRecord,
222+
getToolRecordDetail,
200223
}

0 commit comments

Comments
 (0)