mars-cmbagent 2.2.0__tar.gz → 2.2.2__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 (229) hide show
  1. {mars_cmbagent-2.2.0/mars_cmbagent.egg-info → mars_cmbagent-2.2.2}/PKG-INFO +5 -4
  2. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/external_tools/__init__.py +15 -5
  3. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/external_tools/ag2_free_tools.py +6 -8
  4. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/external_tools/crewai_tools.py +56 -10
  5. mars_cmbagent-2.2.2/cmbagent/external_tools/langchain_tools.py +303 -0
  6. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/external_tools/news_tools.py +123 -23
  7. mars_cmbagent-2.2.2/cmbagent/external_tools/user_tools.py +345 -0
  8. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/token_manager.py +15 -1
  9. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/workflows/deep_research.py +1 -1
  10. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2/mars_cmbagent.egg-info}/PKG-INFO +5 -4
  11. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/mars_cmbagent.egg-info/SOURCES.txt +1 -0
  12. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/mars_cmbagent.egg-info/requires.txt +4 -3
  13. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/pyproject.toml +13 -4
  14. mars_cmbagent-2.2.0/cmbagent/external_tools/langchain_tools.py +0 -246
  15. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/LICENSE +0 -0
  16. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/MANIFEST.in +0 -0
  17. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/NOTICE +0 -0
  18. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/README.md +0 -0
  19. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/__init__.py +0 -0
  20. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/admin/__init__.py +0 -0
  21. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/admin/admin.yaml +0 -0
  22. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/bash/__init__.py +0 -0
  23. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/bash/bash.py +0 -0
  24. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/bash/bash.yaml +0 -0
  25. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/engineer/__init__.py +0 -0
  26. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/engineer/engineer.yaml +0 -0
  27. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/engineer_nest/__init__.py +0 -0
  28. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/engineer_nest/engineer_nest.yaml +0 -0
  29. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/engineer_response_evaluator/__init__.py +0 -0
  30. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/engineer_response_evaluator/engineer_response_evaluator.py +0 -0
  31. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/engineer_response_evaluator/engineer_response_evaluator.yaml +0 -0
  32. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/execution_recorder/__init__.py +0 -0
  33. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/execution_recorder/execution_recorder.py +0 -0
  34. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/execution_recorder/execution_recorder.yaml +0 -0
  35. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/executor/__init__.py +0 -0
  36. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/executor/executor.yaml +0 -0
  37. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/executor_bash/__init__.py +0 -0
  38. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/executor_bash/executor_bash.yaml +0 -0
  39. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/executor_response_evaluator/__init__.py +0 -0
  40. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/executor_response_evaluator/executor_response_evaluator.py +0 -0
  41. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/executor_response_evaluator/executor_response_evaluator.yaml +0 -0
  42. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/image_review_recorder/__init__.py +0 -0
  43. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/image_review_recorder/image_review_recorder.yaml +0 -0
  44. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/image_reviewer/__init__.py +0 -0
  45. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/image_reviewer/image_reviewer.py +0 -0
  46. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/image_reviewer/image_reviewer.yaml +0 -0
  47. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/parallel_response_selector/__init__.py +0 -0
  48. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/parallel_response_selector/parallel_response_selector.py +0 -0
  49. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/coding/parallel_response_selector/parallel_response_selector.yaml +0 -0
  50. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/control/control_starter/__init__.py +0 -0
  51. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/control/control_starter/control_starter.yaml +0 -0
  52. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/control/controller/__init__.py +0 -0
  53. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/control/controller/controller.yaml +0 -0
  54. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/control/terminator/__init__.py +0 -0
  55. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/control/terminator/terminator.py +0 -0
  56. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/control/terminator/terminator.yaml +0 -0
  57. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_hater/__init__.py +0 -0
  58. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_hater/idea_hater.yaml +0 -0
  59. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_hater_response_evaluator/__init__.py +0 -0
  60. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_hater_response_evaluator/idea_hater_response_evaluator.py +0 -0
  61. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_hater_response_evaluator/idea_hater_response_evaluator.yaml +0 -0
  62. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_maker/__init__.py +0 -0
  63. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_maker/idea_maker.yaml +0 -0
  64. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_maker_response_evaluator/__init__.py +0 -0
  65. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_maker_response_evaluator/idea_maker_response_evaluator.py +0 -0
  66. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_maker_response_evaluator/idea_maker_response_evaluator.yaml +0 -0
  67. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_saver/__init__.py +0 -0
  68. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_saver/idea_saver.py +0 -0
  69. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/hypothesis/idea_saver/idea_saver.yaml +0 -0
  70. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/installer/__init__.py +0 -0
  71. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/installer/installer.py +0 -0
  72. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/installer/installer.yaml +0 -0
  73. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/keywords/aaai_keywords_finder/__init__.py +0 -0
  74. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/keywords/aaai_keywords_finder/aaai_keywords_finder.py +0 -0
  75. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/keywords/aaai_keywords_finder/aaai_keywords_finder.yaml +0 -0
  76. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/keywords/aas_keyword_finder/__init__.py +0 -0
  77. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/keywords/aas_keyword_finder/aas_keyword_finder.yaml +0 -0
  78. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/keywords/list_keywords_finder/__init__.py +0 -0
  79. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/keywords/list_keywords_finder/list_keywords_finder.py +0 -0
  80. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/keywords/list_keywords_finder/list_keywords_finder.yaml +0 -0
  81. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/adaptive_plan_recorder/__init__.py +0 -0
  82. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/adaptive_plan_recorder/adaptive_plan_recorder.py +0 -0
  83. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/adaptive_plan_recorder/adaptive_plan_recorder.yaml +0 -0
  84. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/adaptive_planner/__init__.py +0 -0
  85. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/adaptive_planner/adaptive_planner.py +0 -0
  86. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/adaptive_planner/adaptive_planner.yaml +0 -0
  87. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/adaptive_reviewer/__init__.py +0 -0
  88. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/adaptive_reviewer/adaptive_reviewer.yaml +0 -0
  89. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_comparator/__init__.py +0 -0
  90. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_comparator/plan_comparator.yaml +0 -0
  91. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_recorder/__init__.py +0 -0
  92. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_recorder/plan_recorder.py +0 -0
  93. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_recorder/plan_recorder.yaml +0 -0
  94. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_reviewer/__init__.py +0 -0
  95. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_reviewer/plan_reviewer.yaml +0 -0
  96. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_setter/__init__.py +0 -0
  97. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/plan_setter/plan_setter.yaml +0 -0
  98. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/planner/__init__.py +0 -0
  99. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/planner/planner.yaml +0 -0
  100. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/planner_response_evaluator/__init__.py +0 -0
  101. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/planner_response_evaluator/planner_response_evaluator.py +0 -0
  102. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/planner_response_evaluator/planner_response_evaluator.yaml +0 -0
  103. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/review_recorder/__init__.py +0 -0
  104. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/review_recorder/review_recorder.py +0 -0
  105. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/review_recorder/review_recorder.yaml +0 -0
  106. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/reviewer_response_evaluator/__init__.py +0 -0
  107. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/reviewer_response_evaluator/reviewer_response_evaluator.py +0 -0
  108. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/planning/reviewer_response_evaluator/reviewer_response_evaluator.yaml +0 -0
  109. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/researcher/__init__.py +0 -0
  110. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/researcher/researcher.yaml +0 -0
  111. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/researcher_executor/__init__.py +0 -0
  112. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/researcher_executor/researcher_executor.py +0 -0
  113. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/researcher_executor/researcher_executor.yaml +0 -0
  114. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/researcher_response_evaluator/__init__.py +0 -0
  115. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/researcher_response_evaluator/researcher_response_evaluator.py +0 -0
  116. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/researcher_response_evaluator/researcher_response_evaluator.yaml +0 -0
  117. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/summarizer/__init__.py +0 -0
  118. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/summarizer/summarizer.py +0 -0
  119. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/summarizer/summarizer.yaml +0 -0
  120. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/summarizer_response_evaluator/__init__.py +0 -0
  121. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/summarizer_response_evaluator/summarizer_response_evaluator.py +0 -0
  122. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/agents/research/summarizer_response_evaluator/summarizer_response_evaluator.yaml +0 -0
  123. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/base_agent.py +0 -0
  124. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/callbacks.py +0 -0
  125. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/cmbagent.py +0 -0
  126. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/cmbagent_utils.py +0 -0
  127. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/config/__init__.py +0 -0
  128. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/config/model_config.yaml +0 -0
  129. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/config/model_registry.py +0 -0
  130. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/context.py +0 -0
  131. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/__init__.py +0 -0
  132. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/approval_types.py +0 -0
  133. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/base.py +0 -0
  134. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/dag_builder.py +0 -0
  135. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/dag_executor.py +0 -0
  136. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/dag_metadata.py +0 -0
  137. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/dag_types.py +0 -0
  138. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/dag_visualizer.py +0 -0
  139. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/file_repository.py +0 -0
  140. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/README +0 -0
  141. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/env.py +0 -0
  142. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/script.py.mako +0 -0
  143. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/2_0_0_drop_phase_tables.py +0 -0
  144. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/490016e6a277_add_branch_fields_to_workflow_runs.py +0 -0
  145. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/92e46cb423de_initial_schema.py +0 -0
  146. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/a1b2c3d4e5f6_rename_workflow_step_agent_to_goal.py +0 -0
  147. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/a7b8c9d0e1f2_add_racing_groups.py +0 -0
  148. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/b2c3d4e5f6a7_add_summary_to_workflow_steps.py +0 -0
  149. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/b8c9d0e1f2a3_add_task_stage_support.py +0 -0
  150. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/c3d4e5f6a7b8_add_file_tracking_columns.py +0 -0
  151. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/d4e5f6a7b8c9_add_session_states.py +0 -0
  152. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/e5f6a7b8c9d0_add_approvals_connections.py +0 -0
  153. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/f524830711dc_add_execution_events_and_enhance_.py +0 -0
  154. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/f6a7b8c9d0e1_add_session_id_to_files.py +0 -0
  155. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/migrations/versions/fca0d6632d2f_add_state_history_table.py +0 -0
  156. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/models.py +0 -0
  157. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/persistence.py +0 -0
  158. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/repository.py +0 -0
  159. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/session_manager.py +0 -0
  160. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/state_machine.py +0 -0
  161. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/states.py +0 -0
  162. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/topological_sort.py +0 -0
  163. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/transitions.py +0 -0
  164. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/websocket_approval_manager.py +0 -0
  165. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/database/workflow_controller.py +0 -0
  166. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/execution/__init__.py +0 -0
  167. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/execution/claude_code_escalation.py +0 -0
  168. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/execution/remote_executor.py +0 -0
  169. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/external_tools/integration_helpers.py +0 -0
  170. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/external_tools/tool_adapter.py +0 -0
  171. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/external_tools/tool_registry.py +0 -0
  172. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/__init__.py +0 -0
  173. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/adaptive_review.py +0 -0
  174. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/compare_plans.py +0 -0
  175. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/execution_control.py +0 -0
  176. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/fs_evidence.py +0 -0
  177. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/ideas.py +0 -0
  178. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/image_utils.py +0 -0
  179. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/keywords.py +0 -0
  180. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/parallel_selection.py +0 -0
  181. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/planning.py +0 -0
  182. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/registration.py +0 -0
  183. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/status.py +0 -0
  184. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/utils.py +0 -0
  185. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions/vlm_review.py +0 -0
  186. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/functions.py +0 -0
  187. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/hand_offs.py +0 -0
  188. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/images/logo.png +0 -0
  189. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/llm_provider.py +0 -0
  190. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/phases/__init__.py +0 -0
  191. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/phases/base.py +0 -0
  192. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/phases/execution_manager.py +0 -0
  193. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/phases/registry.py +0 -0
  194. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/__init__.py +0 -0
  195. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/anthropic_provider.py +0 -0
  196. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/aws_bedrock_provider.py +0 -0
  197. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/azure_provider.py +0 -0
  198. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/base.py +0 -0
  199. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/enterprise_gateway_provider.py +0 -0
  200. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/errors.py +0 -0
  201. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/google_provider.py +0 -0
  202. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/mistral_provider.py +0 -0
  203. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/openai_provider.py +0 -0
  204. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/providers/registry.py +0 -0
  205. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/tracing.py +0 -0
  206. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/__init__.py +0 -0
  207. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/arxiv_downloader.py +0 -0
  208. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/context_utils.py +0 -0
  209. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/keywords/aaai.md +0 -0
  210. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/keywords/aas_kwd_to_url.pkl +0 -0
  211. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/keywords/unesco_hierarchical.json +0 -0
  212. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/keywords_utils.py +0 -0
  213. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/message_transforms.py +0 -0
  214. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/ocr.py +0 -0
  215. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/output.py +0 -0
  216. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/paper_downloader.py +0 -0
  217. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/summarization.py +0 -0
  218. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/utils.py +0 -0
  219. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/utils/yaml.py +0 -0
  220. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/version.py +0 -0
  221. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/workflows/__init__.py +0 -0
  222. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/workflows/compare_plans.py +0 -0
  223. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/workflows/keywords.py +0 -0
  224. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/workflows/one_shot.py +0 -0
  225. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/workflows/parallel_fanout.py +0 -0
  226. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/cmbagent/workflows/planning_control.py +0 -0
  227. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/mars_cmbagent.egg-info/dependency_links.txt +0 -0
  228. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/mars_cmbagent.egg-info/top_level.txt +0 -0
  229. {mars_cmbagent-2.2.0 → mars_cmbagent-2.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mars_cmbagent
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: MARS CMBAgent — multi-agent system for autonomous discovery, powered by ag2. Built on the open-source CMBAgents/cmbagent core.
5
5
  Maintainer-email: MARS Team <cmbagent@infosys.com>
6
6
  License-Expression: Apache-2.0
@@ -21,6 +21,10 @@ Requires-Dist: jsonref==1.1.0
21
21
  Requires-Dist: pydantic>=2.7.4
22
22
  Requires-Dist: aiohttp>=3.9.0
23
23
  Requires-Dist: pandas>=2.2
24
+ Requires-Dist: structlog>=24.0
25
+ Requires-Dist: duckduckgo-search>=4.0.0
26
+ Requires-Dist: ddgs>=6.0.0
27
+ Requires-Dist: feedparser>=6.0.11
24
28
  Requires-Dist: ipython
25
29
  Requires-Dist: torch
26
30
  Provides-Extra: tracing
@@ -39,9 +43,6 @@ Requires-Dist: langchain-openai>=0.1.0; extra == "tools"
39
43
  Requires-Dist: langchain-anthropic>=0.1.0; extra == "tools"
40
44
  Requires-Dist: langchain-google-genai>=1.0.0; extra == "tools"
41
45
  Requires-Dist: crewai[tools]>=0.1.0; extra == "tools"
42
- Requires-Dist: duckduckgo-search>=4.0.0; extra == "tools"
43
- Requires-Dist: ddgs>=6.0.0; extra == "tools"
44
- Requires-Dist: feedparser>=6.0.11; extra == "tools"
45
46
  Requires-Dist: wikipedia>=1.4.0; extra == "tools"
46
47
  Requires-Dist: arxiv>=2.0.0; extra == "tools"
47
48
  Requires-Dist: markdownify>=1.0.0; extra == "tools"
@@ -48,13 +48,18 @@ from .news_tools import (
48
48
  announcements_noauth,
49
49
  curated_ai_sources_catalog,
50
50
  curated_ai_sources_search,
51
- newsapi_search,
52
- gnews_search,
53
51
  multi_engine_web_search,
54
52
  scrape_official_news_pages,
55
53
  verify_url,
56
54
  verify_reference_links,
57
55
  )
56
+ from .user_tools import (
57
+ register_tool,
58
+ register_callable,
59
+ register_mcp_server,
60
+ load_tools_from_config,
61
+ list_user_tools,
62
+ )
58
63
 
59
64
  # New AG2 native interoperability functions
60
65
  try:
@@ -93,16 +98,21 @@ __all__ = [
93
98
  'get_langchain_web_tools',
94
99
  'get_langchain_code_tools',
95
100
 
96
- # News and announcement tools
101
+ # Free news and announcement tools (no API key required)
97
102
  'announcements_noauth',
98
103
  'curated_ai_sources_catalog',
99
104
  'curated_ai_sources_search',
100
- 'newsapi_search',
101
- 'gnews_search',
102
105
  'multi_engine_web_search',
103
106
  'scrape_official_news_pages',
104
107
  'verify_url',
105
108
  'verify_reference_links',
109
+
110
+ # User tool onboarding (plain functions, MCP servers, config file)
111
+ 'register_tool',
112
+ 'register_callable',
113
+ 'register_mcp_server',
114
+ 'load_tools_from_config',
115
+ 'list_user_tools',
106
116
  ]
107
117
 
108
118
  # Add AG2 native interop functions if available
@@ -21,9 +21,7 @@ from .news_tools import (
21
21
  announcements_noauth,
22
22
  curated_ai_sources_catalog,
23
23
  curated_ai_sources_search,
24
- gnews_search,
25
24
  multi_engine_web_search,
26
- newsapi_search,
27
25
  scrape_official_news_pages,
28
26
  verify_url,
29
27
  verify_reference_links,
@@ -74,7 +72,11 @@ def _build_safe_duckduckgo_tool() -> Any:
74
72
  title = item.get("title") or item.get("url") or "Untitled"
75
73
  url = item.get("url") or ""
76
74
  engine = item.get("engine") or "fallback"
77
- lines.append(f"{idx}. [{engine}] {title} - {url}")
75
+ body = (item.get("body") or "").strip()
76
+ lines.append(f"{idx}. [{engine}] {title}")
77
+ lines.append(f" URL: {url}")
78
+ if body:
79
+ lines.append(f" Snippet: {body[:400]}")
78
80
  return "\n".join(lines)
79
81
 
80
82
  logger.warning(
@@ -118,11 +120,9 @@ class AG2FreeToolsLoader:
118
120
  }
119
121
 
120
122
  def load_news_tools(self) -> List[Any]:
121
- """Load structured news and announcement retrieval tools."""
123
+ """Load free news and announcement retrieval tools (no API key required)."""
122
124
  tools = [
123
125
  announcements_noauth,
124
- newsapi_search,
125
- gnews_search,
126
126
  scrape_official_news_pages,
127
127
  multi_engine_web_search,
128
128
  curated_ai_sources_catalog,
@@ -132,8 +132,6 @@ class AG2FreeToolsLoader:
132
132
  ]
133
133
  self.loaded_tools['news'] = tools
134
134
  logger.info("tool_loaded", tool="Announcements NoAuth")
135
- logger.info("tool_loaded", tool="NewsAPI")
136
- logger.info("tool_loaded", tool="GNews")
137
135
  logger.info("tool_loaded", tool="Official News Pages")
138
136
  logger.info("tool_loaded", tool="Multi-Engine Web Search")
139
137
  logger.info("tool_loaded", tool="Curated AI Sources Catalog")
@@ -2,8 +2,15 @@
2
2
  CrewAI free tools integration for CMBAgent.
3
3
 
4
4
  This module provides access to CrewAI's free tools that don't require API keys.
5
+
6
+ When ``crewai_tools`` is not installed we log a **single** friendly install hint
7
+ per loader call instead of spamming a separate ``tool_import_failed`` warning
8
+ for every micro-import. Install with::
9
+
10
+ pip install mars_cmbagent[tools] # or: pip install 'crewai[tools]'
5
11
  """
6
12
 
13
+ import importlib
7
14
  import logging
8
15
  import structlog
9
16
  from typing import List
@@ -12,6 +19,25 @@ from .tool_adapter import AG2ToolAdapter, convert_crewai_tool_to_ag2
12
19
  logger = structlog.get_logger(__name__)
13
20
 
14
21
 
22
+ def _crewai_tools_available() -> bool:
23
+ """One-shot check: is the ``crewai_tools`` package importable?"""
24
+ try:
25
+ importlib.import_module("crewai_tools")
26
+ return True
27
+ except ImportError:
28
+ return False
29
+
30
+
31
+ def _log_missing(scope: str) -> None:
32
+ """Log a single friendly install hint (info level, never warning)."""
33
+ logger.info(
34
+ "external_tools_optional_dep_missing",
35
+ scope=scope,
36
+ package="crewai_tools",
37
+ install_hint="pip install mars_cmbagent[tools]",
38
+ )
39
+
40
+
15
41
  def get_crewai_free_tools() -> List[AG2ToolAdapter]:
16
42
  """
17
43
  Get all available free CrewAI tools.
@@ -23,6 +49,10 @@ def get_crewai_free_tools() -> List[AG2ToolAdapter]:
23
49
  >>> from cmbagent.external_tools import get_crewai_free_tools
24
50
  >>> tools = get_crewai_free_tools()
25
51
  """
52
+ if not _crewai_tools_available():
53
+ _log_missing("crewai_free_tools")
54
+ return []
55
+
26
56
  tools = []
27
57
 
28
58
  try:
@@ -39,7 +69,7 @@ def get_crewai_free_tools() -> List[AG2ToolAdapter]:
39
69
  convert_crewai_tool_to_ag2(FileWriteTool()),
40
70
  ])
41
71
  except Exception as e:
42
- logger.warning("tool_import_failed", tool="CrewAI file tools", error=str(e))
72
+ logger.debug("crewai_subtool_import_failed", tool="file", error=str(e))
43
73
 
44
74
  try:
45
75
  # Code analysis tools (free)
@@ -53,7 +83,7 @@ def get_crewai_free_tools() -> List[AG2ToolAdapter]:
53
83
  convert_crewai_tool_to_ag2(CodeInterpreterTool()),
54
84
  ])
55
85
  except Exception as e:
56
- logger.warning("tool_import_failed", tool="CrewAI code tools", error=str(e))
86
+ logger.debug("crewai_subtool_import_failed", tool="code", error=str(e))
57
87
 
58
88
  try:
59
89
  # Web scraping tools (free)
@@ -67,7 +97,7 @@ def get_crewai_free_tools() -> List[AG2ToolAdapter]:
67
97
  convert_crewai_tool_to_ag2(WebsiteSearchTool()),
68
98
  ])
69
99
  except Exception as e:
70
- logger.warning("tool_import_failed", tool="CrewAI web tools", error=str(e))
100
+ logger.debug("crewai_subtool_import_failed", tool="web", error=str(e))
71
101
 
72
102
  try:
73
103
  # Directory and file search tools (free)
@@ -89,7 +119,7 @@ def get_crewai_free_tools() -> List[AG2ToolAdapter]:
89
119
  convert_crewai_tool_to_ag2(MDXSearchTool()),
90
120
  ])
91
121
  except Exception as e:
92
- logger.warning("tool_import_failed", tool="CrewAI search tools", error=str(e))
122
+ logger.debug("crewai_subtool_import_failed", tool="search", error=str(e))
93
123
 
94
124
  try:
95
125
  # PDF tools (free)
@@ -97,7 +127,7 @@ def get_crewai_free_tools() -> List[AG2ToolAdapter]:
97
127
 
98
128
  tools.append(convert_crewai_tool_to_ag2(PDFSearchTool()))
99
129
  except Exception as e:
100
- logger.warning("tool_import_failed", tool="CrewAI PDF tools", error=str(e))
130
+ logger.debug("crewai_subtool_import_failed", tool="pdf", error=str(e))
101
131
 
102
132
  try:
103
133
  # GitHub tools (free with GitHub API)
@@ -105,7 +135,7 @@ def get_crewai_free_tools() -> List[AG2ToolAdapter]:
105
135
 
106
136
  tools.append(convert_crewai_tool_to_ag2(GithubSearchTool()))
107
137
  except Exception as e:
108
- logger.warning("tool_import_failed", tool="CrewAI GitHub tools", error=str(e))
138
+ logger.debug("crewai_subtool_import_failed", tool="github", error=str(e))
109
139
 
110
140
  return tools
111
141
 
@@ -117,6 +147,10 @@ def get_crewai_file_tools() -> List[AG2ToolAdapter]:
117
147
  Returns:
118
148
  List of file-related tools
119
149
  """
150
+ if not _crewai_tools_available():
151
+ _log_missing("crewai_file_tools")
152
+ return []
153
+
120
154
  tools = []
121
155
 
122
156
  try:
@@ -134,7 +168,7 @@ def get_crewai_file_tools() -> List[AG2ToolAdapter]:
134
168
  convert_crewai_tool_to_ag2(DirectorySearchTool()),
135
169
  ])
