Skip to content

Commit 60fb82a

Browse files
authored
✨ Release/v1.7.8
2 parents f1f02b6 + bc908c6 commit 60fb82a

File tree

224 files changed

+13698
-8566
lines changed

Some content is hidden

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

224 files changed

+13698
-8566
lines changed

.github/workflows/deploy-docs.yml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,11 @@ jobs:
3838
with:
3939
fetch-depth: 0
4040

41-
- name: Setup Node
42-
uses: actions/setup-node@v4
43-
with:
44-
node-version: 20
45-
cache: npm
46-
cache-dependency-path: ./doc/package-lock.json
47-
4841
- name: Setup Pages
4942
uses: actions/configure-pages@v4
5043

5144
- name: Install dependencies
52-
run: npm ci
45+
run: npm install
5346

5447
- name: Build with VitePress
5548
run: npm run docs:build

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ docker/openssh-server
2020
docker/volumes/db/data
2121
docker/.env
2222
docker/.run
23+
docker/deploy.options
2324

2425
frontend_standalone/
2526
.pnpm-store/

backend/agents/create_agent_info.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
get_vector_db_core,
1616
get_embedding_model,
1717
)
18-
from services.tenant_config_service import get_selected_knowledge_list
18+
from services.tenant_config_service import get_selected_knowledge_list, build_knowledge_name_mapping
1919
from services.remote_mcp_service import get_remote_mcp_server_list
2020
from services.memory_config_service import build_memory_context
2121
from services.image_service import get_vlm_model
@@ -241,6 +241,7 @@ async def create_tool_config_list(agent_id, tenant_id, user_id):
241241
"index_names": index_names,
242242
"vdb_core": get_vector_db_core(),
243243
"embedding_model": get_embedding_model(tenant_id=tenant_id),
244+
"name_resolver": build_knowledge_name_mapping(tenant_id=tenant_id, user_id=user_id),
244245
}
245246
elif tool_config.class_name == "AnalyzeTextFileTool":
246247
tool_config.metadata = {

backend/apps/agent_app.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44

55
from fastapi import APIRouter, Body, Header, HTTPException, Request
66

7-
from consts.model import AgentRequest, AgentInfoRequest, AgentIDRequest, ConversationResponse, AgentImportRequest
7+
from consts.model import AgentRequest, AgentInfoRequest, AgentIDRequest, ConversationResponse, AgentImportRequest, AgentNameBatchCheckRequest, AgentNameBatchRegenerateRequest
88
from services.agent_service import (
99
get_agent_info_impl,
1010
get_creating_sub_agent_info_impl,
1111
update_agent_info_impl,
1212
delete_agent_impl,
1313
export_agent_impl,
1414
import_agent_impl,
15+
check_agent_name_conflict_batch_impl,
16+
regenerate_agent_name_batch_impl,
1517
list_all_agent_info_impl,
1618
run_agent_stream,
1719
stop_agent_tasks,
@@ -146,6 +148,36 @@ async def import_agent_api(request: AgentImportRequest, authorization: Optional[
146148
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Agent import error.")
147149

148150

151+
@agent_config_router.post("/check_name")
152+
async def check_agent_name_batch_api(request: AgentNameBatchCheckRequest, authorization: Optional[str] = Header(None)):
153+
"""
154+
Batch check whether agent name/display_name conflicts exist in the tenant.
155+
"""
156+
try:
157+
return await check_agent_name_conflict_batch_impl(request, authorization)
158+
except ValueError as e:
159+
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=str(e))
160+
except Exception as e:
161+
logger.error(f"Agent name batch check error: {str(e)}")
162+
raise HTTPException(
163+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Agent name batch check error.")
164+
165+
166+
@agent_config_router.post("/regenerate_name")
167+
async def regenerate_agent_name_batch_api(request: AgentNameBatchRegenerateRequest, authorization: Optional[str] = Header(None)):
168+
"""
169+
Batch regenerate agent name/display_name using LLM or suffix fallback.
170+
"""
171+
try:
172+
return await regenerate_agent_name_batch_impl(request, authorization)
173+
except ValueError as e:
174+
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=str(e))
175+
except Exception as e:
176+
logger.error(f"Agent name batch regenerate error: {str(e)}")
177+
raise HTTPException(
178+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Agent name batch regenerate error.")
179+
180+
149181
@agent_config_router.get("/list")
150182
async def list_all_agent_info_api(authorization: Optional[str] = Header(None), request: Request = None):
151183
"""

backend/apps/file_management_app.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
import re
3+
import base64
34
from http import HTTPStatus
45
from typing import List, Optional
56
from urllib.parse import urlparse, urlunparse, unquote, quote
@@ -149,7 +150,16 @@ async def process_files(
149150
@file_management_config_router.get("/download/{object_name:path}")
150151
async def get_storage_file(
151152
object_name: str = PathParam(..., description="File object name"),
152-
download: str = Query("ignore", description="How to get the file"),
153+
download: str = Query(
154+
"ignore",
155+
description=(
156+
"How to get the file: "
157+
"'ignore' (default, return file info), "
158+
"'stream' (return file stream), "
159+
"'redirect' (redirect to download URL), "
160+
"'base64' (return base64-encoded content for images)."
161+
),
162+
),
153163
expires: int = Query(3600, description="URL validity period (seconds)"),
154164
filename: Optional[str] = Query(None, description="Original filename for download (optional)")
155165
):
@@ -192,6 +202,28 @@ async def get_storage_file(
192202
"ETag": f'"{object_name}"',
193203
}
194204
)
205+
elif download == "base64":
206+
# Return base64 encoded file content (primarily for images)
207+
file_stream, content_type = await get_file_stream_impl(object_name=object_name)
208+
try:
209+
data = file_stream.read()
210+
except Exception as exc:
211+
logger.error("Failed to read file stream for base64: %s", str(exc))
212+
raise HTTPException(
213+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
214+
detail="Failed to read file content for base64 encoding",
215+
)
216+
217+
base64_content = base64.b64encode(data).decode("utf-8")
218+
return JSONResponse(
219+
status_code=HTTPStatus.OK,
220+
content={
221+
"success": True,
222+
"base64": base64_content,
223+
"content_type": content_type,
224+
"object_name": object_name,
225+
},
226+
)
195227
else:
196228
# return file metadata
197229
return await get_file_url_impl(object_name=object_name, expires=expires)

0 commit comments

Comments
 (0)