fastworkflow 2.22.0__tar.gz → 2.22.3__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 (191) hide show
  1. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/PKG-INFO +2 -1
  2. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/command_directory.py +76 -16
  3. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/command_routing.py +51 -6
  4. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/train/__main__.py +58 -1
  5. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/workflow_agent.py +6 -0
  6. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/pyproject.toml +4 -3
  7. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/LICENSE +0 -0
  8. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/README.md +0 -0
  9. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/.DS_Store +0 -0
  10. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/__init__.py +0 -0
  11. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_commands/.gitkeep +0 -0
  12. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/__init__.py +0 -0
  13. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/__init__.py +0 -0
  14. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/abort.py +0 -0
  15. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/you_misunderstood.py +0 -0
  16. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/go_up.py +0 -0
  17. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/reset_context.py +0 -0
  18. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_can_i_do.py +0 -0
  19. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_is_current_context.py +0 -0
  20. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/_commands/__init__.py +0 -0
  21. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/_commands/wildcard.py +0 -0
  22. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/command_context_model.json +0 -0
  23. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/intent_detection.py +0 -0
  24. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/_workflows/command_metadata_extraction/parameter_extraction.py +0 -0
  25. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/active_workflow.py +0 -0
  26. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/__main__.py +0 -0
  27. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/ast_class_extractor.py +0 -0
  28. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/class_analysis_structures.py +0 -0
  29. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/cli_specification.md +0 -0
  30. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/command_dependency_resolver.py +0 -0
  31. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/command_file_generator.py +0 -0
  32. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/command_file_template.py +0 -0
  33. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/command_import_utils.py +0 -0
  34. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/command_stub_generator.py +0 -0
  35. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/context_folder_generator.py +0 -0
  36. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/context_model_generator.py +0 -0
  37. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/dependency_manager.py +0 -0
  38. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/dir_scanner.py +0 -0
  39. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/documentation_generator.py +0 -0
  40. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/genai_postprocessor.py +0 -0
  41. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/inheritance_block_regenerator.py +0 -0
  42. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/libcst_transformers.py +0 -0
  43. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/navigator_stub_generator.py +0 -0
  44. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/pydantic_model_generator.py +0 -0
  45. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/build/utterance_generator.py +0 -0
  46. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/cache_matching.py +0 -0
  47. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/chat_session.py +0 -0
  48. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/cli.py +0 -0
  49. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/command_context_model.py +0 -0
  50. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/command_executor.py +0 -0
  51. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/command_interfaces.py +0 -0
  52. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/command_metadata_api.py +0 -0
  53. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/conversation_history_io.py +0 -0
  54. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/docs/context_modules_prd.txt +0 -0
  55. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/docs/integrate-chat-agent/SKILL.md +0 -0
  56. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/docs/integrate-chat-agent/reference.md +0 -0
  57. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/extended_workflow_example/README.md +0 -0
  58. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/extended_workflow_example/_commands/WorkItem/get_status.py +0 -0
  59. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/extended_workflow_example/_commands/generate_report.py +0 -0
  60. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/extended_workflow_example/_commands/startup.py +0 -0
  61. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/extended_workflow_example/simple_workflow_template.json +0 -0
  62. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/extended_workflow_example/workflow_inheritance_model.json +0 -0
  63. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/fastworkflow.env +0 -0
  64. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/fastworkflow.passwords.env +0 -0
  65. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/hello_world/_commands/README.md +0 -0
  66. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/hello_world/_commands/add_two_numbers.py +0 -0
  67. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/hello_world/_commands/context_inheritance_model.json +0 -0
  68. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/hello_world/application/add_two_numbers.py +0 -0
  69. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_1/_commands/context_inheritance_model.json +0 -0
  70. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_1/_commands/send_message.py +0 -0
  71. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_1/application/send_message.py +0 -0
  72. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_2/_commands/User/send_message.py +0 -0
  73. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_2/_commands/context_inheritance_model.json +0 -0
  74. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_2/_commands/startup.py +0 -0
  75. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_2/application/user.py +0 -0
  76. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_3/_commands/PremiumUser/send_priority_message.py +0 -0
  77. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_3/_commands/User/send_message.py +0 -0
  78. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_3/_commands/context_inheritance_model.json +0 -0
  79. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_3/_commands/initialize_user.py +0 -0
  80. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_3/application/user.py +0 -0
  81. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/_ChatRoom.py +0 -0
  82. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/add_user.py +0 -0
  83. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/broadcast_message.py +0 -0
  84. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/get_current_user.py +0 -0
  85. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/list_users.py +0 -0
  86. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/set_current_user.py +0 -0
  87. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/_PremiumUser.py +0 -0
  88. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/send_priority_message.py +0 -0
  89. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/User/_User.py +0 -0
  90. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/User/send_message.py +0 -0
  91. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/context_inheritance_model.json +0 -0
  92. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/_commands/set_root_context.py +0 -0
  93. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/application/chatroom.py +0 -0
  94. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/application/user.py +0 -0
  95. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/context_hierarchy_model.json +0 -0
  96. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/messaging_app_4/startup_action.json +0 -0
  97. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/calculate.py +0 -0
  98. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/cancel_pending_order.py +0 -0
  99. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/exchange_delivered_order_items.py +0 -0
  100. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_email.py +0 -0
  101. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_name_zip.py +0 -0
  102. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/get_order_details.py +0 -0
  103. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/get_product_details.py +0 -0
  104. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/get_user_details.py +0 -0
  105. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/list_all_product_types.py +0 -0
  106. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_address.py +0 -0
  107. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_items.py +0 -0
  108. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_payment.py +0 -0
  109. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/modify_user_address.py +0 -0
  110. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/return_delivered_order_items.py +0 -0
  111. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/_commands/transfer_to_human_agents.py +0 -0
  112. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/context_inheritance_model.json +0 -0
  113. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/retail_data/__init__.py +0 -0
  114. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/retail_data/orders.json +0 -0
  115. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/retail_data/products.json +0 -0
  116. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/retail_data/users.json +0 -0
  117. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/calculate.py +0 -0
  118. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/cancel_pending_order.py +0 -0
  119. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/exchange_delivered_order_items.py +0 -0
  120. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_email.py +0 -0
  121. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_name_zip.py +0 -0
  122. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/get_order_details.py +0 -0
  123. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/get_product_details.py +0 -0
  124. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/get_user_details.py +0 -0
  125. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/list_all_product_types.py +0 -0
  126. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_address.py +0 -0
  127. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_items.py +0 -0
  128. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_payment.py +0 -0
  129. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/modify_user_address.py +0 -0
  130. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/return_delivered_order_items.py +0 -0
  131. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/think.py +0 -0
  132. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/tool.py +0 -0
  133. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/tools/transfer_to_human_agents.py +0 -0
  134. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/retail_workflow/workflow_description.txt +0 -0
  135. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/__init__.py +0 -0
  136. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/_WorkItem.py +0 -0
  137. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/add_child_workitem.py +0 -0
  138. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/get_status.py +0 -0
  139. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/go_to_workitem.py +0 -0
  140. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/mark_as_complete.py +0 -0
  141. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_first_child_workitem.py +0 -0
  142. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_last_child_workitem.py +0 -0
  143. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_next_workitem.py +0 -0
  144. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_previous_workitem.py +0 -0
  145. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_all_child_workitems.py +0 -0
  146. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_child_workitem.py +0 -0
  147. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/show_schema.py +0 -0
  148. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/_commands/startup.py +0 -0
  149. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/application/__init__.py +0 -0
  150. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/application/workitem.py +0 -0
  151. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/simple_workflow_template.json +0 -0
  152. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/examples/simple_workflow_template/startup_action.json +0 -0
  153. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/intent_clarification_agent.py +0 -0
  154. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/mcp_server.py +0 -0
  155. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/model_pipeline_training.py +0 -0
  156. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/refine/__main__.py +0 -0
  157. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run/__init__.py +0 -0
  158. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run/__main__.py +0 -0
  159. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/README.md +0 -0
  160. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/__init__.py +0 -0
  161. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/__main__.py +0 -0
  162. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/conversation_store.py +0 -0
  163. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/jwt_manager.py +0 -0
  164. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/mcp_specific.py +0 -0
  165. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/redoc_2_standalone_html.py +0 -0
  166. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/turns.py +0 -0
  167. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/run_fastapi_mcp/utils.py +0 -0
  168. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/session_state_store.py +0 -0
  169. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/train/__init__.py +0 -0
  170. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/train/generate_synthetic.py +0 -0
  171. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/turn.py +0 -0
  172. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/user_message_queues.py +0 -0
  173. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/__init__.py +0 -0
  174. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/chat_adapter.py +0 -0
  175. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/context_utils.py +0 -0
  176. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/dspy_cache_utils.py +0 -0
  177. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/dspy_logger.py +0 -0
  178. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/dspy_utils.py +0 -0
  179. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/env.py +0 -0
  180. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/fuzzy_match.py +0 -0
  181. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/generate_param_examples.py +0 -0
  182. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/logging.py +0 -0
  183. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/parameterize_func_decorator.py +0 -0
  184. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/pydantic_model_2_dspy_signature_class.py +0 -0
  185. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/python_utils.py +0 -0
  186. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/react.py +0 -0
  187. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/signatures.py +0 -0
  188. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/utils/startup_progress.py +0 -0
  189. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/workflow.py +0 -0
  190. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/workflow_execution_context.py +0 -0
  191. {fastworkflow-2.22.0 → fastworkflow-2.22.3}/fastworkflow/workflow_inheritance_model.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastworkflow
3
- Version: 2.22.0
3
+ Version: 2.22.3
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
@@ -32,6 +32,7 @@ Requires-Dist: prompt_toolkit (>=3.0.43,<4.0.0)
32
32
  Requires-Dist: pyarrow (>=23.0.1)
33
33
  Requires-Dist: pyasn1 (>=0.6.3)
34
34
  Requires-Dist: pydantic (>=2.9.2,<3.0.0)
35
+ Requires-Dist: pydantic-settings (>=2.14.2) ; extra == "server" or extra == "fastapi"
35
36
  Requires-Dist: pygments (>=2.20.0)
36
37
  Requires-Dist: pyjwt[crypto] (>=2.13.0) ; extra == "server" or extra == "fastapi"
37
38
  Requires-Dist: python-dotenv (>=1.2.2,<2.0.0)
@@ -1,4 +1,5 @@
1
1
  import contextlib
2
+ import hashlib
2
3
  import os
3
4
  from typing import Optional
4
5
  from pathlib import Path
@@ -121,6 +122,9 @@ class CommandDirectory(BaseModel):
121
122
  core_command_names: list[str] = Field(default_factory=list)
122
123
  # Mapping of context name to its metadata containing callback class module information
123
124
  map_context_2_metadata: dict[str, "ContextMetadata"] = Field(default_factory=dict)
125
+ # Fingerprint of the command sources this snapshot was built from. Used to
126
+ # invalidate the persisted cache when commands are added/removed/renamed/edited.
127
+ source_fingerprint: Optional[str] = None
124
128
 
125
129
  def register_command_metadata(self, command_name: str, metadata: CommandMetadata):
126
130
  if not (command_name and metadata):
@@ -165,6 +169,9 @@ class CommandDirectory(BaseModel):
165
169
 
166
170
  def save(self):
167
171
  commandroutinginfo_folderpath = CommandDirectory.get_commandinfo_folderpath(self.workflow_folderpath)
172
+ # Stamp the current source fingerprint so the persisted snapshot can be
173
+ # validated (and invalidated) against the live _commands tree on reload.
174
+ self.source_fingerprint = compute_commands_source_fingerprint(self.workflow_folderpath)
168
175
  with open(Path(commandroutinginfo_folderpath) / "command_directory.json", "w") as f:
169
176
  f.write(self.model_dump_json(indent=4))
170
177
 
@@ -593,16 +600,71 @@ def _lazy_hydrate_metadata(module_path: str, metadata: CommandMetadata, director
593
600
  module,
594
601
  )
595
602
 
603
+ # Files (beyond *.py) that the command/routing snapshots derive from. Changes
604
+ # to these must also invalidate the persisted caches.
605
+ _CONTEXT_MODEL_BASENAMES = ("context_inheritance_model.json",)
606
+
607
+
608
+ def _command_source_roots(workflow_folderpath: str) -> list[Path]:
609
+ """Return every `_commands` root that contributes to this workflow.
610
+
611
+ This includes the workflow's own `_commands` plus any base-workflow
612
+ `_commands` declared via `workflow_inheritance_model.json`. Base resolution
613
+ is best-effort: if it fails we still fingerprint the local sources so the
614
+ cache never silently goes stale.
615
+ """
616
+ roots: list[Path] = []
617
+ with contextlib.suppress(Exception):
618
+ inheritance_model = WorkflowInheritanceModel.load(workflow_folderpath)
619
+ roots.extend(
620
+ Path(base_path) / "_commands"
621
+ for base_path in inheritance_model.resolve_base_paths(workflow_folderpath)
622
+ )
623
+ roots.append(Path(workflow_folderpath) / "_commands")
624
+ return roots
625
+
626
+
627
+ def compute_commands_source_fingerprint(workflow_folderpath: str) -> str:
628
+ """Fingerprint the command sources a snapshot is derived from.
629
+
630
+ The fingerprint is a hash over the *set* of source files and their
631
+ `(size, mtime_ns)`. Unlike a "newest mtime" comparison, this detects
632
+ additions, deletions, renames, and edits uniformly, which is required to
633
+ safely invalidate `command_directory.json` and `routing_definition.json`.
634
+ """
635
+ workflow_folderpath = str(Path(workflow_folderpath).resolve())
636
+ entries: list[tuple[str, int, int]] = []
637
+
638
+ for root in _command_source_roots(workflow_folderpath):
639
+ if not root.is_dir():
640
+ continue
641
+ for p in root.rglob("*"):
642
+ if not p.is_file():
643
+ continue
644
+ if p.suffix == ".py" or p.name in _CONTEXT_MODEL_BASENAMES:
645
+ st = p.stat()
646
+ entries.append((str(p), st.st_size, st.st_mtime_ns))
647
+
648
+ # Routing also depends on the hierarchy model at the workflow root.
649
+ hierarchy = Path(workflow_folderpath) / "context_hierarchy_model.json"
650
+ if hierarchy.is_file():
651
+ st = hierarchy.stat()
652
+ entries.append((str(hierarchy), st.st_size, st.st_mtime_ns))
653
+
654
+ return hashlib.sha256(repr(sorted(entries)).encode("utf-8")).hexdigest()
655
+
656
+
596
657
  @lru_cache(maxsize=32)
597
658
  def get_cached_command_directory(workflow_folderpath: str) -> CommandDirectory:
598
659
  """Return a cached CommandDirectory, rebuilding only when sources change.
599
660
 
600
661
  The cache key is the *resolved* workflow path so that duplicate relative
601
- paths share the same entry. We compare the modification time of the
602
- persisted `command_directory.json` file against the most recent `.py`
603
- timestamp in the `_commands` tree. When the cache is fresh we deserialize
604
- the JSON directly; otherwise we rebuild via `CommandDirectory.load()` and
605
- persist the new snapshot.
662
+ paths share the same entry. We validate the persisted `command_directory.json`
663
+ against a fingerprint of the live `_commands` tree (see
664
+ `compute_commands_source_fingerprint`). When the fingerprint matches we
665
+ deserialize the JSON directly; otherwise we rebuild via
666
+ `CommandDirectory.load()` and persist the new snapshot. The fingerprint is
667
+ deletion- and rename-aware, unlike a plain mtime comparison.
606
668
  """
607
669
 
608
670
  workflow_folderpath = str(Path(workflow_folderpath).resolve())
@@ -610,18 +672,16 @@ def get_cached_command_directory(workflow_folderpath: str) -> CommandDirectory:
610
672
  cache_folder = Path(CommandDirectory.get_commandinfo_folderpath(workflow_folderpath))
611
673
  cache_file = cache_folder / "command_directory.json"
612
674
 
613
- commands_root = Path(workflow_folderpath) / "_commands"
614
- if commands_root.exists():
615
- # Use a generator expression with a default to handle empty directories
616
- latest_src_mtime = max((p.stat().st_mtime for p in commands_root.rglob("*.py")), default=0.0)
617
- else:
618
- latest_src_mtime = 0.0
675
+ current_fingerprint = compute_commands_source_fingerprint(workflow_folderpath)
619
676
 
620
- # Fast-path: load JSON if it is newer than any source file
621
- if cache_file.exists() and cache_file.stat().st_mtime > latest_src_mtime:
622
- return CommandDirectory.model_validate_json(cache_file.read_text())
623
-
624
- # (Re)build and persist
677
+ # Fast-path: load JSON if its stamped fingerprint matches the live sources
678
+ if cache_file.exists():
679
+ with contextlib.suppress(Exception):
680
+ cached = CommandDirectory.model_validate_json(cache_file.read_text())
681
+ if cached.source_fingerprint == current_fingerprint:
682
+ return cached
683
+
684
+ # (Re)build and persist (save() re-stamps the fingerprint)
625
685
  directory = CommandDirectory.load(workflow_folderpath)
626
686
  directory.save()
627
687
  return directory
@@ -23,7 +23,12 @@ from typing import Any, Dict, Optional, Set, Type, ClassVar
23
23
  from pydantic import BaseModel, ConfigDict
24
24
 
25
25
  from fastworkflow import ModuleType
26
- from fastworkflow.command_directory import CommandDirectory, UtteranceMetadata, get_cached_command_directory
26
+ from fastworkflow.command_directory import (
27
+ CommandDirectory,
28
+ UtteranceMetadata,
29
+ compute_commands_source_fingerprint,
30
+ get_cached_command_directory,
31
+ )
27
32
  from fastworkflow.command_context_model import CommandContextModel
28
33
  from fastworkflow.utils import python_utils
29
34
  from fastworkflow.utils.logging import logger
@@ -192,7 +197,12 @@ class RoutingDefinition(BaseModel):
192
197
  save_dict['command_directory_map'] = {k: list(v) for k, v in save_dict['command_directory_map'].items()}
193
198
  if 'routing_definition_map' in save_dict:
194
199
  save_dict['routing_definition_map'] = {k: list(v) for k, v in save_dict['routing_definition_map'].items()}
195
-
200
+
201
+ # Stamp the source fingerprint so the persisted routing definition can be
202
+ # invalidated when commands/contexts change. Unlike command_directory.json,
203
+ # this file previously had no staleness check at all.
204
+ save_dict['source_fingerprint'] = compute_commands_source_fingerprint(self.workflow_folderpath)
205
+
196
206
  with open(save_path, "w", encoding="utf-8") as f:
197
207
  json.dump(save_dict, f, indent=4)
198
208
 
@@ -348,10 +358,20 @@ class RoutingRegistry:
348
358
  if workflow_folderpath in cls._definitions:
349
359
  return cls._definitions[workflow_folderpath]
350
360
 
351
- # Attempt to load; if missing, build and save
352
- try:
353
- definition = RoutingDefinition.load(workflow_folderpath)
354
- except Exception:
361
+ # Attempt to load the persisted definition, but only trust it when its
362
+ # stamped source fingerprint still matches the live _commands tree.
363
+ # This is the staleness check the persisted routing definition
364
+ # previously lacked: without it, adding/removing/renaming a command
365
+ # left routing_definition.json pointing at the old command set until
366
+ # it was manually deleted.
367
+ definition = None
368
+ if cls._persisted_definition_is_fresh(workflow_folderpath):
369
+ try:
370
+ definition = RoutingDefinition.load(workflow_folderpath)
371
+ except Exception:
372
+ definition = None
373
+
374
+ if definition is None:
355
375
  definition = RoutingDefinition.build(workflow_folderpath)
356
376
  definition.save()
357
377
  cls._definitions[workflow_folderpath] = definition
@@ -361,6 +381,31 @@ class RoutingRegistry:
361
381
  cls._definitions[workflow_folderpath] = RoutingDefinition.build(workflow_folderpath)
362
382
  return cls._definitions[workflow_folderpath]
363
383
 
384
+ @staticmethod
385
+ def _persisted_definition_is_fresh(workflow_folderpath: str) -> bool:
386
+ """Return True if routing_definition.json exists and its stamped
387
+ source fingerprint matches the current _commands tree.
388
+
389
+ A missing file, unreadable JSON, missing/legacy fingerprint, or a
390
+ fingerprint mismatch all count as *not fresh*, forcing a rebuild.
391
+ """
392
+ load_path = (
393
+ f"{CommandDirectory.get_commandinfo_folderpath(workflow_folderpath)}"
394
+ f"/routing_definition.json"
395
+ )
396
+ if not os.path.isfile(load_path):
397
+ return False
398
+ try:
399
+ with open(load_path, "r", encoding="utf-8") as f:
400
+ data = json.load(f)
401
+ except (OSError, json.JSONDecodeError):
402
+ return False
403
+
404
+ if stored_fingerprint := data.get("source_fingerprint"):
405
+ return stored_fingerprint == compute_commands_source_fingerprint(workflow_folderpath)
406
+ else:
407
+ return False
408
+
364
409
  @classmethod
