beswarm 0.3.10__tar.gz → 0.3.12__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 (138) hide show
  1. {beswarm-0.3.10 → beswarm-0.3.12}/PKG-INFO +1 -1
  2. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/request.py +7 -7
  3. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/search_web.py +7 -1
  4. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/utils.py +40 -12
  5. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm.egg-info/PKG-INFO +1 -1
  6. {beswarm-0.3.10 → beswarm-0.3.12}/pyproject.toml +1 -1
  7. {beswarm-0.3.10 → beswarm-0.3.12}/MANIFEST.in +0 -0
  8. {beswarm-0.3.10 → beswarm-0.3.12}/README.md +0 -0
  9. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/__init__.py +0 -0
  10. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/agents/chatgroup.py +0 -0
  11. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/agents/planact.py +0 -0
  12. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/__init__.py +0 -0
  13. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/architext/architext/__init__.py +0 -0
  14. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/architext/architext/core.py +0 -0
  15. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/architext/test/openai_client.py +0 -0
  16. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/architext/test/test.py +0 -0
  17. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/architext/test/test_save_load.py +0 -0
  18. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/__init__.py +0 -0
  19. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/log_config.py +0 -0
  20. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/models.py +0 -0
  21. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/response.py +0 -0
  22. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/test/test_base_api.py +0 -0
  23. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/test/test_geminimask.py +0 -0
  24. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/test/test_image.py +0 -0
  25. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/test/test_payload.py +0 -0
  26. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/core/utils.py +0 -0
  27. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/models/__init__.py +0 -0
  28. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/models/audio.py +0 -0
  29. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/models/base.py +0 -0
  30. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/models/chatgpt.py +0 -0
  31. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/__init__.py +0 -0
  32. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/arXiv.py +0 -0
  33. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/config.py +0 -0
  34. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/excute_command.py +0 -0
  35. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/get_time.py +0 -0
  36. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/image.py +0 -0
  37. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/list_directory.py +0 -0
  38. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/read_image.py +0 -0
  39. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/readonly.py +0 -0
  40. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/registry.py +0 -0
  41. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/run_python.py +0 -0
  42. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/plugins/websearch.py +0 -0
  43. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/utils/__init__.py +0 -0
  44. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/utils/prompt.py +0 -0
  45. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/aient/utils/scripts.py +0 -0
  46. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/test/test_Web_crawler.py +0 -0
  47. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/test/test_ddg_search.py +0 -0
  48. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/test/test_google_search.py +0 -0
  49. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/test/test_ollama.py +0 -0
  50. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/test/test_plugin.py +0 -0
  51. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/test/test_url.py +0 -0
  52. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/aient/test/test_whisper.py +0 -0
  53. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/bemcp/bemcp/__init__.py +0 -0
  54. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/bemcp/bemcp/decorator.py +0 -0
  55. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/bemcp/bemcp/main.py +0 -0
  56. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/bemcp/bemcp/utils.py +0 -0
  57. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/bemcp/test/client.py +0 -0
  58. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/bemcp/test/server.py +0 -0
  59. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/broker.py +0 -0
  60. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/cli.py +0 -0
  61. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/core.py +0 -0
  62. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/knowledge_graph.py +0 -0
  63. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/prompt.py +0 -0
  64. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/README.md +0 -0
  65. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/arduino-tags.scm +0 -0
  66. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/c-tags.scm +0 -0
  67. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/chatito-tags.scm +0 -0
  68. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -0
  69. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/cpp-tags.scm +0 -0
  70. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/csharp-tags.scm +0 -0
  71. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/d-tags.scm +0 -0
  72. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/dart-tags.scm +0 -0
  73. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/elisp-tags.scm +0 -0
  74. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/elixir-tags.scm +0 -0
  75. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/elm-tags.scm +0 -0
  76. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/gleam-tags.scm +0 -0
  77. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/go-tags.scm +0 -0
  78. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/java-tags.scm +0 -0
  79. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/javascript-tags.scm +0 -0
  80. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/lua-tags.scm +0 -0
  81. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/pony-tags.scm +0 -0
  82. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/properties-tags.scm +0 -0
  83. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/python-tags.scm +0 -0
  84. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/r-tags.scm +0 -0
  85. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/racket-tags.scm +0 -0
  86. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/ruby-tags.scm +0 -0
  87. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/rust-tags.scm +0 -0
  88. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/solidity-tags.scm +0 -0
  89. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/swift-tags.scm +0 -0
  90. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-language-pack/udev-tags.scm +0 -0
  91. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/README.md +0 -0
  92. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/c-tags.scm +0 -0
  93. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
  94. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/cpp-tags.scm +0 -0
  95. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/dart-tags.scm +0 -0
  96. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/elisp-tags.scm +0 -0
  97. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/elixir-tags.scm +0 -0
  98. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/elm-tags.scm +0 -0
  99. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/go-tags.scm +0 -0
  100. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/hcl-tags.scm +0 -0
  101. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/java-tags.scm +0 -0
  102. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/javascript-tags.scm +0 -0
  103. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
  104. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
  105. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/php-tags.scm +0 -0
  106. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/python-tags.scm +0 -0
  107. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/ql-tags.scm +0 -0
  108. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/ruby-tags.scm +0 -0
  109. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/rust-tags.scm +0 -0
  110. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/scala-tags.scm +0 -0
  111. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/queries/tree-sitter-languages/typescript-tags.scm +0 -0
  112. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/taskmanager.py +0 -0
  113. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/__init__.py +0 -0
  114. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/click.py +0 -0
  115. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/completion.py +0 -0
  116. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/deep_search.py +0 -0
  117. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/edit_file.py +0 -0
  118. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/graph.py +0 -0
  119. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/planner.py +0 -0
  120. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/read_file.py +0 -0
  121. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/repomap.py +0 -0
  122. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/request_input.py +0 -0
  123. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/screenshot.py +0 -0
  124. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/search_arxiv.py +0 -0
  125. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/subtasks.py +0 -0
  126. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/worker.py +0 -0
  127. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/write_csv.py +0 -0
  128. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm/tools/write_file.py +0 -0
  129. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm.egg-info/SOURCES.txt +0 -0
  130. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm.egg-info/dependency_links.txt +0 -0
  131. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm.egg-info/entry_points.txt +0 -0
  132. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm.egg-info/requires.txt +0 -0
  133. {beswarm-0.3.10 → beswarm-0.3.12}/beswarm.egg-info/top_level.txt +0 -0
  134. {beswarm-0.3.10 → beswarm-0.3.12}/setup.cfg +0 -0
  135. {beswarm-0.3.10 → beswarm-0.3.12}/test/test_TaskManager.py +0 -0
  136. {beswarm-0.3.10 → beswarm-0.3.12}/test/test_broker.py +0 -0
  137. {beswarm-0.3.10 → beswarm-0.3.12}/test/test_graph.py +0 -0
  138. {beswarm-0.3.10 → beswarm-0.3.12}/test/test_new_TaskManager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beswarm
