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,224 +0,0 @@
1
- # src/flock/core/api/run_store.py
2
- """Manages the state of active and completed Flock runs."""
3
-
4
- import threading
5
- from datetime import datetime
6
- from typing import Any
7
-
8
- from flock.core.logging.logging import get_logger
9
-
10
- from .models import ( # Import from the models file
11
- FlockAPIResponse,
12
- FlockBatchResponse,
13
- )
14
-
15
- logger = get_logger("api.run_store")
16
-
17
-
18
- class RunStore:
19
- """Stores and manages the state of Flock runs."""
20
-
21
- def __init__(self):
22
- self._runs: dict[str, FlockAPIResponse] = {}
23
- self._batches: dict[str, FlockBatchResponse] = {}
24
- self._lock = threading.Lock() # Basic lock for thread safety
25
-
26
- def create_run(self, run_id: str) -> FlockAPIResponse:
27
- """Creates a new run record with 'starting' status."""
28
- with self._lock:
29
- if run_id in self._runs:
30
- logger.warning(f"Run ID {run_id} already exists. Overwriting.")
31
- response = FlockAPIResponse(
32
- run_id=run_id, status="starting", started_at=datetime.now()
33
- )
34
- self._runs[run_id] = response
35
- logger.debug(f"Created run record for run_id: {run_id}")
36
- return response
37
-
38
- def get_run(self, run_id: str) -> FlockAPIResponse | None:
39
- """Gets the status of a run."""
40
- with self._lock:
41
- return self._runs.get(run_id)
42
-
43
- def update_run_status(
44
- self, run_id: str, status: str, error: str | None = None
45
- ):
46
- """Updates the status and potentially error of a run."""
47
- with self._lock:
48
- if run_id in self._runs:
49
- self._runs[run_id].status = status
50
- if error:
51
- self._runs[run_id].error = error
52
- if status in ["completed", "failed"]:
53
- self._runs[run_id].completed_at = datetime.now()
54
- logger.debug(f"Updated status for run_id {run_id} to {status}")
55
- else:
56
- logger.warning(
57
- f"Attempted to update status for non-existent run_id: {run_id}"
58
- )
59
-
60
- def update_run_result(self, run_id: str, result: dict):
61
- """Updates the result of a completed run."""
62
- with self._lock:
63
- if run_id in self._runs:
64
- # Ensure result is serializable (e.g., convert Box)
65
- final_result = (
66
- dict(result) if hasattr(result, "to_dict") else result
67
- )
68
- self._runs[run_id].result = final_result
69
- self._runs[run_id].status = "completed"
70
- self._runs[run_id].completed_at = datetime.now()
71
- logger.debug(f"Updated result for completed run_id: {run_id}")
72
- else:
73
- logger.warning(
74
- f"Attempted to update result for non-existent run_id: {run_id}"
75
- )
76
-
77
- def create_batch(self, batch_id: str) -> FlockBatchResponse:
78
- """Creates a new batch record with 'starting' status."""
79
- with self._lock:
80
- if batch_id in self._batches:
81
- logger.warning(
82
- f"Batch ID {batch_id} already exists. Overwriting."
83
- )
84
- response = FlockBatchResponse(
85
- batch_id=batch_id,
86
- status="starting",
87
- results=[],
88
- started_at=datetime.now(),
89
- total_items=0,
90
- completed_items=0,
91
- progress_percentage=0.0,
92
- )
93
- self._batches[batch_id] = response
94
- logger.debug(f"Created batch record for batch_id: {batch_id}")
95
- return response
96
-
97
- def get_batch(self, batch_id: str) -> FlockBatchResponse | None:
98
- """Gets the status of a batch run."""
99
- with self._lock:
100
- return self._batches.get(batch_id)
101
-
102
- def update_batch_status(
103
- self, batch_id: str, status: str, error: str | None = None
104
- ):
105
- """Updates the status and potentially error of a batch run."""
106
- with self._lock:
107
- if batch_id in self._batches:
108
- self._batches[batch_id].status = status
109
- if error:
110
- self._batches[batch_id].error = error
111
- if status in ["completed", "failed"]:
112
- self._batches[batch_id].completed_at = datetime.now()
113
- # When completed, ensure progress is 100%
114
- if (
115
- status == "completed"
116
- and self._batches[batch_id].total_items > 0
117
- ):
118
- self._batches[batch_id].completed_items = self._batches[
119
- batch_id
120
- ].total_items
121
- self._batches[batch_id].progress_percentage = 100.0
122
- logger.debug(
123
- f"Updated status for batch_id {batch_id} to {status}"
124
- )
125
- else:
126
- logger.warning(
127
- f"Attempted to update status for non-existent batch_id: {batch_id}"
128
- )
129
-
130
- def update_batch_result(self, batch_id: str, results: list[Any]):
131
- """Updates the results of a completed batch run."""
132
- with self._lock:
133
- if batch_id in self._batches:
134
- # Ensure results are serializable
135
- final_results = [
136
- dict(r) if hasattr(r, "to_dict") else r for r in results
137
- ]
138
- self._batches[batch_id].results = final_results
139
- self._batches[batch_id].status = "completed"
140
- self._batches[batch_id].completed_at = datetime.now()
141
-
142
- # Update progress tracking
143
- self._batches[batch_id].completed_items = len(final_results)
144
- self._batches[batch_id].total_items = len(final_results)
145
- self._batches[batch_id].progress_percentage = 100.0
146
-
147
- logger.debug(
148
- f"Updated results for completed batch_id: {batch_id}"
149
- )
150
- else:
151
- logger.warning(
152
- f"Attempted to update results for non-existent batch_id: {batch_id}"
153
- )
154
-
155
- def set_batch_total_items(self, batch_id: str, total_items: int):
156
- """Sets the total number of items in a batch."""
157
- try:
158
- with self._lock:
159
- if batch_id in self._batches:
160
- self._batches[batch_id].total_items = total_items
161
- # Recalculate percentage
162
- if total_items > 0:
163
- self._batches[batch_id].progress_percentage = (
164
- self._batches[batch_id].completed_items
165
- / total_items
166
- * 100.0
167
- )
168
- logger.debug(
169
- f"Set total_items for batch_id {batch_id} to {total_items}"
170
- )
171
- else:
172
- logger.warning(
173
- f"Attempted to set total_items for non-existent batch_id: {batch_id}"
174
- )
175
- except Exception as e:
176
- logger.error(f"Error setting batch total items: {e}", exc_info=True)
177
-
178
- def update_batch_progress(
179
- self,
180
- batch_id: str,
181
- completed_items: int,
182
- partial_results: list[Any] = None,
183
- ):
184
- """Updates the progress of a batch run and optionally adds partial results.
185
-
186
- Args:
187
- batch_id: The ID of the batch to update
188
- completed_items: The number of items that have been completed
189
- partial_results: Optional list of results for completed items to add to the batch
190
- """
191
- try:
192
- with self._lock:
193
- if batch_id in self._batches:
194
- self._batches[batch_id].completed_items = completed_items
195
-
196
- # Calculate percentage if we have a total
197
- if self._batches[batch_id].total_items > 0:
198
- self._batches[batch_id].progress_percentage = (
199
- completed_items
200
- / self._batches[batch_id].total_items
201
- * 100.0
202
- )
203
-
204
- # Add partial results if provided
205
- if partial_results:
206
- # Ensure results are serializable
207
- final_results = [
208
- dict(r) if hasattr(r, "to_dict") else r
209
- for r in partial_results
210
- ]
211
- self._batches[batch_id].results = final_results
212
-
213
- logger.debug(
214
- f"Updated progress for batch_id {batch_id}: {completed_items}/{self._batches[batch_id].total_items} "
215
- f"({self._batches[batch_id].progress_percentage:.1f}%)"
216
- )
217
- else:
218
- logger.warning(
219
- f"Attempted to update progress for non-existent batch_id: {batch_id}"
220
- )
221
- except Exception as e:
222
- logger.error(f"Error updating batch progress: {e}", exc_info=True)
223
-
224
- # Add methods for cleanup, persistence, etc. later
flock/core/api/runner.py DELETED
@@ -1,44 +0,0 @@
1
- # src/flock/api/runner.py
2
- """Provides functionality to start the Flock API server."""
3
-
4
- from collections.abc import Callable, Sequence
5
- from typing import TYPE_CHECKING, Any
6
-
7
- from flock.core.api.custom_endpoint import FlockEndpoint
8
- from flock.core.logging.logging import get_logger
9
-
10
- if TYPE_CHECKING:
11
- from flock.core.flock import Flock
12
-
13
- logger = get_logger("api.runner")
14
-
15
-
16
- def start_flock_api(
17
- flock: "Flock",
18
- host: str = "127.0.0.1",
19
- port: int = 8344,
20
- server_name: str = "Flock API",
21
- create_ui: bool = False,
22
- custom_endpoints: Sequence[FlockEndpoint] | dict[tuple[str, list[str] | None], Callable[..., Any]] | None = None,
23
- ) -> None:
24
- """Start a REST API server for the given Flock instance."""
25
- try:
26
- # Import API class locally to avoid making it a hard dependency for core flock
27
- from flock.core.api import FlockAPI
28
- except ImportError:
29
- logger.error(
30
- "API components not found. Cannot start API. "
31
- "Ensure 'fastapi' and 'uvicorn' are installed."
32
- )
33
- return
34
-
35
- logger.info(
36
- f"Preparing to start API server for Flock '{flock.name}' on {host}:{port} {'with UI' if create_ui else 'without UI'}"
37
- )
38
- api_instance = FlockAPI(flock, custom_endpoints=custom_endpoints) # Pass the Flock instance to the API
39
- api_instance.start(
40
- host=host,
41
- port=port,
42
- server_name=server_name,
43
- create_ui=create_ui,
44
- )
flock/core/api/service.py DELETED
@@ -1,214 +0,0 @@
1
- # flock/core/api/service.py
2
- from typing import TYPE_CHECKING, Any
3
-
4
- if TYPE_CHECKING:
5
- from flock.core.api.endpoints import FlockBatchRequest
6
- from flock.core.api.run_store import RunStore
7
- from flock.core.flock import Flock
8
-
9
-
10
- from flock.core.logging.logging import get_logger
11
-
12
- logger = get_logger("flock.api")
13
-
14
- class FlockApiService:
15
- def __init__(self, flock_instance: "Flock", run_store_instance: "RunStore"):
16
- self.flock = flock_instance
17
- self.run_store = run_store_instance
18
- # You would move the _run_flock, _run_batch, _type_convert_inputs methods here
19
- # from the old FlockAPI class.
20
- async def _run_flock(
21
- self, run_id: str, agent_name: str, inputs: dict[str, Any]
22
- ):
23
- """Executes a flock workflow run (internal helper)."""
24
- try:
25
- if agent_name not in self.flock.agents:
26
- raise ValueError(f"Starting agent '{agent_name}' not found")
27
-
28
- typed_inputs = self._type_convert_inputs(agent_name, inputs)
29
-
30
- logger.debug(
31
- f"Executing flock workflow starting with '{agent_name}' (run_id: {run_id})",
32
- inputs=typed_inputs,
33
- )
34
- # Flock.run_async now handles context creation and execution
35
- result = await self.flock.run_async(
36
- agent=agent_name, input=typed_inputs
37
- )
38
- self.run_store.update_run_result(run_id, result)
39
-
40
- final_agent_name = (
41
- result.get("agent_name", "N/A") if isinstance(result, dict) else "N/A"
42
- ) # Handle if result is not a dict (e.g. Box)
43
- logger.info(
44
- f"Flock workflow completed (run_id: {run_id})",
45
- final_agent=final_agent_name,
46
- )
47
- except Exception as e:
48
- logger.error(
49
- f"Error in flock run {run_id} (started with '{agent_name}'): {e!s}",
50
- exc_info=True,
51
- )
52
- self.run_store.update_run_status(run_id, "failed", str(e))
53
- raise
54
-
55
- async def _run_batch(self, batch_id: str, request: "FlockBatchRequest"):
56
- """Executes a batch of runs (internal helper)."""
57
- try:
58
- if request.agent_name not in self.flock.agents:
59
- raise ValueError(f"Agent '{request.agent_name}' not found")
60
-
61
- logger.debug(
62
- f"Executing batch run starting with '{request.agent_name}' (batch_id: {batch_id})",
63
- batch_size=len(request.batch_inputs)
64
- if isinstance(request.batch_inputs, list)
65
- else "CSV/DataFrame",
66
- )
67
-
68
- # --- Re-integrating the threaded batch execution from Flock.run_batch_async ---
69
- import asyncio
70
- import threading
71
- from concurrent.futures import ThreadPoolExecutor
72
-
73
- def run_batch_sync_in_thread():
74
- loop = asyncio.new_event_loop()
75
- asyncio.set_event_loop(loop)
76
- try:
77
- batch_size = (
78
- len(request.batch_inputs)
79
- if isinstance(request.batch_inputs, list)
80
- else 0 # Or attempt to get from DataFrame/CSV load
81
- )
82
- if batch_size > 0:
83
- self.run_store.set_batch_total_items(batch_id, batch_size)
84
-
85
- class ProgressTracker:
86
- def __init__(self, store, b_id, total_size):
87
- self.store, self.batch_id, self.total_size = store, b_id, total_size
88
- self.current_count, self.partial_results, self._lock = 0, [], threading.Lock()
89
- def increment(self, res=None):
90
- with self._lock:
91
- self.current_count += 1
92
- if res is not None: self.partial_results.append(res)
93
- try: self.store.update_batch_progress(self.batch_id, self.current_count, self.partial_results)
94
- except Exception as e_prog: logger.error(f"Error updating progress: {e_prog}")
95
- return self.current_count
96
-
97
- progress_tracker = ProgressTracker(self.run_store, batch_id, batch_size)
98
-
99
- async def progress_aware_worker(index, item_inputs):
100
- try:
101
- # Call Flock's run_async for a single item
102
- item_result = await self.flock.run_async(
103
- agent=request.agent_name,
104
- input=item_inputs,
105
- box_result=request.box_results,
106
- )
107
- progress_tracker.increment(item_result)
108
- return item_result
109
- except Exception as item_err:
110
- logger.error(f"Error processing batch item {index}: {item_err}")
111
- progress_tracker.increment(item_err if request.return_errors else None)
112
- if request.return_errors: return item_err
113
- return None
114
-
115
- batch_inputs_list = request.batch_inputs
116
- actual_results_list = []
117
-
118
- if isinstance(batch_inputs_list, list):
119
- tasks = []
120
- for i, item_inputs in enumerate(batch_inputs_list):
121
- full_inputs = {**(request.static_inputs or {}), **item_inputs}
122
- tasks.append(progress_aware_worker(i, full_inputs))
123
-
124
- if request.parallel and request.max_workers > 1:
125
- semaphore = asyncio.Semaphore(request.max_workers)
126
- async def bounded_worker(idx, inputs_item):
127
- async with semaphore: return await progress_aware_worker(idx, inputs_item)
128
- bounded_tasks = [bounded_worker(i, {**(request.static_inputs or {}), **item}) for i, item in enumerate(batch_inputs_list)]
129
- actual_results_list = loop.run_until_complete(asyncio.gather(*bounded_tasks, return_exceptions=request.return_errors))
130
- else:
131
- for i, item_inputs in enumerate(batch_inputs_list):
132
- full_inputs = {**(request.static_inputs or {}), **item_inputs}
133
- actual_results_list.append(loop.run_until_complete(progress_aware_worker(i, full_inputs)))
134
- else: # DataFrame or CSV path - let Flock's batch processor handle this directly
135
- # This path relies on self.flock.run_batch_async being able to run within this new event loop.
136
- # It might be simpler to always convert DataFrame/CSV to list of dicts before this point.
137
- actual_results_list = loop.run_until_complete(
138
- self.flock.run_batch_async(
139
- start_agent=request.agent_name,
140
- batch_inputs=request.batch_inputs, # DataFrame or path
141
- input_mapping=request.input_mapping,
142
- static_inputs=request.static_inputs,
143
- parallel=request.parallel, # Will be re-evaluated by internal BatchProcessor
144
- max_workers=request.max_workers,
145
- use_temporal=request.use_temporal, # Will be re-evaluated
146
- box_results=request.box_results,
147
- return_errors=request.return_errors,
148
- silent_mode=True, # Internal batch runs silently for API
149
- write_to_csv=None # API handles CSV output separately if needed
150
- )
151
- )
152
- # Progress for DataFrame/CSV would need integration into BatchProcessor or this loop
153
- if actual_results_list:
154
- self.run_store.set_batch_total_items(batch_id, len(actual_results_list))
155
- self.run_store.update_batch_progress(batch_id, len(actual_results_list), actual_results_list)
156
-
157
-
158
- self.run_store.update_batch_result(batch_id, actual_results_list)
159
- logger.info(f"Batch run completed (batch_id: {batch_id})", num_results=len(actual_results_list))
160
- return actual_results_list
161
- except Exception as thread_err:
162
- logger.error(f"Error in batch run thread {batch_id}: {thread_err!s}", exc_info=True)
163
- self.run_store.update_batch_status(batch_id, "failed", str(thread_err))
164
- return None
165
- finally:
166
- loop.close()
167
- # --- End of re-integrated threaded batch execution ---
168
-
169
- # Submit the synchronous function to a thread pool from the main event loop
170
- main_loop = asyncio.get_running_loop()
171
- with ThreadPoolExecutor(thread_name_prefix="flock-api-batch") as pool:
172
- await main_loop.run_in_executor(pool, run_batch_sync_in_thread)
173
-
174
- except Exception as e:
175
- logger.error(
176
- f"Error setting up batch run {batch_id} (started with '{request.agent_name}'): {e!s}",
177
- exc_info=True,
178
- )
179
- self.run_store.update_batch_status(batch_id, "failed", str(e))
180
- raise
181
-
182
-
183
-
184
-
185
-
186
- def _type_convert_inputs(
187
- self, agent_name: str, inputs: dict[str, Any]
188
- ) -> dict[str, Any]:
189
- """Converts input values (esp. from forms) to expected Python types."""
190
- typed_inputs = {}
191
- agent_def = self.flock.agents.get(agent_name)
192
- if not agent_def or not agent_def.input or not isinstance(agent_def.input, str):
193
- return inputs # Return original if no spec or spec is not a string
194
-
195
- parsed_fields = self._parse_input_spec(agent_def.input) # Relies on the old UI helper
196
- field_types = {f["name"]: f["type"] for f in parsed_fields}
197
-
198
- for k, v in inputs.items():
199
- target_type_str = field_types.get(k)
200
- if target_type_str:
201
- if target_type_str.startswith("bool"):
202
- typed_inputs[k] = str(v).lower() in ["true", "on", "1", "yes"] if isinstance(v, str) else bool(v)
203
- elif target_type_str.startswith("int"):
204
- try: typed_inputs[k] = int(v)
205
- except (ValueError, TypeError): logger.warning(f"Could not convert '{k}' value '{v}' to int for agent '{agent_name}'"); typed_inputs[k] = v
206
- elif target_type_str.startswith("float"):
207
- try: typed_inputs[k] = float(v)
208
- except (ValueError, TypeError): logger.warning(f"Could not convert '{k}' value '{v}' to float for agent '{agent_name}'"); typed_inputs[k] = v
209
- # TODO: Add list/dict parsing (e.g., json.loads) if type_str indicates these,
210
- # especially if inputs come from HTML forms as strings.
211
- else: typed_inputs[k] = v
212
- else:
213
- typed_inputs[k] = v
214
- return typed_inputs
@@ -1,15 +0,0 @@
1
- # src/flock/core/component/__init__.py
2
- """Unified component system for Flock agents."""
3
-
4
- from .agent_component_base import AgentComponent, AgentComponentConfig
5
- from .evaluation_component import EvaluationComponent
6
- from .routing_component import RoutingComponent
7
- from .utility_component import UtilityComponent
8
-
9
- __all__ = [
10
- "AgentComponent",
11
- "AgentComponentConfig",
12
- "EvaluationComponent",
13
- "RoutingComponent",
14
- "UtilityComponent",
15
- ]