flock-core 0.5.0b27__py3-none-any.whl → 0.5.0b50__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of flock-core might be problematic. Click here for more details.

Files changed (357) hide show
  1. flock/__init__.py +12 -217
  2. flock/agent.py +678 -0
  3. flock/api/themes.py +71 -0
  4. flock/artifacts.py +79 -0
  5. flock/cli.py +75 -0
  6. flock/components.py +173 -0
  7. flock/dashboard/__init__.py +28 -0
  8. flock/dashboard/collector.py +283 -0
  9. flock/dashboard/events.py +182 -0
  10. flock/dashboard/launcher.py +230 -0
  11. flock/dashboard/service.py +537 -0
  12. flock/dashboard/websocket.py +235 -0
  13. flock/engines/__init__.py +6 -0
  14. flock/engines/dspy_engine.py +856 -0
  15. flock/examples.py +128 -0
  16. flock/{core/util → helper}/cli_helper.py +4 -3
  17. flock/{core/logging → logging}/__init__.py +2 -3
  18. flock/{core/logging → logging}/formatters/enum_builder.py +3 -4
  19. flock/{core/logging → logging}/formatters/theme_builder.py +19 -44
  20. flock/{core/logging → logging}/formatters/themed_formatter.py +69 -115
  21. flock/{core/logging → logging}/logging.py +77 -61
  22. flock/{core/logging → logging}/telemetry.py +20 -26
  23. flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
  24. flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +6 -9
  25. flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
  26. flock/{core/logging → logging}/trace_and_logged.py +20 -24
  27. flock/mcp/__init__.py +91 -0
  28. flock/{core/mcp/mcp_client.py → mcp/client.py} +103 -154
  29. flock/{core/mcp/mcp_config.py → mcp/config.py} +62 -117
  30. flock/mcp/manager.py +255 -0
  31. flock/mcp/servers/sse/__init__.py +1 -1
  32. flock/mcp/servers/sse/flock_sse_server.py +11 -53
  33. flock/mcp/servers/stdio/__init__.py +1 -1
  34. flock/mcp/servers/stdio/flock_stdio_server.py +8 -48
  35. flock/mcp/servers/streamable_http/flock_streamable_http_server.py +17 -62
  36. flock/mcp/servers/websockets/flock_websocket_server.py +7 -40
  37. flock/{core/mcp/flock_mcp_tool.py → mcp/tool.py} +16 -26
  38. flock/mcp/types/__init__.py +42 -0
  39. flock/{core/mcp → mcp}/types/callbacks.py +9 -15
  40. flock/{core/mcp → mcp}/types/factories.py +7 -6
  41. flock/{core/mcp → mcp}/types/handlers.py +13 -18
  42. flock/{core/mcp → mcp}/types/types.py +70 -74
  43. flock/{core/mcp → mcp}/util/helpers.py +1 -1
  44. flock/orchestrator.py +645 -0
  45. flock/registry.py +148 -0
  46. flock/runtime.py +262 -0
  47. flock/service.py +140 -0
  48. flock/store.py +69 -0
  49. flock/subscription.py +111 -0
  50. flock/themes/andromeda.toml +1 -1
  51. flock/themes/apple-system-colors.toml +1 -1
  52. flock/themes/arcoiris.toml +1 -1
  53. flock/themes/atomonelight.toml +1 -1
  54. flock/themes/ayu copy.toml +1 -1
  55. flock/themes/ayu-light.toml +1 -1
  56. flock/themes/belafonte-day.toml +1 -1
  57. flock/themes/belafonte-night.toml +1 -1
  58. flock/themes/blulocodark.toml +1 -1
  59. flock/themes/breeze.toml +1 -1
  60. flock/themes/broadcast.toml +1 -1
  61. flock/themes/brogrammer.toml +1 -1
  62. flock/themes/builtin-dark.toml +1 -1
  63. flock/themes/builtin-pastel-dark.toml +1 -1
  64. flock/themes/catppuccin-latte.toml +1 -1
  65. flock/themes/catppuccin-macchiato.toml +1 -1
  66. flock/themes/catppuccin-mocha.toml +1 -1
  67. flock/themes/cga.toml +1 -1
  68. flock/themes/chalk.toml +1 -1
  69. flock/themes/ciapre.toml +1 -1
  70. flock/themes/coffee-theme.toml +1 -1
  71. flock/themes/cyberpunkscarletprotocol.toml +1 -1
  72. flock/themes/dark+.toml +1 -1
  73. flock/themes/darkermatrix.toml +1 -1
  74. flock/themes/darkside.toml +1 -1
  75. flock/themes/desert.toml +1 -1
  76. flock/themes/django.toml +1 -1
  77. flock/themes/djangosmooth.toml +1 -1
  78. flock/themes/doomone.toml +1 -1
  79. flock/themes/dotgov.toml +1 -1
  80. flock/themes/dracula+.toml +1 -1
  81. flock/themes/duckbones.toml +1 -1
  82. flock/themes/encom.toml +1 -1
  83. flock/themes/espresso.toml +1 -1
  84. flock/themes/everblush.toml +1 -1
  85. flock/themes/fairyfloss.toml +1 -1
  86. flock/themes/fideloper.toml +1 -1
  87. flock/themes/fishtank.toml +1 -1
  88. flock/themes/flexoki-light.toml +1 -1
  89. flock/themes/floraverse.toml +1 -1
  90. flock/themes/framer.toml +1 -1
  91. flock/themes/galizur.toml +1 -1
  92. flock/themes/github.toml +1 -1
  93. flock/themes/grass.toml +1 -1
  94. flock/themes/grey-green.toml +1 -1
  95. flock/themes/gruvboxlight.toml +1 -1
  96. flock/themes/guezwhoz.toml +1 -1
  97. flock/themes/harper.toml +1 -1
  98. flock/themes/hax0r-blue.toml +1 -1
  99. flock/themes/hopscotch.256.toml +1 -1
  100. flock/themes/ic-green-ppl.toml +1 -1
  101. flock/themes/iceberg-dark.toml +1 -1
  102. flock/themes/japanesque.toml +1 -1
  103. flock/themes/jubi.toml +1 -1
  104. flock/themes/kibble.toml +1 -1
  105. flock/themes/kolorit.toml +1 -1
  106. flock/themes/kurokula.toml +1 -1
  107. flock/themes/materialdesigncolors.toml +1 -1
  108. flock/themes/matrix.toml +1 -1
  109. flock/themes/mellifluous.toml +1 -1
  110. flock/themes/midnight-in-mojave.toml +1 -1
  111. flock/themes/monokai-remastered.toml +1 -1
  112. flock/themes/monokai-soda.toml +1 -1
  113. flock/themes/neon.toml +1 -1
  114. flock/themes/neopolitan.toml +1 -1
  115. flock/themes/nord-light.toml +1 -1
  116. flock/themes/ocean.toml +1 -1
  117. flock/themes/onehalfdark.toml +1 -1
  118. flock/themes/onehalflight.toml +1 -1
  119. flock/themes/palenighthc.toml +1 -1
  120. flock/themes/paulmillr.toml +1 -1
  121. flock/themes/pencildark.toml +1 -1
  122. flock/themes/pnevma.toml +1 -1
  123. flock/themes/purple-rain.toml +1 -1
  124. flock/themes/purplepeter.toml +1 -1
  125. flock/themes/raycast-dark.toml +1 -1
  126. flock/themes/red-sands.toml +1 -1
  127. flock/themes/relaxed.toml +1 -1
  128. flock/themes/retro.toml +1 -1
  129. flock/themes/rose-pine.toml +1 -1
  130. flock/themes/royal.toml +1 -1
  131. flock/themes/ryuuko.toml +1 -1
  132. flock/themes/sakura.toml +1 -1
  133. flock/themes/scarlet-protocol.toml +1 -1
  134. flock/themes/seoulbones-dark.toml +1 -1
  135. flock/themes/shades-of-purple.toml +1 -1
  136. flock/themes/smyck.toml +1 -1
  137. flock/themes/softserver.toml +1 -1
  138. flock/themes/solarized-darcula.toml +1 -1
  139. flock/themes/square.toml +1 -1
  140. flock/themes/sugarplum.toml +1 -1
  141. flock/themes/thayer-bright.toml +1 -1
  142. flock/themes/tokyonight.toml +1 -1
  143. flock/themes/tomorrow.toml +1 -1
  144. flock/themes/ubuntu.toml +1 -1
  145. flock/themes/ultradark.toml +1 -1
  146. flock/themes/ultraviolent.toml +1 -1
  147. flock/themes/unikitty.toml +1 -1
  148. flock/themes/urple.toml +1 -1
  149. flock/themes/vesper.toml +1 -1
  150. flock/themes/vimbones.toml +1 -1
  151. flock/themes/wildcherry.toml +1 -1
  152. flock/themes/wilmersdorf.toml +1 -1
  153. flock/themes/wryan.toml +1 -1
  154. flock/themes/xcodedarkhc.toml +1 -1
  155. flock/themes/xcodelight.toml +1 -1
  156. flock/themes/zenbones-light.toml +1 -1
  157. flock/themes/zenwritten-dark.toml +1 -1
  158. flock/utilities.py +301 -0
  159. flock/{components/utility → utility}/output_utility_component.py +68 -53
  160. flock/visibility.py +107 -0
  161. flock_core-0.5.0b50.dist-info/METADATA +747 -0
  162. flock_core-0.5.0b50.dist-info/RECORD +398 -0
  163. flock_core-0.5.0b50.dist-info/entry_points.txt +2 -0
  164. {flock_core-0.5.0b27.dist-info → flock_core-0.5.0b50.dist-info}/licenses/LICENSE +1 -1
  165. flock/adapter/__init__.py +0 -14
  166. flock/adapter/azure_adapter.py +0 -68
  167. flock/adapter/chroma_adapter.py +0 -73
  168. flock/adapter/faiss_adapter.py +0 -97
  169. flock/adapter/pinecone_adapter.py +0 -51
  170. flock/adapter/vector_base.py +0 -47
  171. flock/cli/assets/release_notes.md +0 -140
  172. flock/cli/config.py +0 -8
  173. flock/cli/constants.py +0 -36
  174. flock/cli/create_agent.py +0 -1
  175. flock/cli/create_flock.py +0 -280
  176. flock/cli/execute_flock.py +0 -620
  177. flock/cli/load_agent.py +0 -1
  178. flock/cli/load_examples.py +0 -1
  179. flock/cli/load_flock.py +0 -192
  180. flock/cli/load_release_notes.py +0 -20
  181. flock/cli/loaded_flock_cli.py +0 -254
  182. flock/cli/manage_agents.py +0 -459
  183. flock/cli/registry_management.py +0 -889
  184. flock/cli/runner.py +0 -41
  185. flock/cli/settings.py +0 -857
  186. flock/cli/utils.py +0 -135
  187. flock/cli/view_results.py +0 -29
  188. flock/cli/yaml_editor.py +0 -396
  189. flock/components/__init__.py +0 -30
  190. flock/components/evaluation/__init__.py +0 -9
  191. flock/components/evaluation/declarative_evaluation_component.py +0 -606
  192. flock/components/routing/__init__.py +0 -15
  193. flock/components/routing/conditional_routing_component.py +0 -494
  194. flock/components/routing/default_routing_component.py +0 -103
  195. flock/components/routing/llm_routing_component.py +0 -206
  196. flock/components/utility/__init__.py +0 -15
  197. flock/components/utility/memory_utility_component.py +0 -550
  198. flock/components/utility/metrics_utility_component.py +0 -700
  199. flock/config.py +0 -61
  200. flock/core/__init__.py +0 -110
  201. flock/core/agent/__init__.py +0 -16
  202. flock/core/agent/default_agent.py +0 -180
  203. flock/core/agent/flock_agent_components.py +0 -104
  204. flock/core/agent/flock_agent_execution.py +0 -101
  205. flock/core/agent/flock_agent_integration.py +0 -260
  206. flock/core/agent/flock_agent_lifecycle.py +0 -186
  207. flock/core/agent/flock_agent_serialization.py +0 -381
  208. flock/core/api/__init__.py +0 -10
  209. flock/core/api/custom_endpoint.py +0 -45
  210. flock/core/api/endpoints.py +0 -254
  211. flock/core/api/main.py +0 -162
  212. flock/core/api/models.py +0 -97
  213. flock/core/api/run_store.py +0 -224
  214. flock/core/api/runner.py +0 -44
  215. flock/core/api/service.py +0 -214
  216. flock/core/component/__init__.py +0 -15
  217. flock/core/component/agent_component_base.py +0 -309
  218. flock/core/component/evaluation_component.py +0 -62
  219. flock/core/component/routing_component.py +0 -74
  220. flock/core/component/utility_component.py +0 -69
  221. flock/core/config/flock_agent_config.py +0 -58
  222. flock/core/config/scheduled_agent_config.py +0 -40
  223. flock/core/context/context.py +0 -213
  224. flock/core/context/context_manager.py +0 -37
  225. flock/core/context/context_vars.py +0 -10
  226. flock/core/evaluation/utils.py +0 -396
  227. flock/core/execution/batch_executor.py +0 -369
  228. flock/core/execution/evaluation_executor.py +0 -438
  229. flock/core/execution/local_executor.py +0 -31
  230. flock/core/execution/opik_executor.py +0 -103
  231. flock/core/execution/temporal_executor.py +0 -164
  232. flock/core/flock.py +0 -634
  233. flock/core/flock_agent.py +0 -336
  234. flock/core/flock_factory.py +0 -551
  235. flock/core/flock_scheduler.py +0 -166
  236. flock/core/flock_server_manager.py +0 -136
  237. flock/core/interpreter/python_interpreter.py +0 -689
  238. flock/core/mcp/__init__.py +0 -1
  239. flock/core/mcp/flock_mcp_server.py +0 -680
  240. flock/core/mcp/mcp_client_manager.py +0 -201
  241. flock/core/mcp/types/__init__.py +0 -1
  242. flock/core/mixin/dspy_integration.py +0 -403
  243. flock/core/mixin/prompt_parser.py +0 -125
  244. flock/core/orchestration/__init__.py +0 -15
  245. flock/core/orchestration/flock_batch_processor.py +0 -94
  246. flock/core/orchestration/flock_evaluator.py +0 -113
  247. flock/core/orchestration/flock_execution.py +0 -295
  248. flock/core/orchestration/flock_initialization.py +0 -149
  249. flock/core/orchestration/flock_server_manager.py +0 -67
  250. flock/core/orchestration/flock_web_server.py +0 -117
  251. flock/core/registry/__init__.py +0 -45
  252. flock/core/registry/agent_registry.py +0 -69
  253. flock/core/registry/callable_registry.py +0 -139
  254. flock/core/registry/component_discovery.py +0 -142
  255. flock/core/registry/component_registry.py +0 -64
  256. flock/core/registry/config_mapping.py +0 -64
  257. flock/core/registry/decorators.py +0 -137
  258. flock/core/registry/registry_hub.py +0 -205
  259. flock/core/registry/server_registry.py +0 -57
  260. flock/core/registry/type_registry.py +0 -86
  261. flock/core/serialization/__init__.py +0 -13
  262. flock/core/serialization/callable_registry.py +0 -52
  263. flock/core/serialization/flock_serializer.py +0 -832
  264. flock/core/serialization/json_encoder.py +0 -41
  265. flock/core/serialization/secure_serializer.py +0 -175
  266. flock/core/serialization/serializable.py +0 -342
  267. flock/core/serialization/serialization_utils.py +0 -412
  268. flock/core/util/file_path_utils.py +0 -223
  269. flock/core/util/hydrator.py +0 -309
  270. flock/core/util/input_resolver.py +0 -164
  271. flock/core/util/loader.py +0 -59
  272. flock/core/util/splitter.py +0 -219
  273. flock/di.py +0 -27
  274. flock/platform/docker_tools.py +0 -49
  275. flock/platform/jaeger_install.py +0 -86
  276. flock/webapp/__init__.py +0 -1
  277. flock/webapp/app/__init__.py +0 -0
  278. flock/webapp/app/api/__init__.py +0 -0
  279. flock/webapp/app/api/agent_management.py +0 -241
  280. flock/webapp/app/api/execution.py +0 -709
  281. flock/webapp/app/api/flock_management.py +0 -129
  282. flock/webapp/app/api/registry_viewer.py +0 -30
  283. flock/webapp/app/chat.py +0 -665
  284. flock/webapp/app/config.py +0 -104
  285. flock/webapp/app/dependencies.py +0 -117
  286. flock/webapp/app/main.py +0 -1070
  287. flock/webapp/app/middleware.py +0 -113
  288. flock/webapp/app/models_ui.py +0 -7
  289. flock/webapp/app/services/__init__.py +0 -0
  290. flock/webapp/app/services/feedback_file_service.py +0 -363
  291. flock/webapp/app/services/flock_service.py +0 -337
  292. flock/webapp/app/services/sharing_models.py +0 -81
  293. flock/webapp/app/services/sharing_store.py +0 -598
  294. flock/webapp/app/templates/theme_mapper.html +0 -326
  295. flock/webapp/app/theme_mapper.py +0 -812
  296. flock/webapp/app/utils.py +0 -85
  297. flock/webapp/run.py +0 -215
  298. flock/webapp/static/css/chat.css +0 -301
  299. flock/webapp/static/css/components.css +0 -167
  300. flock/webapp/static/css/header.css +0 -39
  301. flock/webapp/static/css/layout.css +0 -46
  302. flock/webapp/static/css/sidebar.css +0 -127
  303. flock/webapp/static/css/two-pane.css +0 -48
  304. flock/webapp/templates/base.html +0 -200
  305. flock/webapp/templates/chat.html +0 -152
  306. flock/webapp/templates/chat_settings.html +0 -19
  307. flock/webapp/templates/flock_editor.html +0 -16
  308. flock/webapp/templates/index.html +0 -12
  309. flock/webapp/templates/partials/_agent_detail_form.html +0 -93
  310. flock/webapp/templates/partials/_agent_list.html +0 -18
  311. flock/webapp/templates/partials/_agent_manager_view.html +0 -51
  312. flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
  313. flock/webapp/templates/partials/_chat_container.html +0 -15
  314. flock/webapp/templates/partials/_chat_messages.html +0 -57
  315. flock/webapp/templates/partials/_chat_settings_form.html +0 -85
  316. flock/webapp/templates/partials/_create_flock_form.html +0 -50
  317. flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
  318. flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
  319. flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
  320. flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
  321. flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
  322. flock/webapp/templates/partials/_env_vars_table.html +0 -23
  323. flock/webapp/templates/partials/_execution_form.html +0 -118
  324. flock/webapp/templates/partials/_execution_view_container.html +0 -28
  325. flock/webapp/templates/partials/_flock_file_list.html +0 -23
  326. flock/webapp/templates/partials/_flock_properties_form.html +0 -52
  327. flock/webapp/templates/partials/_flock_upload_form.html +0 -16
  328. flock/webapp/templates/partials/_header_flock_status.html +0 -5
  329. flock/webapp/templates/partials/_load_manager_view.html +0 -49
  330. flock/webapp/templates/partials/_registry_table.html +0 -25
  331. flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
  332. flock/webapp/templates/partials/_results_display.html +0 -78
  333. flock/webapp/templates/partials/_settings_env_content.html +0 -9
  334. flock/webapp/templates/partials/_settings_theme_content.html +0 -14
  335. flock/webapp/templates/partials/_settings_view.html +0 -36
  336. flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
  337. flock/webapp/templates/partials/_share_link_snippet.html +0 -35
  338. flock/webapp/templates/partials/_sidebar.html +0 -74
  339. flock/webapp/templates/partials/_streaming_results_container.html +0 -195
  340. flock/webapp/templates/partials/_structured_data_view.html +0 -40
  341. flock/webapp/templates/partials/_theme_preview.html +0 -36
  342. flock/webapp/templates/registry_viewer.html +0 -84
  343. flock/webapp/templates/shared_run_page.html +0 -140
  344. flock/workflow/__init__.py +0 -0
  345. flock/workflow/activities.py +0 -196
  346. flock/workflow/agent_activities.py +0 -24
  347. flock/workflow/agent_execution_activity.py +0 -202
  348. flock/workflow/flock_workflow.py +0 -214
  349. flock/workflow/temporal_config.py +0 -96
  350. flock/workflow/temporal_setup.py +0 -68
  351. flock_core-0.5.0b27.dist-info/METADATA +0 -274
  352. flock_core-0.5.0b27.dist-info/RECORD +0 -559
  353. flock_core-0.5.0b27.dist-info/entry_points.txt +0 -2
  354. /flock/{core/logging → logging}/formatters/themes.py +0 -0
  355. /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
  356. /flock/{core/mcp → mcp}/util/__init__.py +0 -0
  357. {flock_core-0.5.0b27.dist-info → flock_core-0.5.0b50.dist-info}/WHEEL +0 -0
