flowcept 0.9.17__tar.gz → 0.9.19__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.
Files changed (224) hide show
  1. {flowcept-0.9.17 → flowcept-0.9.19}/.gitignore +1 -0
  2. {flowcept-0.9.17 → flowcept-0.9.19}/Makefile +4 -4
  3. {flowcept-0.9.17 → flowcept-0.9.19}/PKG-INFO +8 -1
  4. {flowcept-0.9.17 → flowcept-0.9.19}/README.md +1 -0
  5. {flowcept-0.9.17 → flowcept-0.9.19}/deployment/Dockerfile +2 -5
  6. flowcept-0.9.19/docs/agent.rst +43 -0
  7. {flowcept-0.9.17 → flowcept-0.9.19}/docs/index.rst +1 -0
  8. {flowcept-0.9.17 → flowcept-0.9.19}/docs/prov_capture.rst +1 -1
  9. {flowcept-0.9.17 → flowcept-0.9.19}/pyproject.toml +11 -3
  10. {flowcept-0.9.17 → flowcept-0.9.19}/resources/sample_settings.yaml +2 -1
  11. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/agent_client.py +10 -4
  12. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/agents_utils.py +54 -19
  13. flowcept-0.9.19/src/flowcept/agents/flowcept_agent.py +134 -0
  14. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/flowcept_ctx_manager.py +116 -46
  15. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/gui/gui_utils.py +21 -3
  16. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/prompts/general_prompts.py +1 -1
  17. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/prompts/in_memory_query_prompts.py +158 -45
  18. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/tools/general_tools.py +20 -3
  19. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/tools/in_memory_queries/in_memory_queries_tools.py +14 -31
  20. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/docdb_dao/lmdb_dao.py +48 -0
  21. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/keyvalue_dao.py +12 -3
  22. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/mq_dao/mq_dao_base.py +37 -20
  23. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/mq_dao/mq_dao_kafka.py +2 -2
  24. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/mq_dao/mq_dao_redis.py +33 -2
  25. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/flowcept_dataclasses/task_object.py +4 -1
  26. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/configs.py +17 -3
  27. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_api/flowcept_controller.py +5 -1
  28. flowcept-0.9.19/src/flowcept/flowceptor/adapters/mlflow/interception_event_handler.py +50 -0
  29. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/mlflow/mlflow_interceptor.py +18 -4
  30. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/tensorboard/tensorboard_interceptor.py +1 -0
  31. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/consumers/agent/base_agent_context_manager.py +9 -10
  32. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/consumers/base_consumer.py +22 -4
  33. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/consumers/document_inserter.py +22 -1
  34. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/instrumentation/flowcept_task.py +147 -51
  35. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/instrumentation/task_capture.py +10 -1
  36. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/version.py +1 -1
  37. {flowcept-0.9.17 → flowcept-0.9.19}/tests/adapters/test_file_observer.py +4 -1
  38. {flowcept-0.9.17 → flowcept-0.9.19}/tests/adapters/test_mlflow.py +42 -6
  39. flowcept-0.9.19/tests/agent/agent_tests.py +95 -0
  40. flowcept-0.9.19/tests/conftest.py +16 -0
  41. {flowcept-0.9.17 → flowcept-0.9.19}/tests/instrumentation_tests/flowcept_explicit_tasks.py +43 -0
  42. {flowcept-0.9.17 → flowcept-0.9.19}/tests/instrumentation_tests/flowcept_task_decorator_test.py +31 -2
  43. flowcept-0.9.19/tests/misc_tests/__init__.py +0 -0
  44. flowcept-0.9.17/src/flowcept/agents/flowcept_agent.py +0 -30
  45. flowcept-0.9.17/src/flowcept/flowceptor/adapters/mlflow/interception_event_handler.py +0 -19
  46. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/checks.yml +0 -0
  47. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/create-release-n-publish.yml +0 -0
  48. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/run-llm-tests.yml +0 -0
  49. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/run-tests-all-dbs.yml +0 -0
  50. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/run-tests-in-container.yml +0 -0
  51. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/run-tests-kafka.yml +0 -0
  52. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/run-tests-py313.yml +0 -0
  53. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/run-tests-simple.yml +0 -0
  54. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/run-tests.yml +0 -0
  55. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/run_examples.sh +0 -0
  56. {flowcept-0.9.17 → flowcept-0.9.19}/.github/workflows/version_bumper.py +0 -0
  57. {flowcept-0.9.17 → flowcept-0.9.19}/.readthedocs.yaml +0 -0
  58. {flowcept-0.9.17 → flowcept-0.9.19}/CONTRIBUTING.md +0 -0
  59. {flowcept-0.9.17 → flowcept-0.9.19}/LICENSE +0 -0
  60. {flowcept-0.9.17 → flowcept-0.9.19}/deployment/compose-grafana.yml +0 -0
  61. {flowcept-0.9.17 → flowcept-0.9.19}/deployment/compose-kafka.yml +0 -0
  62. {flowcept-0.9.17 → flowcept-0.9.19}/deployment/compose-mofka.yml +0 -0
  63. {flowcept-0.9.17 → flowcept-0.9.19}/deployment/compose-mongo.yml +0 -0
  64. {flowcept-0.9.17 → flowcept-0.9.19}/deployment/compose.yml +0 -0
  65. {flowcept-0.9.17 → flowcept-0.9.19}/docs/api-reference.rst +0 -0
  66. {flowcept-0.9.17 → flowcept-0.9.19}/docs/architecture.rst +0 -0
  67. {flowcept-0.9.17 → flowcept-0.9.19}/docs/cli-reference.rst +0 -0
  68. {flowcept-0.9.17 → flowcept-0.9.19}/docs/conf.py +0 -0
  69. {flowcept-0.9.17 → flowcept-0.9.19}/docs/contributing.rst +0 -0
  70. {flowcept-0.9.17 → flowcept-0.9.19}/docs/img/PROV-AGENT.svg +0 -0
  71. {flowcept-0.9.17 → flowcept-0.9.19}/docs/img/architecture-diagram.png +0 -0
  72. {flowcept-0.9.17 → flowcept-0.9.19}/docs/img/flowcept-logo-dark.png +0 -0
  73. {flowcept-0.9.17 → flowcept-0.9.19}/docs/img/flowcept-logo.png +0 -0
  74. {flowcept-0.9.17 → flowcept-0.9.19}/docs/large_data.rst +0 -0
  75. {flowcept-0.9.17 → flowcept-0.9.19}/docs/prov_query.rst +0 -0
  76. {flowcept-0.9.17 → flowcept-0.9.19}/docs/prov_storage.rst +0 -0
  77. {flowcept-0.9.17 → flowcept-0.9.19}/docs/publications/README.md +0 -0
  78. {flowcept-0.9.17 → flowcept-0.9.19}/docs/quick_start.rst +0 -0
  79. {flowcept-0.9.17 → flowcept-0.9.19}/docs/schemas.rst +0 -0
  80. {flowcept-0.9.17 → flowcept-0.9.19}/docs/setup.rst +0 -0
  81. {flowcept-0.9.17 → flowcept-0.9.19}/docs/task_schema.rst +0 -0
  82. {flowcept-0.9.17 → flowcept-0.9.19}/docs/telemetry_capture.rst +0 -0
  83. {flowcept-0.9.17 → flowcept-0.9.19}/docs/workflow_schema.rst +0 -0
  84. {flowcept-0.9.17 → flowcept-0.9.19}/examples/agents/a2a/README.md +0 -0
  85. {flowcept-0.9.17 → flowcept-0.9.19}/examples/agents/a2a/agent1.py +0 -0
  86. {flowcept-0.9.17 → flowcept-0.9.19}/examples/agents/a2a/agent2.py +0 -0
  87. {flowcept-0.9.17 → flowcept-0.9.19}/examples/agents/aec_agent_context_manager.py +0 -0
  88. {flowcept-0.9.17 → flowcept-0.9.19}/examples/agents/aec_agent_mock.py +0 -0
  89. {flowcept-0.9.17 → flowcept-0.9.19}/examples/agents/aec_prompts.py +0 -0
  90. {flowcept-0.9.17 → flowcept-0.9.19}/examples/agents/opt_driver_mock.py +0 -0
  91. {flowcept-0.9.17 → flowcept-0.9.19}/examples/consumers/ping_pong_example.py +0 -0
  92. {flowcept-0.9.17 → flowcept-0.9.19}/examples/consumers/simple_consumer.py +0 -0
  93. {flowcept-0.9.17 → flowcept-0.9.19}/examples/consumers/simple_publisher.py +0 -0
  94. {flowcept-0.9.17 → flowcept-0.9.19}/examples/convergence_loop_example.py +0 -0
  95. {flowcept-0.9.17 → flowcept-0.9.19}/examples/dask_example.py +0 -0
  96. {flowcept-0.9.17 → flowcept-0.9.19}/examples/distributed_consumer_example.py +0 -0
  97. {flowcept-0.9.17 → flowcept-0.9.19}/examples/instrumented_loop_example.py +0 -0
  98. {flowcept-0.9.17 → flowcept-0.9.19}/examples/instrumented_simple_example.py +0 -0
  99. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_complex/README.md +0 -0
  100. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_complex/custom_provenance_id_mapping.yaml +0 -0
  101. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_complex/llm_dataprep.py +0 -0
  102. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_complex/llm_main_example.py +0 -0
  103. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_complex/llm_model.py +0 -0
  104. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_complex/llm_test_runner.py +0 -0
  105. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_tutorial/README.md +0 -0
  106. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_tutorial/analysis.ipynb +0 -0
  107. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_tutorial/llm_dataprep.py +0 -0
  108. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_tutorial/llm_model.py +0 -0
  109. {flowcept-0.9.17 → flowcept-0.9.19}/examples/llm_tutorial/llm_train_campaign.py +0 -0
  110. {flowcept-0.9.17 → flowcept-0.9.19}/examples/mlflow_example.py +0 -0
  111. {flowcept-0.9.17 → flowcept-0.9.19}/examples/mqtt_example.py +0 -0
  112. {flowcept-0.9.17 → flowcept-0.9.19}/examples/single_layer_perceptron_example.py +0 -0
  113. {flowcept-0.9.17 → flowcept-0.9.19}/examples/start_here.py +0 -0
  114. {flowcept-0.9.17 → flowcept-0.9.19}/examples/tensorboard_example.py +0 -0
  115. {flowcept-0.9.17 → flowcept-0.9.19}/examples/unmanaged/main.py +0 -0
  116. {flowcept-0.9.17 → flowcept-0.9.19}/examples/unmanaged/simple_task.py +0 -0
  117. {flowcept-0.9.17 → flowcept-0.9.19}/notebooks/analytics.ipynb +0 -0
  118. {flowcept-0.9.17 → flowcept-0.9.19}/notebooks/dask.ipynb +0 -0
  119. {flowcept-0.9.17 → flowcept-0.9.19}/notebooks/dask_from_CLI.ipynb +0 -0
  120. {flowcept-0.9.17 → flowcept-0.9.19}/notebooks/mlflow.ipynb +0 -0
  121. {flowcept-0.9.17 → flowcept-0.9.19}/notebooks/reset_dask_nb_exec_counts.py +0 -0
  122. {flowcept-0.9.17 → flowcept-0.9.19}/notebooks/tensorboard.ipynb +0 -0
  123. {flowcept-0.9.17 → flowcept-0.9.19}/resources/mofka/bedrock_setup.sh +0 -0
  124. {flowcept-0.9.17 → flowcept-0.9.19}/resources/mofka/consumer.py +0 -0
  125. {flowcept-0.9.17 → flowcept-0.9.19}/resources/mofka/mofka-requirements.yaml +0 -0
  126. {flowcept-0.9.17 → flowcept-0.9.19}/resources/mofka/mofka_config.json +0 -0
  127. {flowcept-0.9.17 → flowcept-0.9.19}/resources/ontology/catalog-v001.xml +0 -0
  128. {flowcept-0.9.17 → flowcept-0.9.19}/resources/ontology/prov_agent.owl +0 -0
  129. {flowcept-0.9.17 → flowcept-0.9.19}/resources/simple_redis_consumer.py +0 -0
  130. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/__init__.py +0 -0
  131. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/__init__.py +0 -0
  132. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/dynamic_schema_tracker.py +0 -0
  133. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/gui/__init__.py +0 -0
  134. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/gui/agent_gui.py +0 -0
  135. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/gui/audio_utils.py +0 -0
  136. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/llms/__init__.py +0 -0
  137. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/llms/claude_gcp.py +0 -0
  138. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/llms/gemini25.py +0 -0
  139. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/prompts/__init__.py +0 -0
  140. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/tools/__init__.py +0 -0
  141. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/tools/in_memory_queries/__init__.py +0 -0
  142. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/agents/tools/in_memory_queries/pandas_agent_utils.py +0 -0
  143. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/analytics/__init__.py +0 -0
  144. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/analytics/analytics_utils.py +0 -0
  145. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/analytics/data_augmentation.py +0 -0
  146. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/analytics/plot.py +0 -0
  147. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/cli.py +0 -0
  148. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/__init__.py +0 -0
  149. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/autoflush_buffer.py +0 -0
  150. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/__init__.py +0 -0
  151. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/docdb_dao/__init__.py +0 -0
  152. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/docdb_dao/docdb_dao_base.py +0 -0
  153. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/docdb_dao/mongodb_dao.py +0 -0
  154. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/mq_dao/__init__.py +0 -0
  155. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/mq_dao/mq_dao_mofka.py +0 -0
  156. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/daos/redis_conn.py +0 -0
  157. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/flowcept_dataclasses/__init__.py +0 -0
  158. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/flowcept_dataclasses/base_settings_dataclasses.py +0 -0
  159. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/flowcept_dataclasses/telemetry.py +0 -0
  160. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/flowcept_dataclasses/workflow_object.py +0 -0
  161. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/flowcept_logger.py +0 -0
  162. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/query_utils.py +0 -0
  163. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/settings_factory.py +0 -0
  164. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/task_data_preprocess.py +0 -0
  165. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/utils.py +0 -0
  166. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/commons/vocabulary.py +0 -0
  167. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_api/__init__.py +0 -0
  168. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_api/db_api.py +0 -0
  169. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_api/task_query_api.py +0 -0
  170. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_webserver/__init__.py +0 -0
  171. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_webserver/app.py +0 -0
  172. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_webserver/resources/__init__.py +0 -0
  173. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_webserver/resources/query_rsrc.py +0 -0
  174. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowcept_webserver/resources/task_messages_rsrc.py +0 -0
  175. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/__init__.py +0 -0
  176. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/__init__.py +0 -0
  177. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/base_interceptor.py +0 -0
  178. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/brokers/__init__.py +0 -0
  179. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/brokers/mqtt_interceptor.py +0 -0
  180. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/dask/__init__.py +0 -0
  181. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/dask/dask_dataclasses.py +0 -0
  182. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/dask/dask_interceptor.py +0 -0
  183. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/dask/dask_plugins.py +0 -0
  184. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/instrumentation_interceptor.py +0 -0
  185. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/interceptor_state_manager.py +0 -0
  186. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/mlflow/__init__.py +0 -0
  187. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/mlflow/mlflow_dao.py +0 -0
  188. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/mlflow/mlflow_dataclasses.py +0 -0
  189. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/tensorboard/__init__.py +0 -0
  190. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/adapters/tensorboard/tensorboard_dataclasses.py +0 -0
  191. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/consumers/__init__.py +0 -0
  192. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/consumers/agent/__init__.py +0 -0
  193. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/consumers/consumer_utils.py +0 -0
  194. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/flowceptor/telemetry_capture.py +0 -0
  195. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/instrumentation/__init__.py +0 -0
  196. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/instrumentation/flowcept_agent_task.py +0 -0
  197. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/instrumentation/flowcept_decorator.py +0 -0
  198. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/instrumentation/flowcept_loop.py +0 -0
  199. {flowcept-0.9.17 → flowcept-0.9.19}/src/flowcept/instrumentation/flowcept_torch.py +0 -0
  200. {flowcept-0.9.17 → flowcept-0.9.19}/tests/__init__.py +0 -0
  201. {flowcept-0.9.17 → flowcept-0.9.19}/tests/adapters/__init__.py +0 -0
  202. {flowcept-0.9.17 → flowcept-0.9.19}/tests/adapters/dask_test_utils.py +0 -0
  203. {flowcept-0.9.17 → flowcept-0.9.19}/tests/adapters/test_broker.py +0 -0
  204. {flowcept-0.9.17 → flowcept-0.9.19}/tests/adapters/test_dask.py +0 -0
  205. {flowcept-0.9.17 → flowcept-0.9.19}/tests/adapters/test_dask_with_context_mgmt.py +0 -0
  206. {flowcept-0.9.17 → flowcept-0.9.19}/tests/adapters/test_tensorboard.py +0 -0
  207. {flowcept-0.9.17/tests/api → flowcept-0.9.19/tests/agent}/__init__.py +0 -0
  208. {flowcept-0.9.17/tests/doc_db_inserter → flowcept-0.9.19/tests/api}/__init__.py +0 -0
  209. {flowcept-0.9.17 → flowcept-0.9.19}/tests/api/db_api_test.py +0 -0
  210. {flowcept-0.9.17 → flowcept-0.9.19}/tests/api/flowcept_api_test.py +0 -0
  211. {flowcept-0.9.17 → flowcept-0.9.19}/tests/api/sample_data.json +0 -0
  212. {flowcept-0.9.17 → flowcept-0.9.19}/tests/api/sample_data_with_telemetry_and_rai.json +0 -0
  213. {flowcept-0.9.17 → flowcept-0.9.19}/tests/api/task_query_api_test.py +0 -0
  214. {flowcept-0.9.17/tests/instrumentation_tests → flowcept-0.9.19/tests/doc_db_inserter}/__init__.py +0 -0
  215. {flowcept-0.9.17 → flowcept-0.9.19}/tests/doc_db_inserter/doc_db_inserter_test.py +0 -0
  216. {flowcept-0.9.17/tests/instrumentation_tests/ml_tests → flowcept-0.9.19/tests/instrumentation_tests}/__init__.py +0 -0
  217. {flowcept-0.9.17 → flowcept-0.9.19}/tests/instrumentation_tests/flowcept_loop_test.py +0 -0
  218. {flowcept-0.9.17/tests/misc_tests → flowcept-0.9.19/tests/instrumentation_tests/ml_tests}/__init__.py +0 -0
  219. {flowcept-0.9.17 → flowcept-0.9.19}/tests/instrumentation_tests/ml_tests/dl_trainer.py +0 -0
  220. {flowcept-0.9.17 → flowcept-0.9.19}/tests/instrumentation_tests/ml_tests/ml_decorator_dask_test.py +0 -0
  221. {flowcept-0.9.17 → flowcept-0.9.19}/tests/instrumentation_tests/ml_tests/ml_decorator_test.py +0 -0
  222. {flowcept-0.9.17 → flowcept-0.9.19}/tests/misc_tests/log_test.py +0 -0
  223. {flowcept-0.9.17 → flowcept-0.9.19}/tests/misc_tests/singleton_test.py +0 -0
  224. {flowcept-0.9.17 → flowcept-0.9.19}/tests/misc_tests/telemetry_test.py +0 -0
@@ -34,3 +34,4 @@ core.*
34
34
 
35
35
  uv.lock
36
36
  examples/flowcept_messages.jsonl
37
+ agents.md
@@ -77,13 +77,13 @@ run:
77
77
  docker run --rm -v $(shell pwd):/flowcept -e KVDB_HOST=flowcept_redis -e MQ_HOST=flowcept_redis -e MONGO_HOST=flowcept_mongo --network flowcept_default -it flowcept
78
78
 
79
79
  tests-in-container-mongo:
80
- docker run --rm -v $(shell pwd):/flowcept -e KVDB_HOST=flowcept_redis -e MQ_HOST=flowcept_redis -e MONGO_HOST=flowcept_mongo -e MONGO_ENABLED=true -e LMDB_ENABLED=false --network flowcept_default flowcept /opt/conda/envs/flowcept/bin/pytest --ignore=tests/instrumentation_tests/ml_tests
80
+ docker run --rm -v $(shell pwd):/flowcept -e KVDB_HOST=flowcept_redis -e MQ_HOST=flowcept_redis -e MONGO_HOST=flowcept_mongo -e MONGO_ENABLED=true -e LMDB_ENABLED=false --network flowcept_default flowcept /opt/conda/envs/flowcept/bin/pytest tests --ignore=tests/instrumentation_tests/ml_tests
81
81
 
82
82
  tests-in-container:
83
- docker run --rm -v $(shell pwd):/flowcept -e KVDB_HOST=flowcept_redis -e MQ_HOST=flowcept_redis -e MONGO_ENABLED=false -e LMDB_ENABLED=true --network flowcept_default flowcept /opt/conda/envs/flowcept/bin/pytest --ignore=tests/instrumentation_tests/ml_tests
83
+ docker run --rm -v $(shell pwd):/flowcept -e KVDB_HOST=flowcept_redis -e MQ_HOST=flowcept_redis -e MONGO_ENABLED=false -e LMDB_ENABLED=true --network flowcept_default flowcept /opt/conda/envs/flowcept/bin/pytest tests --ignore=tests/instrumentation_tests/ml_tests
84
84
 
85
85
  tests-in-container-kafka:
86
- docker run --rm -v $(shell pwd):/flowcept -e KVDB_HOST=flowcept_redis -e MQ_HOST=kafka -e MONGO_HOST=flowcept_mongo -e MQ_PORT=29092 -e MQ_TYPE=kafka -e MONGO_ENABLED=true -e LMDB_ENABLED=false --network flowcept_default flowcept /opt/conda/envs/flowcept/bin/pytest --ignore=tests/instrumentation_tests/ml_tests
86
+ docker run --rm -v $(shell pwd):/flowcept -e KVDB_HOST=flowcept_redis -e MQ_HOST=kafka -e MONGO_HOST=flowcept_mongo -e MQ_PORT=29092 -e MQ_TYPE=kafka -e MONGO_ENABLED=true -e LMDB_ENABLED=false --network flowcept_default flowcept /opt/conda/envs/flowcept/bin/pytest tests --ignore=tests/instrumentation_tests/ml_tests
87
87
 
88
88
  # This command can be removed once we have our CLI
89
89
  liveness:
@@ -115,7 +115,7 @@ services-stop-mofka:
115
115
  # Run unit tests using pytest
116
116
  .PHONY: tests
117
117
  tests:
118
- pytest --ignore=tests/adapters/test_tensorboard.py
118
+ pytest --timeout=300 --ignore=tests/adapters/test_tensorboard.py
119
119
 
120
120
  .PHONY: tests-notebooks
121
121
  tests-notebooks:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowcept
3
- Version: 0.9.17
3
+ Version: 0.9.19
4
4
  Summary: Capture and query workflow provenance data using data observability
5
5
  Author: Oak Ridge National Laboratory
6
6
  License-Expression: MIT
@@ -41,6 +41,7 @@ Requires-Dist: pyarrow; extra == 'all'
41
41
  Requires-Dist: pymongo; extra == 'all'
42
42
  Requires-Dist: pymupdf; extra == 'all'
43
43
  Requires-Dist: pytest; extra == 'all'
44
+ Requires-Dist: pytest-timeout; extra == 'all'
44
45
  Requires-Dist: pyyaml; extra == 'all'
45
46
  Requires-Dist: redis; extra == 'all'
46
47
  Requires-Dist: requests; extra == 'all'
@@ -50,6 +51,7 @@ Requires-Dist: seaborn; extra == 'all'
50
51
  Requires-Dist: sphinx; extra == 'all'
51
52
  Requires-Dist: sqlalchemy; extra == 'all'
52
53
  Requires-Dist: streamlit; extra == 'all'
54
+ Requires-Dist: tabulate; extra == 'all'
53
55
  Requires-Dist: tbparse; extra == 'all'
54
56
  Requires-Dist: tensorboard; extra == 'all'
55
57
  Requires-Dist: tensorflow; extra == 'all'
@@ -69,6 +71,7 @@ Requires-Dist: jupyterlab; extra == 'dev'
69
71
  Requires-Dist: nbmake; extra == 'dev'
70
72
  Requires-Dist: pika; extra == 'dev'
71
73
  Requires-Dist: pytest; extra == 'dev'
74
+ Requires-Dist: pytest-timeout; extra == 'dev'
72
75
  Requires-Dist: pyyaml; extra == 'dev'
73
76
  Requires-Dist: ruff; extra == 'dev'
74
77
  Requires-Dist: sphinx; extra == 'dev'
@@ -94,6 +97,7 @@ Requires-Dist: matplotlib; extra == 'llm-agent'
94
97
  Requires-Dist: mcp[cli]; extra == 'llm-agent'
95
98
  Requires-Dist: pymupdf; extra == 'llm-agent'
96
99
  Requires-Dist: streamlit; extra == 'llm-agent'
100
+ Requires-Dist: tabulate; extra == 'llm-agent'
97
101
  Provides-Extra: llm-agent-audio
98
102
  Requires-Dist: gtts; extra == 'llm-agent-audio'
99
103
  Requires-Dist: langchain-community; extra == 'llm-agent-audio'
@@ -105,6 +109,7 @@ Requires-Dist: pymupdf; extra == 'llm-agent-audio'
105
109
  Requires-Dist: speechrecognition; extra == 'llm-agent-audio'
106
110
  Requires-Dist: streamlit; extra == 'llm-agent-audio'
107
111
  Requires-Dist: streamlit-mic-recorder; extra == 'llm-agent-audio'
112
+ Requires-Dist: tabulate; extra == 'llm-agent-audio'
108
113
  Provides-Extra: llm-google
109
114
  Requires-Dist: google-genai; extra == 'llm-google'
110
115
  Requires-Dist: langchain-community; extra == 'llm-google'
@@ -113,6 +118,7 @@ Requires-Dist: matplotlib; extra == 'llm-google'
113
118
  Requires-Dist: mcp[cli]; extra == 'llm-google'
114
119
  Requires-Dist: pymupdf; extra == 'llm-google'
115
120
  Requires-Dist: streamlit; extra == 'llm-google'
121
+ Requires-Dist: tabulate; extra == 'llm-google'
116
122
  Provides-Extra: lmdb
117
123
  Requires-Dist: lmdb; extra == 'lmdb'
118
124
  Provides-Extra: ml-dev
@@ -180,6 +186,7 @@ Flowcept captures and queries workflow provenance at runtime with minimal code c
180
186
 
181
187
 
182
188
  <h4 align="center">
189
+ <a href="https://flowcept.org">Website</a> &#8226;
183
190
  <a href="https://flowcept.readthedocs.io/">Documentation</a> &#8226;
184
191
  <a href="./docs/publications">Publications</a>
185
192
  </h4>
@@ -31,6 +31,7 @@ Flowcept captures and queries workflow provenance at runtime with minimal code c
31
31
 
32
32
 
33
33
  <h4 align="center">
34
+ <a href="https://flowcept.org">Website</a> &#8226;
34
35
  <a href="https://flowcept.readthedocs.io/">Documentation</a> &#8226;
35
36
  <a href="./docs/publications">Publications</a>
36
37
  </h4>
@@ -1,9 +1,6 @@
1
1
  # Use the command `make build` to build this image.
