flock-core 0.5.0b28__py3-none-any.whl → 0.5.56b0__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 (359) 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.56b0.dist-info/METADATA +747 -0
  162. flock_core-0.5.56b0.dist-info/RECORD +398 -0
  163. flock_core-0.5.56b0.dist-info/entry_points.txt +2 -0
  164. {flock_core-0.5.0b28.dist-info → flock_core-0.5.56b0.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 -22
  197. flock/components/utility/example_utility_component.py +0 -250
  198. flock/components/utility/feedback_utility_component.py +0 -206
  199. flock/components/utility/memory_utility_component.py +0 -550
  200. flock/components/utility/metrics_utility_component.py +0 -700
  201. flock/config.py +0 -61
  202. flock/core/__init__.py +0 -110
  203. flock/core/agent/__init__.py +0 -16
  204. flock/core/agent/default_agent.py +0 -216
  205. flock/core/agent/flock_agent_components.py +0 -104
  206. flock/core/agent/flock_agent_execution.py +0 -101
  207. flock/core/agent/flock_agent_integration.py +0 -260
  208. flock/core/agent/flock_agent_lifecycle.py +0 -186
  209. flock/core/agent/flock_agent_serialization.py +0 -381
  210. flock/core/api/__init__.py +0 -10
  211. flock/core/api/custom_endpoint.py +0 -45
  212. flock/core/api/endpoints.py +0 -254
  213. flock/core/api/main.py +0 -162
  214. flock/core/api/models.py +0 -97
  215. flock/core/api/run_store.py +0 -224
  216. flock/core/api/runner.py +0 -44
  217. flock/core/api/service.py +0 -214
  218. flock/core/component/__init__.py +0 -15
  219. flock/core/component/agent_component_base.py +0 -309
  220. flock/core/component/evaluation_component.py +0 -62
  221. flock/core/component/routing_component.py +0 -74
  222. flock/core/component/utility_component.py +0 -69
  223. flock/core/config/flock_agent_config.py +0 -58
  224. flock/core/config/scheduled_agent_config.py +0 -40
  225. flock/core/context/context.py +0 -213
  226. flock/core/context/context_manager.py +0 -37
  227. flock/core/context/context_vars.py +0 -10
  228. flock/core/evaluation/utils.py +0 -396
  229. flock/core/execution/batch_executor.py +0 -369
  230. flock/core/execution/evaluation_executor.py +0 -438
  231. flock/core/execution/local_executor.py +0 -31
  232. flock/core/execution/opik_executor.py +0 -103
  233. flock/core/execution/temporal_executor.py +0 -164
  234. flock/core/flock.py +0 -634
  235. flock/core/flock_agent.py +0 -336
  236. flock/core/flock_factory.py +0 -613
  237. flock/core/flock_scheduler.py +0 -166
  238. flock/core/flock_server_manager.py +0 -136
  239. flock/core/interpreter/python_interpreter.py +0 -689
  240. flock/core/mcp/__init__.py +0 -1
  241. flock/core/mcp/flock_mcp_server.py +0 -680
  242. flock/core/mcp/mcp_client_manager.py +0 -201
  243. flock/core/mcp/types/__init__.py +0 -1
  244. flock/core/mixin/dspy_integration.py +0 -403
  245. flock/core/mixin/prompt_parser.py +0 -125
  246. flock/core/orchestration/__init__.py +0 -15
  247. flock/core/orchestration/flock_batch_processor.py +0 -94
  248. flock/core/orchestration/flock_evaluator.py +0 -113
  249. flock/core/orchestration/flock_execution.py +0 -295
  250. flock/core/orchestration/flock_initialization.py +0 -149
  251. flock/core/orchestration/flock_server_manager.py +0 -67
  252. flock/core/orchestration/flock_web_server.py +0 -117
  253. flock/core/registry/__init__.py +0 -45
  254. flock/core/registry/agent_registry.py +0 -69
  255. flock/core/registry/callable_registry.py +0 -139
  256. flock/core/registry/component_discovery.py +0 -142
  257. flock/core/registry/component_registry.py +0 -64
  258. flock/core/registry/config_mapping.py +0 -64
  259. flock/core/registry/decorators.py +0 -137
  260. flock/core/registry/registry_hub.py +0 -205
  261. flock/core/registry/server_registry.py +0 -57
  262. flock/core/registry/type_registry.py +0 -86
  263. flock/core/serialization/__init__.py +0 -13
  264. flock/core/serialization/callable_registry.py +0 -52
  265. flock/core/serialization/flock_serializer.py +0 -832
  266. flock/core/serialization/json_encoder.py +0 -41
  267. flock/core/serialization/secure_serializer.py +0 -175
  268. flock/core/serialization/serializable.py +0 -342
  269. flock/core/serialization/serialization_utils.py +0 -412
  270. flock/core/util/file_path_utils.py +0 -223
  271. flock/core/util/hydrator.py +0 -309
  272. flock/core/util/input_resolver.py +0 -164
  273. flock/core/util/loader.py +0 -59
  274. flock/core/util/splitter.py +0 -219
  275. flock/di.py +0 -27
  276. flock/platform/docker_tools.py +0 -49
  277. flock/platform/jaeger_install.py +0 -86
  278. flock/webapp/__init__.py +0 -1
  279. flock/webapp/app/__init__.py +0 -0
  280. flock/webapp/app/api/__init__.py +0 -0
  281. flock/webapp/app/api/agent_management.py +0 -241
  282. flock/webapp/app/api/execution.py +0 -709
  283. flock/webapp/app/api/flock_management.py +0 -129
  284. flock/webapp/app/api/registry_viewer.py +0 -30
  285. flock/webapp/app/chat.py +0 -665
  286. flock/webapp/app/config.py +0 -104
  287. flock/webapp/app/dependencies.py +0 -117
  288. flock/webapp/app/main.py +0 -1070
  289. flock/webapp/app/middleware.py +0 -113
  290. flock/webapp/app/models_ui.py +0 -7
  291. flock/webapp/app/services/__init__.py +0 -0
  292. flock/webapp/app/services/feedback_file_service.py +0 -363
  293. flock/webapp/app/services/flock_service.py +0 -337
  294. flock/webapp/app/services/sharing_models.py +0 -81
  295. flock/webapp/app/services/sharing_store.py +0 -762
  296. flock/webapp/app/templates/theme_mapper.html +0 -326
  297. flock/webapp/app/theme_mapper.py +0 -812
  298. flock/webapp/app/utils.py +0 -85
  299. flock/webapp/run.py +0 -215
  300. flock/webapp/static/css/chat.css +0 -301
  301. flock/webapp/static/css/components.css +0 -167
  302. flock/webapp/static/css/header.css +0 -39
  303. flock/webapp/static/css/layout.css +0 -46
  304. flock/webapp/static/css/sidebar.css +0 -127
  305. flock/webapp/static/css/two-pane.css +0 -48
  306. flock/webapp/templates/base.html +0 -200
  307. flock/webapp/templates/chat.html +0 -152
  308. flock/webapp/templates/chat_settings.html +0 -19
  309. flock/webapp/templates/flock_editor.html +0 -16
  310. flock/webapp/templates/index.html +0 -12
  311. flock/webapp/templates/partials/_agent_detail_form.html +0 -93
  312. flock/webapp/templates/partials/_agent_list.html +0 -18
  313. flock/webapp/templates/partials/_agent_manager_view.html +0 -51
  314. flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
  315. flock/webapp/templates/partials/_chat_container.html +0 -15
  316. flock/webapp/templates/partials/_chat_messages.html +0 -57
  317. flock/webapp/templates/partials/_chat_settings_form.html +0 -85
  318. flock/webapp/templates/partials/_create_flock_form.html +0 -50
  319. flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
  320. flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
  321. flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
  322. flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
  323. flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
  324. flock/webapp/templates/partials/_env_vars_table.html +0 -23
  325. flock/webapp/templates/partials/_execution_form.html +0 -118
  326. flock/webapp/templates/partials/_execution_view_container.html +0 -28
  327. flock/webapp/templates/partials/_flock_file_list.html +0 -23
  328. flock/webapp/templates/partials/_flock_properties_form.html +0 -52
  329. flock/webapp/templates/partials/_flock_upload_form.html +0 -16
  330. flock/webapp/templates/partials/_header_flock_status.html +0 -5
  331. flock/webapp/templates/partials/_load_manager_view.html +0 -49
  332. flock/webapp/templates/partials/_registry_table.html +0 -25
  333. flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
  334. flock/webapp/templates/partials/_results_display.html +0 -78
  335. flock/webapp/templates/partials/_settings_env_content.html +0 -9
  336. flock/webapp/templates/partials/_settings_theme_content.html +0 -14
  337. flock/webapp/templates/partials/_settings_view.html +0 -36
  338. flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
  339. flock/webapp/templates/partials/_share_link_snippet.html +0 -35
  340. flock/webapp/templates/partials/_sidebar.html +0 -74
  341. flock/webapp/templates/partials/_streaming_results_container.html +0 -195
  342. flock/webapp/templates/partials/_structured_data_view.html +0 -40
  343. flock/webapp/templates/partials/_theme_preview.html +0 -36
  344. flock/webapp/templates/registry_viewer.html +0 -84
  345. flock/webapp/templates/shared_run_page.html +0 -140
  346. flock/workflow/__init__.py +0 -0
  347. flock/workflow/activities.py +0 -196
  348. flock/workflow/agent_activities.py +0 -24
  349. flock/workflow/agent_execution_activity.py +0 -202
  350. flock/workflow/flock_workflow.py +0 -214
  351. flock/workflow/temporal_config.py +0 -96
  352. flock/workflow/temporal_setup.py +0 -68
  353. flock_core-0.5.0b28.dist-info/METADATA +0 -274
  354. flock_core-0.5.0b28.dist-info/RECORD +0 -561
  355. flock_core-0.5.0b28.dist-info/entry_points.txt +0 -2
  356. /flock/{core/logging → logging}/formatters/themes.py +0 -0
  357. /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
  358. /flock/{core/mcp → mcp}/util/__init__.py +0 -0
  359. {flock_core-0.5.0b28.dist-info → flock_core-0.5.56b0.dist-info}/WHEEL +0 -0
flock/examples.py ADDED
@@ -0,0 +1,128 @@
1
+ """Concrete demo wiring matching the design document."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+ from pathlib import Path
7
+
8
+
9
+ if __name__ == "__main__" and __package__ is None:
10
+ sys.path.append(str(Path(__file__).resolve().parents[2]))
11
+
12
+ from typing import TYPE_CHECKING
13
+
14
+ from pydantic import BaseModel, Field
15
+
16
+ from flock.artifacts import Artifact
17
+ from flock.components import EngineComponent
18
+ from flock.orchestrator import Flock
19
+ from flock.registry import flock_tool, flock_type, type_registry
20
+ from flock.runtime import EvalInputs, EvalResult
21
+ from flock.utilities import LoggingUtility, MetricsUtility
22
+
23
+
24
+ if TYPE_CHECKING:
25
+ from flock.agent import AgentBuilder
26
+
27
+
28
+ @flock_type
29
+ class Idea(BaseModel):
30
+ topic: str
31
+ genre: str
32
+
33
+
34
+ @flock_type
35
+ class Movie(BaseModel):
36
+ fun_title: str = Field(description="Fun title in CAPS")
37
+ runtime: int = Field(ge=60, le=400)
38
+ synopsis: str
39
+
40
+
41
+ @flock_type
42
+ class Tagline(BaseModel):
43
+ line: str
44
+
45
+
46
+ @flock_tool
47
+ def announce(tagline: Tagline) -> dict[str, str]:
48
+ return {"announced": tagline.line}
49
+
50
+
51
+ class MovieEngine(EngineComponent):
52
+ async def evaluate(self, agent, ctx, inputs: EvalInputs) -> EvalResult:
53
+ idea = Idea(**inputs.artifacts[0].payload)
54
+ synopsis = f"{idea.topic} told as a {idea.genre} adventure."
55
+ movie = Movie(fun_title=idea.topic.upper(), runtime=120, synopsis=synopsis)
56
+ artifact = Artifact(
57
+ type=type_registry.name_for(Movie),
58
+ payload=movie.model_dump(),
59
+ produced_by=agent.name,
60
+ )
61
+ return EvalResult(artifacts=[artifact])
62
+
63
+
64
+ class TaglineEngine(EngineComponent):
65
+ async def evaluate(self, agent, ctx, inputs: EvalInputs) -> EvalResult:
66
+ movie = Movie(**inputs.artifacts[0].payload)
67
+ tagline = Tagline(line=f"Don't miss {movie.fun_title}!")
68
+ artifact = Artifact(
69
+ type=type_registry.name_for(Tagline),
70
+ payload=tagline.model_dump(),
71
+ produced_by=agent.name,
72
+ )
73
+ return EvalResult(artifacts=[artifact])
74
+
75
+
76
+ def create_demo_orchestrator(
77
+ model: str | None = None,
78
+ ) -> tuple[Flock, dict[str, AgentBuilder]]:
79
+ orchestrator = Flock(model)
80
+
81
+ movie = (
82
+ orchestrator.agent("movie")
83
+ .description("Generate a movie concept.")
84
+ .consumes(Idea)
85
+ .publishes(Movie)
86
+ .only_for("tagline", "presenter")
87
+ .with_utilities(MetricsUtility(), LoggingUtility())
88
+ .with_engines(MovieEngine())
89
+ )
90
+
91
+ tagline = (
92
+ orchestrator.agent("tagline")
93
+ .description("Generate a tagline.")
94
+ .consumes(Movie, where=lambda m: 60 <= m.runtime <= 200, from_agents={"movie"})
95
+ .publishes(Tagline)
96
+ .with_engines(TaglineEngine())
97
+ )
98
+
99
+ presenter = (
100
+ orchestrator.agent("presenter")
101
+ .description("Announce the winner.")
102
+ .consumes(Tagline, mode="both")
103
+ .calls(announce)
104
+ )
105
+
106
+ return orchestrator, {"movie": movie, "tagline": tagline, "presenter": presenter}
107
+
108
+
109
+ __all__ = [
110
+ "Idea",
111
+ "Movie",
112
+ "Tagline",
113
+ "announce",
114
+ "create_demo_orchestrator",
115
+ ]
116
+
117
+ if __name__ == "__main__":
118
+ import asyncio
119
+
120
+ async def _demo_run() -> None:
121
+ orchestrator, agents = create_demo_orchestrator()
122
+ idea = Idea(topic="AI agents collaborating", genre="comedy")
123
+ outputs = await orchestrator.arun(agents["movie"], idea)
124
+ await orchestrator.run_until_idle()
125
+ for artifact in outputs:
126
+ print(f"{artifact.type}: {artifact.payload}")
127
+
128
+ asyncio.run(_demo_run())
@@ -1,7 +1,8 @@
1
1
  from importlib.metadata import PackageNotFoundError, version
2
2
 
3
+
3
4
  try:
4
- __version__ = version("flock-core")
5
+ __version__ = version("flock-flow")
5
6
  except PackageNotFoundError:
6
7
  __version__ = "0.2.0"
7
8
 
@@ -51,7 +52,7 @@ def init_console(clear_screen: bool = True, show_banner: bool = True, model: str
51
52
  │ ▒█▀▀▀ █░░ █▀▀█ █▀▀ █░█ │
52
53
  │ ▒█▀▀▀ █░░ █░░█ █░░ █▀▄ │
53
54
  │ ▒█░░░ ▀▀▀ ▀▀▀▀ ▀▀▀ ▀░▀ │
54
- ╰━━━━━━━━v{__version__}━━━━━━━╯
55
+ ╰━━━━━━━━v{__version__}━━━━━━━━━╯
55
56
  🦆 🐤 🐧 🐓
56
57
  """,
57
58
  justify="center",
@@ -63,7 +64,7 @@ def init_console(clear_screen: bool = True, show_banner: bool = True, model: str
63
64
  if show_banner:
64
65
  console.print(banner_text)
65
66
  console.print(
66
- "[italic]'Kea'[/] milestone - [bold]white duck GmbH[/] - [cyan]https://whiteduck.de[/]\n"
67
+ "[italic]'Raven'[/] milestone - [bold]white duck GmbH[/] - [cyan]https://whiteduck.de[/]\n"
67
68
  )
68
69
 
69
70
  if model:
@@ -1,6 +1,5 @@
1
1
  """Flock logging system with Rich integration and structured logging support."""
2
2
 
3
- from .logging import configure_logging
4
-
5
- __all__ = ["configure_logging"]
3
+ # from flock.logging import configure_logging
6
4
 
5
+ # __all__ = ["configure_logging"]
@@ -4,14 +4,13 @@ import os
4
4
  import pathlib
5
5
  import re
6
6
 
7
- theme_folder = pathlib.Path(__file__).parent.parent.parent.parent / "themes"
7
+
8
+ theme_folder = pathlib.Path(__file__).parent.parent.parent / "themes"
8
9
 
9
10
  if not theme_folder.exists():
10
11
  raise FileNotFoundError(f"Theme folder not found: {theme_folder}")
11
12
 
12
- theme_files = [
13
- pathlib.Path(f.path).stem for f in os.scandir(theme_folder) if f.is_file()
14
- ]
13
+ theme_files = [pathlib.Path(f.path).stem for f in os.scandir(theme_folder) if f.is_file()]
15
14
 
16
15
  theme_enum_entries = {}
17
16
  for theme in theme_files:
@@ -153,9 +153,7 @@ def generate_default_rich_block(theme: dict | None = None) -> dict[str, Any]:
153
153
  ),
154
154
  "panel_padding": random.choice([[1, 2], [1, 1], [2, 2], [0, 2]]),
155
155
  "panel_title_align": random.choice(["left", "center", "right"]),
156
- "table_row_styles": random.choice(
157
- [["", "dim"], ["", "italic"], ["", "underline"]]
158
- ),
156
+ "table_row_styles": random.choice([["", "dim"], ["", "italic"], ["", "underline"]]),
159
157
  }
