besser-agentic-framework 4.3.2__tar.gz → 4.4.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.
- {besser_agentic_framework-4.3.2/besser_agentic_framework.egg-info → besser_agentic_framework-4.4.0}/PKG-INFO +23 -15
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/agent.py +327 -8
- besser_agentic_framework-4.4.0/baf/core/message.py +115 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/session.py +74 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/state.py +5 -1
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/transition/transition_builder.py +1 -1
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_db.py +214 -5
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/table_overview.py +4 -1
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/exceptions/logger.py +1 -1
- besser_agentic_framework-4.4.0/baf/library/state/__init__.py +23 -0
- besser_agentic_framework-4.4.0/baf/library/state/reasoning_state_library.py +788 -0
- besser_agentic_framework-4.4.0/baf/library/tool/__init__.py +27 -0
- besser_agentic_framework-4.4.0/baf/library/tool/task_tools.py +143 -0
- besser_agentic_framework-4.4.0/baf/library/tool/workspace_tools.py +123 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/transition/events/base_events.py +8 -5
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/llm/llm.py +50 -1
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/llm/llm_openai_api.py +49 -1
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/payload.py +30 -1
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/chat.py +14 -0
- besser_agentic_framework-4.4.0/baf/platforms/websocket/streamlit_ui/reasoning.py +242 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/websocket_callbacks.py +18 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/websocket_platform.py +169 -40
- besser_agentic_framework-4.4.0/baf/reasoning/__init__.py +5 -0
- besser_agentic_framework-4.4.0/baf/reasoning/skill.py +172 -0
- besser_agentic_framework-4.4.0/baf/reasoning/tool.py +382 -0
- besser_agentic_framework-4.4.0/baf/reasoning/workspace.py +309 -0
- besser_agentic_framework-4.4.0/baf/test/components/conftest.py +56 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_core_agent.py +104 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_core_intent_entity.py +106 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_core_message.py +82 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_core_processor.py +47 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_core_property.py +71 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_core_session.py +67 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_core_state.py +123 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_core_transition.py +81 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_library_events.py +78 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_nlp_configurations.py +80 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_nlp_engine.py +65 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_nlp_preprocessing.py +68 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_platforms.py +63 -0
- besser_agentic_framework-4.4.0/baf/test/components/test_workflows.py +132 -0
- besser_agentic_framework-4.4.0/baf/test/dependencies/conftest.py +6 -0
- besser_agentic_framework-4.4.0/baf/test/dependencies/test_core.py +136 -0
- besser_agentic_framework-4.4.0/baf/test/dependencies/test_docs.py +26 -0
- besser_agentic_framework-4.4.0/baf/test/dependencies/test_extras.py +92 -0
- besser_agentic_framework-4.4.0/baf/test/dependencies/test_framework.py +184 -0
- besser_agentic_framework-4.4.0/baf/test/dependencies/test_llms.py +21 -0
- besser_agentic_framework-4.4.0/baf/test/dependencies/test_tensorflow.py +21 -0
- besser_agentic_framework-4.4.0/baf/test/dependencies/test_torch.py +27 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/greetings_agent.py +1 -1
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/llm_agent.py +1 -1
- besser_agentic_framework-4.4.0/baf/test/examples/reasoning_agent.py +84 -0
- besser_agentic_framework-4.4.0/baf/utils/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0/besser_agentic_framework.egg-info}/PKG-INFO +23 -15
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/besser_agentic_framework.egg-info/SOURCES.txt +35 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/besser_agentic_framework.egg-info/requires.txt +33 -13
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/requirements/requirements-core.txt +4 -2
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/requirements/requirements-extras.txt +7 -4
- besser_agentic_framework-4.4.0/requirements/requirements-tensorflow.txt +2 -0
- besser_agentic_framework-4.4.0/requirements/requirements-torch.txt +3 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/setup.cfg +1 -1
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/setup.py +10 -2
- besser_agentic_framework-4.3.2/baf/core/message.py +0 -53
- besser_agentic_framework-4.3.2/requirements/requirements-tensorflow.txt +0 -2
- besser_agentic_framework-4.3.2/requirements/requirements-torch.txt +0 -2
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/LICENSE +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/MANIFEST.in +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/README.md +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/entity/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/entity/entity.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/entity/entity_entry.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/file.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/intent/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/intent/intent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/intent/intent_parameter.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/processors/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/processors/audio_language_detection_processor.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/processors/language_detection_processor.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/processors/processor.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/processors/user_adaptation_processor.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/property.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/transition/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/transition/condition.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/transition/event.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/core/transition/transition.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/db_handler.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/db_connection.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/flow_graph.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/home.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/intent_details.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/monitoring_ui.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/sidebar.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/db/monitoring_ui/utils.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/exceptions/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/exceptions/exceptions.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/coroutine/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/coroutine/async_helpers.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/entity/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/entity/base_entities.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/intent/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/intent/intent_library.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/state/state_library.py +0 -0
- {besser_agentic_framework-4.3.2/baf/library/state → besser_agentic_framework-4.4.0/baf/library/transition}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/transition/condition_functions.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/transition/conditions.py +0 -0
- {besser_agentic_framework-4.3.2/baf/library/transition → besser_agentic_framework-4.4.0/baf/library/transition/events}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/transition/events/github_webhooks_events.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/library/transition/events/gitlab_webhooks_events.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/__init__.py +0 -0
- {besser_agentic_framework-4.3.2/baf/library/transition/events → besser_agentic_framework-4.4.0/baf/nlp/intent_classifier}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/intent_classifier/intent_classifier.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/intent_classifier/intent_classifier_configuration.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/intent_classifier/intent_classifier_prediction.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/intent_classifier/llm_intent_classifier.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/intent_classifier/simple_intent_classifier_pytorch.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/intent_classifier/simple_intent_classifier_tensorflow.py +0 -0
- {besser_agentic_framework-4.3.2/baf/nlp/intent_classifier → besser_agentic_framework-4.4.0/baf/nlp/llm}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/llm/llm_huggingface.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/llm/llm_huggingface_api.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/llm/llm_replicate_api.py +0 -0
- {besser_agentic_framework-4.3.2/baf/nlp/llm → besser_agentic_framework-4.4.0/baf/nlp/ner}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2/baf/nlp/ner → besser_agentic_framework-4.4.0/baf/nlp/ner/base}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/ner/base/any.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/ner/base/datetime.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/ner/base/number.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/ner/matched_parameter.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/ner/ner.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/ner/ner_prediction.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/ner/simple_ner.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/nlp_engine.py +0 -0
- {besser_agentic_framework-4.3.2/baf/nlp/ner/base → besser_agentic_framework-4.4.0/baf/nlp/preprocessing}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/preprocessing/pipelines.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/preprocessing/text_preprocessing.py +0 -0
- {besser_agentic_framework-4.3.2/baf/nlp/preprocessing → besser_agentic_framework-4.4.0/baf/nlp/rag}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/rag/rag.py +0 -0
- {besser_agentic_framework-4.3.2/baf/nlp/rag → besser_agentic_framework-4.4.0/baf/nlp/speech2text}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/speech2text/api_speech2text.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/speech2text/hf_speech2text.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/speech2text/luxasr_speech2text.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/speech2text/openai_speech2text.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/speech2text/speech2text.py +0 -0
- {besser_agentic_framework-4.3.2/baf/nlp/speech2text → besser_agentic_framework-4.4.0/baf/nlp/text2speech}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/text2speech/hf_text2speech.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/text2speech/openai_text2speech.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/text2speech/piper_text2speech.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/text2speech/text2speech.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/nlp/utils.py +0 -0
- {besser_agentic_framework-4.3.2/baf/nlp/text2speech → besser_agentic_framework-4.4.0/baf/platforms}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/a2a_platform.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/agent_card.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/agent_registry.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/client.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/error_handler.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/message_router.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/server.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/a2a/task_protocol.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/github/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/github/github_actions.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/github/github_objects.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/github/github_platform.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/gitlab/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/gitlab/gitlab_actions.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/gitlab/gitlab_objects.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/gitlab/gitlab_platform.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/platform.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/telegram/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/telegram/telegram_platform.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/audio_queue.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/chat_interface_style.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/initialization.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/login.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/message_input.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/profile_selector.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/session_management.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/sidebar.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/streamlit_ui.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/user_db.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/platforms/websocket/streamlit_ui/vars.py +0 -0
- {besser_agentic_framework-4.3.2/baf/platforms → besser_agentic_framework-4.4.0/baf/test}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2/baf/test → besser_agentic_framework-4.4.0/baf/test/components}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2/baf/test/examples → besser_agentic_framework-4.4.0/baf/test/dependencies}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2/baf/test/examples/multiagent → besser_agentic_framework-4.4.0/baf/test/examples}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/a2a_multiagent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/api_speech2text_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/github_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/gitlab_agent.py +0 -0
- {besser_agentic_framework-4.3.2/baf/utils → besser_agentic_framework-4.4.0/baf/test/examples/multiagent}/__init__.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/multiagent/coder_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/multiagent/main_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/multiagent/reviewer_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/rag_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/speech2speech_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/speech2text_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/stargazer_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/telegram_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/text2speech_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/weather_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/test/examples/web_crawl_agent.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/baf/utils/web_crawl.py +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/besser_agentic_framework.egg-info/dependency_links.txt +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/besser_agentic_framework.egg-info/top_level.txt +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/pyproject.toml +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/requirements/requirements-docs.txt +0 -0
- {besser_agentic_framework-4.3.2 → besser_agentic_framework-4.4.0}/requirements/requirements-llms.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: besser-agentic-framework
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4.0
|
|
4
4
|
Summary: BESSER Agentic Framework (BAF)
|
|
5
5
|
Author: Luxembourg Institute of Science and Technology
|
|
6
6
|
License: MIT
|
|
@@ -18,7 +18,8 @@ Requires-Dist: dateparser==1.1.8
|
|
|
18
18
|
Requires-Dist: langdetect==1.0.9
|
|
19
19
|
Requires-Dist: markdownify==1.2.2
|
|
20
20
|
Requires-Dist: nltk==3.9.1
|
|
21
|
-
Requires-Dist: numpy==1.26.4
|
|
21
|
+
Requires-Dist: numpy==1.26.4; python_version < "3.13"
|
|
22
|
+
Requires-Dist: numpy<3,>=2.1; python_version >= "3.13"
|
|
22
23
|
Requires-Dist: pandas==2.3.3
|
|
23
24
|
Requires-Dist: python-telegram-bot==21.0
|
|
24
25
|
Requires-Dist: psycopg2-binary>=2.9.10
|
|
@@ -27,7 +28,8 @@ Requires-Dist: pyvis==0.3.2
|
|
|
27
28
|
Requires-Dist: PyYAML==6.0.2
|
|
28
29
|
Requires-Dist: requests==2.31.0
|
|
29
30
|
Requires-Dist: snowballstemmer==2.2.0
|
|
30
|
-
Requires-Dist: sqlalchemy==2.0.29
|
|
31
|
+
Requires-Dist: sqlalchemy==2.0.29; python_version < "3.13"
|
|
32
|
+
Requires-Dist: sqlalchemy<2.1,>=2.0.31; python_version >= "3.13"
|
|
31
33
|
Requires-Dist: streamlit==1.40.0
|
|
32
34
|
Requires-Dist: streamlit-antd-components==0.3.2
|
|
33
35
|
Requires-Dist: text2num==2.5.0
|
|
@@ -35,16 +37,19 @@ Requires-Dist: websocket-client==1.6.4
|
|
|
35
37
|
Requires-Dist: websockets==11.0.3
|
|
36
38
|
Requires-Dist: bcrypt==4.0.1
|
|
37
39
|
Provides-Extra: extras
|
|
38
|
-
Requires-Dist: spacy==3.7
|
|
40
|
+
Requires-Dist: spacy==3.8.7; extra == "extras"
|
|
39
41
|
Requires-Dist: scikit-learn>=1.7.0; extra == "extras"
|
|
40
42
|
Requires-Dist: librosa==0.10.1; extra == "extras"
|
|
41
43
|
Requires-Dist: SpeechRecognition==3.10.0; extra == "extras"
|
|
42
44
|
Requires-Dist: soundfile==0.13.1; extra == "extras"
|
|
43
45
|
Requires-Dist: opencv-python==4.10.0.84; extra == "extras"
|
|
44
46
|
Requires-Dist: plotly==5.18.0; extra == "extras"
|
|
45
|
-
Requires-Dist: chromadb==0.5.4; extra == "extras"
|
|
46
|
-
Requires-Dist:
|
|
47
|
-
Requires-Dist: langchain
|
|
47
|
+
Requires-Dist: chromadb==0.5.4; python_version < "3.13" and extra == "extras"
|
|
48
|
+
Requires-Dist: chromadb==1.0.0; python_version >= "3.13" and extra == "extras"
|
|
49
|
+
Requires-Dist: langchain==0.2.9; python_version < "3.13" and extra == "extras"
|
|
50
|
+
Requires-Dist: langchain-community==0.2.7; python_version < "3.13" and extra == "extras"
|
|
51
|
+
Requires-Dist: langchain==0.3.10; python_version >= "3.13" and extra == "extras"
|
|
52
|
+
Requires-Dist: langchain-community==0.3.10; python_version >= "3.13" and extra == "extras"
|
|
48
53
|
Requires-Dist: pypdf==4.3.1; extra == "extras"
|
|
49
54
|
Requires-Dist: tiktoken==0.9.0; extra == "extras"
|
|
50
55
|
Provides-Extra: llms
|
|
@@ -53,9 +58,9 @@ Requires-Dist: replicate==0.23.1; extra == "llms"
|
|
|
53
58
|
Requires-Dist: transformers==4.53.0; extra == "llms"
|
|
54
59
|
Provides-Extra: tensorflow
|
|
55
60
|
Requires-Dist: keras==3.12.0; extra == "tensorflow"
|
|
56
|
-
Requires-Dist: tensorflow==2.20.0; extra == "tensorflow"
|
|
61
|
+
Requires-Dist: tensorflow-cpu==2.20.0; extra == "tensorflow"
|
|
57
62
|
Provides-Extra: torch
|
|
58
|
-
Requires-Dist: torch==2.
|
|
63
|
+
Requires-Dist: torch==2.6.0+cpu; extra == "torch"
|
|
59
64
|
Requires-Dist: scikit-learn>=1.7.0; extra == "torch"
|
|
60
65
|
Provides-Extra: docs
|
|
61
66
|
Requires-Dist: sphinx==7.2.3; extra == "docs"
|
|
@@ -64,24 +69,27 @@ Requires-Dist: sphinx-paramlinks==0.6.0; extra == "docs"
|
|
|
64
69
|
Requires-Dist: furo==2023.8.19; extra == "docs"
|
|
65
70
|
Requires-Dist: m2r2==0.3.3; extra == "docs"
|
|
66
71
|
Provides-Extra: all
|
|
67
|
-
Requires-Dist: spacy==3.7
|
|
72
|
+
Requires-Dist: spacy==3.8.7; extra == "all"
|
|
68
73
|
Requires-Dist: scikit-learn>=1.7.0; extra == "all"
|
|
69
74
|
Requires-Dist: librosa==0.10.1; extra == "all"
|
|
70
75
|
Requires-Dist: SpeechRecognition==3.10.0; extra == "all"
|
|
71
76
|
Requires-Dist: soundfile==0.13.1; extra == "all"
|
|
72
77
|
Requires-Dist: opencv-python==4.10.0.84; extra == "all"
|
|
73
78
|
Requires-Dist: plotly==5.18.0; extra == "all"
|
|
74
|
-
Requires-Dist: chromadb==0.5.4; extra == "all"
|
|
75
|
-
Requires-Dist:
|
|
76
|
-
Requires-Dist: langchain
|
|
79
|
+
Requires-Dist: chromadb==0.5.4; python_version < "3.13" and extra == "all"
|
|
80
|
+
Requires-Dist: chromadb==1.0.0; python_version >= "3.13" and extra == "all"
|
|
81
|
+
Requires-Dist: langchain==0.2.9; python_version < "3.13" and extra == "all"
|
|
82
|
+
Requires-Dist: langchain-community==0.2.7; python_version < "3.13" and extra == "all"
|
|
83
|
+
Requires-Dist: langchain==0.3.10; python_version >= "3.13" and extra == "all"
|
|
84
|
+
Requires-Dist: langchain-community==0.3.10; python_version >= "3.13" and extra == "all"
|
|
77
85
|
Requires-Dist: pypdf==4.3.1; extra == "all"
|
|
78
86
|
Requires-Dist: tiktoken==0.9.0; extra == "all"
|
|
79
87
|
Requires-Dist: openai==1.93.0; extra == "all"
|
|
80
88
|
Requires-Dist: replicate==0.23.1; extra == "all"
|
|
81
89
|
Requires-Dist: transformers==4.53.0; extra == "all"
|
|
82
90
|
Requires-Dist: keras==3.12.0; extra == "all"
|
|
83
|
-
Requires-Dist: tensorflow==2.20.0; extra == "all"
|
|
84
|
-
Requires-Dist: torch==2.
|
|
91
|
+
Requires-Dist: tensorflow-cpu==2.20.0; extra == "all"
|
|
92
|
+
Requires-Dist: torch==2.6.0+cpu; extra == "all"
|
|
85
93
|
Requires-Dist: scikit-learn>=1.7.0; extra == "all"
|
|
86
94
|
Dynamic: license-file
|
|
87
95
|
Dynamic: provides-extra
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import importlib
|
|
3
|
+
import inspect
|
|
2
4
|
import json
|
|
3
5
|
import operator
|
|
4
6
|
import threading
|
|
@@ -24,7 +26,7 @@ from baf.db.monitoring_db import MonitoringDB
|
|
|
24
26
|
from baf.exceptions.exceptions import AgentNotTrainedError, DuplicatedEntityError, DuplicatedInitialStateError, \
|
|
25
27
|
DuplicatedIntentError, DuplicatedStateError, InitialStateNotFound
|
|
26
28
|
from baf.exceptions.logger import logger
|
|
27
|
-
from baf.library.transition.events.base_events import ReceiveMessageEvent, ReceiveJSONEvent
|
|
29
|
+
from baf.library.transition.events.base_events import ReceiveMessageEvent, ReceiveJSONEvent, ReceiveFileEvent
|
|
28
30
|
from baf.nlp.intent_classifier.intent_classifier_configuration import IntentClassifierConfiguration, \
|
|
29
31
|
SimpleIntentClassifierConfiguration
|
|
30
32
|
from baf.nlp.intent_classifier.intent_classifier_prediction import IntentClassifierPrediction
|
|
@@ -35,6 +37,7 @@ from baf.platforms.websocket.websocket_platform import WebSocketPlatform
|
|
|
35
37
|
from baf.platforms.github.github_platform import GitHubPlatform
|
|
36
38
|
from baf.platforms.gitlab.gitlab_platform import GitLabPlatform
|
|
37
39
|
from baf.platforms.a2a.a2a_platform import A2APlatform
|
|
40
|
+
from baf.reasoning import Tool, Skill, Workspace
|
|
38
41
|
|
|
39
42
|
|
|
40
43
|
class Agent:
|
|
@@ -66,6 +69,22 @@ class Agent:
|
|
|
66
69
|
global_state_component (dict[State, list[State]]): Dictionary of global state components, where key is initial
|
|
67
70
|
global state and values is set of states in corresponding global component
|
|
68
71
|
processors (list[Processors]): List of processors used by the agent
|
|
72
|
+
_tools (dict[str, Tool]): Tools registered on the agent and exposed
|
|
73
|
+
to the predefined reasoning state. Keyed by tool name. Populated
|
|
74
|
+
by :meth:`add_tool` / :meth:`new_tool` / :meth:`load_tools`, the
|
|
75
|
+
``@agent.tool`` decorator, and indirectly by :meth:`add_workspace`
|
|
76
|
+
/ :meth:`new_workspace` (which register the universal
|
|
77
|
+
``list_directory`` / ``read_file`` and — when at least one
|
|
78
|
+
workspace is writable — ``write_file`` / ``create_file`` /
|
|
79
|
+
``delete_file`` tools).
|
|
80
|
+
_skills (dict[str, Skill]): Markdown-based playbooks the reasoning
|
|
81
|
+
state injects into the system prompt. Keyed by skill name.
|
|
82
|
+
Populated by :meth:`add_skill` / :meth:`new_skill` /
|
|
83
|
+
:meth:`load_skills`.
|
|
84
|
+
_workspaces (dict[str, Workspace]): Filesystem workspaces the agent
|
|
85
|
+
can browse and (when ``writable=True``) modify through the
|
|
86
|
+
universal workspace tools. Keyed by workspace name. Populated
|
|
87
|
+
by :meth:`add_workspace` / :meth:`new_workspace`.
|
|
69
88
|
"""
|
|
70
89
|
|
|
71
90
|
def __init__(
|
|
@@ -94,6 +113,9 @@ class Agent:
|
|
|
94
113
|
self.processors: list[Processor] = []
|
|
95
114
|
self._user_profiles: Any = None
|
|
96
115
|
self._agent_configurations: dict[str, Any] = {}
|
|
116
|
+
self._tools: dict[str, Tool] = {}
|
|
117
|
+
self._skills: dict[str, Skill] = {}
|
|
118
|
+
self._workspaces: dict[str, Workspace] = {}
|
|
97
119
|
|
|
98
120
|
if user_profiles_path:
|
|
99
121
|
self.load_user_profiles(user_profiles_path)
|
|
@@ -121,9 +143,8 @@ class Agent:
|
|
|
121
143
|
|
|
122
144
|
Supported formats are YAML (``.yaml``, ``.yml``).
|
|
123
145
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
.. literalinclude:: ../../../../baf/agent/test/examples/config.yaml
|
|
146
|
+
See ``baf/test/examples/config.yaml`` in the repository for a complete
|
|
147
|
+
example of an agent configuration file.
|
|
127
148
|
|
|
128
149
|
Args:
|
|
129
150
|
path (str): the path to the properties file
|
|
@@ -316,6 +337,267 @@ class Agent:
|
|
|
316
337
|
self.states.append(new_state)
|
|
317
338
|
return new_state
|
|
318
339
|
|
|
340
|
+
# --- Reasoning extension ----------------------------------------------- #
|
|
341
|
+
|
|
342
|
+
def add_tool(self, tool: Tool) -> Tool:
|
|
343
|
+
"""Add an already-constructed :class:`~baf.reasoning.tool.Tool` to the agent.
|
|
344
|
+
|
|
345
|
+
Mirrors :meth:`add_intent`: the caller builds the wrapper, this method
|
|
346
|
+
registers it. Use :meth:`new_tool` when you want to skip the explicit
|
|
347
|
+
``Tool(...)`` construction.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
tool (Tool): the tool wrapper to register.
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
Tool: the registered tool wrapper.
|
|
354
|
+
"""
|
|
355
|
+
if tool.name in self._tools:
|
|
356
|
+
logger.warning(f"[Agent] Replacing existing tool '{tool.name}'")
|
|
357
|
+
self._tools[tool.name] = tool
|
|
358
|
+
logger.info(f"[Agent] Registered tool: {tool.name}")
|
|
359
|
+
return tool
|
|
360
|
+
|
|
361
|
+
def new_tool(self, fn: Callable, name: str = None, description: str = None) -> Tool:
|
|
362
|
+
"""Build a :class:`~baf.reasoning.tool.Tool` from a callable and register it.
|
|
363
|
+
|
|
364
|
+
See :class:`baf.reasoning.tool.Tool` for the auto-introspection rules.
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
fn (Callable): the function to expose. May be a bound method.
|
|
368
|
+
name (str): override the tool's public name. Defaults to ``fn.__name__``.
|
|
369
|
+
description (str): override the description shown to the LLM.
|
|
370
|
+
Defaults to the first line of ``fn.__doc__``.
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
Tool: the registered tool wrapper.
|
|
374
|
+
"""
|
|
375
|
+
return self.add_tool(Tool(fn, name=name, description=description))
|
|
376
|
+
|
|
377
|
+
def load_tools(self, path: str) -> list[Tool]:
|
|
378
|
+
"""Load every public top-level callable from a Python module or folder of modules.
|
|
379
|
+
|
|
380
|
+
``path`` may be a single ``.py`` file or a folder (non-recursive). For
|
|
381
|
+
each module, every callable whose name does not start with ``_`` is
|
|
382
|
+
registered as a tool. Callables imported from other modules are skipped
|
|
383
|
+
— only those *defined* in the loaded module are considered, so importing
|
|
384
|
+
helpers in ``tools.py`` does not pollute the tool registry.
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
path (str): path to a ``.py`` file or to a folder containing them.
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
list[Tool]: the tools that were registered (may be empty).
|
|
391
|
+
"""
|
|
392
|
+
target = Path(path)
|
|
393
|
+
if not target.exists():
|
|
394
|
+
raise FileNotFoundError(f"load_tools: path does not exist: {path}")
|
|
395
|
+
|
|
396
|
+
if target.is_file():
|
|
397
|
+
files = [target]
|
|
398
|
+
else:
|
|
399
|
+
files = sorted(p for p in target.iterdir() if p.is_file() and p.suffix == ".py")
|
|
400
|
+
|
|
401
|
+
registered: list = []
|
|
402
|
+
for file in files:
|
|
403
|
+
module_name = f"baf_loaded_tools_{file.stem}"
|
|
404
|
+
spec = importlib.util.spec_from_file_location(module_name, file)
|
|
405
|
+
if spec is None or spec.loader is None:
|
|
406
|
+
logger.warning(f"[Agent] Could not load tools from {file}: no spec")
|
|
407
|
+
continue
|
|
408
|
+
module = importlib.util.module_from_spec(spec)
|
|
409
|
+
try:
|
|
410
|
+
spec.loader.exec_module(module)
|
|
411
|
+
except Exception as e:
|
|
412
|
+
logger.warning(f"[Agent] Failed to import tools from {file}: {e}")
|
|
413
|
+
continue
|
|
414
|
+
for member_name, member in inspect.getmembers(module):
|
|
415
|
+
if member_name.startswith("_"):
|
|
416
|
+
continue
|
|
417
|
+
if not callable(member):
|
|
418
|
+
continue
|
|
419
|
+
# Skip classes and members imported from other modules.
|
|
420
|
+
if inspect.isclass(member):
|
|
421
|
+
continue
|
|
422
|
+
if getattr(member, "__module__", None) != module.__name__:
|
|
423
|
+
continue
|
|
424
|
+
registered.append(self.new_tool(member))
|
|
425
|
+
return registered
|
|
426
|
+
|
|
427
|
+
def tool(self, fn: Callable = None, *, name: str = None, description: str = None):
|
|
428
|
+
"""Decorator form of :meth:`new_tool`.
|
|
429
|
+
|
|
430
|
+
Usable bare (``@agent.tool``) or with arguments (``@agent.tool(name='x')``).
|
|
431
|
+
"""
|
|
432
|
+
def _wrap(f: Callable) -> Callable:
|
|
433
|
+
self.new_tool(f, name=name, description=description)
|
|
434
|
+
return f
|
|
435
|
+
if fn is None:
|
|
436
|
+
return _wrap
|
|
437
|
+
return _wrap(fn)
|
|
438
|
+
|
|
439
|
+
def add_skill(self, skill: Skill) -> Skill:
|
|
440
|
+
"""Add an already-constructed :class:`~baf.reasoning.skill.Skill` to the agent.
|
|
441
|
+
|
|
442
|
+
Mirrors :meth:`add_intent`. Use :meth:`new_skill` to skip the explicit
|
|
443
|
+
``Skill(...)`` construction (especially convenient for loading from a
|
|
444
|
+
``.md`` file path).
|
|
445
|
+
|
|
446
|
+
Args:
|
|
447
|
+
skill (Skill): the skill to register.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
Skill: the registered skill.
|
|
451
|
+
"""
|
|
452
|
+
if skill.name in self._skills:
|
|
453
|
+
logger.warning(f"[Agent] Replacing existing skill '{skill.name}'")
|
|
454
|
+
self._skills[skill.name] = skill
|
|
455
|
+
logger.info(f"[Agent] Registered skill: {skill.name}")
|
|
456
|
+
return skill
|
|
457
|
+
|
|
458
|
+
def new_skill(self, source: str, name: str = None, description: str = None) -> Skill:
|
|
459
|
+
"""Build a :class:`~baf.reasoning.skill.Skill` and register it.
|
|
460
|
+
|
|
461
|
+
``source`` is either a path to an existing ``.md`` file (loaded via
|
|
462
|
+
:meth:`Skill.from_file`) or a literal markdown string. The path
|
|
463
|
+
detection is automatic.
|
|
464
|
+
|
|
465
|
+
Args:
|
|
466
|
+
source (str): path to a ``.md`` file or the markdown content as a string.
|
|
467
|
+
name (str): override the skill name (otherwise taken from frontmatter,
|
|
468
|
+
a leading H1, or the filename stem).
|
|
469
|
+
description (str): override the description (otherwise taken from
|
|
470
|
+
frontmatter).
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
Skill: the registered skill.
|
|
474
|
+
"""
|
|
475
|
+
candidate = Path(source) if isinstance(source, str) else None
|
|
476
|
+
if candidate is not None and candidate.is_file() and candidate.suffix.lower() == ".md":
|
|
477
|
+
skill = Skill.from_file(str(candidate))
|
|
478
|
+
if name:
|
|
479
|
+
skill.name = name
|
|
480
|
+
if description:
|
|
481
|
+
skill.description = description
|
|
482
|
+
else:
|
|
483
|
+
skill = Skill(source, name=name, description=description)
|
|
484
|
+
return self.add_skill(skill)
|
|
485
|
+
|
|
486
|
+
def load_skills(self, folder: str) -> list[Skill]:
|
|
487
|
+
"""Register every ``*.md`` file in ``folder`` (non-recursive) as a skill.
|
|
488
|
+
|
|
489
|
+
Args:
|
|
490
|
+
folder (str): path to a folder containing markdown files.
|
|
491
|
+
|
|
492
|
+
Returns:
|
|
493
|
+
list[Skill]: the skills that were registered.
|
|
494
|
+
"""
|
|
495
|
+
return [self.add_skill(s) for s in Skill.from_folder(folder)]
|
|
496
|
+
|
|
497
|
+
def add_workspace(self, workspace: Workspace) -> Workspace:
|
|
498
|
+
"""Add an already-constructed :class:`~baf.reasoning.workspace.Workspace` to the agent.
|
|
499
|
+
|
|
500
|
+
The first call also registers the universal ``list_directory`` /
|
|
501
|
+
``read_file`` tools, and — if at least one registered workspace has
|
|
502
|
+
``writable=True`` — the ``write_file`` / ``create_file`` /
|
|
503
|
+
``delete_file`` tools.
|
|
504
|
+
|
|
505
|
+
Mirrors :meth:`add_intent`. Use :meth:`new_workspace` to skip the
|
|
506
|
+
explicit ``Workspace(...)`` construction.
|
|
507
|
+
|
|
508
|
+
Args:
|
|
509
|
+
workspace (Workspace): the workspace to register.
|
|
510
|
+
|
|
511
|
+
Returns:
|
|
512
|
+
Workspace: the registered workspace.
|
|
513
|
+
|
|
514
|
+
Raises:
|
|
515
|
+
ValueError: if a workspace with the same name is already registered.
|
|
516
|
+
"""
|
|
517
|
+
if workspace.name in self._workspaces:
|
|
518
|
+
raise ValueError(f"Workspace '{workspace.name}' is already registered")
|
|
519
|
+
self._workspaces[workspace.name] = workspace
|
|
520
|
+
self._ensure_workspace_tools_registered()
|
|
521
|
+
logger.info(f"[Agent] Registered workspace: {workspace.name} "
|
|
522
|
+
f"(root={workspace.root}, writable={workspace.writable})")
|
|
523
|
+
return workspace
|
|
524
|
+
|
|
525
|
+
def new_workspace(self, path: str, name: str = "workspace",
|
|
526
|
+
description: str = None,
|
|
527
|
+
writable: bool = True,
|
|
528
|
+
max_read_bytes: int = 200_000) -> Workspace:
|
|
529
|
+
"""Build a :class:`~baf.reasoning.workspace.Workspace` and register it.
|
|
530
|
+
|
|
531
|
+
Args:
|
|
532
|
+
path (str): the workspace root path.
|
|
533
|
+
name (str): the workspace identifier the LLM passes as the
|
|
534
|
+
``workspace`` tool argument. Must be unique within the agent.
|
|
535
|
+
description (str): a short human-readable explanation of *what* the
|
|
536
|
+
workspace contains. Strongly recommended — without it the LLM
|
|
537
|
+
only sees the name and root path and may not realise it should
|
|
538
|
+
browse the workspace.
|
|
539
|
+
writable (bool): whether mutating operations are allowed on this
|
|
540
|
+
workspace (``write_file`` / ``create_file`` / ``delete_file``).
|
|
541
|
+
Defaults to True.
|
|
542
|
+
max_read_bytes (int): cap on ``read_file`` output, in bytes.
|
|
543
|
+
|
|
544
|
+
Returns:
|
|
545
|
+
Workspace: the registered workspace.
|
|
546
|
+
"""
|
|
547
|
+
return self.add_workspace(Workspace(
|
|
548
|
+
path, name=name, description=description,
|
|
549
|
+
writable=writable, max_read_bytes=max_read_bytes,
|
|
550
|
+
))
|
|
551
|
+
|
|
552
|
+
def _resolve_workspace(self, name: str = None) -> 'Workspace':
|
|
553
|
+
"""Look up a workspace by name, or pick the only one when ``name`` is None.
|
|
554
|
+
|
|
555
|
+
Raises a ``ValueError`` (which the Tool wrapper turns into an LLM-readable
|
|
556
|
+
ERROR string) on missing or ambiguous lookups.
|
|
557
|
+
"""
|
|
558
|
+
if name is None:
|
|
559
|
+
if len(self._workspaces) == 1:
|
|
560
|
+
return next(iter(self._workspaces.values()))
|
|
561
|
+
if not self._workspaces:
|
|
562
|
+
raise ValueError("No workspaces are registered")
|
|
563
|
+
raise ValueError(
|
|
564
|
+
f"Multiple workspaces are registered, please specify one of: "
|
|
565
|
+
f"{list(self._workspaces.keys())}"
|
|
566
|
+
)
|
|
567
|
+
if name not in self._workspaces:
|
|
568
|
+
raise ValueError(
|
|
569
|
+
f"Workspace '{name}' not found. Available: {list(self._workspaces.keys())}"
|
|
570
|
+
)
|
|
571
|
+
return self._workspaces[name]
|
|
572
|
+
|
|
573
|
+
def _ensure_workspace_tools_registered(self) -> None:
|
|
574
|
+
"""Register the universal workspace tools.
|
|
575
|
+
|
|
576
|
+
Read tools (``list_directory``, ``read_file``) are registered as soon
|
|
577
|
+
as any workspace exists. Write tools (``write_file``, ``create_file``,
|
|
578
|
+
``delete_file``) are registered only once at least one workspace has
|
|
579
|
+
``writable=True`` — read-only-only setups never expose them to the LLM.
|
|
580
|
+
|
|
581
|
+
The tool callables themselves live in
|
|
582
|
+
:mod:`baf.library.tool.workspace_tools`. This method only owns the
|
|
583
|
+
gating policy (which family to expose, when) plus the dedup check.
|
|
584
|
+
Idempotent — already-registered tools are skipped.
|
|
585
|
+
"""
|
|
586
|
+
# Imported lazily to avoid pulling baf.library.tool at module load time.
|
|
587
|
+
from baf.library.tool.workspace_tools import (
|
|
588
|
+
build_workspace_read_tools,
|
|
589
|
+
build_workspace_write_tools,
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
for fn in build_workspace_read_tools(self):
|
|
593
|
+
if fn.__name__ not in self._tools:
|
|
594
|
+
self.new_tool(fn)
|
|
595
|
+
|
|
596
|
+
if any(ws.writable for ws in self._workspaces.values()):
|
|
597
|
+
for fn in build_workspace_write_tools(self):
|
|
598
|
+
if fn.__name__ not in self._tools:
|
|
599
|
+
self.new_tool(fn)
|
|
600
|
+
|
|
319
601
|
def add_intent(self, intent: Intent) -> Intent:
|
|
320
602
|
"""Add an intent to the agent.
|
|
321
603
|
|
|
@@ -534,6 +816,9 @@ class Agent:
|
|
|
534
816
|
else:
|
|
535
817
|
t = MessageType.STR
|
|
536
818
|
session.save_message(Message(t=t, content=event.message, is_user=True, timestamp=datetime.now()))
|
|
819
|
+
if isinstance(event, ReceiveFileEvent):
|
|
820
|
+
session.save_message(Message(t=MessageType.FILE, content=event.file.get_json_string(), is_user=True, timestamp=datetime.now()))
|
|
821
|
+
|
|
537
822
|
logger.info(f'Received event: {event.log()}')
|
|
538
823
|
|
|
539
824
|
def process(self, session: Session, message: Any, is_user_message: bool) -> Any:
|
|
@@ -602,12 +887,14 @@ class Agent:
|
|
|
602
887
|
else:
|
|
603
888
|
return None
|
|
604
889
|
|
|
605
|
-
def _new_session(self, session_id: str, platform: Platform) -> Session:
|
|
890
|
+
def _new_session(self, session_id: str, platform: Platform, username: str or None = None, session_name: str or None = None) -> Session:
|
|
606
891
|
"""Create a new session for the agent.
|
|
607
892
|
|
|
608
893
|
Args:
|
|
609
894
|
session_id (str): the session id
|
|
610
895
|
platform (Platform): the platform where the session is to be created and used
|
|
896
|
+
username (str): the name of the session user (optional)
|
|
897
|
+
session_name (str): the name of the session (optional)
|
|
611
898
|
|
|
612
899
|
Returns:
|
|
613
900
|
Session: the session
|
|
@@ -616,7 +903,7 @@ class Agent:
|
|
|
616
903
|
raise ValueError(f'Trying to create a new session with an existing id" {session_id}')
|
|
617
904
|
if platform not in self._platforms:
|
|
618
905
|
raise ValueError(f"Platform {platform.__class__.__name__} not found in agent '{self.name}'")
|
|
619
|
-
session = Session(session_id, self, platform)
|
|
906
|
+
session = Session(session_id, self, platform, username, session_name)
|
|
620
907
|
self._sessions[session_id] = session
|
|
621
908
|
if self._persist_sessions and self._monitoring_db_session_exists(session_id, platform):
|
|
622
909
|
dest_state = self._monitoring_db_get_last_state_of_session(session_id, platform)
|
|
@@ -635,10 +922,10 @@ class Agent:
|
|
|
635
922
|
session._run_event_thread()
|
|
636
923
|
return session
|
|
637
924
|
|
|
638
|
-
def get_or_create_session(self, session_id: str, platform: Platform) -> Session:
|
|
925
|
+
def get_or_create_session(self, session_id: str, platform: Platform, username: str or None = None, session_name: str or None = None) -> Session:
|
|
639
926
|
session = self._get_session(session_id)
|
|
640
927
|
if session is None:
|
|
641
|
-
session = self._new_session(session_id, platform)
|
|
928
|
+
session = self._new_session(session_id, platform, username, session_name)
|
|
642
929
|
return session
|
|
643
930
|
|
|
644
931
|
def close_session(self, session_id: str) -> None:
|
|
@@ -854,6 +1141,38 @@ class Agent:
|
|
|
854
1141
|
thread = threading.Thread(target=self._monitoring_db.insert_chat, args=(session, message))
|
|
855
1142
|
thread.start()
|
|
856
1143
|
|
|
1144
|
+
def _monitoring_db_insert_reasoning_event(
|
|
1145
|
+
self,
|
|
1146
|
+
session: Session,
|
|
1147
|
+
kind: str,
|
|
1148
|
+
payload: Any,
|
|
1149
|
+
) -> None:
|
|
1150
|
+
"""Insert a reasoning-state event (step or task-list snapshot) into the
|
|
1151
|
+
dedicated ``reasoning_step`` table. Synchronous on purpose so a
|
|
1152
|
+
subsequent ``link_pending_reasoning_events`` call sees the row.
|
|
1153
|
+
"""
|
|
1154
|
+
if self.get_property(DB_MONITORING) and self._monitoring_db.connected:
|
|
1155
|
+
self._monitoring_db.insert_reasoning_event(session, kind, payload)
|
|
1156
|
+
|
|
1157
|
+
def _monitoring_db_select_reasoning_events(
|
|
1158
|
+
self,
|
|
1159
|
+
session: Session,
|
|
1160
|
+
until_timestamp=None,
|
|
1161
|
+
):
|
|
1162
|
+
"""Fetch all reasoning events for a session, in chronological order."""
|
|
1163
|
+
if self.get_property(DB_MONITORING) and self._monitoring_db.connected:
|
|
1164
|
+
return self._monitoring_db.select_reasoning_events(
|
|
1165
|
+
session, until_timestamp=until_timestamp,
|
|
1166
|
+
)
|
|
1167
|
+
return None
|
|
1168
|
+
|
|
1169
|
+
def _monitoring_db_link_pending_reasoning_events(self, session: Session) -> None:
|
|
1170
|
+
"""Attach reasoning events with chat_id IS NULL to the most recent
|
|
1171
|
+
chat row for ``session``. Best-effort, called at the end of every
|
|
1172
|
+
reasoning loop."""
|
|
1173
|
+
if self.get_property(DB_MONITORING) and self._monitoring_db.connected:
|
|
1174
|
+
self._monitoring_db.link_pending_reasoning_events(session)
|
|
1175
|
+
|
|
857
1176
|
def _monitoring_db_insert_event(self, event: Event) -> None:
|
|
858
1177
|
"""Insert an event record into the monitoring database.
|
|
859
1178
|
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from baf.platforms.payload import PayloadAction
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MessageType(Enum):
|
|
9
|
+
"""Enumeration of the different message types in :class:`Message`."""
|
|
10
|
+
|
|
11
|
+
STR = 'str'
|
|
12
|
+
JSON = 'json'
|
|
13
|
+
MARKDOWN = 'markdown'
|
|
14
|
+
HTML = 'html'
|
|
15
|
+
FILE = 'file'
|
|
16
|
+
IMAGE = 'image'
|
|
17
|
+
DATAFRAME = 'dataframe'
|
|
18
|
+
PLOTLY = 'plotly'
|
|
19
|
+
LOCATION = 'location'
|
|
20
|
+
OPTIONS = 'options'
|
|
21
|
+
AUDIO = 'audio'
|
|
22
|
+
RAG_ANSWER = 'rag_answer'
|
|
23
|
+
UI = 'ui'
|
|
24
|
+
REASONING_TRACE = 'reasoning_trace' # UI-internal synthetic type aggregating streamed reasoning_step / task_list_update events
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_message_type(value: str):
|
|
28
|
+
for message_type in MessageType:
|
|
29
|
+
if message_type.value == value:
|
|
30
|
+
return message_type
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Message:
|
|
35
|
+
"""
|
|
36
|
+
A conversation message. It is used by the streamlit UI to display the messages properly, depending on the sender
|
|
37
|
+
(i.e., user or agent) and the type (string, audio, file, DataFrame, plot, etc.)
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
t (MessageType): The type of the message
|
|
41
|
+
content (Any): The message content
|
|
42
|
+
is_user (bool): Whether the message comes from the user (true) or the agent (false)
|
|
43
|
+
timestamp (datetime): The timestamp of the message (when the message was sent)
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
type (MessageType): The type of the message
|
|
47
|
+
content (Any): The message content
|
|
48
|
+
is_user (bool): Whether the message comes from the user (true) or the agent (false)
|
|
49
|
+
timestamp (datetime): The timestamp of the message (when the message was sent)
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(self, t: MessageType, content: Any, is_user: bool, timestamp: datetime):
|
|
53
|
+
self.type: MessageType = t
|
|
54
|
+
self.content: Any = content
|
|
55
|
+
self.is_user: bool = is_user
|
|
56
|
+
self.timestamp: datetime = timestamp
|
|
57
|
+
# TODO: Parse content to specific type (in DB, messages are stored a str)
|
|
58
|
+
|
|
59
|
+
def get_action(self):
|
|
60
|
+
if self.is_user:
|
|
61
|
+
match self.type:
|
|
62
|
+
case MessageType.STR:
|
|
63
|
+
return PayloadAction.USER_MESSAGE
|
|
64
|
+
case MessageType.JSON:
|
|
65
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
66
|
+
case MessageType.MARKDOWN:
|
|
67
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
68
|
+
case MessageType.HTML:
|
|
69
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
70
|
+
case MessageType.FILE:
|
|
71
|
+
return PayloadAction.USER_FILE
|
|
72
|
+
case MessageType.IMAGE:
|
|
73
|
+
return PayloadAction.USER_FILE # TODO: Not implemented
|
|
74
|
+
case MessageType.DATAFRAME:
|
|
75
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
76
|
+
case MessageType.PLOTLY:
|
|
77
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
78
|
+
case MessageType.LOCATION:
|
|
79
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
80
|
+
case MessageType.OPTIONS:
|
|
81
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
82
|
+
case MessageType.AUDIO:
|
|
83
|
+
return PayloadAction.USER_VOICE
|
|
84
|
+
case MessageType.RAG_ANSWER:
|
|
85
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
86
|
+
case MessageType.UI:
|
|
87
|
+
return PayloadAction.USER_MESSAGE # TODO: Not implemented
|
|
88
|
+
else:
|
|
89
|
+
match self.type:
|
|
90
|
+
case MessageType.STR:
|
|
91
|
+
return PayloadAction.AGENT_REPLY_STR
|
|
92
|
+
case MessageType.JSON:
|
|
93
|
+
return PayloadAction.AGENT_REPLY_STR # TODO: Not implemented
|
|
94
|
+
case MessageType.MARKDOWN:
|
|
95
|
+
return PayloadAction.AGENT_REPLY_MARKDOWN
|
|
96
|
+
case MessageType.HTML:
|
|
97
|
+
return PayloadAction.AGENT_REPLY_HTML
|
|
98
|
+
case MessageType.FILE:
|
|
99
|
+
return PayloadAction.AGENT_REPLY_FILE
|
|
100
|
+
case MessageType.IMAGE:
|
|
101
|
+
return PayloadAction.AGENT_REPLY_IMAGE
|
|
102
|
+
case MessageType.DATAFRAME:
|
|
103
|
+
return PayloadAction.AGENT_REPLY_DF
|
|
104
|
+
case MessageType.PLOTLY:
|
|
105
|
+
return PayloadAction.AGENT_REPLY_PLOTLY
|
|
106
|
+
case MessageType.LOCATION:
|
|
107
|
+
return PayloadAction.AGENT_REPLY_LOCATION
|
|
108
|
+
case MessageType.OPTIONS:
|
|
109
|
+
return PayloadAction.AGENT_REPLY_OPTIONS
|
|
110
|
+
case MessageType.AUDIO:
|
|
111
|
+
return PayloadAction.AGENT_REPLY_AUDIO
|
|
112
|
+
case MessageType.RAG_ANSWER:
|
|
113
|
+
return PayloadAction.AGENT_REPLY_RAG
|
|
114
|
+
case MessageType.UI:
|
|
115
|
+
return PayloadAction.AGENT_REPLY_UI
|