Skip to content

Commit d7aa26b

Browse files
authored
Release/v1.7.10
Release/v1.7.10
2 parents c7f4a15 + 1675714 commit d7aa26b

File tree

127 files changed

+13082
-2388
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+13082
-2388
lines changed

.github/dependabot.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
version: 2
2+
3+
updates:
4+
- package-ecosystem: "npm"
5+
directory: "/frontend"
6+
schedule:
7+
interval: "weekly"
8+
open-pull-requests-limit: 5
9+
labels:
10+
- "dependencies"
11+
12+
- package-ecosystem: "npm"
13+
directory: "/doc"
14+
schedule:
15+
interval: "weekly"
16+
open-pull-requests-limit: 2
17+
labels:
18+
- "dependencies"
19+
20+
- package-ecosystem: "pip"
21+
directory: "/backend"
22+
schedule:
23+
interval: "weekly"
24+
open-pull-requests-limit: 5
25+
labels:
26+
- "dependencies"
27+
28+
- package-ecosystem: "pip"
29+
directory: "/sdk"
30+
schedule:
31+
interval: "weekly"
32+
open-pull-requests-limit: 5
33+
labels:
34+
- "dependencies"
35+
36+

.github/workflows/codeql.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,4 @@ jobs:
9999
- name: Perform CodeQL Analysis
100100
uses: github/codeql-action/analyze@v3
101101
with:
102-
category: "/language:${{matrix.language}}"
102+
category: "/language:${{matrix.language}}"

backend/apps/agent_app.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
list_all_agent_info_impl,
1818
run_agent_stream,
1919
stop_agent_tasks,
20-
get_agent_call_relationship_impl
20+
get_agent_call_relationship_impl,
21+
clear_agent_new_mark_impl
2122
)
2223
from utils.auth_utils import get_current_user_info, get_current_user_id
2324

