beswarm 0.2.37__tar.gz → 0.2.39__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.
Potentially problematic release.
This version of beswarm might be problematic. Click here for more details.
- {beswarm-0.2.37 → beswarm-0.2.39}/PKG-INFO +1 -1
- beswarm-0.2.39/beswarm/agents/chatgroup.py +275 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/agents/planact.py +7 -3
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/__init__.py +2 -1
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/worker.py +13 -1
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm.egg-info/PKG-INFO +1 -1
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm.egg-info/SOURCES.txt +1 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/pyproject.toml +1 -1
- {beswarm-0.2.37 → beswarm-0.2.39}/MANIFEST.in +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/README.md +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/__init__.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/main.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/setup.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/__init__.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/__init__.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/log_config.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/models.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/request.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/response.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/test/test_base_api.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/test/test_geminimask.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/test/test_image.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/test/test_payload.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/core/utils.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/__init__.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/audio.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/base.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/chatgpt.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/claude.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/duckduckgo.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/gemini.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/groq.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/models/vertex.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/__init__.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/arXiv.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/config.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/excute_command.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/get_time.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/image.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/list_directory.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/read_file.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/read_image.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/readonly.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/registry.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/run_python.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/websearch.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/plugins/write_file.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/utils/__init__.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/utils/prompt.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/src/aient/utils/scripts.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/chatgpt.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/claude.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_API.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_Deepbricks.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_Web_crawler.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_aiwaves.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_aiwaves_arxiv.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_ask_gemini.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_class.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_claude.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_claude_zh_char.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_ddg_search.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_download_pdf.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_gemini.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_get_token_dict.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_google_search.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_jieba.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_json.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_logging.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_ollama.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_plugin.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_py_run.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_requests.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_search.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_tikitoken.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_token.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_url.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_whisper.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_wildcard.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/aient/test/test_yjh.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/bemcp/bemcp/__init__.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/bemcp/bemcp/decorator.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/bemcp/bemcp/main.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/bemcp/bemcp/utils.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/bemcp/test/client.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/bemcp/test/server.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/broker.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/core.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/prompt.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/README.md +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/arduino-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/c-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/chatito-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/cpp-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/csharp-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/d-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/dart-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/elisp-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/elixir-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/elm-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/gleam-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/go-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/java-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/javascript-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/lua-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/pony-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/properties-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/python-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/r-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/racket-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/ruby-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/rust-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/solidity-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/swift-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/udev-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/README.md +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/c-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/cpp-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/dart-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/elisp-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/elixir-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/elm-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/go-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/hcl-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/java-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/javascript-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/php-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/python-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/ql-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/ruby-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/rust-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/scala-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-languages/typescript-tags.scm +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/taskmanager.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/click.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/completion.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/edit_file.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/planner.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/repomap.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/request_input.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/screenshot.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/search_arxiv.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/search_web.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/tools/subtasks.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm/utils.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm.egg-info/dependency_links.txt +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm.egg-info/requires.txt +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/beswarm.egg-info/top_level.txt +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/setup.cfg +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/test/test_TaskManager.py +0 -0
- {beswarm-0.2.37 → beswarm-0.2.39}/test/test_broker.py +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A simplified, declarative implementation of the Beswarm worker agent system,
|
|
3
|
+
built using the custom MessageBroker for a high-level pub/sub architecture.
|
|
4
|
+
"""
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
import uuid
|
|
8
|
+
import json
|
|
9
|
+
import copy
|
|
10
|
+
import asyncio
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from typing import List, Dict, Union
|
|
14
|
+
|
|
15
|
+
from ..broker import MessageBroker
|
|
16
|
+
from ..bemcp.bemcp import MCPManager
|
|
17
|
+
from ..utils import register_mcp_tools
|
|
18
|
+
from ..aient.src.aient.models import chatgpt
|
|
19
|
+
from ..aient.src.aient.plugins import get_function_call_list, registry
|
|
20
|
+
|
|
21
|
+
worker_system_prompt = """
|
|
22
|
+
你是{name}。帮助用户头脑风暴。请分析不同用户的观点,并给出你的观点。
|
|
23
|
+
你的回答必须是 @用户名字开头。后面接上你的回复。如果你觉得无需回答的时候,请直接回复<stop>。
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
class BaseAgent:
|
|
27
|
+
"""Base class for agents, handling common initialization and disposal."""
|
|
28
|
+
def __init__(self, name: str, tools_json: List, agent_config: Dict, work_dir: str, cache_messages: Union[bool, List[Dict]], broker: MessageBroker, listen_topic: str, publish_topic: str, status_topic: str):
|
|
29
|
+
|
|
30
|
+
self.id = str(uuid.uuid4())
|
|
31
|
+
self.name = name
|
|
32
|
+
self.tools_json = tools_json
|
|
33
|
+
self.work_dir = work_dir
|
|
34
|
+
self.cache_file = Path(work_dir) / ".beswarm" / "work_agent_conversation_history.json"
|
|
35
|
+
self.config = copy.deepcopy(agent_config)
|
|
36
|
+
self.cache_messages = cache_messages
|
|
37
|
+
if cache_messages and isinstance(cache_messages, bool) and cache_messages == True:
|
|
38
|
+
self.cache_messages = json.loads(self.cache_file.read_text(encoding="utf-8"))
|
|
39
|
+
self.broker = broker
|
|
40
|
+
self.listen_topic = listen_topic
|
|
41
|
+
self.error_topic = listen_topic + ".error"
|
|
42
|
+
self.publish_topic = publish_topic
|
|
43
|
+
self.status_topic = status_topic
|
|
44
|
+
self._subscription = self.broker.subscribe(self.handle_message, [self.listen_topic, self.error_topic])
|
|
45
|
+
|
|
46
|
+
async def handle_message(self, message: Dict):
|
|
47
|
+
"""Process incoming messages. Must be implemented by subclasses."""
|
|
48
|
+
raise NotImplementedError
|
|
49
|
+
|
|
50
|
+
def dispose(self):
|
|
51
|
+
"""Cancels the subscription and cleans up resources."""
|
|
52
|
+
if self._subscription:
|
|
53
|
+
self._subscription.dispose()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class WorkerAgent(BaseAgent):
|
|
57
|
+
"""Executes instructions and publishes results to a message broker."""
|
|
58
|
+
def __init__(self, name: str, tools_json: List, agent_config: Dict, work_dir: str, cache_messages: Union[bool, List[Dict]], broker: MessageBroker, listen_topic: str, publish_topic: str, status_topic: str):
|
|
59
|
+
super().__init__(name, tools_json, agent_config, work_dir, cache_messages, broker, listen_topic, publish_topic, status_topic)
|
|
60
|
+
|
|
61
|
+
self.config["system_prompt"] = self.config["system_prompt"].format(name=self.name)
|
|
62
|
+
self.agent = chatgpt(**self.config)
|
|
63
|
+
|
|
64
|
+
async def handle_message(self, message: Dict):
|
|
65
|
+
"""Receives an instruction, executes it, and publishes the response."""
|
|
66
|
+
|
|
67
|
+
if message.get("id") == self.id:
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
instruction = message["result"]
|
|
71
|
+
response = await self.agent.ask_async(instruction)
|
|
72
|
+
|
|
73
|
+
if '<stop>' in response.strip():
|
|
74
|
+
if response.replace('<stop>', '').strip() != '':
|
|
75
|
+
self.broker.publish({"id": self.id, "status": "new_message", "result": f"{self.name}: {response.replace('<stop>', '')}\n\n"}, self.status_topic)
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
if response.strip() == '':
|
|
79
|
+
print("\n❌ 工作智能体回复为空,请重新生成指令。")
|
|
80
|
+
self.broker.publish(message, self.error_topic)
|
|
81
|
+
else:
|
|
82
|
+
self.broker.publish({"id": self.id, "status": "new_message", "result": f"{self.name}: {response}\n\n"}, self.status_topic)
|
|
83
|
+
self.broker.publish({
|
|
84
|
+
"id": self.id,
|
|
85
|
+
"result": f"{self.name}: {response}"
|
|
86
|
+
}, self.publish_topic)
|
|
87
|
+
|
|
88
|
+
class Tee:
|
|
89
|
+
def __init__(self, *files):
|
|
90
|
+
self.files = files
|
|
91
|
+
|
|
92
|
+
def write(self, obj):
|
|
93
|
+
for f in self.files:
|
|
94
|
+
f.write(obj)
|
|
95
|
+
f.flush()
|
|
96
|
+
|
|
97
|
+
def flush(self):
|
|
98
|
+
for f in self.files:
|
|
99
|
+
f.flush()
|
|
100
|
+
|
|
101
|
+
class ChatGroupWorker:
|
|
102
|
+
"""The 'glue' class that orchestrates agents via a MessageBroker."""
|
|
103
|
+
def __init__(self, tools: List[Union[str, Dict]], work_dir: str, cache_messages: Union[bool, List[Dict]] = None, broker: MessageBroker = None, mcp_manager: MCPManager = None, task_manager = None):
|
|
104
|
+
self.tools = tools
|
|
105
|
+
self.work_dir = Path(work_dir)
|
|
106
|
+
self.cache_messages = cache_messages
|
|
107
|
+
|
|
108
|
+
self.broker = broker
|
|
109
|
+
self.mcp_manager = mcp_manager
|
|
110
|
+
self.task_manager = task_manager
|
|
111
|
+
self.task_completion_event = asyncio.Event()
|
|
112
|
+
self.final_result = None
|
|
113
|
+
self._status_subscription = None
|
|
114
|
+
self.agents = []
|
|
115
|
+
self.setup()
|
|
116
|
+
|
|
117
|
+
self.channel = self.broker.request_channel()
|
|
118
|
+
self.WORKER_RESPONSE_TOPIC = self.channel + ".worker_responses"
|
|
119
|
+
self.TASK_STATUS_TOPIC =self.channel + ".task_status"
|
|
120
|
+
|
|
121
|
+
def setup(self):
|
|
122
|
+
cache_dir = self.work_dir / ".beswarm"
|
|
123
|
+
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
124
|
+
self.task_manager.set_root_path(self.work_dir)
|
|
125
|
+
self.cache_file = cache_dir / "work_agent_conversation_history.json"
|
|
126
|
+
if not self.cache_file.exists():
|
|
127
|
+
self.cache_file.write_text("[]", encoding="utf-8")
|
|
128
|
+
|
|
129
|
+
DEBUG = os.getenv("DEBUG", "false").lower() in ("true", "1", "t", "yes")
|
|
130
|
+
if DEBUG:
|
|
131
|
+
log_file = open(cache_dir / "history.log", "a", encoding="utf-8")
|
|
132
|
+
log_file.write(f"========== {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ==========\n")
|
|
133
|
+
original_stdout = sys.stdout
|
|
134
|
+
original_stderr = sys.stderr
|
|
135
|
+
sys.stdout = Tee(original_stdout, log_file)
|
|
136
|
+
sys.stderr = Tee(original_stderr, log_file)
|
|
137
|
+
|
|
138
|
+
async def _configure_tools(self):
|
|
139
|
+
mcp_list = [item for item in self.tools if isinstance(item, dict)]
|
|
140
|
+
if mcp_list:
|
|
141
|
+
for mcp_item in mcp_list:
|
|
142
|
+
mcp_name, mcp_config = list(mcp_item.items())[0]
|
|
143
|
+
await self.mcp_manager.add_server(mcp_name, mcp_config)
|
|
144
|
+
client = self.mcp_manager.clients.get(mcp_name)
|
|
145
|
+
await register_mcp_tools(client, registry)
|
|
146
|
+
all_mcp_tools = await self.mcp_manager.get_all_tools()
|
|
147
|
+
self.tools.extend([tool.name for tool in sum(all_mcp_tools.values(), [])])
|
|
148
|
+
self.tools = [item for item in self.tools if not isinstance(item, dict)]
|
|
149
|
+
if "task_complete" not in self.tools: self.tools.append("task_complete")
|
|
150
|
+
self.tools_json = [value for _, value in get_function_call_list(self.tools).items()]
|
|
151
|
+
|
|
152
|
+
def _task_status_subscriber(self, message: Dict):
|
|
153
|
+
"""Subscriber for task status changes."""
|
|
154
|
+
if message.get("status") == "finished":
|
|
155
|
+
self.final_result = message.get("result")
|
|
156
|
+
self.task_completion_event.set()
|
|
157
|
+
|
|
158
|
+
if message.get("status") == "error":
|
|
159
|
+
raise Exception(message.get("result"))
|
|
160
|
+
|
|
161
|
+
if message.get("status") == "new_message":
|
|
162
|
+
print(message.get("result"))
|
|
163
|
+
chat_window = open(self.work_dir / ".beswarm" / "chat_window.md", "a", encoding="utf-8")
|
|
164
|
+
chat_window.write("# " + message.get("result") + "\n")
|
|
165
|
+
|
|
166
|
+
def _setup_agents(self):
|
|
167
|
+
worker_agent_config = {
|
|
168
|
+
"api_key": os.getenv("API_KEY"), "api_url": os.getenv("BASE_URL"),
|
|
169
|
+
"engine": os.getenv("FAST_MODEL") or os.getenv("MODEL"),
|
|
170
|
+
"system_prompt": worker_system_prompt,
|
|
171
|
+
"print_log": True, "temperature": 0.5, "function_call_max_loop": 100
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
chat_agent1 = WorkerAgent(
|
|
175
|
+
name="数学家", tools_json=self.tools_json, agent_config=worker_agent_config, work_dir=self.work_dir, cache_messages=self.cache_messages,
|
|
176
|
+
broker=self.broker, listen_topic=self.WORKER_RESPONSE_TOPIC,
|
|
177
|
+
publish_topic=self.WORKER_RESPONSE_TOPIC, status_topic=self.TASK_STATUS_TOPIC
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
chat_agent2 = WorkerAgent(
|
|
181
|
+
name="哲学家", tools_json=self.tools_json, agent_config=worker_agent_config, work_dir=self.work_dir, cache_messages=self.cache_messages,
|
|
182
|
+
broker=self.broker, listen_topic=self.WORKER_RESPONSE_TOPIC,
|
|
183
|
+
publish_topic=self.WORKER_RESPONSE_TOPIC, status_topic=self.TASK_STATUS_TOPIC
|
|
184
|
+
)
|
|
185
|
+
self.agents = [chat_agent1, chat_agent2]
|
|
186
|
+
|
|
187
|
+
async def run(self):
|
|
188
|
+
"""Sets up subscriptions and starts the workflow, waiting for user input."""
|
|
189
|
+
os.chdir(self.work_dir.absolute())
|
|
190
|
+
await self._configure_tools()
|
|
191
|
+
|
|
192
|
+
self._setup_agents()
|
|
193
|
+
|
|
194
|
+
self._status_subscription = self.broker.subscribe(self._task_status_subscriber, self.TASK_STATUS_TOPIC)
|
|
195
|
+
|
|
196
|
+
print("开启群聊, 请输入内容开始对话, 输入 'exit' 或 'quit' 结束:")
|
|
197
|
+
loop = asyncio.get_running_loop()
|
|
198
|
+
|
|
199
|
+
async def user_input_loop():
|
|
200
|
+
while True:
|
|
201
|
+
try:
|
|
202
|
+
line = await loop.run_in_executor(None, sys.stdin.readline)
|
|
203
|
+
line = line.strip()
|
|
204
|
+
if not line:
|
|
205
|
+
continue
|
|
206
|
+
if line.lower() in ['exit', 'quit']:
|
|
207
|
+
self.task_completion_event.set()
|
|
208
|
+
break
|
|
209
|
+
|
|
210
|
+
self.broker.publish({"id": "user", "result": f"小蓝: {line}"}, self.WORKER_RESPONSE_TOPIC)
|
|
211
|
+
self.broker.publish({"id": "user", "status": "new_message", "result": f"小蓝: {line}\n\n"}, self.TASK_STATUS_TOPIC)
|
|
212
|
+
except asyncio.CancelledError:
|
|
213
|
+
break
|
|
214
|
+
|
|
215
|
+
input_task = asyncio.create_task(user_input_loop())
|
|
216
|
+
|
|
217
|
+
await self.task_completion_event.wait()
|
|
218
|
+
|
|
219
|
+
if not input_task.done():
|
|
220
|
+
input_task.cancel()
|
|
221
|
+
|
|
222
|
+
self.cleanup()
|
|
223
|
+
return self.final_result
|
|
224
|
+
|
|
225
|
+
async def run_for_web(self):
|
|
226
|
+
"""Sets up agents and subscriptions for web-based interaction, then yields messages."""
|
|
227
|
+
os.chdir(self.work_dir.absolute())
|
|
228
|
+
await self._configure_tools()
|
|
229
|
+
self._setup_agents()
|
|
230
|
+
|
|
231
|
+
self._status_subscription = self.broker.subscribe(self._task_status_subscriber, self.TASK_STATUS_TOPIC)
|
|
232
|
+
|
|
233
|
+
print("Web chat group is running. Waiting for messages...")
|
|
234
|
+
await self.task_completion_event.wait()
|
|
235
|
+
print("Web chat group finished.")
|
|
236
|
+
self.cleanup()
|
|
237
|
+
|
|
238
|
+
def cleanup(self):
|
|
239
|
+
"""Cleans up resources like agent subscriptions and MCP manager."""
|
|
240
|
+
print("Cleaning up resources...")
|
|
241
|
+
for agent in self.agents:
|
|
242
|
+
agent.dispose()
|
|
243
|
+
if self._status_subscription:
|
|
244
|
+
self._status_subscription.dispose()
|
|
245
|
+
|
|
246
|
+
# This needs to be async, so we run it in a new event loop if needed
|
|
247
|
+
try:
|
|
248
|
+
loop = asyncio.get_running_loop()
|
|
249
|
+
if loop.is_running():
|
|
250
|
+
loop.create_task(self.mcp_manager.cleanup())
|
|
251
|
+
else:
|
|
252
|
+
asyncio.run(self.mcp_manager.cleanup())
|
|
253
|
+
except RuntimeError: # No running loop
|
|
254
|
+
asyncio.run(self.mcp_manager.cleanup())
|
|
255
|
+
|
|
256
|
+
async def stream_run(self):
|
|
257
|
+
"""Runs the workflow and yields status messages."""
|
|
258
|
+
os.chdir(self.work_dir.absolute())
|
|
259
|
+
await self._configure_tools()
|
|
260
|
+
|
|
261
|
+
instruction_agent, worker_agent = self._setup_agents()
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
async for message in self.broker.iter_topic(self.TASK_STATUS_TOPIC):
|
|
265
|
+
if message.get("status") == "new_message":
|
|
266
|
+
yield message.get("result")
|
|
267
|
+
elif message.get("status") == "finished":
|
|
268
|
+
yield message.get("result")
|
|
269
|
+
break
|
|
270
|
+
elif message.get("status") == "error":
|
|
271
|
+
raise Exception(message.get("result"))
|
|
272
|
+
finally:
|
|
273
|
+
instruction_agent.dispose()
|
|
274
|
+
worker_agent.dispose()
|
|
275
|
+
await self.mcp_manager.cleanup()
|
|
@@ -119,7 +119,7 @@ class InstructionAgent(BaseAgent):
|
|
|
119
119
|
raise Exception(f"Model: {self.config['engine']} not found!")
|
|
120
120
|
if "'status_code': 413" in raw_response or \
|
|
121
121
|
"'status_code': 400" in raw_response:
|
|
122
|
-
self.broker.publish({"status": "error", "result":
|
|
122
|
+
self.broker.publish({"status": "error", "result": "The request body is too long, please try again."}, self.status_topic)
|
|
123
123
|
return
|
|
124
124
|
|
|
125
125
|
self.broker.publish({"status": "new_message", "result": "\n🤖 指令智能体:\n" + raw_response}, self.status_topic)
|
|
@@ -256,7 +256,9 @@ class BrokerWorker:
|
|
|
256
256
|
self.task_completion_event.set()
|
|
257
257
|
|
|
258
258
|
if message.get("status") == "error":
|
|
259
|
-
|
|
259
|
+
print(message.get("result"))
|
|
260
|
+
self.final_result = message.get("result")
|
|
261
|
+
self.task_completion_event.set()
|
|
260
262
|
|
|
261
263
|
if message.get("status") == "new_message":
|
|
262
264
|
print(message.get("result"))
|
|
@@ -332,7 +334,9 @@ class BrokerWorker:
|
|
|
332
334
|
yield message.get("result")
|
|
333
335
|
break
|
|
334
336
|
elif message.get("status") == "error":
|
|
335
|
-
|
|
337
|
+
print(message.get("result"))
|
|
338
|
+
self.final_result = message.get("result")
|
|
339
|
+
self.task_completion_event.set()
|
|
336
340
|
finally:
|
|
337
341
|
instruction_agent.dispose()
|
|
338
342
|
worker_agent.dispose()
|
|
@@ -3,9 +3,9 @@ from .search_web import search_web
|
|
|
3
3
|
from .completion import task_complete
|
|
4
4
|
from .search_arxiv import search_arxiv
|
|
5
5
|
from .repomap import get_code_repo_map
|
|
6
|
-
from .worker import worker, worker_gen
|
|
7
6
|
from .request_input import request_admin_input
|
|
8
7
|
from .screenshot import save_screenshot_to_file
|
|
8
|
+
from .worker import worker, worker_gen, chatgroup
|
|
9
9
|
from .click import find_and_click_element, scroll_screen
|
|
10
10
|
from .subtasks import create_task, resume_task, get_all_tasks_status, get_task_result
|
|
11
11
|
|
|
@@ -31,6 +31,7 @@ __all__ = [
|
|
|
31
31
|
"get_time",
|
|
32
32
|
"edit_file",
|
|
33
33
|
"read_file",
|
|
34
|
+
"chatgroup",
|
|
34
35
|
"worker_gen",
|
|
35
36
|
"read_image",
|
|
36
37
|
"search_web",
|
|
@@ -3,6 +3,7 @@ from typing import List, Dict, Union
|
|
|
3
3
|
|
|
4
4
|
from ..core import mcp_manager, broker, task_manager
|
|
5
5
|
from ..agents.planact import BrokerWorker
|
|
6
|
+
from ..agents.chatgroup import ChatGroupWorker
|
|
6
7
|
from ..aient.src.aient.plugins import register_tool
|
|
7
8
|
|
|
8
9
|
|
|
@@ -26,4 +27,15 @@ async def worker_gen(goal: str, tools: List[Union[str, Dict]], work_dir: str, ca
|
|
|
26
27
|
end_time = datetime.now()
|
|
27
28
|
print(f"\n任务开始时间: {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
28
29
|
print(f"任务结束时间: {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
29
|
-
print(f"总用时: {end_time - start_time}")
|
|
30
|
+
print(f"总用时: {end_time - start_time}")
|
|
31
|
+
|
|
32
|
+
@register_tool()
|
|
33
|
+
async def chatgroup(tools: List[Union[str, Dict]], work_dir: str, cache_messages: Union[bool, List[Dict]] = None):
|
|
34
|
+
start_time = datetime.now()
|
|
35
|
+
worker_instance = ChatGroupWorker(tools, work_dir, cache_messages, broker, mcp_manager, task_manager)
|
|
36
|
+
result = await worker_instance.run()
|
|
37
|
+
end_time = datetime.now()
|
|
38
|
+
print(f"\n任务开始时间: {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
39
|
+
print(f"任务结束时间: {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
40
|
+
print(f"总用时: {end_time - start_time}")
|
|
41
|
+
return result
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/arduino-tags.scm
RENAMED
|
File without changes
|
|
File without changes
|
{beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/chatito-tags.scm
RENAMED
|
File without changes
|
{beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/commonlisp-tags.scm
RENAMED
|
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
|
|
File without changes
|
{beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/javascript-tags.scm
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/properties-tags.scm
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{beswarm-0.2.37 → beswarm-0.2.39}/beswarm/queries/tree-sitter-language-pack/solidity-tags.scm
RENAMED
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|