Coverage for workspace.py: 27%

1"""

2工作空间模块

3

4每个 agent 有独立的工作空间，所有路径都从这里派生，不在各模块中硬编码。

5

6目录结构：

7 ~/.qrclaw/agents/<agent_id>/

8 ├── sessions/ 会话文件

9 ├── logs/ 日志文件

10 ├── skills/ 技能

11 ├── MEMORY.md 中期记忆

12 ├── HEARTBEAT.md 心跳任务配置

13 └── sub-agents/ 子 agent 工作空间

14 └── <sub_id>/

15 ├── sessions/

16 ├── logs/

17 ├── skills/

18 └── MEMORY.md

19"""

20 from pathlib import Path

21

22# 所有 agent 的根目录

23 AGENTS_ROOT = Path.home() / ".qrclaw" / "agents"

24

25

26 class Workspace:

27 """agent 工作空间，持有该 agent 所有资源的路径。"""

28

29 def __init__(self, agent_id: str = "default", _root: Path = None):

30 self.agent_id = agent_id

31 # _root 由 sub_agent() 传入，支持嵌套路径

32 self.root = _root or (AGENTS_ROOT / agent_id)

33

34 # 各子目录/文件路径

35 self.sessions_dir = self.root / "sessions"

36 self.logs_dir = self.root / "logs"

37 self.skills_dir = self.root / "skills"

38 self.memory_file = self.root / "MEMORY.md"

39 self.heartbeat_file = self.root / "HEARTBEAT.md"

40 self.sub_agents_dir = self.root / "sub-agents"

41

42 # 确保目录都存在

43 self.sessions_dir.mkdir(parents=True, exist_ok=True)

44 self.logs_dir.mkdir(parents=True, exist_ok=True)

45 self.skills_dir.mkdir(parents=True, exist_ok=True)

46

47 def sub_agent(self, sub_id: str) -> "Workspace":

48 """

49 创建子 agent 工作空间，嵌套在当前 agent 下。

50

51 路径：<当前agent_root>/sub-agents/<sub_id>/

52 """

53 sub_root = self.sub_agents_dir / sub_id

54 return Workspace(agent_id=sub_id, _root=sub_root)

55

56

57 def list_agents() -> list[str]:

58 """列出所有顶级 agent ID。"""

59 if not AGENTS_ROOT.exists():

60 return []

61 return [d.name for d in sorted(AGENTS_ROOT.iterdir()) if d.is_dir()]