fastworkflow 2.15.13__tar.gz → 2.17.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.13 → fastworkflow-2.17.0}/PKG-INFO +4 -2
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/README.md +2 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_can_i_do.py +16 -2
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/wildcard.py +15 -6
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/intent_detection.py +1 -1
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/chat_session.py +117 -54
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/command_context_model.py +73 -7
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/command_executor.py +1 -1
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/command_metadata_api.py +56 -6
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/fastworkflow.env +1 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/fastworkflow.passwords.env +2 -1
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/mcp_server.py +3 -3
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/run/__main__.py +0 -6
- fastworkflow-2.17.0/fastworkflow/run_fastapi_mcp/README.md +300 -0
- fastworkflow-2.17.0/fastworkflow/run_fastapi_mcp/conversation_store.py +391 -0
- fastworkflow-2.17.0/fastworkflow/run_fastapi_mcp/jwt_manager.py +256 -0
- fastworkflow-2.17.0/fastworkflow/run_fastapi_mcp/main.py +1206 -0
- fastworkflow-2.17.0/fastworkflow/run_fastapi_mcp/mcp_specific.py +103 -0
- fastworkflow-2.17.0/fastworkflow/run_fastapi_mcp/redoc_2_standalone_html.py +40 -0
- fastworkflow-2.17.0/fastworkflow/run_fastapi_mcp/utils.py +427 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/workflow_agent.py +3 -2
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/pyproject.toml +9 -3
- fastworkflow-2.15.13/fastworkflow/run_agent/__main__.py +0 -294
- fastworkflow-2.15.13/fastworkflow/run_agent/agent_module.py +0 -194
- fastworkflow-2.15.13/fastworkflow/utils/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/LICENSE +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/.DS_Store +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_commands/.gitkeep +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/abort.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/you_misunderstood.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/go_up.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/reset_context.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_is_current_context.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/_commands/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/command_context_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/_workflows/command_metadata_extraction/parameter_extraction.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/__main__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/ast_class_extractor.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/class_analysis_structures.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/cli_specification.md +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/command_dependency_resolver.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/command_file_generator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/command_file_template.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/command_import_utils.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/command_stub_generator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/context_folder_generator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/context_model_generator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/dependency_manager.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/dir_scanner.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/documentation_generator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/genai_postprocessor.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/inheritance_block_regenerator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/libcst_transformers.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/navigator_stub_generator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/pydantic_model_generator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/build/utterance_generator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/cache_matching.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/cli.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/command_directory.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/command_interfaces.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/command_routing.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/docs/context_modules_prd.txt +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/extended_workflow_example/README.md +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/extended_workflow_example/_commands/WorkItem/get_status.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/extended_workflow_example/_commands/generate_report.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/extended_workflow_example/_commands/startup.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/extended_workflow_example/simple_workflow_template.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/extended_workflow_example/workflow_inheritance_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/hello_world/_commands/README.md +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/hello_world/_commands/add_two_numbers.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/hello_world/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/hello_world/application/add_two_numbers.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_1/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_1/_commands/send_message.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_1/application/send_message.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_2/_commands/User/send_message.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_2/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_2/_commands/startup.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_2/application/user.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_3/_commands/PremiumUser/send_priority_message.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_3/_commands/User/send_message.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_3/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_3/_commands/initialize_user.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_3/application/user.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/_ChatRoom.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/add_user.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/broadcast_message.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/get_current_user.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/list_users.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/ChatRoom/set_current_user.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/_PremiumUser.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/PremiumUser/send_priority_message.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/User/_User.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/User/send_message.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/_commands/set_root_context.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/application/chatroom.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/application/user.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/context_hierarchy_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/messaging_app_4/startup_action.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/calculate.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/cancel_pending_order.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/exchange_delivered_order_items.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_email.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/find_user_id_by_name_zip.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/get_order_details.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/get_product_details.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/get_user_details.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/list_all_product_types.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_address.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_items.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/modify_pending_order_payment.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/modify_user_address.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/return_delivered_order_items.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/_commands/transfer_to_human_agents.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/context_inheritance_model.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/retail_data/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/retail_data/orders.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/retail_data/products.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/retail_data/users.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/calculate.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/cancel_pending_order.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/exchange_delivered_order_items.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_email.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/find_user_id_by_name_zip.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/get_order_details.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/get_product_details.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/get_user_details.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/list_all_product_types.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_address.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_items.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/modify_pending_order_payment.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/modify_user_address.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/return_delivered_order_items.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/think.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/tool.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/tools/transfer_to_human_agents.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/retail_workflow/workflow_description.txt +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/_WorkItem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/add_child_workitem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/get_status.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/go_to_workitem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/mark_as_complete.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_first_child_workitem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_last_child_workitem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_next_workitem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/move_to_previous_workitem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_all_child_workitems.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/remove_child_workitem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/WorkItem/show_schema.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/_commands/startup.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/application/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/application/workitem.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/simple_workflow_template.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/examples/simple_workflow_template/startup_action.json +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/model_pipeline_training.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/refine/__main__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/run/__init__.py +0 -0
- {fastworkflow-2.15.13/fastworkflow/run_agent → fastworkflow-2.17.0/fastworkflow/train}/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/train/__main__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/train/generate_synthetic.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/user_message_queues.py +0 -0
- {fastworkflow-2.15.13/fastworkflow/train → fastworkflow-2.17.0/fastworkflow/utils}/__init__.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/command_dependency_graph.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/context_utils.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/dspy_cache_utils.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/dspy_logger.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/dspy_utils.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/env.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/fuzzy_match.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/generate_param_examples.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/logging.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/parameterize_func_decorator.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/pydantic_model_2_dspy_signature_class.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/python_utils.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/react.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/signatures.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/utils/startup_progress.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.0}/fastworkflow/workflow.py +0 -0
- {fastworkflow-2.15.13 → fastworkflow-2.17.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.17.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.
|
|
@@ -8,6 +8,7 @@ import json
|
|
|
8
8
|
|
|
9
9
|
import fastworkflow
|
|
10
10
|
from fastworkflow.train.generate_synthetic import generate_diverse_utterances
|
|
11
|
+
from fastworkflow.command_context_model import get_workflow_info
|
|
11
12
|
from fastworkflow.command_metadata_api import CommandMetadataAPI
|
|
12
13
|
|
|
13
14
|
class Signature:
|
|
@@ -139,20 +140,33 @@ class ResponseGenerator:
|
|
|
139
140
|
with contextlib.suppress(Exception):
|
|
140
141
|
if fastworkflow.chat_session:
|
|
141
142
|
is_agent_mode = fastworkflow.chat_session.run_as_agent
|
|
142
|
-
|
|
143
|
+
|
|
143
144
|
app_workflow = workflow.context["app_workflow"]
|
|
144
|
-
|
|
145
|
+
|
|
146
|
+
# Get workflow definition
|
|
147
|
+
workflow_info = get_workflow_info(app_workflow.folderpath)
|
|
148
|
+
workflow_def_text = CommandMetadataAPI.get_workflow_definition_display_text(workflow_info)
|
|
149
|
+
|
|
150
|
+
# Get available commands in current context
|
|
151
|
+
commands_text = CommandMetadataAPI.get_command_display_text(
|
|
145
152
|
subject_workflow_path=app_workflow.folderpath,
|
|
146
153
|
cme_workflow_path=workflow.folderpath,
|
|
147
154
|
active_context_name=app_workflow.current_command_context_name,
|
|
148
155
|
for_agents=is_agent_mode,
|
|
149
156
|
)
|
|
157
|
+
|
|
158
|
+
response = f"{workflow_def_text}\n\n{commands_text}"
|
|
150
159
|
|
|
160
|
+
nlu_pipeline_stage = workflow.context.get(
|
|
161
|
+
"NLU_Pipeline_Stage",
|
|
162
|
+
fastworkflow.NLUPipelineStage.INTENT_DETECTION)
|
|
163
|
+
success = nlu_pipeline_stage == fastworkflow.NLUPipelineStage.INTENT_DETECTION
|
|
151
164
|
return fastworkflow.CommandOutput(
|
|
152
165
|
workflow_id=workflow.id,
|
|
153
166
|
command_responses=[
|
|
154
167
|
fastworkflow.CommandResponse(
|
|
155
168
|
response=response,
|
|
169
|
+
success=success
|
|
156
170
|
)
|
|
157
171
|
]
|
|
158
172
|
)
|
|
@@ -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
|
|
@@ -35,7 +35,7 @@ class ChatWorker(Thread):
|
|
|
35
35
|
"""Process messages for the root workflow"""
|
|
36
36
|
try:
|
|
37
37
|
self.chat_session._status = SessionStatus.RUNNING
|
|
38
|
-
workflow =
|
|
38
|
+
workflow = self.chat_session.get_active_workflow()
|
|
39
39
|
logger.debug(f"Started root workflow {workflow.id}")
|
|
40
40
|
|
|
41
41
|
# Run the workflow loop
|
|
@@ -44,39 +44,34 @@ class ChatWorker(Thread):
|
|
|
44
44
|
finally:
|
|
45
45
|
self.chat_session._status = SessionStatus.STOPPED
|
|
46
46
|
# Ensure workflow is popped if thread terminates unexpectedly
|
|
47
|
-
if
|
|
48
|
-
|
|
47
|
+
if self.chat_session.get_active_workflow() is not None:
|
|
48
|
+
self.chat_session.pop_active_workflow()
|
|
49
49
|
|
|
50
50
|
class ChatSession:
|
|
51
|
-
|
|
52
|
-
_workflow_stack: ClassVar[deque[fastworkflow.Workflow]] = deque() # Stack of workflow objects
|
|
53
|
-
|
|
54
|
-
@classmethod
|
|
55
|
-
def get_active_workflow(cls) -> Optional[fastworkflow.Workflow]:
|
|
51
|
+
def get_active_workflow(self) -> Optional[fastworkflow.Workflow]:
|
|
56
52
|
"""Get the currently active workflow (top of stack)"""
|
|
57
|
-
with
|
|
58
|
-
return
|
|
53
|
+
with self._workflow_stack_lock:
|
|
54
|
+
return self._workflow_stack[-1] if self._workflow_stack else None
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
with
|
|
63
|
-
|
|
64
|
-
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]}")
|
|
65
61
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
with
|
|
69
|
-
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:
|
|
70
66
|
return None
|
|
71
|
-
workflow =
|
|
72
|
-
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]}")
|
|
73
69
|
return workflow
|
|
74
70
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
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()
|
|
80
75
|
logger.debug("Workflow stack cleared")
|
|
81
76
|
|
|
82
77
|
def stop_workflow(self) -> None:
|
|
@@ -95,7 +90,7 @@ class ChatSession:
|
|
|
95
90
|
logger.warning("Chat worker thread did not terminate within timeout")
|
|
96
91
|
|
|
97
92
|
# Clear the workflow stack
|
|
98
|
-
|
|
93
|
+
self.clear_workflow_stack()
|
|
99
94
|
|
|
100
95
|
# Reset status to stopped
|
|
101
96
|
self._status = SessionStatus.STOPPED
|
|
@@ -116,6 +111,10 @@ class ChatSession:
|
|
|
116
111
|
A chat session can run multiple workflows that share the same message queues.
|
|
117
112
|
Use start_workflow() to start a specific workflow within this session.
|
|
118
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
|
+
|
|
119
118
|
# Create queues for user messages and command outputs
|
|
120
119
|
self._user_message_queue = Queue()
|
|
121
120
|
self._command_output_queue = Queue()
|
|
@@ -197,7 +196,7 @@ class ChatSession:
|
|
|
197
196
|
|
|
198
197
|
# Check if we need to stop the current workflow
|
|
199
198
|
# Stop if this is a new root workflow (no parent, keep_alive=True)
|
|
200
|
-
current_workflow =
|
|
199
|
+
current_workflow = self.get_active_workflow()
|
|
201
200
|
if (current_workflow and
|
|
202
201
|
parent_workflow_id is None and
|
|
203
202
|
self._keep_alive):
|
|
@@ -244,7 +243,7 @@ class ChatSession:
|
|
|
244
243
|
self._status = SessionStatus.STARTING
|
|
245
244
|
|
|
246
245
|
# Push this workflow as active
|
|
247
|
-
|
|
246
|
+
self.push_active_workflow(workflow)
|
|
248
247
|
|
|
249
248
|
# Initialize workflow tool agent if in agent mode
|
|
250
249
|
# This must happen after pushing the workflow to the stack
|
|
@@ -304,12 +303,12 @@ class ChatSession:
|
|
|
304
303
|
|
|
305
304
|
@property
|
|
306
305
|
def workflow_is_complete(self) -> bool:
|
|
307
|
-
workflow =
|
|
306
|
+
workflow = self.get_active_workflow()
|
|
308
307
|
return workflow.is_complete if workflow else True
|
|
309
308
|
|
|
310
309
|
@workflow_is_complete.setter
|
|
311
310
|
def workflow_is_complete(self, value: bool) -> None:
|
|
312
|
-
if workflow :=
|
|
311
|
+
if workflow := self.get_active_workflow():
|
|
313
312
|
workflow.is_complete = value
|
|
314
313
|
|
|
315
314
|
@property
|
|
@@ -317,21 +316,22 @@ class ChatSession:
|
|
|
317
316
|
"""Return the conversation history."""
|
|
318
317
|
return self._conversation_history
|
|
319
318
|
|
|
320
|
-
def clear_conversation_history(self, trace_filename_suffix: Optional[str] = None) -> None:
|
|
319
|
+
# def clear_conversation_history(self, trace_filename_suffix: Optional[str] = None) -> None:
|
|
320
|
+
def clear_conversation_history(self) -> None:
|
|
321
321
|
"""
|
|
322
322
|
Clear the conversation history.
|
|
323
323
|
This resets the conversation history to an empty state.
|
|
324
324
|
"""
|
|
325
325
|
self._conversation_history = dspy.History(messages=[])
|
|
326
326
|
# Filename for conversation traces
|
|
327
|
-
if trace_filename_suffix:
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
else:
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
+
# )
|
|
335
335
|
|
|
336
336
|
def _run_workflow_loop(self) -> Optional[fastworkflow.CommandOutput]:
|
|
337
337
|
"""
|
|
@@ -341,7 +341,7 @@ class ChatSession:
|
|
|
341
341
|
- All outputs (success or failure) are sent to queue during processing
|
|
342
342
|
"""
|
|
343
343
|
last_output = None
|
|
344
|
-
workflow =
|
|
344
|
+
workflow = self.get_active_workflow()
|
|
345
345
|
|
|
346
346
|
try:
|
|
347
347
|
# Handle startup command/action
|
|
@@ -385,7 +385,7 @@ class ChatSession:
|
|
|
385
385
|
|
|
386
386
|
finally:
|
|
387
387
|
self._status = SessionStatus.STOPPED
|
|
388
|
-
|
|
388
|
+
self.pop_active_workflow()
|
|
389
389
|
logger.debug(f"Workflow {workflow.id if workflow else 'unknown'} completed")
|
|
390
390
|
|
|
391
391
|
return None
|
|
@@ -401,7 +401,7 @@ class ChatSession:
|
|
|
401
401
|
# def _process_mcp_tool_call(self, message: str) -> fastworkflow.CommandOutput:
|
|
402
402
|
# # sourcery skip: class-extract-method, extract-method
|
|
403
403
|
# """Process an MCP tool call message"""
|
|
404
|
-
# workflow =
|
|
404
|
+
# workflow = self.get_active_workflow()
|
|
405
405
|
|
|
406
406
|
# try:
|
|
407
407
|
# # Parse JSON message
|
|
@@ -429,7 +429,7 @@ class ChatSession:
|
|
|
429
429
|
# self.command_output_queue.put(command_output)
|
|
430
430
|
|
|
431
431
|
# # Flush on successful or failed tool call – state may have changed.
|
|
432
|
-
# if workflow :=
|
|
432
|
+
# if workflow := self.get_active_workflow():
|
|
433
433
|
# workflow.flush()
|
|
434
434
|
|
|
435
435
|
# return command_output
|
|
@@ -495,16 +495,21 @@ class ChatSession:
|
|
|
495
495
|
# Create CommandOutput with the agent's response
|
|
496
496
|
command_response = fastworkflow.CommandResponse(response=result_text)
|
|
497
497
|
|
|
498
|
+
conversation_traces = None
|
|
498
499
|
conversation_summary = message
|
|
499
500
|
# Attach actions captured during agent execution as artifacts if available
|
|
500
501
|
if os.path.exists("action.jsonl"):
|
|
501
502
|
with open("action.jsonl", "r", encoding="utf-8") as f:
|
|
502
503
|
actions = [json.loads(line) for line in f if line.strip()]
|
|
503
|
-
conversation_summary = self._extract_conversation_summary(message, actions, result_text)
|
|
504
|
+
conversation_summary, conversation_traces = self._extract_conversation_summary(message, actions, result_text)
|
|
504
505
|
command_response.artifacts["conversation_summary"] = conversation_summary
|
|
505
506
|
|
|
506
507
|
self.conversation_history.messages.append(
|
|
507
|
-
{
|
|
508
|
+
{
|
|
509
|
+
"conversation summary": conversation_summary,
|
|
510
|
+
"conversation_traces": conversation_traces,
|
|
511
|
+
"feedback": None # Initialize feedback slot for this turn
|
|
512
|
+
}
|
|
508
513
|
)
|
|
509
514
|
|
|
510
515
|
command_output = fastworkflow.CommandOutput(
|
|
@@ -514,11 +519,11 @@ class ChatSession:
|
|
|
514
519
|
|
|
515
520
|
# Put output in queue (following same pattern as _process_message)
|
|
516
521
|
if (not command_output.success or self._keep_alive) and \
|
|
517
|
-
|
|
522
|
+
self.command_output_queue:
|
|
518
523
|
self.command_output_queue.put(command_output)
|
|
519
524
|
|
|
520
525
|
# Persist workflow state changes
|
|
521
|
-
if workflow :=
|
|
526
|
+
if workflow := self.get_active_workflow():
|
|
522
527
|
workflow.flush()
|
|
523
528
|
|
|
524
529
|
return command_output
|
|
@@ -529,20 +534,77 @@ class ChatSession:
|
|
|
529
534
|
# command_output = self.profile_invoke_command(message)
|
|
530
535
|
|
|
531
536
|
command_output = self._CommandExecutor.invoke_command(self, message)
|
|
537
|
+
|
|
538
|
+
# Record assistant mode trace to action.jsonl (similar to agent mode in workflow_agent.py)
|
|
539
|
+
# This ensures assistant commands are captured even when interspersed with agent commands
|
|
540
|
+
response_text = ""
|
|
541
|
+
if command_output.command_responses:
|
|
542
|
+
response_text = command_output.command_responses[0].response or ""
|
|
543
|
+
|
|
544
|
+
# Convert parameters to dict if it's a Pydantic model or other complex object
|
|
545
|
+
params = command_output.command_parameters or {}
|
|
546
|
+
if hasattr(params, 'model_dump'):
|
|
547
|
+
params = params.model_dump()
|
|
548
|
+
elif hasattr(params, 'dict'):
|
|
549
|
+
params = params.dict()
|
|
550
|
+
|
|
551
|
+
record = {
|
|
552
|
+
"command": message,
|
|
553
|
+
"command_name": command_output.command_name or "",
|
|
554
|
+
"parameters": params,
|
|
555
|
+
"response": response_text
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
self.conversation_history.messages.append(
|
|
559
|
+
{
|
|
560
|
+
"conversation summary": "assistant_mode_command",
|
|
561
|
+
"conversation_traces": json.dumps(record),
|
|
562
|
+
"feedback": None # Initialize feedback slot for this turn
|
|
563
|
+
}
|
|
564
|
+
)
|
|
565
|
+
|
|
532
566
|
if (not command_output.success or self._keep_alive) and \
|
|
533
567
|
self.command_output_queue:
|
|
534
568
|
self.command_output_queue.put(command_output)
|
|
535
569
|
|
|
536
570
|
# Persist workflow state changes lazily accumulated during message processing.
|
|
537
|
-
if workflow :=
|
|
571
|
+
if workflow := self.get_active_workflow():
|
|
538
572
|
workflow.flush()
|
|
539
573
|
|
|
540
574
|
return command_output
|
|
541
575
|
|
|
542
576
|
def _process_action(self, action: fastworkflow.Action) -> fastworkflow.CommandOutput:
|
|
543
577
|
"""Process a startup action"""
|
|
544
|
-
workflow =
|
|
578
|
+
workflow = self.get_active_workflow()
|
|
545
579
|
command_output = self._CommandExecutor.perform_action(workflow, action)
|
|
580
|
+
|
|
581
|
+
# Record action trace to action.jsonl
|
|
582
|
+
response_text = ""
|
|
583
|
+
if command_output.command_responses:
|
|
584
|
+
response_text = command_output.command_responses[0].response or ""
|
|
585
|
+
|
|
586
|
+
# Convert parameters to dict if it's a Pydantic model or other complex object
|
|
587
|
+
params = action.parameters or {}
|
|
588
|
+
if hasattr(params, 'model_dump'):
|
|
589
|
+
params = params.model_dump()
|
|
590
|
+
elif hasattr(params, 'dict'):
|
|
591
|
+
params = params.dict()
|
|
592
|
+
|
|
593
|
+
record = {
|
|
594
|
+
"command": "process_action",
|
|
595
|
+
"command_name": action.command_name,
|
|
596
|
+
"parameters": params,
|
|
597
|
+
"response": response_text
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
self.conversation_history.messages.append(
|
|
601
|
+
{
|
|
602
|
+
"conversation summary": "process_action command",
|
|
603
|
+
"conversation_traces": json.dumps(record),
|
|
604
|
+
"feedback": None # Initialize feedback slot for this turn
|
|
605
|
+
}
|
|
606
|
+
)
|
|
607
|
+
|
|
546
608
|
if (not command_output.success or self._keep_alive) and \
|
|
547
609
|
self.command_output_queue:
|
|
548
610
|
self.command_output_queue.put(command_output)
|
|
@@ -573,15 +635,16 @@ class ChatSession:
|
|
|
573
635
|
user_query: str, workflow_actions: list[dict[str, str]], final_agent_response: str) -> str:
|
|
574
636
|
"""
|
|
575
637
|
Summarizes conversation based on original user query, workflow actions and agentt response.
|
|
638
|
+
Returns the conversation summary and the log entry
|
|
576
639
|
"""
|
|
577
640
|
# Lets log everything to a file called action_log.jsonl, if it exists
|
|
578
|
-
|
|
641
|
+
conversation_traces = {
|
|
579
642
|
"user_query": user_query,
|
|
580
643
|
"agent_workflow_interactions": workflow_actions,
|
|
581
644
|
"final_agent_response": final_agent_response
|
|
582
645
|
}
|
|
583
|
-
with open(self._conversation_traces_file_name, "a", encoding="utf-8") as f:
|
|
584
|
-
|
|
646
|
+
# with open(self._conversation_traces_file_name, "a", encoding="utf-8") as f:
|
|
647
|
+
# f.write(json.dumps(log_entry) + "\n")
|
|
585
648
|
|
|
586
649
|
class ConversationSummarySignature(dspy.Signature):
|
|
587
650
|
"""
|
|
@@ -601,7 +664,7 @@ class ChatSession:
|
|
|
601
664
|
user_query=user_query,
|
|
602
665
|
workflow_actions=workflow_actions,
|
|
603
666
|
final_agent_response=final_agent_response)
|
|
604
|
-
return prediction.conversation_summary
|
|
667
|
+
return prediction.conversation_summary, json.dumps(conversation_traces)
|
|
605
668
|
|
|
606
669
|
|
|
607
670
|
def profile_invoke_command(self, message: str):
|
|
@@ -2,11 +2,12 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Any
|
|
6
|
+
import os
|
|
5
7
|
from pathlib import Path
|
|
6
|
-
from typing import Any, Optional, Type
|
|
7
8
|
|
|
8
9
|
import fastworkflow
|
|
9
|
-
from fastworkflow.command_directory import
|
|
10
|
+
from fastworkflow.command_directory import get_cached_command_directory
|
|
10
11
|
from fastworkflow.utils import python_utils
|
|
11
12
|
|
|
12
13
|
"""Utility for loading and traversing the single-file workflow command context model.
|
|
@@ -152,10 +153,10 @@ class CommandContextModel:
|
|
|
152
153
|
hierarchy_model_path = Path(self._workflow_path) / "context_hierarchy_model.json"
|
|
153
154
|
if not hierarchy_model_path.is_file():
|
|
154
155
|
return {}
|
|
155
|
-
|
|
156
|
+
|
|
156
157
|
with hierarchy_model_path.open("r") as f:
|
|
157
158
|
hierarchy_data = json.load(f)
|
|
158
|
-
|
|
159
|
+
|
|
159
160
|
return hierarchy_data
|
|
160
161
|
|
|
161
162
|
def _resolve_ancestry(self, hierarchy: dict[str, dict[str, list[str]]]) -> None:
|
|
@@ -205,10 +206,10 @@ class CommandContextModel:
|
|
|
205
206
|
all_ancestors.add(parent)
|
|
206
207
|
grandparents = self.get_ancestor_contexts(parent, visiting.copy(), _hierarchy)
|
|
207
208
|
all_ancestors.update(grandparents)
|
|
208
|
-
|
|
209
|
+
|
|
209
210
|
final_ancestors = sorted(list(all_ancestors))
|
|
210
211
|
self._resolved_ancestors[context_name] = final_ancestors
|
|
211
|
-
|
|
212
|
+
|
|
212
213
|
visiting.remove(context_name)
|
|
213
214
|
|
|
214
215
|
return final_ancestors
|
|
@@ -228,7 +229,7 @@ class CommandContextModel:
|
|
|
228
229
|
# or by being part of a command inheritance structure. If it's not
|
|
229
230
|
# in _command_contexts, it's an unknown/invalid context.
|
|
230
231
|
raise CommandContextModelValidationError(f"Context '{context_name}' not found in model.")
|
|
231
|
-
|
|
232
|
+
|
|
232
233
|
if visiting is None:
|
|
233
234
|
visiting = set()
|
|
234
235
|
|
|
@@ -294,3 +295,68 @@ class CommandContextModel:
|
|
|
294
295
|
return getattr(module, context_metadata.context_class, None)
|
|
295
296
|
else:
|
|
296
297
|
return None
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
# ---------------------------------------------------------------------
|
|
301
|
+
# Workflow info helper (module-level)
|
|
302
|
+
# ---------------------------------------------------------------------
|
|
303
|
+
|
|
304
|
+
def get_workflow_info(chat_session_or_path: fastworkflow.ChatSession | str) -> dict[str, Any]:
|
|
305
|
+
"""
|
|
306
|
+
Return workflow-level metadata for the active workflow in the given chat session or workflow path.
|
|
307
|
+
|
|
308
|
+
Shape:
|
|
309
|
+
{
|
|
310
|
+
"workflow_name": str,
|
|
311
|
+
"available_contexts": list[str],
|
|
312
|
+
"context_inheritance_model": dict,
|
|
313
|
+
"context_hierarchy_model": dict
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
Notes:
|
|
317
|
+
- available_contexts are derived from CommandContextModel.load(workflow_path)
|
|
318
|
+
so they reflect filesystem + inheritance.
|
|
319
|
+
- current context and purpose/description are intentionally omitted.
|
|
320
|
+
- Raw JSON for inheritance (from _commands/context_inheritance_model.json)
|
|
321
|
+
and hierarchy (from context_hierarchy_model.json) is returned verbatim when present.
|
|
322
|
+
"""
|
|
323
|
+
if isinstance(chat_session_or_path, str):
|
|
324
|
+
workflow_path_str = chat_session_or_path
|
|
325
|
+
else:
|
|
326
|
+
workflow_path_str = chat_session_or_path.get_active_workflow().folderpath
|
|
327
|
+
workflow_name = os.path.basename(os.path.abspath(workflow_path_str))
|
|
328
|
+
|
|
329
|
+
available_contexts: list[str]
|
|
330
|
+
inheritance_json: dict[str, Any] = {}
|
|
331
|
+
hierarchy_json: dict[str, Any] = {}
|
|
332
|
+
|
|
333
|
+
try:
|
|
334
|
+
# Derive contexts via consolidated model
|
|
335
|
+
context_model = CommandContextModel.load(workflow_path_str)
|
|
336
|
+
# Do not normalize names beyond keeping what the model exposes
|
|
337
|
+
available_contexts = sorted([key for key in context_model._command_contexts.keys() if key != 'IntentDetection'])
|
|
338
|
+
except Exception:
|
|
339
|
+
available_contexts = ["/"]
|
|
340
|
+
|
|
341
|
+
# Load raw context inheritance model (if present)
|
|
342
|
+
try:
|
|
343
|
+
inheritance_path = Path(workflow_path_str) / "_commands" / "context_inheritance_model.json"
|
|
344
|
+
if inheritance_path.is_file():
|
|
345
|
+
inheritance_json = json.loads(inheritance_path.read_text())
|
|
346
|
+
except Exception:
|
|
347
|
+
inheritance_json = {}
|
|
348
|
+
|
|
349
|
+
# Load raw context hierarchy model (if present)
|
|
350
|
+
try:
|
|
351
|
+
hierarchy_path = Path(workflow_path_str) / "context_hierarchy_model.json"
|
|
352
|
+
if hierarchy_path.is_file():
|
|
353
|
+
hierarchy_json = json.loads(hierarchy_path.read_text())
|
|
354
|
+
except Exception:
|
|
355
|
+
hierarchy_json = {}
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
"workflow_name": workflow_name,
|
|
359
|
+
"available_contexts": available_contexts,
|
|
360
|
+
"context_inheritance_model": inheritance_json,
|
|
361
|
+
"context_hierarchy_model": hierarchy_json,
|
|
362
|
+
}
|
|
@@ -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
|
|