@@ -1,260 +0,0 @@
1
- # src/flock/core/agent/flock_agent_integration.py
2
- """Tool and server integration functionality for FlockAgent."""
3
-
4
- from collections.abc import Callable
5
- from functools import wraps
6
- from inspect import Parameter, signature
7
- from typing import TYPE_CHECKING, Any, TypeVar, cast
8
-
9
- from flock.core.context.context import FlockContext
10
- from flock.core.logging.logging import get_logger
11
- from flock.core.mcp.flock_mcp_server import FlockMCPServer
12
- from pydantic import BaseModel
13
- from flock.core.registry import get_registry
14
- from flock.core.serialization.serialization_utils import (
15
- _format_type_to_string,
16
- collect_pydantic_models,
17
- )
18
-
19
- if TYPE_CHECKING:
20
- from flock.core.flock_agent import FlockAgent
21
-
22
- logger = get_logger("agent.integration")
23
-
24
- R = TypeVar("R", bound=str)
25
-
26
-
27
- def adapt(prop_name: str, fn: Callable[..., R]) -> Callable[[FlockContext], R]:
28
- """Coerce *fn* into the canonical ``(ctx: FlockContext) -> str`` form.
29
-
30
- Acceptable signatures
31
- ---------------------
32
- 1. ``() -> str`` (no parameters)
33
- 2. ``(ctx: FlockContext) -> str`` (exactly one positional parameter)
34
-
35
- Anything else raises ``TypeError``.
36
-
37
- The wrapper also enforces at runtime that the result is ``str``.
38
- """
39
- if not callable(fn):
40
- raise TypeError(f"{prop_name} must be a callable, got {type(fn).__name__}")
41
-
42
- sig = signature(fn)
43
- params = list(sig.parameters.values())
44
-
45
- def _validate_result(res: object) -> R:
46
- if not isinstance(res, str):
47
- raise TypeError(
48
- f"{prop_name} callable must return str, got {type(res).__name__}"
49
- )
50
- return cast(R, res)
51
-
52
- # ── Case 1: () -> str ────────────────────────────────────────────────────
53
- if len(params) == 0:
54
-
55
- @wraps(fn)
56
- def _wrapped(ctx: FlockContext) -> R:
57
- return _validate_result(fn())
58
-
59
- return _wrapped
60
-
61
- # ── Case 2: (ctx) -> str ────────────────────────────────────────────────
62
- if len(params) == 1:
63
- p: Parameter = params[0]
64
- valid_kind = p.kind in (
65
- Parameter.POSITIONAL_ONLY,
66
- Parameter.POSITIONAL_OR_KEYWORD,
67
- )
68
- valid_annotation = p.annotation in (Parameter.empty, FlockContext)
69
- has_no_default = p.default is Parameter.empty
70
-
71
- if valid_kind and valid_annotation and has_no_default:
72
-
73
- @wraps(fn)
74
- def _wrapped(ctx: FlockContext) -> R:
75
- return _validate_result(fn(ctx)) # type: ignore[arg-type]
76
-
77
- return _wrapped
78
-
79
- # ── Anything else: reject ───────────────────────────────────────────────
80
- raise TypeError(
81
- f"{prop_name} callable must be () -> str or (ctx: FlockContext) -> str; "
82
- f"got signature {sig}"
83
- )
84
-
85
- class FlockAgentIntegration:
86
- """Handles tool and server integration for FlockAgent including MCP servers and callable tools."""
87
-
88
- def __init__(self, agent: "FlockAgent"):
89
- self.agent = agent
90
-
91
- def _resolve(self, raw: str | Callable[..., str], name: str, ctx: FlockContext | None) -> str | None:
92
- # Support Pydantic BaseModel classes (alternative I/O definitions)
93
- try:
94
- if isinstance(raw, type) and issubclass(raw, BaseModel):
95
- return self._build_spec_from_pydantic(raw)
96
- # Also support instances directly (use their class schema)
97
- if isinstance(raw, BaseModel):
98
- return self._build_spec_from_pydantic(type(raw))
99
- except Exception:
100
- # If introspection failed, fall through to normal handling
101
- pass
102
-
103
- if callable(raw):
104
- raw = adapt(name, raw)(ctx or FlockContext())
105
- return raw
106
-
107
- def _build_spec_from_pydantic(self, model_cls: type[BaseModel]) -> str:
108
- """Builds a flock I/O spec string from a Pydantic BaseModel class.
109
-
110
- Format per field: "name: type | description"; description omitted when empty.
111
- Also ensures involved Pydantic models are registered in the TypeRegistry
112
- so type resolution works when constructing DSPy signatures.
113
- """
114
- # Proactively register this model and any nested models
115
- try:
116
- registry = get_registry()
117
- registry.register_type(model_cls, name=model_cls.__name__)
118
- # Register nested Pydantic models used in type hints
119
- if hasattr(model_cls, "model_fields"):
120
- for _, f in model_cls.model_fields.items():
121
- ann = getattr(f, "annotation", None)
122
- for m in collect_pydantic_models(ann):
123
- registry.register_type(m, name=m.__name__)
124
- except Exception:
125
- # Registration best-effort; continue building spec
126
- pass
127
-
128
- fields = []
129
- # Pydantic v2: class-level model_fields
130
- if not hasattr(model_cls, "model_fields") or model_cls.model_fields is None: # type: ignore[attr-defined]
131
- return ""
132
-
133
- for name, field in model_cls.model_fields.items(): # type: ignore[attr-defined]
134
- type_hint = getattr(field, "annotation", None)
135
- type_str = _format_type_to_string(type_hint) if type_hint is not None else "str"
136
- desc = getattr(field, "description", None) or ""
137
- if desc:
138
- fields.append(f"{name}: {type_str} | {desc}")
139
- else:
140
- fields.append(f"{name}: {type_str}")
141
-
142
- return ", ".join(fields)
143
-
144
- def resolve_description(self, context: FlockContext | None = None) -> str | None:
145
- """Resolve the agent's description, handling callable descriptions."""
146
- return self._resolve(self.agent.description_spec, "description", context)
147
-
148
- def resolve_input(self, context: FlockContext | None = None) -> str | None:
149
- """Resolve the agent's input, handling callable inputs."""
150
- return self._resolve(self.agent.input_spec, "input", context)
151
-
152
- def resolve_output(self, context: FlockContext | None = None) -> str | None:
153
- """Resolve the agent's output, handling callable outputs."""
154
- return self._resolve(self.agent.output_spec, "output", context)
155
-
156
- def resolve_next_agent(self, context: FlockContext | None = None) -> str | None:
157
- """Resolve the next agent, handling callable next agents."""
158
- return self._resolve(self.agent.next_agent_spec, "next_agent", context)
159
-
160
- async def get_mcp_tools(self) -> list[Any]:
161
- """Get tools from registered MCP servers."""
162
- mcp_tools = []
163
- if self.agent.servers:
164
- from flock.core.registry import get_registry
165
-
166
- registry = get_registry() # Get the registry
167
- for server in self.agent.servers:
168
- registered_server: FlockMCPServer | None = None
169
- server_tools = []
170
- if isinstance(server, FlockMCPServer):
171
- # check if registered
172
- server_name = server.config.name
173
- registered_server = registry.get_server(
174
- server_name
175
- )
176
- else:
177
- # servers must be registered.
178
- registered_server = registry.get_server(
179
- name=server
180
- )
181
- if registered_server:
182
- server_tools = await registered_server.get_tools(
183
- agent_id=self.agent.agent_id,
184
- run_id=self.agent.context.run_id,
185
- )
186
- else:
187
- logger.warning(
188
- f"No Server with name '{server.config.name if isinstance(server, FlockMCPServer) else server}' registered! Skipping."
189
- )
190
- mcp_tools = mcp_tools + server_tools
191
- return mcp_tools
192
-
193
- async def execute_with_middleware(
194
- self,
195
- current_inputs: dict[str, Any],
196
- registered_tools: list[Any],
197
- mcp_tools: list[Any]
198
- ) -> dict[str, Any]:
199
- """Execute evaluator with optional DI middleware pipeline."""
200
- container = None
201
- if self.agent.context is not None:
202
- container = self.agent.context.get_variable("di.container")
203
-
204
- # If a MiddlewarePipeline is registered in DI, wrap the evaluator
205
- result: dict[str, Any] | None = None
206
-
207
- if container is not None:
208
- try:
209
- from wd.di.middleware import (
210
- MiddlewarePipeline,
211
- )
212
-
213
- pipeline: MiddlewarePipeline | None = None
214
- try:
215
- pipeline = container.get_service(MiddlewarePipeline)
216
- except Exception:
217
- pipeline = None
218
-
219
- if pipeline is not None:
220
- # Build execution chain where the evaluator is the terminal handler
221
-
222
- async def _final_handler():
223
- return await self.agent.evaluator.evaluate_core(
224
- self.agent, current_inputs, self.agent.context, registered_tools, mcp_tools
225
- )
226
-
227
- idx = 0
228
-
229
- async def _invoke_next():
230
- nonlocal idx
231
-
232
- if idx < len(pipeline._middleware):
233
- mw = pipeline._middleware[idx]
234
- idx += 1
235
- return await mw(self.agent.context, _invoke_next) # type: ignore[arg-type]
236
- return await _final_handler()
237
-
238
- # Execute pipeline
239
- result = await _invoke_next()
240
- else:
241
- # No pipeline registered, direct evaluation
242
- result = await self.agent.evaluator.evaluate_core(
243
- self.agent, current_inputs, self.agent.context, registered_tools, mcp_tools
244
- )
245
- except ImportError:
246
- # wd.di not installed – fall back
247
- result = await self.agent.evaluator.evaluate_core(
248
- self.agent, current_inputs, self.agent.context, registered_tools, mcp_tools
249
- )
250
- else:
251
- # No DI container – standard execution
252
- result = await self.agent.evaluator.evaluate_core(
253
- self.agent,
254
- current_inputs,
255
- self.agent.context,
256
- registered_tools,
257
- mcp_tools,
258
- )
259
-
260
- return result
@@ -1,186 +0,0 @@
1
- # src/flock/core/agent/flock_agent_lifecycle.py
2
- """Lifecycle management functionality for FlockAgent."""
3
-
4
- from typing import TYPE_CHECKING, Any
5
-
6
- from opentelemetry import trace
7
-
8
- from flock.core.logging.logging import get_logger
9
-
10
- if TYPE_CHECKING:
11
- from flock.core.flock_agent import FlockAgent
12
-
13
- logger = get_logger("agent.lifecycle")
14
- tracer = trace.get_tracer(__name__)
15
-
16
-
17
- class FlockAgentLifecycle:
18
- """Handles lifecycle management for FlockAgent including initialization, evaluation, and termination."""
19
-
20
- def __init__(self, agent: "FlockAgent"):
21
- self.agent = agent
22
-
23
- async def initialize(self, inputs: dict[str, Any]) -> None:
24
- """Initialize agent and run module initializers."""
25
- logger.debug(f"Initializing agent '{self.agent.name}'")
26
- with tracer.start_as_current_span("agent.initialize") as span:
27
- span.set_attribute("agent.name", self.agent.name)
28
- span.set_attribute("inputs", str(inputs))
29
- logger.info(
30
- f"agent.initialize",
31
- agent=self.agent.name,
32
- )
33
- try:
34
- for component in self.agent.get_enabled_components():
35
- await component.on_initialize(self.agent, inputs, self.agent.context)
36
- except Exception as component_error:
37
- logger.error(
38
- "Error during initialize",
39
- agent=self.agent.name,
40
- error=str(component_error),
41
- )
42
- span.record_exception(component_error)
43
-
44
- async def terminate(
45
- self, inputs: dict[str, Any], result: dict[str, Any]
46
- ) -> None:
47
- """Terminate agent and run module terminators."""
48
- logger.debug(f"Terminating agent '{self.agent.name}'")
49
- with tracer.start_as_current_span("agent.terminate") as span:
50
- span.set_attribute("agent.name", self.agent.name)
51
- span.set_attribute("inputs", str(inputs))
52
- span.set_attribute("result", str(result))
53
- logger.info(
54
- f"agent.terminate",
55
- agent=self.agent.name,
56
- )
57
- try:
58
- current_result = result
59
- for component in self.agent.get_enabled_components():
60
- tmp_result = await component.on_terminate(
61
- self.agent, inputs, self.agent.context, current_result
62
- )
63
- # If the component returns a result, use it
64
- if tmp_result:
65
- current_result = tmp_result
66
-
67
- if self.agent.config.write_to_file:
68
- self.agent._serialization._save_output(self.agent.name, current_result)
69
-
70
- if self.agent.config.wait_for_input:
71
- # simple input prompt
72
- input("Press Enter to continue...")
73
-
74
- except Exception as component_error:
75
- logger.error(
76
- "Error during terminate",
77
- agent=self.agent.name,
78
- error=str(component_error),
79
- )
80
- span.record_exception(component_error)
81
-
82
- async def on_error(self, error: Exception, inputs: dict[str, Any]) -> None:
83
- """Handle errors and run component error handlers."""
84
- logger.error(f"Error occurred in agent '{self.agent.name}': {error}")
85
- with tracer.start_as_current_span("agent.on_error") as span:
86
- span.set_attribute("agent.name", self.agent.name)
87
- span.set_attribute("inputs", str(inputs))
88
- try:
89
- for component in self.agent.get_enabled_components():
90
- await component.on_error(self.agent, inputs, self.agent.context, error)
91
- except Exception as component_error:
92
- logger.error(
93
- "Error during on_error",
94
- agent=self.agent.name,
95
- error=str(component_error),
96
- )
97
- span.record_exception(component_error)
98
-
99
- async def evaluate(self, inputs: dict[str, Any]) -> dict[str, Any]:
100
- """Core evaluation logic, calling the assigned evaluator and components."""
101
- if not self.agent.evaluator:
102
- raise RuntimeError(
103
- f"Agent '{self.agent.name}' has no evaluator assigned."
104
- )
105
- with tracer.start_as_current_span("agent.evaluate") as span:
106
- span.set_attribute("agent.name", self.agent.name)
107
- span.set_attribute("inputs", str(inputs))
108
- logger.info(
109
- f"agent.evaluate",
110
- agent=self.agent.name,
111
- )
112
-
113
- logger.debug(f"Evaluating agent '{self.agent.name}'")
114
- current_inputs = inputs
115
-
116
- # Pre-evaluate hooks
117
- for component in self.agent.get_enabled_components():
118
- current_inputs = await component.on_pre_evaluate(
119
- self.agent, current_inputs, self.agent.context
120
- )
121
-
122
- # Actual evaluation
123
- try:
124
- # Get tools and MCP tools through integration handler
125
- registered_tools = []
126
- if self.agent.tools:
127
- registered_tools = self.agent.tools
128
-
129
- # Retrieve available mcp_tools if the evaluator needs them
130
- mcp_tools = []
131
- if self.agent.servers:
132
- mcp_tools = await self.agent._integration.get_mcp_tools()
133
-
134
- # Filter tools based on the agent's whitelist (if it has been provided)
135
- if self.agent.tool_whitelist is not None and len(self.agent.tool_whitelist) > 0:
136
- for tool in mcp_tools:
137
- if hasattr(tool, "name") and tool.name not in self.agent.tool_whitelist:
138
- mcp_tools.remove(tool)
139
- for tool in registered_tools:
140
- if hasattr(tool, "__name__") and tool.__name__ not in self.agent.tool_whitelist:
141
- registered_tools.remove(tool)
142
-
143
- # --------------------------------------------------
144
- # Use evaluator component's evaluate_core method
145
- # --------------------------------------------------
146
- result = await self.agent.evaluator.evaluate_core(
147
- self.agent, current_inputs, self.agent.context, registered_tools, mcp_tools
148
- )
149
-
150
- except Exception as eval_error:
151
- logger.error(
152
- "Error during evaluate",
153
- agent=self.agent.name,
154
- error=str(eval_error),
155
- )
156
- span.record_exception(eval_error)
157
- await self.on_error(
158
- eval_error, current_inputs
159
- ) # Call error hook
160
- raise # Re-raise the exception
161
-
162
- # Post-evaluate hooks
163
- current_result = result
164
- for component in self.agent.get_enabled_components():
165
- tmp_result = await component.on_post_evaluate(
166
- self.agent,
167
- current_inputs,
168
- self.agent.context,
169
- current_result,
170
- )
171
- # If the component returns a result, use it
172
- if tmp_result:
173
- current_result = tmp_result
174
-
175
- # Handle routing logic
176
- router = self.agent.router
177
- if router:
178
- try:
179
- self.agent.next_agent = await router.determine_next_step(
180
- self.agent, current_result, self.agent.context
181
- )
182
- except Exception as e:
183
- logger.error(f"Error in routing: {e}")
184
-
185
- logger.debug(f"Evaluation completed for agent '{self.agent.name}'")
186
- return current_result