file_manager.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. """
  2. agent67.tools.file_manager — 文件管理器
  3. Lambda: λ action_json. file_op(action)
  4. """
  5. import json
  6. import os
  7. import shlex
  8. import subprocess
  9. from datetime import datetime
  10. from pathlib import Path
  11. from .safety import ask_user_confirm
  12. def manage_file(input_json: str) -> str:
  13. """
  14. 文件系统操作。
  15. 支持: read / write / list / search / info / mkdir / move / delete / tree
  16. """
  17. try:
  18. data = json.loads(input_json)
  19. except json.JSONDecodeError:
  20. return f"❌ 无效的 JSON 输入: {input_json}"
  21. action = data.get("action", "")
  22. path = os.path.expanduser(data.get("path", ""))
  23. try:
  24. if action == "read":
  25. p = Path(path)
  26. if not p.exists():
  27. return f"❌ 文件不存在: {path}"
  28. content = p.read_text(encoding="utf-8", errors="replace")
  29. if len(content) > 5000:
  30. return content[:5000] + f"\n... (文件共 {len(content)} 字符,已截断)"
  31. return content
  32. elif action == "write":
  33. content = data.get("content", "")
  34. p = Path(path)
  35. p.parent.mkdir(parents=True, exist_ok=True)
  36. p.write_text(content, encoding="utf-8")
  37. return f"✅ 已写入 {path} ({len(content)} 字符)"
  38. elif action == "list":
  39. p = Path(path) if path else Path.home()
  40. if not p.exists():
  41. return f"❌ 目录不存在: {path}"
  42. items = sorted(p.iterdir(), key=lambda x: (not x.is_dir(), x.name))
  43. lines = []
  44. for item in items[:50]:
  45. prefix = "📁" if item.is_dir() else "📄"
  46. size = ""
  47. if item.is_file():
  48. s = item.stat().st_size
  49. size = f" ({s} B)" if s < 1024 else f" ({s // 1024} KB)"
  50. lines.append(f" {prefix} {item.name}{size}")
  51. header = f"📂 {p} ({len(items)} 项)"
  52. if len(items) > 50:
  53. header += " (只显示前50项)"
  54. return header + "\n" + "\n".join(lines)
  55. elif action == "search":
  56. pattern = data.get("pattern", "*")
  57. p = Path(path) if path else Path.home()
  58. matches = list(p.rglob(pattern))[:20]
  59. if not matches:
  60. return f"未找到匹配 '{pattern}' 的文件"
  61. return f"找到 {len(matches)} 个匹配:\n" + "\n".join(
  62. f" {m}" for m in matches
  63. )
  64. elif action == "info":
  65. p = Path(path)
  66. if not p.exists():
  67. return f"❌ 路径不存在: {path}"
  68. stat = p.stat()
  69. return (
  70. f"📋 {p.name}\n"
  71. f" 类型: {'目录' if p.is_dir() else '文件'}\n"
  72. f" 大小: {stat.st_size:,} bytes\n"
  73. f" 修改: {datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S')}\n"
  74. f" 权限: {oct(stat.st_mode)[-3:]}"
  75. )
  76. elif action == "mkdir":
  77. Path(path).mkdir(parents=True, exist_ok=True)
  78. return f"✅ 目录已创建: {path}"
  79. elif action == "move":
  80. src = os.path.expanduser(data.get("src", ""))
  81. dst = os.path.expanduser(data.get("dst", ""))
  82. if not os.path.exists(src):
  83. return f"❌ 源路径不存在: {src}"
  84. os.rename(src, dst)
  85. return f"✅ 已移动: {src} → {dst}"
  86. elif action == "delete":
  87. if not ask_user_confirm(f"删除: {path}"):
  88. return "❌ 用户取消了删除操作"
  89. p = Path(path)
  90. if p.is_file():
  91. p.unlink()
  92. return f"✅ 文件已删除: {path}"
  93. elif p.is_dir():
  94. import shutil
  95. shutil.rmtree(path)
  96. return f"✅ 目录已删除: {path}"
  97. return f"❌ 路径不存在: {path}"
  98. elif action == "tree":
  99. depth = data.get("depth", 2)
  100. result = subprocess.run(
  101. f"find {shlex.quote(path)} -maxdepth {depth} -type f -o -type d",
  102. shell=True, capture_output=True, text=True, timeout=10,
  103. )
  104. return result.stdout.strip()[:3000] or f"目录为空: {path}"
  105. else:
  106. return f"❌ 未知操作: {action}. 支持: read/write/list/search/info/mkdir/move/delete/tree"
  107. except PermissionError:
  108. return f"🔒 权限不足: {path}"
  109. except Exception as e:
  110. return f"❌ 错误: {e}"