Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
32f0a33
Develop datamate core final version
Zhi-a Jan 16, 2026
07559ea
bugfix #2236 the username input box in email tools has input error
xuyaqist Jan 16, 2026
f5f473b
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 19, 2026
ddf9ec8
Button responsive layout optimization
xuyaqist Jan 19, 2026
50861b8
🧪 Add global test configuration and common fixtures for improved test…
Zhi-a Jan 19, 2026
d095ece
🧪 Add global test configuration and common fixtures for improved test…
Zhi-a Jan 19, 2026
25817e8
add expand edit modal
xuyaqist Jan 19, 2026
ac695b0
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 19, 2026
1e1337e
bugfix
xuyaqist Jan 19, 2026
5b669f1
🧪 Add global test configuration and common fixtures for improved test…
Zhi-a Jan 19, 2026
c669e5a
adjust ToolConfigModal&ToolTestPanel into one modal, fix input focus …
xuyaqist Jan 19, 2026
73d8ee9
add i18n
xuyaqist Jan 19, 2026
3550681
♻️ [WIP] User Management: Add initial data to role_permission_t, upda…
Jasonxia007 Jan 20, 2026
f437c9f
🐛&♻️ bugfix #2236 the username input box in email tools has input error
WMC001 Jan 20, 2026
aaae08a
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 19, 2026
6b0f87b
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 20, 2026
f500ad7
♻️ [WIP] User Management: Add initial data to role_permission_t, upda…
Jasonxia007 Jan 20, 2026
99746c6
第一次提交:初步增加Dify检索工具
SimengBian Jan 20, 2026
ef6dd6d
🧪 Add test files and frontend ui rules
Jasonxia007 Jan 20, 2026
aeaff95
🧪 Add test files and frontend ui rules
Jasonxia007 Jan 20, 2026
cd9ce25
♻️ User Management: Add initial data to role_permission_t
WMC001 Jan 20, 2026
395bf7f
第二次提交:功能基本正常可用
SimengBian Jan 20, 2026
b2a3f66
第三次提交:修改入参格式为JSON字符串
SimengBian Jan 20, 2026
07968ea
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 21, 2026
c3ecc43
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 21, 2026
0c2851c
Merge branch 'develop' of https://github.com/ModelEngine-Group/nexent…
Zhi-a Jan 21, 2026
ca83e9b
🧪 Add global test configuration and common fixtures for improved test
WMC001 Jan 21, 2026
f184fc8
✨ Add Dify Knowledgebase Search Tool
WMC001 Jan 21, 2026
b170cd2
✨ Refactor configuration management: Removed save_datamate_url endpoi…
Zhi-a Jan 21, 2026
9bba2cf
✨ Enhance DataMate configuration handling: Implemented error handling…
Zhi-a Jan 21, 2026
1833f7f
Merge branch 'develop' of https://github.com/ModelEngine-Group/nexent…
Zhi-a Jan 21, 2026
541dddd
✨ Implement upload restrictions for DataMate knowledge base: Added lo…
Zhi-a Jan 21, 2026
9e41038
✨ Update AppConfig to disable model engine by default and optimize te…
Zhi-a Jan 21, 2026
5c21516
Merge branch 'develop' of https://github.com/ModelEngine-Group/nexent…
Zhi-a Jan 21, 2026
fb3f5c9
🧪 Add test for list_indices to skip datamate sources
Zhi-a Jan 21, 2026
9c5f60e
Agent Import Optimization
Jan 22, 2026
cbec7a5
✨Develop datamate core part1
Zhi-a Jan 22, 2026
9cd002b
Unify datamate&dify search tool name
SimengBian Jan 22, 2026
36d8dd3
♻️ Improve dify search tool
WMC001 Jan 22, 2026
2237bae
✨ Agent Import Optimization
WMC001 Jan 22, 2026
8ecec7c
✨Develop datamate core part1
WMC001 Jan 22, 2026
9159e87
✨ Update DocumentList component and localization for DataMate restric…
Zhi-a Jan 22, 2026
07437ff
bugfix when saving a new created agent, cannot auto quit creating mod…
xuyaqist Jan 22, 2026
0780dbb
Merge branch 'develop' of https://github.com/ModelEngine-Group/nexent…
Zhi-a Jan 22, 2026
a100f7f
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 22, 2026
149bef5
Update opensource-memorial-wall.md
haruhikage1 Jan 22, 2026
52f156c
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 22, 2026
8ecaec8
Update opensource-memorial-wall.md from haruhikage1/patch-2
WMC001 Jan 22, 2026
29f9a6f
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 22, 2026
0cc1353
✨Added Datamate vector knowledge base core v2
Zhi-a Jan 22, 2026
8fc011c
✨ Develop datamate core final version part2
WMC001 Jan 22, 2026
5d3f7fa
Merge branch 'develop' of https://github.com/ModelEngine-Group/nexent…
Zhi-a Jan 22, 2026
8cc187e
🐛 Bugfix when saving a new created agent, cannot auto quit creating m…
WMC001 Jan 22, 2026
85af1bb
Enhanced unit tests to cover new SSL verification logic and ensure co…
Zhi-a Jan 22, 2026
d8e060a
✨ Develop datamate core part3 ---repair bug
WMC001 Jan 22, 2026
b419865
Update docs to illustrate dify_search tool
SimengBian Jan 22, 2026
3f46440
Unify default top_k as 3 in all search tools
SimengBian Jan 22, 2026
a7a9cbf
Repair test_datamate_search_tool error
SimengBian Jan 22, 2026
f1be1f4
📝 Update docs to illustrate dify_search tool
WMC001 Jan 22, 2026
d17e466
Agents created in the Agent Space can directly navigate to the Agent …
Jan 22, 2026
09c5c13
🐛 By default, users are not allowed to upload images to start the MCP…
YehongPan Jan 22, 2026
8f77aca
🐛 Agents created in the Agent Space can directly navigate to the Agent …
WMC001 Jan 22, 2026
cd32292
🐛 By default, users are not allowed to upload images to start the MCP…
WMC001 Jan 23, 2026
1a47ba3
✨ Modify KnowledgeBaseList and KnowledgeBaseContext components to imp…
Zhi-a Jan 23, 2026
6084117
✨ Add confirmation modal for deleting DataMate knowledge bases and up…
Zhi-a Jan 23, 2026
834e1dd
🐛 Bugfix: Seleted wrong model when creating agent #2296
WMC001 Jan 23, 2026
9e2b822
🐛 Add confirmation modal for deleting DataMate knowledge bases and up…
WMC001 Jan 23, 2026
08d3c83
📝 Update app version to 1.7.9.3
WMC001 Jan 23, 2026
4cb9183
🐛 Bugfix: Seleted wrong model when creating agent #2296
WMC001 Jan 23, 2026
886bdd8
🐛 Add default user_id & tenant_id to docker
Jasonxia007 Jan 23, 2026
058af63
🐛 Add default user_id & tenant_id to docker
WMC001 Jan 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions .cursor/rules/frontend/ui_standards_rules.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
globs: frontend/app/**,frontend/components/**
alwaysApply: false
---
# Frontend UI Standards Rules

## Principle
Use Ant Design as primary UI library with minimal Tailwind CSS. Prioritize mature Ant Design solutions for responsive layouts. Avoid secondary encapsulation unless necessary.

## Technology Usage Guidelines
- **Ant Design**: Forms, data display, complex interactions (`<Button>`, `<Modal>`, `<Form>`)
- **Tailwind CSS**: Spacing, layout, simple styling (`className="flex items-center gap-2 text-sm"`)
- **Inline Styles**: Special cases (`style={{ fontSize: "48px" }}`)
- **Override AntD**: Use `<style jsx global>` when necessary

## Layout Standards

### Global Layout
Use Header, Sider, Footer, Content structure. Reference: https://ant.design/components/layout-cn

```tsx
const { Header, Footer, Sider, Content } = Layout;

<Layout>
<Header>Header</Header>
<Layout>
<Sider width="25%">Sider</Sider>
<Content>Content</Content>
</Layout>
<Footer>Footer</Footer>
</Layout>
```

### Responsive Grid
Use AntD Grid for responsive layouts. Reference: https://ant.design/components/grid-cn

```tsx
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
</Row>
```

### Flex Layout
Use AntD Flex for component alignment. Reference: https://ant.design/components/flex-cn

```tsx
<Flex vertical className="h-full overflow-hidden">
<Row><Col>Content 1</Col></Row>
<Row><Col>Content 2</Col></Row>
<Row className="flex:1 min-h-0">
<Col><Flex className="h-full overflow-hidden">...</Flex></Col>
</Row>
</Flex>
```

## Component Standards

### Modals
1. **Complex Modal**: For reusable modals with custom content
2. **Simple Modal**: Use `useConfirmModal` for one-time confirmations

#### Modal Standards
- Use `centered` for positioning
- Confirm buttons: `type="primary" danger={true}`
- i18n keys: `common.cancel`, `common.confirm`
- Icon: `<ExclamationCircleFilled />` aligned with title

```tsx
// Complex modal
<Modal
open={isOpen}
centered
okButtonProps={{ type: "primary", danger: true }}
okText={t("common.confirm")}
>
<div className="flex items-start gap-4">
<ExclamationCircleFilled style={{ color: token.colorWarning, fontSize: '22px' }} />
<div>
<div className="font-medium">{t("title")}</div>
<div className="text-sm">{t("content")}</div>
</div>
</div>
</Modal>

// Simple modal
const { confirm } = useConfirmModal();
confirm({
title: t("delete.confirmTitle"),
content: t("delete.confirmContent"),
onOk: () => { /* ... */ }
});
```

### Icon Library
- **Primary**: `lucide-react` for consistency
- **Fallback**: `@ant-design/icons` when lucide-react lacks icons

```tsx
import { ExternalLink } from "lucide-react";
import { PlusOutlined } from '@ant-design/icons';