@@ -148,6 +149,21 @@ async def import_agent_api(request: AgentImportRequest, authorization: Optional[
148149
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Agent import error.")
149150

150151

152+
@agent_config_router.put("/clear_new/{agent_id}")
153+
async def clear_agent_new_mark_api(agent_id: int, authorization: Optional[str] = Header(None)):
154+
"""
155+
Clear the NEW mark for an agent
156+
"""
157+
try:
158+
user_id, tenant_id, _ = get_current_user_info(authorization)
159+
affected_rows = await clear_agent_new_mark_impl(agent_id, tenant_id, user_id)
160+
return {"message": "Agent NEW mark cleared successfully", "affected_rows": affected_rows}
161+
except Exception as e:
162+
logger.error(f"Failed to clear agent NEW mark: {str(e)}")
163+
raise HTTPException(
164+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Failed to clear agent NEW mark.")
165+
166+
151167
@agent_config_router.post("/check_name")
152168
async def check_agent_name_batch_api(request: AgentNameBatchCheckRequest, authorization: Optional[str] = Header(None)):
153169
"""

backend/apps/config_app.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from apps.voice_app import voice_config_router as voice_router
2222
from apps.tenant_app import router as tenant_router
2323
from apps.group_app import router as group_router
24+
from apps.user_app import router as user_router
2425
from apps.invitation_app import router as invitation_router
2526
from consts.const import IS_SPEED_MODE
2627

@@ -64,6 +65,7 @@
6465
app.include_router(remote_mcp_router)
6566
app.include_router(tenant_router)
6667
app.include_router(group_router)
68+
app.include_router(user_router)
6769
app.include_router(invitation_router)
6870

6971
# Initialize monitoring for the application

backend/apps/group_app.py

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010

1111
from consts.model import (
1212
GroupCreateRequest, GroupUpdateRequest,
13-
GroupUserRequest, GroupListRequest, SetDefaultGroupRequest
13+
GroupUserRequest, GroupListRequest, SetDefaultGroupRequest,
14+
GroupMembersUpdateRequest
1415
)
1516
from consts.exceptions import NotFoundException, ValidationError, UnauthorizedError
1617
from services.group_service import (
1718
create_group, get_group_info, update_group, delete_group,
1819
add_user_to_single_group, remove_user_from_single_group, get_group_users,
1920
add_user_to_groups, get_tenant_default_group_id, set_tenant_default_group_id,
20-
get_groups_by_tenant
21+
get_groups_by_tenant, update_group_members
2122
)
2223
from services.tenant_service import get_tenant_info
2324
from utils.auth_utils import get_current_user_id
@@ -140,11 +141,13 @@ async def get_groups_endpoint(
140141
try:
141142
# Validate tenant exists
142143
get_tenant_info(request.tenant_id)
143-
# Get groups under given tenant with pagination
144+
# Get groups under given tenant with pagination and sorting
144145
result = get_groups_by_tenant(
145146
tenant_id=request.tenant_id,
146147
page=request.page,
147-
page_size=request.page_size
148+
page_size=request.page_size,
149+
sort_by=request.sort_by,
150+
sort_order=request.sort_order
148151
)
149152

150153
return JSONResponse(
@@ -486,6 +489,70 @@ async def get_group_users_endpoint(group_id: int) -> JSONResponse:
486489
)
487490

488491

492+
@router.put("/{group_id}/members")
493+
async def update_group_members_endpoint(
494+
group_id: int,
495+
request: GroupMembersUpdateRequest,
496+
authorization: Optional[str] = Header(None)
497+
) -> JSONResponse:
498+
"""
499+
Update group members by setting the exact list of users.
500+
501+
Args:
502+
group_id: Group identifier
503+
request: Request containing the list of user IDs to set as group members
504+
authorization: Bearer token for authentication
505+
506+
Returns:
507+
JSONResponse: Update results with counts
508+
"""
509+
try:
510+
# Get current user ID from token
511+
current_user_id, _ = get_current_user_id(authorization)
512+
513+
# Update group members
514+
result = update_group_members(
515+
group_id=group_id,
516+
user_ids=request.user_ids,
517+
current_user_id=current_user_id
518+
)
519+
520+
logger.info(f"Updated group {group_id} members by user {current_user_id}: {result}")
521+
522+
return JSONResponse(
523+
status_code=HTTPStatus.OK,
524+
content={
525+
"message": "Group members updated successfully",
526+
"data": result
527+
}
528+
)
529+
530+
except NotFoundException as exc:
531+
logger.warning(f"Group not found for member update: {group_id}")
532+
raise HTTPException(
533+
status_code=HTTPStatus.NOT_FOUND,
534+
detail=str(exc)
535+
)
536+
except ValidationError as exc:
537+
logger.warning(f"Group members update validation error: {str(exc)}")
538+
raise HTTPException(
539+
status_code=HTTPStatus.BAD_REQUEST,
540+
detail=str(exc)
541+
)
542+
except UnauthorizedError as exc:
543+
logger.warning(f"Unauthorized group members update attempt: {str(exc)}")
544+
raise HTTPException(
545+
status_code=HTTPStatus.UNAUTHORIZED,
546+
detail=str(exc)
547+
)
548+
except Exception as exc:
549+
logger.error(f"Unexpected error during group members update: {str(exc)}")
550+
raise HTTPException(
551+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
552+
detail="Failed to update group members"
553+
)
554+
555+
489556
@router.post("/members/batch")
490557
async def add_user_to_groups_endpoint(
491558
request: GroupUserRequest,

backend/apps/invitation_app.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ async def list_invitations_endpoint(
4848
tenant_id=request.tenant_id,
4949
page=request.page,
5050
page_size=request.page_size,
51-
user_id=user_id
51+
user_id=user_id,
52+
sort_by=request.sort_by,
53+
sort_order=request.sort_order
5254
)
5355

5456
logger.info(f"User {user_id} retrieved invitation list (tenant: {request.tenant_id or 'all'}, page: {request.page}, size: {request.page_size})")

backend/apps/remote_mcp_app.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77

88
from consts.const import NEXENT_MCP_DOCKER_IMAGE, ENABLE_UPLOAD_IMAGE
99
from consts.exceptions import MCPConnectionError, MCPNameIllegal, MCPContainerError
10-
from consts.model import MCPConfigRequest
10+
from consts.model import MCPConfigRequest, MCPUpdateRequest
1111
from services.remote_mcp_service import (
1212
add_remote_mcp_server_list,
1313
delete_remote_mcp_server_list,
1414
get_remote_mcp_server_list,
1515
check_mcp_health_and_update_db,
1616
delete_mcp_by_container_id,
1717
upload_and_start_mcp_image,
18+
update_remote_mcp_server_list,
1819
)
1920
from database.remote_mcp_db import check_mcp_name_exists
2021
from services.tool_configuration_service import get_tool_from_remote_mcp_server
@@ -107,6 +108,38 @@ async def delete_remote_proxies(
107108
detail="Failed to delete remote MCP proxy")
108109

109110

111+
@router.put("/update")
112+
async def update_remote_proxy(
113+
update_data: MCPUpdateRequest,
114+
authorization: Optional[str] = Header(None)
115+
):
116+
""" Used to update an existing remote MCP server """
117+
try:
118+
user_id, tenant_id = get_current_user_id(authorization)
119+
await update_remote_mcp_server_list(
120+
update_data=update_data,
121+
tenant_id=tenant_id,
122+
user_id=user_id
123+
)
124+
return JSONResponse(
125+
status_code=HTTPStatus.OK,
126+
content={"message": "Successfully updated remote MCP proxy",
127+
"status": "success"}
128+
)
129+
except MCPNameIllegal as e:
130+
logger.error(f"Failed to update remote MCP proxy: {e}")
131+
raise HTTPException(status_code=HTTPStatus.CONFLICT,
132+
detail=str(e))
133+
except MCPConnectionError as e:
134+
logger.error(f"Failed to update remote MCP proxy: {e}")
135+
raise HTTPException(status_code=HTTPStatus.SERVICE_UNAVAILABLE,
136+
detail=str(e))
137+
except Exception as e:
138+
logger.error(f"Failed to update remote MCP proxy: {e}")
139+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
140+
detail="Failed to update remote MCP proxy")
141+
142+
110143
@router.get("/list")
111144
async def get_remote_proxies(
112145
authorization: Optional[str] = Header(None)

0 commit comments

Comments
 (0)