waldiez 0.3.12__tar.gz → 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of waldiez might be problematic. Click here for more details.

Files changed (148) hide show
  1. {waldiez-0.3.12 → waldiez-0.4.1}/PKG-INFO +25 -22
  2. {waldiez-0.3.12 → waldiez-0.4.1}/pyproject.toml +24 -21
  3. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/_version.py +1 -1
  4. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/cli.py +1 -3
  5. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/agent_exporter.py +5 -1
  6. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/captain_agent.py +9 -12
  7. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/swarm_agent.py +12 -7
  8. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/utils/comments.py +1 -0
  9. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/chats/utils/swarm.py +1 -1
  10. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/flow_exporter.py +3 -1
  11. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/utils/__init__.py +3 -6
  12. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/utils/flow_content.py +38 -0
  13. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/utils/importing_utils.py +64 -30
  14. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/utils/logging_utils.py +25 -4
  15. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/skills/skills_exporter.py +13 -6
  16. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/skills/utils.py +92 -6
  17. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agent/__init__.py +2 -1
  18. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agent/agent.py +5 -8
  19. waldiez-0.4.1/waldiez/models/agents/agent/agent_type.py +11 -0
  20. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/captain_agent/captain_agent.py +1 -1
  21. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/group_manager/speakers.py +3 -0
  22. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/rag_user/retrieve_config.py +3 -0
  23. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +1 -0
  24. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/swarm_agent/after_work.py +13 -11
  25. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/swarm_agent/on_condition.py +3 -2
  26. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/swarm_agent/on_condition_available.py +1 -0
  27. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/swarm_agent/swarm_agent_data.py +3 -3
  28. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/swarm_agent/update_system_message.py +1 -0
  29. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/chat/chat_message.py +1 -0
  30. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/chat/chat_summary.py +1 -0
  31. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/common/__init__.py +2 -0
  32. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/common/method_utils.py +98 -0
  33. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/model/__init__.py +2 -1
  34. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/model/extra_requirements.py +2 -0
  35. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/model/model.py +25 -6
  36. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/model/model_data.py +1 -0
  37. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/skill/__init__.py +4 -0
  38. waldiez-0.4.1/waldiez/models/skill/extra_requirements.py +39 -0
  39. waldiez-0.4.1/waldiez/models/skill/skill.py +301 -0
  40. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/skill/skill_data.py +14 -0
  41. waldiez-0.4.1/waldiez/models/skill/skill_type.py +8 -0
  42. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/waldiez.py +36 -6
  43. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/runner.py +19 -7
  44. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/running/environment.py +30 -1
  45. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/running/running.py +0 -6
  46. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/utils/pysqlite3_checker.py +18 -5
  47. waldiez-0.3.12/waldiez/models/skill/skill.py +0 -157
  48. {waldiez-0.3.12 → waldiez-0.4.1}/.gitignore +0 -0
  49. {waldiez-0.3.12 → waldiez-0.4.1}/LICENSE +0 -0
  50. {waldiez-0.3.12 → waldiez-0.4.1}/NOTICE.md +0 -0
  51. {waldiez-0.3.12 → waldiez-0.4.1}/README.md +0 -0
  52. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/__init__.py +0 -0
  53. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/__main__.py +0 -0
  54. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporter.py +0 -0
  55. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/__init__.py +0 -0
  56. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/__init__.py +0 -0
  57. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/__init__.py +0 -0
  58. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/code_execution.py +0 -0
  59. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/group_manager.py +0 -0
  60. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/rag_user/__init__.py +0 -0
  61. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/rag_user/chroma_utils.py +0 -0
  62. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/rag_user/mongo_utils.py +0 -0
  63. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/rag_user/pgvector_utils.py +0 -0
  64. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/rag_user/qdrant_utils.py +0 -0
  65. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/rag_user/rag_user.py +0 -0
  66. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/rag_user/vector_db.py +0 -0
  67. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/reasoning.py +0 -0
  68. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/teachability.py +0 -0
  69. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/agent/utils/termination_message.py +0 -0
  70. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/__init__.py +0 -0
  71. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/agent_position.py +0 -0
  72. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/base_exporter.py +0 -0
  73. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/export_position.py +0 -0
  74. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/import_position.py +0 -0
  75. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/mixin.py +0 -0
  76. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/utils/__init__.py +0 -0
  77. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/utils/naming.py +0 -0
  78. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/utils/path_check.py +0 -0
  79. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/base/utils/to_string.py +0 -0
  80. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/chats/__init__.py +0 -0
  81. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/chats/chats_exporter.py +0 -0
  82. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/chats/utils/__init__.py +0 -0
  83. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/chats/utils/common.py +0 -0
  84. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/chats/utils/nested.py +0 -0
  85. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/chats/utils/sequential.py +0 -0
  86. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/chats/utils/single_chat.py +0 -0
  87. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/__init__.py +0 -0
  88. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/utils/agent_utils.py +0 -0
  89. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/utils/chat_utils.py +0 -0
  90. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/utils/def_main.py +0 -0
  91. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/flow/utils/flow_names.py +0 -0
  92. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/models/__init__.py +0 -0
  93. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/models/models_exporter.py +0 -0
  94. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/models/utils.py +0 -0
  95. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/exporting/skills/__init__.py +0 -0
  96. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/__init__.py +0 -0
  97. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/__init__.py +0 -0
  98. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agent/agent_data.py +0 -0
  99. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agent/code_execution.py +0 -0
  100. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agent/linked_skill.py +0 -0
  101. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agent/nested_chat.py +0 -0
  102. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agent/teachability.py +0 -0
  103. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agent/termination_message.py +0 -0
  104. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/agents.py +0 -0
  105. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/assistant/__init__.py +0 -0
  106. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/assistant/assistant.py +0 -0
  107. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/assistant/assistant_data.py +0 -0
  108. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/captain_agent/__init__.py +0 -0
  109. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/captain_agent/captain_agent_data.py +0 -0
  110. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/captain_agent/captain_agent_lib_entry.py +0 -0
  111. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/extra_requirements.py +0 -0
  112. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/group_manager/__init__.py +0 -0
  113. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/group_manager/group_manager.py +0 -0
  114. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/group_manager/group_manager_data.py +0 -0
  115. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/rag_user/__init__.py +0 -0
  116. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/rag_user/rag_user.py +0 -0
  117. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/rag_user/rag_user_data.py +0 -0
  118. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/rag_user/vector_db_config.py +0 -0
  119. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/reasoning/__init__.py +0 -0
  120. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/reasoning/reasoning_agent.py +0 -0
  121. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/reasoning/reasoning_agent_data.py +0 -0
  122. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/swarm_agent/__init__.py +0 -0
  123. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/swarm_agent/on_condition_target.py +0 -0
  124. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/swarm_agent/swarm_agent.py +0 -0
  125. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/user_proxy/__init__.py +0 -0
  126. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/user_proxy/user_proxy.py +0 -0
  127. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/agents/user_proxy/user_proxy_data.py +0 -0
  128. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/chat/__init__.py +0 -0
  129. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/chat/chat.py +0 -0
  130. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/chat/chat_data.py +0 -0
  131. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/chat/chat_nested.py +0 -0
  132. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/common/ag2_version.py +0 -0
  133. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/common/base.py +0 -0
  134. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/common/date_utils.py +0 -0
  135. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/common/dict_utils.py +0 -0
  136. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/flow/__init__.py +0 -0
  137. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/flow/flow.py +0 -0
  138. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/flow/flow_data.py +0 -0
  139. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/models/flow/utils.py +0 -0
  140. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/py.typed +0 -0
  141. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/running/__init__.py +0 -0
  142. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/running/gen_seq_diagram.py +0 -0
  143. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/utils/__init__.py +0 -0
  144. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/utils/cli_extras/__init__.py +0 -0
  145. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/utils/cli_extras/jupyter.py +0 -0
  146. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/utils/cli_extras/studio.py +0 -0
  147. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/utils/conflict_checker.py +0 -0
  148. {waldiez-0.3.12 → waldiez-0.4.1}/waldiez/utils/flaml_warnings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: waldiez
