ag2 0.9.1__py3-none-any.whl → 0.9.1.post0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (357) hide show
  1. {ag2-0.9.1.dist-info → ag2-0.9.1.post0.dist-info}/METADATA +264 -73
  2. ag2-0.9.1.post0.dist-info/RECORD +392 -0
  3. {ag2-0.9.1.dist-info → ag2-0.9.1.post0.dist-info}/WHEEL +1 -2
  4. autogen/__init__.py +89 -0
  5. autogen/_website/__init__.py +3 -0
  6. autogen/_website/generate_api_references.py +427 -0
  7. autogen/_website/generate_mkdocs.py +1174 -0
  8. autogen/_website/notebook_processor.py +476 -0
  9. autogen/_website/process_notebooks.py +656 -0
  10. autogen/_website/utils.py +412 -0
  11. autogen/agentchat/__init__.py +44 -0
  12. autogen/agentchat/agent.py +182 -0
  13. autogen/agentchat/assistant_agent.py +85 -0
  14. autogen/agentchat/chat.py +309 -0
  15. autogen/agentchat/contrib/__init__.py +5 -0
  16. autogen/agentchat/contrib/agent_eval/README.md +7 -0
  17. autogen/agentchat/contrib/agent_eval/agent_eval.py +108 -0
  18. autogen/agentchat/contrib/agent_eval/criterion.py +43 -0
  19. autogen/agentchat/contrib/agent_eval/critic_agent.py +44 -0
  20. autogen/agentchat/contrib/agent_eval/quantifier_agent.py +39 -0
  21. autogen/agentchat/contrib/agent_eval/subcritic_agent.py +45 -0
  22. autogen/agentchat/contrib/agent_eval/task.py +42 -0
  23. autogen/agentchat/contrib/agent_optimizer.py +429 -0
  24. autogen/agentchat/contrib/capabilities/__init__.py +5 -0
  25. autogen/agentchat/contrib/capabilities/agent_capability.py +20 -0
  26. autogen/agentchat/contrib/capabilities/generate_images.py +301 -0
  27. autogen/agentchat/contrib/capabilities/teachability.py +393 -0
  28. autogen/agentchat/contrib/capabilities/text_compressors.py +66 -0
  29. autogen/agentchat/contrib/capabilities/tools_capability.py +22 -0
  30. autogen/agentchat/contrib/capabilities/transform_messages.py +93 -0
  31. autogen/agentchat/contrib/capabilities/transforms.py +566 -0
  32. autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
  33. autogen/agentchat/contrib/capabilities/vision_capability.py +214 -0
  34. autogen/agentchat/contrib/captainagent/__init__.py +9 -0
  35. autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
  36. autogen/agentchat/contrib/captainagent/captainagent.py +512 -0
  37. autogen/agentchat/contrib/captainagent/tool_retriever.py +335 -0
  38. autogen/agentchat/contrib/captainagent/tools/README.md +44 -0
  39. autogen/agentchat/contrib/captainagent/tools/__init__.py +5 -0
  40. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +40 -0
  41. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +28 -0
  42. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +28 -0
  43. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +28 -0
  44. autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +21 -0
  45. autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +30 -0
  46. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +27 -0
  47. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +53 -0
  48. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +53 -0
  49. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +38 -0
  50. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +21 -0
  51. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +34 -0
  52. autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +60 -0
  53. autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +61 -0
  54. autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +47 -0
  55. autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +33 -0
  56. autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +21 -0
  57. autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +35 -0
  58. autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +21 -0
  59. autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +18 -0
  60. autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +28 -0
  61. autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +31 -0
  62. autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +16 -0
  63. autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +25 -0
  64. autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +23 -0
  65. autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +27 -0
  66. autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +28 -0
  67. autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +34 -0
  68. autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +39 -0
  69. autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +23 -0
  70. autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +36 -0
  71. autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +15 -0
  72. autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +15 -0
  73. autogen/agentchat/contrib/captainagent/tools/requirements.txt +10 -0
  74. autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +34 -0
  75. autogen/agentchat/contrib/gpt_assistant_agent.py +526 -0
  76. autogen/agentchat/contrib/graph_rag/__init__.py +9 -0
  77. autogen/agentchat/contrib/graph_rag/document.py +29 -0
  78. autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +170 -0
  79. autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +103 -0
  80. autogen/agentchat/contrib/graph_rag/graph_query_engine.py +53 -0
  81. autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +63 -0
  82. autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +268 -0
  83. autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +83 -0
  84. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +210 -0
  85. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +93 -0
  86. autogen/agentchat/contrib/img_utils.py +397 -0
  87. autogen/agentchat/contrib/llamaindex_conversable_agent.py +117 -0
  88. autogen/agentchat/contrib/llava_agent.py +187 -0
  89. autogen/agentchat/contrib/math_user_proxy_agent.py +464 -0
  90. autogen/agentchat/contrib/multimodal_conversable_agent.py +125 -0
  91. autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +324 -0
  92. autogen/agentchat/contrib/rag/__init__.py +10 -0
  93. autogen/agentchat/contrib/rag/chromadb_query_engine.py +272 -0
  94. autogen/agentchat/contrib/rag/llamaindex_query_engine.py +198 -0
  95. autogen/agentchat/contrib/rag/mongodb_query_engine.py +329 -0
  96. autogen/agentchat/contrib/rag/query_engine.py +74 -0
  97. autogen/agentchat/contrib/retrieve_assistant_agent.py +56 -0
  98. autogen/agentchat/contrib/retrieve_user_proxy_agent.py +703 -0
  99. autogen/agentchat/contrib/society_of_mind_agent.py +199 -0
  100. autogen/agentchat/contrib/swarm_agent.py +1425 -0
  101. autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
  102. autogen/agentchat/contrib/vectordb/__init__.py +5 -0
  103. autogen/agentchat/contrib/vectordb/base.py +232 -0
  104. autogen/agentchat/contrib/vectordb/chromadb.py +315 -0
  105. autogen/agentchat/contrib/vectordb/couchbase.py +407 -0
  106. autogen/agentchat/contrib/vectordb/mongodb.py +550 -0
  107. autogen/agentchat/contrib/vectordb/pgvectordb.py +928 -0
  108. autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
  109. autogen/agentchat/contrib/vectordb/utils.py +126 -0
  110. autogen/agentchat/contrib/web_surfer.py +303 -0
  111. autogen/agentchat/conversable_agent.py +4020 -0
  112. autogen/agentchat/group/__init__.py +64 -0
  113. autogen/agentchat/group/available_condition.py +91 -0
  114. autogen/agentchat/group/context_condition.py +77 -0
  115. autogen/agentchat/group/context_expression.py +238 -0
  116. autogen/agentchat/group/context_str.py +41 -0
  117. autogen/agentchat/group/context_variables.py +192 -0
  118. autogen/agentchat/group/group_tool_executor.py +202 -0
  119. autogen/agentchat/group/group_utils.py +591 -0
  120. autogen/agentchat/group/handoffs.py +244 -0
  121. autogen/agentchat/group/llm_condition.py +93 -0
  122. autogen/agentchat/group/multi_agent_chat.py +237 -0
  123. autogen/agentchat/group/on_condition.py +58 -0
  124. autogen/agentchat/group/on_context_condition.py +54 -0
  125. autogen/agentchat/group/patterns/__init__.py +18 -0
  126. autogen/agentchat/group/patterns/auto.py +159 -0
  127. autogen/agentchat/group/patterns/manual.py +176 -0
  128. autogen/agentchat/group/patterns/pattern.py +288 -0
  129. autogen/agentchat/group/patterns/random.py +106 -0
  130. autogen/agentchat/group/patterns/round_robin.py +117 -0
  131. autogen/agentchat/group/reply_result.py +26 -0
  132. autogen/agentchat/group/speaker_selection_result.py +41 -0
  133. autogen/agentchat/group/targets/__init__.py +4 -0
  134. autogen/agentchat/group/targets/group_chat_target.py +132 -0
  135. autogen/agentchat/group/targets/group_manager_target.py +151 -0
  136. autogen/agentchat/group/targets/transition_target.py +413 -0
  137. autogen/agentchat/group/targets/transition_utils.py +6 -0
  138. autogen/agentchat/groupchat.py +1694 -0
  139. autogen/agentchat/realtime/__init__.py +3 -0
  140. autogen/agentchat/realtime/experimental/__init__.py +20 -0
  141. autogen/agentchat/realtime/experimental/audio_adapters/__init__.py +8 -0
  142. autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +148 -0
  143. autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +139 -0
  144. autogen/agentchat/realtime/experimental/audio_observer.py +42 -0
  145. autogen/agentchat/realtime/experimental/clients/__init__.py +15 -0
  146. autogen/agentchat/realtime/experimental/clients/gemini/__init__.py +7 -0
  147. autogen/agentchat/realtime/experimental/clients/gemini/client.py +274 -0
  148. autogen/agentchat/realtime/experimental/clients/oai/__init__.py +8 -0
  149. autogen/agentchat/realtime/experimental/clients/oai/base_client.py +220 -0
  150. autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +243 -0
  151. autogen/agentchat/realtime/experimental/clients/oai/utils.py +48 -0
  152. autogen/agentchat/realtime/experimental/clients/realtime_client.py +190 -0
  153. autogen/agentchat/realtime/experimental/function_observer.py +85 -0
  154. autogen/agentchat/realtime/experimental/realtime_agent.py +158 -0
  155. autogen/agentchat/realtime/experimental/realtime_events.py +42 -0
  156. autogen/agentchat/realtime/experimental/realtime_observer.py +100 -0
  157. autogen/agentchat/realtime/experimental/realtime_swarm.py +475 -0
  158. autogen/agentchat/realtime/experimental/websockets.py +21 -0
  159. autogen/agentchat/realtime_agent/__init__.py +21 -0
  160. autogen/agentchat/user_proxy_agent.py +111 -0
  161. autogen/agentchat/utils.py +206 -0
  162. autogen/agents/__init__.py +3 -0
  163. autogen/agents/contrib/__init__.py +10 -0
  164. autogen/agents/contrib/time/__init__.py +8 -0
  165. autogen/agents/contrib/time/time_reply_agent.py +73 -0
  166. autogen/agents/contrib/time/time_tool_agent.py +51 -0
  167. autogen/agents/experimental/__init__.py +27 -0
  168. autogen/agents/experimental/deep_research/__init__.py +7 -0
  169. autogen/agents/experimental/deep_research/deep_research.py +52 -0
  170. autogen/agents/experimental/discord/__init__.py +7 -0
  171. autogen/agents/experimental/discord/discord.py +66 -0
  172. autogen/agents/experimental/document_agent/__init__.py +19 -0
  173. autogen/agents/experimental/document_agent/chroma_query_engine.py +316 -0
  174. autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +118 -0
  175. autogen/agents/experimental/document_agent/document_agent.py +461 -0
  176. autogen/agents/experimental/document_agent/document_conditions.py +50 -0
  177. autogen/agents/experimental/document_agent/document_utils.py +380 -0
  178. autogen/agents/experimental/document_agent/inmemory_query_engine.py +220 -0
  179. autogen/agents/experimental/document_agent/parser_utils.py +130 -0
  180. autogen/agents/experimental/document_agent/url_utils.py +426 -0
  181. autogen/agents/experimental/reasoning/__init__.py +7 -0
  182. autogen/agents/experimental/reasoning/reasoning_agent.py +1178 -0
  183. autogen/agents/experimental/slack/__init__.py +7 -0
  184. autogen/agents/experimental/slack/slack.py +73 -0
  185. autogen/agents/experimental/telegram/__init__.py +7 -0
  186. autogen/agents/experimental/telegram/telegram.py +77 -0
  187. autogen/agents/experimental/websurfer/__init__.py +7 -0
  188. autogen/agents/experimental/websurfer/websurfer.py +62 -0
  189. autogen/agents/experimental/wikipedia/__init__.py +7 -0
  190. autogen/agents/experimental/wikipedia/wikipedia.py +90 -0
  191. autogen/browser_utils.py +309 -0
  192. autogen/cache/__init__.py +10 -0
  193. autogen/cache/abstract_cache_base.py +75 -0
  194. autogen/cache/cache.py +203 -0
  195. autogen/cache/cache_factory.py +88 -0
  196. autogen/cache/cosmos_db_cache.py +144 -0
  197. autogen/cache/disk_cache.py +102 -0
  198. autogen/cache/in_memory_cache.py +58 -0
  199. autogen/cache/redis_cache.py +123 -0
  200. autogen/code_utils.py +596 -0
  201. autogen/coding/__init__.py +22 -0
  202. autogen/coding/base.py +119 -0
  203. autogen/coding/docker_commandline_code_executor.py +268 -0
  204. autogen/coding/factory.py +47 -0
  205. autogen/coding/func_with_reqs.py +202 -0
  206. autogen/coding/jupyter/__init__.py +23 -0
  207. autogen/coding/jupyter/base.py +36 -0
  208. autogen/coding/jupyter/docker_jupyter_server.py +167 -0
  209. autogen/coding/jupyter/embedded_ipython_code_executor.py +182 -0
  210. autogen/coding/jupyter/import_utils.py +82 -0
  211. autogen/coding/jupyter/jupyter_client.py +231 -0
  212. autogen/coding/jupyter/jupyter_code_executor.py +160 -0
  213. autogen/coding/jupyter/local_jupyter_server.py +172 -0
  214. autogen/coding/local_commandline_code_executor.py +405 -0
  215. autogen/coding/markdown_code_extractor.py +45 -0
  216. autogen/coding/utils.py +56 -0
  217. autogen/doc_utils.py +34 -0
  218. autogen/events/__init__.py +7 -0
  219. autogen/events/agent_events.py +1010 -0
  220. autogen/events/base_event.py +99 -0
  221. autogen/events/client_events.py +167 -0
  222. autogen/events/helpers.py +36 -0
  223. autogen/events/print_event.py +46 -0
  224. autogen/exception_utils.py +73 -0
  225. autogen/extensions/__init__.py +5 -0
  226. autogen/fast_depends/__init__.py +16 -0
  227. autogen/fast_depends/_compat.py +80 -0
  228. autogen/fast_depends/core/__init__.py +14 -0
  229. autogen/fast_depends/core/build.py +225 -0
  230. autogen/fast_depends/core/model.py +576 -0
  231. autogen/fast_depends/dependencies/__init__.py +15 -0
  232. autogen/fast_depends/dependencies/model.py +29 -0
  233. autogen/fast_depends/dependencies/provider.py +39 -0
  234. autogen/fast_depends/library/__init__.py +10 -0
  235. autogen/fast_depends/library/model.py +46 -0
  236. autogen/fast_depends/py.typed +6 -0
  237. autogen/fast_depends/schema.py +66 -0
  238. autogen/fast_depends/use.py +280 -0
  239. autogen/fast_depends/utils.py +187 -0
  240. autogen/formatting_utils.py +83 -0
  241. autogen/function_utils.py +13 -0
  242. autogen/graph_utils.py +178 -0
  243. autogen/import_utils.py +526 -0
  244. autogen/interop/__init__.py +22 -0
  245. autogen/interop/crewai/__init__.py +7 -0
  246. autogen/interop/crewai/crewai.py +88 -0
  247. autogen/interop/interoperability.py +71 -0
  248. autogen/interop/interoperable.py +46 -0
  249. autogen/interop/langchain/__init__.py +8 -0
  250. autogen/interop/langchain/langchain_chat_model_factory.py +155 -0
  251. autogen/interop/langchain/langchain_tool.py +82 -0
  252. autogen/interop/litellm/__init__.py +7 -0
  253. autogen/interop/litellm/litellm_config_factory.py +113 -0
  254. autogen/interop/pydantic_ai/__init__.py +7 -0
  255. autogen/interop/pydantic_ai/pydantic_ai.py +168 -0
  256. autogen/interop/registry.py +69 -0
  257. autogen/io/__init__.py +15 -0
  258. autogen/io/base.py +151 -0
  259. autogen/io/console.py +56 -0
  260. autogen/io/processors/__init__.py +12 -0
  261. autogen/io/processors/base.py +21 -0
  262. autogen/io/processors/console_event_processor.py +56 -0
  263. autogen/io/run_response.py +293 -0
  264. autogen/io/thread_io_stream.py +63 -0
  265. autogen/io/websockets.py +213 -0
  266. autogen/json_utils.py +43 -0
  267. autogen/llm_config.py +379 -0
  268. autogen/logger/__init__.py +11 -0
  269. autogen/logger/base_logger.py +128 -0
  270. autogen/logger/file_logger.py +261 -0
  271. autogen/logger/logger_factory.py +42 -0
  272. autogen/logger/logger_utils.py +57 -0
  273. autogen/logger/sqlite_logger.py +523 -0
  274. autogen/math_utils.py +339 -0
  275. autogen/mcp/__init__.py +7 -0
  276. autogen/mcp/mcp_client.py +208 -0
  277. autogen/messages/__init__.py +7 -0
  278. autogen/messages/agent_messages.py +948 -0
  279. autogen/messages/base_message.py +107 -0
  280. autogen/messages/client_messages.py +171 -0
  281. autogen/messages/print_message.py +49 -0
  282. autogen/oai/__init__.py +53 -0
  283. autogen/oai/anthropic.py +714 -0
  284. autogen/oai/bedrock.py +628 -0
  285. autogen/oai/cerebras.py +299 -0
  286. autogen/oai/client.py +1435 -0
  287. autogen/oai/client_utils.py +169 -0
  288. autogen/oai/cohere.py +479 -0
  289. autogen/oai/gemini.py +990 -0
  290. autogen/oai/gemini_types.py +129 -0
  291. autogen/oai/groq.py +305 -0
  292. autogen/oai/mistral.py +303 -0
  293. autogen/oai/oai_models/__init__.py +11 -0
  294. autogen/oai/oai_models/_models.py +16 -0
  295. autogen/oai/oai_models/chat_completion.py +87 -0
  296. autogen/oai/oai_models/chat_completion_audio.py +32 -0
  297. autogen/oai/oai_models/chat_completion_message.py +86 -0
  298. autogen/oai/oai_models/chat_completion_message_tool_call.py +37 -0
  299. autogen/oai/oai_models/chat_completion_token_logprob.py +63 -0
  300. autogen/oai/oai_models/completion_usage.py +60 -0
  301. autogen/oai/ollama.py +643 -0
  302. autogen/oai/openai_utils.py +881 -0
  303. autogen/oai/together.py +370 -0
  304. autogen/retrieve_utils.py +491 -0
  305. autogen/runtime_logging.py +160 -0
  306. autogen/token_count_utils.py +267 -0
  307. autogen/tools/__init__.py +20 -0
  308. autogen/tools/contrib/__init__.py +9 -0
  309. autogen/tools/contrib/time/__init__.py +7 -0
  310. autogen/tools/contrib/time/time.py +41 -0
  311. autogen/tools/dependency_injection.py +254 -0
  312. autogen/tools/experimental/__init__.py +43 -0
  313. autogen/tools/experimental/browser_use/__init__.py +7 -0
  314. autogen/tools/experimental/browser_use/browser_use.py +161 -0
  315. autogen/tools/experimental/crawl4ai/__init__.py +7 -0
  316. autogen/tools/experimental/crawl4ai/crawl4ai.py +153 -0
  317. autogen/tools/experimental/deep_research/__init__.py +7 -0
  318. autogen/tools/experimental/deep_research/deep_research.py +328 -0
  319. autogen/tools/experimental/duckduckgo/__init__.py +7 -0
  320. autogen/tools/experimental/duckduckgo/duckduckgo_search.py +109 -0
  321. autogen/tools/experimental/google/__init__.py +14 -0
  322. autogen/tools/experimental/google/authentication/__init__.py +11 -0
  323. autogen/tools/experimental/google/authentication/credentials_hosted_provider.py +43 -0
  324. autogen/tools/experimental/google/authentication/credentials_local_provider.py +91 -0
  325. autogen/tools/experimental/google/authentication/credentials_provider.py +35 -0
  326. autogen/tools/experimental/google/drive/__init__.py +9 -0
  327. autogen/tools/experimental/google/drive/drive_functions.py +124 -0
  328. autogen/tools/experimental/google/drive/toolkit.py +88 -0
  329. autogen/tools/experimental/google/model.py +17 -0
  330. autogen/tools/experimental/google/toolkit_protocol.py +19 -0
  331. autogen/tools/experimental/google_search/__init__.py +8 -0
  332. autogen/tools/experimental/google_search/google_search.py +93 -0
  333. autogen/tools/experimental/google_search/youtube_search.py +181 -0
  334. autogen/tools/experimental/messageplatform/__init__.py +17 -0
  335. autogen/tools/experimental/messageplatform/discord/__init__.py +7 -0
  336. autogen/tools/experimental/messageplatform/discord/discord.py +288 -0
  337. autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
  338. autogen/tools/experimental/messageplatform/slack/slack.py +391 -0
  339. autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
  340. autogen/tools/experimental/messageplatform/telegram/telegram.py +275 -0
  341. autogen/tools/experimental/perplexity/__init__.py +7 -0
  342. autogen/tools/experimental/perplexity/perplexity_search.py +260 -0
  343. autogen/tools/experimental/tavily/__init__.py +7 -0
  344. autogen/tools/experimental/tavily/tavily_search.py +183 -0
  345. autogen/tools/experimental/web_search_preview/__init__.py +7 -0
  346. autogen/tools/experimental/web_search_preview/web_search_preview.py +114 -0
  347. autogen/tools/experimental/wikipedia/__init__.py +7 -0
  348. autogen/tools/experimental/wikipedia/wikipedia.py +287 -0
  349. autogen/tools/function_utils.py +411 -0
  350. autogen/tools/tool.py +187 -0
  351. autogen/tools/toolkit.py +86 -0
  352. autogen/types.py +29 -0
  353. autogen/version.py +7 -0
  354. ag2-0.9.1.dist-info/RECORD +0 -6
  355. ag2-0.9.1.dist-info/top_level.txt +0 -1
  356. {ag2-0.9.1.dist-info → ag2-0.9.1.post0.dist-info/licenses}/LICENSE +0 -0
  357. {ag2-0.9.1.dist-info → ag2-0.9.1.post0.dist-info/licenses}/NOTICE.md +0 -0
