fastworkflow 2.17.8__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.
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/PKG-INFO +1 -1
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/parameter_extraction.py +81 -5
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/chat_session.py +14 -3
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/command_metadata_api.py +50 -0
- fastworkflow-2.17.9/fastworkflow/intent_clarification_agent.py +132 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/train/__main__.py +1 -1
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/react.py +13 -1
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/signatures.py +49 -31
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/workflow_agent.py +78 -4
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/pyproject.toml +1 -1
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/LICENSE +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/README.md +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/.DS_Store +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_commands/.gitkeep +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/abort.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/you_misunderstood.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/go_up.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/reset_context.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_can_i_do.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_is_current_context.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/_commands/wildcard.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/command_context_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/_workflows/command_metadata_extraction/intent_detection.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/__main__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/ast_class_extractor.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/class_analysis_structures.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/cli_specification.md +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/command_dependency_resolver.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/command_file_generator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/command_file_template.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/command_import_utils.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/command_stub_generator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/context_folder_generator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/context_model_generator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/dependency_manager.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/dir_scanner.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/documentation_generator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/genai_postprocessor.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/inheritance_block_regenerator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/libcst_transformers.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/navigator_stub_generator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/pydantic_model_generator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/build/utterance_generator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/cache_matching.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/cli.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/command_context_model.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/command_directory.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/command_executor.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/command_interfaces.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/command_routing.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/docs/context_modules_prd.txt +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/README.md +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/_commands/WorkItem/get_status.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/_commands/generate_report.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/_commands/startup.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/simple_workflow_template.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/extended_workflow_example/workflow_inheritance_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/fastworkflow.env +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/fastworkflow.passwords.env +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/hello_world/_commands/README.md +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/hello_world/_commands/add_two_numbers.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/hello_world/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/hello_world/application/add_two_numbers.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_1/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_1/_commands/send_message.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_1/application/send_message.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_2/_commands/User/send_message.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_2/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_2/_commands/startup.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_2/application/user.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/_commands/PremiumUser/send_priority_message.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/_commands/User/send_message.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/_commands/initialize_user.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_3/application/user.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/_ChatRoom.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/add_user.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/broadcast_message.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/get_current_user.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/list_users.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/set_current_user.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/_PremiumUser.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/send_priority_message.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/User/_User.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/User/send_message.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/_commands/set_root_context.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/application/chatroom.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/application/user.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/context_hierarchy_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/messaging_app_4/startup_action.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/calculate.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/cancel_pending_order.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/exchange_delivered_order_items.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_email.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_name_zip.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/get_order_details.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/get_product_details.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/get_user_details.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/list_all_product_types.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_address.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_items.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_payment.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/modify_user_address.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/return_delivered_order_items.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/_commands/transfer_to_human_agents.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/context_inheritance_model.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/retail_data/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/retail_data/orders.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/retail_data/products.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/retail_data/users.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/calculate.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/cancel_pending_order.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/exchange_delivered_order_items.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_email.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_name_zip.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/get_order_details.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/get_product_details.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/get_user_details.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/list_all_product_types.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_address.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_items.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_payment.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/modify_user_address.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/return_delivered_order_items.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/think.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/tool.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/tools/transfer_to_human_agents.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/retail_workflow/workflow_description.txt +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/_WorkItem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/add_child_workitem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/get_status.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/go_to_workitem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/mark_as_complete.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_first_child_workitem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_last_child_workitem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_next_workitem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_previous_workitem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_all_child_workitems.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_child_workitem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/show_schema.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/_commands/startup.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/application/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/application/workitem.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/simple_workflow_template.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/examples/simple_workflow_template/startup_action.json +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/mcp_server.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/model_pipeline_training.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/refine/__main__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run/__main__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/README.md +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/__main__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/conversation_store.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/jwt_manager.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/mcp_specific.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/redoc_2_standalone_html.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/run_fastapi_mcp/utils.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/train/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/train/generate_synthetic.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/user_message_queues.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/__init__.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/chat_adapter.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/command_dependency_graph.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/context_utils.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/dspy_cache_utils.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/dspy_logger.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/dspy_utils.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/env.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/fuzzy_match.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/generate_param_examples.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/logging.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/parameterize_func_decorator.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/pydantic_model_2_dspy_signature_class.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/python_utils.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/utils/startup_progress.py +0 -0
- {fastworkflow-2.17.8 → fastworkflow-2.17.9}/fastworkflow/workflow.py +0 -0
- {fastworkflow-2.17.8 → 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.
|
|
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
|
-
#
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
self.
|
|
66
|
-
|
|
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
|
|
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
|
+
)
|
|
@@ -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("
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
|
|
@@ -99,10 +99,10 @@ def _execute_workflow_query(command: str, chat_session_obj: fastworkflow.ChatSes
|
|
|
99
99
|
# Extract command name and parameters from command_output
|
|
100
100
|
name = command_output.command_name
|
|
101
101
|
params = command_output.command_parameters
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
# Handle parameter serialization
|
|
104
104
|
params_dict = params.model_dump() if params else None
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
# Extract response text
|
|
107
107
|
response_text = ""
|
|
108
108
|
if command_output.command_responses:
|
|
@@ -135,8 +135,81 @@ def _execute_workflow_query(command: str, chat_session_obj: fastworkflow.ChatSes
|
|
|
135
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
|
-
|
|
139
|
-
|
|
138
|
+
# Check workflow context to determine if we're in an error state that needs specialized handling
|
|
139
|
+
cme_workflow = chat_session_obj.cme_workflow
|
|
140
|
+
nlu_stage = cme_workflow.context.get("NLU_Pipeline_Stage")
|
|
141
|
+
|
|
142
|
+
# Handle intent ambiguity clarification state with specialized agent
|
|
143
|
+
if nlu_stage == fastworkflow.NLUPipelineStage.INTENT_AMBIGUITY_CLARIFICATION:
|
|
144
|
+
if intent_agent := chat_session_obj.intent_clarification_agent:
|
|
145
|
+
# Get suggested commands from intent detection system
|
|
146
|
+
from fastworkflow._workflows.command_metadata_extraction.intent_detection import CommandNamePrediction
|
|
147
|
+
predictor = CommandNamePrediction(cme_workflow)
|
|
148
|
+
suggested_commands = predictor._get_suggested_commands(predictor.path)
|
|
149
|
+
|
|
150
|
+
suggested_commands = list(suggested_commands) if suggested_commands is not None else []
|
|
151
|
+
|
|
152
|
+
# Get metadata for only the suggested commands
|
|
153
|
+
current_workflow = chat_session_obj.get_active_workflow()
|
|
154
|
+
suggested_commands_metadata = CommandMetadataAPI.get_suggested_commands_metadata(
|
|
155
|
+
subject_workflow_path=current_workflow.folderpath,
|
|
156
|
+
cme_workflow_path=fastworkflow.get_internal_workflow_path("command_metadata_extraction"),
|
|
157
|
+
active_context_name=current_workflow.current_command_context_name,
|
|
158
|
+
suggested_command_names=suggested_commands
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Get the workflow agent's trajectory and inputs for context
|
|
162
|
+
workflow_tool_agent = chat_session_obj.workflow_tool_agent
|
|
163
|
+
agent_inputs = workflow_tool_agent.inputs if workflow_tool_agent else {}
|
|
164
|
+
agent_trajectory = workflow_tool_agent.current_trajectory if workflow_tool_agent else {}
|
|
165
|
+
|
|
166
|
+
lm = dspy_utils.get_lm("LLM_AGENT", "LITELLM_API_KEY_AGENT")
|
|
167
|
+
with dspy.context(lm=lm):
|
|
168
|
+
result = intent_agent(
|
|
169
|
+
original_command=command,
|
|
170
|
+
error_message=response_text,
|
|
171
|
+
agent_inputs=agent_inputs,
|
|
172
|
+
agent_trajectory=agent_trajectory,
|
|
173
|
+
suggested_commands_metadata=suggested_commands_metadata
|
|
174
|
+
)
|
|
175
|
+
# The clarified command should have the correct name with all original parameters
|
|
176
|
+
clarified_cmd = result.clarified_command if hasattr(result, 'clarified_command') else str(result)
|
|
177
|
+
# Execute the clarified command
|
|
178
|
+
return _execute_workflow_query(clarified_cmd, chat_session_obj=chat_session_obj)
|
|
179
|
+
else:
|
|
180
|
+
# No intent clarification agent available, fall back to abort
|
|
181
|
+
abort_confirmation = _execute_workflow_query('abort', chat_session_obj=chat_session_obj)
|
|
182
|
+
return f'{response_text}\n{abort_confirmation}'
|
|
183
|
+
|
|
184
|
+
# Handle intent misunderstanding clarification state with specialized agent
|
|
185
|
+
if nlu_stage == fastworkflow.NLUPipelineStage.INTENT_MISUNDERSTANDING_CLARIFICATION:
|
|
186
|
+
if intent_agent := chat_session_obj.intent_clarification_agent:
|
|
187
|
+
# Get the workflow agent's trajectory and inputs for context
|
|
188
|
+
workflow_tool_agent = chat_session_obj.workflow_tool_agent
|
|
189
|
+
agent_inputs = workflow_tool_agent.inputs if workflow_tool_agent else {}
|
|
190
|
+
agent_trajectory = workflow_tool_agent.current_trajectory if workflow_tool_agent else {}
|
|
191
|
+
|
|
192
|
+
lm = dspy_utils.get_lm("LLM_AGENT", "LITELLM_API_KEY_AGENT")
|
|
193
|
+
with dspy.context(lm=lm):
|
|
194
|
+
result = intent_agent(
|
|
195
|
+
original_command=command,
|
|
196
|
+
error_message=response_text,
|
|
197
|
+
agent_inputs=agent_inputs,
|
|
198
|
+
agent_trajectory=agent_trajectory,
|
|
199
|
+
suggested_commands_metadata=""
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
clarified_cmd = result.clarified_command if hasattr(result, 'clarified_command') else str(result)
|
|
203
|
+
|
|
204
|
+
return _execute_workflow_query(clarified_cmd, chat_session_obj=chat_session_obj)
|
|
205
|
+
else:
|
|
206
|
+
# No intent clarification agent available, fall back to abort
|
|
207
|
+
abort_confirmation = _execute_workflow_query('abort', chat_session_obj=chat_session_obj)
|
|
208
|
+
return f'{response_text}\n{abort_confirmation}'
|
|
209
|
+
|
|
210
|
+
# Handle parameter extraction errors with abort
|
|
211
|
+
if nlu_stage == fastworkflow.NLUPipelineStage.PARAMETER_EXTRACTION:
|
|
212
|
+
abort_confirmation = _execute_workflow_query('abort', chat_session_obj=chat_session_obj)
|
|
140
213
|
return f'{response_text}\n{abort_confirmation}'
|
|
141
214
|
|
|
142
215
|
return response_text
|
|
@@ -253,6 +326,7 @@ def initialize_workflow_tool_agent(chat_session: fastworkflow.ChatSession, max_i
|
|
|
253
326
|
The clarification_request must be plain text without any formatting.
|
|
254
327
|
Note that using the wrong command name can produce missing information errors. Double-check with the what_can_i_do tool to verify that the correct command name is being used
|
|
255
328
|
"""
|
|
329
|
+
chat_session_obj.workflow_tool_agent.iteration_counter = 0 # reset iteration counter, everytime we ask the user
|
|
256
330
|
return _ask_user_tool(clarification_request, chat_session_obj=chat_session_obj)
|
|
257
331
|
|
|
258
332
|
tools = [
|
|
@@ -9,7 +9,7 @@ repository = "https://github.com/radiantlogicinc/fastworkflow"
|
|
|
9
9
|
|
|
10
10
|
[tool.poetry]
|
|
11
11
|
name = "fastworkflow"
|
|
12
|
-
version = "2.17.
|
|
12
|
+
version = "2.17.9"
|
|
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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|