3
- Version: 0.3.12
3
+ Version: 0.4.1
4
4
  Summary: waldiez
5
5
  Project-URL: homepage, https://waldiez.github.io/waldiez/python
6
6
  Project-URL: repository, https://github.com/waldiez/python.git
@@ -25,9 +25,10 @@ Requires-Dist: asyncer==0.0.8
25
25
  Requires-Dist: graphviz==0.20.3
26
26
  Requires-Dist: httpx<1
27
27
  Requires-Dist: jupytext
28
+ Requires-Dist: numpy<2.2.0
28
29
  Requires-Dist: pandas>=2
29
30
  Requires-Dist: parso==0.8.4
30
- Requires-Dist: pyautogen==0.7.3
31
+ Requires-Dist: pyautogen==0.7.4
31
32
  Requires-Dist: pydantic<3,>=2.6.1
32
33
  Requires-Dist: typer<0.16,>=0.9
33
34
  Provides-Extra: ag2-extras
@@ -44,36 +45,38 @@ Requires-Dist: pgvector>=0.3.6; extra == 'ag2-extras'
44
45
  Requires-Dist: protobuf>=4.25.3; extra == 'ag2-extras'
45
46
  Requires-Dist: psycopg[binary]>=3.2.3; extra == 'ag2-extras'
46
47
  Requires-Dist: psycopg[binary]>=3.2.4; extra == 'ag2-extras'
