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
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)