365
410
  def clear_registry(cls):
366
411
  """Clears the registry. Useful for testing."""
@@ -1,4 +1,5 @@
1
1
  import argparse
2
+ import contextlib
2
3
  import os
3
4
  import json
4
5
  import shutil
@@ -11,7 +12,7 @@ import fastworkflow
11
12
  from fastworkflow.utils.logging import logger
12
13
  from fastworkflow.utils import python_utils
13
14
  from fastworkflow import ModuleType
14
- from fastworkflow.model_pipeline_training import train, get_route_layer_filepath_model
15
+ from fastworkflow.model_pipeline_training import train, get_route_layer_filepath_model, GLOBAL_CONTEXT_FOLDER
15
16
  from fastworkflow.utils.generate_param_examples import generate_dspy_examples
16
17
  from fastworkflow.command_directory import CommandDirectory, get_cached_command_directory
17
18
  from fastworkflow.command_routing import RoutingDefinition, RoutingRegistry
@@ -81,6 +82,12 @@ def train_workflow(workflow_path: str):
81
82
  train(workflow)
82
83
  workflow.close()
83
84
 
85
+ # Only after training has successfully (re)generated artifacts do we prune
86
+ # leftovers from commands/contexts that no longer exist. Running this *after*
87
+ # the writes (rather than wiping up-front) means a failed train leaves the
88
+ # previous, complete ___command_info intact and runnable.
89
+ _prune_stale_artifacts(workflow_path)
90
+
84
91
  def _generate_dspy_examples_helper(workflow):
85
92
  json_path=get_route_layer_filepath_model(workflow.folderpath,"command_directory.json")
86
93
  # json_path = "./examples/sample_workflow/___command_info/command_directory.json"
@@ -123,6 +130,56 @@ def _generate_dspy_examples_helper(workflow):
123
130
  else:
124
131
  None
125
132
 
133
+ def _prune_stale_artifacts(workflow_path: str):
134
+ """Remove orphaned per-command and per-context training artifacts.
135
+
136
+ An artifact is "orphaned" only when the command or context it belongs to no
137
+ longer exists in the freshly built routing definition / command directory.
138
+ This is intentionally conservative: it never touches the JSON snapshots
139
+ themselves, and it never removes a model folder whose context is still known
140
+ (so checked-in / still-valid models such as ErrorCorrection are preserved).
141
+
142
+ Because orphans are looked up by name/context at run time, they are harmless;
143
+ this is purely a cleanliness pass and is safe to run after a successful train.
144
+ """
145
+ info_dir = os.path.join(workflow_path, "___command_info")
146
+ if not os.path.isdir(info_dir):
147
+ return
148
+
149
+ # Expected per-command DSPy artifacts: one per command that has parameters.
150
+ cmd_dir_json = os.path.join(info_dir, "command_directory.json")
151
+ expected_param_files: set[str] = set()
152
+ if os.path.isfile(cmd_dir_json):
153
+ commands = _get_commands_with_parameters(cmd_dir_json)
154
+ expected_param_files = {f"{name}_param_labeled.json" for name in commands}
155
+
156
+ # Expected per-context model folders: every context known to routing, with
157
+ # "*" mapped to the global folder. Folders for unknown contexts are orphans.
158
+ crd = RoutingRegistry.get_definition(workflow_path)
159
+ expected_ctx_folders = {GLOBAL_CONTEXT_FOLDER}
160
+ for ctx_name in crd.contexts.keys():
161
+ expected_ctx_folders.add(GLOBAL_CONTEXT_FOLDER if ctx_name == "*" else ctx_name)
162
+
163
+ for entry in os.listdir(info_dir):
164
+ full_path = os.path.join(info_dir, entry)
165
+ if (
166
+ entry.endswith("_param_labeled.json")
167
+ and os.path.isfile(full_path)
168
+ and entry not in expected_param_files
169
+ ):
170
+ with contextlib.suppress(OSError):
171
+ os.remove(full_path)
172
+ logger.info(f"Pruned orphaned param artifact: {full_path}")
173
+ elif (
174
+ os.path.isdir(full_path)
175
+ and os.path.isfile(os.path.join(full_path, "threshold.json"))
176
+ and entry not in expected_ctx_folders
177
+ ):
178
+ with contextlib.suppress(OSError):
179
+ shutil.rmtree(full_path)
180
+ logger.info(f"Pruned orphaned context model folder: {full_path}")
181
+
182
+
126
183
  def _get_commands_with_parameters(json_path):
127
184
  """
128
185
  Parse command_directory.json file and create a mapping between command names
@@ -370,6 +370,12 @@ def _ask_user_tool(clarification_request: str, chat_session_obj: fastworkflow.Ch
370
370
  )
371
371
  if output_queue is not None:
372
372
  output_queue.put(command_output)
373
+ # Preserve the transport contract: the output must be visible before the
374
+ # trace sentinel releases the CLI to read it. In v3.0 the queued payload
375
+ # becomes a partial TurnOutput, but the pairing and ordering stay the same.
376
+ trace_queue = chat_session_obj.command_trace_queue
377
+ if trace_queue is not None:
378
+ trace_queue.put(None)
373
379
 
374
380
  # Topology A: append the unanswered ask_user entry before blocking.
375
381
  # (Topology B appends it inside the WEC core at AskUserSuspend time.)
@@ -9,7 +9,7 @@ repository = "https://github.com/radiantlogicinc/fastworkflow"
9
9
 
10
10
  [tool.poetry]
11
11
  name = "fastworkflow"
12
- version = "2.22.0"
12
+ version = "2.22.3"
13
13
  description = "A framework for rapidly building large-scale, deterministic, interactive workflows with a fault-tolerant, conversational UX"
14
14
  authors = ["Dhar Rawal <drawal@radiantlogic.com>"]
15
15
  license = "Apache-2.0"
@@ -69,6 +69,7 @@ fastapi-mcp = {version = "^0.4.0", optional = true}
69
69
  pyjwt = {extras = ["crypto"], version = ">=2.13.0", optional = true} # Replaces python-jose (CVE-2024-23342); >=2.13.0 fixes alg allow-list bypass (PYSEC-2026-176) + DoS (PYSEC-2026-175/177/178/179)
70
70
  python-multipart = {version = ">=0.0.31", optional = true} # CVE-2026-40347, CVE-2026-42561 (multipart parsing DoS) + CVE-2026-53540 (negative Content-Length unbounded read, fixed 0.0.31). Only pulled by the `server` extra (FastAPI form parsing); not needed by the client/core install.
71
71
  starlette = {version = ">=1.3.1", optional = true} # CVE-2025-62727, CVE-2025-54121 (Range header DoS) + CVE-2026-54282 (request.url host spoof, 1.3.0) + CVE-2026-54283 (urlencoded form DoS, 1.3.1). Pulled transitively by fastapi (requires starlette>=0.46.0) in the `server` extra.
72
+ pydantic-settings = {version = ">=2.14.2", optional = true} # GHSA-4xgf-cpjx-pc3j (NestedSecretsSettingsSource follows symlinks outside secrets_dir -> local file read + secrets_dir_max_size bypass, fixed 2.14.2). Pulled transitively by mcp/fastapi-mcp in the `server` extra.
72
73
  datasets = {version = "^4.0.0", optional = true}
73
74
 
74
75
  # Security floor constraints for transitive dependencies of the CORE (client) install.
@@ -117,6 +118,6 @@ training = ["datasets"]
117
118
  # Full FastAPI-MCP server feature set (`fastworkflow run_fastapi_mcp`) with the
118
119
  # security-patched server deps. `litellm_proxy/` client routing does NOT require
119
120
  # this extra (plain litellm handles it via api_base).
120
- server = ["uvicorn", "fastapi", "fastapi-mcp", "pyjwt", "python-multipart", "starlette"]
121
+ server = ["uvicorn", "fastapi", "fastapi-mcp", "pyjwt", "python-multipart", "starlette", "pydantic-settings"]
121
122
  # Backward-compatible alias for the pre-2.18.2 extra name.
122
- fastapi = ["uvicorn", "fastapi", "fastapi-mcp", "pyjwt", "python-multipart", "starlette"]
123
+ fastapi = ["uvicorn", "fastapi", "fastapi-mcp", "pyjwt", "python-multipart", "starlette", "pydantic-settings"]
File without changes
File without changes