flock-core 0.4.543__py3-none-any.whl → 0.5.0__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 (501) hide show
  1. flock/__init__.py +12 -217
  2. flock/agent.py +1079 -0
  3. flock/api/themes.py +71 -0
  4. flock/artifacts.py +86 -0
  5. flock/cli.py +147 -0
  6. flock/components.py +189 -0
  7. flock/dashboard/__init__.py +30 -0
  8. flock/dashboard/collector.py +559 -0
  9. flock/dashboard/events.py +188 -0
  10. flock/dashboard/graph_builder.py +563 -0
  11. flock/dashboard/launcher.py +235 -0
  12. flock/dashboard/models/graph.py +156 -0
  13. flock/dashboard/service.py +991 -0
  14. flock/dashboard/static_v2/assets/index-DFRnI_mt.js +111 -0
  15. flock/dashboard/static_v2/assets/index-fPLNdmp1.css +1 -0
  16. flock/dashboard/static_v2/index.html +13 -0
  17. flock/dashboard/websocket.py +246 -0
  18. flock/engines/__init__.py +6 -0
  19. flock/engines/dspy_engine.py +932 -0
  20. flock/examples.py +131 -0
  21. flock/frontend/README.md +778 -0
  22. flock/frontend/docs/DESIGN_SYSTEM.md +1980 -0
  23. flock/frontend/index.html +12 -0
  24. flock/frontend/package-lock.json +4337 -0
  25. flock/frontend/package.json +48 -0
  26. flock/frontend/src/App.tsx +139 -0
  27. flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +647 -0
  28. flock/frontend/src/__tests__/integration/indexeddb-persistence.test.tsx +699 -0
  29. flock/frontend/src/components/common/BuildInfo.tsx +39 -0
  30. flock/frontend/src/components/common/EmptyState.module.css +115 -0
  31. flock/frontend/src/components/common/EmptyState.tsx +128 -0
  32. flock/frontend/src/components/common/ErrorBoundary.module.css +169 -0
  33. flock/frontend/src/components/common/ErrorBoundary.tsx +118 -0
  34. flock/frontend/src/components/common/KeyboardShortcutsDialog.css +251 -0
  35. flock/frontend/src/components/common/KeyboardShortcutsDialog.tsx +151 -0
  36. flock/frontend/src/components/common/LoadingSpinner.module.css +97 -0
  37. flock/frontend/src/components/common/LoadingSpinner.tsx +29 -0
  38. flock/frontend/src/components/controls/PublishControl.css +547 -0
  39. flock/frontend/src/components/controls/PublishControl.test.tsx +543 -0
  40. flock/frontend/src/components/controls/PublishControl.tsx +432 -0
  41. flock/frontend/src/components/details/DetailWindowContainer.tsx +58 -0
  42. flock/frontend/src/components/details/LiveOutputTab.test.tsx +792 -0
  43. flock/frontend/src/components/details/LiveOutputTab.tsx +220 -0
  44. flock/frontend/src/components/details/MessageDetailWindow.tsx +439 -0
  45. flock/frontend/src/components/details/MessageHistoryTab.tsx +374 -0
  46. flock/frontend/src/components/details/NodeDetailWindow.test.tsx +501 -0
  47. flock/frontend/src/components/details/NodeDetailWindow.tsx +218 -0
  48. flock/frontend/src/components/details/RunStatusTab.tsx +348 -0
  49. flock/frontend/src/components/details/tabs.test.tsx +1015 -0
  50. flock/frontend/src/components/filters/ArtifactTypeFilter.tsx +21 -0
  51. flock/frontend/src/components/filters/CorrelationIDFilter.module.css +102 -0
  52. flock/frontend/src/components/filters/CorrelationIDFilter.test.tsx +197 -0
  53. flock/frontend/src/components/filters/CorrelationIDFilter.tsx +121 -0
  54. flock/frontend/src/components/filters/FilterFlyout.module.css +104 -0
  55. flock/frontend/src/components/filters/FilterFlyout.tsx +80 -0
  56. flock/frontend/src/components/filters/FilterPills.module.css +220 -0
  57. flock/frontend/src/components/filters/FilterPills.test.tsx +189 -0
  58. flock/frontend/src/components/filters/FilterPills.tsx +143 -0
  59. flock/frontend/src/components/filters/ProducerFilter.tsx +21 -0
  60. flock/frontend/src/components/filters/SavedFiltersControl.module.css +60 -0
  61. flock/frontend/src/components/filters/SavedFiltersControl.test.tsx +158 -0
  62. flock/frontend/src/components/filters/SavedFiltersControl.tsx +159 -0
  63. flock/frontend/src/components/filters/TagFilter.tsx +21 -0
  64. flock/frontend/src/components/filters/TimeRangeFilter.module.css +115 -0
  65. flock/frontend/src/components/filters/TimeRangeFilter.test.tsx +154 -0
  66. flock/frontend/src/components/filters/TimeRangeFilter.tsx +110 -0
  67. flock/frontend/src/components/filters/VisibilityFilter.tsx +21 -0
  68. flock/frontend/src/components/graph/AgentNode.test.tsx +77 -0
  69. flock/frontend/src/components/graph/AgentNode.tsx +324 -0
  70. flock/frontend/src/components/graph/GraphCanvas.tsx +613 -0
  71. flock/frontend/src/components/graph/MessageFlowEdge.tsx +128 -0
  72. flock/frontend/src/components/graph/MessageNode.test.tsx +64 -0
  73. flock/frontend/src/components/graph/MessageNode.tsx +129 -0
  74. flock/frontend/src/components/graph/MiniMap.tsx +47 -0
  75. flock/frontend/src/components/graph/TransformEdge.tsx +123 -0
  76. flock/frontend/src/components/layout/DashboardLayout.css +420 -0
  77. flock/frontend/src/components/layout/DashboardLayout.tsx +287 -0
  78. flock/frontend/src/components/layout/Header.module.css +88 -0
  79. flock/frontend/src/components/layout/Header.tsx +52 -0
  80. flock/frontend/src/components/modules/HistoricalArtifactsModule.module.css +288 -0
  81. flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +450 -0
  82. flock/frontend/src/components/modules/HistoricalArtifactsModuleWrapper.tsx +13 -0
  83. flock/frontend/src/components/modules/JsonAttributeRenderer.tsx +140 -0
  84. flock/frontend/src/components/modules/ModuleRegistry.test.ts +333 -0
  85. flock/frontend/src/components/modules/ModuleRegistry.ts +93 -0
  86. flock/frontend/src/components/modules/ModuleWindow.tsx +223 -0
  87. flock/frontend/src/components/modules/TraceModuleJaeger.tsx +1971 -0
  88. flock/frontend/src/components/modules/TraceModuleJaegerWrapper.tsx +13 -0
  89. flock/frontend/src/components/modules/registerModules.ts +29 -0
  90. flock/frontend/src/components/settings/AdvancedSettings.tsx +175 -0
  91. flock/frontend/src/components/settings/AppearanceSettings.tsx +185 -0
  92. flock/frontend/src/components/settings/GraphSettings.tsx +110 -0
  93. flock/frontend/src/components/settings/MultiSelect.tsx +235 -0
  94. flock/frontend/src/components/settings/SettingsPanel.css +327 -0
  95. flock/frontend/src/components/settings/SettingsPanel.tsx +131 -0
  96. flock/frontend/src/components/settings/ThemeSelector.tsx +298 -0
  97. flock/frontend/src/components/settings/TracingSettings.tsx +404 -0
  98. flock/frontend/src/hooks/useKeyboardShortcuts.ts +148 -0
  99. flock/frontend/src/hooks/useModulePersistence.test.ts +442 -0
  100. flock/frontend/src/hooks/useModulePersistence.ts +154 -0
  101. flock/frontend/src/hooks/useModules.ts +157 -0
  102. flock/frontend/src/hooks/usePersistence.ts +141 -0
  103. flock/frontend/src/main.tsx +13 -0
  104. flock/frontend/src/services/api.ts +337 -0
  105. flock/frontend/src/services/graphService.test.ts +330 -0
  106. flock/frontend/src/services/graphService.ts +75 -0
  107. flock/frontend/src/services/indexeddb.test.ts +793 -0
  108. flock/frontend/src/services/indexeddb.ts +848 -0
  109. flock/frontend/src/services/layout.test.ts +437 -0
  110. flock/frontend/src/services/layout.ts +357 -0
  111. flock/frontend/src/services/themeApplicator.ts +140 -0
  112. flock/frontend/src/services/themeService.ts +77 -0
  113. flock/frontend/src/services/websocket.ts +650 -0
  114. flock/frontend/src/store/filterStore.test.ts +250 -0
  115. flock/frontend/src/store/filterStore.ts +272 -0
  116. flock/frontend/src/store/graphStore.test.ts +570 -0
  117. flock/frontend/src/store/graphStore.ts +462 -0
  118. flock/frontend/src/store/moduleStore.test.ts +253 -0
  119. flock/frontend/src/store/moduleStore.ts +75 -0
  120. flock/frontend/src/store/settingsStore.ts +188 -0
  121. flock/frontend/src/store/streamStore.ts +68 -0
  122. flock/frontend/src/store/uiStore.test.ts +54 -0
  123. flock/frontend/src/store/uiStore.ts +122 -0
  124. flock/frontend/src/store/wsStore.ts +34 -0
  125. flock/frontend/src/styles/index.css +15 -0
  126. flock/frontend/src/styles/scrollbar.css +47 -0
  127. flock/frontend/src/styles/variables.css +488 -0
  128. flock/frontend/src/test/setup.ts +1 -0
  129. flock/frontend/src/types/filters.ts +47 -0
  130. flock/frontend/src/types/graph.ts +95 -0
  131. flock/frontend/src/types/modules.ts +10 -0
  132. flock/frontend/src/types/theme.ts +55 -0
  133. flock/frontend/src/utils/artifacts.ts +24 -0
  134. flock/frontend/src/utils/mockData.ts +98 -0
  135. flock/frontend/src/utils/performance.ts +16 -0
  136. flock/frontend/src/vite-env.d.ts +17 -0
  137. flock/frontend/tsconfig.json +27 -0
  138. flock/frontend/tsconfig.node.json +11 -0
  139. flock/frontend/vite.config.ts +25 -0
  140. flock/frontend/vitest.config.ts +11 -0
  141. flock/{core/util → helper}/cli_helper.py +9 -5
  142. flock/{core/logging → logging}/__init__.py +2 -3
  143. flock/logging/auto_trace.py +159 -0
  144. flock/{core/logging → logging}/formatters/enum_builder.py +3 -4
  145. flock/{core/logging → logging}/formatters/theme_builder.py +19 -44
  146. flock/{core/logging → logging}/formatters/themed_formatter.py +69 -107
  147. flock/{core/logging → logging}/logging.py +78 -61
  148. flock/{core/logging → logging}/telemetry.py +66 -26
  149. flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
  150. flock/logging/telemetry_exporter/duckdb_exporter.py +216 -0
  151. flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +13 -10
  152. flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
  153. flock/logging/trace_and_logged.py +304 -0
  154. flock/mcp/__init__.py +91 -0
  155. flock/{core/mcp/mcp_client.py → mcp/client.py} +131 -158
  156. flock/{core/mcp/mcp_config.py → mcp/config.py} +86 -132
  157. flock/mcp/manager.py +286 -0
  158. flock/mcp/servers/sse/__init__.py +1 -1
  159. flock/mcp/servers/sse/flock_sse_server.py +16 -58
  160. flock/mcp/servers/stdio/__init__.py +1 -1
  161. flock/mcp/servers/stdio/flock_stdio_server.py +13 -53
  162. flock/mcp/servers/streamable_http/flock_streamable_http_server.py +22 -67
  163. flock/mcp/servers/websockets/flock_websocket_server.py +12 -45
  164. flock/{core/mcp/flock_mcp_tool_base.py → mcp/tool.py} +24 -78
  165. flock/mcp/types/__init__.py +42 -0
  166. flock/{core/mcp → mcp}/types/callbacks.py +12 -15
  167. flock/{core/mcp → mcp}/types/factories.py +7 -6
  168. flock/{core/mcp → mcp}/types/handlers.py +13 -18
  169. flock/{core/mcp → mcp}/types/types.py +70 -74
  170. flock/{core/mcp → mcp}/util/helpers.py +3 -3
  171. flock/orchestrator.py +970 -0
  172. flock/registry.py +148 -0
  173. flock/runtime.py +262 -0
  174. flock/service.py +277 -0
  175. flock/store.py +1214 -0
  176. flock/subscription.py +111 -0
  177. flock/themes/andromeda.toml +1 -1
  178. flock/themes/apple-system-colors.toml +1 -1
  179. flock/themes/arcoiris.toml +1 -1
  180. flock/themes/atomonelight.toml +1 -1
  181. flock/themes/ayu copy.toml +1 -1
  182. flock/themes/ayu-light.toml +1 -1
  183. flock/themes/belafonte-day.toml +1 -1
  184. flock/themes/belafonte-night.toml +1 -1
  185. flock/themes/blulocodark.toml +1 -1
  186. flock/themes/breeze.toml +1 -1
  187. flock/themes/broadcast.toml +1 -1
  188. flock/themes/brogrammer.toml +1 -1
  189. flock/themes/builtin-dark.toml +1 -1
  190. flock/themes/builtin-pastel-dark.toml +1 -1
  191. flock/themes/catppuccin-latte.toml +1 -1
  192. flock/themes/catppuccin-macchiato.toml +1 -1
  193. flock/themes/catppuccin-mocha.toml +1 -1
  194. flock/themes/cga.toml +1 -1
  195. flock/themes/chalk.toml +1 -1
  196. flock/themes/ciapre.toml +1 -1
  197. flock/themes/coffee-theme.toml +1 -1
  198. flock/themes/cyberpunkscarletprotocol.toml +1 -1
  199. flock/themes/dark+.toml +1 -1
  200. flock/themes/darkermatrix.toml +1 -1
  201. flock/themes/darkmatrix.toml +2 -2
  202. flock/themes/darkside.toml +1 -1
  203. flock/themes/deep.toml +2 -2
  204. flock/themes/desert.toml +1 -1
  205. flock/themes/django.toml +1 -1
  206. flock/themes/djangosmooth.toml +1 -1
  207. flock/themes/doomone.toml +1 -1
  208. flock/themes/dotgov.toml +1 -1
  209. flock/themes/dracula+.toml +1 -1
  210. flock/themes/duckbones.toml +1 -1
  211. flock/themes/encom.toml +1 -1
  212. flock/themes/espresso.toml +1 -1
  213. flock/themes/everblush.toml +1 -1
  214. flock/themes/fairyfloss.toml +1 -1
  215. flock/themes/fideloper.toml +1 -1
  216. flock/themes/fishtank.toml +1 -1
  217. flock/themes/flexoki-light.toml +1 -1
  218. flock/themes/floraverse.toml +1 -1
  219. flock/themes/framer.toml +1 -1
  220. flock/themes/galizur.toml +1 -1
  221. flock/themes/github.toml +1 -1
  222. flock/themes/grass.toml +1 -1
  223. flock/themes/grey-green.toml +1 -1
  224. flock/themes/gruvboxlight.toml +1 -1
  225. flock/themes/guezwhoz.toml +1 -1
  226. flock/themes/harper.toml +1 -1
  227. flock/themes/hax0r-blue.toml +1 -1
  228. flock/themes/hopscotch.256.toml +1 -1
  229. flock/themes/ic-green-ppl.toml +1 -1
  230. flock/themes/iceberg-dark.toml +1 -1
  231. flock/themes/japanesque.toml +1 -1
  232. flock/themes/jubi.toml +1 -1
  233. flock/themes/kibble.toml +1 -1
  234. flock/themes/kolorit.toml +1 -1
  235. flock/themes/kurokula.toml +1 -1
  236. flock/themes/materialdesigncolors.toml +1 -1
  237. flock/themes/matrix.toml +1 -1
  238. flock/themes/mellifluous.toml +1 -1
  239. flock/themes/midnight-in-mojave.toml +1 -1
  240. flock/themes/monokai-remastered.toml +1 -1
  241. flock/themes/monokai-soda.toml +1 -1
  242. flock/themes/neon.toml +1 -1
  243. flock/themes/neopolitan.toml +5 -5
  244. flock/themes/nord-light.toml +1 -1
  245. flock/themes/ocean.toml +1 -1
  246. flock/themes/onehalfdark.toml +1 -1
  247. flock/themes/onehalflight.toml +1 -1
  248. flock/themes/palenighthc.toml +1 -1
  249. flock/themes/paulmillr.toml +1 -1
  250. flock/themes/pencildark.toml +1 -1
  251. flock/themes/pnevma.toml +1 -1
  252. flock/themes/purple-rain.toml +1 -1
  253. flock/themes/purplepeter.toml +1 -1
  254. flock/themes/raycast-dark.toml +1 -1
  255. flock/themes/red-sands.toml +1 -1
  256. flock/themes/relaxed.toml +1 -1
  257. flock/themes/retro.toml +1 -1
  258. flock/themes/rose-pine.toml +1 -1
  259. flock/themes/royal.toml +1 -1
  260. flock/themes/ryuuko.toml +1 -1
  261. flock/themes/sakura.toml +1 -1
  262. flock/themes/scarlet-protocol.toml +1 -1
  263. flock/themes/seoulbones-dark.toml +1 -1
  264. flock/themes/shades-of-purple.toml +1 -1
  265. flock/themes/smyck.toml +1 -1
  266. flock/themes/softserver.toml +1 -1
  267. flock/themes/solarized-darcula.toml +1 -1
  268. flock/themes/square.toml +1 -1
  269. flock/themes/sugarplum.toml +1 -1
  270. flock/themes/thayer-bright.toml +1 -1
  271. flock/themes/tokyonight.toml +1 -1
  272. flock/themes/tomorrow.toml +1 -1
  273. flock/themes/ubuntu.toml +1 -1
  274. flock/themes/ultradark.toml +1 -1
  275. flock/themes/ultraviolent.toml +1 -1
  276. flock/themes/unikitty.toml +1 -1
  277. flock/themes/urple.toml +1 -1
  278. flock/themes/vesper.toml +1 -1
  279. flock/themes/vimbones.toml +1 -1
  280. flock/themes/wildcherry.toml +1 -1
  281. flock/themes/wilmersdorf.toml +1 -1
  282. flock/themes/wryan.toml +1 -1
  283. flock/themes/xcodedarkhc.toml +1 -1
  284. flock/themes/xcodelight.toml +1 -1
  285. flock/themes/zenbones-light.toml +1 -1
  286. flock/themes/zenwritten-dark.toml +1 -1
  287. flock/utilities.py +301 -0
  288. flock/utility/output_utility_component.py +226 -0
  289. flock/visibility.py +107 -0
  290. flock_core-0.5.0.dist-info/METADATA +964 -0
  291. flock_core-0.5.0.dist-info/RECORD +525 -0
  292. flock_core-0.5.0.dist-info/entry_points.txt +2 -0
  293. {flock_core-0.4.543.dist-info → flock_core-0.5.0.dist-info}/licenses/LICENSE +1 -1
  294. flock/adapter/__init__.py +0 -14
  295. flock/adapter/azure_adapter.py +0 -68
  296. flock/adapter/chroma_adapter.py +0 -73
  297. flock/adapter/faiss_adapter.py +0 -97
  298. flock/adapter/pinecone_adapter.py +0 -51
  299. flock/adapter/vector_base.py +0 -47
  300. flock/cli/assets/release_notes.md +0 -140
  301. flock/cli/config.py +0 -8
  302. flock/cli/constants.py +0 -36
  303. flock/cli/create_agent.py +0 -1
  304. flock/cli/create_flock.py +0 -280
  305. flock/cli/execute_flock.py +0 -620
  306. flock/cli/load_agent.py +0 -1
  307. flock/cli/load_examples.py +0 -1
  308. flock/cli/load_flock.py +0 -192
  309. flock/cli/load_release_notes.py +0 -20
  310. flock/cli/loaded_flock_cli.py +0 -254
  311. flock/cli/manage_agents.py +0 -459
  312. flock/cli/registry_management.py +0 -889
  313. flock/cli/runner.py +0 -41
  314. flock/cli/settings.py +0 -857
  315. flock/cli/utils.py +0 -135
  316. flock/cli/view_results.py +0 -29
  317. flock/cli/yaml_editor.py +0 -396
  318. flock/config.py +0 -56
  319. flock/core/__init__.py +0 -44
  320. flock/core/api/__init__.py +0 -10
  321. flock/core/api/custom_endpoint.py +0 -45
  322. flock/core/api/endpoints.py +0 -262
  323. flock/core/api/main.py +0 -162
  324. flock/core/api/models.py +0 -101
  325. flock/core/api/run_store.py +0 -224
  326. flock/core/api/runner.py +0 -44
  327. flock/core/api/service.py +0 -214
  328. flock/core/config/flock_agent_config.py +0 -11
  329. flock/core/config/scheduled_agent_config.py +0 -40
  330. flock/core/context/context.py +0 -214
  331. flock/core/context/context_manager.py +0 -40
  332. flock/core/context/context_vars.py +0 -11
  333. flock/core/evaluation/utils.py +0 -395
  334. flock/core/execution/batch_executor.py +0 -369
  335. flock/core/execution/evaluation_executor.py +0 -438
  336. flock/core/execution/local_executor.py +0 -31
  337. flock/core/execution/opik_executor.py +0 -103
  338. flock/core/execution/temporal_executor.py +0 -166
  339. flock/core/flock.py +0 -1003
  340. flock/core/flock_agent.py +0 -1258
  341. flock/core/flock_evaluator.py +0 -60
  342. flock/core/flock_factory.py +0 -513
  343. flock/core/flock_module.py +0 -207
  344. flock/core/flock_registry.py +0 -702
  345. flock/core/flock_router.py +0 -83
  346. flock/core/flock_scheduler.py +0 -166
  347. flock/core/flock_server_manager.py +0 -136
  348. flock/core/interpreter/python_interpreter.py +0 -689
  349. flock/core/logging/live_capture.py +0 -137
  350. flock/core/logging/trace_and_logged.py +0 -59
  351. flock/core/mcp/__init__.py +0 -1
  352. flock/core/mcp/flock_mcp_server.py +0 -640
  353. flock/core/mcp/mcp_client_manager.py +0 -201
  354. flock/core/mcp/types/__init__.py +0 -1
  355. flock/core/mixin/dspy_integration.py +0 -445
  356. flock/core/mixin/prompt_parser.py +0 -125
  357. flock/core/serialization/__init__.py +0 -13
  358. flock/core/serialization/callable_registry.py +0 -52
  359. flock/core/serialization/flock_serializer.py +0 -854
  360. flock/core/serialization/json_encoder.py +0 -41
  361. flock/core/serialization/secure_serializer.py +0 -175
  362. flock/core/serialization/serializable.py +0 -342
  363. flock/core/serialization/serialization_utils.py +0 -409
  364. flock/core/util/file_path_utils.py +0 -223
  365. flock/core/util/hydrator.py +0 -309
  366. flock/core/util/input_resolver.py +0 -141
  367. flock/core/util/loader.py +0 -59
  368. flock/core/util/splitter.py +0 -219
  369. flock/di.py +0 -41
  370. flock/evaluators/__init__.py +0 -1
  371. flock/evaluators/declarative/__init__.py +0 -1
  372. flock/evaluators/declarative/declarative_evaluator.py +0 -217
  373. flock/evaluators/memory/memory_evaluator.py +0 -90
  374. flock/evaluators/test/test_case_evaluator.py +0 -38
  375. flock/evaluators/zep/zep_evaluator.py +0 -59
  376. flock/modules/__init__.py +0 -1
  377. flock/modules/assertion/__init__.py +0 -1
  378. flock/modules/assertion/assertion_module.py +0 -286
  379. flock/modules/callback/__init__.py +0 -1
  380. flock/modules/callback/callback_module.py +0 -91
  381. flock/modules/enterprise_memory/README.md +0 -99
  382. flock/modules/enterprise_memory/enterprise_memory_module.py +0 -526
  383. flock/modules/mem0/__init__.py +0 -1
  384. flock/modules/mem0/mem0_module.py +0 -126
  385. flock/modules/mem0_async/__init__.py +0 -1
  386. flock/modules/mem0_async/async_mem0_module.py +0 -126
  387. flock/modules/memory/__init__.py +0 -1
  388. flock/modules/memory/memory_module.py +0 -429
  389. flock/modules/memory/memory_parser.py +0 -125
  390. flock/modules/memory/memory_storage.py +0 -736
  391. flock/modules/output/__init__.py +0 -1
  392. flock/modules/output/output_module.py +0 -196
  393. flock/modules/performance/__init__.py +0 -1
  394. flock/modules/performance/metrics_module.py +0 -678
  395. flock/modules/zep/__init__.py +0 -1
  396. flock/modules/zep/zep_module.py +0 -192
  397. flock/platform/docker_tools.py +0 -49
  398. flock/platform/jaeger_install.py +0 -86
  399. flock/routers/__init__.py +0 -1
  400. flock/routers/agent/__init__.py +0 -1
  401. flock/routers/agent/agent_router.py +0 -236
  402. flock/routers/agent/handoff_agent.py +0 -58
  403. flock/routers/conditional/conditional_router.py +0 -486
  404. flock/routers/default/__init__.py +0 -1
  405. flock/routers/default/default_router.py +0 -80
  406. flock/routers/feedback/feedback_router.py +0 -114
  407. flock/routers/list_generator/list_generator_router.py +0 -166
  408. flock/routers/llm/__init__.py +0 -1
  409. flock/routers/llm/llm_router.py +0 -365
  410. flock/tools/__init__.py +0 -0
  411. flock/tools/azure_tools.py +0 -781
  412. flock/tools/code_tools.py +0 -167
  413. flock/tools/file_tools.py +0 -149
  414. flock/tools/github_tools.py +0 -157
  415. flock/tools/markdown_tools.py +0 -205
  416. flock/tools/system_tools.py +0 -9
  417. flock/tools/text_tools.py +0 -810
  418. flock/tools/web_tools.py +0 -92
  419. flock/tools/zendesk_tools.py +0 -501
  420. flock/webapp/__init__.py +0 -1
  421. flock/webapp/app/__init__.py +0 -0
  422. flock/webapp/app/api/__init__.py +0 -0
  423. flock/webapp/app/api/agent_management.py +0 -237
  424. flock/webapp/app/api/execution.py +0 -503
  425. flock/webapp/app/api/flock_management.py +0 -125
  426. flock/webapp/app/api/registry_viewer.py +0 -29
  427. flock/webapp/app/chat.py +0 -662
  428. flock/webapp/app/config.py +0 -104
  429. flock/webapp/app/dependencies.py +0 -117
  430. flock/webapp/app/main.py +0 -1086
  431. flock/webapp/app/middleware.py +0 -113
  432. flock/webapp/app/models_ui.py +0 -7
  433. flock/webapp/app/services/__init__.py +0 -0
  434. flock/webapp/app/services/feedback_file_service.py +0 -363
  435. flock/webapp/app/services/flock_service.py +0 -345
  436. flock/webapp/app/services/sharing_models.py +0 -81
  437. flock/webapp/app/services/sharing_store.py +0 -597
  438. flock/webapp/app/templates/theme_mapper.html +0 -326
  439. flock/webapp/app/theme_mapper.py +0 -811
  440. flock/webapp/app/utils.py +0 -85
  441. flock/webapp/run.py +0 -219
  442. flock/webapp/static/css/chat.css +0 -301
  443. flock/webapp/static/css/components.css +0 -167
  444. flock/webapp/static/css/header.css +0 -39
  445. flock/webapp/static/css/layout.css +0 -281
  446. flock/webapp/static/css/sidebar.css +0 -127
  447. flock/webapp/static/css/two-pane.css +0 -48
  448. flock/webapp/templates/base.html +0 -389
  449. flock/webapp/templates/chat.html +0 -152
  450. flock/webapp/templates/chat_settings.html +0 -19
  451. flock/webapp/templates/flock_editor.html +0 -16
  452. flock/webapp/templates/index.html +0 -12
  453. flock/webapp/templates/partials/_agent_detail_form.html +0 -93
  454. flock/webapp/templates/partials/_agent_list.html +0 -18
  455. flock/webapp/templates/partials/_agent_manager_view.html +0 -51
  456. flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
  457. flock/webapp/templates/partials/_chat_container.html +0 -15
  458. flock/webapp/templates/partials/_chat_messages.html +0 -57
  459. flock/webapp/templates/partials/_chat_settings_form.html +0 -85
  460. flock/webapp/templates/partials/_create_flock_form.html +0 -50
  461. flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
  462. flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
  463. flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
  464. flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
  465. flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
  466. flock/webapp/templates/partials/_env_vars_table.html +0 -23
  467. flock/webapp/templates/partials/_execution_form.html +0 -127
  468. flock/webapp/templates/partials/_execution_view_container.html +0 -28
  469. flock/webapp/templates/partials/_flock_file_list.html +0 -23
  470. flock/webapp/templates/partials/_flock_properties_form.html +0 -52
  471. flock/webapp/templates/partials/_flock_upload_form.html +0 -16
  472. flock/webapp/templates/partials/_header_flock_status.html +0 -5
  473. flock/webapp/templates/partials/_live_logs.html +0 -13
  474. flock/webapp/templates/partials/_load_manager_view.html +0 -49
  475. flock/webapp/templates/partials/_registry_table.html +0 -25
  476. flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
  477. flock/webapp/templates/partials/_results_display.html +0 -78
  478. flock/webapp/templates/partials/_settings_env_content.html +0 -9
  479. flock/webapp/templates/partials/_settings_theme_content.html +0 -14
  480. flock/webapp/templates/partials/_settings_view.html +0 -36
  481. flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
  482. flock/webapp/templates/partials/_share_link_snippet.html +0 -35
  483. flock/webapp/templates/partials/_sidebar.html +0 -74
  484. flock/webapp/templates/partials/_structured_data_view.html +0 -40
  485. flock/webapp/templates/partials/_theme_preview.html +0 -36
  486. flock/webapp/templates/registry_viewer.html +0 -84
  487. flock/webapp/templates/shared_run_page.html +0 -140
  488. flock/workflow/__init__.py +0 -0
  489. flock/workflow/activities.py +0 -237
  490. flock/workflow/agent_activities.py +0 -24
  491. flock/workflow/agent_execution_activity.py +0 -240
  492. flock/workflow/flock_workflow.py +0 -225
  493. flock/workflow/temporal_config.py +0 -96
  494. flock/workflow/temporal_setup.py +0 -60
  495. flock_core-0.4.543.dist-info/METADATA +0 -676
  496. flock_core-0.4.543.dist-info/RECORD +0 -572
  497. flock_core-0.4.543.dist-info/entry_points.txt +0 -2
  498. /flock/{core/logging → logging}/formatters/themes.py +0 -0
  499. /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
  500. /flock/{core/mcp → mcp}/util/__init__.py +0 -0
  501. {flock_core-0.4.543.dist-info → flock_core-0.5.0.dist-info}/WHEEL +0 -0
