beswarm 0.2.87__tar.gz → 0.2.89__tar.gz

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 (137) hide show
  1. {beswarm-0.2.87 → beswarm-0.2.89}/PKG-INFO +1 -1
  2. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/agents/planact.py +4 -4
  3. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/taskmanager.py +11 -4
  4. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/subtasks.py +57 -29
  5. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm.egg-info/PKG-INFO +1 -1
  6. {beswarm-0.2.87 → beswarm-0.2.89}/pyproject.toml +1 -1
  7. {beswarm-0.2.87 → beswarm-0.2.89}/MANIFEST.in +0 -0
  8. {beswarm-0.2.87 → beswarm-0.2.89}/README.md +0 -0
  9. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/__init__.py +0 -0
  10. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/agents/chatgroup.py +0 -0
  11. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/__init__.py +0 -0
  12. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/architext/architext/__init__.py +0 -0
  13. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/architext/architext/core.py +0 -0
  14. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/architext/test/openai_client.py +0 -0
  15. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/architext/test/test.py +0 -0
  16. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/architext/test/test_save_load.py +0 -0
  17. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/__init__.py +0 -0
  18. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/log_config.py +0 -0
  19. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/models.py +0 -0
  20. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/request.py +0 -0
  21. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/response.py +0 -0
  22. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/test/test_base_api.py +0 -0
  23. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/test/test_geminimask.py +0 -0
  24. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/test/test_image.py +0 -0
  25. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/test/test_payload.py +0 -0
  26. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/core/utils.py +0 -0
  27. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/models/__init__.py +0 -0
  28. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/models/audio.py +0 -0
  29. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/models/base.py +0 -0
  30. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/models/chatgpt.py +0 -0
  31. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/__init__.py +0 -0
  32. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/arXiv.py +0 -0
  33. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/config.py +0 -0
  34. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/excute_command.py +0 -0
  35. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/get_time.py +0 -0
  36. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/image.py +0 -0
  37. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/list_directory.py +0 -0
  38. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/read_file.py +0 -0
  39. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/read_image.py +0 -0
  40. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/readonly.py +0 -0
  41. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/registry.py +0 -0
  42. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/run_python.py +0 -0
  43. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/websearch.py +0 -0
  44. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/plugins/write_file.py +0 -0
  45. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/utils/__init__.py +0 -0
  46. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/utils/prompt.py +0 -0
  47. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/aient/utils/scripts.py +0 -0
  48. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_Web_crawler.py +0 -0
  49. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_ddg_search.py +0 -0
  50. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_google_search.py +0 -0
  51. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_ollama.py +0 -0
  52. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_plugin.py +0 -0
  53. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_search.py +0 -0
  54. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_url.py +0 -0
  55. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_whisper.py +0 -0
  56. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/aient/test/test_yjh.py +0 -0
  57. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/bemcp/bemcp/__init__.py +0 -0
  58. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/bemcp/bemcp/decorator.py +0 -0
  59. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/bemcp/bemcp/main.py +0 -0
  60. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/bemcp/bemcp/utils.py +0 -0
  61. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/bemcp/test/client.py +0 -0
  62. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/bemcp/test/server.py +0 -0
  63. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/broker.py +0 -0
  64. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/core.py +0 -0
  65. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/knowledge_graph.py +0 -0
  66. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/prompt.py +0 -0
  67. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/README.md +0 -0
  68. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/arduino-tags.scm +0 -0
  69. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/c-tags.scm +0 -0
  70. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/chatito-tags.scm +0 -0
  71. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -0
  72. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/cpp-tags.scm +0 -0
  73. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/csharp-tags.scm +0 -0
  74. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/d-tags.scm +0 -0
  75. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/dart-tags.scm +0 -0
  76. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/elisp-tags.scm +0 -0
  77. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/elixir-tags.scm +0 -0
  78. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/elm-tags.scm +0 -0
  79. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/gleam-tags.scm +0 -0
  80. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/go-tags.scm +0 -0
  81. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/java-tags.scm +0 -0
  82. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/javascript-tags.scm +0 -0
  83. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/lua-tags.scm +0 -0
  84. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/pony-tags.scm +0 -0
  85. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/properties-tags.scm +0 -0
  86. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/python-tags.scm +0 -0
  87. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/r-tags.scm +0 -0
  88. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/racket-tags.scm +0 -0
  89. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/ruby-tags.scm +0 -0
  90. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/rust-tags.scm +0 -0
  91. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/solidity-tags.scm +0 -0
  92. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/swift-tags.scm +0 -0
  93. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-language-pack/udev-tags.scm +0 -0
  94. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/README.md +0 -0
  95. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/c-tags.scm +0 -0
  96. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
  97. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/cpp-tags.scm +0 -0
  98. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/dart-tags.scm +0 -0
  99. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/elisp-tags.scm +0 -0
  100. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/elixir-tags.scm +0 -0
  101. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/elm-tags.scm +0 -0
  102. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/go-tags.scm +0 -0
  103. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/hcl-tags.scm +0 -0
  104. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/java-tags.scm +0 -0
  105. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/javascript-tags.scm +0 -0
  106. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
  107. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
  108. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/php-tags.scm +0 -0
  109. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/python-tags.scm +0 -0
  110. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/ql-tags.scm +0 -0
  111. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/ruby-tags.scm +0 -0
  112. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/rust-tags.scm +0 -0
  113. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/scala-tags.scm +0 -0
  114. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/queries/tree-sitter-languages/typescript-tags.scm +0 -0
  115. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/__init__.py +0 -0
  116. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/click.py +0 -0
  117. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/completion.py +0 -0
  118. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/edit_file.py +0 -0
  119. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/graph.py +0 -0
  120. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/planner.py +0 -0
  121. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/repomap.py +0 -0
  122. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/request_input.py +0 -0
  123. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/screenshot.py +0 -0
  124. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/search_arxiv.py +0 -0
  125. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/search_web.py +0 -0
  126. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/worker.py +0 -0
  127. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/tools/write_csv.py +0 -0
  128. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm/utils.py +0 -0
  129. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm.egg-info/SOURCES.txt +0 -0
  130. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm.egg-info/dependency_links.txt +0 -0
  131. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm.egg-info/requires.txt +0 -0
  132. {beswarm-0.2.87 → beswarm-0.2.89}/beswarm.egg-info/top_level.txt +0 -0
  133. {beswarm-0.2.87 → beswarm-0.2.89}/setup.cfg +0 -0
  134. {beswarm-0.2.87 → beswarm-0.2.89}/test/test_TaskManager.py +0 -0
  135. {beswarm-0.2.87 → beswarm-0.2.89}/test/test_broker.py +0 -0
  136. {beswarm-0.2.87 → beswarm-0.2.89}/test/test_graph.py +0 -0
  137. {beswarm-0.2.87 → beswarm-0.2.89}/test/test_new_TaskManager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beswarm
