feat: add automatic node dependency management

This commit is contained in:
jingrow 2025-11-12 03:07:26 +08:00
parent 94c2e051c1
commit 8a09f790fd
4 changed files with 7 additions and 2447 deletions

View File

@ -4,7 +4,6 @@
""" """
import subprocess import subprocess
import logging import logging
import re
from pathlib import Path from pathlib import Path
from typing import Dict, Any, Optional, List from typing import Dict, Any, Optional, List
from jingrow.utils.path import get_jingrow_root from jingrow.utils.path import get_jingrow_root
@ -48,76 +47,6 @@ def discover_nodes_with_dependencies() -> List[str]:
return sorted(nodes_with_deps) return sorted(nodes_with_deps)
def update_workspace_members() -> Dict[str, Any]:
"""
自动更新 pyproject.toml 中的 workspace members
自动发现所有有 pyproject.toml 的节点更新为具体列表避免通配符匹配到无 pyproject.toml 的目录
Returns:
更新结果字典
"""
try:
jingrow_root = get_jingrow_root()
pyproject_path = jingrow_root.parent / "pyproject.toml"
if not pyproject_path.exists():
return {"success": False, "error": "pyproject.toml 不存在"}
# 发现所有有依赖的节点
nodes_with_deps = discover_nodes_with_dependencies()
# 读取 pyproject.toml
with open(pyproject_path, 'r', encoding='utf-8') as f:
content = f.read()
# 构建新的 members 列表
members_lines = []
for node_type in nodes_with_deps:
members_lines.append(f' "jingrow/ai/nodes/{node_type}",')
# 如果没有节点,使用空列表
if not members_lines:
members_lines = []
# 替换 workspace members 部分
# 匹配 [tool.uv.workspace] 到下一个 [ 或文件结尾
pattern = r'(\[tool\.uv\.workspace\]\s+members\s*=\s*\[)(.*?)(\]\s*(?:exclude\s*=.*?)?)'
def replace_workspace(match):
if members_lines:
return f'{match.group(1)}\n' + '\n'.join(members_lines) + f'\n{match.group(3)}'
else:
return f'{match.group(1)}\n{match.group(3)}'
if re.search(pattern, content, re.DOTALL):
new_content = re.sub(pattern, replace_workspace, content, flags=re.DOTALL)
else:
# 如果没有 workspace 配置,添加一个
if members_lines:
workspace_section = f'\n\n[tool.uv.workspace]\nmembers = [\n' + '\n'.join(members_lines) + '\n]\n'
else:
workspace_section = '\n\n[tool.uv.workspace]\nmembers = []\n'
new_content = content.rstrip() + workspace_section
# 只在内容有变化时才写入
if new_content != content:
with open(pyproject_path, 'w', encoding='utf-8') as f:
f.write(new_content)
return {
"success": True,
"message": f"已更新 workspace members: {', '.join(nodes_with_deps) if nodes_with_deps else ''}"
}
else:
return {
"success": True,
"message": "workspace members 无需更新"
}
except Exception as e:
logger.error(f"更新 workspace members 失败: {str(e)}")
return {"success": False, "error": str(e)}
def install_node_dependencies(node_type: str, sync: bool = True) -> Dict[str, Any]: def install_node_dependencies(node_type: str, sync: bool = True) -> Dict[str, Any]:
""" """
安装节点的依赖 安装节点的依赖
@ -141,11 +70,6 @@ def install_node_dependencies(node_type: str, sync: bool = True) -> Dict[str, An
# 节点没有独立依赖,返回成功(使用根依赖) # 节点没有独立依赖,返回成功(使用根依赖)
return {"success": True, "message": "节点使用根依赖,无需安装"} return {"success": True, "message": "节点使用根依赖,无需安装"}
# 更新 workspace members确保节点在 workspace 中)
update_result = update_workspace_members()
if not update_result.get("success"):
logger.warning(f"更新 workspace members 失败: {update_result.get('error')}")
# 获取项目根目录apps/jingrow # 获取项目根目录apps/jingrow
project_root = jingrow_root.parent project_root = jingrow_root.parent

View File

@ -19,8 +19,3 @@ dependencies = [
"Pillow>=10.0.0", "Pillow>=10.0.0",
"Jinja2>=3.1.0", "Jinja2>=3.1.0",
] ]
[tool.uv.workspace]
members = [
"jingrow/ai/nodes/web_scrapers",
]

2359
apps/jingrow/uv.lock generated

File diff suppressed because it is too large Load Diff

14
dev.sh
View File

@ -136,16 +136,16 @@ check_deps() {
# 检查后端依赖(优先使用 uv # 检查后端依赖(优先使用 uv
info "同步后端依赖 (uv)..." info "同步后端依赖 (uv)..."
if [ -f "apps/jingrow/pyproject.toml" ]; then if [ -f "apps/jingrow/pyproject.toml" ]; then
# 在 uv sync 之前,自动更新 workspace members包含所有有依赖的节点 # 同步主项目依赖
info "自动更新 workspace members..." (cd apps/jingrow && uv sync) || {
(cd apps/jingrow && uv run python -c "from jingrow.utils.node_dependencies import update_workspace_members; result = update_workspace_members(); print(result.get('message', '更新完成'))" 2>&1) || {
warn "更新 workspace members 失败,继续执行 uv sync"
}
# 使用 --all-packages 确保安装所有 workspace members 的依赖
(cd apps/jingrow && uv sync --all-packages) || {
error "uv 同步失败" error "uv 同步失败"
exit 1 exit 1
} }
# 安装所有节点的依赖(直接使用 uv pip install不修改配置文件
info "安装节点依赖..."
(cd apps/jingrow && uv run python -c "from jingrow.utils.node_dependencies import discover_nodes_with_dependencies, install_node_dependencies; nodes = discover_nodes_with_dependencies(); [install_node_dependencies(node) for node in nodes]" 2>&1) || {
warn "安装节点依赖失败,但继续执行"
}
elif [ -f "apps/jingrow/requirements.txt" ]; then elif [ -f "apps/jingrow/requirements.txt" ]; then
warn "未发现 pyproject.toml使用 requirements.txt 安装" warn "未发现 pyproject.toml使用 requirements.txt 安装"
(cd apps/jingrow && uv pip install -r requirements.txt) || { (cd apps/jingrow && uv pip install -r requirements.txt) || {