47
- Requires-Dist: pyautogen[anthropic]==0.7.3; extra == 'ag2-extras'
48
- Requires-Dist: pyautogen[bedrock]==0.7.3; extra == 'ag2-extras'
49
- Requires-Dist: pyautogen[cohere]==0.7.3; extra == 'ag2-extras'
50
- Requires-Dist: pyautogen[gemini]==0.7.3; extra == 'ag2-extras'
51
- Requires-Dist: pyautogen[groq]==0.7.3; extra == 'ag2-extras'
52
- Requires-Dist: pyautogen[lmm]==0.7.3; extra == 'ag2-extras'
53
- Requires-Dist: pyautogen[mistral]==0.7.3; extra == 'ag2-extras'
54
- Requires-Dist: pyautogen[neo4j]==0.7.3; extra == 'ag2-extras'
55
- Requires-Dist: pyautogen[ollama]==0.7.3; extra == 'ag2-extras'
56
- Requires-Dist: pyautogen[together]==0.7.3; extra == 'ag2-extras'
57
- Requires-Dist: pyautogen[websurfer]==0.7.3; extra == 'ag2-extras'
58
- Requires-Dist: pydantic-ai==0.0.21; extra == 'ag2-extras'
48
+ Requires-Dist: pyautogen[anthropic]==0.7.4; extra == 'ag2-extras'
49
+ Requires-Dist: pyautogen[bedrock]==0.7.4; extra == 'ag2-extras'
50
+ Requires-Dist: pyautogen[cohere]==0.7.4; extra == 'ag2-extras'
51
+ Requires-Dist: pyautogen[gemini]==0.7.4; extra == 'ag2-extras'
52
+ Requires-Dist: pyautogen[groq]==0.7.4; extra == 'ag2-extras'
53
+ Requires-Dist: pyautogen[interop-crewai]==0.7.4; extra == 'ag2-extras'
54
+ Requires-Dist: pyautogen[interop-langchain]==0.7.4; extra == 'ag2-extras'
55
+ Requires-Dist: pyautogen[lmm]==0.7.4; extra == 'ag2-extras'
56
+ Requires-Dist: pyautogen[mistral]==0.7.4; extra == 'ag2-extras'
57
+ Requires-Dist: pyautogen[neo4j]==0.7.4; extra == 'ag2-extras'
58
+ Requires-Dist: pyautogen[ollama]==0.7.4; extra == 'ag2-extras'
59
+ Requires-Dist: pyautogen[together]==0.7.4; extra == 'ag2-extras'
60
+ Requires-Dist: pyautogen[websurfer]==0.7.4; extra == 'ag2-extras'
61
+ Requires-Dist: pydantic-ai>=0.0.21; extra == 'ag2-extras'
59
62
  Requires-Dist: pymongo>=4.11; extra == 'ag2-extras'
60
63
  Requires-Dist: pypdf; extra == 'ag2-extras'
61
64
  Requires-Dist: qdrant-client[fastembed]; extra == 'ag2-extras'
62
65
  Requires-Dist: sentence-transformers; extra == 'ag2-extras'
63
- Requires-Dist: weaviate-client==4.10.2; extra == 'ag2-extras'
66
+ Requires-Dist: weaviate-client>=4.10.2; extra == 'ag2-extras'
64
67
  Provides-Extra: dev
65
68
  Requires-Dist: autoflake==2.3.1; extra == 'dev'
66
69
  Requires-Dist: bandit==1.8.2; extra == 'dev'
67
70
  Requires-Dist: black[jupyter]==25.1.0; extra == 'dev'
68
71
  Requires-Dist: flake8==7.1.1; extra == 'dev'
69
72
  Requires-Dist: isort==6.0.0; extra == 'dev'
70
- Requires-Dist: mypy==1.14.1; extra == 'dev'
73
+ Requires-Dist: mypy==1.15.0; extra == 'dev'
71
74
  Requires-Dist: pandas-stubs; extra == 'dev'
72
75
  Requires-Dist: pre-commit==4.1.0; extra == 'dev'
73
76
  Requires-Dist: pydocstyle==6.3.0; extra == 'dev'
74
77
  Requires-Dist: pylint==3.3.4; extra == 'dev'
75
78
  Requires-Dist: python-dotenv==1.0.1; extra == 'dev'
76
- Requires-Dist: ruff==0.9.4; extra == 'dev'
79
+ Requires-Dist: ruff==0.9.6; extra == 'dev'
77
80
  Requires-Dist: toml; (python_version <= '3.10') and extra == 'dev'
78
81
  Requires-Dist: types-pyyaml==6.0.12.20241230; extra == 'dev'
79
82
  Requires-Dist: types-toml==0.10.8.20240310; extra == 'dev'
@@ -83,16 +86,16 @@ Requires-Dist: mdx-include==1.4.2; extra == 'docs'
83
86
  Requires-Dist: mdx-truly-sane-lists==1.3; extra == 'docs'
84
87
  Requires-Dist: mkdocs-jupyter==0.25.1; extra == 'docs'
85
88
  Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == 'docs'
86
- Requires-Dist: mkdocs-material==9.6.2; extra == 'docs'
89
+ Requires-Dist: mkdocs-material==9.6.4; extra == 'docs'
87
90
  Requires-Dist: mkdocs-minify-html-plugin==0.2.4; extra == 'docs'
88
91
  Requires-Dist: mkdocs==1.6.1; extra == 'docs'