3
- Version: 0.2.87
3
+ Version: 0.2.89
4
4
  Summary: MAS
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -226,12 +226,10 @@ class BrokerWorker:
226
226
  self.WORKER_RESPONSE_TOPIC = self.channel + ".worker_responses"
227
227
  self.TASK_STATUS_TOPIC =self.channel + ".task_status"
228
228
 
229
- self.setup()
230
-
231
- def setup(self):
229
+ async def setup(self):
232
230
  cache_dir = self.work_dir / ".beswarm"
233
231
  cache_dir.mkdir(parents=True, exist_ok=True)
234
- self.task_manager.set_root_path(self.work_dir)
232
+ await self.task_manager.set_root_path(self.work_dir)
235
233
  self.kgm.set_root_path(self.work_dir)
236
234
  self.cache_file = cache_dir / "work_agent_conversation_history.json"
237
235
  if not self.cache_file.exists():
@@ -308,6 +306,7 @@ class BrokerWorker:
308
306
 
309
307
  async def run(self):
310
308
  """Sets up subscriptions and starts the workflow."""
309
+ await self.setup()
311
310
  os.chdir(self.work_dir.absolute())
312
311
  await self._configure_tools()
313
312
 
@@ -326,6 +325,7 @@ class BrokerWorker:
326
325
 
327
326
  async def stream_run(self):
328
327
  """Runs the workflow and yields status messages."""
328
+ await self.setup()
329
329
  os.chdir(self.work_dir.absolute())
330
330
  await self._configure_tools()
331
331
 
@@ -30,6 +30,7 @@ class TaskManager:
30
30
  raise ValueError("并发限制必须大于0")
31
31
 
32
32
  self.tasks_cache = {} # 存储所有任务的状态和元数据, key: task_id
33
+ self.task_events = {} # 为每个任务存储一个asyncio.Event,用于等待特定任务完成
33
34
 
34
35
  self._pending_queue = asyncio.Queue() # 内部待办任务队列
35
36
  self._results_queue = asyncio.Queue() # 内部已完成任务结果队列
@@ -39,7 +40,7 @@ class TaskManager:
39
40
  self.cache_dir = None
40
41
  self.task_cache_file = None
41
42
 
42
- def set_root_path(self, root_path):
43
+ async def set_root_path(self, root_path):
43
44
  """设置工作根目录并加载持久化的任务状态。"""
44
45
  if self.root_path is not None:
45
46
  return
@@ -57,7 +58,7 @@ class TaskManager:
57
58
  # 启动工作者池
58
59
  self.start()
59
60
  # 恢复中断的任务
60
- self.resume_interrupted_tasks()
61
+ await self.resume_interrupted_tasks()
61
62
 
62
63
  def start(self):
63
64
  """启动并发工作者池。"""
@@ -118,6 +119,8 @@ class TaskManager:
118
119
 
119
120
  self._update_task_status(task_id, status, result=str(result))
120
121
  self._results_queue.put_nowait((task_id, status, result))
122
+ if task_id in self.task_events:
123
+ self.task_events[task_id].set()
121
124
 
122
125
  def set_task_cache(self, *keys_and_value):
123
126
  """设置可嵌套的任务缓存。"""
@@ -167,6 +170,7 @@ class TaskManager:
167
170
  task_ids = []
168
171
  for params in tasks_params_list:
169
172
  task_id = str(uuid.uuid4())
173
+ self.task_events[task_id] = asyncio.Event()
170
174
  coro = task_coro_func(**params)
171
175
 
172
176
  # 初始化任务状态为 PENDING
@@ -187,6 +191,7 @@ class TaskManager:
187
191
  task_ids = []
188
192
  for params in tasks_params_list:
189
193
  task_id = str(uuid.uuid4())
194
+ self.task_events[task_id] = asyncio.Event()
190
195
  coro = task_coro_func(**params)
191
196
 
192
197
  self._update_task_status(task_id, TaskStatus.PENDING, args=params)
@@ -196,7 +201,7 @@ class TaskManager:
196
201
  print(f"已将 {len(task_ids)} 个新任务加入待处理队列。队列当前大小: {self._pending_queue.qsize()}")
197
202
  return task_ids
198
203
 
199
- def resume_interrupted_tasks(self):
204
+ async def resume_interrupted_tasks(self):
200
205
  """在启动时,恢复所有处于 PENDING 或 RUNNING 状态的旧任务。"""