136
170
  except Exception as e:
137
- logger.warning("tool_import_failed", tool="CrewAI file tools", error=str(e))
171
+ logger.debug("crewai_subtool_import_failed", tool="file", error=str(e))
138
172
 
139
173
  return tools
140
174
 
@@ -146,6 +180,10 @@ def get_crewai_web_tools() -> List[AG2ToolAdapter]:
146
180
  Returns:
147
181
  List of web-related tools
148
182
  """
183
+ if not _crewai_tools_available():
184
+ _log_missing("crewai_web_tools")
185
+ return []
186
+
149
187
  tools = []
150
188
 
151
189
  try:
@@ -159,7 +197,7 @@ def get_crewai_web_tools() -> List[AG2ToolAdapter]:
159
197
  convert_crewai_tool_to_ag2(WebsiteSearchTool()),
160
198
  ])
161
199
  except Exception as e:
162
- logger.warning("tool_import_failed", tool="CrewAI web tools", error=str(e))
200
+ logger.debug("crewai_subtool_import_failed", tool="web", error=str(e))
163
201
 
164
202
  return tools
165
203
 
@@ -171,6 +209,10 @@ def get_crewai_code_tools() -> List[AG2ToolAdapter]:
171
209
  Returns:
172
210
  List of code-related tools
173
211
  """
