beswarm 0.1.91__py3-none-any.whl → 0.1.92__py3-none-any.whl

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.
@@ -341,7 +341,8 @@ async def get_vertex_gemini_payload(request, engine, provider, api_key=None):
341
341
  else:
342
342
  location = gemini1
343
343
 
344
- if "gemini-2.5-pro-exp-03-25" == original_model or "gemini-2.5-pro-preview-06-05" == original_model:
344
+ if "gemini-2.5-flash-lite-preview-06-17" == original_model or \
345
+ "gemini-2.5-pro-preview-06-05" == original_model:
345
346
  location = gemini2_5_pro_exp
346
347
 
347
348
  if "google-vertex-ai" in provider.get("base_url", ""):
@@ -362,7 +363,8 @@ async def get_vertex_gemini_payload(request, engine, provider, api_key=None):
362
363
  else:
363
364
  url = f"https://aiplatform.googleapis.com/v1/publishers/google/models/{original_model}:{gemini_stream}?key={api_key}"
364
365
  headers.pop("Authorization", None)
365
- elif "gemini-2.5-pro-exp-03-25" == original_model or "gemini-2.5-pro-preview-06-05" == original_model:
366
+ elif "gemini-2.5-flash-lite-preview-06-17" == original_model or \
367
+ "gemini-2.5-pro-preview-06-05" == original_model:
366
368
  url = "https://aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/{MODEL_ID}:{stream}".format(
367
369
  LOCATION=await location.next(),
368
370
  PROJECT_ID=project_id,
@@ -0,0 +1,4 @@
1
+ from .main import MCPManager, MCPClient
2
+ from .utils import convert_tool_format
3
+
4
+ __all__ = ["MCPManager", "MCPClient", "convert_tool_format"]
@@ -0,0 +1,220 @@
1
+ import asyncio
2
+ from typing import Any, Dict, List, Optional
3
+ from contextlib import AsyncExitStack
4
+
5
+ from mcp import ClientSession, StdioServerParameters
6
+ from mcp.client.stdio import stdio_client
7
+ from mcp.client.sse import sse_client
8
+ import mcp.types as types
9
+
10
+ class MCPClient:
11
+ """
12
+ A client for interacting with a single Model Context Protocol (MCP) server.
13
+ It can connect to a server via stdio or a URL (SSE).
14
+ This class is an asynchronous context manager.
15
+ """
16
+ def __init__(self, server_config: Dict[str, Any]):
17
+ """
18
+ Initializes the MCPClient.
19
+
20
+ Args:
21
+ server_config: A dictionary containing server configuration.
22
+ It should have either 'command' and 'args' for stdio,
23
+ or 'url' for SSE.
24
+ """
25
+ if not ("command" in server_config or "url" in server_config):
26
+ raise ValueError("Server config must contain 'command' or 'url'")
27
+ self.server_config = server_config
28
+ self.session: Optional[ClientSession] = None
29
+ self._exit_stack: Optional[AsyncExitStack] = None
30
+
31
+ async def connect(self):
32
+ """Connects to the MCP server and initializes resources."""
33
+ return await self.__aenter__()
34
+
35
+ async def disconnect(self):
36
+ """Disconnects from the MCP server and cleans up resources."""
37
+ return await self.__aexit__(None, None, None)
38
+
39
+ async def __aenter__(self):
40
+ """Connects to the MCP server and initializes resources."""
41
+ if self.session:
42
+ return self
43
+
44
+ self._exit_stack = AsyncExitStack()
45
+ try:
46
+ if "command" in self.server_config:
47
+ server_params = StdioServerParameters(**self.server_config)
48
+ transport = await self._exit_stack.enter_async_context(stdio_client(server_params))
49
+ else:
50
+ transport = await self._exit_stack.enter_async_context(sse_client(**self.server_config))
51
+
52
+ read_stream, write_stream = transport
53
+ self.session = await self._exit_stack.enter_async_context(ClientSession(read_stream, write_stream))
54
+ await self.session.initialize()
55
+ print(f"Connected to server.")
56
+ return self
57
+ except Exception:
58
+ # If setup fails, make sure to clean up anything that was started.
59
+ if self._exit_stack:
60
+ await self._exit_stack.aclose()
61
+ raise
62
+
63
+ async def __aexit__(self, exc_type, exc_value, traceback):
64
+ """Disconnects from the MCP server and cleans up resources."""
65
+ if self._exit_stack:
66
+ await self._exit_stack.aclose()
67
+ self.session = None
68
+ self._exit_stack = None
69
+ print("Disconnected from server.")
70
+
71
+ async def list_tools(self) -> List[types.Tool]:
72
+ """Lists available tools from the server."""
73
+ if not self.session:
74
+ raise ConnectionError("Not connected to any server.")
75
+ response = await self.session.list_tools()
76
+ return response.tools
77
+
78
+ async def call_tool(self, name: str, args: Dict[str, Any]) -> types.CallToolResult:
79
+ """Calls a tool on the server."""
80
+ if not self.session:
81
+ raise ConnectionError("Not connected to any server.")
82
+ return await self.session.call_tool(name, args)
83
+
84
+ async def list_resources(self) -> List[types.Resource]:
85
+ """Lists available resources from the server."""
86
+ if not self.session:
87
+ raise ConnectionError("Not connected to any server.")
88
+ response = await self.session.list_resources()
89
+ return response.resources
90
+
91
+ async def read_resource(self, uri: str) -> types.ReadResourceResult:
92
+ """Reads a resource from the server."""
93
+ if not self.session:
94
+ raise ConnectionError("Not connected to any server.")
95
+ return await self.session.read_resource(uri)
96
+
97
+
98
+ class MCPManager:
99
+ """
100
+ Manages connections to multiple MCP servers.
101
+ """
102
+ def __init__(self):
103
+ self.clients: Dict[str, MCPClient] = {}
104
+ self._exit_stack = AsyncExitStack()
105
+
106
+ async def add_server(self, name: str, config: Dict[str, Any]):
107
+ """
108
+ Adds and connects to a new MCP server.
109
+
110
+ Args:
111
+ name: A unique name for the server.
112
+ config: The server configuration dictionary.
113
+ """
114
+ if name in self.clients:
115
+ print(f"Server '{name}' already exists.")
116
+ return
117
+
118
+ client = MCPClient(config)
119
+ await self._exit_stack.enter_async_context(client)
120
+ self.clients[name] = client
121
+ print(f"Server '{name}' added and connected.")
122
+
123
+ async def remove_server(self, name: str):
124
+ """
125
+ Disconnects and removes an MCP server.
126
+ """
127
+ # NOTE: With the new ExitStack-based management, removing a single
128
+ # server is complex. This method is left as a placeholder and will
129
+ # not correctly clean up resources for the removed server.
130
+ if name in self.clients:
131
+ del self.clients[name]
132
+ print(f"Server '{name}' removed (Warning: resources may not be cleaned up immediately).")
133
+ else:
134
+ print(f"Server '{name}' not found.")
135
+
136
+ async def get_all_tools(self) -> Dict[str, List[types.Tool]]:
137
+ """Gets a dictionary of all tools from all connected servers."""
138
+ all_tools = {}
139
+ for name, client in self.clients.items():
140
+ try:
141
+ tools = await client.list_tools()
142
+ all_tools[name] = tools
143
+ except Exception as e:
144
+ print(f"Error getting tools from server '{name}': {e}")
145
+ return all_tools
146
+
147
+ async def call_tool(self, server_name: str, tool_name: str, args: Dict[str, Any]) -> types.CallToolResult:
148
+ """
149
+ Calls a specific tool on a specific server.
150
+ """
151
+ if server_name not in self.clients:
152
+ raise ValueError(f"Server '{server_name}' not found.")
153
+ return await self.clients[server_name].call_tool(tool_name, args)
154
+
155
+ async def cleanup(self):
156
+ """Disconnects all clients by closing the manager's exit stack."""
157
+ if self.clients:
158
+ await self._exit_stack.aclose()
159
+ self.clients.clear()
160
+
161
+ async def test_bemcp():
162
+ """
163
+ Test function for MCPManager and MCPClient.
164
+ """
165
+ manager = MCPManager()
166
+
167
+ # Configuration for a test server (using the existing test/server.py)
168
+ test_server_config = {
169
+ "command": "uv",
170
+ "args": ["run", "test/server.py"],
171
+ "env": None
172
+ }
173
+
174
+ # Add the test server
175
+ await manager.add_server("test_server", test_server_config)
176
+
177
+ # List all tools
178
+ all_tools = await manager.get_all_tools()
179
+ print("\n--- All Tools ---")
180
+ for server_name, tools in all_tools.items():
181
+ print(f"Server: {server_name}")
182
+ for tool in tools:
183
+ print(f" - {tool.name}: {tool.description}")
184
+ print("-------------------\n")
185
+
186
+ # Call a tool
187
+ print("--- Calling 'add' tool on 'test_server' with a=2, b=3 ---")
188
+ try:
189
+ result = await manager.call_tool("test_server", "add", {"a": 2, "b": 3})
190
+ print("Result:", result.content[0].text)
191
+ except Exception as e:
192
+ print(f"Error calling tool: {e}")
193
+ print("--------------------------------------------------------\n")
194
+
195
+ # Call another tool
196
+ print("--- Calling 'calculate_bmi' tool on 'test_server' with weight_kg=70, height_m=1.75 ---")
197
+ try:
198
+ result = await manager.call_tool("test_server", "calculate_bmi", {"weight_kg": 70, "height_m": 1.75})
199
+ print("Result:", result.content[0].text)
200
+ except Exception as e:
201
+ print(f"Error calling tool: {e}")
202
+ print("-------------------------------------------------------------------------------------\n")
203
+
204
+ # Read a resource
205
+ print("--- Reading resource 'config://app' from 'test_server' ---")
206
+ client = manager.clients.get("test_server")
207
+ if client:
208
+ try:
209
+ resource_result = await client.read_resource('config://app')
210
+ print("Resource content:", resource_result.contents[0].text)
211
+ except Exception as e:
212
+ print(f"Error reading resource: {e}")
213
+ print("----------------------------------------------------------\n")
214
+
215
+
216
+ # Clean up
217
+ await manager.cleanup()
218
+
219
+ if __name__ == "__main__":
220
+ asyncio.run(test_bemcp())
@@ -0,0 +1,30 @@
1
+ from typing import Any, Dict
2
+ from mcp import types
3
+
4
+ def convert_tool_format(tool: types.Tool) -> Dict[str, Any]:
5
+ """
6
+ Converts an MCP tool to a format compatible with LLM providers.
7
+ """
8
+ # This is one possible format, similar to OpenAI's function calling.
9
+ # The commented-out section shows another common variation.
10
+ # converted_tool = {
11
+ # "type": "function",
12
+ # "function": {
13
+ # "name": tool.name,
14
+ # "description": tool.description,
15
+ # "parameters": {
16
+ # "type": "object",
17
+ # "properties": tool.inputSchema["properties"],
18
+ # "required": tool.inputSchema["required"]
19
+ # }
20
+ # }
21
+ # }
22
+ converted_tool = {
23
+ "type": "function",
24
+ "function": {
25
+ "name": tool.name,
26
+ "description": tool.description,
27
+ "input_schema": tool.inputSchema
28
+ }
29
+ }
30
+ return converted_tool
@@ -0,0 +1,49 @@
1
+ import asyncio
2
+
3
+ from mcp.client.stdio import stdio_client
4
+ from mcp import ClientSession, StdioServerParameters
5
+
6
+ # 为 stdio 连接创建服务器参数
7
+ server_params = StdioServerParameters(
8
+ # 服务器执行的命令,这里我们使用 uv 来运行 web_search.py
9
+ command='uv',
10
+ # 运行的参数
11
+ args=['run', 'server.py'],
12
+ # 环境变量,默认为 None,表示使用当前环境变量
13
+ # env=None
14
+ )
15
+
16
+
17
+ async def main():
18
+ # 创建 stdio 客户端
19
+ async with stdio_client(server_params) as (stdio, write):
20
+ # 创建 ClientSession 对象
21
+ async with ClientSession(stdio, write) as session:
22
+ # 初始化 ClientSession
23
+ await session.initialize()
24
+
25
+ # 列出可用的工具
26
+ response = await session.list_tools()
27
+ print(response.model_dump_json(indent=2))
28
+
29
+ response = await session.list_resources()
30
+ print(response.model_dump_json(indent=2))
31
+
32
+ response = await session.list_prompts()
33
+ print(response.model_dump_json(indent=2))
34
+
35
+ # 调用工具
36
+ response = await session.call_tool('add', {"a": "2", "b": "3"})
37
+ print(response.model_dump_json(indent=2))
38
+
39
+ # 调用工具
40
+ response = await session.read_resource('config://app')
41
+ print(response.model_dump_json(indent=2))
42
+
43
+ # 调用工具
44
+ response = await session.get_prompt('debug_error', {"error": "test"})
45
+ print(response.model_dump_json(indent=2))
46
+
47
+
48
+ if __name__ == '__main__':
49
+ asyncio.run(main())
@@ -0,0 +1,43 @@
1
+ # server.py
2
+ import httpx
3
+ from mcp.server.fastmcp import FastMCP
4
+ from mcp.server.fastmcp.prompts import base
5
+
6
+ # Create an MCP server
7
+ mcp = FastMCP("Demo")
8
+
9
+
10
+ # Add an addition tool
11
+ @mcp.tool()
12
+ def add(a: int, b: int) -> int:
13
+ """Add two numbers"""
14
+ return a + b
15
+
16
+ @mcp.tool()
17
+ def calculate_bmi(weight_kg: float, height_m: float) -> float:
18
+ """Calculate BMI given weight in kg and height in meters"""
19
+ return weight_kg / (height_m**2)
20
+
21
+ @mcp.tool()
22
+ async def fetch_weather(city: str) -> str:
23
+ """Fetch current weather for a city"""
24
+ async with httpx.AsyncClient() as client:
25
+ response = await client.get(f"https://api.weather.com/{city}")
26
+ return response.text
27
+
28
+ @mcp.resource("config://app")
29
+ def get_config() -> str:
30
+ """Static configuration data"""
31
+ return "App configuration here"
32
+
33
+ @mcp.prompt()
34
+ def debug_error(error: str) -> list[base.Message]:
35
+ return [
36
+ base.UserMessage("I'm seeing this error:"),
37
+ base.UserMessage(error),
38
+ base.AssistantMessage("I'll help debug that. What have you tried so far?"),
39
+ ]
40
+
41
+ if __name__ == "__main__":
42
+ mcp.run(transport='stdio')
43
+ # mcp.run(transport='sse')
beswarm/tools/worker.py CHANGED
@@ -7,9 +7,12 @@ from pathlib import Path
7
7
  from datetime import datetime
8
8
 
9
9
  from ..aient.src.aient.models import chatgpt
10
- from ..aient.src.aient.plugins import register_tool, get_function_call_list
10
+ from ..aient.src.aient.plugins import register_tool, get_function_call_list, registry
11
11
  from ..prompt import worker_system_prompt, instruction_system_prompt
12
- from ..utils import extract_xml_content, get_current_screen_image_message, replace_xml_content
12
+ from ..utils import extract_xml_content, get_current_screen_image_message, replace_xml_content, register_mcp_tools
13
+ from ..bemcp.bemcp import MCPClient, convert_tool_format, MCPManager
14
+
15
+ manager = MCPManager()
13
16
 
14
17
  @register_tool()
15
18
  async def worker(goal, tools, work_dir, cache_messages=None):
@@ -31,6 +34,19 @@ async def worker(goal, tools, work_dir, cache_messages=None):
31
34
  start_time = datetime.now()
32
35
  finish_flag = 0
33
36
 
37
+ mcp_list = [item for item in tools if isinstance(item, dict)]
38
+ if mcp_list:
39
+ for mcp_item in mcp_list:
40
+ mcp_name, mcp_config = list(mcp_item.items())[0]
41
+ await manager.add_server(mcp_name, mcp_config)
42
+ client = manager.clients.get(mcp_name)
43
+ await register_mcp_tools(client, registry)
44
+ all_tools = await manager.get_all_tools()
45
+ mcp_tools_name = [tool.name for tool in sum(all_tools.values(), [])]
46
+ tools += mcp_tools_name
47
+
48
+ tools = [item for item in tools if not isinstance(item, dict)]
49
+
34
50
  tools_json = [value for _, value in get_function_call_list(tools).items()]
35
51
  work_agent_system_prompt = worker_system_prompt.format(
36
52
  os_version=platform.platform(),
@@ -179,11 +195,26 @@ async def worker(goal, tools, work_dir, cache_messages=None):
179
195
  print(f"\n任务开始时间: {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
180
196
  print(f"任务结束时间: {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
181
197
  print(f"总用时: {total_time}")
198
+ await manager.cleanup()
182
199
  return "任务已完成"
183
200
 
184
201
  async def worker_gen(goal, tools, work_dir, cache_messages=None):
185
202
  start_time = datetime.now()
186
203
  finish_flag = 0
204
+
205
+ mcp_list = [item for item in tools if isinstance(item, dict)]
206
+ if mcp_list:
207
+ for mcp_item in mcp_list:
208
+ mcp_name, mcp_config = list(mcp_item.items())[0]
209
+ await manager.add_server(mcp_name, mcp_config)
210
+ client = manager.clients.get(mcp_name)
211
+ await register_mcp_tools(client, registry)
212
+ all_tools = await manager.get_all_tools()
213
+ mcp_tools_name = [tool.name for tool in sum(all_tools.values(), [])]
214
+ tools += mcp_tools_name
215
+
216
+ tools = [item for item in tools if not isinstance(item, dict)]
217
+
187
218
  tools_json = [value for _, value in get_function_call_list(tools).items()]
188
219
  work_agent_system_prompt = worker_system_prompt.format(
189
220
  os_version=platform.platform(),
@@ -335,4 +366,5 @@ async def worker_gen(goal, tools, work_dir, cache_messages=None):
335
366
  total_time = end_time - start_time
336
367
  print(f"\n任务开始时间: {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
337
368
  print(f"任务结束时间: {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
338
- print(f"总用时: {total_time}")
369
+ print(f"总用时: {total_time}")
370
+ await manager.cleanup()
beswarm/utils.py CHANGED
@@ -68,6 +68,102 @@ async def get_current_screen_image_message(prompt):
68
68
  message_list.append(image_message)
69
69
  return message_list
70
70
 
71
+ import asyncio
72
+ from .bemcp.bemcp import MCPClient, convert_tool_format
73
+
74
+ async def register_mcp_tools(mcp_client: MCPClient, registry: "Registry"):
75
+ """
76
+ Fetches tools from an MCP client, dynamically creates corresponding
77
+ Python functions with correct signatures, and registers them using the
78
+ provided registry instance.
79
+ """
80
+ try:
81
+ mcp_tools = await mcp_client.list_tools()
82
+ print(f"Found {len(mcp_tools)} tools on the MCP server.")
83
+ except Exception as e:
84
+ print(f"Error fetching tools from MCP server: {e}")
85
+ return
86
+
87
+ # Create a dummy file for inspect.getsource to work with exec
88
+ # This helps make the created functions inspectable
89
+ source_storage = {}
90
+
91
+ for tool in mcp_tools:
92
+ openai_spec = convert_tool_format(tool)
93
+ func_spec = openai_spec.get('function', {})
94
+
95
+ tool_name = func_spec.get('name')
96
+ if not tool_name or not tool_name.isidentifier():
97
+ print(f"Skipping tool with invalid name: {tool_name}")
98
+ continue
99
+
100
+ description = func_spec.get('description', 'No description available.')
101
+ params_spec = func_spec.get('parameters', {})
102
+ properties = params_spec.get('properties', {})
103
+ required = set(params_spec.get('required', []))
104
+
105
+ param_defs = []
106
+ for name, spec in properties.items():
107
+ if name in required:
108
+ param_defs.append(name)
109
+ else:
110
+ # Add default value for optional parameters
111
+ default = spec.get('default', 'None')
112
+ param_defs.append(f"{name}={default}")
113
+
114
+ params_str = ", ".join(param_defs)
115
+ arg_names = list(properties.keys())
116
+ # Create a dictionary of arguments to pass to call_tool
117
+ args_dict_str = "{" + ", ".join(f"'{k}': {k}" for k in arg_names) + "}"
118
+
119
+ # Dynamically generate the Python source code for the function
120
+ func_source = f"""
121
+ async def {tool_name}({params_str}):
122
+ \"\"\"{description}\"\"\"
123
+ tool_args = {args_dict_str}
124
+
125
+ # This function is a dynamically generated wrapper for an MCP tool.
126
+ print(f"-> Calling MCP tool '{tool_name}' with args: {{tool_args}}")
127
+ result = await mcp_client.call_tool('{tool_name}', tool_args)
128
+
129
+ # Extract text content if available, otherwise return the raw result
130
+ if hasattr(result, 'content') and isinstance(result.content, list) and result.content:
131
+ if hasattr(result.content[0], 'text'):
132
+ return result.content[0].text
133
+ return result
134
+ """
135
+ # Store the source code so inspect.getsource can find it
136
+ source_storage[tool_name] = func_source
137
+
138
+ # Use a dictionary for the execution scope
139
+ exec_scope = {'mcp_client': mcp_client, 'asyncio': asyncio}
140
+
141
+ try:
142
+ # Execute the source code to create the function object
143
+ exec(func_source, exec_scope)
144
+ generated_func = exec_scope[tool_name]
145
+
146
+ # Monkey-patch getsourcelines to work with our storage
147
+ # This makes our generated function fully compatible with the registry
148
+ import inspect
149
+ import linecache
150
+ linecache.cache[f"<mcp_adapter/{tool_name}>"] = (
151
+ len(func_source),
152
+ None,
153
+ [line + '\n' for line in func_source.splitlines()],
154
+ f"<mcp_adapter/{tool_name}>",
155
+ )
156
+ generated_func.__code__ = generated_func.__code__.replace(co_filename=f"<mcp_adapter/{tool_name}>")
157
+
158
+ # Register the newly created function
159
+ registry.register(type="tool", name=tool_name)(generated_func)
160
+ print(f"Successfully registered MCP tool: '{tool_name}'")
161
+
162
+ except Exception as e:
163
+ import traceback
164
+ print(f"Failed to create or register function for tool '{tool_name}': {e}")
165
+ traceback.print_exc()
166
+
71
167
  if __name__ == "__main__":
72
168
  print(extract_xml_content("<instructions>\n123</instructions>", "instructions"))
73
169
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beswarm
3
- Version: 0.1.91
3
+ Version: 0.1.92
4
4
  Summary: MAS
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -11,6 +11,7 @@ Requires-Dist: fastapi>=0.115.12
11
11
  Requires-Dist: grep-ast>=0.8.1
12
12
  Requires-Dist: httpx>=0.28.1
13
13
  Requires-Dist: httpx-socks>=0.10.0
14
+ Requires-Dist: mcp[cli]>=1.9.4
14
15
  Requires-Dist: msgspec>=0.19.0
15
16
  Requires-Dist: networkx>=3.4.2
16
17
  Requires-Dist: numpy>=2.2.5
@@ -1,13 +1,13 @@
1
1
  beswarm/__init__.py,sha256=HZjUOJtZR5QhMuDbq-wukQQn1VrBusNWai_ysGo-VVI,20
2
2
  beswarm/prompt.py,sha256=cBz8sSmFj0edIGOZjCMg0rg3pFXQYo8xGvXSA8Py1hg,31591
3
- beswarm/utils.py,sha256=cOYwuONpNG_dkSYIvdEqQOxRUdIy0Bh9CTYkvKKskdw,2816
3
+ beswarm/utils.py,sha256=lm0drN1ebXM9haoKaW2DLzJJRCOpLmiJ864mH4jAdB4,6697
4
4
  beswarm/aient/main.py,sha256=SiYAIgQlLJqYusnTVEJOx1WNkSJKMImhgn5aWjfroxg,3814
5
5
  beswarm/aient/setup.py,sha256=IUr9oCEhGFNVvz7v8J9tedwE_JK6Hlf8XpnENoq2K2s,487
6
6
  beswarm/aient/src/aient/__init__.py,sha256=SRfF7oDVlOOAi6nGKiJIUK6B_arqYLO9iSMp-2IZZps,21
7
7
  beswarm/aient/src/aient/core/__init__.py,sha256=NxjebTlku35S4Dzr16rdSqSTWUvvwEeACe8KvHJnjPg,34
8
8
  beswarm/aient/src/aient/core/log_config.py,sha256=kz2_yJv1p-o3lUQOwA3qh-LSc3wMHv13iCQclw44W9c,274
9
9
  beswarm/aient/src/aient/core/models.py,sha256=oUGsytAVBuhE_MLco7PqIQGwWD8lEYkZxgb8HEuynmA,7444
10
- beswarm/aient/src/aient/core/request.py,sha256=Zp5Q6iZp3OWZt95cZLh0VmbwvF18jXQB88UfA_3AKt8,67279
10
+ beswarm/aient/src/aient/core/request.py,sha256=7IaN5iFYQgDK9W8ej-OZCom4bSZiPN5t_S_91DBRb28,67313
11
11
  beswarm/aient/src/aient/core/response.py,sha256=WIJhvf3Th3-XW3MsDq8QdzxXcNe5q1mCKcCZx8pzm2A,33213
12
12
  beswarm/aient/src/aient/core/utils.py,sha256=zidsBUBd3KskzcxQcPB1y5x1RhtWcbZeWvmgb4LAadA,27318
13
13
  beswarm/aient/src/aient/core/test/test_base_api.py,sha256=pWnycRJbuPSXKKU9AQjWrMAX1wiLC_014Qc9hh5C2Pw,524
@@ -71,6 +71,11 @@ beswarm/aient/test/test_url.py,sha256=ASE3kT2-ooaX6Flw4botjXnuqaBgutqRWPx3fow5nL
71
71
  beswarm/aient/test/test_whisper.py,sha256=GxKYzhh3lA8t62V_DDj42VQTXkdjocSFcl5u96WF580,378
72
72
  beswarm/aient/test/test_wildcard.py,sha256=EQwwNrTMHV4CEcZKdwUVGrwtNUsF0CCKbM-_W9IOYsk,693
73
73
  beswarm/aient/test/test_yjh.py,sha256=MsHuBLNOqi3fyX-uboBKmTevkZW_KVv12p-pkF5ir3Y,787
74
+ beswarm/bemcp/bemcp/__init__.py,sha256=Ss6bDXiZJgVIZS6KWytcGwXmIFu7SsagIXa5NpeWJ7c,140
75
+ beswarm/bemcp/bemcp/main.py,sha256=dadyyAv0yzEX5EYnBM14SmBN7X3keJTrheDVie2rVJ4,8370
76
+ beswarm/bemcp/bemcp/utils.py,sha256=YDRa4JvBjdNTJBzbrkwRXmRXy2gw8s9lb61WsnYZN10,953
77
+ beswarm/bemcp/test/client.py,sha256=j7PDg5Esyri-e2vz2ubZ4foDSAq5Iv8Yfl_xyzTDsFY,1593
78
+ beswarm/bemcp/test/server.py,sha256=58F0_xQTHc6mt_MTXLSz_JE1COzDdEYueco1OVuFay0,1159
74
79
  beswarm/queries/tree-sitter-language-pack/README.md,sha256=ivZSEuWqYfUVLZl2AZZGRlm0bQsaG-VTBKBwACyM07k,291
75
80
  beswarm/queries/tree-sitter-language-pack/arduino-tags.scm,sha256=HbgdothT9Jjk56COXTtUkVAdZ14rZNnqzLbWVLeRs5U,177
76
81
  beswarm/queries/tree-sitter-language-pack/c-tags.scm,sha256=EIz45o5hBh8yEuck5ZR_4IpcGyWSeNrzxFmtkKZGt2k,461
@@ -128,8 +133,8 @@ beswarm/tools/screenshot.py,sha256=u6t8FCgW5YHJ_Oc4coo8e0F3wTusWE_-H8dFh1rBq9Q,1
128
133
  beswarm/tools/search_arxiv.py,sha256=GpuIOYX8T0iRC-X-hmuR9AUJVn15WWZq864DaoC7BUc,8004
129
134
  beswarm/tools/search_web.py,sha256=B24amOnGHnmdV_6S8bw8O2PdhZRRIDtJjg-wXcfP7dQ,11859
130
135
  beswarm/tools/think.py,sha256=WLw-7jNIsnS6n8MMSYUin_f-BGLENFmnKM2LISEp0co,1760
131
- beswarm/tools/worker.py,sha256=o24fkVGVXQ3eVLZFpYozMv5fas-Wc269dLCFKqOeaSI,16275
132
- beswarm-0.1.91.dist-info/METADATA,sha256=JjbdA88aNFt2ipP1J3JEeVFpQ4lMDoL5zyv4CpLnIUs,3553
133
- beswarm-0.1.91.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
134
- beswarm-0.1.91.dist-info/top_level.txt,sha256=pJw4O87wvt5882smuSO6DfByJz7FJ8SxxT8h9fHCmpo,8
135
- beswarm-0.1.91.dist-info/RECORD,,
136
+ beswarm/tools/worker.py,sha256=hqfOOW0PeLHYgmB2eHPIPd4wpI_RMsDGGkH5DMy0SLo,17597
137
+ beswarm-0.1.92.dist-info/METADATA,sha256=5b6zhFvaxJGQxuoaSMYmM4jsoiaQTNx7JTqsVfMvLp8,3584
138
+ beswarm-0.1.92.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
139
+ beswarm-0.1.92.dist-info/top_level.txt,sha256=pJw4O87wvt5882smuSO6DfByJz7FJ8SxxT8h9fHCmpo,8
140
+ beswarm-0.1.92.dist-info/RECORD,,