beswarm 0.1.20__py3-none-any.whl → 0.1.22__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.
beswarm/aient/setup.py CHANGED
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
 
5
5
  setup(
6
6
  name="aient",
7
- version="1.0.79",
7
+ version="1.0.81",
8
8
  description="Aient: The Awakening of Agent.",
9
9
  long_description=Path.open(Path("README.md"), encoding="utf-8").read(),
10
10
  long_description_content_type="text/markdown",
@@ -300,7 +300,8 @@ async def get_vertex_gemini_payload(request, engine, provider, api_key=None):
300
300
  original_model = model_dict[request.model]
301
301
  search_tool = None
302
302
 
303
- pro_models = ["gemini-2.5", "gemini-2.0", "gemini-exp"]
303
+ # https://cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/2-0-flash?hl=zh-cn
304
+ pro_models = ["gemini-2.5"]
304
305
  if any(pro_model in original_model for pro_model in pro_models):
305
306
  location = gemini2
306
307
  search_tool = {"googleSearch": {}}
@@ -946,7 +947,8 @@ async def get_gpt_payload(request, engine, provider, api_key=None):
946
947
 
947
948
  if "api.x.ai" in url:
948
949
  payload.pop("stream_options", None)
949
- payload.pop("presencePenalty", None)
950
+ payload.pop("presence_penalty", None)
951
+ payload.pop("frequency_penalty", None)
950
952
 
951
953
  if "grok-3-mini" in original_model:
952
954
  if request.model.endswith("high"):
@@ -995,7 +997,7 @@ async def get_gpt_payload(request, engine, provider, api_key=None):
995
997
 
996
998
  return url, headers, payload
997
999
 
998
- def build_azure_endpoint(base_url, deployment_id, api_version="2024-10-21"):
1000
+ def build_azure_endpoint(base_url, deployment_id, api_version="2025-01-01-preview"):
999
1001
  # 移除base_url末尾的斜杠(如果有)
1000
1002
  base_url = base_url.rstrip('/')
1001
1003
  final_url = base_url
@@ -551,30 +551,27 @@ async def generate_no_stream_response(timestamp, model, content=None, tools_id=N
551
551
 
552
552
  return json_data
553
553
 
554
- def get_image_format(file_content):
554
+ def get_image_format(file_content: bytes):
555
555
  try:
556
556
  img = Image.open(io.BytesIO(file_content))
557
557
  return img.format.lower()
558
558
  except:
559
559
  return None
560
560
 
561
- def encode_image(image_path):
562
- with open(image_path, "rb") as image_file:
563
- file_content = image_file.read()
564
- img_format = get_image_format(file_content)
565
- if not img_format:
566
- raise ValueError("无法识别的图片格式")
567
- base64_encoded = base64.b64encode(file_content).decode('utf-8')
568
-
569
- if img_format == 'png':
570
- return f"data:image/png;base64,{base64_encoded}"
571
- elif img_format in ['jpg', 'jpeg']:
572
- return f"data:image/jpeg;base64,{base64_encoded}"
573
- else:
574
- raise ValueError(f"不支持的图片格式: {img_format}")
561
+ def encode_image(file_content: bytes):
562
+ img_format = get_image_format(file_content)
563
+ if not img_format:
564
+ raise ValueError("无法识别的图片格式")
565
+ base64_encoded = base64.b64encode(file_content).decode('utf-8')
566
+
567
+ if img_format == 'png':
568
+ return f"data:image/png;base64,{base64_encoded}"
569
+ elif img_format in ['jpg', 'jpeg']:
570
+ return f"data:image/jpeg;base64,{base64_encoded}"
571
+ else:
572
+ raise ValueError(f"不支持的图片格式: {img_format}")
575
573
 
576
- async def get_doc_from_url(url):
577
- filename = urllib.parse.unquote(url.split("/")[-1])
574
+ async def get_image_from_url(url):
578
575
  transport = httpx.AsyncHTTPTransport(
579
576
  http2=True,
580
577
  verify=False,
@@ -586,19 +583,19 @@ async def get_doc_from_url(url):
586
583
  url,
587
584
  timeout=30.0
588
585
  )
589
- with open(filename, 'wb') as f:
590
- f.write(response.content)
586
+ response.raise_for_status()
587
+ return response.content
591
588
 
592
589
  except httpx.RequestError as e:
593
- print(f"An error occurred while requesting {e.request.url!r}.")
594
-
595
- return filename
590
+ logger.error(f"请求 URL 时出错 {e.request.url!r}: {e}")
591
+ raise HTTPException(status_code=400, detail=f"无法从 URL 获取内容: {url}")
592
+ except httpx.HTTPStatusError as e:
593
+ logger.error(f"获取 URL 时发生 HTTP 错误 {e.request.url!r}: {e.response.status_code}")
594
+ raise HTTPException(status_code=e.response.status_code, detail=f"获取 URL 时出错: {url}")
596
595
 
597
596
  async def get_encode_image(image_url):
598
- filename = await get_doc_from_url(image_url)
599
- image_path = os.getcwd() + "/" + filename
600
- base64_image = encode_image(image_path)
601
- os.remove(image_path)
597
+ file_content = await get_image_from_url(image_url)
598
+ base64_image = encode_image(file_content)
602
599
  return base64_image
603
600
 
604
601
  # from PIL import Image
@@ -81,6 +81,7 @@ class chatgpt(BaseLLM):
81
81
  self.function_calls_counter = {}
82
82
  self.function_call_max_loop = function_call_max_loop
83
83
  self.cut_history_by_function_name = cut_history_by_function_name
84
+ self.latest_file_content = {}
84
85
 
85
86
 
86
87
  # 注册和处理传入的工具
@@ -228,6 +229,27 @@ class chatgpt(BaseLLM):
228
229
  else:
229
230
  break
230
231
 
232
+ def get_latest_file_content(self) -> str:
233
+ """
234
+ 获取最新文件内容
235
+ """
236
+ result = ""
237
+ if self.latest_file_content:
238
+ for file_path, content in self.latest_file_content.items():
239
+ result += (
240
+ "<file>"
241
+ f"<file_path>{file_path}</file_path>"
242
+ f"<file_content>{content}</file_content>"
243
+ "</file>\n\n"
244
+ )
245
+ if result:
246
+ result = (
247
+ "<latest_file_content>"
248
+ f"{result}"
249
+ "</latest_file_content>"
250
+ )
251
+ return result
252
+
231
253
  async def get_post_body(
232
254
  self,
233
255
  prompt: str,
@@ -237,7 +259,7 @@ class chatgpt(BaseLLM):
237
259
  pass_history: int = 9999,
238
260
  **kwargs,
239
261
  ):
240
- self.conversation[convo_id][0] = {"role": "system","content": self.system_prompt}
262
+ self.conversation[convo_id][0] = {"role": "system","content": self.system_prompt + "\n\n" + self.get_latest_file_content()}
241
263
 
242
264
  # 构造 provider 信息
243
265
  provider = {
@@ -253,7 +275,7 @@ class chatgpt(BaseLLM):
253
275
  request_data = {
254
276
  "model": model or self.engine,
255
277
  "messages": copy.deepcopy(self.conversation[convo_id]) if pass_history else [
256
- {"role": "system","content": self.system_prompt},
278
+ {"role": "system","content": self.system_prompt + "\n\n" + self.get_latest_file_content()},
257
279
  {"role": role, "content": prompt}
258
280
  ],
259
281
  "stream": True,
@@ -499,7 +521,7 @@ class chatgpt(BaseLLM):
499
521
 
500
522
  for tool_info in tool_calls:
501
523
  tool_name = tool_info['function_name']
502
- tool_args = json.dumps(tool_info['parameter']) if not isinstance(tool_info['parameter'], str) else tool_info['parameter']
524
+ tool_args = json.dumps(tool_info['parameter'], ensure_ascii=False) if not isinstance(tool_info['parameter'], str) else tool_info['parameter']
503
525
  tool_id = tool_info.get('function_call_id', tool_name + "_tool_call")
504
526
 
505
527
  tool_response = ""
@@ -515,7 +537,13 @@ class chatgpt(BaseLLM):
515
537
  tool_response = chunk.replace("function_response:", "")
516
538
  else:
517
539
  yield chunk
518
- all_responses.append(f"[{tool_name}({tool_args}) Result]:\n\n{tool_response}")
540
+ if tool_name == "read_file" and "<read_file error>" not in tool_response:
541
+ self.latest_file_content[tool_info['parameter']["file_path"]] = tool_response
542
+ all_responses.append(f"[{tool_name}({tool_args}) Result]:\n\nRead file successfully! The file content has been updated in the tag <latest_file_content>.")
543
+ elif tool_name == "write_to_file":
544
+ all_responses.append(f"[{tool_name}(...) Result]:\n\n{tool_response}")
545
+ else:
546
+ all_responses.append(f"[{tool_name}({tool_args}) Result]:\n\n{tool_response}")
519
547
 
520
548
  # 合并所有工具响应
521
549
  function_response = "\n\n".join(all_responses)
@@ -795,6 +823,7 @@ class chatgpt(BaseLLM):
795
823
  Reset the conversation
796
824
  """
797
825
  self.system_prompt = system_prompt or self.system_prompt
826
+ self.latest_file_content = {}
798
827
  self.conversation[convo_id] = [
799
828
  {"role": "system", "content": self.system_prompt},
800
829
  ]
@@ -27,7 +27,11 @@ ls -l &amp;&amp; echo 'Hello, World!'
27
27
  # 使用subprocess.run捕获命令输出
28
28
  result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
29
29
  # 返回命令的标准输出
30
- return f"执行命令成功:\n{result.stdout}"
30
+ if "pip install" in command:
31
+ stdout_log = "\n".join([x for x in result.stdout.split('\n') if '━━' not in x])
32
+ else:
33
+ stdout_log = result.stdout
34
+ return f"执行命令成功:\n{stdout_log}"
31
35
  except subprocess.CalledProcessError as e:
32
36
  # 如果命令执行失败,返回错误信息和错误输出
33
37
  return f"执行命令失败 (退出码 {e.returncode}):\n错误: {e.stderr}\n输出: {e.stdout}"
@@ -50,11 +50,11 @@ Examples:
50
50
  try:
51
51
  # 检查文件是否存在
52
52
  if not os.path.exists(file_path):
53
- return f"错误: 文件 '{file_path}' 不存在"
53
+ return f"<read_file error>文件 '{file_path}' 不存在</read_file error>"
54
54
 
55
55
  # 检查是否为文件
56
56
  if not os.path.isfile(file_path):
57
- return f"错误: '{file_path}' 不是一个文件"
57
+ return f"<read_file error>'{file_path}' 不是一个文件</read_file error>"
58
58
 
59
59
  # 检查文件扩展名
60
60
  if file_path.lower().endswith('.pdf'):
@@ -63,7 +63,7 @@ Examples:
63
63
 
64
64
  # 如果提取结果为空
65
65
  if not text_content:
66
- return f"错误: 无法从 '{file_path}' 提取文本内容"
66
+ return f"<read_file error>无法从 '{file_path}' 提取文本内容</read_file error>"
67
67
  elif file_path.lower().endswith('.ipynb'):
68
68
  try:
69
69
  with open(file_path, 'r', encoding='utf-8') as file:
@@ -95,9 +95,9 @@ Examples:
95
95
 
96
96
  text_content = json.dumps(notebook_content, indent=2, ensure_ascii=False)
97
97
  except json.JSONDecodeError:
98
- return f"错误: 文件 '{file_path}' 不是有效的JSON格式 (IPython Notebook)"
98
+ return f"<read_file error>文件 '{file_path}' 不是有效的JSON格式 (IPython Notebook)。</read_file error>"
99
99
  except Exception as e:
100
- return f"处理IPython Notebook文件 '{file_path}' 时发生错误: {e}"
100
+ return f"<read_file error>处理IPython Notebook文件 '{file_path}' 时发生错误: {e}</read_file error>"
101
101
  else:
102
102
  # 读取文件内容
103
103
  with open(file_path, 'r', encoding='utf-8') as file:
@@ -107,11 +107,11 @@ Examples:
107
107
  return text_content
108
108
 
109
109
  except PermissionError:
110
- return f"错误: 没有权限访问文件 '{file_path}'"
110
+ return f"<read_file error>没有权限访问文件 '{file_path}'</read_file error>"
111
111
  except UnicodeDecodeError:
112
- return f"错误: 文件 '{file_path}' 不是文本文件或编码不是UTF-8"
112
+ return f"<read_file error>文件 '{file_path}' 不是文本文件或编码不是UTF-8</read_file error>"
113
113
  except Exception as e:
114
- return f"读取文件时发生错误: {e}"
114
+ return f"<read_file error>读取文件时发生错误: {e}</read_file error>"
115
115
 
116
116
  if __name__ == "__main__":
117
117
  # python -m beswarm.aient.src.aient.plugins.read_file
@@ -48,4 +48,4 @@ Example: Requesting to write to frontend-config.json
48
48
  with open(path, mode, encoding='utf-8') as file:
49
49
  file.write(content)
50
50
 
51
- return f"文件已成功写入:{path}"
51
+ return f"已成功写入文件:{path}"
@@ -28,20 +28,6 @@ def cut_message(message: str, max_tokens: int, model_name: str):
28
28
  encode_text = encoding.encode(message, disallowed_special=())
29
29
  return message, len(encode_text)
30
30
 
31
- import imghdr
32
- def encode_image(image_path):
33
- with open(image_path, "rb") as image_file:
34
- file_content = image_file.read()
35
- file_type = imghdr.what(None, file_content)
36
- base64_encoded = base64.b64encode(file_content).decode('utf-8')
37
-
38
- if file_type == 'png':
39
- return f"data:image/png;base64,{base64_encoded}"
40
- elif file_type in ['jpeg', 'jpg']:
41
- return f"data:image/jpeg;base64,{base64_encoded}"
42
- else:
43
- raise ValueError(f"不支持的图片格式: {file_type}")
44
-
45
31
  def get_doc_from_url(url):
46
32
  filename = urllib.parse.unquote(url.split("/")[-1])
47
33
  response = requests.get(url, stream=True)
@@ -50,13 +36,6 @@ def get_doc_from_url(url):
50
36
  f.write(chunk)
51
37
  return filename
52
38
 
53
- def get_encode_image(image_url):
54
- filename = get_doc_from_url(image_url)
55
- image_path = os.getcwd() + "/" + filename
56
- base64_image = encode_image(image_path)
57
- os.remove(image_path)
58
- return base64_image
59
-
60
39
  from io import BytesIO
61
40
  def get_audio_message(file_bytes):
62
41
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beswarm
3
- Version: 0.1.20
3
+ Version: 0.1.22
4
4
  Summary: MAS
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,21 +1,21 @@
1
1
  beswarm/__init__.py,sha256=HZjUOJtZR5QhMuDbq-wukQQn1VrBusNWai_ysGo-VVI,20
2
2
  beswarm/utils.py,sha256=AdDCcqAIIKQEMl7PfryVgeT9G5sHe7QNsZnrvmTGA8E,283
3
3
  beswarm/aient/main.py,sha256=SiYAIgQlLJqYusnTVEJOx1WNkSJKMImhgn5aWjfroxg,3814
4
- beswarm/aient/setup.py,sha256=EzoroFZIKVg3AI6yCw9_O8zbBKEUmPzLYs5ls_Gdh9E,487
4
+ beswarm/aient/setup.py,sha256=2clD7tuxd3hJrDJeJBsAqDtIyd6qpLLzb4a4-8nz-VE,487
5
5
  beswarm/aient/src/aient/__init__.py,sha256=SRfF7oDVlOOAi6nGKiJIUK6B_arqYLO9iSMp-2IZZps,21
6
6
  beswarm/aient/src/aient/core/__init__.py,sha256=NxjebTlku35S4Dzr16rdSqSTWUvvwEeACe8KvHJnjPg,34
7
7
  beswarm/aient/src/aient/core/log_config.py,sha256=kz2_yJv1p-o3lUQOwA3qh-LSc3wMHv13iCQclw44W9c,274
8
8
  beswarm/aient/src/aient/core/models.py,sha256=_1wYZg_n9kb2A3C8xCboyqleH2iHc9scwOvtx9DPeok,7582
9
- beswarm/aient/src/aient/core/request.py,sha256=PF3hBBzl5RZTda2bAT_Vlp7DiXFhYMzk2Egp7irKVPk,60810
9
+ beswarm/aient/src/aient/core/request.py,sha256=DzjOtWb7rm1frsyKRIsnhONCuttURfwtqERc_qJqHgg,60931
10
10
  beswarm/aient/src/aient/core/response.py,sha256=CSAOQmybBu3i2Yq2YUyi91dZWTN1tmtJEBTI8RFwj_s,30594
11
- beswarm/aient/src/aient/core/utils.py,sha256=R4oKj1oVsdfePdQReaW-ZU4VRTCetvdCKPz_OOTOU_w,26072
11
+ beswarm/aient/src/aient/core/utils.py,sha256=Pmr_ghNsmhKTG65g8_M8BBc_pHGgnD88-SNsJNPJFw4,26158
12
12
  beswarm/aient/src/aient/core/test/test_base_api.py,sha256=pWnycRJbuPSXKKU9AQjWrMAX1wiLC_014Qc9hh5C2Pw,524
13
13
  beswarm/aient/src/aient/core/test/test_image.py,sha256=_T4peNGdXKBHHxyQNx12u-NTyFE8TlYI6NvvagsG2LE,319
14
14
  beswarm/aient/src/aient/core/test/test_payload.py,sha256=8jBiJY1uidm1jzL-EiK0s6UGmW9XkdsuuKFGrwFhFkw,2755
15
15
  beswarm/aient/src/aient/models/__init__.py,sha256=ouNDNvoBBpIFrLsk09Q_sq23HR0GbLAKfGLIFmfEuXE,219
16
16
  beswarm/aient/src/aient/models/audio.py,sha256=kRd-8-WXzv4vwvsTGwnstK-WR8--vr9CdfCZzu8y9LA,1934
17
17
  beswarm/aient/src/aient/models/base.py,sha256=z-Z0pJfTN2x0cuwfvu0BdMRY9O-RmLwHEnBIJN1x4Fg,6719
18
- beswarm/aient/src/aient/models/chatgpt.py,sha256=fWow2ezxduRU3sQxjoK7ZTOAQeY0byP-lCwYf-JcJUM,43105
18
+ beswarm/aient/src/aient/models/chatgpt.py,sha256=AqWgn79hKsfMEx1IEtxU3SaZfJAQ5aFUFN7kKrjZsII,44489
19
19
  beswarm/aient/src/aient/models/claude.py,sha256=thK9P8qkaaoUN3OOJ9Shw4KDs-pAGKPoX4FOPGFXva8,28597
20
20
  beswarm/aient/src/aient/models/duckduckgo.py,sha256=1l7vYCs9SG5SWPCbcl7q6pCcB5AUF_r-a4l9frz3Ogo,8115
21
21
  beswarm/aient/src/aient/models/gemini.py,sha256=chGLc-8G_DAOxr10HPoOhvVFW1RvMgHd6mt--VyAW98,14730
@@ -24,20 +24,20 @@ beswarm/aient/src/aient/models/vertex.py,sha256=qVD5l1Q538xXUPulxG4nmDjXE1VoV4yu
24
24
  beswarm/aient/src/aient/plugins/__init__.py,sha256=p3KO6Aa3Lupos4i2SjzLQw1hzQTigOAfEHngsldrsyk,986
25
25
  beswarm/aient/src/aient/plugins/arXiv.py,sha256=yHjb6PS3GUWazpOYRMKMzghKJlxnZ5TX8z9F6UtUVow,1461
26
26
  beswarm/aient/src/aient/plugins/config.py,sha256=KnZ5xtb5o41FI2_qvxTEQhssdd3WJc7lIAFNR85INQw,7817
27
- beswarm/aient/src/aient/plugins/excute_command.py,sha256=0sQZGLCaRfh0yMM63fXU8XZV7jlo9FKeyEbM-rfgTFg,1209
27
+ beswarm/aient/src/aient/plugins/excute_command.py,sha256=ixSN1q2d3JoJK8OipRB9M2XGMnf4R1b1o_E7F5cUSOU,1392
28
28
  beswarm/aient/src/aient/plugins/get_time.py,sha256=Ih5XIW5SDAIhrZ9W4Qe5Hs1k4ieKPUc_LAd6ySNyqZk,654
29
29
  beswarm/aient/src/aient/plugins/image.py,sha256=ZElCIaZznE06TN9xW3DrSukS7U3A5_cjk1Jge4NzPxw,2072
30
30
  beswarm/aient/src/aient/plugins/list_directory.py,sha256=5ubm-mfrj-tanGSDp4M_Tmb6vQb3dx2-XVfQ2yL2G8A,1394
31
- beswarm/aient/src/aient/plugins/read_file.py,sha256=v07127SXOhS8YGJ6X82Gw2xlk-nlKvX7SdxzZVe1z0Y,4625
31
+ beswarm/aient/src/aient/plugins/read_file.py,sha256=cJxGnhcz1_gjkgeemVyixLUiCvf-dWm-UtDfrbFdlLE,4857
32
32
  beswarm/aient/src/aient/plugins/registry.py,sha256=YknzhieU_8nQ3oKlUSSWDB4X7t2Jx0JnqT2Jd9Xsvfk,3574
33
33
  beswarm/aient/src/aient/plugins/run_python.py,sha256=dgcUwBunMuDkaSKR5bToudVzSdrXVewktDDFUz_iIOQ,4589
34
34
  beswarm/aient/src/aient/plugins/websearch.py,sha256=yiBzqXK5X220ibR-zko3VDsn4QOnLu1k6E2YOygCeTQ,15185
35
- beswarm/aient/src/aient/plugins/write_file.py,sha256=qYbNvcDTGs00pWYb0UOSYSeN4kw5_DMDxjaSlxtlAkU,1732
35
+ beswarm/aient/src/aient/plugins/write_file.py,sha256=FfQgAaojwtHiUORLBBt98mKWddoWgjd3o2UD1v1mgUI,1732
36
36
  beswarm/aient/src/aient/prompt/__init__.py,sha256=GBtn6-JDT8KHFCcuPpfSNE_aGddg5p4FEyMCy4BfwGs,20
37
37
  beswarm/aient/src/aient/prompt/agent.py,sha256=WLs0KiNZs29FJ5w7N3kQZYLVEeS7K8vxIOUw06LcXVE,23825
38
38
  beswarm/aient/src/aient/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  beswarm/aient/src/aient/utils/prompt.py,sha256=UcSzKkFE4-h_1b6NofI6xgk3GoleqALRKY8VBaXLjmI,11311
40
- beswarm/aient/src/aient/utils/scripts.py,sha256=n0jR5eXCBIK12W4bIx-xU1FVl1hZ4zDC7hq_BWQHYJU,27537
40
+ beswarm/aient/src/aient/utils/scripts.py,sha256=PPwaJEigPkpciJHUXOag483iq1GjvaLReHDHjkinv6c,26780
41
41
  beswarm/aient/test/chatgpt.py,sha256=Hvl7FuDt1c74N5TVBmhErOPvJbJJzA7FNp5VoZM4u30,4957
42
42
  beswarm/aient/test/claude.py,sha256=IyB4qI1eJLwlSfDNSnt2FhbQWYyBighHUjJxEXc3osQ,1095
43
43
  beswarm/aient/test/test.py,sha256=rldnoLQdtRR8IKFSIzTti7eIK2MpPMoi9gL5qD8_K44,29
@@ -125,7 +125,7 @@ beswarm/tools/repomap.py,sha256=CwvwoN5Swr42EzrORTTeV8MMb7mPviy4a4b0fxBu50k,4082
125
125
  beswarm/tools/search_arxiv.py,sha256=9slwBemXjEqrd7-YgVmyMijPXlkhZCybEDRVhWVQ9B0,7937
126
126
  beswarm/tools/think.py,sha256=WLw-7jNIsnS6n8MMSYUin_f-BGLENFmnKM2LISEp0co,1760
127
127
  beswarm/tools/worker.py,sha256=JZkMT4JAkrV_0-CBATLAPVZzVGEMMEM2XUTTMGmED0E,5245
128
- beswarm-0.1.20.dist-info/METADATA,sha256=k7N6PewO59xBaDZoNU2ZfhzIdx8E3RQu2K7iVCZs0ug,2870
129
- beswarm-0.1.20.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
130
- beswarm-0.1.20.dist-info/top_level.txt,sha256=pJw4O87wvt5882smuSO6DfByJz7FJ8SxxT8h9fHCmpo,8
131
- beswarm-0.1.20.dist-info/RECORD,,
128
+ beswarm-0.1.22.dist-info/METADATA,sha256=TvB5VYiqaoxoW7nsqcf8D2mBRRwL8cSxPzeI_QSBYE8,2870
129
+ beswarm-0.1.22.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
130
+ beswarm-0.1.22.dist-info/top_level.txt,sha256=pJw4O87wvt5882smuSO6DfByJz7FJ8SxxT8h9fHCmpo,8
131
+ beswarm-0.1.22.dist-info/RECORD,,