@@ -0,0 +1,1174 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+
6
+ import json
7
+ import os
8
+ import re
9
+ import shutil
10
+ from pathlib import Path
11
+ from typing import Optional, Union
12
+
13
+ from ..import_utils import optional_import_block, require_optional_import
14
+ from .notebook_processor import (
15
+ create_base_argument_parser,
16
+ process_notebooks_core,
17
+ )
18
+ from .utils import (
19
+ NavigationGroup,
20
+ add_authors_and_social_preview,
21
+ copy_files,
22
+ get_authors_info,
23
+ get_git_tracked_and_untracked_files_in_directory,
24
+ remove_marker_blocks,
25
+ render_gallery_html,
26
+ separate_front_matter_and_content,
27
+ sort_files_by_date,
28
+ )
29
+
30
+ with optional_import_block():
31
+ import yaml
32
+ from jinja2 import Template
33
+
34
+
35
+ root_dir = Path(__file__).resolve().parents[2]
36
+ website_dir = root_dir / "website"
37
+
38
+ mint_docs_dir = website_dir / "docs"
39
+
40
+ mkdocs_root_dir = website_dir / "mkdocs"
41
+
42
+ mkdocs_docs_dir = mkdocs_root_dir / "docs"
43
+ mkdocs_output_dir = mkdocs_root_dir / "docs" / "docs"
44
+
45
+
46
+ def filter_excluded_files(files: list[Path], exclusion_list: list[str], website_dir: Path) -> list[Path]:
47
+ return [
48
+ file
49
+ for file in files
50
+ if not any(Path(str(file.relative_to(website_dir))).as_posix().startswith(excl) for excl in exclusion_list)
51
+ ]
52
+
53
+
54
+ def copy_file(file: Path, mkdocs_output_dir: Path) -> None:
55
+ dest = mkdocs_output_dir / file.relative_to(file.parents[1])
56
+ dest.parent.mkdir(parents=True, exist_ok=True)
57
+ shutil.copy2(file, dest)
58
+
59
+
60
+ def transform_tab_component(content: str) -> str:
61
+ """Transform React-style tab components to MkDocs tab components.
62
+
63
+ Args:
64
+ content: String containing React-style tab components.
65
+ Expected format is:
66
+ <Tabs>
67
+ <Tab title="Title 1">
68
+ content 1
69
+ </Tab>
70
+ <Tab title="Title 2">
71
+ content 2
72
+ </Tab>
73
+ </Tabs>
74
+
75
+ Returns:
76
+ String with MkDocs tab components:
77
+ === "Title 1"
78
+ content 1
79
+
80
+ === "Title 2"
81
+ content 2
82
+ """
83
+ if "<Tabs>" not in content:
84
+ return content
85
+
86
+ # Find and replace each Tabs section
87
+ pattern = re.compile(r"<Tabs>(.*?)</Tabs>", re.DOTALL)
88
+
89
+ def replace_tabs(match: re.Match[str]) -> str:
90
+ tabs_content = match.group(1)
91
+
92
+ # Extract all Tab elements
93
+ tab_pattern = re.compile(r'<Tab title="([^"]+)">(.*?)</Tab>', re.DOTALL)
94
+ tabs = tab_pattern.findall(tabs_content)
95
+
96
+ if not tabs:
97
+ return ""
98
+
99
+ result = []
100
+
101
+ for i, (title, tab_content) in enumerate(tabs):
102
+ # Add tab header
103
+ result.append(f'=== "{title}"')
104
+
105
+ # Process content by maintaining indentation structure
106
+ lines = tab_content.strip().split("\n")
107
+
108
+ # Find minimum common indentation for non-empty lines
109
+ non_empty_lines = [line for line in lines if line.strip()]
110
+ min_indent = min([len(line) - len(line.lstrip()) for line in non_empty_lines]) if non_empty_lines else 0
111
+
112
+ # Remove common indentation and add 4-space indent
113
+ processed_lines = []
114
+ for line in lines:
115
+ if line.strip():
116
+ # Remove the common indentation but preserve relative indentation
117
+ if len(line) >= min_indent:
118
+ processed_lines.append(" " + line[min_indent:])
119
+ else:
120
+ processed_lines.append(" " + line.lstrip())
121
+ else:
122
+ processed_lines.append("")
123
+
124
+ result.append("\n".join(processed_lines))
125
+
126
+ # Add a blank line between tabs (but not after the last one)
127
+ if i < len(tabs) - 1:
128
+ result.append("")
129
+
130
+ return "\n".join(result)
131
+
132
+ # Replace each Tabs section
133
+ result = pattern.sub(replace_tabs, content)
134
+
135
+ return result
136
+
137
+
138
+ def transform_card_grp_component(content: str) -> str:
139
+ # Replace CardGroup tags
140
+ modified_content = re.sub(r"<CardGroup\s+cols=\{(\d+)\}>\s*", "", content)
141
+ modified_content = re.sub(r"\s*</CardGroup>", "", modified_content)
142
+
143
+ # Replace Card tags with title and href attributes
144
+ pattern = r'<Card\s+title="([^"]*)"\s+href="([^"]*)">(.*?)</Card>'
145
+ replacement = r'<a class="card" href="\2">\n<h2>\1</h2>\3</a>'
146
+ modified_content = re.sub(pattern, replacement, modified_content, flags=re.DOTALL)
147
+
148
+ # Replace simple Card tags
149
+ modified_content = re.sub(r"<Card>", '<div class="card">', modified_content)
150
+ modified_content = re.sub(r"</Card>", "</div>", modified_content)
151
+
152
+ return modified_content
153
+
154
+
155
+ def fix_asset_path(content: str) -> str:
156
+ # Replace static/img paths with /assets/img
157
+ modified_content = re.sub(r'src="/static/img/([^"]+)"', r'src="/assets/img/\1"', content)
158
+ modified_content = re.sub(r"!\[([^\]]*)\]\(/static/img/([^)]+)\)", r"![\1](/assets/img/\2)", modified_content)
159
+
160
+ # Replace docs paths with /docs
161
+ modified_content = re.sub(r'href="/docs/([^"]+)"', r'href="/docs/\1"', modified_content)
162
+
163
+ return modified_content
164
+
165
+
166
+ def fix_internal_references(abs_file_url: str, mkdocs_docs_dir: Path = mkdocs_docs_dir) -> str:
167
+ # Special case for the API Reference
168
+ if abs_file_url in {"/docs/api-reference", "/docs/api-reference/autogen"}:
169
+ return (
170
+ f"{abs_file_url}/autogen/AfterWork"
171
+ if abs_file_url == "/docs/api-reference"
172
+ else f"{abs_file_url}/AfterWork"
173
+ )
174
+
175
+ # Handle API reference URLs with hash fragments
176
+ if abs_file_url.startswith("/docs/api-reference/") and "#" in abs_file_url:
177
+ base_url, fragment = abs_file_url.split("#")
178
+ module_prefix = base_url.replace("/docs/api-reference/", "").replace("/", ".")
179
+ return f"{base_url}#{module_prefix}.{fragment.replace('-', '_')}"
180
+
181
+ file_path = mkdocs_docs_dir / (abs_file_url.lstrip("/") + ".md")
182
+ if file_path.is_file():
183
+ return abs_file_url
184
+
185
+ full_path = mkdocs_docs_dir / abs_file_url.lstrip("/")
186
+
187
+ if not full_path.is_dir():
188
+ return abs_file_url
189
+
190
+ # Find the first .md file in the directory
191
+ md_files = sorted(list(full_path.glob("*.md")))
192
+ return f"{abs_file_url}/{md_files[0].stem}"
193
+
194
+
195
+ def absolute_to_relative(source_path: str, dest_path: str) -> str:
196
+ """Convert an absolute path to a relative path from the source directory.
197
+
198
+ Args:
199
+ source_path: The source file's absolute path (e.g., "/docs/home/quick-start.md")
200
+ dest_path: The destination file's absolute path (e.g., "/docs/user-guide/basic-concepts/installing-ag2")
201
+
202
+ Returns:
203
+ A relative path from source to destination (e.g., "../../user-guide/basic-concepts/installing-ag2")
204
+ """
205
+ sep = os.sep
206
+ try:
207
+ # Primary approach: Use pathlib for clean path calculation
208
+ rel_path = str(Path(dest_path).relative_to(Path(source_path).parent))
209
+ return f".{sep}{rel_path}" if Path(source_path).stem == "index" else f"..{sep}{rel_path}"
210
+ except ValueError:
211
+ # Fallback approach: Use os.path.relpath when paths don't share a common parent
212
+ rel_path = os.path.relpath(dest_path, source_path)
213
+
214
+ # Special case for blog directories: add deeper path traversal
215
+ ret_val = os.path.join("..", "..", "..", rel_path) if "blog" in source_path else rel_path
216
+
217
+ # Special case for index files: strip leading "../"
218
+ if Path(source_path).stem == "index":
219
+ ret_val = ret_val[3:]
220
+
221
+ return ret_val
222
+
223
+
224
+ def fix_internal_links(source_path: str, content: str) -> str:
225
+ """Detect internal links in content that start with '/docs' and convert them to relative paths.
226
+
227
+ Args:
228
+ source_path: The source file's absolute path
229
+ content: The content with potential internal links
230
+
231
+ Returns:
232
+ Content with internal links converted to relative paths
233
+ """
234
+
235
+ # Define regex patterns for HTML and Markdown links
236
+ html_link_pattern = r'href="(/docs/[^"]*)"'
237
+ html_img_src_pattern = r'src="(/snippets/[^"]+)"'
238
+ html_assets_src_pattern = r'src="(/assets/[^"]+)"'
239
+
240
+ markdown_link_pattern = r"\[([^\]]+)\]\((/docs/[^)]*)\)"
241
+ markdown_img_pattern = r"!\[([^\]]*)\]\((/snippets/[^)]+)\)"
242
+ markdown_assets_pattern = r"!\[([^\]]*)\]\((/assets/[^)]+)\)"
243
+
244
+ def handle_blog_url(url: str) -> str:
245
+ """Special handling for blog URLs, converting date format from YYYY-MM-DD to YYYY/MM/DD.
246
+
247
+ Args:
248
+ url: The URL to process
249
+
250
+ Returns:
251
+ The URL with date format converted if it matches the blog URL pattern
252
+ """
253
+ blog_date_pattern = r"/docs/blog/(\d{4})-(\d{2})-(\d{2})-([\w-]+)"
254
+
255
+ if re.match(blog_date_pattern, url):
256
+ return re.sub(blog_date_pattern, r"/docs/blog/\1/\2/\3/\4", url)
257
+
258
+ return url
259
+
260
+ # Convert HTML links
261
+ def replace_html(match: re.Match[str], attr_type: str) -> str:
262
+ # There's only one group in the pattern, which is the path
263
+ absolute_link = match.group(1)
264
+
265
+ absolute_link = handle_blog_url(absolute_link)
266
+ abs_file_path = fix_internal_references(absolute_link)
267
+ relative_link = absolute_to_relative(source_path, abs_file_path)
268
+ return f'{attr_type}="{relative_link}"'
269
+
270
+ # Convert Markdown links
271
+ def replace_markdown(match: re.Match[str], is_image: bool) -> str:
272
+ text = match.group(1)
273
+ absolute_link = match.group(2)
274
+
275
+ absolute_link = handle_blog_url(absolute_link)
276
+ abs_file_path = fix_internal_references(absolute_link)
277
+ relative_link = absolute_to_relative(source_path, abs_file_path)
278
+ prefix = "!" if is_image else ""
279
+ return f"{prefix}[{text}]({relative_link})"
280
+
281
+ # Apply replacements
282
+ content = re.sub(html_link_pattern, lambda match: replace_html(match, "href"), content)
283
+ content = re.sub(html_img_src_pattern, lambda match: replace_html(match, "src"), content)
284
+ content = re.sub(html_assets_src_pattern, lambda match: replace_html(match, "src"), content)
285
+
286
+ content = re.sub(markdown_link_pattern, lambda match: replace_markdown(match, False), content)
287
+ content = re.sub(markdown_img_pattern, lambda match: replace_markdown(match, True), content)
288
+ content = re.sub(markdown_assets_pattern, lambda match: replace_markdown(match, True), content)
289
+
290
+ return content
291
+
292
+
293
+ def transform_content_for_mkdocs(content: str, rel_file_path: str) -> str:
294
+ # Transform admonitions (Tip, Warning, Note)
295
+ tag_mappings = {
296
+ "Tip": "tip",
297
+ "Warning": "warning",
298
+ "Note": "note",
299
+ "Danger": "danger",
300
+ }
301
+ for html_tag, mkdocs_type in tag_mappings.items():
302
+ pattern = f"<{html_tag}>(.*?)</{html_tag}>"
303
+
304
+ def replacement(match: re.Match[str]) -> str:
305
+ inner_content = match.group(1).strip()
306
+
307
+ lines = inner_content.split("\n")
308
+
309
+ non_empty_lines = [line for line in lines if line.strip()]
310
+ min_indent = min([len(line) - len(line.lstrip()) for line in non_empty_lines]) if non_empty_lines else 0
311
+
312
+ # Process each line
313
+ processed_lines = []
314
+ for line in lines:
315
+ if line.strip():
316
+ # Remove common indentation and add 4-space indent
317
+ if len(line) >= min_indent:
318
+ processed_lines.append(" " + line[min_indent:])
319
+ else:
320
+ processed_lines.append(" " + line.lstrip())
321
+ else:
322
+ processed_lines.append("")
323
+
324
+ # Format the admonition with properly indented content
325
+ return f"!!! {mkdocs_type.lstrip()}\n" + "\n".join(processed_lines)
326
+
327
+ content = re.sub(pattern, replacement, content, flags=re.DOTALL)
328
+
329
+ # Clean up style tags with double curly braces
330
+ style_pattern = r"style\s*=\s*{{\s*([^}]+)\s*}}"
331
+
332
+ def style_replacement(match: re.Match[str]) -> str:
333
+ style_content = match.group(1).strip()
334
+ return f"style={{ {style_content} }}"
335
+
336
+ content = re.sub(style_pattern, style_replacement, content)
337
+
338
+ # Fix snippet imports
339
+ content = fix_snippet_imports(content)
340
+
341
+ # Transform tab components
342
+ content = transform_tab_component(content)
343
+
344
+ # Transform CardGroup components
345
+ content = transform_card_grp_component(content)
346
+
347
+ # Fix assets path
348
+ content = fix_asset_path(content)
349
+
350
+ # Remove the mintlify specific markers
351
+ content = remove_marker_blocks(content, "DELETE-ME-WHILE-BUILDING-MKDOCS")
352
+
353
+ # Fix Internal links
354
+ content = fix_internal_links(rel_file_path, content)
355
+
356
+ return content
357
+
358
+
359
+ def rename_user_story(p: Path) -> Path:
360
+ name = p.parent.name.split("-")[3:]
361
+ return p.parent / ("_".join(name).lower() + p.suffix)
362
+
363
+
364
+ def process_and_copy_files(input_dir: Path, output_dir: Path, files: list[Path]) -> None:
365
+ sep = os.sep
366
+ # Keep track of MD files we need to process
367
+ md_files_to_process = []
368
+
369
+ # Step 1: First copy mdx files to destination as md files
370
+ for file in files:
371
+ if file.suffix == ".mdx":
372
+ dest = output_dir / file.relative_to(input_dir).with_suffix(".md")
373
+
374
+ if file.name == "home.mdx":
375
+ dest = output_dir / "home.md"
376
+
377
+ if f"{sep}user-stories{sep}" in str(dest):
378
+ dest = rename_user_story(dest)
379
+
380
+ dest.parent.mkdir(parents=True, exist_ok=True)
381
+ dest.write_text(file.read_text())
382
+ md_files_to_process.append(dest)
383
+ else:
384
+ copy_files(input_dir, output_dir, [file])
385
+
386
+ # Step 2: Process the MD files we created
387
+ for md_file in md_files_to_process:
388
+ content = md_file.read_text()
389
+
390
+ rel_path = f"{sep}{md_file.relative_to(output_dir.parents[0])}"
391
+ processed_content = transform_content_for_mkdocs(content, rel_path)
392
+
393
+ md_file.write_text(processed_content)
394
+
395
+
396
+ def format_title(file_path_str: str, keywords: dict[str, str], mkdocs_docs_dir: Path) -> str:
397
+ """Format a page title with proper capitalization for special keywords."""
398
+ file_path = mkdocs_docs_dir / Path(file_path_str)
399
+
400
+ # Default formatting function for filenames
401
+ def format_with_keywords(text: str) -> str:
402
+ words = text.replace("-", " ").title().split()
403
+ return " ".join(keywords.get(word, word) for word in words)
404
+
405
+ try:
406
+ front_matter_string, _ = separate_front_matter_and_content(file_path)
407
+ if front_matter_string:
408
+ front_matter = yaml.safe_load(front_matter_string[4:-3])
409
+ sidebar_title: str = front_matter.get("sidebarTitle")
410
+ if sidebar_title:
411
+ return sidebar_title
412
+ except (FileNotFoundError, yaml.YAMLError):
413
+ pass
414
+
415
+ # Fall back to filename if file not found or no sidebarTitle
416
+ return format_with_keywords(Path(file_path_str).stem)
417
+
418
+
419
+ def format_page_entry(page_loc: str, indent: str, keywords: dict[str, str], mkdocs_docs_dir: Path) -> str:
420
+ """Format a single page entry as either a parenthesized path or a markdown link."""
421
+ file_path_str = f"{page_loc}.md"
422
+ title = format_title(file_path_str, keywords, mkdocs_docs_dir)
423
+ return f"{indent} - [{title}]({file_path_str})"
424
+
425
+
426
+ def format_navigation(
427
+ nav: list[NavigationGroup],
428
+ mkdocs_docs_dir: Path = mkdocs_docs_dir,
429
+ depth: int = 0,
430
+ keywords: Optional[dict[str, str]] = None,
431
+ ) -> str:
432
+ """Recursively format navigation structure into markdown-style nested list.
433
+
434
+ Args:
435
+ nav: List of navigation items with groups and pages
436
+ mkdocs_docs_dir: Directory where the markdown files are located
437
+ depth: Current indentation depth
438
+ keywords: Dictionary of special case word capitalizations
439
+
440
+ Returns:
441
+ Formatted navigation as a string
442
+ """
443
+ if keywords is None:
444
+ keywords = {
445
+ "Ag2": "AG2",
446
+ "Rag": "RAG",
447
+ "Llm": "LLM",
448
+ }
449
+
450
+ indent = " " * depth
451
+ result = []
452
+
453
+ for item in nav:
454
+ # Add group header
455
+ result.append(f"{indent}- {item['group']}")
456
+
457
+ # Process each page
458
+ for page in item["pages"]:
459
+ if isinstance(page, dict):
460
+ # Handle nested navigation groups
461
+ result.append(format_navigation([page], mkdocs_docs_dir, depth + 1, keywords))
462
+ else:
463
+ # Handle individual pages
464
+ result.append(format_page_entry(page, indent, keywords, mkdocs_docs_dir))
465
+
466
+ ret_val = "\n".join(result)
467
+
468
+ ret_val = ret_val.replace(
469
+ "- Quick Start\n - [Quick Start](docs/quick-start.md)\n",
470
+ "- [Quick Start](docs/quick-start.md)\n",
471
+ )
472
+ ret_val = ret_val.replace(
473
+ "- Basic Concepts\n",
474
+ "- [Basic Concepts](docs/user-guide/basic-concepts/overview.md)\n",
475
+ )
476
+ ret_val = ret_val.replace("- FAQs\n - [Faq](docs/faq/FAQ.md)\n", "- [FAQs](docs/faq/FAQ.md)\n")
477
+ return ret_val
478
+
479
+
480
+ def add_api_ref_to_mkdocs_template(mkdocs_nav: str, section_to_follow: str) -> str:
481
+ """Add API Reference section to the navigation template."""
482
+ api_reference_section = """- API References
483
+ {api}
484
+ """
485
+ section_to_follow_marker = f"- {section_to_follow}"
486
+
487
+ replacement_content = f"{api_reference_section}{section_to_follow_marker}"
488
+ ret_val = mkdocs_nav.replace(section_to_follow_marker, replacement_content)
489
+ return ret_val
490
+
491
+
492
+ @require_optional_import("jinja2", "docs")
493
+ def generate_mkdocs_navigation(website_dir: Path, mkdocs_root_dir: Path, nav_exclusions: list[str]) -> None:
494
+ mintlify_nav_template_path = website_dir / "mint-json-template.json.jinja"
495
+ mkdocs_nav_path = mkdocs_root_dir / "docs" / "navigation_template.txt"
496
+ summary_md_path = mkdocs_root_dir / "docs" / "SUMMARY.md"
497
+
498
+ mintlify_json = json.loads(Template(mintlify_nav_template_path.read_text(encoding="utf-8")).render())
499
+ mintlify_nav = mintlify_json["navigation"]
500
+ filtered_nav = [item for item in mintlify_nav if item["group"] not in nav_exclusions]
501
+
502
+ mkdocs_docs_dir = mkdocs_root_dir / "docs"
503
+ mkdocs_nav = format_navigation(filtered_nav, mkdocs_docs_dir)
504
+ mkdocs_nav_with_api_ref = add_api_ref_to_mkdocs_template(mkdocs_nav, "Contributor Guide")
505
+
506
+ blog_nav = "- Blog\n - [Blog](docs/blog/index.md)"
507
+
508
+ mkdocs_nav_content = "---\nsearch:\n exclude: true\n---\n" + mkdocs_nav_with_api_ref + "\n" + blog_nav + "\n"
509
+ mkdocs_nav_path.write_text(mkdocs_nav_content)
510
+ summary_md_path.write_text(mkdocs_nav_content)
511
+
512
+
513
+ def copy_assets(website_dir: Path) -> None:
514
+ src_dir = website_dir / "static" / "img"
515
+ dest_dir = website_dir / "mkdocs" / "docs" / "assets" / "img"
516
+
517
+ git_tracket_img_files = get_git_tracked_and_untracked_files_in_directory(website_dir / "static" / "img")
518
+ copy_files(src_dir, dest_dir, git_tracket_img_files)
519
+
520
+
521
+ def add_excerpt_marker(content: str) -> str:
522
+ """Add <!-- more --> marker before the second heading in markdown body content.
523
+
524
+ Args:
525
+ content (str): Body content of the markdown file (without frontmatter)
526
+
527
+ Returns:
528
+ str: Modified body content with <!-- more --> added
529
+ """
530
+
531
+ if "<!-- more -->" in content:
532
+ return content.replace(r"\<!-- more -->", "<!-- more -->")
533
+
534
+ # Find all headings
535
+ heading_pattern = re.compile(r"^(#{1,6}\s+.+?)$", re.MULTILINE)
536
+ headings = list(heading_pattern.finditer(content))
537
+
538
+ # If there are fewer than 2 headings, add the marker at the end
539
+ if len(headings) < 2:
540
+ # If there's content, add the marker at the end
541
+ return content.rstrip() + "\n\n<!-- more -->\n"
542
+
543
+ # Get position of the second heading
544
+ second_heading = headings[1]
545
+ position = second_heading.start()
546
+
547
+ # Insert the more marker before the second heading
548
+ return content[:position] + "\n<!-- more -->\n\n" + content[position:]
549
+
550
+
551
+ def generate_url_slug(file: Path) -> str:
552
+ parent_dir = file.parts[-2]
553
+ slug = "-".join(parent_dir.split("-")[3:])
554
+ return f"\nslug: {slug}"
555
+
556
+
557
+ def process_blog_contents(contents: str, file: Path) -> str:
558
+ # Split the content into parts
559
+ parts = contents.split("---", 2)
560
+ if len(parts) < 3:
561
+ return contents
562
+
563
+ frontmatter = parts[1]
564
+ content = parts[2]
565
+
566
+ # Extract tags
567
+ tags_match = re.search(r"tags:\s*\[(.*?)\]", frontmatter)
568
+ if not tags_match:
569
+ return contents
570
+
571
+ tags_str = tags_match.group(1)
572
+ tags = [tag.strip() for tag in tags_str.split(",")]
573
+
574
+ # Extract date from second-to-last part of file path
575
+ date_match = re.match(r"(\d{4}-\d{2}-\d{2})", file.parts[-2])
576
+ date = date_match.group(1) if date_match else None
577
+
578
+ # Remove original tags
579
+ frontmatter = re.sub(r"tags:\s*\[.*?\]", "", frontmatter).strip()
580
+
581
+ # Format tags and categories as YAML lists
582
+ tags_yaml = "tags:\n - " + "\n - ".join(tags)
583
+ categories_yaml = "categories:\n - " + "\n - ".join(tags)
584
+
585
+ # Add date to metadata
586
+ date_yaml = f"\ndate: {date}" if date else ""
587
+
588
+ # Add URL slug metadata
589
+ url_slug = generate_url_slug(file)
590
+
591
+ # add the excerpt marker in the content
592
+ content_with_excerpt_marker = add_excerpt_marker(content)
593
+
594
+ return f"---\n{frontmatter}\n{tags_yaml}\n{categories_yaml}{date_yaml}{url_slug}\n---{content_with_excerpt_marker}"
595
+
596
+
597
+ def fix_snippet_imports(content: str, snippets_dir: Path = mkdocs_output_dir.parent / "snippets") -> str:
598
+ """Replace import statements for MDX files from snippets directory with the target format.
599
+
600
+ Args:
601
+ content (str): Content containing import statements
602
+ snippets_dir (Path): Path to the snippets directory
603
+
604
+ Returns:
605
+ str: Content with import statements replaced
606
+ """
607
+ # Regular expression to find import statements for MDX files from /snippets/
608
+ import_pattern = re.compile(r'import\s+(\w+)\s+from\s+"(/snippets/[^"]+\.mdx)"\s*;')
609
+
610
+ # Process all matches
611
+ matches = list(import_pattern.finditer(content))
612
+
613
+ # Process matches in reverse order to avoid offset issues when replacing text
614
+ for match in reversed(matches):
615
+ imported_path = match.group(2)
616
+
617
+ # Check if the path starts with /snippets/
618
+ if not imported_path.startswith("/snippets/"):
619
+ continue
620
+
621
+ # Extract the relative path (without the /snippets/ prefix)
622
+ relative_path = imported_path[len("/snippets/") :]
623
+
624
+ # Construct the full file path
625
+ file_path = snippets_dir / relative_path
626
+
627
+ # Read the file content
628
+ with open(file_path, "r") as f:
629
+ file_content = f.read()
630
+
631
+ # Replace the import statement with the file content
632
+ start, end = match.span()
633
+ content = content[:start] + file_content + content[end:]
634
+
635
+ return content
636
+
637
+
638
+ def process_blog_files(mkdocs_output_dir: Path, authors_yml_path: Path, snippets_src_path: Path) -> None:
639
+ src_blog_dir = mkdocs_output_dir / "_blogs"
640
+ target_blog_dir = mkdocs_output_dir / "blog"
641
+ target_posts_dir = target_blog_dir / "posts"
642
+ snippets_dir = mkdocs_output_dir.parent / "snippets"
643
+
644
+ # Create the target posts directory
645
+ target_posts_dir.mkdir(parents=True, exist_ok=True)
646
+
647
+ # Create the index file in the target blog directory
648
+ index_file = target_blog_dir / "index.md"
649
+ index_file.write_text("# Blog\n\n")
650
+
651
+ # Get all files to copy
652
+ files_to_copy = list(src_blog_dir.rglob("*"))
653
+
654
+ # process blog metadata
655
+ for file in files_to_copy:
656
+ if file.suffix == ".md":
657
+ contents = file.read_text()
658
+ processed_contents = process_blog_contents(contents, file)
659
+ processed_contents = fix_snippet_imports(processed_contents, snippets_dir)
660
+ file.write_text(processed_contents)
661
+
662
+ # Copy files from source to target
663
+ copy_files(src_blog_dir, target_posts_dir, files_to_copy)
664
+
665
+ # Copy snippets directory
666
+ snippets_files_to_copy = list(snippets_src_path.rglob("*"))
667
+ copy_files(snippets_src_path, snippets_dir, snippets_files_to_copy)
668
+
669
+ # Copy authors_yml_path to the target_blog_dir and rename it as .authors.yml
670
+ target_authors_yml_path = target_blog_dir / ".authors.yml"
671
+ shutil.copy2(authors_yml_path, target_authors_yml_path)
672
+
673
+
674
+ _is_first_notebook = True
675
+
676
+
677
+ def add_front_matter_to_metadata_yml(
678
+ front_matter: dict[str, Union[str, list[str], None]], website_build_directory: Path, rendered_mdx: Path
679
+ ) -> None:
680
+ """Add notebook metadata to a YAML file containing metadata for all notebooks."""
681
+ global _is_first_notebook
682
+
683
+ source = front_matter.get("source_notebook")
684
+ if isinstance(source, str) and source.startswith("/website/docs/"):
685
+ return
686
+
687
+ # Get the metadata file path
688
+ metadata_yml_path = website_build_directory / "../../data/notebooks_metadata.yml"
689
+
690
+ # Create parent directories if they don't exist
691
+ metadata_yml_path.parent.mkdir(parents=True, exist_ok=True)
692
+
693
+ # If this is the first notebook, delete the existing file
694
+ if _is_first_notebook and metadata_yml_path.exists():
695
+ metadata_yml_path.unlink()
696
+ _is_first_notebook = False
697
+
698
+ # Create new entry for current notebook
699
+ title = front_matter.get("title", "")
700
+ link = f"/docs/use-cases/notebooks/notebooks/{rendered_mdx.stem}.md"
701
+ rel_link = f"../notebooks/{rendered_mdx.stem}"
702
+ description = front_matter.get("description", "")
703
+ tags = front_matter.get("tags", []) or []
704
+
705
+ # Escape quotes in strings
706
+ title = str(title).replace('"', '\\"')
707
+ description = str(description).replace('"', '\\"')
708
+ source_str = str(source or "").replace('"', '\\"')
709
+
710
+ # Open file in append mode
711
+ with open(metadata_yml_path, "a", encoding="utf-8") as f:
712
+ # Write the entry
713
+ f.write(f'- title: "{title}"\n')
714
+ f.write(f' link: "{link}"\n')
715
+ f.write(f' rel_link: "{rel_link}"\n')
716
+ f.write(f' description: "{description}"\n')
717
+ f.write(' image: ""\n')
718
+
719
+ # Write tags
720
+ if tags:
721
+ f.write(" tags:\n")
722
+ for tag in tags:
723
+ if tag: # Only write non-empty tags
724
+ tag_str = str(tag).replace('"', '\\"')
725
+ f.write(f' - "{tag_str}"\n')
726
+ else:
727
+ f.write(" tags: []\n")
728
+
729
+ # Write source
730
+ f.write(f' source: "{source_str}"\n')
731
+ f.write("\n")
732
+
733
+
734
+ def transform_admonition_blocks(content: str) -> str:
735
+ """Transform admonition blocks from ::: syntax to Material for MkDocs syntax.
736
+
737
+ Converts blocks like:
738
+ :::info Requirements
739
+ content here
740
+ :::
741
+
742
+ To:
743
+ !!! info "Requirements"
744
+ content here
745
+
746
+ Args:
747
+ content: String containing ::: syntax admonition blocks
748
+
749
+ Returns:
750
+ String with Material for MkDocs admonition blocks
751
+ """
752
+
753
+ tag_mappings = {
754
+ "Tip": "tip",
755
+ "Warning": "warning",
756
+ "Note": "note",
757
+ "Danger": "danger",
758
+ }
759
+
760
+ # Simplified approach: first detect admonition blocks boundaries
761
+ lines = content.split("\n")
762
+ admonition_start = None
763
+ admonition_type = None
764
+ admonition_title = None
765
+ admonition_content: list[str] = []
766
+ result_lines = []
767
+
768
+ i = 0
769
+ while i < len(lines):
770
+ line = lines[i]
771
+
772
+ # Check for admonition start
773
+ if line.strip().startswith(":::") and admonition_start is None:
774
+ admonition_start = i
775
+ # Extract admonition type and optional title
776
+ match = re.match(r":::(\w+)(?:\s+(.+))?", line.strip())
777
+ if match:
778
+ admonition_type = match.group(1)
779
+ admonition_title = match.group(2) if match.group(2) else ""
780
+ else:
781
+ # No match for admonition type means we couldn't parse the format
782
+ admonition_type = None
783
+ i += 1
784
+ continue
785
+
786
+ # Check for admonition end
787
+ elif line.strip() == ":::" and admonition_start is not None:
788
+ # If admonition_type is None, preserve the original content
789
+ if admonition_type is None:
790
+ # Add back the original admonition block without transformation
791
+ original_lines = []
792
+ original_lines.append(lines[admonition_start]) # Opening :::
793
+ original_lines.extend(admonition_content) # Content
794
+ original_lines.append(line) # Closing :::
795
+ result_lines.extend(original_lines)
796
+ else:
797
+ # Process as before for valid admonition types
798
+ # Map the admonition type
799
+ if admonition_type in tag_mappings:
800
+ mapped_type = tag_mappings[admonition_type]
801
+ else:
802
+ # Try case-insensitive match
803
+ for tag, mapped in tag_mappings.items():
804
+ if tag.lower() == admonition_type.lower():
805
+ mapped_type = mapped
806
+ break
807
+ else:
808
+ # Default to lowercase of original if no mapping found
809
+ mapped_type = admonition_type.lower()
810
+
811
+ # Process indentation
812
+ if admonition_content:
813
+ # Find minimum common indentation
814
+ non_empty_lines = [line for line in admonition_content if line.strip()]
815
+ min_indent = min((len(line) - len(line.lstrip()) for line in non_empty_lines), default=0)
816
+
817
+ # Remove common indentation and add 4-space indent
818
+ processed_content = []
819
+ for line in admonition_content:
820
+ if line.strip():
821
+ if len(line) >= min_indent:
822
+ processed_content.append(" " + line[min_indent:])
823
+ else:
824
+ processed_content.append(" " + line.lstrip())
825
+ else:
826
+ processed_content.append("")
827
+ else:
828
+ processed_content = []
829
+
830
+ # Create the MkDocs admonition
831
+ if admonition_title:
832
+ mkdocs_admonition = [f'!!! {mapped_type} "{admonition_title}"'] + processed_content
833
+ else:
834
+ mkdocs_admonition = [f"!!! {mapped_type}"] + processed_content
835
+
836
+ # Add the processed admonition
837
+ result_lines.extend(mkdocs_admonition)
838
+
839
+ # Reset admonition tracking
840
+ admonition_start = None
841
+ admonition_type = None
842
+ admonition_title = None
843
+ admonition_content = []
844
+ i += 1
845
+ continue
846
+
847
+ elif admonition_start is not None:
848
+ admonition_content.append(line)
849
+ i += 1
850
+ continue
851
+
852
+ else:
853
+ result_lines.append(line)
854
+ i += 1
855
+
856
+ if admonition_start is not None:
857
+ for j in range(admonition_start, len(lines)):
858
+ result_lines.append(lines[j])
859
+
860
+ return "\n".join(result_lines)
861
+
862
+
863
+ def remove_mdx_code_blocks(content: str) -> str:
864
+ """Remove ````mdx-code-block and ```` markers from the content.
865
+
866
+ This function removes the mdx-code-block markers while preserving the content inside.
867
+
868
+ Args:
869
+ content: String containing mdx-code-block markers
870
+
871
+ Returns:
872
+ String with mdx-code-block markers removed
873
+ """
874
+
875
+ # Pattern to match mdx-code-block sections
876
+ # Captures everything between ````mdx-code-block and ````
877
+ pattern = re.compile(r"````mdx-code-block\n(.*?)\n````", re.DOTALL)
878
+
879
+ # Replace with just the content (group 1)
880
+ result = pattern.sub(r"\1", content)
881
+
882
+ return result
883
+
884
+
885
+ @require_optional_import("yaml", "docs")
886
+ def post_process_func(
887
+ rendered_mdx: Path,
888
+ source_notebooks: Path,
889
+ front_matter: dict[str, Union[str, list[str], None]],
890
+ website_build_directory: Path,
891
+ ) -> None:
892
+ with open(rendered_mdx, encoding="utf-8") as f:
893
+ content = f.read()
894
+
895
+ # If there is front matter in the mdx file, we need to remove it
896
+ if content.startswith("---"):
897
+ front_matter_end = content.find("---", 3)
898
+ mdx_front_matter = yaml.safe_load(content[4:front_matter_end])
899
+ # Merge while preserving original values
900
+ front_matter = {**front_matter, **mdx_front_matter}
901
+ content = content[front_matter_end + 3 :]
902
+
903
+ # Clean heading IDs using regex - matches from # to the end of ID block
904
+ content = re.sub(r"(#{1,6}[^{]+){#[^}]+}", r"\1", content)
905
+
906
+ # Each intermediate path needs to be resolved for this to work reliably
907
+ repo_root = Path(__file__).resolve().parents[2]
908
+ repo_relative_notebook = source_notebooks.resolve().relative_to(repo_root)
909
+ front_matter["source_notebook"] = f"/{repo_relative_notebook}"
910
+ front_matter["custom_edit_url"] = f"https://github.com/ag2ai/ag2/edit/main/{repo_relative_notebook}"
911
+
912
+ github_link = f"https://github.com/ag2ai/ag2/blob/main/{repo_relative_notebook}"
913
+ content = (
914
+ f'\n<a href="{github_link}" class="github-badge" target="_blank">'
915
+ + """<img noZoom src="https://img.shields.io/badge/Open%20on%20GitHub-grey?logo=github" alt="Open on GitHub" />"""
916
+ + "</a>"
917
+ + content
918
+ )
919
+
920
+ # If no colab link is present, insert one
921
+ if "colab-badge.svg" not in content:
922
+ colab_link = f"https://colab.research.google.com/github/ag2ai/ag2/blob/main/{repo_relative_notebook}"
923
+ content = (
924
+ f'\n<a href="{colab_link}" class="colab-badge" target="_blank">'
925
+ + """<img noZoom src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" />"""
926
+ + "</a>"
927
+ + content
928
+ )
929
+
930
+ # Create the front matter metadata js file for examples by notebook section
931
+ add_front_matter_to_metadata_yml(front_matter, website_build_directory, rendered_mdx)
932
+
933
+ # Dump front_matter to yaml
934
+ front_matter_str = yaml.dump(front_matter, default_flow_style=False)
935
+
936
+ # Add render_macros: false to the front matter
937
+ front_matter_str += "render_macros: false\n"
938
+
939
+ # transform content for mkdocs
940
+ rel_path = f"/{rendered_mdx.relative_to(website_build_directory.parents[0])}"
941
+ content = transform_content_for_mkdocs(content, rel_path)
942
+
943
+ # Convert mdx image syntax to mintly image syntax
944
+ # content = convert_mdx_image_blocks(content, rendered_mdx, website_build_directory)
945
+
946
+ # ensure editUrl is present
947
+ # content = ensure_edit_url(content, repo_relative_notebook)
948
+
949
+ # Remove admonition blocks
950
+ content = transform_admonition_blocks(content)
951
+
952
+ # Remove mdx-code-block markers
953
+ content = remove_mdx_code_blocks(content)
954
+
955
+ # Generate the page title
956
+ page_header = front_matter.get("title")
957
+ page_title = f"# {page_header}\n\n" if page_header else ""
958
+
959
+ # Rewrite the content as
960
+ # ---
961
+ # front_matter_str
962
+ # ---
963
+ # content
964
+ new_content = f"---\n{front_matter_str}---\n\n{page_title}\n{content}"
965
+
966
+ # Change the file extension to .md
967
+ rendered_md = rendered_mdx.with_suffix(".md")
968
+
969
+ with open(rendered_md, "w", encoding="utf-8") as f:
970
+ f.write(new_content)
971
+
972
+ # Optionally, remove the original .mdx file
973
+ rendered_mdx.unlink()
974
+
975
+
976
+ def target_dir_func(website_build_directory: Path) -> Path:
977
+ """Return the target directory for notebooks."""
978
+ return website_build_directory / "use-cases" / "notebooks" / "notebooks"
979
+
980
+
981
+ def inject_gallery_html(notebooks_md_path: Path, metadata_yml_path: Path) -> None:
982
+ """Generate the index.html file for the notebooks section."""
983
+ with open(notebooks_md_path, encoding="utf-8") as f:
984
+ content = f.read()
985
+
986
+ gallery_html = render_gallery_html(metadata_yml_path)
987
+
988
+ updated_content = content.replace("{{ render_gallery(gallery_items) }}", gallery_html)
989
+ with open(notebooks_md_path, "w", encoding="utf-8") as f:
990
+ f.write(updated_content)
991
+
992
+
993
+ @require_optional_import("yaml", "docs")
994
+ def add_notebooks_nav(mkdocs_nav_path: Path, metadata_yml_path: Path) -> None:
995
+ """Add notebooks navigation to the summary markdown file.
996
+
997
+ Args:
998
+ mkdocs_nav_path: Path to the mkdocs navigation template file
999
+ metadata_yml_path: Path to the notebooks metadata YAML file
1000
+ """
1001
+ # Read the metadata file to get notebook items
1002
+ with open(metadata_yml_path, "r") as file:
1003
+ items = yaml.safe_load(file)
1004
+
1005
+ # Create navigation list entries for each notebook
1006
+ nav_list = []
1007
+ for item in items:
1008
+ _link = item["link"][1:] if item["link"].startswith("/") else item["link"]
1009
+ nav_list.append(f" - [{item['title']}]({_link})\n")
1010
+
1011
+ # Read the summary file
1012
+ with open(mkdocs_nav_path, "r") as file:
1013
+ lines = file.readlines()
1014
+
1015
+ # Find where to insert the notebook entries
1016
+ for i, line in enumerate(lines):
1017
+ if line.strip() == "- [All Notebooks](docs/use-cases/notebooks/Notebooks.md)":
1018
+ # Insert all notebook items after the Notebooks line
1019
+ # No need to insert extra blank lines, just the notebook entries
1020
+ for j, nav_item in enumerate(nav_list):
1021
+ lines.insert(i + 1 + j, nav_item)
1022
+ break
1023
+
1024
+ # Write the updated content back to the summary file
1025
+ with open(mkdocs_nav_path, "w") as file:
1026
+ file.writelines(lines)
1027
+
1028
+
1029
+ def _generate_navigation_entries(dir_path: Path, mkdocs_output_dir: Path) -> list[str]:
1030
+ """Generate navigation entries for user stories and community talks.
1031
+
1032
+ Args:
1033
+ dir_path (Path): Path to the directory containing user stories or community talks.
1034
+ mkdocs_output_dir (Path): Path to the MkDocs output directory.
1035
+
1036
+ Returns:
1037
+ str: Formatted navigation entries.
1038
+ """
1039
+
1040
+ # Read all user story files and sort them by date (newest first)
1041
+ files = sorted(dir_path.glob("**/*.md"), key=sort_files_by_date, reverse=True)
1042
+
1043
+ # Prepare user stories navigation entries
1044
+ entries = []
1045
+ for file in files:
1046
+ # Extract the title from the frontmatter using a simpler split approach
1047
+ content = file.read_text()
1048
+
1049
+ # Split content at the "---" markers
1050
+ parts = content.split("---", 2)
1051
+ if len(parts) < 3:
1052
+ # No valid frontmatter found, use directory name as title
1053
+ title = file.parent.name
1054
+ else:
1055
+ # Parse the frontmatter
1056
+ frontmatter_text = parts[1].strip()
1057
+ frontmatter = yaml.safe_load(frontmatter_text)
1058
+ title = frontmatter.get("title", file.parent.name)
1059
+
1060
+ # Generate relative path from the docs root directory
1061
+ relative_path = file.parent.relative_to(mkdocs_output_dir)
1062
+ path_for_link = str(relative_path).replace("\\", "/")
1063
+
1064
+ # Format navigation entry
1065
+ entries.append(f" - [{title}]({path_for_link}/{file.name})")
1066
+
1067
+ return entries
1068
+
1069
+
1070
+ def generate_community_insights_nav(mkdocs_output_dir: Path, mkdocs_nav_path: Path) -> None:
1071
+ user_stories_dir = mkdocs_output_dir / "docs" / "user-stories"
1072
+ community_talks_dir = mkdocs_output_dir / "docs" / "community-talks"
1073
+
1074
+ user_stories_entries = _generate_navigation_entries(user_stories_dir, mkdocs_output_dir)
1075
+ community_talks_entries = _generate_navigation_entries(community_talks_dir, mkdocs_output_dir)
1076
+
1077
+ user_stories_nav = " - User Stories\n" + "\n".join(user_stories_entries)
1078
+ community_talks_nav = " - Community Talks\n" + "\n".join(community_talks_entries)
1079
+ community_insights_nav = "- Community Insights\n" + user_stories_nav + "\n" + community_talks_nav
1080
+
1081
+ # Read existing navigation template
1082
+ nav_content = mkdocs_nav_path.read_text()
1083
+
1084
+ section_to_follow_marker = "- Blog"
1085
+
1086
+ replacement_content = f"{community_insights_nav}\n{section_to_follow_marker}"
1087
+ updated_nav_content = nav_content.replace(section_to_follow_marker, replacement_content)
1088
+
1089
+ # Write updated navigation to file
1090
+ mkdocs_nav_path.write_text(updated_nav_content)
1091
+
1092
+
1093
+ def add_authors_info_to_user_stories(website_dir: Path) -> None:
1094
+ mkdocs_output_dir = website_dir / "mkdocs" / "docs" / "docs"
1095
+ user_stories_dir = mkdocs_output_dir / "user-stories"
1096
+ authors_yml = website_dir / "blogs_and_user_stories_authors.yml"
1097
+
1098
+ all_authors_info = get_authors_info(authors_yml)
1099
+
1100
+ add_authors_and_social_preview(website_dir, user_stories_dir, all_authors_info, "mkdocs")
1101
+
1102
+ for file_path in user_stories_dir.glob("**/*.md"):
1103
+ content = file_path.read_text(encoding="utf-8")
1104
+ rel_path = f"/{file_path.relative_to(mkdocs_output_dir.parents[0])}"
1105
+ updated_content = transform_content_for_mkdocs(content, rel_path)
1106
+ file_path.write_text(updated_content, encoding="utf-8")
1107
+
1108
+
1109
+ def main(force: bool) -> None:
1110
+ parser = create_base_argument_parser()
1111
+ args = parser.parse_args(["render"])
1112
+ args.dry_run = False
1113
+ args.quarto_bin = "quarto"
1114
+ args.notebooks = None
1115
+
1116
+ # check if args.force is set
1117
+ if force and mkdocs_output_dir.exists():
1118
+ shutil.rmtree(mkdocs_output_dir)
1119
+
1120
+ exclusion_list = [
1121
+ "docs/.gitignore",
1122
+ "docs/installation",
1123
+ "docs/user-guide/getting-started",
1124
+ "docs/user-guide/models/litellm-with-watsonx.md",
1125
+ "docs/contributor-guide/Migration-Guide.md",
1126
+ ]
1127
+ nav_exclusions = [""]
1128
+
1129
+ files_to_copy = get_git_tracked_and_untracked_files_in_directory(mint_docs_dir)
1130
+ filtered_files = filter_excluded_files(files_to_copy, exclusion_list, website_dir)
1131
+
1132
+ # Copy snippet files
1133
+ snippet_files = get_git_tracked_and_untracked_files_in_directory(website_dir / "snippets")
1134
+ copy_files(website_dir / "snippets", mkdocs_output_dir.parent / "snippets", snippet_files)
1135
+
1136
+ copy_assets(website_dir)
1137
+ process_and_copy_files(mint_docs_dir, mkdocs_output_dir, filtered_files)
1138
+
1139
+ snippets_dir_path = website_dir / "snippets"
1140
+ authors_yml_path = website_dir / "blogs_and_user_stories_authors.yml"
1141
+
1142
+ process_blog_files(mkdocs_output_dir, authors_yml_path, snippets_dir_path)
1143
+ generate_mkdocs_navigation(website_dir, mkdocs_root_dir, nav_exclusions)
1144
+
1145
+ if args.website_build_directory is None:
1146
+ args.website_build_directory = mkdocs_output_dir
1147
+
1148
+ if args.notebook_directory is None:
1149
+ args.notebook_directory = mkdocs_root_dir / "../../notebook"
1150
+
1151
+ metadata_yml_path = Path(args.website_build_directory) / "../../data/notebooks_metadata.yml"
1152
+
1153
+ if not metadata_yml_path.exists() or (force and mkdocs_output_dir.exists()):
1154
+ process_notebooks_core(args, post_process_func, target_dir_func)
1155
+
1156
+ # Render Notebooks Gallery HTML
1157
+ notebooks_md_path = mkdocs_output_dir / "use-cases" / "notebooks" / "Notebooks.md"
1158
+ inject_gallery_html(notebooks_md_path, metadata_yml_path)
1159
+
1160
+ # Add Notebooks Navigation to Summary.md
1161
+ mkdocs_nav_path = mkdocs_root_dir / "docs" / "navigation_template.txt"
1162
+ add_notebooks_nav(mkdocs_nav_path, metadata_yml_path)
1163
+
1164
+ # Render Community Gallery HTML
1165
+ community_md_path = mkdocs_output_dir / "use-cases" / "community-gallery" / "community-gallery.md"
1166
+ metadata_yml_path = Path(args.website_build_directory) / "../../data/gallery_items.yml"
1167
+ inject_gallery_html(community_md_path, metadata_yml_path)
1168
+
1169
+ # Generate Navigation for User Stories
1170
+ docs_dir = mkdocs_root_dir / "docs"
1171
+ generate_community_insights_nav(docs_dir, mkdocs_nav_path)
1172
+
1173
+ # Add Authors info to User Stories
1174
+ add_authors_info_to_user_stories(website_dir)