2
- FROM miniconda:local
3
-
4
- RUN apt-get update && \
5
- apt-get install -y vim curl wget make patch gcc \
6
- && rm -rf /var/lib/apt/lists/*
2
+ # Use conda-forge base image consistently across local/CI.
3
+ FROM condaforge/miniforge3:23.11.0-0
7
4
 
8
5
  WORKDIR /flowcept
9
6
 
@@ -0,0 +1,43 @@
1
+ Flowcept Agent
2
+ ==============
3
+
4
+ The Flowcept Agent is an MCP-powered LLM interface for querying provenance data. It exposes a small set of tools
5
+ (e.g., ``prompt_handler``) that route natural-language questions to in-memory queries over captured task summaries.
6
+
7
+ Online-first design
8
+ ------------------
9
+ Like Flowcept as a whole, the agent is designed to run **while a workflow is still executing**. In online mode,
10
+ it consumes messages from the MQ (typically Redis) so it can respond to queries in near real time. This is the
11
+ recommended setup for interactive RAG/MCP analysis during live runs.
12
+
13
+ Offline (file-based) queries
14
+ ----------------------------
15
+ For simple tests or disconnected environments, the agent can also be initialized from a **JSONL buffer file**.
16
+ In this mode, Flowcept writes messages to disk (``dump_buffer``), and the agent loads the file once at startup
17
+ before serving queries.
18
+
19
+ This is a minimal offline example:
20
+
21
+ .. code-block:: python
22
+
23
+ import json
24
+ from flowcept import Flowcept, flowcept_task
25
+ from flowcept.agents.flowcept_agent import FlowceptAgent
26
+
27
+ @flowcept_task
28
+ def sum_one(x):
29
+ return x + 1
30
+
31
+ # Run a small workflow and dump the buffer to disk
32
+ with Flowcept(start_persistence=False, save_workflow=False, check_safe_stops=False) as f:
33
+ sum_one(1)
34
+ f.dump_buffer("flowcept_buffer.jsonl")
35
+
36
+ # Start the agent from the buffer file and query it
37
+ agent = FlowceptAgent(buffer_path="flowcept_buffer.jsonl")
38
+ agent.start()
39
+ resp = agent.query("how many tasks?")
40
+ print(json.loads(resp))
41
+ agent.stop()
42
+
43
+ In the future, this page will include a full **online** example (live MQ + Redis) and deployment guidance.
@@ -57,6 +57,7 @@ Flowcept
57
57
  quick_start
58
58
  architecture
59
59
  setup
60
+ agent
60
61
  prov_capture
61
62
  telemetry_capture
62
63
  prov_storage
@@ -124,7 +124,7 @@ Optional Arguments
124
124
 
125
125
  When creating a ``Flowcept`` instance (with or without a context manager), you can pass:
126
126
 
127
- - **interceptors**: list of interceptors (e.g., ``"instrumentation"``, ``"dask"``, ``"mlflow"``). Defaults to ``["instrumentation"]`` if enabled.
127
+ - **interceptors**: list of interceptors (e.g., ``"instrumentation"``, ``"dask"``, ``"mlflow"``). Defaults to ``["instrumentation"]`` if enabled. Instrumentation defaults to enabled unless explicitly set to ``false`` in settings.
128
128
  - **bundle_exec_id**: identifier for grouping interceptors. Defaults to ``id(self)``.
129
129
  - **campaign_id**: unique identifier for the campaign. Defaults to a generated UUID.
130
130
  - **workflow_id**: unique identifier for the workflow. Defaults to a generated UUID.
@@ -65,7 +65,7 @@ mlflow = ["mlflow-skinny", "SQLAlchemy", "alembic", "watchdog", "cryptography"]
65
65
  nvidia = ["nvidia-ml-py"]
66
66
  mqtt = ["paho-mqtt"]
67
67
  tensorboard = ["tensorboard", "tensorflow", "tbparse"]
68
- llm_agent = ["mcp[cli]", "langchain_community", "langchain_openai", "streamlit", "PyMuPDF", "matplotlib"]
68
+ llm_agent = ["mcp[cli]", "langchain_community", "langchain_openai", "streamlit", "PyMuPDF", "matplotlib", "tabulate"]
69
69
  llm_google = ["flowcept[llm_agent]", "google-genai"]
70
70
  llm_agent_audio = ["flowcept[llm_agent]", "streamlit-mic-recorder", "SpeechRecognition", "pydub", "gTTS"]
71
71
  # System dependency (required for pydub)
@@ -80,8 +80,9 @@ dev = [
80
80
  "nbmake",
81
81
  "pika",
82
82
  "pytest",
83
+ "pytest-timeout",
83
84
  "ruff",
84
- "pyyaml",
85
+ "pyyaml"
85
86
  ]
86
87
  # Torch and some other ml-specific libs, only used for dev purposes, require the following specific versions.
87
88
  ml_dev = [
@@ -129,5 +130,12 @@ packages = ["src/flowcept"]
129
130
  [tool.hatch.build.targets.wheel.force-include]
130
131
  "resources/sample_settings.yaml" = "resources/sample_settings.yaml"
131
132
 
133
+ [tool.pytest.ini_options]
134
+ filterwarnings = [
135
+ "ignore:websockets\\.legacy is deprecated:DeprecationWarning",
136
+ "ignore:websockets\\.server\\.WebSocketServerProtocol is deprecated:DeprecationWarning",
137
+ "ignore:Use `streamable_http_client` instead\\.:DeprecationWarning",
138
+ ]
139
+
132
140
  [project.scripts]
133
- flowcept = "flowcept.cli:main"
141
+ flowcept = "flowcept.cli:main"
@@ -1,4 +1,4 @@
1
- flowcept_version: 0.9.17 # Version of the Flowcept package. This setting file is compatible with this version.
1
+ flowcept_version: 0.9.19 # Version of the Flowcept package. This setting file is compatible with this version.
2
2
 
3
3
  project:
4
4
  debug: true # Toggle debug mode. This will add a property `debug: true` to all saved data, making it easier to retrieve/delete them later.
@@ -94,6 +94,7 @@ agent:
94
94
  service_provider: '?'
95
95
  model_kwargs: {}
96
96
  audio_enabled: false
97
+ debug: true
97
98
 
98
99
  databases:
99
100
 
@@ -1,4 +1,6 @@
1
1
  import asyncio
2
+ import json
3
+ import re
2
4
  from typing import Dict, List, Callable
3
5
 
4
6
  from flowcept.configs import AGENT_HOST, AGENT_PORT
@@ -48,10 +50,14 @@ def run_tool(
48
50
  result: List[TextContent] = await session.call_tool(tool_name, arguments=kwargs)
49
51
  actual_result = []
50
52
  for r in result.content:
51
- if isinstance(r, str):
52
- actual_result.append(r)
53
- else:
54
- actual_result.append(r.text)
53
+ text = r if isinstance(r, str) else r.text
54
+ try:
55
+ json.loads(text)
56
+ actual_result.append(text)
57
+ except Exception:
58
+ match = re.search(r"Error code:\\s*(\\d+)", text)
59
+ code = int(match.group(1)) if match else 400
60
+ actual_result.append(json.dumps({"code": code, "result": text, "tool_name": tool_name}))
55
61
 
56
62
  return actual_result
57
63
 
@@ -1,4 +1,6 @@
1
1
  import os
2
+ import re
3
+ import unicodedata
2
4
  from typing import Union, Dict
3
5
 
4
6
  from flowcept.flowceptor.consumers.agent.base_agent_context_manager import BaseAgentContextManager
@@ -137,8 +139,8 @@ def build_llm_model(
137
139
  if _service_provider == "sambanova":
138
140
  from langchain_community.llms.sambanova import SambaStudio
139
141
 
140
- os.environ["SAMBASTUDIO_URL"] = AGENT.get("llm_server_url")
141
- os.environ["SAMBASTUDIO_API_KEY"] = AGENT.get("api_key")
142
+ os.environ["SAMBASTUDIO_URL"] = os.environ.get("SAMBASTUDIO_URL", AGENT.get("llm_server_url"))
143
+ os.environ["SAMBASTUDIO_API_KEY"] = os.environ.get("SAMBASTUDIO_API_KEY", AGENT.get("api_key"))
142
144
 
143
145
  llm = SambaStudio(model_kwargs=_model_kwargs)
144
146
  elif _service_provider == "azure":
@@ -153,7 +155,16 @@ def build_llm_model(
153
155
  from langchain_openai import ChatOpenAI
154
156
 
155
157
  api_key = os.environ.get("OPENAI_API_KEY", AGENT.get("api_key", None))
156
- llm = ChatOpenAI(openai_api_key=api_key, **model_kwargs)
158
+ base_url = os.environ.get("OPENAI_BASE_URL", AGENT.get("llm_server_url") or None)
159
+ org = os.environ.get("OPENAI_ORG_ID", AGENT.get("organization", None))
160
+
161
+ init_kwargs = {"api_key": api_key}
162
+ if base_url:
163
+ init_kwargs["base_url"] = base_url
164
+ if org:
165
+ init_kwargs["organization"] = org
166
+
167
+ llm = ChatOpenAI(**init_kwargs, **_model_kwargs)
157
168
  elif _service_provider == "google":
158
169
  if "claude" in _model_kwargs["model"]:
159
170
  api_key = os.environ.get("GOOGLE_API_KEY", AGENT.get("api_key", None))
@@ -166,22 +177,6 @@ def build_llm_model(
166
177
  from flowcept.agents.llms.gemini25 import Gemini25LLM
167
178
 
168
179
  llm = Gemini25LLM(**_model_kwargs)
169
- elif _service_provider == "openai":
170
- from langchain_openai import ChatOpenAI
171
-
172
- api_key = os.environ.get("OPENAI_API_KEY", AGENT.get("api_key"))
173
- base_url = os.environ.get("OPENAI_BASE_URL", AGENT.get("llm_server_url") or None) # optional
174
- org = os.environ.get("OPENAI_ORG_ID", AGENT.get("organization", None)) # optional
175
-
176
- init_kwargs = {"api_key": api_key}
177
- if base_url:
178
- init_kwargs["base_url"] = base_url
179
- if org:
180
- init_kwargs["organization"] = org
181
-
182
- # IMPORTANT: use the merged kwargs so `model` and temps flow through
183
- llm = ChatOpenAI(**init_kwargs, **_model_kwargs)
184
-
185
180
  else:
186
181
  raise Exception("Currently supported providers are sambanova, openai, azure, and google.")
187
182
  if track_tools:
@@ -194,3 +189,43 @@ def build_llm_model(
194
189
  if tool_task:
195
190
  llm.parent_task_id = tool_task.task_id
196
191
  return llm
192
+
193
+
194
+ def normalize_message(user_msg: str) -> str:
195
+ """
196
+ Normalize a user message into a canonical, comparison-friendly form.
197
+
198
+ The function standardizes text by trimming whitespace, applying Unicode
199
+ normalization, normalizing dash characters, collapsing repeated whitespace,
200
+ removing trailing punctuation that does not affect semantics, and converting
201
+ the result to lowercase.
202
+
203
+ Parameters
204
+ ----------
205
+ user_msg : str
206
+ Raw user input message.
207
+
208
+ Returns
209
+ -------
210
+ str
211
+ Normalized message suitable for matching, comparison, or hashing.
212
+ """
213
+ # 1) Strip leading/trailing whitespace
214
+ user_msg = user_msg.strip()
215
+
216
+ # 2) Unicode normalize to avoid weird characters (like fancy quotes, dashes)
217
+ user_msg = unicodedata.normalize("NFKC", user_msg)
218
+
219
+ # 3) Normalize dashes commonly used in chemistry (C–H, C—H, etc.)
220
+ user_msg = user_msg.replace("–", "-").replace("—", "-")
221
+
222
+ # 4) Collapse multiple spaces / newlines into a single space
223
+ user_msg = re.sub(r"\s+", " ", user_msg)
224
+
225
+ # 5) Remove trailing punctuation that doesn't change semantics
226
+ # e.g., "?", "!", "." at the VERY end
227
+ user_msg = re.sub(r"[?!.\s]+$", "", user_msg)
228
+
229
+ user_msg = user_msg.lower()
230
+
231
+ return user_msg
@@ -0,0 +1,134 @@
1
+ import json
2
+ import os
3
+ from threading import Thread
4
+
5
+ from flowcept.agents import check_liveness
6
+ from flowcept.agents.agents_utils import ToolResult
7
+ from flowcept.agents.tools.general_tools import prompt_handler
8
+ from flowcept.agents.agent_client import run_tool
9
+ from flowcept.agents.flowcept_ctx_manager import mcp_flowcept, ctx_manager
10
+ from flowcept.commons.flowcept_logger import FlowceptLogger
11
+ from flowcept.configs import AGENT_HOST, AGENT_PORT, DUMP_BUFFER_PATH, MQ_ENABLED
12
+ from flowcept.flowceptor.consumers.agent.base_agent_context_manager import BaseAgentContextManager
13
+ from uuid import uuid4
14
+
15
+ import uvicorn
16
+
17
+
18
+ class FlowceptAgent:
19
+ """
20
+ Flowcept agent server wrapper with optional offline buffer loading.
21
+ """
22
+
23
+ def __init__(self, buffer_path: str | None = None):
24
+ """
25
+ Initialize a FlowceptAgent.
26
+
27
+ Parameters
28
+ ----------
29
+ buffer_path : str or None
30
+ Optional path to a JSONL buffer file. When MQ is disabled, the agent
31
+ loads this file once at startup.
32
+ """
33
+ self.buffer_path = buffer_path
34
+ self.logger = FlowceptLogger()
35
+ self._server_thread: Thread | None = None
36
+ self._server = None
37
+
38
+ def _load_buffer_once(self) -> int:
39
+ """
40
+ Load messages from a JSONL buffer file into the agent context.
41
+
42
+ Returns
43
+ -------
44
+ int
45
+ Number of messages loaded.
46
+ """
47
+ path = self.buffer_path or DUMP_BUFFER_PATH
48
+ if not os.path.exists(path):
49
+ raise FileNotFoundError(f"Buffer file not found: {path}")
50
+
51
+ count = 0
52
+ self.logger.info(f"Loading agent buffer from {path}")
53
+ if ctx_manager.agent_id is None:
54
+ agent_id = str(uuid4())
55
+ BaseAgentContextManager.agent_id = agent_id
56
+ ctx_manager.agent_id = agent_id
57
+ with open(path, "r") as handle:
58
+ for line in handle:
59
+ line = line.strip()
60
+ if not line:
61
+ continue
62
+ msg_obj = json.loads(line)
63
+ ctx_manager.message_handler(msg_obj)
64
+ count += 1
65
+ self.logger.info(f"Loaded {count} messages from buffer.")
66
+ return count
67
+
68
+ def _run_server(self):
69
+ """Run the MCP server (blocking call)."""
70
+ config = uvicorn.Config(mcp_flowcept.streamable_http_app, host=AGENT_HOST, port=AGENT_PORT, lifespan="on")
71
+ self._server = uvicorn.Server(config)
72
+ self._server.run()
73
+
74
+ def start(self):
75
+ """
76
+ Start the agent server in a background thread.
77
+
78
+ Returns
79
+ -------
80
+ FlowceptAgent
81
+ The current instance.
82
+ """
83
+ if not MQ_ENABLED:
84
+ self._load_buffer_once()
85
+
86
+ self._server_thread = Thread(target=self._run_server, daemon=False)
87
+ self._server_thread.start()
88
+ self.logger.info(f"Flowcept agent server started on {AGENT_HOST}:{AGENT_PORT}")
89
+ return self
90
+
91
+ def stop(self):
92
+ """Stop the agent server and wait briefly for shutdown."""
93
+ if self._server is not None:
94
+ self._server.should_exit = True
95
+ if self._server_thread is not None:
96
+ self._server_thread.join(timeout=5)
97
+
98
+ def wait(self):
99
+ """Block until the server thread exits."""
100
+ if self._server_thread is not None:
101
+ self._server_thread.join()
102
+
103
+ def query(self, message: str) -> ToolResult:
104
+ """
105
+ Send a prompt to the agent's main router tool and return the response.
106
+ """
107
+ try:
108
+ resp = run_tool(tool_name=prompt_handler, kwargs={"message": message})[0]
109
+ except Exception as e:
110
+ return ToolResult(code=400, result=f"Error executing tool prompt_handler: {e}", tool_name="prompt_handler")
111
+
112
+ try:
113
+ return ToolResult(**json.loads(resp))
114
+ except Exception as e:
115
+ return ToolResult(
116
+ code=499,
117
+ result=f"Could not parse tool response as JSON: {resp}",
118
+ extra=str(e),
119
+ tool_name="prompt_handler",
120
+ )
121
+
122
+
123
+ def main():
124
+ """
125
+ Start the MCP server.
126
+ """
127
+ agent = FlowceptAgent().start()
128
+ # Wake up tool call
129
+ print(run_tool(check_liveness, host=AGENT_HOST, port=AGENT_PORT)[0])
130
+ agent.wait()
131
+
132
+
133
+ if __name__ == "__main__":
134
+ main()