<ExternalLink />
<PlusOutlined />
```

## i18n Usage

```tsx
import { useTranslation, Trans } from "react-i18next";

// Simple text
t("common.confirm")

// HTML content
<Trans
i18nKey="modal.description"
values={{ title }}
components={{ strong: <strong /> }}
/>
```
13 changes: 12 additions & 1 deletion backend/agents/create_agent_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ async def create_agent_config(
tenant_id=tenant_id, user_id=user_id)
if knowledge_info_list:
for knowledge_info in knowledge_info_list:
if knowledge_info.get('knowledge_sources') != 'elasticsearch':
continue
knowledge_name = knowledge_info.get("index_name")
try:
message = ElasticSearchService().get_summary(index_name=knowledge_name)
Expand Down Expand Up @@ -239,13 +241,22 @@ async def create_tool_config_list(agent_id, tenant_id, user_id):
knowledge_info_list = get_selected_knowledge_list(
tenant_id=tenant_id, user_id=user_id)
index_names = [knowledge_info.get(
"index_name") for knowledge_info in knowledge_info_list]
"index_name") for knowledge_info in knowledge_info_list if knowledge_info.get('knowledge_sources') == 'elasticsearch']
tool_config.metadata = {
"index_names": index_names,
"vdb_core": get_vector_db_core(),
"embedding_model": get_embedding_model(tenant_id=tenant_id),
"name_resolver": build_knowledge_name_mapping(tenant_id=tenant_id, user_id=user_id),
}
elif tool_config.class_name == "DataMateSearchTool":
knowledge_info_list = get_selected_knowledge_list(
tenant_id=tenant_id, user_id=user_id)
index_names = [knowledge_info.get(
"index_name") for knowledge_info in knowledge_info_list if
knowledge_info.get('knowledge_sources') == 'datamate']
tool_config.metadata = {
"index_names": index_names,
}
elif tool_config.class_name == "AnalyzeTextFileTool":
tool_config.metadata = {
"llm_model": get_llm_model(tenant_id=tenant_id),
Expand Down
2 changes: 2 additions & 0 deletions backend/apps/config_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from apps.agent_app import agent_config_router as agent_router
from apps.config_sync_app import router as config_sync_router
from apps.datamate_app import router as datamate_router
from apps.vectordatabase_app import router as vectordatabase_router
from apps.file_management_app import file_management_config_router as file_manager_router
from apps.image_app import router as proxy_router
Expand Down Expand Up @@ -43,6 +44,7 @@
app.include_router(config_sync_router)
app.include_router(agent_router)
app.include_router(vectordatabase_router)
app.include_router(datamate_router)
app.include_router(voice_router)
app.include_router(file_manager_router)
app.include_router(proxy_router)
Expand Down
6 changes: 4 additions & 2 deletions backend/apps/config_sync_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ async def save_config(config: GlobalConfig, authorization: Optional[str] = Heade
)
except Exception as e:
logger.error(f"Failed to save configuration: {str(e)}")
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Failed to save configuration.")
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST,
detail="Failed to save configuration.")


@router.get("/load_config")
Expand All @@ -49,4 +50,5 @@ async def load_config(authorization: Optional[str] = Header(None), request: Requ
)
except Exception as e:
logger.error(f"Failed to load configuration: {str(e)}")
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Failed to load configuration.")
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST,
detail="Failed to load configuration.")
48 changes: 48 additions & 0 deletions backend/apps/datamate_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import logging
from typing import Optional

from fastapi import APIRouter, Header, HTTPException, Path
from fastapi.responses import JSONResponse
from http import HTTPStatus

from services.datamate_service import (
sync_datamate_knowledge_bases_and_create_records,
fetch_datamate_knowledge_base_file_list
)
from utils.auth_utils import get_current_user_id

router = APIRouter(prefix="/datamate")
logger = logging.getLogger("datamate_app")


@router.post("/sync_datamate_knowledges")
async def sync_datamate_knowledges(
authorization: Optional[str] = Header(None)
):
"""Sync DataMate knowledge bases and create knowledge records in local database."""
try:
user_id, tenant_id = get_current_user_id(authorization)

return await sync_datamate_knowledge_bases_and_create_records(
tenant_id=tenant_id,
user_id=user_id
)
except Exception as e:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=f"Error syncing DataMate knowledge bases and creating records: {str(e)}")


@router.get("/{knowledge_base_id}/files")
async def get_datamate_knowledge_base_files_endpoint(
knowledge_base_id: str = Path(...,
description="ID of the DataMate knowledge base"),
authorization: Optional[str] = Header(None)
):
"""Get all files from a DataMate knowledge base."""
try:
user_id, tenant_id = get_current_user_id(authorization)
result = await fetch_datamate_knowledge_base_file_list(knowledge_base_id, tenant_id)
return JSONResponse(status_code=HTTPStatus.OK, content=result)
except Exception as e:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=f"Error fetching DataMate knowledge base files: {str(e)}")
28 changes: 25 additions & 3 deletions backend/apps/tenant_config_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from fastapi.responses import JSONResponse

from consts.const import DEPLOYMENT_VERSION, APP_VERSION
from consts.model import UpdateKnowledgeListRequest
from services.tenant_config_service import get_selected_knowledge_list, update_selected_knowledge
from utils.auth_utils import get_current_user_id

Expand Down Expand Up @@ -61,16 +62,37 @@ def load_knowledge_list(
@router.post("/update_knowledge_list")
def update_knowledge_list(
authorization: Optional[str] = Header(None),
knowledge_list: List[str] = Body(None)
request: UpdateKnowledgeListRequest = Body(...)
):
try:
user_id, tenant_id = get_current_user_id(authorization)

# Convert grouped request to flat lists
knowledge_list = []
knowledge_sources = []

if request.nexent:
knowledge_list.extend(request.nexent)
knowledge_sources.extend(["nexent"] * len(request.nexent))

if request.datamate:
knowledge_list.extend(request.datamate)
knowledge_sources.extend(["datamate"] * len(request.datamate))

result = update_selected_knowledge(
tenant_id=tenant_id, user_id=user_id, index_name_list=knowledge_list)
tenant_id=tenant_id, user_id=user_id, index_name_list=knowledge_list, knowledge_sources=knowledge_sources)
if result:
# Get updated knowledge base information
selected_knowledge_info = get_selected_knowledge_list(
tenant_id=tenant_id, user_id=user_id)

content = {"selectedKbNames": [item["index_name"] for item in selected_knowledge_info],
"selectedKbModels": [item["embedding_model_name"] for item in selected_knowledge_info],
"selectedKbSources": [item["knowledge_sources"] for item in selected_knowledge_info]}

return JSONResponse(
status_code=HTTPStatus.OK,
content={"message": "update success", "status": "success"}
content={"content": content, "message": "update success", "status": "success"}
)
else:
raise HTTPException(
Expand Down
31 changes: 1 addition & 30 deletions backend/apps/user_management_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from consts.exceptions import NoInviteCodeException, IncorrectInviteCodeException, UserRegistrationException
from services.user_management_service import get_authorized_client, validate_token, \
check_auth_service_health, signup_user, signup_user_with_invitation, signin_user, refresh_user_token, \
get_session_by_authorization, revoke_regular_user, get_user_info, get_permissions_by_role
get_session_by_authorization, revoke_regular_user, get_user_info
from consts.exceptions import UnauthorizedError
from utils.auth_utils import get_current_user_id

Expand Down Expand Up @@ -287,32 +287,3 @@ async def revoke_user_account(request: Request):
logging.error(f"User revoke failed: {str(e)}")
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="User revoke failed")


@router.get("/role_permissions/{user_role}")
async def get_role_permissions(user_role: str):
"""
Get all permissions for a specific user role.

Args:
user_role (str): User role to query permissions for (SU, ADMIN, DEV, USER)

Returns:
JSONResponse: Permissions data with success message
"""
try:
permissions_data = await get_permissions_by_role(user_role)

return JSONResponse(status_code=HTTPStatus.OK, content={
"message": permissions_data["message"],
"data": {
"user_role": permissions_data["user_role"],
"permissions": permissions_data["permissions"],
"total_permissions": permissions_data["total_permissions"]
}
})
except Exception as e:
logging.error(
f"Failed to get role permissions for role {user_role}: {str(e)}")
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=f"Failed to retrieve permissions for role {user_role}")
5 changes: 3 additions & 2 deletions backend/consts/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# Vector database providers
class VectorDatabaseType(str, Enum):
ELASTICSEARCH = "elasticsearch"
DATAMATE = "datamate"


# Elasticsearch Configuration
Expand All @@ -23,7 +24,6 @@ class VectorDatabaseType(str, Enum):
ES_USERNAME = "elastic"
ELASTICSEARCH_SERVICE = os.getenv("ELASTICSEARCH_SERVICE")


# Data Processing Service Configuration
DATA_PROCESS_SERVICE = os.getenv("DATA_PROCESS_SERVICE")
CLIP_MODEL_PATH = os.getenv("CLIP_MODEL_PATH")
Expand Down Expand Up @@ -253,6 +253,7 @@ class VectorDatabaseType(str, Enum):
TENANT_NAME = "TENANT_NAME"
TENANT_ID = "TENANT_ID"
DEFAULT_GROUP_ID = "DEFAULT_GROUP_ID"
DATAMATE_URL = "DATAMATE_URL"

# Task Status Constants
TASK_STATUS = {
Expand Down Expand Up @@ -293,4 +294,4 @@ class VectorDatabaseType(str, Enum):
MODEL_ENGINE_ENABLED = os.getenv("MODEL_ENGINE_ENABLED")

# APP Version
APP_VERSION = "v1.7.9.2"
APP_VERSION = "v1.7.9.3"
11 changes: 10 additions & 1 deletion backend/consts/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ class AppConfig(BaseModel):
iconType: str
customIconUrl: Optional[str] = None
avatarUri: Optional[str] = None
modelEngineEnabled: bool = True
modelEngineEnabled: bool = False
datamateUrl: Optional[str] = None


class GlobalConfig(BaseModel):
Expand Down Expand Up @@ -460,6 +461,14 @@ class MCPConfigRequest(BaseModel):
..., description="Dictionary of MCP server configurations")


class UpdateKnowledgeListRequest(BaseModel):
"""Request model for updating user's selected knowledge base list grouped by source"""
nexent: Optional[List[str]] = Field(
None, description="List of knowledge base index names from nexent source")
datamate: Optional[List[str]] = Field(
None, description="List of knowledge base index names from datamate source")


# Tenant Management Data Models
# ---------------------------------------------------------------------------
class TenantCreateRequest(BaseModel):
Expand Down
Loading
Loading