@@ -1,486 +0,0 @@
1
- # src/flock/routers/conditional/conditional_router.py
2
-
3
- import re
4
- from collections.abc import Callable
5
- from typing import Any, Literal
6
-
7
- from pydantic import Field, model_validator
8
-
9
- from flock.core.context.context import FlockContext
10
- from flock.core.flock_agent import FlockAgent
11
- from flock.core.flock_registry import flock_component, get_registry
12
- from flock.core.flock_router import (
13
- FlockRouter,
14
- FlockRouterConfig,
15
- HandOffRequest,
16
- )
17
- from flock.core.logging.logging import get_logger
18
-
19
- logger = get_logger("router.conditional")
20
-
21
-
22
- class ConditionalRouterConfig(FlockRouterConfig):
23
- """Configuration for the ConditionalRouter."""
24
-
25
- condition_context_key: str = Field(
26
- default="flock.condition",
27
- description="Context key containing the value to evaluate the condition against.",
28
- )
29
-
30
- # --- Define ONE type of condition check ---
31
- condition_callable: (
32
- str | Callable[[Any], tuple[bool, str | None]] | None
33
- ) = Field(
34
- default=None,
35
- description="A callable (or registered name) that takes the context value and returns a tuple containing: (bool: True if condition passed, False otherwise, Optional[str]: Feedback message if condition failed).",
36
- )
37
- # String Checks
38
- expected_string: str | None = Field(
39
- default=None, description="String value to compare against."
40
- )
41
- string_mode: Literal[
42
- "equals",
43
- "contains",
44
- "regex",
45
- "startswith",
46
- "endswith",
47
- "not_equals",
48
- "not_contains",
49
- ] = Field(default="equals", description="How to compare strings.")
50
- ignore_case: bool = Field(
51
- default=True, description="Ignore case during string comparison."
52
- )
53
- # Length Checks (String or List)
54
- min_length: int | None = Field(
55
- default=None,
56
- description="Minimum length for strings or items for lists.",
57
- )
58
- max_length: int | None = Field(
59
- default=None,
60
- description="Maximum length for strings or items for lists.",
61
- )
62
- # Number Checks
63
- expected_number: int | float | None = Field(
64
- default=None, description="Number to compare against."
65
- )
66
- number_mode: Literal["<", "<=", "==", "!=", ">=", ">"] = Field(
67
- default="==", description="How to compare numbers."
68
- )
69
- # List Checks
70
- min_items: int | None = Field(
71
- default=None, description="Minimum number of items in a list."
72
- )
73
- max_items: int | None = Field(
74
- default=None, description="Maximum number of items in a list."
75
- )
76
- # Type Check
77
- expected_type_name: str | None = Field(
78
- default=None,
79
- description="Registered name of the expected Python type (e.g., 'str', 'list', 'MyCustomType').",
80
- )
81
- # Boolean Check
82
- expected_bool: bool | None = Field(
83
- default=None, description="Expected boolean value (True or False)."
84
- )
85
- # Existence Check
86
- check_exists: bool | None = Field(
87
- default=None,
88
- description="If True, succeeds if key exists; if False, succeeds if key *doesn't* exist. Ignores value.",
89
- )
90
-
91
- # --- Routing Targets ---
92
- success_agent: str | None = Field(
93
- default=None,
94
- description="Agent name to route to if the condition evaluates to True.",
95
- )
96
- failure_agent: str | None = Field(
97
- default=None,
98
- description="Agent name to route to if the condition evaluates to False (after retries, if enabled).",
99
- )
100
- retry_agent: str | None = Field(
101
- default=None,
102
- description="Agent name to route to if the condition evaluates to False (during retries, if enabled).",
103
- )
104
-
105
- # --- Optional Retry Logic (for Failure Path) ---
106
- retry_on_failure: bool = Field(
107
- default=False,
108
- description="If True, route back to the retry_agent on failure before going to failure_agent.",
109
- )
110
- max_retries: int = Field(
111
- default=1,
112
- description="Maximum number of times to retry the current agent on failure.",
113
- )
114
- feedback_context_key: str | None = Field(
115
- default="flock.assertion_feedback", # Useful if paired with AssertionCheckerModule
116
- description="Optional context key containing feedback message to potentially include when retrying.",
117
- )
118
- feedback_on_failure: str | None = Field(
119
- default=None,
120
- description="Default feedback message to use when condition evaluation fails.",
121
- )
122
- retry_count_context_key_prefix: str = Field(
123
- default="flock.conditional_retry_count_",
124
- description="Internal prefix for context key storing retry attempts per agent.",
125
- )
126
-
127
- # --- Validator to ensure only one condition type is set ---
128
- @model_validator(mode="after")
129
- def check_exclusive_condition(self) -> "ConditionalRouterConfig":
130
- conditions_set = [
131
- self.condition_callable is not None,
132
- self.expected_string is not None
133
- or self.min_length is not None
134
- or self.max_length is not None, # String/Length group
135
- self.expected_number is not None, # Number group
136
- self.min_items is not None
137
- or self.max_items is not None, # List size group
138
- self.expected_type_name is not None, # Type group
139
- self.expected_bool is not None, # Bool group
140
- self.check_exists is not None, # Existence group
141
- ]
142
- if sum(conditions_set) > 1:
143
- raise ValueError(
144
- "Only one type of condition (callable, string/length, number, list size, type, boolean, exists) can be configured per ConditionalRouter."
145
- )
146
- if sum(conditions_set) == 0:
147
- raise ValueError(
148
- "At least one condition type must be configured for ConditionalRouter."
149
- )
150
- return self
151
-
152
-
153
- @flock_component(config_class=ConditionalRouterConfig)
154
- class ConditionalRouter(FlockRouter):
155
- """Routes workflow based on evaluating a condition against a value in the FlockContext.
156
- Supports various built-in checks (string, number, list, type, bool, existence)
157
- or a custom callable. Can optionally retry the current agent on failure.
158
- """
159
-
160
- name: str = "conditional_router"
161
- config: ConditionalRouterConfig = Field(
162
- default_factory=ConditionalRouterConfig
163
- )
164
-
165
- def _evaluate_condition(self, value: Any) -> tuple[bool, str | None]:
166
- """Evaluates the condition based on the router's configuration.
167
-
168
- Returns:
169
- Tuple[bool, Optional[str]]: A tuple containing:
170
- - bool: True if the condition passed, False otherwise.
171
- - Optional[str]: A feedback message if the condition failed, otherwise None.
172
- """
173
- cfg = self.config
174
- condition_passed = False
175
- feedback = cfg.feedback_on_failure # Default feedback
176
- condition_type = "unknown"
177
-
178
- try:
179
- # 0. Check Existence first (simplest)
180
- if cfg.check_exists is not None:
181
- condition_type = "existence"
182
- value_exists = value is not None
183
- condition_passed = (
184
- value_exists if cfg.check_exists else not value_exists
185
- )
186
- if not condition_passed:
187
- feedback = f"Existence check failed: Expected key '{cfg.condition_context_key}' to {'exist' if cfg.check_exists else 'not exist or be None'}, but it was {'found' if value_exists else 'missing/None'}."
188
-
189
- # 1. Custom Callable
190
- elif cfg.condition_callable:
191
- condition_type = "callable"
192
- callable_func = cfg.condition_callable
193
- if isinstance(callable_func, str): # Lookup registered callable
194
- registry = get_registry()
195
- try:
196
- callable_func = registry.get_callable(callable_func)
197
- except KeyError:
198
- feedback = f"Condition callable '{cfg.condition_callable}' not found in registry."
199
- logger.error(feedback)
200
- return False, feedback # Treat as failure
201
-
202
- if callable(callable_func):
203
- eval_result = callable_func(value)
204
- if (
205
- isinstance(eval_result, tuple)
206
- and len(eval_result) == 2
207
- and isinstance(eval_result[0], bool)
208
- ):
209
- condition_passed, custom_feedback = eval_result
210
- if not condition_passed and isinstance(
211
- custom_feedback, str
212
- ):
213
- feedback = custom_feedback
214
- elif isinstance(eval_result, bool):
215
- condition_passed = eval_result
216
- if not condition_passed:
217
- feedback = f"Callable condition '{getattr(callable_func, '__name__', 'anonymous')}' returned False."
218
- else:
219
- feedback = f"Condition callable '{getattr(callable_func, '__name__', 'anonymous')}' returned unexpected type: {type(eval_result)}."
220
- logger.warning(feedback)
221
- return False, feedback # Treat as failure
222
- else:
223
- feedback = f"Configured condition_callable '{cfg.condition_callable}' is not callable."
224
- logger.error(feedback)
225
- return False, feedback
226
-
227
- # 2. String / Length Checks
228
- elif (
229
- cfg.expected_string is not None
230
- or cfg.min_length is not None
231
- or cfg.max_length is not None
232
- ):
233
- condition_type = "string/length"
234
- if not isinstance(value, str):
235
- feedback = f"Cannot perform string/length check on non-string value: {type(value)}."
236
- logger.warning(feedback)
237
- return False, feedback
238
- s_value = value
239
- val_len = len(s_value)
240
- length_passed = True
241
- length_feedback = []
242
- if cfg.min_length is not None and val_len < cfg.min_length:
243
- length_passed = False
244
- length_feedback.append(
245
- f"length {val_len} is less than minimum {cfg.min_length}"
246
- )
247
- if cfg.max_length is not None and val_len > cfg.max_length:
248
- length_passed = False
249
- length_feedback.append(
250
- f"length {val_len} is greater than maximum {cfg.max_length}"
251
- )
252
-
253
- content_passed = True
254
- content_feedback = ""
255
- if cfg.expected_string is not None:
256
- expected = cfg.expected_string
257
- s1 = s_value if not cfg.ignore_case else s_value.lower()
258
- s2 = expected if not cfg.ignore_case else expected.lower()
259
- mode = cfg.string_mode
260
- if mode == "equals":
261
- content_passed = s1 == s2
262
- elif mode == "contains":
263
- content_passed = s2 in s1
264
- elif mode == "startswith":
265
- content_passed = s1.startswith(s2)
266
- elif mode == "endswith":
267
- content_passed = s1.endswith(s2)
268
- elif mode == "not_equals":
269
- content_passed = s1 != s2
270
- elif mode == "not_contains":
271
- content_passed = s2 not in s1
272
- elif mode == "regex":
273
- content_passed = bool(re.search(expected, value))
274
- else:
275
- content_passed = False
276
- if not content_passed:
277
- content_feedback = f"String content check '{mode}' failed against expected '{expected}' (ignore_case={cfg.ignore_case})."
278
-
279
- condition_passed = length_passed and content_passed
280
- if not condition_passed:
281
- feedback_parts = length_feedback + (
282
- [content_feedback] if content_feedback else []
283
- )
284
- feedback = (
285
- "; ".join(feedback_parts)
286
- if feedback_parts
287
- else "String/length condition failed."
288
- )
289
-
290
- # 3. Number Check
291
- elif cfg.expected_number is not None:
292
- condition_type = "number"
293
- if not isinstance(value, (int, float)):
294
- feedback = f"Cannot perform number check on non-numeric value: {type(value)}."
295
- logger.warning(feedback)
296
- return False, feedback
297
- num_value = value
298
- expected = cfg.expected_number
299
- mode = cfg.number_mode
300
- op_map = {
301
- "<": lambda a, b: a < b,
302
- "<=": lambda a, b: a <= b,
303
- "==": lambda a, b: a == b,
304
- "!=": lambda a, b: a != b,
305
- ">=": lambda a, b: a >= b,
306
- ">": lambda a, b: a > b,
307
- }
308
- if mode in op_map:
309
- condition_passed = op_map[mode](num_value, expected)
310
- if not condition_passed:
311
- feedback = f"Number check failed: {num_value} {mode} {expected} is false."
312
- else:
313
- condition_passed = False
314
- feedback = f"Invalid number comparison mode: {mode}"
315
-
316
- # 4. List Size Check
317
- elif cfg.min_items is not None or cfg.max_items is not None:
318
- condition_type = "list size"
319
- if not isinstance(value, list):
320
- feedback = f"Cannot perform list size check on non-list value: {type(value)}."
321
- logger.warning(feedback)
322
- return False, feedback
323
- list_len = len(value)
324
- size_passed = True
325
- size_feedback = []
326
- if cfg.min_items is not None and list_len < cfg.min_items:
327
- size_passed = False
328
- size_feedback.append(
329
- f"list size {list_len} is less than minimum {cfg.min_items}"
330
- )
331
- if cfg.max_items is not None and list_len > cfg.max_items:
332
- size_passed = False
333
- size_feedback.append(
334
- f"list size {list_len} is greater than maximum {cfg.max_items}"
335
- )
336
- condition_passed = size_passed
337
- if not condition_passed:
338
- feedback = "; ".join(size_feedback)
339
-
340
- # 5. Type Check
341
- elif cfg.expected_type_name is not None:
342
- condition_type = "type"
343
- registry = get_registry()
344
- try:
345
- expected_type = registry.get_type(cfg.expected_type_name)
346
- condition_passed = isinstance(value, expected_type)
347
- if not condition_passed:
348
- feedback = f"Type check failed: Value type '{type(value).__name__}' is not instance of expected '{cfg.expected_type_name}'."
349
- except KeyError:
350
- feedback = f"Expected type '{cfg.expected_type_name}' not found in registry."
351
- logger.error(feedback)
352
- return False, feedback
353
-
354
- # 6. Boolean Check
355
- elif cfg.expected_bool is not None:
356
- condition_type = "boolean"
357
- if not isinstance(value, bool):
358
- feedback = f"Cannot perform boolean check on non-bool value: {type(value)}."
359
- logger.warning(feedback)
360
- return False, feedback
361
- condition_passed = value == cfg.expected_bool
362
- if not condition_passed:
363
- feedback = f"Boolean check failed: Value '{value}' is not expected '{cfg.expected_bool}'."
364
-
365
- logger.debug(
366
- f"Condition check '{condition_type}' result: {condition_passed}"
367
- )
368
- return condition_passed, feedback if not condition_passed else None
369
-
370
- except Exception as e:
371
- feedback = (
372
- f"Error evaluating condition type '{condition_type}': {e}"
373
- )
374
- logger.error(feedback, exc_info=True)
375
- return (
376
- False,
377
- feedback,
378
- ) # Treat evaluation errors as condition failure
379
-
380
- async def route(
381
- self,
382
- current_agent: FlockAgent,
383
- result: dict[str, Any],
384
- context: FlockContext,
385
- ) -> HandOffRequest:
386
- cfg = self.config
387
- condition_value = context.get_variable(cfg.condition_context_key, None)
388
- feedback_value = context.get_variable(cfg.feedback_context_key, None)
389
-
390
- logger.debug(
391
- f"Routing based on condition key '{cfg.condition_context_key}', value: {str(condition_value)[:100]}..."
392
- )
393
-
394
- # Evaluate the condition and get feedback on failure
395
- condition_passed, feedback_msg = self._evaluate_condition(
396
- condition_value
397
- )
398
-
399
- if condition_passed:
400
- # --- Success Path ---
401
- logger.info(
402
- f"Condition PASSED for agent '{current_agent.name}'. Routing to success path."
403
- )
404
- # Reset retry count if applicable
405
- if cfg.retry_on_failure:
406
- retry_key = (
407
- f"{cfg.retry_count_context_key_prefix}{current_agent.name}"
408
- )
409
- if retry_key in context.state:
410
- del context.state[retry_key]
411
- logger.debug(
412
- f"Reset retry count for agent '{current_agent.name}'."
413
- )
414
-
415
- # Clear feedback from context on success
416
- if (
417
- cfg.feedback_context_key
418
- and cfg.feedback_context_key in context.state
419
- ):
420
- del context.state[cfg.feedback_context_key]
421
- logger.debug(
422
- f"Cleared feedback key '{cfg.feedback_context_key}' on success."
423
- )
424
-
425
- next_agent = cfg.success_agent or "" # Stop chain if None
426
- logger.debug(f"Success route target: '{next_agent}'")
427
- return HandOffRequest(next_agent=next_agent)
428
-
429
- else:
430
- # --- Failure Path ---
431
- logger.warning(
432
- f"Condition FAILED for agent '{current_agent.name}'. Reason: {feedback_msg}"
433
- )
434
-
435
- if cfg.retry_on_failure:
436
- # --- Retry Logic ---
437
- retry_key = (
438
- f"{cfg.retry_count_context_key_prefix}{current_agent.name}"
439
- )
440
- retry_count = context.get_variable(retry_key, 0)
441
-
442
- if retry_count < cfg.max_retries:
443
- next_retry_count = retry_count + 1
444
- context.set_variable(retry_key, next_retry_count)
445
- logger.info(
446
- f"Routing back to agent '{current_agent.name}' for retry #{next_retry_count}/{cfg.max_retries}."
447
- )
448
-
449
- # Add specific feedback to context if retry is enabled
450
- if cfg.feedback_context_key:
451
- context.set_variable(
452
- cfg.feedback_context_key,
453
- feedback_msg or cfg.feedback_on_failure,
454
- )
455
- logger.debug(
456
- f"Set feedback key '{cfg.feedback_context_key}': {feedback_msg or cfg.feedback_on_failure}"
457
- )
458
-
459
- return HandOffRequest(
460
- next_agent=current_agent.name, # Route back to self
461
- output_to_input_merge_strategy="add", # Make feedback available
462
- )
463
- else:
464
- # --- Max Retries Exceeded ---
465
- logger.error(
466
- f"Max retries ({cfg.max_retries}) exceeded for agent '{current_agent.name}'."
467
- )
468
- if retry_key in context.state:
469
- del context.state[retry_key] # Reset count
470
- # Clear feedback before final failure route? Optional.
471
- # if cfg.feedback_context_key in context.state: del context.state[cfg.feedback_context_key]
472
- next_agent = cfg.failure_agent or ""
473
- logger.debug(
474
- f"Failure route target (after retries): '{next_agent}'"
475
- )
476
- return HandOffRequest(next_agent=next_agent)
477
- else:
478
- # --- No Retry Logic ---
479
- next_agent = (
480
- cfg.failure_agent or ""
481
- ) # Use failure agent or stop
482
- logger.debug(f"Failure route target (no retry): '{next_agent}'")
483
- # Optionally add feedback even if not retrying?
484
- # if cfg.feedback_context_key:
485
- # context.set_variable(cfg.feedback_context_key, feedback_msg or cfg.feedback_on_failure)
486
- return HandOffRequest(next_agent=next_agent)
@@ -1 +0,0 @@
1
- """Default router implementation for the Flock framework."""
@@ -1,80 +0,0 @@
1
- """Default router implementation for the Flock framework."""
2
-
3
- from collections.abc import Callable
4
- from typing import Any
5
-
6
- from pydantic import Field
7
-
8
- from flock.core.context.context import FlockContext
9
- from flock.core.flock_agent import FlockAgent
10
- from flock.core.flock_registry import flock_component
11
- from flock.core.flock_router import (
12
- FlockRouter,
13
- FlockRouterConfig,
14
- HandOffRequest,
15
- )
16
- from flock.core.logging.logging import get_logger
17
-
18
- logger = get_logger("default_router")
19
-
20
-
21
- class DefaultRouterConfig(FlockRouterConfig):
22
- """Configuration for the default router."""
23
-
24
- hand_off: str | HandOffRequest | Callable[..., HandOffRequest] = Field(
25
- default="", description="Next agent to hand off to"
26
- )
27
-
28
-
29
- @flock_component(config_class=DefaultRouterConfig)
30
- class DefaultRouter(FlockRouter):
31
- """Default router implementation.
32
-
33
- This router simply uses the agent's hand_off property to determine the next agent.
34
- It does not perform any dynamic routing.
35
- """
36
-
37
- name: str = "default_router"
38
- config: DefaultRouterConfig = Field(
39
- default_factory=DefaultRouterConfig, description="Output configuration"
40
- )
41
-
42
- def __init__(
43
- self,
44
- name: str = "default_router",
45
- config: DefaultRouterConfig | None = None,
46
- ):
47
- """Initialize the DefaultRouter.
48
-
49
- Args:
50
- name: The name of the router
51
- config: The router configuration
52
- """
53
- super().__init__(
54
- name=name, config=config or DefaultRouterConfig(name=name)
55
- )
56
-
57
- async def route(
58
- self,
59
- current_agent: FlockAgent,
60
- result: dict[str, Any],
61
- context: FlockContext,
62
- ) -> HandOffRequest:
63
- """Determine the next agent to hand off to based on the current agent's output.
64
-
65
- Args:
66
- current_agent: The agent that just completed execution
67
- result: The output from the current agent
68
- context: The global execution context
69
-
70
- Returns:
71
- A HandOff object containing the next agent and input data
72
- """
73
- handoff = self.config.hand_off
74
- if callable(handoff):
75
- handoff = handoff(context, result)
76
- if isinstance(handoff, str):
77
- handoff = HandOffRequest(
78
- next_agent=handoff, output_to_input_merge_strategy="match"
79
- )
80
- return handoff
@@ -1,114 +0,0 @@
1
- # src/flock/routers/correction/correction_router.py (New File)
2
-
3
- from typing import Any
4
-
5
- from pydantic import Field
6
-
7
- from flock.core.context.context import FlockContext
8
- from flock.core.flock_agent import FlockAgent
9
- from flock.core.flock_registry import flock_component
10
- from flock.core.flock_router import (
11
- FlockRouter,
12
- FlockRouterConfig,
13
- HandOffRequest,
14
- )
15
- from flock.core.logging.logging import get_logger
16
-
17
- logger = get_logger("router.correction")
18
-
19
-
20
- class FeedbackRetryRouterConfig(FlockRouterConfig):
21
- max_retries: int = Field(
22
- default=1,
23
- description="Maximum number of times to retry the same agent on failure.",
24
- )
25
- feedback_context_key: str = Field(
26
- default="flock.assertion_feedback",
27
- description="Context key containing feedback from AssertionCheckerModule.",
28
- )
29
- retry_count_context_key_prefix: str = Field(
30
- default="flock.retry_count_",
31
- description="Prefix for context key storing retry attempts per agent.",
32
- )
33
- fallback_agent: str | None = Field(
34
- None, description="Agent to route to if max_retries is exceeded."
35
- )
36
-
37
-
38
- @flock_component(config_class=FeedbackRetryRouterConfig)
39
- class FeedbackRetryRouter(FlockRouter):
40
- """Routes based on assertion feedback in the context.
41
-
42
- If feedback exists for the current agent and retries are not exhausted,
43
- it routes back to the same agent, adding the feedback to its input.
44
- Otherwise, it can route to a fallback agent or stop the chain.
45
- """
46
-
47
- name: str = "feedback_retry_router"
48
- config: FeedbackRetryRouterConfig = Field(
49
- default_factory=FeedbackRetryRouterConfig
50
- )
51
-
52
- async def route(
53
- self,
54
- current_agent: FlockAgent,
55
- result: dict[str, Any],
56
- context: FlockContext,
57
- ) -> HandOffRequest:
58
- feedback = context.get_variable(self.config.feedback_context_key)
59
-
60
- if feedback:
61
- logger.warning(
62
- f"Assertion feedback detected for agent '{current_agent.name}'. Attempting retry."
63
- )
64
-
65
- retry_key = f"{self.config.retry_count_context_key_prefix}{current_agent.name}"
66
- retry_count = context.get_variable(retry_key, 0)
67
- logger.warning(f"Feedback: {feedback} - Retry Count {retry_count}")
68
-
69
- if retry_count < self.config.max_retries:
70
- logger.info(
71
- f"Routing back to agent '{current_agent.name}' for retry #{retry_count + 1}"
72
- )
73
- context.set_variable(retry_key, retry_count + 1)
74
- context.set_variable(
75
- f"{current_agent.name}_prev_result", result
76
- )
77
- # Add feedback to the *next* agent's input (which is the same agent)
78
- # Requires the agent's signature to potentially accept a 'feedback' input field.
79
- return HandOffRequest(
80
- next_agent=current_agent.name,
81
- output_to_input_merge_strategy="match", # Add feedback to existing context/previous results
82
- add_input_fields=[
83
- f"{self.config.feedback_context_key} | Feedback for prev result",
84
- f"{current_agent.name}_prev_result | Previous Result",
85
- ],
86
- add_description=f"Try to fix the previous result based on the feedback.",
87
- override_context=None, # Context already updated with feedback and retry count
88
- )
89
- else:
90
- logger.error(
91
- f"Max retries ({self.config.max_retries}) exceeded for agent '{current_agent.name}'."
92
- )
93
- # Max retries exceeded, route to fallback or stop
94
- if self.config.fallback_agent:
95
- logger.info(
96
- f"Routing to fallback agent '{self.config.fallback_agent}'"
97
- )
98
- # Clear feedback before going to fallback? Optional.
99
- if self.config.feedback_context_key in context.state:
100
- del context.state[self.config.feedback_context_key]
101
- return HandOffRequest(next_agent=self.config.fallback_agent)
102
- else:
103
- logger.info("No fallback agent defined. Stopping workflow.")
104
- return HandOffRequest(next_agent="") # Stop the chain
105
-
106
- else:
107
- # No feedback, assertions passed or module not configured for feedback
108
- logger.debug(
109
- f"No assertion feedback for agent '{current_agent.name}'. Proceeding normally."
110
- )
111
- # Default behavior: Stop the chain if no other routing is defined
112
- # In a real system, you might chain this with another router (e.g., LLMRouter)
113
- # to decide the *next different* agent if assertions passed.
114
- return HandOffRequest(next_agent="") # Stop or pass to next router