fastworkflow 2.15.12__tar.gz → 2.16.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.
Potentially problematic release.
This version of fastworkflow might be problematic. Click here for more details.
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/PKG-INFO +4 -2
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/README.md +2 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_can_i_do.py +9 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/wildcard.py +15 -6
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/intent_detection.py +1 -1
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/chat_session.py +129 -54
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/command_executor.py +1 -1
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/fastworkflow.env +1 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/fastworkflow.passwords.env +2 -1
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/mcp_server.py +3 -3
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/workflow_agent.py +14 -5
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/pyproject.toml +7 -3
- fastworkflow-2.15.12/fastworkflow/run_agent/__main__.py +0 -294
- fastworkflow-2.15.12/fastworkflow/run_agent/agent_module.py +0 -194
- fastworkflow-2.15.12/fastworkflow/utils/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/LICENSE +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/.DS_Store +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_commands/.gitkeep +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/abort.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/you_misunderstood.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/go_up.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/reset_context.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_is_current_context.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/command_context_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/_workflows/command_metadata_extraction/parameter_extraction.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/__main__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/ast_class_extractor.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/class_analysis_structures.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/cli_specification.md +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/command_dependency_resolver.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/command_file_generator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/command_file_template.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/command_import_utils.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/command_stub_generator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/context_folder_generator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/context_model_generator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/dependency_manager.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/dir_scanner.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/documentation_generator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/genai_postprocessor.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/inheritance_block_regenerator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/libcst_transformers.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/navigator_stub_generator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/pydantic_model_generator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/build/utterance_generator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/cache_matching.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/cli.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/command_context_model.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/command_directory.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/command_interfaces.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/command_metadata_api.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/command_routing.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/docs/context_modules_prd.txt +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/extended_workflow_example/README.md +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/extended_workflow_example/_commands/WorkItem/get_status.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/extended_workflow_example/_commands/generate_report.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/extended_workflow_example/_commands/startup.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/extended_workflow_example/simple_workflow_template.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/extended_workflow_example/workflow_inheritance_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/hello_world/_commands/README.md +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/hello_world/_commands/add_two_numbers.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/hello_world/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/hello_world/application/add_two_numbers.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_1/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_1/_commands/send_message.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_1/application/send_message.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_2/_commands/User/send_message.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_2/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_2/_commands/startup.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_2/application/user.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_3/_commands/PremiumUser/send_priority_message.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_3/_commands/User/send_message.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_3/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_3/_commands/initialize_user.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_3/application/user.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/_ChatRoom.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/add_user.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/broadcast_message.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/get_current_user.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/list_users.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/set_current_user.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/_PremiumUser.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/send_priority_message.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/User/_User.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/User/send_message.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/_commands/set_root_context.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/application/chatroom.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/application/user.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/context_hierarchy_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/messaging_app_4/startup_action.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/calculate.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/cancel_pending_order.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/exchange_delivered_order_items.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_email.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_name_zip.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/get_order_details.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/get_product_details.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/get_user_details.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/list_all_product_types.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_address.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_items.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_payment.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/modify_user_address.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/return_delivered_order_items.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/_commands/transfer_to_human_agents.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/retail_data/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/retail_data/orders.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/retail_data/products.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/retail_data/users.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/calculate.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/cancel_pending_order.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/exchange_delivered_order_items.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_email.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_name_zip.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/get_order_details.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/get_product_details.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/get_user_details.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/list_all_product_types.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_address.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_items.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_payment.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/modify_user_address.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/return_delivered_order_items.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/think.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/tool.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/tools/transfer_to_human_agents.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/retail_workflow/workflow_description.txt +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/_WorkItem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/add_child_workitem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/get_status.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/go_to_workitem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/mark_as_complete.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_first_child_workitem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_last_child_workitem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_next_workitem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_previous_workitem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_all_child_workitems.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_child_workitem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/show_schema.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/_commands/startup.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/application/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/application/workitem.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/simple_workflow_template.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/simple_workflow_template/startup_action.json +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/model_pipeline_training.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/refine/__main__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/run/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/run/__main__.py +0 -0
- {fastworkflow-2.15.12/fastworkflow/run_agent → fastworkflow-2.16.0/fastworkflow/train}/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/train/__main__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/train/generate_synthetic.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/user_message_queues.py +0 -0
- {fastworkflow-2.15.12/fastworkflow/train → fastworkflow-2.16.0/fastworkflow/utils}/__init__.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/command_dependency_graph.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/context_utils.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/dspy_cache_utils.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/dspy_logger.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/dspy_utils.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/env.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/fuzzy_match.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/generate_param_examples.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/logging.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/parameterize_func_decorator.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/pydantic_model_2_dspy_signature_class.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/python_utils.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/react.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/signatures.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/utils/startup_progress.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/workflow.py +0 -0
- {fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/workflow_inheritance_model.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastworkflow
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.16.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
|
|
7
7
|
Author: Dhar Rawal
|
|
8
8
|
Author-email: drawal@radiantlogic.com
|
|
9
|
-
Requires-Python: >=3.11
|
|
9
|
+
Requires-Python: >=3.11,<3.14
|
|
10
10
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -581,6 +581,7 @@ This single command will generate the `greet.py` command, `get_properties` and `
|
|
|
581
581
|
| `LLM_RESPONSE_GEN` | LiteLLM model string for response generation | `run` | `mistral/mistral-small-latest` |
|
|
582
582
|
| `LLM_PLANNER` | LiteLLM model string for the agent's task planner | `run` (agent mode) | `mistral/mistral-small-latest` |
|
|
583
583
|
| `LLM_AGENT` | LiteLLM model string for the DSPy agent | `run` (agent mode) | `mistral/mistral-small-latest` |
|
|
584
|
+
| `LLM_CONVERSATION_STORE` | LiteLLM model string for conversation topic/summary generation | FastAPI service | `mistral/mistral-small-latest` |
|
|
584
585
|
| `NOT_FOUND` | Placeholder value for missing parameters during extraction | Always | `"NOT_FOUND"` |
|
|
585
586
|
| `MISSING_INFORMATION_ERRMSG` | Error message prefix for missing parameters | Always | `"Missing required..."` |
|
|
586
587
|
| `INVALID_INFORMATION_ERRMSG` | Error message prefix for invalid parameters | Always | `"Invalid information..."` |
|
|
@@ -594,6 +595,7 @@ This single command will generate the `greet.py` command, `get_properties` and `
|
|
|
594
595
|
| `LITELLM_API_KEY_RESPONSE_GEN`| API key for the `LLM_RESPONSE_GEN` model | `run` | *required* |
|
|
595
596
|
| `LITELLM_API_KEY_PLANNER`| API key for the `LLM_PLANNER` model | `run` (agent mode) | *required* |
|
|
596
597
|
| `LITELLM_API_KEY_AGENT`| API key for the `LLM_AGENT` model | `run` (agent mode) | *required* |
|
|
598
|
+
| `LITELLM_API_KEY_CONVERSATION_STORE`| API key for the `LLM_CONVERSATION_STORE` model | FastAPI service | *required* |
|
|
597
599
|
|
|
598
600
|
> [!tip]
|
|
599
601
|
> The example workflows are configured to use Mistral's models by default. You can get a free API key from [Mistral AI](https://mistral.ai) that works with the `mistral-small-latest` model.
|
|
@@ -548,6 +548,7 @@ This single command will generate the `greet.py` command, `get_properties` and `
|
|
|
548
548
|
| `LLM_RESPONSE_GEN` | LiteLLM model string for response generation | `run` | `mistral/mistral-small-latest` |
|
|
549
549
|
| `LLM_PLANNER` | LiteLLM model string for the agent's task planner | `run` (agent mode) | `mistral/mistral-small-latest` |
|
|
550
550
|
| `LLM_AGENT` | LiteLLM model string for the DSPy agent | `run` (agent mode) | `mistral/mistral-small-latest` |
|
|
551
|
+
| `LLM_CONVERSATION_STORE` | LiteLLM model string for conversation topic/summary generation | FastAPI service | `mistral/mistral-small-latest` |
|
|
551
552
|
| `NOT_FOUND` | Placeholder value for missing parameters during extraction | Always | `"NOT_FOUND"` |
|
|
552
553
|
| `MISSING_INFORMATION_ERRMSG` | Error message prefix for missing parameters | Always | `"Missing required..."` |
|
|
553
554
|
| `INVALID_INFORMATION_ERRMSG` | Error message prefix for invalid parameters | Always | `"Invalid information..."` |
|
|
@@ -561,6 +562,7 @@ This single command will generate the `greet.py` command, `get_properties` and `
|
|
|
561
562
|
| `LITELLM_API_KEY_RESPONSE_GEN`| API key for the `LLM_RESPONSE_GEN` model | `run` | *required* |
|
|
562
563
|
| `LITELLM_API_KEY_PLANNER`| API key for the `LLM_PLANNER` model | `run` (agent mode) | *required* |
|
|
563
564
|
| `LITELLM_API_KEY_AGENT`| API key for the `LLM_AGENT` model | `run` (agent mode) | *required* |
|
|
565
|
+
| `LITELLM_API_KEY_CONVERSATION_STORE`| API key for the `LLM_CONVERSATION_STORE` model | FastAPI service | *required* |
|
|
564
566
|
|
|
565
567
|
> [!tip]
|
|
566
568
|
> The example workflows are configured to use Mistral's models by default. You can get a free API key from [Mistral AI](https://mistral.ai) that works with the `mistral-small-latest` model.
|
|
@@ -148,11 +148,20 @@ class ResponseGenerator:
|
|
|
148
148
|
for_agents=is_agent_mode,
|
|
149
149
|
)
|
|
150
150
|
|
|
151
|
+
# Check if the NLU pipeline stage is intent detection
|
|
152
|
+
success = False
|
|
153
|
+
nlu_pipeline_stage = workflow.context.get(
|
|
154
|
+
"NLU_Pipeline_Stage",
|
|
155
|
+
fastworkflow.NLUPipelineStage.INTENT_DETECTION)
|
|
156
|
+
if nlu_pipeline_stage == fastworkflow.NLUPipelineStage.INTENT_DETECTION:
|
|
157
|
+
success = True
|
|
158
|
+
|
|
151
159
|
return fastworkflow.CommandOutput(
|
|
152
160
|
workflow_id=workflow.id,
|
|
153
161
|
command_responses=[
|
|
154
162
|
fastworkflow.CommandResponse(
|
|
155
163
|
response=response,
|
|
164
|
+
success=success
|
|
156
165
|
)
|
|
157
166
|
]
|
|
158
167
|
)
|
|
@@ -67,7 +67,10 @@ class ResponseGenerator:
|
|
|
67
67
|
if cnp_output.command_name == 'ErrorCorrection/you_misunderstood':
|
|
68
68
|
workflow_context["NLU_Pipeline_Stage"] = NLUPipelineStage.INTENT_MISUNDERSTANDING_CLARIFICATION
|
|
69
69
|
workflow_context["command"] = command
|
|
70
|
-
|
|
70
|
+
elif (
|
|
71
|
+
nlu_pipeline_stage == fastworkflow.NLUPipelineStage.INTENT_DETECTION or
|
|
72
|
+
cnp_output.command_name == 'ErrorCorrection/abort'
|
|
73
|
+
):
|
|
71
74
|
workflow.end_command_processing()
|
|
72
75
|
workflow.context = workflow_context
|
|
73
76
|
|
|
@@ -76,9 +79,13 @@ class ResponseGenerator:
|
|
|
76
79
|
command=command,
|
|
77
80
|
)
|
|
78
81
|
command_output = CommandExecutor.perform_action(workflow, startup_action)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
if (
|
|
83
|
+
nlu_pipeline_stage == fastworkflow.NLUPipelineStage.INTENT_DETECTION or
|
|
84
|
+
cnp_output.command_name == 'ErrorCorrection/abort'
|
|
85
|
+
):
|
|
86
|
+
command_output.command_responses[0].artifacts["command_handled"] = True
|
|
87
|
+
# Set the additional attributes
|
|
88
|
+
command_output.command_name = cnp_output.command_name
|
|
82
89
|
return command_output
|
|
83
90
|
|
|
84
91
|
if nlu_pipeline_stage in {
|
|
@@ -138,7 +145,9 @@ class ResponseGenerator:
|
|
|
138
145
|
workflow.context = workflow_context
|
|
139
146
|
|
|
140
147
|
command_name = cnp_output.command_name
|
|
141
|
-
|
|
148
|
+
# Use the preserved original command (with parameters) if available
|
|
149
|
+
preserved_command = f'{command_name}: {workflow.context.get("command", command)}'
|
|
150
|
+
extractor = ParameterExtraction(workflow, app_workflow, command_name, preserved_command)
|
|
142
151
|
pe_output = extractor.extract()
|
|
143
152
|
if not pe_output.parameters_are_valid:
|
|
144
153
|
return CommandOutput(
|
|
@@ -161,7 +170,7 @@ class ResponseGenerator:
|
|
|
161
170
|
CommandResponse(
|
|
162
171
|
response="",
|
|
163
172
|
artifacts={
|
|
164
|
-
"command":
|
|
173
|
+
"command": preserved_command,
|
|
165
174
|
"command_name": command_name,
|
|
166
175
|
"cmd_parameters": pe_output.cmd_parameters,
|
|
167
176
|
},
|
|
@@ -136,7 +136,7 @@ class CommandNamePrediction:
|
|
|
136
136
|
NLUPipelineStage.INTENT_AMBIGUITY_CLARIFICATION,
|
|
137
137
|
NLUPipelineStage.INTENT_MISUNDERSTANDING_CLARIFICATION
|
|
138
138
|
) and not command_name:
|
|
139
|
-
command_name = "
|
|
139
|
+
command_name = "what can i do?"
|
|
140
140
|
|
|
141
141
|
if not command_name or command_name == "wildcard":
|
|
142
142
|
fully_qualified_command_name=None
|
|
@@ -8,6 +8,7 @@ import contextlib
|
|
|
8
8
|
import uuid
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
import os
|
|
11
|
+
from datetime import datetime
|
|
11
12
|
|
|
12
13
|
import dspy
|
|
13
14
|
|
|
@@ -34,7 +35,7 @@ class ChatWorker(Thread):
|
|
|
34
35
|
"""Process messages for the root workflow"""
|
|
35
36
|
try:
|
|
36
37
|
self.chat_session._status = SessionStatus.RUNNING
|
|
37
|
-
workflow =
|
|
38
|
+
workflow = self.chat_session.get_active_workflow()
|
|
38
39
|
logger.debug(f"Started root workflow {workflow.id}")
|
|
39
40
|
|
|
40
41
|
# Run the workflow loop
|
|
@@ -43,39 +44,34 @@ class ChatWorker(Thread):
|
|
|
43
44
|
finally:
|
|
44
45
|
self.chat_session._status = SessionStatus.STOPPED
|
|
45
46
|
# Ensure workflow is popped if thread terminates unexpectedly
|
|
46
|
-
if
|
|
47
|
-
|
|
47
|
+
if self.chat_session.get_active_workflow() is not None:
|
|
48
|
+
self.chat_session.pop_active_workflow()
|
|
48
49
|
|
|
49
50
|
class ChatSession:
|
|
50
|
-
|
|
51
|
-
_workflow_stack: ClassVar[deque[fastworkflow.Workflow]] = deque() # Stack of workflow objects
|
|
52
|
-
|
|
53
|
-
@classmethod
|
|
54
|
-
def get_active_workflow(cls) -> Optional[fastworkflow.Workflow]:
|
|
51
|
+
def get_active_workflow(self) -> Optional[fastworkflow.Workflow]:
|
|
55
52
|
"""Get the currently active workflow (top of stack)"""
|
|
56
|
-
with
|
|
57
|
-
return
|
|
53
|
+
with self._workflow_stack_lock:
|
|
54
|
+
return self._workflow_stack[-1] if self._workflow_stack else None
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
with
|
|
62
|
-
|
|
63
|
-
logger.debug(f"Workflow stack: {[w.id for w in
|
|
56
|
+
def push_active_workflow(self, workflow: fastworkflow.Workflow) -> None:
|
|
57
|
+
"""Push a workflow onto this session's stack"""
|
|
58
|
+
with self._workflow_stack_lock:
|
|
59
|
+
self._workflow_stack.append(workflow)
|
|
60
|
+
logger.debug(f"Workflow stack: {[w.id for w in self._workflow_stack]}")
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
with
|
|
68
|
-
if not
|
|
62
|
+
def pop_active_workflow(self) -> Optional[fastworkflow.Workflow]:
|
|
63
|
+
"""Pop a workflow from this session's stack"""
|
|
64
|
+
with self._workflow_stack_lock:
|
|
65
|
+
if not self._workflow_stack:
|
|
69
66
|
return None
|
|
70
|
-
workflow =
|
|
71
|
-
logger.debug(f"Workflow stack after pop: {[w.id for w in
|
|
67
|
+
workflow = self._workflow_stack.pop()
|
|
68
|
+
logger.debug(f"Workflow stack after pop: {[w.id for w in self._workflow_stack]}")
|
|
72
69
|
return workflow
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
cls._workflow_stack.clear()
|
|
71
|
+
def clear_workflow_stack(self) -> None:
|
|
72
|
+
"""Clear the entire workflow stack for this session"""
|
|
73
|
+
with self._workflow_stack_lock:
|
|
74
|
+
self._workflow_stack.clear()
|
|
79
75
|
logger.debug("Workflow stack cleared")
|
|
80
76
|
|
|
81
77
|
def stop_workflow(self) -> None:
|
|
@@ -94,7 +90,7 @@ class ChatSession:
|
|
|
94
90
|
logger.warning("Chat worker thread did not terminate within timeout")
|
|
95
91
|
|
|
96
92
|
# Clear the workflow stack
|
|
97
|
-
|
|
93
|
+
self.clear_workflow_stack()
|
|
98
94
|
|
|
99
95
|
# Reset status to stopped
|
|
100
96
|
self._status = SessionStatus.STOPPED
|
|
@@ -115,6 +111,10 @@ class ChatSession:
|
|
|
115
111
|
A chat session can run multiple workflows that share the same message queues.
|
|
116
112
|
Use start_workflow() to start a specific workflow within this session.
|
|
117
113
|
"""
|
|
114
|
+
# Create instance-level workflow stack (supports nested workflows within this session)
|
|
115
|
+
self._workflow_stack: deque[fastworkflow.Workflow] = deque()
|
|
116
|
+
self._workflow_stack_lock = Lock()
|
|
117
|
+
|
|
118
118
|
# Create queues for user messages and command outputs
|
|
119
119
|
self._user_message_queue = Queue()
|
|
120
120
|
self._command_output_queue = Queue()
|
|
@@ -144,6 +144,10 @@ class ChatSession:
|
|
|
144
144
|
}
|
|
145
145
|
)
|
|
146
146
|
|
|
147
|
+
# this intializes the conversation traces file name also
|
|
148
|
+
# which is necessary when starting a brand new chat session
|
|
149
|
+
self.clear_conversation_history()
|
|
150
|
+
|
|
147
151
|
def start_workflow(self,
|
|
148
152
|
workflow_folderpath: str,
|
|
149
153
|
workflow_id_str: Optional[str] = None,
|
|
@@ -192,7 +196,7 @@ class ChatSession:
|
|
|
192
196
|
|
|
193
197
|
# Check if we need to stop the current workflow
|
|
194
198
|
# Stop if this is a new root workflow (no parent, keep_alive=True)
|
|
195
|
-
current_workflow =
|
|
199
|
+
current_workflow = self.get_active_workflow()
|
|
196
200
|
if (current_workflow and
|
|
197
201
|
parent_workflow_id is None and
|
|
198
202
|
self._keep_alive):
|
|
@@ -239,7 +243,7 @@ class ChatSession:
|
|
|
239
243
|
self._status = SessionStatus.STARTING
|
|
240
244
|
|
|
241
245
|
# Push this workflow as active
|
|
242
|
-
|
|
246
|
+
self.push_active_workflow(workflow)
|
|
243
247
|
|
|
244
248
|
# Initialize workflow tool agent if in agent mode
|
|
245
249
|
# This must happen after pushing the workflow to the stack
|
|
@@ -299,12 +303,12 @@ class ChatSession:
|
|
|
299
303
|
|
|
300
304
|
@property
|
|
301
305
|
def workflow_is_complete(self) -> bool:
|
|
302
|
-
workflow =
|
|
306
|
+
workflow = self.get_active_workflow()
|
|
303
307
|
return workflow.is_complete if workflow else True
|
|
304
308
|
|
|
305
309
|
@workflow_is_complete.setter
|
|
306
310
|
def workflow_is_complete(self, value: bool) -> None:
|
|
307
|
-
if workflow :=
|
|
311
|
+
if workflow := self.get_active_workflow():
|
|
308
312
|
workflow.is_complete = value
|
|
309
313
|
|
|
310
314
|
@property
|
|
@@ -312,12 +316,22 @@ class ChatSession:
|
|
|
312
316
|
"""Return the conversation history."""
|
|
313
317
|
return self._conversation_history
|
|
314
318
|
|
|
319
|
+
# def clear_conversation_history(self, trace_filename_suffix: Optional[str] = None) -> None:
|
|
315
320
|
def clear_conversation_history(self) -> None:
|
|
316
321
|
"""
|
|
317
322
|
Clear the conversation history.
|
|
318
323
|
This resets the conversation history to an empty state.
|
|
319
324
|
"""
|
|
320
325
|
self._conversation_history = dspy.History(messages=[])
|
|
326
|
+
# Filename for conversation traces
|
|
327
|
+
# if trace_filename_suffix:
|
|
328
|
+
# self._conversation_traces_file_name: str = (
|
|
329
|
+
# f"conversation_traces_{trace_filename_suffix}"
|
|
330
|
+
# )
|
|
331
|
+
# else:
|
|
332
|
+
# self._conversation_traces_file_name: str = (
|
|
333
|
+
# f"conversation_traces_{datetime.now().strftime('%m_%d_%Y:%H_%M_%S')}.jsonl"
|
|
334
|
+
# )
|
|
321
335
|
|
|
322
336
|
def _run_workflow_loop(self) -> Optional[fastworkflow.CommandOutput]:
|
|
323
337
|
"""
|
|
@@ -327,7 +341,7 @@ class ChatSession:
|
|
|
327
341
|
- All outputs (success or failure) are sent to queue during processing
|
|
328
342
|
"""
|
|
329
343
|
last_output = None
|
|
330
|
-
workflow =
|
|
344
|
+
workflow = self.get_active_workflow()
|
|
331
345
|
|
|
332
346
|
try:
|
|
333
347
|
# Handle startup command/action
|
|
@@ -371,7 +385,7 @@ class ChatSession:
|
|
|
371
385
|
|
|
372
386
|
finally:
|
|
373
387
|
self._status = SessionStatus.STOPPED
|
|
374
|
-
|
|
388
|
+
self.pop_active_workflow()
|
|
375
389
|
logger.debug(f"Workflow {workflow.id if workflow else 'unknown'} completed")
|
|
376
390
|
|
|
377
391
|
return None
|
|
@@ -387,7 +401,7 @@ class ChatSession:
|
|
|
387
401
|
# def _process_mcp_tool_call(self, message: str) -> fastworkflow.CommandOutput:
|
|
388
402
|
# # sourcery skip: class-extract-method, extract-method
|
|
389
403
|
# """Process an MCP tool call message"""
|
|
390
|
-
# workflow =
|
|
404
|
+
# workflow = self.get_active_workflow()
|
|
391
405
|
|
|
392
406
|
# try:
|
|
393
407
|
# # Parse JSON message
|
|
@@ -415,7 +429,7 @@ class ChatSession:
|
|
|
415
429
|
# self.command_output_queue.put(command_output)
|
|
416
430
|
|
|
417
431
|
# # Flush on successful or failed tool call – state may have changed.
|
|
418
|
-
# if workflow :=
|
|
432
|
+
# if workflow := self.get_active_workflow():
|
|
419
433
|
# workflow.flush()
|
|
420
434
|
|
|
421
435
|
# return command_output
|
|
@@ -442,8 +456,8 @@ class ChatSession:
|
|
|
442
456
|
# to the workflow internally (directly via CommandExecutor)
|
|
443
457
|
|
|
444
458
|
# Ensure any prior action log is removed before a fresh agent run
|
|
445
|
-
if os.path.exists("action.
|
|
446
|
-
os.remove("action.
|
|
459
|
+
if os.path.exists("action.jsonl"):
|
|
460
|
+
os.remove("action.jsonl")
|
|
447
461
|
|
|
448
462
|
refined_user_query = self._refine_user_query(message, self.conversation_history)
|
|
449
463
|
|
|
@@ -483,14 +497,18 @@ class ChatSession:
|
|
|
483
497
|
|
|
484
498
|
conversation_summary = message
|
|
485
499
|
# Attach actions captured during agent execution as artifacts if available
|
|
486
|
-
if os.path.exists("action.
|
|
487
|
-
with open("action.
|
|
500
|
+
if os.path.exists("action.jsonl"):
|
|
501
|
+
with open("action.jsonl", "r", encoding="utf-8") as f:
|
|
488
502
|
actions = [json.loads(line) for line in f if line.strip()]
|
|
489
|
-
conversation_summary = self._extract_conversation_summary(message, actions, result_text)
|
|
503
|
+
conversation_summary, conversation_traces = self._extract_conversation_summary(message, actions, result_text)
|
|
490
504
|
command_response.artifacts["conversation_summary"] = conversation_summary
|
|
491
505
|
|
|
492
506
|
self.conversation_history.messages.append(
|
|
493
|
-
{
|
|
507
|
+
{
|
|
508
|
+
"conversation summary": conversation_summary,
|
|
509
|
+
"conversation_traces": conversation_traces,
|
|
510
|
+
"feedback": None # Initialize feedback slot for this turn
|
|
511
|
+
}
|
|
494
512
|
)
|
|
495
513
|
|
|
496
514
|
command_output = fastworkflow.CommandOutput(
|
|
@@ -500,11 +518,11 @@ class ChatSession:
|
|
|
500
518
|
|
|
501
519
|
# Put output in queue (following same pattern as _process_message)
|
|
502
520
|
if (not command_output.success or self._keep_alive) and \
|
|
503
|
-
|
|
521
|
+
self.command_output_queue:
|
|
504
522
|
self.command_output_queue.put(command_output)
|
|
505
523
|
|
|
506
524
|
# Persist workflow state changes
|
|
507
|
-
if workflow :=
|
|
525
|
+
if workflow := self.get_active_workflow():
|
|
508
526
|
workflow.flush()
|
|
509
527
|
|
|
510
528
|
return command_output
|
|
@@ -515,20 +533,77 @@ class ChatSession:
|
|
|
515
533
|
# command_output = self.profile_invoke_command(message)
|
|
516
534
|
|
|
517
535
|
command_output = self._CommandExecutor.invoke_command(self, message)
|
|
536
|
+
|
|
537
|
+
# Record assistant mode trace to action.jsonl (similar to agent mode in workflow_agent.py)
|
|
538
|
+
# This ensures assistant commands are captured even when interspersed with agent commands
|
|
539
|
+
response_text = ""
|
|
540
|
+
if command_output.command_responses:
|
|
541
|
+
response_text = command_output.command_responses[0].response or ""
|
|
542
|
+
|
|
543
|
+
# Convert parameters to dict if it's a Pydantic model or other complex object
|
|
544
|
+
params = command_output.command_parameters or {}
|
|
545
|
+
if hasattr(params, 'model_dump'):
|
|
546
|
+
params = params.model_dump()
|
|
547
|
+
elif hasattr(params, 'dict'):
|
|
548
|
+
params = params.dict()
|
|
549
|
+
|
|
550
|
+
record = {
|
|
551
|
+
"command": message,
|
|
552
|
+
"command_name": command_output.command_name or "",
|
|
553
|
+
"parameters": params,
|
|
554
|
+
"response": response_text
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
self.conversation_history.messages.append(
|
|
558
|
+
{
|
|
559
|
+
"conversation summary": "assistant_mode_command",
|
|
560
|
+
"conversation_traces": json.dumps(record),
|
|
561
|
+
"feedback": None # Initialize feedback slot for this turn
|
|
562
|
+
}
|
|
563
|
+
)
|
|
564
|
+
|
|
518
565
|
if (not command_output.success or self._keep_alive) and \
|
|
519
566
|
self.command_output_queue:
|
|
520
567
|
self.command_output_queue.put(command_output)
|
|
521
568
|
|
|
522
569
|
# Persist workflow state changes lazily accumulated during message processing.
|
|
523
|
-
if workflow :=
|
|
570
|
+
if workflow := self.get_active_workflow():
|
|
524
571
|
workflow.flush()
|
|
525
572
|
|
|
526
573
|
return command_output
|
|
527
574
|
|
|
528
575
|
def _process_action(self, action: fastworkflow.Action) -> fastworkflow.CommandOutput:
|
|
529
576
|
"""Process a startup action"""
|
|
530
|
-
workflow =
|
|
577
|
+
workflow = self.get_active_workflow()
|
|
531
578
|
command_output = self._CommandExecutor.perform_action(workflow, action)
|
|
579
|
+
|
|
580
|
+
# Record action trace to action.jsonl
|
|
581
|
+
response_text = ""
|
|
582
|
+
if command_output.command_responses:
|
|
583
|
+
response_text = command_output.command_responses[0].response or ""
|
|
584
|
+
|
|
585
|
+
# Convert parameters to dict if it's a Pydantic model or other complex object
|
|
586
|
+
params = action.parameters or {}
|
|
587
|
+
if hasattr(params, 'model_dump'):
|
|
588
|
+
params = params.model_dump()
|
|
589
|
+
elif hasattr(params, 'dict'):
|
|
590
|
+
params = params.dict()
|
|
591
|
+
|
|
592
|
+
record = {
|
|
593
|
+
"command": "process_action",
|
|
594
|
+
"command_name": action.command_name,
|
|
595
|
+
"parameters": params,
|
|
596
|
+
"response": response_text
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
self.conversation_history.messages.append(
|
|
600
|
+
{
|
|
601
|
+
"conversation summary": "process_action command",
|
|
602
|
+
"conversation_traces": json.dumps(record),
|
|
603
|
+
"feedback": None # Initialize feedback slot for this turn
|
|
604
|
+
}
|
|
605
|
+
)
|
|
606
|
+
|
|
532
607
|
if (not command_output.success or self._keep_alive) and \
|
|
533
608
|
self.command_output_queue:
|
|
534
609
|
self.command_output_queue.put(command_output)
|
|
@@ -559,16 +634,16 @@ class ChatSession:
|
|
|
559
634
|
user_query: str, workflow_actions: list[dict[str, str]], final_agent_response: str) -> str:
|
|
560
635
|
"""
|
|
561
636
|
Summarizes conversation based on original user query, workflow actions and agentt response.
|
|
637
|
+
Returns the conversation summary and the log entry
|
|
562
638
|
"""
|
|
563
639
|
# Lets log everything to a file called action_log.jsonl, if it exists
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
f.write(json.dumps(log_entry) + "\n")
|
|
640
|
+
conversation_traces = {
|
|
641
|
+
"user_query": user_query,
|
|
642
|
+
"agent_workflow_interactions": workflow_actions,
|
|
643
|
+
"final_agent_response": final_agent_response
|
|
644
|
+
}
|
|
645
|
+
# with open(self._conversation_traces_file_name, "a", encoding="utf-8") as f:
|
|
646
|
+
# f.write(json.dumps(log_entry) + "\n")
|
|
572
647
|
|
|
573
648
|
class ConversationSummarySignature(dspy.Signature):
|
|
574
649
|
"""
|
|
@@ -588,7 +663,7 @@ class ChatSession:
|
|
|
588
663
|
user_query=user_query,
|
|
589
664
|
workflow_actions=workflow_actions,
|
|
590
665
|
final_agent_response=final_agent_response)
|
|
591
|
-
return prediction.conversation_summary
|
|
666
|
+
return prediction.conversation_summary, json.dumps(conversation_traces)
|
|
592
667
|
|
|
593
668
|
|
|
594
669
|
def profile_invoke_command(self, message: str):
|
|
@@ -56,7 +56,7 @@ class CommandExecutor(CommandExecutorInterface):
|
|
|
56
56
|
command_name = command_output.command_responses[0].artifacts["command_name"]
|
|
57
57
|
input_obj = command_output.command_responses[0].artifacts["cmd_parameters"]
|
|
58
58
|
|
|
59
|
-
workflow =
|
|
59
|
+
workflow = chat_session.get_active_workflow()
|
|
60
60
|
workflow_name = workflow.folderpath.split('/')[-1]
|
|
61
61
|
context = workflow.current_command_context_displayname
|
|
62
62
|
|
|
@@ -3,6 +3,7 @@ LLM_PARAM_EXTRACTION=mistral/mistral-small-latest
|
|
|
3
3
|
LLM_RESPONSE_GEN=mistral/mistral-small-latest
|
|
4
4
|
LLM_PLANNER=mistral/mistral-small-latest
|
|
5
5
|
LLM_AGENT=mistral/mistral-small-latest
|
|
6
|
+
LLM_CONVERSATION_STORE=mistral/mistral-small-latest
|
|
6
7
|
|
|
7
8
|
SPEEDDICT_FOLDERNAME=___workflow_contexts
|
|
8
9
|
SYNTHETIC_UTTERANCE_GEN_NUMOF_PERSONAS=4
|
{fastworkflow-2.15.12 → fastworkflow-2.16.0}/fastworkflow/examples/fastworkflow.passwords.env
RENAMED
|
@@ -3,4 +3,5 @@ LITELLM_API_KEY_SYNDATA_GEN=<API KEY for synthetic data generation model>
|
|
|
3
3
|
LITELLM_API_KEY_PARAM_EXTRACTION=<API KEY for parameter extraction model>
|
|
4
4
|
LITELLM_API_KEY_RESPONSE_GEN=<API KEY for response generation model>
|
|
5
5
|
LITELLM_API_KEY_PLANNER=<API KEY for the agent's task planner model>
|
|
6
|
-
LITELLM_API_KEY_AGENT=<API KEY for the agent model>
|
|
6
|
+
LITELLM_API_KEY_AGENT=<API KEY for the agent model>
|
|
7
|
+
LITELLM_API_KEY_CONVERSATION_STORE=<API KEY for conversation topic/summary generation model>
|
|
@@ -41,7 +41,7 @@ class FastWorkflowMCPServer:
|
|
|
41
41
|
NOT_FOUND = fastworkflow.get_env_var('NOT_FOUND')
|
|
42
42
|
|
|
43
43
|
# Get available commands from workflow
|
|
44
|
-
workflow = fastworkflow.
|
|
44
|
+
workflow = fastworkflow.chat_session.get_active_workflow()
|
|
45
45
|
workflow_folderpath = workflow.folderpath
|
|
46
46
|
# Use cached routing definition instead of rebuilding every time
|
|
47
47
|
routing = RoutingRegistry.get_definition(workflow_folderpath)
|
|
@@ -147,7 +147,7 @@ class FastWorkflowMCPServer:
|
|
|
147
147
|
arguments=arguments
|
|
148
148
|
)
|
|
149
149
|
|
|
150
|
-
workflow = fastworkflow.
|
|
150
|
+
workflow = fastworkflow.chat_session.get_active_workflow()
|
|
151
151
|
# Execute using MCP-compliant method
|
|
152
152
|
return CommandExecutor.perform_mcp_tool_call(
|
|
153
153
|
workflow,
|
|
@@ -203,7 +203,7 @@ class FastWorkflowMCPServer:
|
|
|
203
203
|
|
|
204
204
|
Falls back to the first available path if the active context is none.
|
|
205
205
|
"""
|
|
206
|
-
workflow = fastworkflow.
|
|
206
|
+
workflow = fastworkflow.chat_session.get_active_workflow()
|
|
207
207
|
return workflow.current_command_context_name
|
|
208
208
|
|
|
209
209
|
|
|
@@ -125,14 +125,14 @@ def _execute_workflow_query(command: str, chat_session_obj: fastworkflow.ChatSes
|
|
|
125
125
|
timestamp_ms=int(time.time() * 1000),
|
|
126
126
|
))
|
|
127
127
|
|
|
128
|
-
# Append executed action to action.
|
|
128
|
+
# Append executed action to action.jsonl for external consumers (agent mode only)
|
|
129
129
|
record = {
|
|
130
130
|
"command": command,
|
|
131
131
|
"command_name": name,
|
|
132
132
|
"parameters": params_dict,
|
|
133
133
|
"response": response_text
|
|
134
134
|
}
|
|
135
|
-
with open("action.
|
|
135
|
+
with open("action.jsonl", "a", encoding="utf-8") as f:
|
|
136
136
|
f.write(json.dumps(record, ensure_ascii=False) + "\n")
|
|
137
137
|
|
|
138
138
|
if 'PARAMETER EXTRACTION ERROR' in response_text or 'The command is ambiguous' in response_text:
|
|
@@ -174,12 +174,21 @@ def _ask_user_tool(clarification_request: str, chat_session_obj: fastworkflow.Ch
|
|
|
174
174
|
Note that using the wrong command name can produce missing information errors. Double-check with the missing_information_guidance_tool to verify that the correct command name is being used
|
|
175
175
|
"""
|
|
176
176
|
command_output = fastworkflow.CommandOutput(
|
|
177
|
-
command_responses=[fastworkflow.CommandResponse(response=clarification_request)]
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
command_responses=[fastworkflow.CommandResponse(response=clarification_request)],
|
|
178
|
+
workflow_name = chat_session_obj.get_active_workflow().folderpath.split('/')[-1]
|
|
179
|
+
)
|
|
180
180
|
chat_session_obj.command_output_queue.put(command_output)
|
|
181
181
|
|
|
182
182
|
user_query = chat_session_obj.user_message_queue.get()
|
|
183
|
+
|
|
184
|
+
# add the agent user dialog to the log
|
|
185
|
+
with open("action.jsonl", "a", encoding="utf-8") as f:
|
|
186
|
+
agent_user_dialog = {
|
|
187
|
+
"agent_query": clarification_request,
|
|
188
|
+
"user_response": user_query
|
|
189
|
+
}
|
|
190
|
+
f.write(json.dumps(agent_user_dialog, ensure_ascii=False) + "\n")
|
|
191
|
+
|
|
183
192
|
return build_query_with_next_steps(user_query, chat_session_obj, with_agent_inputs_and_trajectory = True)
|
|
184
193
|
|
|
185
194
|
def initialize_workflow_tool_agent(chat_session: fastworkflow.ChatSession, max_iters: int = 25):
|
|
@@ -9,7 +9,7 @@ repository = "https://github.com/radiantlogicinc/fastworkflow"
|
|
|
9
9
|
|
|
10
10
|
[tool.poetry]
|
|
11
11
|
name = "fastworkflow"
|
|
12
|
-
version = "2.
|
|
12
|
+
version = "2.16.0"
|
|
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"
|
|
@@ -31,7 +31,7 @@ exclude = [
|
|
|
31
31
|
fastworkflow = "fastworkflow.cli:main"
|
|
32
32
|
|
|
33
33
|
[tool.poetry.dependencies]
|
|
34
|
-
python = ">=3.11"
|
|
34
|
+
python = ">=3.11,<3.14"
|
|
35
35
|
pydantic = "^2.9.2"
|
|
36
36
|
speedict = "^0.3.12"
|
|
37
37
|
python-dotenv = "^1.0.1"
|
|
@@ -60,9 +60,13 @@ bandit = "^1.7.10"
|
|
|
60
60
|
[tool.poetry.group.test.dependencies]
|
|
61
61
|
pytest = "^8.3.3"
|
|
62
62
|
requests-mock = "^1.12.1"
|
|
63
|
+
pytest-cov = "^6.2.1"
|
|
63
64
|
|
|
64
65
|
# poetry install --with aws if you are using AWS Bedrock for LLM or LLM_AGENT
|
|
65
|
-
pytest-cov = "^6.2.1"
|
|
66
66
|
[tool.poetry.group.aws.dependencies]
|
|
67
67
|
boto3 = {version = "1.36.0", optional = true}
|
|
68
68
|
|
|
69
|
+
|
|
70
|
+
[tool.poetry.group.fastapi.dependencies]
|
|
71
|
+
fastapi = ">=0.115.5,<0.116.0"
|
|
72
|
+
|