201
206
  interrupted_tasks = [
202
207
  (tid, info) for tid, info in self.tasks_cache.items()
@@ -210,6 +215,7 @@ class TaskManager:
210
215
  worker_fun = registry.tools["worker"]
211
216
 
212
217
  for task_id, task_info in interrupted_tasks:
218
+ self.task_events[task_id] = asyncio.Event()
213
219
  args = task_info.get("args")
214
220
  if not args:
215
221
  print(f"警告:任务 <{task_id[:8]}> 缺少参数,无法恢复。")
@@ -218,7 +224,7 @@ class TaskManager:
218
224
 
219
225
  coro = worker_fun(**args)
220
226
  self._update_task_status(task_id, TaskStatus.PENDING)
221
- self._pending_queue.put_nowait((task_id, coro))
227
+ await self._pending_queue.put((task_id, coro))
222
228
 
223
229
  print(f"{len(interrupted_tasks)} 个中断的任务已重新加入队列。")
224
230
 
@@ -238,6 +244,7 @@ class TaskManager:
238
244
  worker_fun = registry.tools["worker"]
239
245
  coro = worker_fun(**tasks_params)
240
246
 
247
+ self.task_events[task_id] = asyncio.Event()
241
248
  self._update_task_status(task_id, TaskStatus.PENDING, args=tasks_params)
242
249
  self._pending_queue.put_nowait((task_id, coro))
243
250
 
@@ -30,7 +30,7 @@ def create_task(goal, tools, work_dir):
30
30
  if task_id == "root_path":
31
31
  continue
32
32
  if task_info.get("args", {}).get("work_dir") == work_dir:
33
- return f"<tool_error>工作目录 '{work_dir}' 已被任务 {task_id} 使用。请为子任务选择一个唯一的工作目录。</tool_error>"
33
+ return f"<tool_error>工作目录 '{work_dir}' 已被任务 {task_id} 使用。请为子任务重新选择一个唯一的工作目录。</tool_error>"
34
34
 
35
35
  # 获取 worker 函数,这是正确的
36
36
  worker_fun = registry.tools["worker"]
@@ -71,74 +71,102 @@ def resume_task(task_id, goal):
71
71
  @register_tool()
72
72
  def get_all_tasks_status():
73
73
  """
74
- 获取所有任务的状态。
75
- 子任务状态会持久化到磁盘,因此即使历史记录为空,之前的子任务仍然存在。
74
+ 立即获取并返回所有任务的当前状态快照。
75
+ 此函数不会等待,它会立刻返回一个包含所有已知任务(包括已完成、正在运行和待处理的)信息的字典。
76
+ **警告:** 此工具会返回所有任务的完整信息,可能导致大量的token消耗。
77
+ 如果需要等待任务完成,请使用 `get_task_result()`。仅在需要对所有任务进行全面概览或调试时才应使用此工具。
76
78
 
77
79
  Returns:
78
- str: 所有任务的状态。每个任务的id,状态,结果。
80
+ dict: 包含所有任务当前状态的字典。
79
81
  """
80
82
  task_manager = current_task_manager.get()
81
83
  return task_manager.tasks_cache
82
84
 
83
85
  @register_tool()
84
- async def get_task_result(reduce: bool = False):
86
+ async def get_task_result(task_id: str = None, reduce: bool = False):
85
87
  """
86
- 等待并获取子任务的执行结果。
88
+ 等待并获取一个或多个子任务的执行结果。
87
89
 
88
- 如果 `reduce` 为 `False`(默认),此工具会等待并返回任何一个子任务完成的结果。
89
- 一旦有任务完成,它会立即获取并返回该任务的结果。如果调用时没有任务完成,它会阻塞并等待。
90
+ 此工具有多种操作模式,**推荐使用默认模式**。
90
91
 
91
- 如果 `reduce` 为 `True`,此工具会进入“规约”模式,等待 **所有** 正在运行或待处理的子任务都执行完毕后,
92
- 才将所有任务的结果汇总并返回。这在子任务之间无依赖、可以完全并行执行的场景下非常有用,
93
- 可以避免为了获取每个任务的结果而进行多次轮询,从而节省token。
92
+ 1. **等待并获取下一个完成的任务(推荐的标准方法)**:
93
+ 在不提供 `task_id` 且 `reduce=False` 的情况下,此工具会异步等待,直到队列中有任何一个子任务完成,然后返回该任务的结果。
94
+ 这是处理子任务最常用的模式,它允许你以事件驱动的方式、按完成顺序处理结果。
94
95
 
95
- 警告:当子任务之间存在依赖关系,或者需要根据一个任务的结果来决定下一步操作时,**禁止** 使用 `reduce=True`。
96
+ 2. **获取特定任务的结果(特殊需求)**:
97
+ 仅当你需要等待一个 *特定* 子任务时,才提供 `task_id` 参数。工具将专门等待该ID的任务完成并返回其结果。
98
+ 如果任务已经完成,结果会立即返回。
99
+
100
+ 3. **规约模式(等待所有任务)**:
101
+ 设置 `reduce=True` 会使工具等待 **所有** 正在运行或待处理的任务都完成后,才一次性返回所有结果的摘要。
102
+ **警告:** 仅在子任务间完全独立、可以并行执行时使用此模式。当使用此模式时,不应提供 `task_id`。
96
103
 
97
104
  Args:
98
- reduce (bool, optional): 是否启用规约模式。默认为 `False`。
105
+ task_id (str, optional): 要获取结果的特定任务的ID。仅在需要等待特定任务时使用。
106
+ reduce (bool, optional): 是否等待所有任务完成后再汇总返回。默认为 `False`。
99
107
 
100
108
  Returns:
101
- str:
102
- - 当 `reduce=False` 时,返回单个子任务的执行结果。
103
- - 当 `reduce=True` 时,返回一个包含所有任务最终状态和结果的汇总字符串。
109
+ str: 任务的执行结果或结果摘要。
104
110
  """
105
111
  task_manager = current_task_manager.get()
112
+
113
+ if task_id and reduce:
114
+ return "<tool_error>无效的参数组合:不能同时提供 `task_id` 和设置 `reduce=True`。</tool_error>"
115
+
106
116
  def get_running_tasks_count():
107
117
  return len([
108
- task_id for task_id, task in task_manager.tasks_cache.items()
109
- if task_id != "root_path" and task.get("status") in ["PENDING", "RUNNING"]
118
+ tid for tid, task in task_manager.tasks_cache.items()
119
+ if tid != "root_path" and task.get("status") in ["PENDING", "RUNNING"]
110
120
  ])
111
121
 
122
+ if task_id:
123
+ # 模式1:等待并获取指定任务的结果
124
+ if task_id not in task_manager.tasks_cache:
125
+ return f"<tool_error>任务ID '{task_id}' 不存在。</tool_error>"
126
+
127
+ # 如果任务已经完成,直接返回结果
128
+ task_info = task_manager.tasks_cache[task_id]
129
+ if task_info.get("status") in ["DONE", "ERROR"]:
130
+ return f"Task ID: {task_id}\nStatus: {task_info['status']}\nResult: {task_info.get('result', 'N/A')}"
131
+
132
+ # 如果任务未完成,等待事件
133
+ event = task_manager.task_events.get(task_id)
134
+ if event:
135
+ await event.wait()
136
+ # 事件触发后,再次获取最新状态
137
+ task_info = task_manager.tasks_cache[task_id]
138
+ return f"Task ID: {task_id}\nStatus: {task_info['status']}\nResult: {task_info.get('result', 'N/A')}"
139
+ else:
140
+ return f"<tool_error>任务 '{task_id}' 的事件不存在,可能是一个旧任务或状态已损坏。</tool_error>"
141
+
142
+ # 检查是否还有正在运行的任务
112
143
  if get_running_tasks_count() == 0:
113
144
  return "All tasks are finished."
114
145
 
115
146
  if not reduce:
116
- # 默认行为:获取下一个完成的任务结果
117
- task_id, status, result = await task_manager.get_next_result()
118
-
147
+ # 模式2:获取下一个完成的任务结果
148
+ next_task_id, status, result = await task_manager.get_next_result()
119
149
  unfinished_tasks = [tid for tid, task in task_manager.tasks_cache.items() if tid != "root_path" and task.get("status") not in ["DONE", "ERROR"]]
120
150
  text = "".join([
121
- f"Task ID: {task_id}\n",
151
+ f"Task ID: {next_task_id}\n",
122
152
  f"Status: {status.value}\n",
123
153
  f"Result: {result}\n\n",
124
- f"There are {len(unfinished_tasks)} unfinished tasks, unfinished task ids: {unfinished_tasks[:5]} ..." if unfinished_tasks else "All tasks are finished.",
154
+ f"There are {len(unfinished_tasks)} unfinished tasks, unfinished task ids: {unfinished_tasks[0]}" if unfinished_tasks else "All tasks are finished.",
125
155
  ])
126
156
  return text
127
157
  else:
128
- # 规约模式:等待所有任务完成
158
+ # 模式3:规约模式 - 等待所有任务完成
129
159
  while get_running_tasks_count() > 0:
130
160
  await task_manager.get_next_result()
131
161
 
132
- # 收集所有任务的结果
133
162
  all_results = []
134
- for task_id, task in task_manager.tasks_cache.items():
135
- if task_id == "root_path":
163
+ for tid, task in task_manager.tasks_cache.items():
164
+ if tid == "root_path":
136
165
  continue
137
-
138
166
  status = task.get('status', 'UNKNOWN')
139
167
  result = task.get('result', 'No result available')
140
168
  all_results.append(
141
- f"Task ID: {task_id}\nStatus: {status}\nResult: {result}"
169
+ f"Task ID: {tid}\nStatus: {status}\nResult: {result}"
142
170
  )
143
171
 
144
172
  summary = f"All {len(all_results)} subtasks have been completed.\n\n"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beswarm
3
- Version: 0.2.87
3
+ Version: 0.2.89
4
4
  Summary: MAS
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "beswarm"
3
- version = "0.2.87"
3
+ version = "0.2.89"
4
4
  description = "MAS"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes