@huajiwuyan/hello 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +68 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +448 -0
  4. package/package.json +38 -0
  5. package/templates/claude/commands/hello.md +760 -0
  6. package/templates/claude/skills/SKILL.md +90 -0
  7. package/templates/claude/skills/SKILL.toml +7 -0
  8. package/templates/claude/skills/assets/icon-large.svg +12 -0
  9. package/templates/claude/skills/assets/icon-small-400px.svg +12 -0
  10. package/templates/claude/skills/assets/templates/CHANGELOG.md +24 -0
  11. package/templates/claude/skills/assets/templates/CHANGELOG_{YYYY}.md +25 -0
  12. package/templates/claude/skills/assets/templates/INDEX.md +36 -0
  13. package/templates/claude/skills/assets/templates/archive/_index.md +22 -0
  14. package/templates/claude/skills/assets/templates/context.md +82 -0
  15. package/templates/claude/skills/assets/templates/modules/_index.md +22 -0
  16. package/templates/claude/skills/assets/templates/modules/module.md +35 -0
  17. package/templates/claude/skills/assets/templates/plan/proposal.md +104 -0
  18. package/templates/claude/skills/assets/templates/plan/tasks.md +49 -0
  19. package/templates/claude/skills/references/functions/auto.md +217 -0
  20. package/templates/claude/skills/references/functions/clean.md +167 -0
  21. package/templates/claude/skills/references/functions/commit.md +374 -0
  22. package/templates/claude/skills/references/functions/exec.md +178 -0
  23. package/templates/claude/skills/references/functions/help.md +105 -0
  24. package/templates/claude/skills/references/functions/init.md +228 -0
  25. package/templates/claude/skills/references/functions/plan.md +219 -0
  26. package/templates/claude/skills/references/functions/review.md +146 -0
  27. package/templates/claude/skills/references/functions/rollback.md +208 -0
  28. package/templates/claude/skills/references/functions/test.md +153 -0
  29. package/templates/claude/skills/references/functions/upgrade.md +371 -0
  30. package/templates/claude/skills/references/functions/validate.md +147 -0
  31. package/templates/claude/skills/references/rules/package.md +212 -0
  32. package/templates/claude/skills/references/rules/scaling.md +150 -0
  33. package/templates/claude/skills/references/rules/state.md +318 -0
  34. package/templates/claude/skills/references/rules/tools.md +371 -0
  35. package/templates/claude/skills/references/services/knowledge.md +408 -0
  36. package/templates/claude/skills/references/services/templates.md +344 -0
  37. package/templates/claude/skills/references/stages/analyze.md +201 -0
  38. package/templates/claude/skills/references/stages/design.md +379 -0
  39. package/templates/claude/skills/references/stages/develop.md +497 -0
  40. package/templates/claude/skills/references/stages/evaluate.md +286 -0
  41. package/templates/claude/skills/references/stages/tweak.md +244 -0
  42. package/templates/claude/skills/scripts/create_package.py +260 -0
  43. package/templates/claude/skills/scripts/list_packages.py +145 -0
  44. package/templates/claude/skills/scripts/migrate_package.py +399 -0
  45. package/templates/claude/skills/scripts/project_stats.py +438 -0
  46. package/templates/claude/skills/scripts/upgradewiki.py +321 -0
  47. package/templates/claude/skills/scripts/utils.py +596 -0
  48. package/templates/claude/skills/scripts/validate_package.py +309 -0
  49. package/templates/codex/prompts/hello.md +757 -0
  50. package/templates/codex/skills/SKILL.md +74 -0
  51. package/templates/codex/skills/SKILL.toml +7 -0
  52. package/templates/codex/skills/assets/icon-large.svg +12 -0
  53. package/templates/codex/skills/assets/icon-small-400px.svg +12 -0
  54. package/templates/codex/skills/assets/templates/CHANGELOG.md +24 -0
  55. package/templates/codex/skills/assets/templates/CHANGELOG_{YYYY}.md +25 -0
  56. package/templates/codex/skills/assets/templates/INDEX.md +36 -0
  57. package/templates/codex/skills/assets/templates/archive/_index.md +22 -0
  58. package/templates/codex/skills/assets/templates/context.md +82 -0
  59. package/templates/codex/skills/assets/templates/modules/_index.md +22 -0
  60. package/templates/codex/skills/assets/templates/modules/module.md +35 -0
  61. package/templates/codex/skills/assets/templates/plan/proposal.md +104 -0
  62. package/templates/codex/skills/assets/templates/plan/tasks.md +29 -0
  63. package/templates/codex/skills/references/functions/auto.md +181 -0
  64. package/templates/codex/skills/references/functions/brain.md +275 -0
  65. package/templates/codex/skills/references/functions/clean.md +154 -0
  66. package/templates/codex/skills/references/functions/commit.md +265 -0
  67. package/templates/codex/skills/references/functions/debug/condition-based-waiting.md +151 -0
  68. package/templates/codex/skills/references/functions/debug/defense-in-depth.md +147 -0
  69. package/templates/codex/skills/references/functions/debug/root-cause-tracing.md +168 -0
  70. package/templates/codex/skills/references/functions/debug.md +389 -0
  71. package/templates/codex/skills/references/functions/exec.md +153 -0
  72. package/templates/codex/skills/references/functions/help.md +101 -0
  73. package/templates/codex/skills/references/functions/init.md +221 -0
  74. package/templates/codex/skills/references/functions/plan.md +178 -0
  75. package/templates/codex/skills/references/functions/review.md +135 -0
  76. package/templates/codex/skills/references/functions/rlm.md +864 -0
  77. package/templates/codex/skills/references/functions/rollback.md +190 -0
  78. package/templates/codex/skills/references/functions/test.md +140 -0
  79. package/templates/codex/skills/references/functions/upgrade.md +363 -0
  80. package/templates/codex/skills/references/functions/validate.md +135 -0
  81. package/templates/codex/skills/references/rules/cache.md +136 -0
  82. package/templates/codex/skills/references/rules/scaling.md +124 -0
  83. package/templates/codex/skills/references/rules/state.md +201 -0
  84. package/templates/codex/skills/references/rules/tools.md +301 -0
  85. package/templates/codex/skills/references/services/attention.md +53 -0
  86. package/templates/codex/skills/references/services/knowledge.md +559 -0
  87. package/templates/codex/skills/references/services/package.md +383 -0
  88. package/templates/codex/skills/references/services/templates.md +390 -0
  89. package/templates/codex/skills/references/stages/analyze.md +191 -0
  90. package/templates/codex/skills/references/stages/design.md +355 -0
  91. package/templates/codex/skills/references/stages/develop.md +520 -0
  92. package/templates/codex/skills/references/stages/tweak.md +239 -0
  93. package/templates/codex/skills/rlm/__init__.py +39 -0
  94. package/templates/codex/skills/rlm/agent_orchestrator.py +422 -0
  95. package/templates/codex/skills/rlm/context_manager.py +366 -0
  96. package/templates/codex/skills/rlm/engine.py +915 -0
  97. package/templates/codex/skills/rlm/folding.py +391 -0
  98. package/templates/codex/skills/rlm/repl.py +452 -0
  99. package/templates/codex/skills/rlm/roles/analyzer.md +66 -0
  100. package/templates/codex/skills/rlm/roles/designer.md +94 -0
  101. package/templates/codex/skills/rlm/roles/explorer.md +43 -0
  102. package/templates/codex/skills/rlm/roles/implementer.md +62 -0
  103. package/templates/codex/skills/rlm/roles/kb_keeper.md +138 -0
  104. package/templates/codex/skills/rlm/roles/pkg_keeper.md +163 -0
  105. package/templates/codex/skills/rlm/roles/reviewer.md +74 -0
  106. package/templates/codex/skills/rlm/roles/synthesizer.md +90 -0
  107. package/templates/codex/skills/rlm/roles/tester.md +83 -0
  108. package/templates/codex/skills/rlm/schemas/agent_result.json +174 -0
  109. package/templates/codex/skills/rlm/session.py +376 -0
  110. package/templates/codex/skills/rlm/shared_tasks.py +370 -0
  111. package/templates/codex/skills/scripts/create_package.py +260 -0
  112. package/templates/codex/skills/scripts/list_packages.py +145 -0
  113. package/templates/codex/skills/scripts/migrate_package.py +399 -0
  114. package/templates/codex/skills/scripts/project_stats.py +438 -0
  115. package/templates/codex/skills/scripts/upgradewiki.py +321 -0
  116. package/templates/codex/skills/scripts/utils.py +596 -0
  117. package/templates/codex/skills/scripts/validate_package.py +309 -0