160
158
  # Extra table layout properties (non-content).
161
159
  default_extra_table_props = {
@@ -175,13 +173,12 @@ def generate_default_rich_block(theme: dict | None = None) -> dict[str, Any]:
175
173
  "table_caption_justify": "center",
176
174
  "table_highlight": False,
177
175
  }
178
- defaults = {
176
+ return {
179
177
  **default_color_props,
180
178
  **extra_color_props,
181
179
  **default_non_color_props,
182
180
  **default_extra_table_props,
183
181
  }
184
- return defaults
185
182
 
186
183
 
187
184
  def load_theme_from_file(filepath: str) -> dict:
@@ -207,9 +204,7 @@ def get_default_styles(theme: dict | None) -> dict[str, Any]:
207
204
  else:
208
205
  defaults = generate_default_rich_block(theme)
209
206
  rich_props = theme.get("rich", {})
210
- final_styles = {
211
- key: rich_props.get(key, defaults[key]) for key in defaults
212
- }
207
+ final_styles = {key: rich_props.get(key, defaults[key]) for key in defaults}
213
208
  # Ensure tuple for padding properties.
214
209
  final_styles["panel_padding"] = tuple(final_styles["panel_padding"])
215
210
  if "table_padding" in final_styles:
@@ -272,33 +267,23 @@ def create_rich_renderable(
272
267
  table.add_column("Key", style=styles["column_output"])
273
268
  table.add_column("Value", style=styles["column_value"])
274
269
  for k, v in value.items():
275
- table.add_row(
276
- str(k), create_rich_renderable(v, level + 1, theme, styles)
277
- )
270
+ table.add_row(str(k), create_rich_renderable(v, level + 1, theme, styles))
278
271
  return table
279
272
 
280
- elif isinstance(value, (list, tuple)):
273
+ if isinstance(value, (list, tuple)):
281
274
  if all(isinstance(item, dict) for item in value):
282
275
  sub_tables = []
283
276
  for i, item in enumerate(value):
284
277
  sub_tables.append(f"[bold]Item {i + 1}[/bold]")
285
- sub_tables.append(
286
- create_rich_renderable(item, level + 1, theme, styles)
287
- )
278
+ sub_tables.append(create_rich_renderable(item, level + 1, theme, styles))
288
279
  return Group(*sub_tables)
289
- else:
290
- rendered_items = [
291
- create_rich_renderable(item, level + 1, theme, styles)
292
- for item in value
293
- ]
294
- if all(isinstance(item, str) for item in rendered_items):
295
- return "\n".join(rendered_items)
296
- else:
297
- return Group(*rendered_items)
298
- else:
299
- if isinstance(value, str) and "\n" in value:
300
- return f"\n{value}\n"
301
- return str(value)
280
+ rendered_items = [create_rich_renderable(item, level + 1, theme, styles) for item in value]
281
+ if all(isinstance(item, str) for item in rendered_items):
282
+ return "\n".join(rendered_items)
283
+ return Group(*rendered_items)
284
+ if isinstance(value, str) and "\n" in value:
285
+ return f"\n{value}\n"
286
+ return str(value)
302
287
 
303
288
 
304
289
  # --- Theme Builder Functions --- #
@@ -312,9 +297,7 @@ def load_theme_files(theme_dir: pathlib.Path) -> list[pathlib.Path]:
312
297
  def display_color_palette(theme: dict) -> None:
313
298
  """Display the color palette from a theme's [colors] sections with a color preview."""
314
299
  console = Console()
315
- palette_table = Table(
316
- title="Color Palette", show_header=True, header_style="bold"
317
- )
300
+ palette_table = Table(title="Color Palette", show_header=True, header_style="bold")
318
301
  palette_table.add_column("Section", style="bold")
319
302
  palette_table.add_column("Key", style="italic")
320
303
  palette_table.add_column("Value", style="bold")
@@ -331,9 +314,7 @@ def display_color_palette(theme: dict) -> None:
331
314
  console.print(palette_table)
332
315
 
333
316
 
334
- def generate_sample_rich_blocks(
335
- chosen_theme: dict, count: int
336
- ) -> list[dict[str, Any]]:
317
+ def generate_sample_rich_blocks(chosen_theme: dict, count: int) -> list[dict[str, Any]]:
337
318
  """Generate a list of sample rich blocks (randomized layout) using the chosen theme's colors."""
338
319
  samples = []
339
320
  for _ in range(count):
@@ -349,9 +330,7 @@ def generate_sample_table(sample_theme: dict, dummy_data: dict) -> Panel:
349
330
  # For simplicity, we create our own panel.
350
331
  styles = get_default_styles(sample_theme)
351
332
  # Build a basic table (using our earlier functions)
352
- table = create_rich_renderable(
353
- dummy_data, theme=sample_theme, styles=styles
354
- )
333
+ table = create_rich_renderable(dummy_data, theme=sample_theme, styles=styles)
355
334
  return Panel(
356
335
  table,
357
336
  title="Sample Table",
@@ -373,7 +352,7 @@ def save_theme(theme: dict, filename: pathlib.Path) -> None:
373
352
 
374
353
  def theme_builder():
375
354
  console = Console(force_terminal=True, color_system="truecolor")
376
- themes_dir = pathlib.Path(__file__).parent.parent.parent.parent / "themes"
355
+ themes_dir = pathlib.Path(__file__).parent.parent.parent / "themes"
377
356
  theme_files = load_theme_files(themes_dir)
378
357
 
379
358
  if not theme_files:
@@ -443,9 +422,7 @@ def theme_builder():
443
422
  samples = []
444
423
  for i, rich_block in enumerate(sample_rich_blocks):
445
424
  # Build a sample theme: copy the chosen theme and override its [rich] block.
446
- sample_theme = dict(
447
- chosen_theme
448
- ) # shallow copy (good enough if colors remain unchanged)
425
+ sample_theme = dict(chosen_theme) # shallow copy (good enough if colors remain unchanged)
449
426
  sample_theme["rich"] = rich_block
450
427
  sample_table = generate_sample_table(sample_theme, dummy_data)
451
428
  samples.append((sample_theme, sample_table))
@@ -468,9 +445,7 @@ def theme_builder():
468
445
  return
469
446
 
470
447
  # Ask for file name to save the chosen theme.
471
- filename = console.input(
472
- "\nEnter a filename to save the chosen theme (e.g. mytheme.toml): "
473
- )
448
+ filename = console.input("\nEnter a filename to save the chosen theme (e.g. mytheme.toml): ")
474
449
  save_path = themes_dir / filename
475
450
  save_theme(chosen_sample_theme, save_path)
476
451
  console.print(f"\n[green]Theme saved as {save_path}.[/green]")
@@ -5,21 +5,21 @@ import random
5
5
  import re
6
6
  from typing import Any
7
7
 
8
- from temporalio import workflow
9
-
10
- from flock.core.logging.formatters.themes import OutputTheme
8
+ import toml # install with: pip install toml
9
+ from pydantic import BaseModel
11
10
 
12
- with workflow.unsafe.imports_passed_through():
13
- from pygments.style import Style
14
- from pygments.token import Token
15
- from rich import box
16
- from rich.console import Console, Group
17
- from rich.panel import Panel
18
- from rich.syntax import PygmentsSyntaxTheme, Syntax
19
- from rich.table import Table
20
- from rich.theme import Theme
11
+ # with workflow.unsafe.imports_passed_through():
12
+ from pygments.style import Style
13
+ from pygments.token import Token
14
+ from rich import box
15
+ from rich.console import Console, Group
16
+ from rich.panel import Panel
17
+ from rich.syntax import PygmentsSyntaxTheme, Syntax
18
+ from rich.table import Table
19
+ from rich.theme import Theme
21
20
 
22
- import toml # install with: pip install toml
21
+ # from temporalio import workflow
22
+ from flock.logging.formatters.themes import OutputTheme
23
23
 
24
24
 
25
25
  def resolve_style_string(style_str: str, theme: dict) -> str:
@@ -76,18 +76,10 @@ def generate_default_rich_block(theme: dict | None = None) -> dict[str, Any]:
76
76
  cursor_cursor = theme["colors"]["cursor"].get("cursor", "#d0d0d0")
77
77
  cursor_text = theme["colors"]["cursor"].get("text", "#151515")
78
78
 
79
- primary_background = theme["colors"]["primary"].get(
80
- "background", "#161719"
81
- )
82
- primary_foreground = theme["colors"]["primary"].get(
83
- "foreground", "#c5c8c6"
84
- )
85
- selection_background = theme["colors"]["selection"].get(
86
- "background", "#444444"
87
- )
88
- selection_text = theme["colors"]["selection"].get(
89
- "text", primary_foreground
90
- )
79
+ primary_background = theme["colors"]["primary"].get("background", "#161719")
80
+ primary_foreground = theme["colors"]["primary"].get("foreground", "#c5c8c6")
81
+ selection_background = theme["colors"]["selection"].get("background", "#444444")
82
+ selection_text = theme["colors"]["selection"].get("text", primary_foreground)
91
83
  else:
92
84
  bright_black = "black"
93
85
  bright_blue = "blue"
@@ -155,9 +147,7 @@ def generate_default_rich_block(theme: dict | None = None) -> dict[str, Any]:
155
147
  "panel_padding": random.choice([[1, 2], [1, 1], [2, 2], [0, 2]]),
156
148
  "panel_title_align": random.choice(["left", "center", "right"]),
157
149
  # Add table_row_styles property.
158
- "table_row_styles": random.choice(
159
- [["", "dim"], ["", "italic"], ["", "underline"]]
160
- ),
150
+ "table_row_styles": random.choice([["", "dim"], ["", "italic"], ["", "underline"]]),
161
151
  }
162
152
  # Extra table layout properties (non content properties).
163
153
  default_extra_table_props = {
@@ -178,13 +168,12 @@ def generate_default_rich_block(theme: dict | None = None) -> dict[str, Any]:
178
168
  "table_highlight": False,
179
169
  }
180
170
  # Combine all defaults.
181
- defaults = {
171
+ return {
182
172
  **default_color_props,
183
173
  **extra_color_props,
184
174
  **default_non_color_props,
185
175
  **default_extra_table_props,
186
176
  }
187
- return defaults
188
177
 
189
178
 
190
179
  def load_theme_from_file(filepath: str) -> dict:
@@ -221,9 +210,7 @@ def get_default_styles(theme: dict | None) -> dict[str, Any]:
221
210
  else:
222
211
  defaults = generate_default_rich_block(theme)
223
212
  rich_props = theme.get("rich", {})
224
- final_styles = {
225
- key: rich_props.get(key, defaults[key]) for key in defaults
226
- }
213
+ final_styles = {key: rich_props.get(key, defaults[key]) for key in defaults}
227
214
 
228
215
  # Ensure that panel_padding and table_padding are tuples.
229
216
  final_styles["panel_padding"] = tuple(final_styles["panel_padding"])
@@ -256,14 +243,6 @@ def create_rich_renderable(
256
243
  if styles is None:
257
244
  styles = get_default_styles(theme)
258
245
 
259
- # Convert Pydantic BaseModel instances to dicts for rendering
260
- try:
261
- from pydantic import BaseModel
262
- if isinstance(value, BaseModel):
263
- value = value.model_dump()
264
- except ImportError:
265
- pass
266
-
267
246
  # If the value is a dictionary, render it as a table.
268
247
  if isinstance(value, dict):
269
248
  # Convert table_box string into an actual box style.
@@ -309,41 +288,31 @@ def create_rich_renderable(
309
288
  return table
310
289
 
311
290
  # If the value is a list or tuple, render each item.
312
- elif isinstance(value, list | tuple):
291
+ if isinstance(value, list | tuple):
313
292
  if all(isinstance(item, dict) for item in value):
314
293
  sub_tables = []
315
294
  for i, item in enumerate(value):
316
295
  sub_tables.append(f"[bold]Item {i + 1}[/bold]")
317
296
  sub_tables.append(
318
- create_rich_renderable(
319
- item, level + 1, theme, styles, max_length=max_length
320
- )
297
+ create_rich_renderable(item, level + 1, theme, styles, max_length=max_length)
321
298
  )
322
299
  return Group(*sub_tables)
323
- else:
324
- rendered_items = [
325
- create_rich_renderable(
326
- item, level + 1, theme, styles, max_length=max_length
327
- )
328
- for item in value
329
- ]
330
- if all(isinstance(item, str) for item in rendered_items):
331
- return "\n".join(rendered_items)
332
- else:
333
- return Group(*rendered_items)
300
+ rendered_items = [
301
+ create_rich_renderable(item, level + 1, theme, styles, max_length=max_length)
302
+ for item in value
303
+ ]
304
+ if all(isinstance(item, str) for item in rendered_items):
305
+ return "\n".join(rendered_items)
306
+ return Group(*rendered_items)
334
307
 
335
308
  # Otherwise, return a string representation.
336
- else:
337
- s = str(value).strip()
338
- if max_length > 0 and len(s) > max_length:
339
- omitted = len(s) - max_length
340
- s = (
341
- s[:max_length]
342
- + f"[bold bright_yellow]...(+{omitted}chars)[/bold bright_yellow]"
343
- )
344
- if isinstance(value, str) and "\n" in value:
345
- return f"\n{s}\n"
346
- return s
309
+ s = str(value).strip()
310
+ if max_length > 0 and len(s) > max_length:
311
+ omitted = len(s) - max_length
312
+ s = s[:max_length] + f"[bold bright_yellow]...(+{omitted}chars)[/bold bright_yellow]"
313
+ if isinstance(value, str) and "\n" in value:
314
+ return f"\n{s}\n"
315
+ return s
347
316
 
348
317
 
349
318
  def load_syntax_theme_from_file(filepath: str) -> dict:
@@ -352,12 +321,10 @@ def load_syntax_theme_from_file(filepath: str) -> dict:
352
321
  theme = toml.load(f)
353
322
 
354
323
  if "colors" not in theme:
355
- raise ValueError(
356
- f"Theme file {filepath} does not contain a 'colors' section."
357
- )
324
+ raise ValueError(f"Theme file {filepath} does not contain a 'colors' section.")
358
325
 
359
326
  # Map theme colors to syntax categories
360
- syntax_theme = {
327
+ return {
361
328
  "background": theme["colors"]["primary"].get("background", "#161719"),
362
329
  "text": theme["colors"]["primary"].get("foreground", "#c5c8c6"),
363
330
  "comment": theme["colors"]["normal"].get("black", "#666666"),
@@ -371,8 +338,6 @@ def load_syntax_theme_from_file(filepath: str) -> dict:
371
338
  "error": theme["colors"]["bright"].get("red", "#ff5555"),
372
339
  }
373
340
 
374
- return syntax_theme
375
-
376
341
 
377
342
  def create_rich_syntax_theme(syntax_theme: dict) -> Theme:
378
343
  """Convert a syntax theme dict to a Rich-compatible Theme."""
@@ -476,6 +441,7 @@ class ThemedAgentResultFormatter:
476
441
  table = Table(**table_kwargs)
477
442
  table.add_column("Output", style=styles["column_output"])
478
443
  table.add_column("Value", style=styles["column_value"])
444
+
479
445
  for key, value in result.items():
480
446
  rich_renderable = create_rich_renderable(
481
447
  value,
@@ -497,58 +463,46 @@ class ThemedAgentResultFormatter:
497
463
  padding=styles["panel_padding"],
498
464
  style=styles["panel_style"],
499
465
  )
500
- else:
501
- syntax = Syntax(
502
- s, # The formatted string
503
- "python", # Highlight as Python (change this for other formats)
504
- theme=self.syntax_style, # Choose a Rich theme (matches your color setup)
505
- line_numbers=False,
506
- )
507
- return Panel(
508
- syntax,
509
- title=agent_name,
510
- title_align=styles["panel_title_align"],
511
- border_style=styles["panel_border_style"],
512
- padding=styles["panel_padding"],
513
- style=styles["panel_style"],
514
- )
466
+ syntax = Syntax(
467
+ s, # The formatted string
468
+ "python", # Highlight as Python (change this for other formats)
469
+ theme=self.syntax_style, # Choose a Rich theme (matches your color setup)
470
+ line_numbers=False,
471
+ )
472
+ return Panel(
473
+ syntax,
474
+ title=agent_name,
475
+ title_align=styles["panel_title_align"],
476
+ border_style=styles["panel_border_style"],
477
+ padding=styles["panel_padding"],
478
+ style=styles["panel_style"],
479
+ )
515
480
 
516
- def display_result(self, result: dict[str, Any], agent_name: str) -> None:
481
+ def display_result(self, result: list[BaseModel], agent_name: str) -> None:
517
482
  """Print an agent's result using Rich formatting."""
518
483
  theme = self.theme
519
- themes_dir = (
520
- pathlib.Path(__file__).parent.parent.parent.parent / "themes"
521
- )
484
+ themes_dir = pathlib.Path(__file__).parent.parent.parent / "themes"
522
485
  all_themes = list(themes_dir.glob("*.toml"))
523
- theme = (
524
- theme.value + ".toml"
525
- if not theme.value.endswith(".toml")
526
- else theme.value
527
- )
528
- theme = (
529
- pathlib.Path(__file__).parent.parent.parent.parent
530
- / "themes"
531
- / theme
532
- )
486
+ theme = theme.value + ".toml" if not theme.value.endswith(".toml") else theme.value
487
+ theme = pathlib.Path(__file__).parent.parent.parent / "themes" / theme
533
488
 
534
489
  if pathlib.Path(theme) not in all_themes:
535
- raise ValueError(
536
- f"Invalid theme: {theme}\nAvailable themes: {all_themes}"
537
- )
490
+ raise ValueError(f"Invalid theme: {theme}\nAvailable themes: {all_themes}")
538
491
 
539
492
  theme_dict = load_theme_from_file(theme)
540
493
 
541
494
  styles = get_default_styles(theme_dict)
542
495
  self.styles = styles
543
- self.syntax_style = create_pygments_syntax_theme(
544
- load_syntax_theme_from_file(theme)
545
- )
496
+ self.syntax_style = create_pygments_syntax_theme(load_syntax_theme_from_file(theme))
546
497
 
547
498
  console = Console()
548
- panel = self.format_result(
549
- result=result,
550
- agent_name=agent_name,
551
- theme=theme_dict,
552
- styles=styles,
553
- )
554
- console.print(panel)
499
+ for item in result:
500
+ # basemodel to dict
501
+ item = item.model_dump()
502
+ panel = self.format_result(
503
+ result=item,
504
+ agent_name=agent_name,
505
+ theme=theme_dict,
506
+ styles=styles,
507
+ )
508
+ console.print(panel)