3
- Version: 0.3.10
3
+ Version: 0.3.12
4
4
  Summary: MAS
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -295,7 +295,7 @@ async def get_gemini_payload(request, engine, provider, api_key=None):
295
295
  if key == request.model:
296
296
  for k, v in value.items():
297
297
  payload[k] = v
298
- elif all(_model not in request.model.lower() for _model in ["gemini", "gpt", "claude", "deepseek"]) and "-" not in key:
298
+ elif all(_model not in request.model.lower() for _model in model_dict.keys()) and "-" not in key:
299
299
  payload[key] = value
300
300
 
301
301
  return url, headers, payload
@@ -591,7 +591,7 @@ async def get_vertex_gemini_payload(request, engine, provider, api_key=None):
591
591
  if key == request.model:
592
592
  for k, v in value.items():
593
593
  payload[k] = v
594
- elif all(_model not in request.model.lower() for _model in ["gemini", "gpt", "claude"]):
594
+ elif all(_model not in request.model.lower() for _model in model_dict.keys()) and "-" not in key:
595
595
  payload[key] = value
596
596
 
597
597
  return url, headers, payload
@@ -1149,7 +1149,7 @@ async def get_gpt_payload(request, engine, provider, api_key=None):
1149
1149
  if key == request.model:
1150
1150
  for k, v in value.items():
