fastworkflow 2.17.7__tar.gz → 2.17.9__tar.gz

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

Potentially problematic release.


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

Files changed (184) hide show
  1. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/PKG-INFO +1 -1
  2. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/parameter_extraction.py +81 -5
  3. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/chat_session.py +14 -3
  4. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/command_metadata_api.py +50 -0
  5. fastworkflow-2.17.9/fastworkflow/intent_clarification_agent.py +132 -0
  6. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/README.md +26 -0
  7. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/__main__.py +2 -1
  8. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/jwt_manager.py +8 -0
  9. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/utils.py +29 -3
  10. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/train/__main__.py +1 -1
  11. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/react.py +13 -1
  12. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/signatures.py +49 -31
  13. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/workflow_agent.py +78 -4
  14. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/pyproject.toml +1 -1
  15. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/LICENSE +0 -0
  16. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/README.md +0 -0
  17. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/.DS_Store +0 -0
  18. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/__init__.py +0 -0
  19. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_commands/.gitkeep +0 -0
  20. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/__init__.py +0 -0
  21. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/__init__.py +0 -0
  22. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/abort.py +0 -0
  23. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/you_misunderstood.py +0 -0
  24. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/go_up.py +0 -0
  25. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/reset_context.py +0 -0
  26. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_can_i_do.py +0 -0
  27. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_is_current_context.py +0 -0
  28. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/__init__.py +0 -0
  29. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/wildcard.py +0 -0
  30. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/command_context_model.json +0 -0
  31. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/intent_detection.py +0 -0
  32. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/__main__.py +0 -0
  33. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/ast_class_extractor.py +0 -0
  34. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/class_analysis_structures.py +0 -0
  35. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/cli_specification.md +0 -0
  36. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/command_dependency_resolver.py +0 -0
  37. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/command_file_generator.py +0 -0
  38. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/command_file_template.py +0 -0
  39. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/command_import_utils.py +0 -0
  40. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/command_stub_generator.py +0 -0
  41. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/context_folder_generator.py +0 -0
  42. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/context_model_generator.py +0 -0
  43. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/dependency_manager.py +0 -0
  44. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/dir_scanner.py +0 -0
  45. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/documentation_generator.py +0 -0
  46. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/genai_postprocessor.py +0 -0
  47. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/inheritance_block_regenerator.py +0 -0
  48. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/libcst_transformers.py +0 -0
  49. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/navigator_stub_generator.py +0 -0
  50. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/pydantic_model_generator.py +0 -0
  51. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/build/utterance_generator.py +0 -0
  52. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/cache_matching.py +0 -0
  53. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/cli.py +0 -0
  54. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/command_context_model.py +0 -0
  55. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/command_directory.py +0 -0
  56. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/command_executor.py +0 -0
  57. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/command_interfaces.py +0 -0
  58. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/command_routing.py +0 -0
  59. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/docs/context_modules_prd.txt +0 -0
  60. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/README.md +0 -0
  61. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/_commands/WorkItem/get_status.py +0 -0
  62. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/_commands/generate_report.py +0 -0
  63. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/_commands/startup.py +0 -0
  64. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/simple_workflow_template.json +0 -0
  65. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/workflow_inheritance_model.json +0 -0
  66. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/fastworkflow.env +0 -0
  67. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/fastworkflow.passwords.env +0 -0
  68. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/hello_world/_commands/README.md +0 -0
  69. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/hello_world/_commands/add_two_numbers.py +0 -0
  70. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/hello_world/_commands/context_inheritance_model.json +0 -0
  71. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/hello_world/application/add_two_numbers.py +0 -0
  72. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_1/_commands/context_inheritance_model.json +0 -0
  73. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_1/_commands/send_message.py +0 -0
  74. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_1/application/send_message.py +0 -0
  75. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_2/_commands/User/send_message.py +0 -0
  76. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_2/_commands/context_inheritance_model.json +0 -0
  77. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_2/_commands/startup.py +0 -0
  78. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_2/application/user.py +0 -0
  79. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/_commands/PremiumUser/send_priority_message.py +0 -0
  80. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/_commands/User/send_message.py +0 -0
  81. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/_commands/context_inheritance_model.json +0 -0
  82. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/_commands/initialize_user.py +0 -0
  83. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/application/user.py +0 -0
  84. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/_ChatRoom.py +0 -0
  85. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/add_user.py +0 -0
  86. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/broadcast_message.py +0 -0
  87. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/get_current_user.py +0 -0
  88. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/list_users.py +0 -0
  89. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/set_current_user.py +0 -0
  90. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/_PremiumUser.py +0 -0
  91. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/send_priority_message.py +0 -0
  92. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/User/_User.py +0 -0
  93. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/User/send_message.py +0 -0
  94. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/context_inheritance_model.json +0 -0
  95. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/set_root_context.py +0 -0
  96. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/application/chatroom.py +0 -0
  97. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/application/user.py +0 -0
  98. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/context_hierarchy_model.json +0 -0
  99. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/startup_action.json +0 -0
  100. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/calculate.py +0 -0
  101. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/cancel_pending_order.py +0 -0
  102. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/exchange_delivered_order_items.py +0 -0
  103. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_email.py +0 -0
  104. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_name_zip.py +0 -0
  105. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/get_order_details.py +0 -0
  106. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/get_product_details.py +0 -0
  107. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/get_user_details.py +0 -0
  108. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/list_all_product_types.py +0 -0
  109. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_address.py +0 -0
  110. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_items.py +0 -0
  111. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_payment.py +0 -0
  112. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/modify_user_address.py +0 -0
  113. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/return_delivered_order_items.py +0 -0
  114. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/transfer_to_human_agents.py +0 -0
  115. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/context_inheritance_model.json +0 -0
  116. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/retail_data/__init__.py +0 -0
  117. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/retail_data/orders.json +0 -0
  118. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/retail_data/products.json +0 -0
  119. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/retail_data/users.json +0 -0
  120. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/calculate.py +0 -0
  121. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/cancel_pending_order.py +0 -0
  122. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/exchange_delivered_order_items.py +0 -0
  123. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_email.py +0 -0
  124. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_name_zip.py +0 -0
  125. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/get_order_details.py +0 -0
  126. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/get_product_details.py +0 -0
  127. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/get_user_details.py +0 -0
  128. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/list_all_product_types.py +0 -0
  129. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_address.py +0 -0
  130. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_items.py +0 -0
  131. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_payment.py +0 -0
  132. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/modify_user_address.py +0 -0
  133. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/return_delivered_order_items.py +0 -0
  134. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/think.py +0 -0
  135. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/tool.py +0 -0
  136. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/transfer_to_human_agents.py +0 -0
  137. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/workflow_description.txt +0 -0
  138. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/__init__.py +0 -0
  139. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/_WorkItem.py +0 -0
  140. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/add_child_workitem.py +0 -0
  141. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/get_status.py +0 -0
  142. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/go_to_workitem.py +0 -0
  143. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/mark_as_complete.py +0 -0
  144. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_first_child_workitem.py +0 -0
  145. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_last_child_workitem.py +0 -0
  146. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_next_workitem.py +0 -0
  147. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_previous_workitem.py +0 -0
  148. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_all_child_workitems.py +0 -0
  149. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_child_workitem.py +0 -0
  150. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/show_schema.py +0 -0
  151. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/startup.py +0 -0
  152. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/application/__init__.py +0 -0
  153. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/application/workitem.py +0 -0
  154. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/simple_workflow_template.json +0 -0
  155. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/startup_action.json +0 -0
  156. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/mcp_server.py +0 -0
  157. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/model_pipeline_training.py +0 -0
  158. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/refine/__main__.py +0 -0
  159. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run/__init__.py +0 -0
  160. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run/__main__.py +0 -0
  161. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/__init__.py +0 -0
  162. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/conversation_store.py +0 -0
  163. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/mcp_specific.py +0 -0
  164. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/redoc_2_standalone_html.py +0 -0
  165. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/train/__init__.py +0 -0
  166. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/train/generate_synthetic.py +0 -0
  167. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/user_message_queues.py +0 -0
  168. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/__init__.py +0 -0
  169. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/chat_adapter.py +0 -0
  170. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/command_dependency_graph.py +0 -0
  171. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/context_utils.py +0 -0
  172. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/dspy_cache_utils.py +0 -0
  173. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/dspy_logger.py +0 -0
  174. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/dspy_utils.py +0 -0
  175. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/env.py +0 -0
  176. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/fuzzy_match.py +0 -0
  177. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/generate_param_examples.py +0 -0
  178. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/logging.py +0 -0
  179. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/parameterize_func_decorator.py +0 -0
  180. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/pydantic_model_2_dspy_signature_class.py +0 -0
  181. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/python_utils.py +0 -0
  182. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/utils/startup_progress.py +0 -0
  183. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/workflow.py +0 -0
  184. {fastworkflow-2.17.7 → fastworkflow-2.17.9}/fastworkflow/workflow_inheritance_model.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastworkflow
3
- Version: 2.17.7
3
+ Version: 2.17.9
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
@@ -1,8 +1,10 @@
1
1
  import contextlib
2
2
  import sys
3
+ import re
3
4
  from typing import Dict, List, Optional
4
5
 
5
6
  from pydantic import BaseModel
7
+ from pydantic_core import PydanticUndefined
6
8
 
7
9
  import fastworkflow
8
10
  from fastworkflow.utils.logging import logger
@@ -59,11 +61,29 @@ class ParameterExtraction:
59
61
  if stored_params:
60
62
  new_params = self._extract_and_merge_missing_parameters(stored_params, self.command)
61
63
  else:
62
- # Otherwise use the LLM-based extraction
63
- new_params = input_for_param_extraction.extract_parameters(
64
- command_parameters_class,
65
- self.command_name,
66
- app_workflow_folderpath)
64
+ # Check if we're in agentic mode (not assistant mode command)
65
+ is_agentic_mode = (
66
+ "is_assistant_mode_command" not in self.cme_workflow.context
67
+ and "run_as_agent" in self.app_workflow.context
68
+ and self.app_workflow.context["run_as_agent"]
69
+ )
70
+
71
+ if is_agentic_mode:
72
+ # Try regex-based extraction first in agentic mode
73
+ new_params = self._extract_parameters_from_xml(self.command, command_parameters_class)
74
+
75
+ # If regex extraction fails, fall back to LLM-based extraction
76
+ if new_params is None:
77
+ new_params = input_for_param_extraction.extract_parameters(
78
+ command_parameters_class,
79
+ self.command_name,
80
+ app_workflow_folderpath)
81
+ else:
82
+ # Use LLM-based extraction for assistant mode
83
+ new_params = input_for_param_extraction.extract_parameters(
84
+ command_parameters_class,
85
+ self.command_name,
86
+ app_workflow_folderpath)
67
87
 
68
88
  is_valid, error_msg, suggestions, missing_invalid_fields = \
69
89
  input_for_param_extraction.validate_parameters(
@@ -272,6 +292,62 @@ class ParameterExtraction:
272
292
  # Construct model without validation
273
293
  return default_params.__class__.model_construct(**params_data)
274
294
 
295
+ @staticmethod
296
+ def _extract_parameters_from_xml(command: str, command_parameters_class: type[BaseModel]) -> Optional[BaseModel]:
297
+ """
298
+ Extract parameters from XML-formatted command using regex.
299
+
300
+ Returns:
301
+ BaseModel instance with extracted parameters, or None if parsing fails
302
+ """
303
+ field_names = list(command_parameters_class.model_fields.keys())
304
+
305
+ # If no parameters are defined, return empty model immediately
306
+ if not field_names:
307
+ return command_parameters_class.model_construct()
308
+
309
+ extracted_data = {}
310
+
311
+ # Try to extract each parameter using XML tags
312
+ for field_name in field_names:
313
+ # Look for <field_name>value</field_name> pattern
314
+ pattern = rf'<{re.escape(field_name)}>(.+?)</{re.escape(field_name)}>'
315
+ if match := re.search(pattern, command, re.DOTALL):
316
+ parameter_value = match[1].strip()
317
+ extracted_data[field_name] = parameter_value
318
+
319
+ # Check if we extracted values for ALL fields (safest criteria for LLM fallback)
320
+ all_fields_extracted = len(extracted_data) == len(field_names)
321
+
322
+ # Check if agent used example values
323
+ if all_fields_extracted:
324
+ for field_name, extracted_value in extracted_data.items():
325
+ field_info = command_parameters_class.model_fields[field_name]
326
+ examples = getattr(field_info, "examples", None)
327
+ if examples and extracted_value in examples:
328
+ all_fields_extracted = False
329
+ break
330
+
331
+ if all_fields_extracted:
332
+ # Initialize all fields with their default values (if they exist) or None
333
+ params_data = {}
334
+ for field_name in field_names:
335
+ field_info = command_parameters_class.model_fields[field_name]
336
+ if field_info.default is not PydanticUndefined:
337
+ params_data[field_name] = field_info.default
338
+ elif field_info.default_factory is not None:
339
+ params_data[field_name] = field_info.default_factory()
340
+ else:
341
+ params_data[field_name] = None
342
+
343
+ # Update with extracted values
344
+ params_data |= extracted_data
345
+
346
+ # Construct model without validation
347
+ return command_parameters_class.model_construct(**params_data)
348
+
349
+ return None
350
+
275
351
  @staticmethod
276
352
  def _extract_and_merge_missing_parameters(stored_params: BaseModel, command: str):
277
353
  """
@@ -133,7 +133,8 @@ class ChatSession:
133
133
 
134
134
  # Initialize agent-related attributes
135
135
  self._run_as_agent = run_as_agent
136
- self._workflow_tool_agent = None
136
+ self._workflow_tool_agent = None
137
+ self._intent_clarification_agent = None
137
138
 
138
139
  # Create the command metadata extraction workflow with a unique ID
139
140
  self._cme_workflow = fastworkflow.Workflow.create(
@@ -272,13 +273,23 @@ class ChatSession:
272
273
  self._current_workflow.context["run_as_agent"] = True
273
274
 
274
275
  # Initialize the workflow tool agent
275
- from fastworkflow.workflow_agent import initialize_workflow_tool_agent
276
+ from fastworkflow.workflow_agent import initialize_workflow_tool_agent
276
277
  self._workflow_tool_agent = initialize_workflow_tool_agent(self)
277
278
 
279
+ # Initialize the intent clarification agent
280
+ from fastworkflow.intent_clarification_agent import initialize_intent_clarification_agent
281
+ self._intent_clarification_agent = initialize_intent_clarification_agent(self)
282
+
278
283
  @property
279
284
  def workflow_tool_agent(self):
280
285
  """Get the workflow tool agent for agent mode."""
281
286
  return self._workflow_tool_agent
287
+
288
+ @property
289
+ def intent_clarification_agent(self):
290
+ """Get the intent clarification agent for agent mode."""
291
+ return self._intent_clarification_agent
292
+
282
293
  @property
283
294
  def cme_workflow(self) -> fastworkflow.Workflow:
284
295
  """Get the command metadata extraction workflow."""
@@ -647,7 +658,7 @@ class ChatSession:
647
658
  def _extract_conversation_summary(self,
648
659
  user_query: str, workflow_actions: list[dict[str, str]], final_agent_response: str) -> str:
649
660
  """
650
- Summarizes conversation based on original user query, workflow actions and agentt response.
661
+ Summarizes conversation based on original user query, workflow actions and agent response.
651
662
  Returns the conversation summary and the log entry
652
663
  """
653
664
  # Lets log everything to a file called action_log.jsonl, if it exists
@@ -613,6 +613,56 @@ class CommandMetadataAPI:
613
613
 
614
614
  return "\n".join(combined_lines)
615
615
 
616
+ @staticmethod
617
+ def get_suggested_commands_metadata(
618
+ subject_workflow_path: str,
619
+ cme_workflow_path: str,
620
+ active_context_name: str,
621
+ suggested_command_names: list[str],
622
+ for_agents: bool = False,
623
+ ) -> str:
624
+ """
625
+ Get metadata display text for ONLY the suggested commands.
626
+
627
+ Args:
628
+ subject_workflow_path: Path to the subject workflow
629
+ cme_workflow_path: Path to the CME workflow
630
+ active_context_name: Active context name
631
+ suggested_command_names: List of suggested command names (can be short names or qualified)
632
+ for_agents: Include agent-specific fields
633
+
634
+ Returns:
635
+ YAML-like formatted string with metadata for suggested commands only
636
+ """
637
+ if not suggested_command_names:
638
+ return "No suggested commands provided."
639
+
640
+ parts: list[str] = []
641
+ for suggested_cmd in suggested_command_names:
642
+ # Try to get metadata for this command
643
+ # The command name could be qualified (Context/command) or short (command)
644
+ if part := CommandMetadataAPI.get_command_display_text_for_command(
645
+ subject_workflow_path=subject_workflow_path,
646
+ cme_workflow_path=cme_workflow_path,
647
+ active_context_name=active_context_name,
648
+ qualified_command_name=suggested_cmd,
649
+ for_agents=for_agents,
650
+ ):
651
+ parts.append(part)
652
+
653
+ if not parts:
654
+ return "No metadata available for suggested commands."
655
+
656
+ # Combine all parts with header
657
+ combined_lines: list[str] = ["Suggested commands with metadata:"]
658
+ for idx, text in enumerate(parts):
659
+ lines = text.splitlines()
660
+ if idx > 0:
661
+ combined_lines.append("") # Blank line separator
662
+ combined_lines.extend(lines)
663
+
664
+ return "\n".join(combined_lines)
665
+
616
666
  @staticmethod
617
667
  def get_command_display_text_for_command(
618
668
  subject_workflow_path: str,
@@ -0,0 +1,132 @@
1
+ """
2
+ Intent detection error state agent module for fastWorkflow.
3
+ Specialized agent for handling intent detection errors.
4
+ """
5
+
6
+ import json
7
+ import dspy
8
+
9
+ import fastworkflow
10
+ from fastworkflow.utils.react import fastWorkflowReAct
11
+ from fastworkflow.command_metadata_api import CommandMetadataAPI
12
+
13
+
14
+ class IntentClarificationAgentSignature(dspy.Signature):
15
+ """
16
+ Handle intent detection errors by clarifying user intent.
17
+ You are provided with:
18
+ 1. The workflow agent's inputs and trajectory - showing what the agent has been trying to do
19
+ 2. Suggested commands metadata (for intent ambiguity) or empty (for intent misunderstanding - use show_available_commands tool)
20
+
21
+ Review the agent trajectory to understand the context and what led to this error.
22
+ If suggested_commands_metadata is provided, review it carefully to understand each command's purpose, parameters, and usage.
23
+ If suggested_commands_metadata is empty, use the show_available_commands tool to get the full list of available commands.
24
+ IMPORTANT: When clarifying intent, preserve ALL parameters from the original command.
25
+ Use available tools to resolve ambiguous or misunderstood commands. Use the ask_user tool ONLY as a last resort. Return the complete clarified command with the correct name and all original parameters.
26
+ """
27
+ original_command = dspy.InputField(desc="The original command with all parameters that caused the error.")
28
+ error_message = dspy.InputField(desc="The intent detection error message from the workflow.")
29
+ agent_inputs = dspy.InputField(desc="The original inputs to the workflow agent.")
30
+ agent_trajectory = dspy.InputField(desc="The workflow agent's trajectory showing all actions taken so far leading to this error.")
31
+ suggested_commands_metadata = dspy.InputField(desc="Metadata for suggested commands (for ambiguity clarification), or empty string (for misunderstanding - use show_available_commands tool instead).")
32
+ clarified_command = dspy.OutputField(desc="The complete command with correct command name AND all original parameters preserved.")
33
+
34
+
35
+ def _show_available_commands(chat_session: fastworkflow.ChatSession) -> str:
36
+ """
37
+ Show available commands to help resolve intent detection errors.
38
+
39
+ Args:
40
+ chat_session: The chat session instance
41
+
42
+ Returns:
43
+ List of available commands
44
+ """
45
+
46
+ current_workflow = chat_session.get_active_workflow()
47
+ return CommandMetadataAPI.get_command_display_text(
48
+ subject_workflow_path=current_workflow.folderpath,
49
+ cme_workflow_path=fastworkflow.get_internal_workflow_path("command_metadata_extraction"),
50
+ active_context_name=current_workflow.current_command_context_name,
51
+ )
52
+
53
+
54
+ def _ask_user_for_clarification(
55
+ clarification_request: str,
56
+ chat_session: fastworkflow.ChatSession
57
+ ) -> str:
58
+ """
59
+ Ask user for clarification when intent is unclear.
60
+
61
+ Args:
62
+ clarification_request: The question to ask the user
63
+ chat_session: The chat session instance
64
+
65
+ Returns:
66
+ User's response
67
+ """
68
+ command_output = fastworkflow.CommandOutput(
69
+ command_responses=[fastworkflow.CommandResponse(response=clarification_request)],
70
+ workflow_name=chat_session.get_active_workflow().folderpath.split('/')[-1]
71
+ )
72
+ chat_session.command_output_queue.put(command_output)
73
+
74
+ user_response = chat_session.user_message_queue.get()
75
+
76
+ # Log to action.jsonl (shared with main agent)
77
+ with open("action.jsonl", "a", encoding="utf-8") as f:
78
+ agent_user_dialog = {
79
+ "intent_clarification_agent": True,
80
+ "agent_query": clarification_request,
81
+ "user_response": user_response
82
+ }
83
+ f.write(json.dumps(agent_user_dialog, ensure_ascii=False) + "\n")
84
+
85
+ return user_response
86
+
87
+
88
+ def initialize_intent_clarification_agent(
89
+ chat_session: fastworkflow.ChatSession,
90
+ max_iters: int = 20
91
+ ):
92
+ """
93
+ Initialize a specialized agent for handling intent detection errors.
94
+ This agent has a limited tool set and shares traces with the main execution agent.
95
+
96
+ Args:
97
+ chat_session: The chat session instance
98
+ max_iters: Maximum iterations for the agent (default: 10)
99
+
100
+ Returns:
101
+ DSPy ReAct agent configured for intent detection error handling
102
+ """
103
+ if not chat_session:
104
+ raise ValueError("chat_session cannot be null")
105
+
106
+ def show_available_commands() -> str:
107
+ """
108
+ Show all available commands to help resolve intent ambiguity.
109
+ """
110
+ return _show_available_commands(chat_session)
111
+
112
+ def ask_user(clarification_request: str) -> str:
113
+ """
114
+ Ask the user for clarification when the intent is unclear.
115
+ Use this as a last resort when you cannot determine the correct command.
116
+
117
+ Args:
118
+ clarification_request: Clear question to ask the user
119
+ """
120
+ return _ask_user_for_clarification(clarification_request, chat_session)
121
+
122
+ # Limited tool set for intent detection errors
123
+ tools = [
124
+ show_available_commands,
125
+ ask_user,
126
+ ]
127
+
128
+ return fastWorkflowReAct(
129
+ IntentClarificationAgentSignature,
130
+ tools=tools,
131
+ max_iters=max_iters,
132
+ )
@@ -82,6 +82,32 @@ uvicorn services.run_fastapi.main:app --workflow_path /path/to/workflow --expect
82
82
  - Tokens without valid signatures are rejected
83
83
  - Recommended for production deployments in untrusted environments
84
84
 
85
+ ### Token Access in Workflow Context
86
+
87
+ JWT tokens are automatically passed to workflows via the `workflow_context` parameter as `http_bearer_token`. This allows workflows to access the bearer token for making authenticated API calls or forwarding authentication.
88
+
89
+ **Important notes:**
90
+ - The token is **only available to authenticated endpoints** (those using `get_session_and_ensure_runtime` dependency)
91
+ - The token is stored in the workflow context dictionary under the key `http_bearer_token`
92
+ - Token is **automatically updated** on every authenticated request, ensuring workflows always have the current valid token
93
+ - Token expiration is **automatically verified** by `verify_token()` in both secure mode (`--expect_encrypted_jwt` flag) and trusted network mode
94
+ - In secure mode: Full cryptographic signature verification + expiration checking
95
+ - In trusted network mode: Expiration checking is performed (signature verification disabled)
96
+ - Tokens should be treated as sensitive data and handled securely in workflows
97
+ - The `/initialize` endpoint is unauthenticated and does NOT provide a token to the workflow context; tokens are only available after calling `/initialize` and using the returned token in subsequent requests
98
+
99
+ **Example usage in workflow:**
100
+
101
+ ```python
102
+ # In workflow code
103
+ workflow_context = self._context # Gets the workflow_context
104
+ bearer_token = workflow_context.get('http_bearer_token')
105
+
106
+ # Use token for API calls
107
+ headers = {"Authorization": f"Bearer {bearer_token}"}
108
+ response = requests.get("https://api.example.com/data", headers=headers)
109
+ ```
110
+
85
111
  ## API Endpoints (REST)
86
112
 
87
113
  ### `POST /initialize`
@@ -126,7 +126,8 @@ async def get_session_and_ensure_runtime(
126
126
  workflow_path=ARGS.workflow_path,
127
127
  context=json.loads(ARGS.context) if ARGS.context else None,
128
128
  startup_command=ARGS.startup_command,
129
- startup_action=fastworkflow.Action(**json.loads(ARGS.startup_action)) if ARGS.startup_action else None
129
+ startup_action=fastworkflow.Action(**json.loads(ARGS.startup_action)) if ARGS.startup_action else None,
130
+ http_bearer_token=session.http_bearer_token
130
131
  )
131
132
 
132
133
  return session
@@ -269,6 +269,14 @@ def verify_token(token: str, expected_type: str = "access") -> dict:
269
269
  logger.warning(f"Token decoding failed: {e}")
270
270
  raise JWTError(f"Failed to decode token: {e}") from e
271
271
 
272
+ # Manually check expiration even in unverified mode
273
+ if exp_timestamp := payload.get("exp"):
274
+ import time
275
+ current_time = int(time.time())
276
+ if exp_timestamp < current_time:
277
+ logger.warning(f"Token expired: exp={exp_timestamp}, now={current_time}")
278
+ raise JWTError("Token has expired")
279
+
272
280
  # Validate token type for consistency (outside try-except to allow JWTError to propagate)
273
281
  if payload.get("type") != expected_type:
274
282
  raise JWTError(f"Invalid token type: expected {expected_type}, got {payload.get('type')}")
@@ -42,6 +42,7 @@ class SessionData(BaseModel):
42
42
  issued_at: int # Unix timestamp
43
43
  expires_at: int # Unix timestamp
44
44
  jti: str # JWT ID (unique token identifier)
45
+ http_bearer_token: Optional[str] = None # The actual JWT token string for workflow context access
45
46
 
46
47
 
47
48
  class InvokeRequest(BaseModel):
@@ -174,13 +175,14 @@ def get_session_from_jwt(
174
175
  try:
175
176
  payload = verify_token(token, expected_type="access")
176
177
 
177
- # Extract session data from payload
178
+ # Extract session data from payload, including the token for workflow context
178
179
  return SessionData(
179
180
  user_id=payload["sub"],
180
181
  token_type=payload["type"],
181
182
  issued_at=payload["iat"],
182
183
  expires_at=payload["exp"],
183
- jti=payload["jti"]
184
+ jti=payload["jti"],
185
+ http_bearer_token=token # Store the actual token for workflow access
184
186
  )
185
187
 
186
188
  except JWTError as e:
@@ -204,7 +206,8 @@ async def ensure_user_runtime_exists(
204
206
  context: Optional[dict] = None,
205
207
  startup_command: Optional[str] = None,
206
208
  startup_action: Optional['fastworkflow.Action'] = None,
207
- stream_format: str = "ndjson"
209
+ stream_format: str = "ndjson",
210
+ http_bearer_token: Optional[str] = None
208
211
  ) -> None:
209
212
  """
210
213
  Ensure a user runtime exists in the session manager. If not, create it.
@@ -220,6 +223,7 @@ async def ensure_user_runtime_exists(
220
223
  startup_command: Optional startup command
221
224
  startup_action: Optional startup action
222
225
  stream_format: Stream format preference ("ndjson" or "sse", default "ndjson")
226
+ http_bearer_token: Optional JWT token to update in workflow context
223
227
 
224
228
  Raises:
225
229
  HTTPException: If session creation fails
@@ -228,8 +232,30 @@ async def ensure_user_runtime_exists(
228
232
  existing_runtime = await session_manager.get_session(user_id)
229
233
  if existing_runtime:
230
234
  logger.debug(f"Session for user_id {user_id} already exists, skipping creation")
235
+
236
+ # Update the workflow's context with the current token if provided
237
+ if http_bearer_token and existing_runtime.chat_session:
238
+ active_workflow = existing_runtime.chat_session.get_active_workflow()
239
+ if active_workflow and active_workflow.context:
240
+ # Update the workflow's context with the current token
241
+ # Note: We mutate the dictionary in-place (no setter call), which means:
242
+ # 1. The change is immediate and visible to workflow code
243
+ # 2. The workflow is NOT marked dirty (won't persist to disk)
244
+ # 3. This is intentional for JWT tokens - we don't want to persist sensitive tokens
245
+ active_workflow.context['http_bearer_token'] = http_bearer_token
246
+ logger.debug(f"Updated http_bearer_token in workflow context for user_id {user_id}")
247
+
231
248
  return
232
249
 
250
+ # Prepare workflow context, ensuring http_bearer_token is available
251
+ if http_bearer_token:
252
+ if context:
253
+ # Add or replace http_bearer_token in the context
254
+ context['http_bearer_token'] = http_bearer_token
255
+ else:
256
+ # Initialize context with http_bearer_token
257
+ context = {'http_bearer_token': http_bearer_token}
258
+
233
259
  logger.info(f"Creating new session for user_id: {user_id}")
234
260
 
235
261
  # Resolve conversation store base folder from SPEEDDICT_FOLDERNAME/user_conversations
@@ -114,7 +114,7 @@ def _get_commands_with_parameters(json_path):
114
114
  command_directory = json.load(f)
115
115
 
116
116
  # Extract the command metadata
117
- commands_metadata = command_directory.get("map_commandkey_2_metadata", {})
117
+ commands_metadata = command_directory.get("map_command_2_metadata", {})
118
118
 
119
119
  # Initialize result dictionary
120
120
  commands_with_parameters = {}
@@ -2,6 +2,7 @@ import logging
2
2
  from typing import TYPE_CHECKING, Any, Callable, Literal
3
3
 
4
4
  from litellm import ContextWindowExceededError
5
+ from litellm import exceptions as litellm_exceptions
5
6
 
6
7
  import dspy
7
8
  from dspy.adapters.types.tool import Tool
@@ -41,6 +42,7 @@ class fastWorkflowReAct(Module):
41
42
  super().__init__()
42
43
  self.signature = signature = ensure_signature(signature)
43
44
  self.max_iters = max_iters
45
+ self.iteration_counter = 0
44
46
 
45
47
  tools = [t if isinstance(t, Tool) else Tool(t) for t in tools]
46
48
  tools = {tool.name: tool for tool in tools}
@@ -105,7 +107,8 @@ class fastWorkflowReAct(Module):
105
107
 
106
108
  trajectory = {}
107
109
  max_iters = input_args.pop("max_iters", self.max_iters)
108
- for idx in range(max_iters):
110
+ idx = 0
111
+ while True:
109
112
  try:
110
113
  pred = self._call_with_potential_trajectory_truncation(self.react, trajectory, **input_args)
111
114
  except ValueError as err:
@@ -126,6 +129,12 @@ class fastWorkflowReAct(Module):
126
129
  if pred.next_tool_name == "finish":
127
130
  break
128
131
 
132
+ idx += 1 # this is the counter for the index of the entire trajectory
133
+ self.iteration_counter += 1 # this counter just determines the number of times we run the react agent and it's reset everytime we call the user for clarification
134
+ if self.iteration_counter >= max_iters:
135
+ logger.warning("Max iterations reached")
136
+ break
137
+
129
138
  extract = self._call_with_potential_trajectory_truncation(self.extract, trajectory, **input_args)
130
139
  return dspy.Prediction(trajectory=trajectory, **extract)
131
140
 
@@ -161,6 +170,9 @@ class fastWorkflowReAct(Module):
161
170
  **input_args,
162
171
  trajectory=self._format_trajectory(trajectory),
163
172
  )
173
+ except litellm_exceptions.BadRequestError:
174
+ logger.warning("Trajectory exceeded the context window, truncating the oldest tool call information.")
175
+ trajectory = self.truncate_trajectory(trajectory)
164
176
  except ContextWindowExceededError:
165
177
  logger.warning("Trajectory exceeded the context window, truncating the oldest tool call information.")
166
178
  trajectory = self.truncate_trajectory(trajectory)
@@ -407,7 +407,7 @@ Today's date is {today}.
407
407
  parsed = ast.literal_eval(text)
408
408
  if isinstance(parsed, list):
409
409
  return parsed
410
- # Fallback: comma-separated
410
+ # Comma-separated values
411
411
  if "," in text:
412
412
  parts = [p.strip() for p in text.split(",")]
413
413
  cleaned = [
@@ -415,6 +415,12 @@ Today's date is {today}.
415
415
  for p in parts
416
416
  ]
417
417
  return cleaned
418
+ # Single value - treat as a list with one element
419
+ if text:
420
+ # Remove quotes if present
421
+ if len(text) >= 2 and ((text[0] == text[-1] == '"') or (text[0] == text[-1] == "'")):
422
+ return [text[1:-1]]
423
+ return [text]
418
424
  return None
419
425
 
420
426
  def _coerce_scalar(expected_type: Type[Any], val: Any) -> Tuple[bool, Optional[Any]]:
@@ -511,7 +517,48 @@ Today's date is {today}.
511
517
 
512
518
  if valid_by_type:
513
519
  if corrected_value is not None:
514
- setattr(cmd_parameters, field_name, corrected_value)
520
+ pattern = next(
521
+ (meta.pattern
522
+ for meta in getattr(field_info, "metadata", [])
523
+ if hasattr(meta, "pattern")),
524
+ None,
525
+ )
526
+ if pattern and field_value is not None and field_value != NOT_FOUND:
527
+ invalid_value = None
528
+ if hasattr(field_info, "json_schema_extra") and field_info.json_schema_extra:
529
+ invalid_value = field_info.json_schema_extra.get("invalid_value")
530
+
531
+ # if invalid_value and field_value == invalid_value:
532
+ # invalid_fields.append(f"{field_name} '{field_value}'")
533
+ # pattern_str = str(pattern)
534
+ # examples = getattr(field_info, "examples", [])
535
+ # example = examples[0] if examples else ""
536
+ # all_suggestions[field_name] = [f"Please use the format matching pattern {pattern_str} (e.g., {example})"]
537
+ # is_valid = False
538
+
539
+ # else:
540
+ pattern_regex = re.compile(pattern)
541
+ if not pattern_regex.fullmatch(str(field_value)):
542
+ invalid_fields.append(f"{field_name} '{field_value}'")
543
+ pattern_str = str(pattern)
544
+ examples = getattr(field_info, "examples", [])
545
+ example = examples[0] if examples else ""
546
+
547
+ invalid_fields.append(f"{field_name} '{field_value}'")
548
+ all_suggestions[field_name] = [f"Please use the format matching pattern {pattern_str} (e.g., {example})"]
549
+ is_valid = False
550
+ else:
551
+ try:
552
+ setattr(cmd_parameters, field_name, corrected_value)
553
+ except Exception as e:
554
+ logger.critical(f"Failed to set attribute {field_name} with value {corrected_value}")
555
+ raise e
556
+ else:
557
+ try:
558
+ setattr(cmd_parameters, field_name, corrected_value)
559
+ except Exception as e:
560
+ logger.critical(f"Failed to set attribute {field_name} with value {corrected_value}")
561
+ raise e
515
562
  else:
516
563
  invalid_fields.append(f"{field_name} '{field_value}'")
517
564
  all_suggestions[field_name] = build_type_suggestion()
@@ -539,35 +586,6 @@ Today's date is {today}.
539
586
  missing_fields.append(field_name)
540
587
  is_valid = False
541
588
 
542
- pattern = next(
543
- (meta.pattern
544
- for meta in getattr(field_info, "metadata", [])
545
- if hasattr(meta, "pattern")),
546
- None,
547
- )
548
- if pattern and field_value is not None and field_value != NOT_FOUND:
549
- invalid_value = None
550
- if hasattr(field_info, "json_schema_extra") and field_info.json_schema_extra:
551
- invalid_value = field_info.json_schema_extra.get("invalid_value")
552
-
553
- if invalid_value and field_value == invalid_value:
554
- invalid_fields.append(f"{field_name} '{field_value}'")
555
- pattern_str = str(pattern)
556
- examples = getattr(field_info, "examples", [])
557
- example = examples[0] if examples else ""
558
- all_suggestions[field_name] = [f"Please use the format matching pattern {pattern_str} (e.g., {example})"]
559
- is_valid = False
560
-
561
- else:
562
- pattern_regex = re.compile(pattern)
563
- if not pattern_regex.fullmatch(str(field_value)):
564
- invalid_fields.append(f"{field_name} '{field_value}'")
565
- pattern_str = str(pattern)
566
- examples = getattr(field_info, "examples", [])
567
- example = examples[0] if examples else ""
568
- all_suggestions[field_name] = [f"Please use the format matching pattern {pattern_str} (e.g., {example})"]
569
- is_valid = False
570
-
571
589
  for field_name, field_info in type(cmd_parameters).model_fields.items():
572
590
  field_value = getattr(cmd_parameters, field_name, None)
573
591