212
+ if not _crewai_tools_available():
213
+ _log_missing("crewai_code_tools")
214
+ return []
215
+
174
216
  tools = []
175
217
 
176
218
  try:
@@ -184,7 +226,7 @@ def get_crewai_code_tools() -> List[AG2ToolAdapter]:
184
226
  convert_crewai_tool_to_ag2(CodeInterpreterTool()),
185
227
  ])
186
228
  except Exception as e:
187
- logger.warning("tool_import_failed", tool="CrewAI code tools", error=str(e))
229
+ logger.debug("crewai_subtool_import_failed", tool="code", error=str(e))
188
230
 
189
231
  return tools
190
232
 
@@ -196,6 +238,10 @@ def get_crewai_search_tools() -> List[AG2ToolAdapter]:
196
238
  Returns:
197
239
  List of search-related tools
198
240
  """
241
+ if not _crewai_tools_available():
242
+ _log_missing("crewai_search_tools")
243
+ return []
244
+
199
245
  tools = []
200
246
 
201
247
  try:
@@ -217,6 +263,6 @@ def get_crewai_search_tools() -> List[AG2ToolAdapter]:
217
263
  convert_crewai_tool_to_ag2(PDFSearchTool()),
218
264
  ])
219
265
  except Exception as e:
220
- logger.warning("tool_import_failed", tool="CrewAI search tools", error=str(e))
266
+ logger.debug("crewai_subtool_import_failed", tool="search", error=str(e))
221
267
 
222
268
  return tools
@@ -0,0 +1,303 @@
1
+ """
2
+ LangChain free tools integration for CMBAgent.
3
+
4
+ This module provides access to LangChain's free tools that don't require API keys.
5
+
6
+ When ``langchain_community`` (or a sub-dep like ``wikipedia`` / ``arxiv``) is not
7
+ installed we log a **single** friendly install hint per loader call instead of
8
+ spamming a separate ``tool_import_failed`` warning for every micro-import.
9
+
10
+ Install with::
11
+
12
+ pip install mars_cmbagent[tools]
13
+ """
14
+
15
+ import importlib
16
+ import logging
17
+ import structlog
18
+ from typing import List
19
+ from .tool_adapter import AG2ToolAdapter, convert_langchain_tool_to_ag2
20
+ from .ag2_free_tools import _build_safe_duckduckgo_tool
21
+
22
+ logger = structlog.get_logger(__name__)
23
+
24
+
25
+ def _has_module(name: str) -> bool:
26
+ """Return True when ``name`` can be imported. Never raises."""
27
+ try:
28
+ importlib.import_module(name)
29
+ return True
30
+ except ImportError:
31
+ return False
32
+
33
+
34
+ def _langchain_community_available() -> bool:
35
+ """One-shot check: is ``langchain_community`` importable?"""
36
+ return _has_module("langchain_community")
37
+
38
+
39
+ def _log_missing(scope: str, package: str = "langchain_community") -> None:
40
+ """Log a single friendly install hint (info level)."""
41
+ logger.info(
42
+ "external_tools_optional_dep_missing",
43
+ scope=scope,
44
+ package=package,
45
+ install_hint="pip install mars_cmbagent[tools]",
46
+ )
47
+
48
+
49
+ def get_langchain_free_tools() -> List[AG2ToolAdapter]:
50
+ """
51
+ Get all available free LangChain tools.
52
+
53
+ Returns:
54
+ List of AG2ToolAdapter instances for free LangChain tools
55
+
56
+ Example:
57
+ >>> from cmbagent.external_tools import get_langchain_free_tools
58
+ >>> tools = get_langchain_free_tools()
59
+ """
60
+ tools: List[AG2ToolAdapter] = []
61
+
62
+ # DuckDuckGo — never depends on langchain_community. Always try.
63
+ try:
64
+ ddg_fn = _build_safe_duckduckgo_tool()
65
+ tools.append(AG2ToolAdapter(
66
+ tool_name="duckduckgo_search",
67
+ tool_description="Search the web via DuckDuckGo with multi-engine fallbacks.",
68
+ tool_function=ddg_fn,
69
+ ))
70
+ except Exception as e:
71
+ logger.debug("langchain_subtool_import_failed", tool="duckduckgo", error=str(e))
72
+
73
+ if not _langchain_community_available():
74
+ _log_missing("langchain_free_tools")
75
+ return tools # DuckDuckGo already added above
76
+
77
+ # Wikipedia tool (free) — requires langchain_community + wikipedia
78
+ if _has_module("wikipedia"):
79
+ try:
80
+ from langchain_community.tools import WikipediaQueryRun
81
+ from langchain_community.utilities import WikipediaAPIWrapper
82
+ tools.append(convert_langchain_tool_to_ag2(
83
+ WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
84
+ ))
85
+ except Exception as e:
86
+ logger.debug("langchain_subtool_import_failed", tool="wikipedia", error=str(e))
87
+ else:
88
+ logger.info(
89
+ "external_tools_optional_dep_missing",
90
+ scope="wikipedia_tool",
91
+ package="wikipedia",
92
+ install_hint="pip install wikipedia",
93
+ )
94
+
95
+ # ArXiv tool (free) — requires langchain_community + arxiv
96
+ if _has_module("arxiv"):
97
+ try:
98
+ from langchain_community.tools import ArxivQueryRun
99
+ from langchain_community.utilities import ArxivAPIWrapper
100
+ tools.append(convert_langchain_tool_to_ag2(
101
+ ArxivQueryRun(api_wrapper=ArxivAPIWrapper())
102
+ ))
103
+ except Exception as e:
104
+ logger.debug("langchain_subtool_import_failed", tool="arxiv", error=str(e))
105
+ else:
106
+ logger.info(
107
+ "external_tools_optional_dep_missing",
108
+ scope="arxiv_tool",
109
+ package="arxiv",
110
+ install_hint="pip install arxiv",
111
+ )
112
+
113
+ # Python REPL tool (free) — moved to langchain_experimental in newer versions
114
+ try:
115
+ from langchain_community.tools import PythonREPLTool
116
+ tools.append(convert_langchain_tool_to_ag2(PythonREPLTool()))
117
+ except Exception as e:
118
+ logger.debug("langchain_subtool_import_failed", tool="python_repl", error=str(e))
119
+
120
+ # File management tools (free — built-in)
121
+ try:
122
+ from langchain_community.tools import (
123
+ ReadFileTool,
124
+ WriteFileTool,
125
+ ListDirectoryTool,
126
+ )
127
+ tools.extend([
128
+ convert_langchain_tool_to_ag2(ReadFileTool()),
129
+ convert_langchain_tool_to_ag2(WriteFileTool()),
130
+ convert_langchain_tool_to_ag2(ListDirectoryTool()),
131
+ ])
132
+ except Exception as e:
133
+ logger.debug("langchain_subtool_import_failed", tool="file_management", error=str(e))
134
+
135
+ # Shell tool (free but use with caution)
136
+ try:
137
+ from langchain_community.tools import ShellTool
138
+ tools.append(convert_langchain_tool_to_ag2(ShellTool()))
139
+ except Exception as e:
140
+ logger.debug("langchain_subtool_import_failed", tool="shell", error=str(e))
141
+
142
+ # JSON tool (free — built-in)
143
+ try:
144
+ from langchain_community.tools import JsonGetValueTool, JsonListKeysTool
145
+ tools.extend([
146
+ convert_langchain_tool_to_ag2(JsonListKeysTool()),
147
+ convert_langchain_tool_to_ag2(JsonGetValueTool()),
148
+ ])
149
+ except Exception as e:
150
+ logger.debug("langchain_subtool_import_failed", tool="json", error=str(e))
151
+
152
+ # Requests tools (free — built-in)
153
+ try:
154
+ from langchain_community.tools import (
155
+ RequestsGetTool,
156
+ RequestsPostTool,
157
+ RequestsPatchTool,
158
+ RequestsPutTool,
159
+ RequestsDeleteTool,
160
+ )
161
+ tools.extend([
162
+ convert_langchain_tool_to_ag2(RequestsGetTool()),
163
+ convert_langchain_tool_to_ag2(RequestsPostTool()),
164
+ convert_langchain_tool_to_ag2(RequestsPatchTool()),
165
+ convert_langchain_tool_to_ag2(RequestsPutTool()),
166
+ convert_langchain_tool_to_ag2(RequestsDeleteTool()),
167
+ ])
168
+ except Exception as e:
169
+ logger.debug("langchain_subtool_import_failed", tool="requests", error=str(e))
170
+
171
+ logger.info("langchain_tools_loaded", count=len(tools))
172
+ return tools
173
+
174
+
175
+ def get_langchain_search_tools() -> List[AG2ToolAdapter]:
176
+ """
177
+ Get LangChain search and research tools.
178
+
179
+ Returns:
180
+ List of search-related tools
181
+ """
182
+ tools: List[AG2ToolAdapter] = []
183
+ try:
184
+ tools.append(AG2ToolAdapter(
185
+ tool_name="duckduckgo_search",
186
+ tool_description="Search the web via DuckDuckGo with multi-engine fallbacks.",
187
+ tool_function=_build_safe_duckduckgo_tool(),
188
+ ))
189
+ except Exception as e:
190
+ logger.debug("langchain_subtool_import_failed", tool="duckduckgo", error=str(e))
191
+
192
+ if not _langchain_community_available():
193
+ _log_missing("langchain_search_tools")
194
+ return tools
195
+
196
+ if _has_module("wikipedia"):
197
+ try:
198
+ from langchain_community.tools import WikipediaQueryRun
199
+ from langchain_community.utilities import WikipediaAPIWrapper
200
+ tools.append(convert_langchain_tool_to_ag2(
201
+ WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
202
+ ))
203
+ except Exception as e:
204
+ logger.debug("langchain_subtool_import_failed", tool="wikipedia", error=str(e))
205
+
206
+ if _has_module("arxiv"):
207
+ try:
208
+ from langchain_community.tools import ArxivQueryRun
209
+ from langchain_community.utilities import ArxivAPIWrapper
210
+ tools.append(convert_langchain_tool_to_ag2(
211
+ ArxivQueryRun(api_wrapper=ArxivAPIWrapper())
212
+ ))
213
+ except Exception as e:
214
+ logger.debug("langchain_subtool_import_failed", tool="arxiv", error=str(e))
215
+
216
+ return tools
217
+
218
+
219
+ def get_langchain_file_tools() -> List[AG2ToolAdapter]:
220
+ """
221
+ Get LangChain file operation tools.
222
+
223
+ Returns:
224
+ List of file-related tools
225
+ """
226
+ if not _langchain_community_available():
227
+ _log_missing("langchain_file_tools")
228
+ return []
229
+
230
+ tools: List[AG2ToolAdapter] = []
231
+ try:
232
+ from langchain_community.tools import (
233
+ ReadFileTool,
234
+ WriteFileTool,
235
+ ListDirectoryTool,
236
+ )
237
+ tools.extend([
238
+ convert_langchain_tool_to_ag2(ReadFileTool()),
239
+ convert_langchain_tool_to_ag2(WriteFileTool()),
240
+ convert_langchain_tool_to_ag2(ListDirectoryTool()),
241
+ ])
242
+ except Exception as e:
243
+ logger.debug("langchain_subtool_import_failed", tool="file", error=str(e))
244
+ return tools
245
+
246
+
247
+ def get_langchain_web_tools() -> List[AG2ToolAdapter]:
248
+ """
249
+ Get LangChain web/HTTP request tools.
250
+
251
+ Returns:
252
+ List of web-related tools
253
+ """
254
+ if not _langchain_community_available():
255
+ _log_missing("langchain_web_tools")
256
+ return []
257
+
258
+ tools: List[AG2ToolAdapter] = []
259
+ try:
260
+ from langchain_community.tools import (
261
+ RequestsGetTool,
262
+ RequestsPostTool,
263
+ RequestsPatchTool,
264
+ RequestsPutTool,
265
+ RequestsDeleteTool,
266
+ )
267
+ tools.extend([
268
+ convert_langchain_tool_to_ag2(RequestsGetTool()),
269
+ convert_langchain_tool_to_ag2(RequestsPostTool()),
270
+ convert_langchain_tool_to_ag2(RequestsPatchTool()),
271
+ convert_langchain_tool_to_ag2(RequestsPutTool()),
272
+ convert_langchain_tool_to_ag2(RequestsDeleteTool()),
273
+ ])
274
+ except Exception as e:
275
+ logger.debug("langchain_subtool_import_failed", tool="web", error=str(e))
276
+ return tools
277
+
278
+
279
+ def get_langchain_code_tools() -> List[AG2ToolAdapter]:
280
+ """
281
+ Get LangChain code execution tools.
282
+
283
+ Returns:
284
+ List of code-related tools
285
+ """
286
+ if not _langchain_community_available():
287
+ _log_missing("langchain_code_tools")
288
+ return []
289
+
290
+ tools: List[AG2ToolAdapter] = []
291
+ try:
292
+ from langchain_community.tools import (
293
+ PythonREPLTool,
294
+ ShellTool,
295
+ )
296
+ tools.extend([
297
+ convert_langchain_tool_to_ag2(PythonREPLTool()),
298
+ convert_langchain_tool_to_ag2(ShellTool()),
299
+ ])
300
+ except Exception as e:
301
+ logger.debug("langchain_subtool_import_failed", tool="code", error=str(e))
302
+ return tools
303
+