1151
1151
  payload[k] = v
1152
- elif all(_model not in request.model.lower() for _model in ["gemini", "gpt", "claude"]):
1152
+ elif all(_model not in request.model.lower() for _model in model_dict.keys()) and "-" not in key:
1153
1153
  payload[key] = value
1154
1154
 
1155
1155
  return url, headers, payload
@@ -1247,7 +1247,7 @@ async def get_azure_payload(request, engine, provider, api_key=None):
1247
1247
  if key == request.model:
1248
1248
  for k, v in value.items():
1249
1249
  payload[k] = v
1250
- elif all(_model not in request.model.lower() for _model in ["gemini", "gpt", "claude"]):
1250
+ elif all(_model not in request.model.lower() for _model in model_dict.keys()) and "-" not in key:
1251
1251
  payload[key] = value
1252
1252
 
1253
1253
  return url, headers, payload
@@ -1367,7 +1367,7 @@ async def get_azure_databricks_payload(request, engine, provider, api_key=None):
1367
1367
  if key == request.model:
1368
1368
  for k, v in value.items():
1369
1369
  payload[k] = v
1370
- elif all(_model not in request.model.lower() for _model in ["gemini", "gpt", "claude"]):
1370
+ elif all(_model not in request.model.lower() for _model in model_dict.keys()) and "-" not in key:
1371
1371
  payload[key] = value
1372
1372
 
1373
1373
  return url, headers, payload
@@ -1454,7 +1454,7 @@ async def get_openrouter_payload(request, engine, provider, api_key=None):
1454
1454
  if key == request.model:
1455
1455
  for k, v in value.items():
1456
1456
  payload[k] = v
1457
- elif all(_model not in request.model.lower() for _model in ["gemini", "gpt", "claude"]):
1457
+ elif all(_model not in request.model.lower() for _model in model_dict.keys()) and "-" not in key:
1458
1458
  payload[key] = value
1459
1459
 
1460
1460
  return url, headers, payload
@@ -1820,7 +1820,7 @@ async def get_claude_payload(request, engine, provider, api_key=None):
1820
1820
  if key == request.model:
1821
1821
  for k, v in value.items():
1822
1822
  payload[k] = v
1823
- elif all(_model not in request.model.lower() for _model in ["gemini", "gpt", "claude"]):
1823
+ elif all(_model not in request.model.lower() for _model in model_dict.keys()) and "-" not in key:
1824
1824
  payload[key] = value
1825
1825
 
1826
1826
  return url, headers, payload
@@ -51,7 +51,13 @@ async def search_web(query: str):
51
51
  async with httpx.AsyncClient() as client:
52
52
  response = await client.post(api_url, headers=headers, data=payload)
53
53
  response.raise_for_status() # 如果状态码是 4xx 或 5xx,则引发 HTTPStatusError
54
- results = json.loads(response.json())
54
+ # The API can return either a JSON object or a string containing JSON.
55
+ # This handles both cases to avoid a TypeError.
56
+ decoded_response = response.json()
57
+ if isinstance(decoded_response, str):
58
+ results = json.loads(decoded_response)
59
+ else:
60
+ results = decoded_response
55
61
  except httpx.HTTPStatusError as e:
56
62
  return {
57
63
  "error": f"HTTP error occurred: {e.response.status_code} - {e.response.text}",
@@ -2,6 +2,9 @@ import re
2
2
  import sys
3
3
  import logging
4
4
  from pathlib import Path
5
+ import queue
6
+ import atexit
7
+ from logging.handlers import QueueHandler, QueueListener
5
8
 
6
9
  def extract_xml_content(text, xml_tag):
7
10
  result = ''
@@ -167,9 +170,17 @@ async def {tool_name}({params_str}):
167
170
  print(f"Failed to create or register function for tool '{tool_name}': {e}")
168
171
  traceback.print_exc()
169
172
 
173
+ # For asynchronous logging
174
+ _listeners = []
175
+ _atexit_registered = False
176
+
177
+ def _stop_all_listeners():
178
+ for listener in _listeners:
179
+ listener.stop()
180
+
170
181
  def setup_logger(logger_name: str, log_file: Path):
171
182
  """
172
- 用最简单的方式设置一个 logger,使其同时输出到文件和终端。
183
+ 用异步方式设置一个 logger,使其同时输出到文件和终端,避免IO阻塞。
173
184
 
174
185
  Args:
175
186
  logger_name (str): Logger 的唯一名称。
@@ -178,35 +189,52 @@ def setup_logger(logger_name: str, log_file: Path):
178
189
  Returns:
179
190
  logging.Logger: 配置好的 logger 实例。
180
191
  """
192
+ global _atexit_registered
193
+
181
194
  # 1. 获取 Logger 实例
182
195
  logger = logging.getLogger(logger_name)
183
196
  logger.setLevel(logging.INFO) # 设置 logger 的最低处理级别为 INFO
184
197
  logger.propagate = False
185
198
 
199
+ # 如果已经配置了异步 handler,直接返回
200
+ if any(isinstance(h, QueueHandler) for h in logger.handlers):
201
+ return logger
202
+
203
+ # 如果有其他 handler,说明被其他方式配置过,也直接返回
186
204
  if logger.hasHandlers():
187
205
  return logger
188
206
 
189
- # 2. 创建文件 Handler
207
+ # 2. 创建用于 Listener 的 Handler(文件和终端)
190
208
  # 确保日志文件所在的目录存在
191
209
  log_file.parent.mkdir(parents=True, exist_ok=True)
192
210
  file_handler = logging.FileHandler(log_file, mode='a', encoding='utf-8')
193
-
194
- # 3. 创建终端 Handler
195
- # 使用 sys.stdout 可以确保输出在标准输出流,与 print() 行为一致
196
211
  stream_handler = logging.StreamHandler(sys.stdout)
197
212
 
198
- # 4. 创建一个通用的 Formatter
213
+ # 3. 创建一个通用的 Formatter
199
214
  formatter = logging.Formatter('%(asctime)s - %(name)s - [%(levelname)s] - %(message)s')
200
215
 
201
- # 5. 为两个 Handler 设置 Formatter
216
+ # 4. 为两个 Handler 设置 Formatter
202
217
  file_handler.setFormatter(formatter)
203
218
  stream_handler.setFormatter(formatter)
204
219
 
205
- # 6. 将两个 Handler 添加到 Logger
206
- # DEBUG = os.getenv("DEBUG", "false").lower() in ("true", "1", "t", "yes")
207
- logger.addHandler(file_handler)
208
- logger.addHandler(stream_handler)
209
- logger.propagate = False
220
+ # 5. 设置 Queue、QueueHandler QueueListener
221
+ log_queue = queue.Queue(-1)
222
+ # listener 在后台线程中从 queue 读取日志,并分发给 file_handler 和 stream_handler
223
+ listener = QueueListener(log_queue, file_handler, stream_handler, respect_handler_level=True)
224
+
225
+ # queue_handler 是一个非阻塞的 handler,它把日志消息放到 queue 中
226
+ queue_handler = QueueHandler(log_queue)
227
+
228
+ # 6. 将 QueueHandler 添加到 Logger
229
+ logger.addHandler(queue_handler)
230
+
231
+ # 7. 启动 listener 并注册 atexit 钩子以确保程序退出时停止
232
+ _listeners.append(listener)
233
+ listener.start()
234
+
235
+ if not _atexit_registered:
236
+ atexit.register(_stop_all_listeners)
237
+ _atexit_registered = True
210
238
 
211
239
  return logger
212
240
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beswarm
3
- Version: 0.3.10
3
+ Version: 0.3.12
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.3.10"
3
+ version = "0.3.12"
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