89
- Requires-Dist: mkdocstrings-python==1.14.1; extra == 'docs'
90
- Requires-Dist: mkdocstrings[crystal,python]==0.28.0; extra == 'docs'
92
+ Requires-Dist: mkdocstrings-python==1.15.0; extra == 'docs'
93
+ Requires-Dist: mkdocstrings[crystal,python]==0.28.1; extra == 'docs'
91
94
  Provides-Extra: jupyter
92
95
  Requires-Dist: jupyterlab>=4.3.0; extra == 'jupyter'
93
- Requires-Dist: waldiez-jupyter==0.3.12; extra == 'jupyter'
96
+ Requires-Dist: waldiez-jupyter==0.4.1; extra == 'jupyter'
94
97
  Provides-Extra: studio
95
- Requires-Dist: waldiez-studio==0.3.12; extra == 'studio'
98
+ Requires-Dist: waldiez-studio==0.4.1; extra == 'studio'
96
99
  Provides-Extra: test
97
100
  Requires-Dist: pytest-asyncio==0.25.3; extra == 'test'
98
101
  Requires-Dist: pytest-cov==6.0.0; extra == 'test'
@@ -26,9 +26,10 @@ dependencies =[
26
26
  "aiofiles==24.1.0",
27
27
  "aiosqlite==0.21.0",
28
28
  "asyncer==0.0.8",
29
+ "numpy<2.2.0",
29
30
  "graphviz==0.20.3",
30
31
  "pandas>=2",
31
- "pyautogen==0.7.3",
32
+ "pyautogen==0.7.4",
32
33
  "jupytext",
33
34
  "parso==0.8.4",
34
35
  "pydantic>=2.6.1,<3",
@@ -50,10 +51,10 @@ exclude = [ "**/example.py" ]
50
51
 
51
52
  [project.optional-dependencies]
52
53
  studio = [
53
- "waldiez_studio==0.3.12",
54
+ "waldiez_studio==0.4.1",
54
55
  ]
55
56
  jupyter = [
56
- "waldiez_jupyter==0.3.12",
57
+ "waldiez_jupyter==0.4.1",
57
58
  "jupyterlab>=4.3.0",
58
59
  ]
59
60
  dev = [
@@ -62,13 +63,13 @@ dev = [
62
63
  'black[jupyter]==25.1.0',
63
64
  'flake8==7.1.1',
64
65
  'isort==6.0.0',
65
- 'mypy==1.14.1',
66
+ 'mypy==1.15.0',
66
67
  "pandas-stubs",
67
68
  'pre-commit==4.1.0',
68
69
  'pydocstyle==6.3.0',
69
70
  'pylint==3.3.4',
70
71
  'python-dotenv==1.0.1',
71
- 'ruff==0.9.4',
72
+ 'ruff==0.9.6',
72
73
  'types-PyYAML==6.0.12.20241230',
73
74
  'yamllint==1.35.1',
74
75
  'toml; python_version <= "3.10"',
@@ -76,18 +77,20 @@ dev = [
76
77
  ]
77
78
  ag2_extras =[
78
79
  # models
79
- 'pyautogen[anthropic]==0.7.3',
80
- 'pyautogen[bedrock]==0.7.3',
81
- 'pyautogen[cohere]==0.7.3',
82
- 'pyautogen[gemini]==0.7.3',
83
- 'pyautogen[groq]==0.7.3',
84
- 'pyautogen[lmm]==0.7.3',
85
- 'pyautogen[mistral]==0.7.3',
86
- 'pyautogen[ollama]==0.7.3',
87
- 'pyautogen[together]==0.7.3',
80
+ 'pyautogen[anthropic]==0.7.4',
81
+ 'pyautogen[bedrock]==0.7.4',
82
+ 'pyautogen[cohere]==0.7.4',
83
+ 'pyautogen[gemini]==0.7.4',
84
+ 'pyautogen[groq]==0.7.4',
85
+ 'pyautogen[lmm]==0.7.4',
86
+ 'pyautogen[mistral]==0.7.4',
87
+ 'pyautogen[ollama]==0.7.4',
88
+ 'pyautogen[together]==0.7.4',
88
89
  # utils
89
- 'pyautogen[neo4j]==0.7.3',
90
- 'pyautogen[websurfer]==0.7.3',
90
+ 'pyautogen[interop-crewai]==0.7.4',
91
+ 'pyautogen[interop-langchain]==0.7.4',
92
+ 'pyautogen[neo4j]==0.7.4',
93
+ 'pyautogen[websurfer]==0.7.4',
91
94
  'chromadb>=0.5.23',
92
95
  'pgvector>=0.3.6',
93
96
  'psycopg[binary]>=3.2.3',
@@ -104,9 +107,9 @@ ag2_extras =[
104
107
  'crewai-tools==0.33.0',
105
108
  'embedchain==0.1.126',
106
109
  'crewai>0.98.0',
107
- 'weaviate-client==4.10.2',
110
+ 'weaviate-client>=4.10.2',
108
111
  'langchain-community>=0.3.12,<1',
109
- 'pydantic-ai==0.0.21',
112
+ 'pydantic-ai>=0.0.21',
110
113
  'pymongo>=4.11',
111
114
  ]
112
115
  test = [
@@ -124,10 +127,10 @@ docs = [
124
127
  'mkdocs==1.6.1',
125
128
  'mkdocs-jupyter==0.25.1',
126
129
  'mkdocs-macros-plugin==1.3.7',
127
- 'mkdocs-material==9.6.2',
130
+ 'mkdocs-material==9.6.4',
128
131
  'mkdocs-minify-html-plugin==0.2.4',
129
- 'mkdocstrings[crystal,python]==0.28.0',
130
- 'mkdocstrings-python==1.14.1'
132
+ 'mkdocstrings[crystal,python]==0.28.1',
133
+ 'mkdocstrings-python==1.15.0'
131
134
  ]
132
135
 
133
136
  [project.scripts]
@@ -2,4 +2,4 @@
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  """Version information for Waldiez."""
4
4
 
5
- __version__ = "0.3.12"
5
+ __version__ = "0.4.1"
@@ -86,10 +86,8 @@ def run(
86
86
  ),
87
87
  ) -> None:
88
88
  """Run a Waldiez flow."""
89
- # a swarm chat without a user agent
90
- # creates a new user (this has a default code execution with docker)
91
- # temp (until we handle/detect docker setup)
92
89
  os.environ["AUTOGEN_USE_DOCKER"] = "0"
90
+ os.environ["NEP50_DISABLE_WARNING"] = "1"
93
91
  output_path = _get_output_path(output, force)
94
92
  with file.open("r", encoding="utf-8") as _file:
95
93
  try:
@@ -239,7 +239,11 @@ class AgentExporter(BaseExporter, ExporterMixin):
239
239
  extras = (
240
240
  f"{group_chat_arg}{retrieve_arg}{self._reasoning}{self._captain}"
241
241
  )
242
- agent_str = f"""{agent_name} = {self.agent.ag2_class}(
242
+ ag2_class = self.agent.ag2_class
243
+ if agent.agent_type == "swarm":
244
+ # SwarmAgent is deprecated.
245
+ ag2_class = "ConversableAgent"
246
+ agent_str = f"""{agent_name} = {ag2_class}(
243
247
  name="{agent_name}",
244
248
  description="{agent.description}"{system_message_arg},
245
249
  human_input_mode="{agent.data.human_input_mode}",
@@ -47,7 +47,7 @@ def get_captain_agent_extras(
47
47
  return ""
48
48
  agent_name = agent_names[agent.id]
49
49
  save_path = str(output_dir) if output_dir else "."
50
- extra_args_content = "\n" + f' agent_config_save_path=r"{save_path}",'
50
+ extra_args_content = "\n" + " agent_config_save_path=os.getcwd(),"
51
51
  if agent.data.agent_lib:
52
52
  lib_dict = [
53
53
  lib.model_dump(by_alias=False) for lib in agent.data.agent_lib
@@ -56,7 +56,7 @@ def get_captain_agent_extras(
56
56
  agent_lib_path = os.path.join(save_path, lib_json_name)
57
57
  with open(agent_lib_path, "w", encoding="utf-8", newline="\n") as f:
58
58
  json.dump(lib_dict, f, ensure_ascii=False, indent=4)
59
- extra_args_content += "\n" + f' agent_lib=r"{agent_lib_path}",'
59
+ extra_args_content += "\n" + f' agent_lib="{lib_json_name}",'
60
60
  if agent.data.tool_lib:
61
61
  extra_args_content += "\n" + f' tool_lib="{agent.data.tool_lib}",'
62
62
  nested_config = generate_nested_config(
@@ -97,19 +97,15 @@ def generate_nested_config(
97
97
  """
98
98
  config_file_or_env_name = f"{agent_name}_llm_config.json"
99
99
  llm_config = get_llm_config(agent, all_models)
100
- to_serialize = {
101
- "config_list": [llm_config],
102
- }
103
100
  os.makedirs(save_path, exist_ok=True)
104
101
  config_file_or_env_path = os.path.join(save_path, config_file_or_env_name)
105
102
  with open(
106
103
  config_file_or_env_path, "w", encoding="utf-8", newline="\n"
107
104
  ) as f:
108
- json.dump(to_serialize, f, ensure_ascii=False, indent=4)
109
- config_file_or_env = f'r"{config_file_or_env_path}"'
105
+ json.dump([llm_config], f, ensure_ascii=False, indent=4)
110
106
  nested_config = {
111
107
  "autobuild_init_config": {
112
- "config_file_or_env": config_file_or_env,
108
+ "config_file_or_env": config_file_or_env_name,
113
109
  "builder_model": llm_config["model"],
114
110
  "agent_model": llm_config["model"],
115
111
  },
@@ -146,10 +142,11 @@ def get_llm_config(
146
142
  max_tokens: Optional[int] = 2048
147
143
  if agent.data.model_ids:
148
144
  waldiez_model = get_waldiez_model(agent.data.model_ids[0], all_models)
149
- model_name = waldiez_model.name
150
- temperature = waldiez_model.data.temperature
151
- top_p = waldiez_model.data.top_p
152
- max_tokens = waldiez_model.data.max_tokens
145
+ llm_config = waldiez_model.get_llm_config(skip_price=True)
146
+ for key in ["temperature", "top_p", "max_tokens"]:
147
+ if key not in llm_config:
148
+ llm_config[key] = None
149
+ return llm_config
153
150
  config_dict = {
154
151
  "model": model_name,
155
152
  "temperature": temperature,
@@ -21,11 +21,11 @@ from waldiez.models import (
21
21
  # functions (List[Callable]):
22
22
  # -A list of functions to register with the agent.
23
23
  # update_agent_state_before_reply (List[Callable]):
24
- # - A list of functions, including UPDATE_SYSTEM_MESSAGEs,
24
+ # - A list of functions, including UpdateSystemMessage,
25
25
  # called to update the agent before it replies.
26
26
 
27
27
  # Additional methods:
28
- # register_hand_off(hand_offs: List[AfterWork|OnCondition]):
28
+ # register_hand_off(agent, hand_offs: List[AfterWork|OnCondition]):
29
29
 
30
30
 
31
31
  def get_swarm_extras(
@@ -173,14 +173,14 @@ def get_update_agent_state_before_reply_arg(
173
173
  name_suffix=agent_names[agent.id],
174
174
  )
175
175
  arg_string += (
176
- "\n" + f"{tab}{tab}UPDATE_SYSTEM_MESSAGE({function_name}),"
176
+ "\n" + f"{tab}{tab}UpdateSystemMessage({function_name}),"
177
177
  )
178
178
  before_agent += "\n" + function_content + "\n"
179
179
  else:
180
180
  escaped_function = string_escape(function.update_function)
181
181
  arg_string += (
182
182
  "\n"
183
- + f'{tab}{tab}UPDATE_SYSTEM_MESSAGE("{escaped_function}"),'
183
+ + f'{tab}{tab}UpdateSystemMessage("{escaped_function}"),'
184
184
  )
185
185
  else:
186
186
  skill_name = skill_names.get(function, "")
@@ -233,7 +233,12 @@ def get_agent_handoff_registrations(
233
233
  if not agent.handoffs:
234
234
  return before_agent, after_agent
235
235
  tab = " "
236
- after_agent = f"{agent_name}.register_hand_off(" + "\n" + f"{tab}[" + "\n"
236
+ # change {agent}.register_hand_off([...
237
+ # to register_hand_off({agent}, [...
238
+ # after_agent = f"{agent_name}.register_hand_off(" + "\n" + f"{tab}[" + "\n"
239
+ after_agent = (
240
+ "register_hand_off(\n" + f"{tab}{agent_name}," + "\n" + f"{tab}[" + "\n"
241
+ )
237
242
  for hand_off in agent.handoffs:
238
243
  if isinstance(hand_off, WaldiezSwarmOnCondition):
239
244
  registration, before_handoff = get_agent_on_condition_handoff(
@@ -385,7 +390,7 @@ def _get_agent_on_condition_handoff_to_agent(
385
390
  before_agent = ""
386
391
  tab = " "
387
392
  on_condition = (
388
- f"{tab}{tab}ON_CONDITION(" + "\n"
393
+ f"{tab}{tab}OnCondition(" + "\n"
389
394
  f"{tab}{tab}{tab}target={recipient}," + "\n"
390
395
  f'{tab}{tab}{tab}condition="{condition}",' + "\n"
391
396
  )
@@ -431,7 +436,7 @@ def _get_agent_on_condition_handoff_to_nested_chat(
431
436
  before_agent += f"{chat_queue_var_name} = {chat_queue} " + "\n"
432
437
  condition_string = string_escape(condition)
433
438
  on_condition = (
434
- f"{tab}{tab}ON_CONDITION(" + "\n"
439
+ f"{tab}{tab}OnCondition(" + "\n"
435
440
  f"{tab}{tab}{tab}target=" + "{\n"
436
441
  f'{tab}{tab}{tab}{tab}"chat_queue": {chat_queue_var_name},' + "\n"
437
442
  f'{tab}{tab}{tab}{tab}"config": None,' + "\n"
@@ -13,6 +13,7 @@ from typing_extensions import Literal
13
13
  CommentKey = Literal[
14
14
  "agents", "imports", "skills", "models", "nested", "run", "logging"
15
15
  ]
16
+ """Possible keys for comments."""
16
17
 
17
18
 
18
19
  def comment(for_notebook: bool, hashtags: int = 1) -> str:
@@ -196,7 +196,7 @@ def get_swarm_after_work_string(
196
196
  The after work string and the additional methods string.
197
197
  """
198
198
  if not chat.after_work:
199
- return "AFTER_WORK(AfterWorkOption.TERMINATE)", ""
199
+ return "AfterWork(AfterWorkOption.TERMINATE)", ""
200
200
  additional_methods = ""
201
201
  after_work_string, function_content = chat.after_work.get_recipient(
202
202
  agent_names=agent_names,
@@ -52,6 +52,7 @@ from .utils import (
52
52
  get_after_run_content,
53
53
  get_def_main,
54
54
  get_ipynb_content_start,
55
+ get_np_no_nep50_handle,
55
56
  get_py_content_start,
56
57
  get_sqlite_out,
57
58
  get_start_logging,
@@ -210,8 +211,9 @@ class FlowExporter(BaseExporter, ExporterMixin):
210
211
  )
211
212
  content += self.get_comment("imports", self.for_notebook) + "\n"
212
213
  content += imports[0] + "\n"
214
+ content += get_np_no_nep50_handle() + "\n"
213
215
  content += self.get_comment("logging", self.for_notebook) + "\n"
214
- content += get_start_logging(tabs=0) + "\n"
216
+ content += get_start_logging(is_async=is_async, tabs=0) + "\n"
215
217
  content += "start_logging()\n\n"
216
218
  if models_output:
217
219
  content += self.get_comment("models", self.for_notebook) + "\n"
@@ -14,14 +14,11 @@ from .def_main import get_def_main
14
14
  from .flow_content import (
15
15
  get_after_run_content,
16
16
  get_ipynb_content_start,
17
+ get_np_no_nep50_handle,
17
18
  get_py_content_start,
18
19
  )
19
20
  from .flow_names import ensure_unique_names
20
- from .importing_utils import (
21
- gather_imports,
22
- get_standard_imports,
23
- get_the_imports_string,
24
- )
21
+ from .importing_utils import gather_imports, get_the_imports_string
25
22
  from .logging_utils import (
26
23
  get_sqlite_out,
27
24
  get_sqlite_out_call,
@@ -41,12 +38,12 @@ __all__ = [
41
38
  "gather_imports",
42
39
  "get_after_run_content",
43
40
  "get_def_main",
41
+ "get_np_no_nep50_handle",
44
42
  "get_py_content_start",
45
43
  "get_ipynb_content_start",
46
44
  "get_start_logging",
47
45
  "get_stop_logging",
48
46
  "get_sqlite_out",
49
47
  "get_sqlite_out_call",
50
- "get_standard_imports",
51
48
  "get_the_imports_string",
52
49
  ]
@@ -71,12 +71,14 @@ PYLINT_RULES = [
71
71
  "unknown-option-value",
72
72
  "unused-argument",
73
73
  "unused-import",
74
+ "unused-variable",
74
75
  "invalid-name",
75
76
  "import-error",
76
77
  "inconsistent-quotes",
77
78
  "missing-function-docstring",
78
79
  "missing-param-doc",
79
80
  "missing-return-doc",
81
+ "ungrouped-imports",
80
82
  ]
81
83
 
82
84
 
@@ -159,3 +161,39 @@ def get_after_run_content(
159
161
  {space}{tab}pass
160
162
  """
161
163
  return content
164
+
165
+
166
+ def get_np_no_nep50_handle() -> str:
167
+ """Handle catching the "module numpy has no attribute _no_pep50_warning" error.
168
+
169
+ Returns
170
+ -------
171
+ str
172
+ The content to handle the error.
173
+ """
174
+ # https://github.com/numpy/numpy/blob/v2.2.2/\
175
+ # doc/source/release/2.2.0-notes.rst#nep-50-promotion-state-option-removed
176
+ content = '''
177
+ # try to make sure we don't get:
178
+ # module 'numpy' has no attribute '_no_nep50_warning'"
179
+ os.environ["NEP50_DEPRECATION_WARNING"] = "0"
180
+ os.environ["NEP50_DISABLE_WARNING"] = "1"
181
+ os.environ["NPY_PROMOTION_STATE"] = "weak"
182
+ if not hasattr(np, "_no_pep50_warning"):
183
+
184
+ import contextlib
185
+ from typing import Generator
186
+
187
+ @contextlib.contextmanager
188
+ def _np_no_nep50_warning() -> Generator[None, None, None]:
189
+ """Dummy function to avoid the warning.
190
+
191
+ Yields
192
+ ------
193
+ None
194
+ Nothing.
195
+ """
196
+ yield
197
+ setattr(np, "_no_pep50_warning", _np_no_nep50_warning) # noqa
198
+ '''
199
+ return content
@@ -36,21 +36,6 @@ COMMON_AUTOGEN_IMPORTS = [
36
36
  ]
37
37
 
38
38
 
39
- def get_standard_imports() -> str:
40
- """Get the standard imports.
41
-
42
- Returns
43
- -------
44
- str
45
- The standard imports.
46
- """
47
- builtin_imports = BUILTIN_IMPORTS.copy()
48
- imports_string = "\n".join(builtin_imports) + "\n"
49
- typing_imports = "from typing import " + ", ".join(TYPING_IMPORTS)
50
- imports_string += typing_imports
51
- return imports_string
52
-
53
-
54
39
  def sort_imports(
55
40
  all_imports: List[Tuple[str, ImportPosition]],
56
41
  ) -> Tuple[List[str], List[str], List[str], List[str], bool]:
@@ -66,10 +51,10 @@ def sort_imports(
66
51
  Tuple[List[str], List[str], List[str], List[str], bool]
67
52
  The sorted imports and a flag if we got `import autogen`.
68
53
  """
69
- builtin_imports = []
70
- third_party_imports = []
71
- local_imports = []
72
- autogen_imports = COMMON_AUTOGEN_IMPORTS.copy()
54
+ builtin_imports: List[str] = []
55
+ third_party_imports: List[str] = []
56
+ local_imports: List[str] = []
57
+ autogen_imports: List[str] = COMMON_AUTOGEN_IMPORTS.copy()
73
58
  got_import_autogen = False
74
59
  for import_string, position in all_imports:
75
60
  if "import autogen" in import_string:
@@ -85,11 +70,22 @@ def sort_imports(
85
70
  elif position == ImportPosition.LOCAL:
86
71
  local_imports.append(import_string)
87
72
  autogen_imports = list(set(autogen_imports))
73
+ third_party_imports = ensure_np_import(third_party_imports)
74
+ sorted_builtins = sorted(
75
+ [imp for imp in builtin_imports if imp.startswith("import ")]
76
+ ) + sorted([imp for imp in builtin_imports if imp.startswith("from ")])
77
+ sorted_third_party = sorted(
78
+ [imp for imp in third_party_imports if imp.startswith("import ")]
79
+ ) + sorted([imp for imp in third_party_imports if imp.startswith("from ")])
80
+ sorted_locals = sorted(
81
+ [imp for imp in local_imports if imp.startswith("import ")]
82
+ ) + sorted([imp for imp in local_imports if imp.startswith("from ")])
83
+
88
84
  return (
89
- sorted(builtin_imports),
85
+ sorted_builtins,
90
86
  sorted(autogen_imports),
91
- sorted(third_party_imports),
92
- sorted(local_imports),
87
+ sorted_third_party,
88
+ sorted_locals,
93
89
  got_import_autogen,
94
90
  )
95
91
 
@@ -131,7 +127,6 @@ def get_the_imports_string(
131
127
  "\nimport anyio"
132
128
  "\nimport nest_asyncio"
133
129
  "\nfrom aiocsv import AsyncDictWriter"
134
- "\nfrom asyncer import asyncify"
135
130
  )
136
131
  if got_import_autogen:
137
132
  final_string += "\nimport autogen # type: ignore\n"
@@ -150,6 +145,27 @@ def get_the_imports_string(
150
145
  return final_string.replace("\n\n\n", "\n\n") # avoid too many newlines
151
146
 
152
147
 
148
+ def ensure_np_import(third_party_imports: List[str]) -> List[str]:
149
+ """Ensure numpy is imported.
150
+
151
+ Parameters
152
+ ----------
153
+ third_party_imports : List[str]
154
+ The third party imports.
155
+
156
+ Returns
157
+ -------
158
+ List[str]
159
+ The third party imports with numpy.
160
+ """
161
+ if (
162
+ not third_party_imports
163
+ or "import numpy as np" not in third_party_imports
164
+ ):
165
+ third_party_imports.append("import numpy as np")
166
+ return third_party_imports
167
+
168
+
153
169
  def gather_imports(
154
170
  model_imports: Optional[List[Tuple[str, ImportPosition]]],
155
171
  skill_imports: Optional[List[Tuple[str, ImportPosition]]],
@@ -174,13 +190,14 @@ def gather_imports(
174
190
  Tuple[str, ImportPosition]
175
191
  The gathered imports.
176
192
  """
177
- imports_string = get_standard_imports()
178
- all_imports: List[Tuple[str, ImportPosition]] = [
179
- (
180
- imports_string,
181
- ImportPosition.BUILTINS,
193
+ all_imports: List[Tuple[str, ImportPosition]] = []
194
+ for import_statement in BUILTIN_IMPORTS:
195
+ all_imports.append(
196
+ (
197
+ import_statement,
198
+ ImportPosition.BUILTINS,
199
+ )
182
200
  )
183
- ]
184
201
  if model_imports:
185
202
  all_imports.extend(model_imports)
186
203
  if skill_imports:
@@ -189,4 +206,21 @@ def gather_imports(
189
206
  all_imports.extend(chat_imports)
190
207
  if agent_imports:
191
208
  all_imports.extend(agent_imports)
192
- return list(set(all_imports))
209
+ # let's try to avoid this:
210
+ # from typing import Annotated
211
+ # from typing import Annotated, Any, Callable, Dict, ...Union
212
+ all_typing_imports = TYPING_IMPORTS.copy()
213
+ final_imports: List[Tuple[str, ImportPosition]] = []
214
+ for import_statement, import_position in all_imports:
215
+ if import_statement.startswith("from typing"):
216
+ to_import = import_statement.split("import")[1].strip()
217
+ if to_import:
218
+ all_typing_imports.append(to_import)
219
+ else:
220
+ final_imports.append((import_statement, import_position))
221
+ unique_typing_imports = list(set(all_typing_imports))
222
+ one_typing_import = "from typing import " + ", ".join(
223
+ sorted(unique_typing_imports)
224
+ )
225
+ final_imports.insert(1, (one_typing_import, ImportPosition.BUILTINS))
226
+ return list(set(final_imports))