@@ -0,0 +1,174 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://helloagents.dev/schemas/agent_result.json",
4
+ "title": "AgentResult",
5
+ "description": "RLM 子代理执行结果的标准格式",
6
+ "type": "object",
7
+ "required": ["status", "key_findings"],
8
+ "properties": {
9
+ "status": {
10
+ "type": "string",
11
+ "enum": ["completed", "failed", "partial", "in_progress"],
12
+ "description": "代理执行状态"
13
+ },
14
+ "key_findings": {
15
+ "type": "array",
16
+ "items": {
17
+ "type": "string"
18
+ },
19
+ "minItems": 1,
20
+ "description": "关键发现列表,至少包含1条"
21
+ },
22
+ "changes_made": {
23
+ "type": "array",
24
+ "items": {
25
+ "type": "object",
26
+ "required": ["file", "type", "description"],
27
+ "properties": {
28
+ "file": {
29
+ "type": "string",
30
+ "description": "文件路径"
31
+ },
32
+ "type": {
33
+ "type": "string",
34
+ "enum": ["create", "modify", "delete"],
35
+ "description": "变更类型"
36
+ },
37
+ "description": {
38
+ "type": "string",
39
+ "description": "变更描述"
40
+ }
41
+ }
42
+ },
43
+ "description": "文件变更记录"
44
+ },
45
+ "issues_found": {
46
+ "type": "array",
47
+ "items": {
48
+ "type": "object",
49
+ "required": ["severity", "description"],
50
+ "properties": {
51
+ "severity": {
52
+ "type": "string",
53
+ "enum": ["high", "medium", "low"],
54
+ "description": "问题严重程度"
55
+ },
56
+ "description": {
57
+ "type": "string",
58
+ "description": "问题描述"
59
+ },
60
+ "location": {
61
+ "type": "string",
62
+ "description": "问题位置(文件:行号)"
63
+ },
64
+ "suggestion": {
65
+ "type": "string",
66
+ "description": "修复建议"
67
+ }
68
+ }
69
+ },
70
+ "description": "发现的问题列表"
71
+ },
72
+ "recommendations": {
73
+ "type": "array",
74
+ "items": {
75
+ "type": "string"
76
+ },
77
+ "description": "后续建议列表"
78
+ },
79
+ "needs_followup": {
80
+ "type": "boolean",
81
+ "default": false,
82
+ "description": "是否需要后续跟进"
83
+ },
84
+ "metadata": {
85
+ "type": "object",
86
+ "properties": {
87
+ "agent_id": {
88
+ "type": "string",
89
+ "description": "代理唯一标识"
90
+ },
91
+ "role": {
92
+ "type": "string",
93
+ "description": "代理角色"
94
+ },
95
+ "depth": {
96
+ "type": "integer",
97
+ "minimum": 0,
98
+ "maximum": 5,
99
+ "description": "递归深度"
100
+ },
101
+ "parent_id": {
102
+ "type": "string",
103
+ "description": "父代理ID"
104
+ },
105
+ "start_time": {
106
+ "type": "string",
107
+ "format": "date-time",
108
+ "description": "开始时间"
109
+ },
110
+ "end_time": {
111
+ "type": "string",
112
+ "format": "date-time",
113
+ "description": "结束时间"
114
+ },
115
+ "token_usage": {
116
+ "type": "object",
117
+ "properties": {
118
+ "input": {
119
+ "type": "integer",
120
+ "description": "输入token数"
121
+ },
122
+ "output": {
123
+ "type": "integer",
124
+ "description": "输出token数"
125
+ }
126
+ }
127
+ }
128
+ },
129
+ "description": "执行元数据"
130
+ }
131
+ },
132
+ "examples": [
133
+ {
134
+ "status": "completed",
135
+ "key_findings": [
136
+ "项目采用模块化架构,共有12个核心模块",
137
+ "发现3处潜在的性能瓶颈",
138
+ "测试覆盖率为78%"
139
+ ],
140
+ "changes_made": [
141
+ {
142
+ "file": "src/api/routes.py",
143
+ "type": "modify",
144
+ "description": "优化了数据库查询逻辑"
145
+ }
146
+ ],
147
+ "issues_found": [
148
+ {
149
+ "severity": "medium",
150
+ "description": "缺少输入验证",
151
+ "location": "src/api/routes.py:45",
152
+ "suggestion": "添加参数验证装饰器"
153
+ }
154
+ ],
155
+ "recommendations": [
156
+ "建议添加缓存层提升性能",
157
+ "考虑将大型函数拆分为更小的单元"
158
+ ],
159
+ "needs_followup": false,
160
+ "metadata": {
161
+ "agent_id": "agent_001",
162
+ "role": "analyzer",
163
+ "depth": 1,
164
+ "parent_id": "root",
165
+ "start_time": "2026-01-23T10:00:00Z",
166
+ "end_time": "2026-01-23T10:05:00Z",
167
+ "token_usage": {
168
+ "input": 2500,
169
+ "output": 800
170
+ }
171
+ }
172
+ }
173
+ ]
174
+ }
@@ -0,0 +1,376 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ HelloAGENTS-RLM Session Manager
5
+ Session 隔离管理器 - 解决多 CLI 并发问题
6
+
7
+ 核心设计:
8
+ - 每个 AI CLI 实例有唯一的 Session ID
9
+ - Session 数据存储在临时目录,不会污染知识库
10
+ - 支持 Session 恢复和清理
11
+ """
12
+
13
+ import json
14
+ import os
15
+ import tempfile
16
+ import uuid
17
+ from datetime import datetime
18
+ from pathlib import Path
19
+ from typing import Any, Dict, List, Optional
20
+
21
+
22
+ class SessionManager:
23
+ """
24
+ Session 隔离管理器
25
+
26
+ 解决问题: 多个 AI CLI 并行工作时的上下文污染
27
+
28
+ 设计原则:
29
+ - Working Context: 在 AI CLI 内存中,不持久化
30
+ - Session Events: 持久化到 session 专属目录
31
+ - Memory: 使用共享知识库
32
+ """
33
+
34
+ # Session 根目录
35
+ SESSION_ROOT = Path(tempfile.gettempdir()) / "helloagents_rlm"
36
+
37
+ def __init__(self, session_id: Optional[str] = None):
38
+ """
39
+ 初始化 Session
40
+
41
+ Args:
42
+ session_id: 可选的 Session ID,不提供则生成新的
43
+ """
44
+ # 优先从环境变量获取 (支持 CLI 传递)
45
+ self.session_id = (
46
+ session_id or
47
+ os.environ.get("HELLOAGENTS_SESSION_ID") or
48
+ self._generate_session_id()
49
+ )
50
+
51
+ # Session 目录
52
+ self.session_dir = self.SESSION_ROOT / self.session_id
53
+ self.session_dir.mkdir(parents=True, exist_ok=True)
54
+
55
+ # Session 文件
56
+ self.events_file = self.session_dir / "events.jsonl"
57
+ self.state_file = self.session_dir / "state.json"
58
+ self.metadata_file = self.session_dir / "metadata.json"
59
+
60
+ # 初始化 metadata
61
+ if not self.metadata_file.exists():
62
+ self._init_metadata()
63
+
64
+ def _generate_session_id(self) -> str:
65
+ """生成唯一 Session ID"""
66
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
67
+ short_uuid = str(uuid.uuid4())[:8]
68
+ return f"session_{timestamp}_{short_uuid}"
69
+
70
+ def _init_metadata(self):
71
+ """初始化 Session 元数据"""
72
+ metadata = {
73
+ "session_id": self.session_id,
74
+ "created_at": datetime.now().isoformat(),
75
+ "last_active": datetime.now().isoformat(),
76
+ "rlm_version": "1.0.0",
77
+ "agent_history": [],
78
+ "total_events": 0,
79
+ }
80
+ self.metadata_file.write_text(
81
+ json.dumps(metadata, ensure_ascii=False, indent=2),
82
+ encoding='utf-8'
83
+ )
84
+
85
+ # ==================== Event 管理 ====================
86
+
87
+ def log_event(self, event_type: str, data: Dict[str, Any]) -> bool:
88
+ """
89
+ 记录事件到 Session
90
+
91
+ Args:
92
+ event_type: 事件类型 (spawn_agent, fold, tool_call, etc.)
93
+ data: 事件数据
94
+ """
95
+ event = {
96
+ "timestamp": datetime.now().isoformat(),
97
+ "type": event_type,
98
+ "data": data,
99
+ }
100
+
101
+ try:
102
+ with open(self.events_file, 'a', encoding='utf-8') as f:
103
+ f.write(json.dumps(event, ensure_ascii=False) + '\n')
104
+
105
+ # 更新 metadata
106
+ self._update_metadata("total_events", lambda x: (x or 0) + 1)
107
+ return True
108
+ except Exception:
109
+ return False
110
+
111
+ def get_events(
112
+ self,
113
+ event_type: Optional[str] = None,
114
+ limit: Optional[int] = None,
115
+ ) -> List[Dict[str, Any]]:
116
+ """获取事件列表"""
117
+ if not self.events_file.exists():
118
+ return []
119
+
120
+ events = []
121
+ try:
122
+ with open(self.events_file, 'r', encoding='utf-8') as f:
123
+ for line in f:
124
+ if line.strip():
125
+ event = json.loads(line)
126
+ if event_type is None or event.get("type") == event_type:
127
+ events.append(event)
128
+ except Exception:
129
+ return []
130
+
131
+ if limit:
132
+ events = events[-limit:]
133
+
134
+ return events
135
+
136
+ def get_recent_events_summary(self, count: int = 10) -> str:
137
+ """获取最近事件摘要 (用于折叠后传递)"""
138
+ events = self.get_events(limit=count)
139
+ if not events:
140
+ return "无最近事件"
141
+
142
+ lines = []
143
+ for e in events:
144
+ event_type = e.get("type", "unknown")
145
+ timestamp = e.get("timestamp", "")[:19] # 截断到秒
146
+ data = e.get("data", {})
147
+
148
+ if event_type == "spawn_agent":
149
+ lines.append(f"- [{timestamp}] spawn: {data.get('role', '?')} - {data.get('task', '?')[:50]}")
150
+ elif event_type == "fold":
151
+ lines.append(f"- [{timestamp}] fold: {data.get('strategy', '?')}")
152
+ elif event_type == "tool_call":
153
+ lines.append(f"- [{timestamp}] tool: {data.get('tool', '?')}")
154
+ else:
155
+ lines.append(f"- [{timestamp}] {event_type}")
156
+
157
+ return '\n'.join(lines)
158
+
159
+ # ==================== State 管理 ====================
160
+
161
+ def save_state(self, state: Dict[str, Any]) -> bool:
162
+ """保存 RLM 状态"""
163
+ try:
164
+ state["last_updated"] = datetime.now().isoformat()
165
+ self.state_file.write_text(
166
+ json.dumps(state, ensure_ascii=False, indent=2),
167
+ encoding='utf-8'
168
+ )
169
+ self._update_metadata("last_active", datetime.now().isoformat())
170
+ return True
171
+ except Exception:
172
+ return False
173
+
174
+ def load_state(self) -> Optional[Dict[str, Any]]:
175
+ """加载 RLM 状态"""
176
+ if not self.state_file.exists():
177
+ return None
178
+
179
+ try:
180
+ return json.loads(self.state_file.read_text(encoding='utf-8'))
181
+ except Exception:
182
+ return None
183
+
184
+ # ==================== Agent 历史 ====================
185
+
186
+ def record_agent(
187
+ self,
188
+ agent_id: str,
189
+ role: str,
190
+ task: str,
191
+ status: str,
192
+ depth: int,
193
+ ) -> bool:
194
+ """记录代理执行历史"""
195
+ record = {
196
+ "agent_id": agent_id,
197
+ "role": role,
198
+ "task": task,
199
+ "status": status,
200
+ "depth": depth,
201
+ "timestamp": datetime.now().isoformat(),
202
+ }
203
+
204
+ # 记录事件
205
+ self.log_event("spawn_agent", record)
206
+
207
+ # 更新 metadata
208
+ try:
209
+ metadata = self._load_metadata()
210
+ if "agent_history" not in metadata:
211
+ metadata["agent_history"] = []
212
+ metadata["agent_history"].append(record)
213
+ # 只保留最近 50 条
214
+ metadata["agent_history"] = metadata["agent_history"][-50:]
215
+ self._save_metadata(metadata)
216
+ return True
217
+ except Exception:
218
+ return False
219
+
220
+ def get_agent_history(self, limit: int = 20) -> List[Dict[str, Any]]:
221
+ """获取代理执行历史"""
222
+ metadata = self._load_metadata()
223
+ history = metadata.get("agent_history", [])
224
+ return history[-limit:] if limit else history
225
+
226
+ # ==================== Metadata 操作 ====================
227
+
228
+ def _load_metadata(self) -> Dict[str, Any]:
229
+ """加载 metadata"""
230
+ if not self.metadata_file.exists():
231
+ return {}
232
+ try:
233
+ return json.loads(self.metadata_file.read_text(encoding='utf-8'))
234
+ except Exception:
235
+ return {}
236
+
237
+ def _save_metadata(self, metadata: Dict[str, Any]):
238
+ """保存 metadata"""
239
+ self.metadata_file.write_text(
240
+ json.dumps(metadata, ensure_ascii=False, indent=2),
241
+ encoding='utf-8'
242
+ )
243
+
244
+ def _update_metadata(self, key: str, value_or_func):
245
+ """更新 metadata 字段"""
246
+ metadata = self._load_metadata()
247
+ if callable(value_or_func):
248
+ metadata[key] = value_or_func(metadata.get(key))
249
+ else:
250
+ metadata[key] = value_or_func
251
+ self._save_metadata(metadata)
252
+
253
+ # ==================== Session 管理 ====================
254
+
255
+ def get_session_info(self) -> Dict[str, Any]:
256
+ """获取 Session 信息"""
257
+ metadata = self._load_metadata()
258
+ events_count = len(self.get_events())
259
+
260
+ return {
261
+ "session_id": self.session_id,
262
+ "session_dir": str(self.session_dir),
263
+ "created_at": metadata.get("created_at"),
264
+ "last_active": metadata.get("last_active"),
265
+ "total_events": events_count,
266
+ "agent_count": len(metadata.get("agent_history", [])),
267
+ }
268
+
269
+ def cleanup(self) -> bool:
270
+ """清理当前 Session"""
271
+ import shutil
272
+ try:
273
+ if self.session_dir.exists():
274
+ shutil.rmtree(self.session_dir)
275
+ return True
276
+ except Exception:
277
+ return False
278
+
279
+ @classmethod
280
+ def list_sessions(cls) -> List[Dict[str, Any]]:
281
+ """列出所有 Sessions"""
282
+ sessions = []
283
+ if not cls.SESSION_ROOT.exists():
284
+ return sessions
285
+
286
+ for session_dir in cls.SESSION_ROOT.iterdir():
287
+ if session_dir.is_dir() and session_dir.name.startswith("session_"):
288
+ metadata_file = session_dir / "metadata.json"
289
+ if metadata_file.exists():
290
+ try:
291
+ metadata = json.loads(metadata_file.read_text(encoding='utf-8'))
292
+ sessions.append({
293
+ "session_id": session_dir.name,
294
+ "created_at": metadata.get("created_at"),
295
+ "last_active": metadata.get("last_active"),
296
+ })
297
+ except Exception:
298
+ continue
299
+
300
+ # 按最后活跃时间排序
301
+ sessions.sort(key=lambda x: x.get("last_active", ""), reverse=True)
302
+ return sessions
303
+
304
+ @classmethod
305
+ def cleanup_old_sessions(cls, max_age_hours: int = 24) -> int:
306
+ """清理过期 Sessions"""
307
+ import shutil
308
+ from datetime import timedelta
309
+
310
+ cleaned = 0
311
+ cutoff = datetime.now() - timedelta(hours=max_age_hours)
312
+
313
+ for session_dir in cls.SESSION_ROOT.iterdir():
314
+ if session_dir.is_dir() and session_dir.name.startswith("session_"):
315
+ metadata_file = session_dir / "metadata.json"
316
+ try:
317
+ if metadata_file.exists():
318
+ metadata = json.loads(metadata_file.read_text(encoding='utf-8'))
319
+ last_active = datetime.fromisoformat(metadata.get("last_active", "2000-01-01"))
320
+ if last_active < cutoff:
321
+ shutil.rmtree(session_dir)
322
+ cleaned += 1
323
+ except Exception:
324
+ continue
325
+
326
+ return cleaned
327
+
328
+
329
+ # ==================== 便捷函数 ====================
330
+
331
+ def get_or_create_session(session_id: Optional[str] = None) -> SessionManager:
332
+ """获取或创建 Session"""
333
+ return SessionManager(session_id)
334
+
335
+
336
+ def get_current_session() -> SessionManager:
337
+ """获取当前 Session (从环境变量)"""
338
+ return SessionManager()
339
+
340
+
341
+ # ==================== CLI 入口 ====================
342
+
343
+ if __name__ == "__main__":
344
+ import argparse
345
+
346
+ parser = argparse.ArgumentParser(description="HelloAGENTS RLM Session Manager")
347
+ parser.add_argument("--new", action="store_true", help="创建新 Session")
348
+ parser.add_argument("--id", type=str, help="指定 Session ID")
349
+ parser.add_argument("--info", action="store_true", help="显示 Session 信息")
350
+ parser.add_argument("--list", action="store_true", help="列出所有 Sessions")
351
+ parser.add_argument("--cleanup", type=int, help="清理超过 N 小时的 Sessions")
352
+ parser.add_argument("--events", type=int, help="显示最近 N 条事件")
353
+ parser.add_argument("--history", type=int, help="显示最近 N 条代理历史")
354
+
355
+ args = parser.parse_args()
356
+
357
+ if args.list:
358
+ sessions = SessionManager.list_sessions()
359
+ print(json.dumps(sessions, ensure_ascii=False, indent=2))
360
+ elif args.cleanup:
361
+ cleaned = SessionManager.cleanup_old_sessions(args.cleanup)
362
+ print(json.dumps({"cleaned_sessions": cleaned}, ensure_ascii=False))
363
+ else:
364
+ session = SessionManager(args.id if not args.new else None)
365
+
366
+ if args.info:
367
+ print(json.dumps(session.get_session_info(), ensure_ascii=False, indent=2))
368
+ elif args.events:
369
+ events = session.get_events(limit=args.events)
370
+ print(json.dumps(events, ensure_ascii=False, indent=2))
371
+ elif args.history:
372
+ history = session.get_agent_history(limit=args.history)
373
+ print(json.dumps(history, ensure_ascii=False, indent=2))
374
+ else:
375
+ # 默认输出 Session ID (方便其他脚本使用)
376
+ print(session.session_id)