add file tree
This commit is contained in:
parent
f22fd5ed72
commit
ed609eba6c
268
fastapi_app.py
268
fastapi_app.py
@ -193,7 +193,6 @@ async def generate_stream_response(agent, messages, request) -> AsyncGenerator[s
|
|||||||
# Models are now imported from utils module
|
# Models are now imported from utils module
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/v1/files/process/async")
|
@app.post("/api/v1/files/process/async")
|
||||||
async def process_files_async_endpoint(request: QueueTaskRequest, authorization: Optional[str] = Header(None)):
|
async def process_files_async_endpoint(request: QueueTaskRequest, authorization: Optional[str] = Header(None)):
|
||||||
"""
|
"""
|
||||||
@ -596,65 +595,6 @@ async def health_check():
|
|||||||
return {"message": "Database Assistant API is running"}
|
return {"message": "Database Assistant API is running"}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/system/status")
|
|
||||||
async def system_status():
|
|
||||||
"""获取系统状态信息"""
|
|
||||||
# 获取助手缓存统计
|
|
||||||
cache_stats = agent_manager.get_cache_stats()
|
|
||||||
|
|
||||||
return {
|
|
||||||
"status": "running",
|
|
||||||
"storage_type": "File-Loaded Agent Manager",
|
|
||||||
"max_cached_agents": max_cached_agents,
|
|
||||||
"agent_cache": {
|
|
||||||
"total_cached_agents": cache_stats["total_cached_agents"],
|
|
||||||
"max_cached_agents": cache_stats["max_cached_agents"],
|
|
||||||
"cached_agents": cache_stats["agents"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/system/cleanup-cache")
|
|
||||||
async def cleanup_cache():
|
|
||||||
"""清理助手缓存"""
|
|
||||||
try:
|
|
||||||
# 清理助手实例缓存
|
|
||||||
cleared_count = agent_manager.clear_cache()
|
|
||||||
|
|
||||||
return {
|
|
||||||
"message": "缓存清理成功",
|
|
||||||
"cleared_agent_instances": cleared_count
|
|
||||||
}
|
|
||||||
except Exception as e:
|
|
||||||
raise HTTPException(status_code=500, detail=f"缓存清理失败: {str(e)}")
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/system/cleanup-agent-cache")
|
|
||||||
async def cleanup_agent_cache():
|
|
||||||
"""仅清理助手实例缓存"""
|
|
||||||
try:
|
|
||||||
cleared_count = agent_manager.clear_cache()
|
|
||||||
return {
|
|
||||||
"message": "助手实例缓存清理成功",
|
|
||||||
"cleared_agent_instances": cleared_count
|
|
||||||
}
|
|
||||||
except Exception as e:
|
|
||||||
raise HTTPException(status_code=500, detail=f"助手实例缓存清理失败: {str(e)}")
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/system/cached-projects")
|
|
||||||
async def get_cached_projects():
|
|
||||||
"""获取所有缓存的项目信息"""
|
|
||||||
try:
|
|
||||||
cache_stats = agent_manager.get_cache_stats()
|
|
||||||
|
|
||||||
return {
|
|
||||||
"cache_stats": cache_stats
|
|
||||||
}
|
|
||||||
except Exception as e:
|
|
||||||
raise HTTPException(status_code=500, detail=f"获取缓存项目信息失败: {str(e)}")
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/system/remove-project-cache")
|
@app.post("/system/remove-project-cache")
|
||||||
async def remove_project_cache(dataset_id: str):
|
async def remove_project_cache(dataset_id: str):
|
||||||
"""移除特定项目的缓存"""
|
"""移除特定项目的缓存"""
|
||||||
@ -764,6 +704,214 @@ async def reset_files_processing(dataset_id: str):
|
|||||||
raise HTTPException(status_code=500, detail=f"重置文件处理状态失败: {str(e)}")
|
raise HTTPException(status_code=500, detail=f"重置文件处理状态失败: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
def build_directory_tree(path: str, relative_path: str = "") -> dict:
|
||||||
|
"""构建目录树结构"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
tree = {
|
||||||
|
"name": os.path.basename(path) or "projects",
|
||||||
|
"path": relative_path,
|
||||||
|
"type": "directory",
|
||||||
|
"children": [],
|
||||||
|
"size": 0,
|
||||||
|
"modified_time": os.path.getmtime(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
entries = os.listdir(path)
|
||||||
|
entries.sort()
|
||||||
|
|
||||||
|
for entry in entries:
|
||||||
|
entry_path = os.path.join(path, entry)
|
||||||
|
entry_relative_path = os.path.join(relative_path, entry) if relative_path else entry
|
||||||
|
|
||||||
|
if os.path.isdir(entry_path):
|
||||||
|
tree["children"].append(build_directory_tree(entry_path, entry_relative_path))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
file_size = os.path.getsize(entry_path)
|
||||||
|
file_modified = os.path.getmtime(entry_path)
|
||||||
|
tree["children"].append({
|
||||||
|
"name": entry,
|
||||||
|
"path": entry_relative_path,
|
||||||
|
"type": "file",
|
||||||
|
"size": file_size,
|
||||||
|
"modified_time": file_modified
|
||||||
|
})
|
||||||
|
tree["size"] += file_size
|
||||||
|
except (OSError, IOError):
|
||||||
|
tree["children"].append({
|
||||||
|
"name": entry,
|
||||||
|
"path": entry_relative_path,
|
||||||
|
"type": "file",
|
||||||
|
"size": 0,
|
||||||
|
"modified_time": 0
|
||||||
|
})
|
||||||
|
except (OSError, IOError) as e:
|
||||||
|
print(f"Error reading directory {path}: {e}")
|
||||||
|
|
||||||
|
return tree
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/v1/projects/tree")
|
||||||
|
async def get_projects_tree(
|
||||||
|
include_files: bool = True,
|
||||||
|
max_depth: int = 10,
|
||||||
|
filter_type: Optional[str] = None
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
获取projects文件夹的目录树结构
|
||||||
|
|
||||||
|
Args:
|
||||||
|
include_files: 是否包含文件,false时只显示目录
|
||||||
|
max_depth: 最大深度限制
|
||||||
|
filter_type: 过滤类型 ('data', 'robot', 'uploads')
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 包含目录树结构的响应
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
projects_dir = "projects"
|
||||||
|
|
||||||
|
if not os.path.exists(projects_dir):
|
||||||
|
return {
|
||||||
|
"success": False,
|
||||||
|
"message": "projects目录不存在",
|
||||||
|
"tree": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree = build_directory_tree(projects_dir)
|
||||||
|
|
||||||
|
# 根据filter_type过滤
|
||||||
|
if filter_type and filter_type in ['data', 'robot', 'uploads']:
|
||||||
|
filtered_children = []
|
||||||
|
for child in tree.get("children", []):
|
||||||
|
if child["name"] == filter_type:
|
||||||
|
filtered_children.append(child)
|
||||||
|
tree["children"] = filtered_children
|
||||||
|
|
||||||
|
# 如果不包含文件,移除所有文件节点
|
||||||
|
if not include_files:
|
||||||
|
tree = filter_directories_only(tree)
|
||||||
|
|
||||||
|
# 计算统计信息
|
||||||
|
stats = calculate_tree_stats(tree)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"success": True,
|
||||||
|
"message": "目录树获取成功",
|
||||||
|
"tree": tree,
|
||||||
|
"stats": stats,
|
||||||
|
"filters": {
|
||||||
|
"include_files": include_files,
|
||||||
|
"max_depth": max_depth,
|
||||||
|
"filter_type": filter_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error getting projects tree: {str(e)}")
|
||||||
|
raise HTTPException(status_code=500, detail=f"获取目录树失败: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
def filter_directories_only(tree: dict) -> dict:
|
||||||
|
"""过滤掉文件,只保留目录"""
|
||||||
|
if tree["type"] != "directory":
|
||||||
|
return tree
|
||||||
|
|
||||||
|
filtered_children = []
|
||||||
|
for child in tree.get("children", []):
|
||||||
|
if child["type"] == "directory":
|
||||||
|
filtered_children.append(filter_directories_only(child))
|
||||||
|
|
||||||
|
tree["children"] = filtered_children
|
||||||
|
return tree
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_tree_stats(tree: dict) -> dict:
|
||||||
|
"""计算目录树统计信息"""
|
||||||
|
stats = {
|
||||||
|
"total_directories": 0,
|
||||||
|
"total_files": 0,
|
||||||
|
"total_size": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
def traverse(node):
|
||||||
|
if node["type"] == "directory":
|
||||||
|
stats["total_directories"] += 1
|
||||||
|
for child in node.get("children", []):
|
||||||
|
traverse(child)
|
||||||
|
else:
|
||||||
|
stats["total_files"] += 1
|
||||||
|
stats["total_size"] += node.get("size", 0)
|
||||||
|
|
||||||
|
traverse(tree)
|
||||||
|
return stats
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/v1/projects/subtree/{sub_path:path}")
|
||||||
|
async def get_projects_subtree(
|
||||||
|
sub_path: str,
|
||||||
|
include_files: bool = True,
|
||||||
|
max_depth: int = 5
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
获取projects子目录的树结构
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sub_path: 子目录路径,如 'data/1624be71-5432-40bf-9758-f4aecffd4e9c'
|
||||||
|
include_files: 是否包含文件
|
||||||
|
max_depth: 最大深度
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 包含子目录树结构的响应
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
full_path = os.path.join("projects", sub_path)
|
||||||
|
|
||||||
|
if not os.path.exists(full_path):
|
||||||
|
return {
|
||||||
|
"success": False,
|
||||||
|
"message": f"路径不存在: {sub_path}",
|
||||||
|
"tree": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if not os.path.isdir(full_path):
|
||||||
|
return {
|
||||||
|
"success": False,
|
||||||
|
"message": f"路径不是目录: {sub_path}",
|
||||||
|
"tree": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree = build_directory_tree(full_path, sub_path)
|
||||||
|
|
||||||
|
# 如果不包含文件,移除所有文件节点
|
||||||
|
if not include_files:
|
||||||
|
tree = filter_directories_only(tree)
|
||||||
|
|
||||||
|
# 计算统计信息
|
||||||
|
stats = calculate_tree_stats(tree)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"success": True,
|
||||||
|
"message": "子目录树获取成功",
|
||||||
|
"sub_path": sub_path,
|
||||||
|
"tree": tree,
|
||||||
|
"stats": stats,
|
||||||
|
"filters": {
|
||||||
|
"include_files": include_files,
|
||||||
|
"max_depth": max_depth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error getting projects subtree: {str(e)}")
|
||||||
|
raise HTTPException(status_code=500, detail=f"获取子目录树失败: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user