fastworkflow 2.13.5__tar.gz → 2.14.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/PKG-INFO +1 -1
  2. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/you_misunderstood.py +1 -1
  3. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/go_up.py +1 -1
  4. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/reset_context.py +1 -1
  5. fastworkflow-2.14.0/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_can_i_do.py +158 -0
  6. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/wildcard.py +7 -3
  7. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/genai_postprocessor.py +143 -149
  8. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/chat_session.py +42 -11
  9. fastworkflow-2.14.0/fastworkflow/command_metadata_api.py +788 -0
  10. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/command_routing.py +4 -1
  11. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/hello_world/_commands/add_two_numbers.py +1 -0
  12. fastworkflow-2.14.0/fastworkflow/examples/retail_workflow/_commands/calculate.py +67 -0
  13. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/cancel_pending_order.py +4 -1
  14. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/exchange_delivered_order_items.py +13 -1
  15. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_email.py +6 -1
  16. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_name_zip.py +6 -1
  17. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/get_order_details.py +22 -10
  18. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/get_product_details.py +12 -4
  19. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/get_user_details.py +21 -5
  20. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/list_all_product_types.py +4 -1
  21. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_address.py +3 -0
  22. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_items.py +12 -0
  23. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_payment.py +7 -1
  24. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/modify_user_address.py +3 -0
  25. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/return_delivered_order_items.py +10 -1
  26. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/_commands/transfer_to_human_agents.py +1 -1
  27. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/calculate.py +1 -1
  28. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/mcp_server.py +52 -44
  29. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/run/__main__.py +9 -5
  30. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/run_agent/__main__.py +8 -8
  31. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/run_agent/agent_module.py +6 -16
  32. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/command_dependency_graph.py +130 -143
  33. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/dspy_utils.py +11 -0
  34. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/signatures.py +7 -0
  35. fastworkflow-2.14.0/fastworkflow/workflow_agent.py +186 -0
  36. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/pyproject.toml +1 -1
  37. fastworkflow-2.13.5/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_can_i_do.py +0 -226
  38. fastworkflow-2.13.5/fastworkflow/agent_integration.py +0 -239
  39. fastworkflow-2.13.5/fastworkflow/examples/retail_workflow/_commands/parameter_dependency_graph.json +0 -36
  40. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/LICENSE +0 -0
  41. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/README.md +0 -0
  42. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/.DS_Store +0 -0
  43. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/__init__.py +0 -0
  44. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/__init__.py +0 -0
  45. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/__init__.py +0 -0
  46. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/abort.py +0 -0
  47. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_is_current_context.py +0 -0
  48. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/__init__.py +0 -0
  49. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/_workflows/command_metadata_extraction/command_context_model.json +0 -0
  50. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/__main__.py +0 -0
  51. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/ast_class_extractor.py +0 -0
  52. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/class_analysis_structures.py +0 -0
  53. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/cli_specification.md +0 -0
  54. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/command_dependency_resolver.py +0 -0
  55. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/command_file_generator.py +0 -0
  56. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/command_file_template.py +0 -0
  57. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/command_import_utils.py +0 -0
  58. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/command_stub_generator.py +0 -0
  59. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/context_folder_generator.py +0 -0
  60. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/context_model_generator.py +0 -0
  61. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/dependency_manager.py +0 -0
  62. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/dir_scanner.py +0 -0
  63. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/documentation_generator.py +0 -0
  64. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/inheritance_block_regenerator.py +0 -0
  65. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/libcst_transformers.py +0 -0
  66. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/navigator_stub_generator.py +0 -0
  67. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/pydantic_model_generator.py +0 -0
  68. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/build/utterance_generator.py +0 -0
  69. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/cache_matching.py +0 -0
  70. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/cli.py +0 -0
  71. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/command_context_model.py +0 -0
  72. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/command_directory.py +0 -0
  73. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/command_executor.py +0 -0
  74. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/command_interfaces.py +0 -0
  75. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/docs/context_modules_prd.txt +0 -0
  76. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/extended_workflow_example/README.md +0 -0
  77. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/extended_workflow_example/_commands/WorkItem/get_status.py +0 -0
  78. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/extended_workflow_example/_commands/generate_report.py +0 -0
  79. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/extended_workflow_example/_commands/startup.py +0 -0
  80. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/extended_workflow_example/simple_workflow_template.json +0 -0
  81. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/extended_workflow_example/workflow_inheritance_model.json +0 -0
  82. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/fastworkflow.env +0 -0
  83. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/fastworkflow.passwords.env +0 -0
  84. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/hello_world/_commands/README.md +0 -0
  85. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/hello_world/_commands/context_inheritance_model.json +0 -0
  86. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/hello_world/application/add_two_numbers.py +0 -0
  87. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_1/_commands/context_inheritance_model.json +0 -0
  88. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_1/_commands/send_message.py +0 -0
  89. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_1/application/send_message.py +0 -0
  90. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_2/_commands/User/send_message.py +0 -0
  91. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_2/_commands/context_inheritance_model.json +0 -0
  92. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_2/_commands/startup.py +0 -0
  93. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_2/application/user.py +0 -0
  94. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_3/_commands/PremiumUser/send_priority_message.py +0 -0
  95. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_3/_commands/User/send_message.py +0 -0
  96. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_3/_commands/context_inheritance_model.json +0 -0
  97. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_3/_commands/initialize_user.py +0 -0
  98. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_3/application/user.py +0 -0
  99. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/_ChatRoom.py +0 -0
  100. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/add_user.py +0 -0
  101. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/broadcast_message.py +0 -0
  102. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/get_current_user.py +0 -0
  103. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/list_users.py +0 -0
  104. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/set_current_user.py +0 -0
  105. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/_PremiumUser.py +0 -0
  106. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/send_priority_message.py +0 -0
  107. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/User/_User.py +0 -0
  108. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/User/send_message.py +0 -0
  109. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/context_inheritance_model.json +0 -0
  110. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/_commands/set_root_context.py +0 -0
  111. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/application/chatroom.py +0 -0
  112. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/application/user.py +0 -0
  113. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/context_hierarchy_model.json +0 -0
  114. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/messaging_app_4/startup_action.json +0 -0
  115. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/command_dependency_graph.json +0 -0
  116. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/context_inheritance_model.json +0 -0
  117. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/retail_data/__init__.py +0 -0
  118. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/retail_data/orders.json +0 -0
  119. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/retail_data/products.json +0 -0
  120. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/retail_data/users.json +0 -0
  121. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/cancel_pending_order.py +0 -0
  122. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/exchange_delivered_order_items.py +0 -0
  123. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_email.py +0 -0
  124. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_name_zip.py +0 -0
  125. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/get_order_details.py +0 -0
  126. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/get_product_details.py +0 -0
  127. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/get_user_details.py +0 -0
  128. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/list_all_product_types.py +0 -0
  129. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_address.py +0 -0
  130. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_items.py +0 -0
  131. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_payment.py +0 -0
  132. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/modify_user_address.py +0 -0
  133. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/return_delivered_order_items.py +0 -0
  134. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/think.py +0 -0
  135. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/tool.py +0 -0
  136. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/tools/transfer_to_human_agents.py +0 -0
  137. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/retail_workflow/workflow_description.txt +0 -0
  138. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/__init__.py +0 -0
  139. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/_WorkItem.py +0 -0
  140. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/add_child_workitem.py +0 -0
  141. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/get_status.py +0 -0
  142. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/go_to_workitem.py +0 -0
  143. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/mark_as_complete.py +0 -0
  144. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_first_child_workitem.py +0 -0
  145. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_last_child_workitem.py +0 -0
  146. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_next_workitem.py +0 -0
  147. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_previous_workitem.py +0 -0
  148. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_all_child_workitems.py +0 -0
  149. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_child_workitem.py +0 -0
  150. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/show_schema.py +0 -0
  151. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/_commands/startup.py +0 -0
  152. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/application/__init__.py +0 -0
  153. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/application/workitem.py +0 -0
  154. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/simple_workflow_template.json +0 -0
  155. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/examples/simple_workflow_template/startup_action.json +0 -0
  156. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/model_pipeline_training.py +0 -0
  157. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/refine/__main__.py +0 -0
  158. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/run/__init__.py +0 -0
  159. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/run_agent/__init__.py +0 -0
  160. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/train/__init__.py +0 -0
  161. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/train/__main__.py +0 -0
  162. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/train/generate_synthetic.py +0 -0
  163. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/user_message_queues.py +0 -0
  164. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/__init__.py +0 -0
  165. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/context_utils.py +0 -0
  166. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/dspy_cache_utils.py +0 -0
  167. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/dspy_logger.py +0 -0
  168. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/env.py +0 -0
  169. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/fuzzy_match.py +0 -0
  170. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/generate_param_examples.py +0 -0
  171. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/logging.py +0 -0
  172. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/parameterize_func_decorator.py +0 -0
  173. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/pydantic_model_2_dspy_signature_class.py +0 -0
  174. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/python_utils.py +0 -0
  175. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/utils/startup_progress.py +0 -0
  176. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/workflow.py +0 -0
  177. {fastworkflow-2.13.5 → fastworkflow-2.14.0}/fastworkflow/workflow_inheritance_model.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastworkflow
3
- Version: 2.13.5
3
+ Version: 2.14.0
4
4
  Summary: A framework for rapidly building large-scale, deterministic, interactive workflows with a fault-tolerant, conversational UX
5
5
  License: Apache-2.0
6
6
  Keywords: fastworkflow,ai,workflow,llm,openai
@@ -41,7 +41,7 @@ class ResponseGenerator:
41
41
  fully_qualified_command_names = (
42
42
  set(cme_command_names) |
43
43
  set(subject_crd.get_command_names(app_workflow.current_command_context_name))
44
- ) - {'wildcard'}
44
+ )
45
45
 
46
46
  valid_command_names = [
47
47
  fully_qualified_command_name.split('/')[-1]
@@ -6,7 +6,7 @@ from fastworkflow.train.generate_synthetic import generate_diverse_utterances
6
6
 
7
7
 
8
8
  class Signature: # noqa: D101
9
- """Change context to the parent of the current context."""
9
+ """Change context to the parent of the current context. This could change the commands that are available."""
10
10
 
11
11
  plain_utterances = [
12
12
  "go up",
@@ -5,7 +5,7 @@ from fastworkflow.train.generate_synthetic import generate_diverse_utterances
5
5
 
6
6
 
7
7
  class Signature: # noqa: D101
8
- """Reset the current context to the global context (*)."""
8
+ """Reset the current context to the global context (*). This could change the commands that are available."""
9
9
  plain_utterances = [
10
10
  "reset context",
11
11
  "clear context",
@@ -0,0 +1,158 @@
1
+ from __future__ import annotations
2
+
3
+ import contextlib
4
+ from pathlib import Path
5
+ from typing import Dict, Any
6
+ from pydantic import BaseModel
7
+ import json
8
+
9
+ import fastworkflow
10
+ from fastworkflow.train.generate_synthetic import generate_diverse_utterances
11
+ from fastworkflow.command_metadata_api import CommandMetadataAPI
12
+
13
+ class Signature:
14
+ """List all the commands available in the current context along with their metadata"""
15
+ class Output(BaseModel):
16
+ valid_command_names: list[str]
17
+
18
+ # Constants from plain_utterances.json
19
+ plain_utterances = [
20
+ "show me all the utterances",
21
+ "what can you do?",
22
+ "what are my options?",
23
+ "what are my choices?",
24
+ "what are my capabilities?",
25
+ "what can i do?",
26
+ "what can i do here?",
27
+ "what can i use?",
28
+ "what are my tools?",
29
+ "now what?",
30
+ "list commands",
31
+ "list utterances"
32
+ ]
33
+
34
+ @staticmethod
35
+ def generate_utterances(workflow: fastworkflow.Workflow, command_name: str) -> list[str]:
36
+ return [
37
+ command_name.split('/')[-1].lower().replace('_', ' ')
38
+ ] + generate_diverse_utterances(Signature.plain_utterances, command_name)
39
+
40
+
41
+ class ResponseGenerator:
42
+ # def _get_enhanced_command_info(self, workflow: fastworkflow.Workflow) -> Dict[str, Any]:
43
+ # """
44
+ # Get enhanced command information for agent mode.
45
+ # Returns structured JSON with context info, command details, etc.
46
+ # """
47
+ # app_workflow = workflow.context["app_workflow"]
48
+
49
+ # # Get the current context information
50
+ # context_info = {
51
+ # "name": app_workflow.current_command_context_name,
52
+ # "display_name": app_workflow.current_command_context_displayname,
53
+ # "description": "",
54
+ # "inheritance": [],
55
+ # "containment": []
56
+ # }
57
+
58
+ # # Try to load context hierarchy information if available
59
+ # with contextlib.suppress(Exception):
60
+ # inheritance_path = Path(app_workflow.folderpath) / "context_inheritance_model.json"
61
+ # if inheritance_path.exists():
62
+ # with open(inheritance_path) as f:
63
+ # inheritance_data = json.load(f)
64
+ # context_info["inheritance"] = inheritance_data.get(context_info["name"], [])
65
+
66
+ # containment_path = Path(app_workflow.folderpath) / "context_containment_model.json"
67
+ # if containment_path.exists():
68
+ # with open(containment_path) as f:
69
+ # containment_data = json.load(f)
70
+ # context_info["containment"] = containment_data.get(context_info["name"], [])
71
+
72
+ # from fastworkflow.command_metadata_api import CommandMetadataAPI
73
+
74
+ # meta = CommandMetadataAPI.get_enhanced_command_info(
75
+ # subject_workflow_path=app_workflow.folderpath,
76
+ # cme_workflow_path=workflow.folderpath,
77
+ # active_context_name=app_workflow.current_command_context_name,
78
+ # )
79
+
80
+ # return {
81
+ # "context": context_info,
82
+ # "commands": meta.get("commands", [])
83
+ # }
84
+
85
+ # def _process_command(
86
+ # self, workflow: fastworkflow.Workflow
87
+ # ) -> Signature.Output:
88
+ # """
89
+ # Provides helpful information about this type of work-item.
90
+ # If the workitem_path is not provided, it provides information about the current work-item.
91
+
92
+ # :param input: The input parameters for the function.
93
+ # """
94
+ # app_workflow = workflow.context["app_workflow"]
95
+ # subject_crd = fastworkflow.RoutingRegistry.get_definition(
96
+ # app_workflow.folderpath)
97
+
98
+ # crd = fastworkflow.RoutingRegistry.get_definition(
99
+ # workflow.folderpath)
100
+ # cme_command_names = crd.get_command_names('IntentDetection')
101
+
102
+ # # ------------------------------------------------------------------
103
+ # # Build the union of command names that *should* be visible, then
104
+ # # filter out any command that (a) is the special wildcard helper or
105
+ # # (b) has no user-facing utterances in *any* command directory.
106
+ # # ------------------------------------------------------------------
107
+
108
+ # candidate_commands: set[str] = (
109
+ # set(cme_command_names)
110
+ # | set(subject_crd.get_command_names(app_workflow.current_command_context_name))
111
+ # )
112
+
113
+ # def _has_utterances(fq_cmd: str) -> bool:
114
+ # """Return True if *fq_cmd* has at least one utterance definition in
115
+ # either the subject workflow or the CME workflow."""
116
+ # return (
117
+ # subject_crd.command_directory.get_utterance_metadata(fq_cmd) is not None
118
+ # or crd.command_directory.get_utterance_metadata(fq_cmd) is not None
119
+ # )
120
+
121
+ # visible_commands = [
122
+ # fq_cmd for fq_cmd in candidate_commands
123
+ # if fq_cmd != "wildcard" and _has_utterances(fq_cmd)
124
+ # ]
125
+
126
+ # valid_command_names = [
127
+ # cmd.split("/")[-1] for cmd in sorted(visible_commands)
128
+ # ]
129
+
130
+ # return Signature.Output(valid_command_names=valid_command_names)
131
+
132
+ def __call__(
133
+ self,
134
+ workflow: fastworkflow.Workflow,
135
+ command: str,
136
+ ) -> fastworkflow.CommandOutput:
137
+ # Check if we're in agent mode by looking for chat session run_as_agent flag
138
+ is_agent_mode = False
139
+ with contextlib.suppress(Exception):
140
+ if fastworkflow.chat_session:
141
+ is_agent_mode = fastworkflow.chat_session.run_as_agent
142
+
143
+ app_workflow = workflow.context["app_workflow"]
144
+ response = CommandMetadataAPI.get_command_display_text(
145
+ subject_workflow_path=app_workflow.folderpath,
146
+ cme_workflow_path=workflow.folderpath,
147
+ active_context_name=app_workflow.current_command_context_name,
148
+ for_agents=is_agent_mode,
149
+ )
150
+
151
+ return fastworkflow.CommandOutput(
152
+ workflow_id=workflow.id,
153
+ command_responses=[
154
+ fastworkflow.CommandResponse(
155
+ response=response,
156
+ )
157
+ ]
158
+ )
@@ -80,7 +80,7 @@ class CommandNamePrediction:
80
80
  valid_command_names = (
81
81
  set(cme_command_names) |
82
82
  set(app_crd.get_command_names(command_context_name))
83
- ) - {'wildcard'}
83
+ )
84
84
 
85
85
  command_name_dict = {
86
86
  fully_qualified_command_name.split('/')[-1]: fully_qualified_command_name
@@ -338,7 +338,11 @@ class ParameterExtraction:
338
338
 
339
339
  stored_params = self._get_stored_parameters(self.cme_workflow)
340
340
 
341
- input_for_param_extraction = InputForParamExtraction.create(self.app_workflow, self.command_name, self.command)
341
+ self.command = self.command.replace(self.command_name, "").strip()
342
+
343
+ input_for_param_extraction = InputForParamExtraction.create(
344
+ self.app_workflow, self.command_name,
345
+ self.command)
342
346
 
343
347
  if stored_params:
344
348
  _, _, _, stored_missing_fields = self._extract_missing_fields(input_for_param_extraction, self.app_workflow, self.command_name, stored_params)
@@ -372,7 +376,7 @@ class ParameterExtraction:
372
376
  if params_str := self._format_parameters_for_display(merged_params):
373
377
  error_msg = f"Extracted parameters so far:\n{params_str}\n\n{error_msg}"
374
378
 
375
- error_msg += "\nEnter 'abort' if you want to abort the command."
379
+ error_msg += "\nEnter 'abort' to get out of this error state and/or execute a different command."
376
380
  error_msg += "\nEnter 'you misunderstood' if the wrong command was executed."
377
381
  return self.Output(
378
382
  parameters_are_valid=False,
@@ -18,8 +18,9 @@ import traceback
18
18
  import libcst as cst
19
19
  import dspy
20
20
  from pydantic import BaseModel, Field
21
- import fastworkflow
22
21
 
22
+ import fastworkflow
23
+ from fastworkflow.utils import dspy_utils
23
24
  from fastworkflow.build.class_analysis_structures import ClassInfo, MethodInfo, FunctionInfo
24
25
  from fastworkflow.build.libcst_transformers import (
25
26
  SignatureDocstringUpdater,
@@ -235,11 +236,7 @@ class GenAIPostProcessor:
235
236
  def __init__(self):
236
237
  """Initialize the post-processor with DSPy configuration."""
237
238
  # Get model and API key from FastWorkflow environment
238
- self.model = fastworkflow.get_env_var("LLM_COMMAND_METADATA_GEN", default="mistral/mistral-small-latest")
239
- self.api_key = fastworkflow.get_env_var("LITELLM_API_KEY_COMMANDMETADATA_GEN", default=None)
240
-
241
- # Initialize DSPy with the configured model
242
- self._initialize_dspy()
239
+ self.lm = dspy_utils.get_lm("LLM_COMMAND_METADATA_GEN", "LITELLM_API_KEY_COMMANDMETADATA_GEN", max_tokens=2000)
243
240
 
244
241
  # Initialize DSPy modules (reuse from original)
245
242
  self.field_generator = FieldMetadataGenerator()
@@ -256,16 +253,6 @@ class GenAIPostProcessor:
256
253
  'utterances_added': 0
257
254
  }
258
255
 
259
- def _initialize_dspy(self):
260
- """Initialize DSPy with the configured model using LiteLLM."""
261
- try:
262
- lm = dspy.LM(model=self.model, api_key=self.api_key, max_tokens=2000)
263
- dspy.settings.configure(lm=lm)
264
- logger.info(f"DSPy initialized with model: {self.model}")
265
- except Exception as e:
266
- logger.error(f"Failed to initialize DSPy: {e}")
267
- raise
268
-
269
256
  def process_workflow(self, workflow_path: str, classes: Dict[str, ClassInfo],
270
257
  functions: Optional[Dict[str, FunctionInfo]] = None) -> bool:
271
258
  """Process all command files in the workflow with targeted updates.
@@ -280,17 +267,17 @@ class GenAIPostProcessor:
280
267
  """
281
268
  try:
282
269
  logger.info("Starting targeted GenAI post-processing with LibCST...")
283
-
270
+
284
271
  # Process command files
285
272
  commands_dir = os.path.join(workflow_path, "_commands")
286
273
  if not os.path.exists(commands_dir):
287
274
  logger.error(f"Commands directory not found: {commands_dir}")
288
275
  return False
289
-
276
+
290
277
  # Track all contexts and commands for workflow description
291
278
  all_contexts = {}
292
279
  global_commands = []
293
-
280
+
294
281
  # Process context-specific commands
295
282
  for context_dir in os.listdir(commands_dir):
296
283
  context_path = os.path.join(commands_dir, context_dir)
@@ -304,10 +291,10 @@ class GenAIPostProcessor:
304
291
  'commands': context_commands,
305
292
  'docstring': ""
306
293
  }
307
-
294
+
308
295
  # Generate context handler docstring (still uses original method)
309
296
  self._generate_context_handler_docstring(context_path, context_dir, context_commands)
310
-
297
+
311
298
  # Process global commands
312
299
  for file_name in os.listdir(commands_dir):
313
300
  file_path = os.path.join(commands_dir, file_name)
@@ -319,20 +306,20 @@ class GenAIPostProcessor:
319
306
  'name': command_name,
320
307
  'docstring': func_info.docstring if func_info else ""
321
308
  })
322
-
309
+
323
310
  # Generate workflow description (reuse original method)
324
311
  self._generate_workflow_description(workflow_path, all_contexts, global_commands)
325
-
312
+
326
313
  # Log statistics
327
- logger.info(f"Targeted post-processing completed:")
314
+ logger.info("Targeted post-processing completed:")
328
315
  logger.info(f" Files processed: {self.stats['files_processed']}")
329
316
  logger.info(f" Files updated: {self.stats['files_updated']}")
330
317
  logger.info(f" Docstrings added: {self.stats['docstrings_added']}")
331
318
  logger.info(f" Fields updated: {self.stats['fields_updated']}")
332
319
  logger.info(f" Utterances added: {self.stats['utterances_added']}")
333
-
320
+
334
321
  return True
335
-
322
+
336
323
  except Exception as e:
337
324
  logger.error(f"Error during targeted GenAI post-processing: {e}")
338
325
  logger.error(traceback.format_exc())
@@ -465,112 +452,116 @@ class GenAIPostProcessor:
465
452
  """Generate enhanced content using DSPy modules, only for missing elements."""
466
453
 
467
454
  enhanced_data = {}
468
-
455
+
469
456
  # Only generate docstring if missing or empty
470
457
  if not current_state.get('has_signature_docstring'):
471
458
  try:
472
- signature_docstring = self.docstring_generator.generate_signature_docstring(
473
- command_name=command_name,
474
- input_fields=[{
475
- 'name': f['name'],
476
- 'type': f['type'],
477
- 'description': '' # Will be generated if needed
478
- } for f in current_state['input_fields']],
479
- output_fields=[{
480
- 'name': f['name'],
481
- 'type': f['type'],
482
- 'description': ''
483
- } for f in current_state['output_fields']],
484
- context_name=context_name or "global"
485
- )
486
- enhanced_data['signature_docstring'] = signature_docstring
487
- logger.debug(f"Generated new docstring for {command_name}")
459
+ with dspy.context(lm=self.lm):
460
+ signature_docstring = self.docstring_generator.generate_signature_docstring(
461
+ command_name=command_name,
462
+ input_fields=[{
463
+ 'name': f['name'],
464
+ 'type': f['type'],
465
+ 'description': '' # Will be generated if needed
466
+ } for f in current_state['input_fields']],
467
+ output_fields=[{
468
+ 'name': f['name'],
469
+ 'type': f['type'],
470
+ 'description': ''
471
+ } for f in current_state['output_fields']],
472
+ context_name=context_name or "global"
473
+ )
474
+ enhanced_data['signature_docstring'] = signature_docstring
475
+ logger.debug(f"Generated new docstring for {command_name}")
488
476
  except Exception as e:
489
477
  logger.warning(f"Failed to generate docstring for {command_name}: {e}")
490
-
478
+
491
479
  # Generate field metadata only for fields missing descriptions/examples
492
480
  field_metadata = {}
493
-
481
+
494
482
  # Process input fields
495
483
  for field_info in current_state['input_fields']:
496
484
  if not field_info.get('has_description') or not field_info.get('has_examples'):
497
485
  try:
498
- metadata = self.field_generator(
499
- field_name=field_info['name'],
500
- field_type=field_info['type'],
501
- method_docstring=method_or_func_info.docstring if method_or_func_info else "",
502
- method_name=command_name,
503
- context_name=context_name or "global",
504
- is_input=True
505
- )
506
-
507
- field_key = f"Input.{field_info['name']}"
508
- field_metadata[field_key] = {}
509
-
510
- if not field_info.get('has_description'):
511
- field_metadata[field_key]['description'] = metadata.description
512
-
513
- if not field_info.get('has_examples'):
514
- field_metadata[field_key]['examples'] = metadata.examples
515
-
516
- if metadata.pattern and metadata.pattern.strip():
517
- field_metadata[field_key]['pattern'] = metadata.pattern
518
-
519
- logger.debug(f"Generated metadata for {field_key}")
486
+ with dspy.context(lm=self.lm):
487
+ metadata = self.field_generator(
488
+ field_name=field_info['name'],
489
+ field_type=field_info['type'],
490
+ method_docstring=method_or_func_info.docstring if method_or_func_info else "",
491
+ method_name=command_name,
492
+ context_name=context_name or "global",
493
+ is_input=True
494
+ )
495
+
496
+ field_key = f"Input.{field_info['name']}"
497
+ field_metadata[field_key] = {}
498
+
499
+ if not field_info.get('has_description'):
500
+ field_metadata[field_key]['description'] = metadata.description
501
+
502
+ if not field_info.get('has_examples'):
503
+ field_metadata[field_key]['examples'] = metadata.examples
504
+
505
+ if metadata.pattern and metadata.pattern.strip():
506
+ field_metadata[field_key]['pattern'] = metadata.pattern
507
+
508
+ logger.debug(f"Generated metadata for {field_key}")
520
509
  except Exception as e:
521
510
  logger.warning(f"Failed to generate metadata for Input.{field_info['name']}: {e}")
522
-
511
+
523
512
  # Process output fields
524
513
  for field_info in current_state['output_fields']:
525
514
  if not field_info.get('has_description') or not field_info.get('has_examples'):
526
515
  try:
527
- metadata = self.field_generator(
528
- field_name=field_info['name'],
529
- field_type=field_info['type'],
530
- method_docstring=method_or_func_info.docstring if method_or_func_info else "",
531
- method_name=command_name,
532
- context_name=context_name or "global",
533
- is_input=False
534
- )
535
-
536
- field_key = f"Output.{field_info['name']}"
537
- field_metadata[field_key] = {}
538
-
539
- if not field_info.get('has_description'):
540
- field_metadata[field_key]['description'] = metadata.description
541
-
542
- if not field_info.get('has_examples'):
543
- field_metadata[field_key]['examples'] = metadata.examples
544
-
545
- logger.debug(f"Generated metadata for {field_key}")
516
+ with dspy.context(lm=self.lm):
517
+ metadata = self.field_generator(
518
+ field_name=field_info['name'],
519
+ field_type=field_info['type'],
520
+ method_docstring=method_or_func_info.docstring if method_or_func_info else "",
521
+ method_name=command_name,
522
+ context_name=context_name or "global",
523
+ is_input=False
524
+ )
525
+
526
+ field_key = f"Output.{field_info['name']}"
527
+ field_metadata[field_key] = {}
528
+
529
+ if not field_info.get('has_description'):
530
+ field_metadata[field_key]['description'] = metadata.description
531
+
532
+ if not field_info.get('has_examples'):
533
+ field_metadata[field_key]['examples'] = metadata.examples
534
+
535
+ logger.debug(f"Generated metadata for {field_key}")
546
536
  except Exception as e:
547
537
  logger.warning(f"Failed to generate metadata for Output.{field_info['name']}: {e}")
548
-
538
+
549
539
  if field_metadata:
550
540
  enhanced_data['field_metadata'] = field_metadata
551
-
541
+
552
542
  # Generate new utterances to append
553
543
  try:
554
- new_utterances = self.utterance_generator(
555
- command_name=command_name,
556
- command_docstring=method_or_func_info.docstring if method_or_func_info else "",
557
- input_fields=[{
558
- 'name': f['name'],
559
- 'type': f['type'],
560
- 'description': ''
561
- } for f in current_state['input_fields']]
562
- )
563
-
564
- # Filter out existing utterances
565
- existing_utterances = set(current_state.get('plain_utterances', []))
566
- truly_new_utterances = [u for u in new_utterances if u not in existing_utterances]
567
-
568
- if truly_new_utterances:
569
- enhanced_data['new_utterances'] = truly_new_utterances
570
- logger.debug(f"Generated {len(truly_new_utterances)} new utterances for {command_name}")
544
+ with dspy.context(lm=self.lm):
545
+ new_utterances = self.utterance_generator(
546
+ command_name=command_name,
547
+ command_docstring=method_or_func_info.docstring if method_or_func_info else "",
548
+ input_fields=[{
549
+ 'name': f['name'],
550
+ 'type': f['type'],
551
+ 'description': ''
552
+ } for f in current_state['input_fields']]
553
+ )
554
+
555
+ # Filter out existing utterances
556
+ existing_utterances = set(current_state.get('plain_utterances', []))
557
+ if truly_new_utterances := [
558
+ u for u in new_utterances if u not in existing_utterances
559
+ ]:
560
+ enhanced_data['new_utterances'] = truly_new_utterances
561
+ logger.debug(f"Generated {len(truly_new_utterances)} new utterances for {command_name}")
571
562
  except Exception as e:
572
563
  logger.warning(f"Failed to generate utterances for {command_name}: {e}")
573
-
564
+
574
565
  return enhanced_data
575
566
 
576
567
  def _generate_context_handler_docstring(self, context_path: str, context_name: str,
@@ -581,66 +572,67 @@ class GenAIPostProcessor:
581
572
  if not os.path.exists(handler_file):
582
573
  logger.debug(f"Context handler file not found: {handler_file}")
583
574
  return
584
-
575
+
585
576
  # Read the file
586
577
  with open(handler_file, 'r') as f:
587
578
  content = f.read()
588
-
579
+
589
580
  # Parse with LibCST
590
581
  module = cst.parse_module(content)
591
-
582
+
592
583
  # Generate context docstring
593
- context_docstring = self.docstring_generator.generate_context_docstring(
594
- context_name=context_name,
595
- commands=commands
596
- )
597
-
598
- # Find the main class and update its docstring
584
+ with dspy.context(lm=self.lm):
585
+ context_docstring = self.docstring_generator.generate_context_docstring(
586
+ context_name=context_name,
587
+ commands=commands
588
+ )
589
+
599
590
  class UpdateContextDocstring(cst.CSTTransformer):
600
591
  def __init__(self, docstring: str):
601
592
  self.docstring = docstring
602
593
  self.updated = False
603
-
594
+
604
595
  def leave_ClassDef(self, original_node: cst.ClassDef, updated_node: cst.ClassDef) -> cst.ClassDef:
605
596
  # Update the first class that matches the context name pattern
606
- if not self.updated and (updated_node.name.value == context_name or
607
- updated_node.name.value.endswith("Handler")):
608
- self.updated = True
609
- # Add or update docstring
610
- if updated_node.body and updated_node.body.body:
611
- first_stmt = updated_node.body.body[0]
612
- if isinstance(first_stmt, cst.SimpleStatementLine):
613
- if first_stmt.body and isinstance(first_stmt.body[0], cst.Expr):
614
- if isinstance(first_stmt.body[0].value, (cst.SimpleString, cst.ConcatenatedString)):
615
- # Replace existing docstring
616
- new_docstring = cst.SimpleStatementLine(
617
- body=[cst.Expr(cst.SimpleString(f'"""{self.docstring}"""'))]
618
- )
619
- new_body = [new_docstring] + list(updated_node.body.body[1:])
620
- return updated_node.with_changes(
621
- body=updated_node.body.with_changes(body=new_body)
622
- )
623
-
624
- # Add new docstring
625
- docstring_node = cst.SimpleStatementLine(
626
- body=[cst.Expr(cst.SimpleString(f'"""{self.docstring}"""'))]
627
- )
628
- new_body = [docstring_node] + list(updated_node.body.body)
629
- return updated_node.with_changes(
630
- body=updated_node.body.with_changes(body=new_body)
631
- )
632
-
633
- return updated_node
634
-
597
+ if (
598
+ self.updated
599
+ or updated_node.name.value != context_name
600
+ and not updated_node.name.value.endswith("Handler")
601
+ ):
602
+ return updated_node
603
+
604
+ self.updated = True
605
+ # Add or update docstring
606
+ if updated_node.body and updated_node.body.body:
607
+ first_stmt = updated_node.body.body[0]
608
+ if isinstance(first_stmt, cst.SimpleStatementLine) and (first_stmt.body and isinstance(first_stmt.body[0], cst.Expr)) and isinstance(first_stmt.body[0].value, (cst.SimpleString, cst.ConcatenatedString)):
609
+ new_docstring = cst.SimpleStatementLine(
610
+ body=[cst.Expr(cst.SimpleString(f'"""{self.docstring}"""'))]
611
+ )
612
+ new_body = [new_docstring] + list(updated_node.body.body[1:])
613
+ return updated_node.with_changes(
614
+ body=updated_node.body.with_changes(body=new_body)
615
+ )
616
+
617
+ # Add new docstring
618
+ docstring_node = cst.SimpleStatementLine(
619
+ body=[cst.Expr(cst.SimpleString(f'"""{self.docstring}"""'))]
620
+ )
621
+ new_body = [docstring_node] + list(updated_node.body.body)
622
+ return updated_node.with_changes(
623
+ body=updated_node.body.with_changes(body=new_body)
624
+ )
625
+
626
+
635
627
  transformer = UpdateContextDocstring(context_docstring)
636
628
  module = module.visit(transformer)
637
-
629
+
638
630
  if transformer.updated:
639
631
  # Write back
640
632
  with open(handler_file, 'w') as f:
641
633
  f.write(module.code)
642
634
  logger.debug(f"Updated context handler docstring for {context_name}")
643
-
635
+
644
636
  except Exception as e:
645
637
  logger.error(f"Error generating context handler docstring: {e}")
646
638
  logger.error(traceback.format_exc())
@@ -649,8 +641,10 @@ class GenAIPostProcessor:
649
641
  all_contexts: Dict[str, Dict],
650
642
  global_commands: List[Dict[str, str]]):
651
643
  """Generate workflow_description.txt file."""
644
+
652
645
  try:
653
- description = self.workflow_generator(all_contexts, global_commands)
646
+ with dspy.context(lm=self.lm):
647
+ description = self.workflow_generator(all_contexts, global_commands)
654
648
 
655
649
  desc_file = os.path.join(workflow_path, "workflow_description.txt")
656
650
  with open(desc_file, 'w') as f: