flock-core 0.5.0b28__py3-none-any.whl → 0.5.0b51__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 (469) 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/frontend/README.md +678 -0
  17. flock/frontend/docs/DESIGN_SYSTEM.md +1980 -0
  18. flock/frontend/index.html +12 -0
  19. flock/frontend/package-lock.json +4347 -0
  20. flock/frontend/package.json +48 -0
  21. flock/frontend/src/App.tsx +79 -0
  22. flock/frontend/src/__tests__/e2e/critical-scenarios.test.tsx +587 -0
  23. flock/frontend/src/__tests__/integration/filtering-e2e.test.tsx +387 -0
  24. flock/frontend/src/__tests__/integration/graph-rendering.test.tsx +640 -0
  25. flock/frontend/src/__tests__/integration/indexeddb-persistence.test.tsx +699 -0
  26. flock/frontend/src/components/common/BuildInfo.tsx +39 -0
  27. flock/frontend/src/components/common/EmptyState.module.css +115 -0
  28. flock/frontend/src/components/common/EmptyState.tsx +128 -0
  29. flock/frontend/src/components/common/ErrorBoundary.module.css +169 -0
  30. flock/frontend/src/components/common/ErrorBoundary.tsx +118 -0
  31. flock/frontend/src/components/common/KeyboardShortcutsDialog.css +251 -0
  32. flock/frontend/src/components/common/KeyboardShortcutsDialog.tsx +151 -0
  33. flock/frontend/src/components/common/LoadingSpinner.module.css +97 -0
  34. flock/frontend/src/components/common/LoadingSpinner.tsx +29 -0
  35. flock/frontend/src/components/controls/PublishControl.css +547 -0
  36. flock/frontend/src/components/controls/PublishControl.test.tsx +543 -0
  37. flock/frontend/src/components/controls/PublishControl.tsx +432 -0
  38. flock/frontend/src/components/details/DetailWindowContainer.tsx +62 -0
  39. flock/frontend/src/components/details/LiveOutputTab.test.tsx +792 -0
  40. flock/frontend/src/components/details/LiveOutputTab.tsx +220 -0
  41. flock/frontend/src/components/details/MessageHistoryTab.tsx +299 -0
  42. flock/frontend/src/components/details/NodeDetailWindow.test.tsx +501 -0
  43. flock/frontend/src/components/details/NodeDetailWindow.tsx +218 -0
  44. flock/frontend/src/components/details/RunStatusTab.tsx +307 -0
  45. flock/frontend/src/components/details/tabs.test.tsx +1015 -0
  46. flock/frontend/src/components/filters/CorrelationIDFilter.module.css +102 -0
  47. flock/frontend/src/components/filters/CorrelationIDFilter.test.tsx +197 -0
  48. flock/frontend/src/components/filters/CorrelationIDFilter.tsx +121 -0
  49. flock/frontend/src/components/filters/FilterBar.module.css +29 -0
  50. flock/frontend/src/components/filters/FilterBar.test.tsx +133 -0
  51. flock/frontend/src/components/filters/FilterBar.tsx +33 -0
  52. flock/frontend/src/components/filters/FilterPills.module.css +79 -0
  53. flock/frontend/src/components/filters/FilterPills.test.tsx +173 -0
  54. flock/frontend/src/components/filters/FilterPills.tsx +67 -0
  55. flock/frontend/src/components/filters/TimeRangeFilter.module.css +91 -0
  56. flock/frontend/src/components/filters/TimeRangeFilter.test.tsx +154 -0
  57. flock/frontend/src/components/filters/TimeRangeFilter.tsx +105 -0
  58. flock/frontend/src/components/graph/AgentNode.test.tsx +75 -0
  59. flock/frontend/src/components/graph/AgentNode.tsx +322 -0
  60. flock/frontend/src/components/graph/GraphCanvas.tsx +406 -0
  61. flock/frontend/src/components/graph/MessageFlowEdge.tsx +128 -0
  62. flock/frontend/src/components/graph/MessageNode.test.tsx +62 -0
  63. flock/frontend/src/components/graph/MessageNode.tsx +116 -0
  64. flock/frontend/src/components/graph/MiniMap.tsx +47 -0
  65. flock/frontend/src/components/graph/TransformEdge.tsx +123 -0
  66. flock/frontend/src/components/layout/DashboardLayout.css +407 -0
  67. flock/frontend/src/components/layout/DashboardLayout.tsx +300 -0
  68. flock/frontend/src/components/layout/Header.module.css +88 -0
  69. flock/frontend/src/components/layout/Header.tsx +52 -0
  70. flock/frontend/src/components/modules/EventLogModule.test.tsx +401 -0
  71. flock/frontend/src/components/modules/EventLogModule.tsx +396 -0
  72. flock/frontend/src/components/modules/EventLogModuleWrapper.tsx +17 -0
  73. flock/frontend/src/components/modules/ModuleRegistry.test.ts +333 -0
  74. flock/frontend/src/components/modules/ModuleRegistry.ts +85 -0
  75. flock/frontend/src/components/modules/ModuleWindow.tsx +155 -0
  76. flock/frontend/src/components/modules/registerModules.ts +20 -0
  77. flock/frontend/src/components/settings/AdvancedSettings.tsx +175 -0
  78. flock/frontend/src/components/settings/AppearanceSettings.tsx +185 -0
  79. flock/frontend/src/components/settings/GraphSettings.tsx +110 -0
  80. flock/frontend/src/components/settings/SettingsPanel.css +327 -0
  81. flock/frontend/src/components/settings/SettingsPanel.tsx +131 -0
  82. flock/frontend/src/components/settings/ThemeSelector.tsx +298 -0
  83. flock/frontend/src/hooks/useKeyboardShortcuts.ts +148 -0
  84. flock/frontend/src/hooks/useModulePersistence.test.ts +442 -0
  85. flock/frontend/src/hooks/useModulePersistence.ts +154 -0
  86. flock/frontend/src/hooks/useModules.ts +139 -0
  87. flock/frontend/src/hooks/usePersistence.ts +139 -0
  88. flock/frontend/src/main.tsx +13 -0
  89. flock/frontend/src/services/api.ts +213 -0
  90. flock/frontend/src/services/indexeddb.test.ts +793 -0
  91. flock/frontend/src/services/indexeddb.ts +794 -0
  92. flock/frontend/src/services/layout.test.ts +437 -0
  93. flock/frontend/src/services/layout.ts +146 -0
  94. flock/frontend/src/services/themeApplicator.ts +140 -0
  95. flock/frontend/src/services/themeService.ts +77 -0
  96. flock/frontend/src/services/websocket.test.ts +595 -0
  97. flock/frontend/src/services/websocket.ts +685 -0
  98. flock/frontend/src/store/filterStore.test.ts +242 -0
  99. flock/frontend/src/store/filterStore.ts +103 -0
  100. flock/frontend/src/store/graphStore.test.ts +186 -0
  101. flock/frontend/src/store/graphStore.ts +414 -0
  102. flock/frontend/src/store/moduleStore.test.ts +253 -0
  103. flock/frontend/src/store/moduleStore.ts +57 -0
  104. flock/frontend/src/store/settingsStore.ts +188 -0
  105. flock/frontend/src/store/streamStore.ts +68 -0
  106. flock/frontend/src/store/uiStore.test.ts +54 -0
  107. flock/frontend/src/store/uiStore.ts +110 -0
  108. flock/frontend/src/store/wsStore.ts +34 -0
  109. flock/frontend/src/styles/index.css +15 -0
  110. flock/frontend/src/styles/scrollbar.css +47 -0
  111. flock/frontend/src/styles/variables.css +488 -0
  112. flock/frontend/src/test/setup.ts +1 -0
  113. flock/frontend/src/types/filters.ts +14 -0
  114. flock/frontend/src/types/graph.ts +55 -0
  115. flock/frontend/src/types/modules.ts +7 -0
  116. flock/frontend/src/types/theme.ts +55 -0
  117. flock/frontend/src/utils/mockData.ts +85 -0
  118. flock/frontend/src/utils/performance.ts +16 -0
  119. flock/frontend/src/utils/transforms.test.ts +860 -0
  120. flock/frontend/src/utils/transforms.ts +323 -0
  121. flock/frontend/src/vite-env.d.ts +17 -0
  122. flock/frontend/tsconfig.json +27 -0
  123. flock/frontend/tsconfig.node.json +11 -0
  124. flock/frontend/vite.config.ts +25 -0
  125. flock/frontend/vitest.config.ts +11 -0
  126. flock/{core/util → helper}/cli_helper.py +4 -3
  127. flock/{core/logging → logging}/__init__.py +2 -3
  128. flock/{core/logging → logging}/formatters/enum_builder.py +3 -4
  129. flock/{core/logging → logging}/formatters/theme_builder.py +19 -44
  130. flock/{core/logging → logging}/formatters/themed_formatter.py +69 -115
  131. flock/{core/logging → logging}/logging.py +77 -61
  132. flock/{core/logging → logging}/telemetry.py +20 -26
  133. flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
  134. flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +6 -9
  135. flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
  136. flock/{core/logging → logging}/trace_and_logged.py +20 -24
  137. flock/mcp/__init__.py +91 -0
  138. flock/{core/mcp/mcp_client.py → mcp/client.py} +103 -154
  139. flock/{core/mcp/mcp_config.py → mcp/config.py} +62 -117
  140. flock/mcp/manager.py +255 -0
  141. flock/mcp/servers/sse/__init__.py +1 -1
  142. flock/mcp/servers/sse/flock_sse_server.py +11 -53
  143. flock/mcp/servers/stdio/__init__.py +1 -1
  144. flock/mcp/servers/stdio/flock_stdio_server.py +8 -48
  145. flock/mcp/servers/streamable_http/flock_streamable_http_server.py +17 -62
  146. flock/mcp/servers/websockets/flock_websocket_server.py +7 -40
  147. flock/{core/mcp/flock_mcp_tool.py → mcp/tool.py} +16 -26
  148. flock/mcp/types/__init__.py +42 -0
  149. flock/{core/mcp → mcp}/types/callbacks.py +9 -15
  150. flock/{core/mcp → mcp}/types/factories.py +7 -6
  151. flock/{core/mcp → mcp}/types/handlers.py +13 -18
  152. flock/{core/mcp → mcp}/types/types.py +70 -74
  153. flock/{core/mcp → mcp}/util/helpers.py +1 -1
  154. flock/orchestrator.py +645 -0
  155. flock/registry.py +148 -0
  156. flock/runtime.py +262 -0
  157. flock/service.py +140 -0
  158. flock/store.py +69 -0
  159. flock/subscription.py +111 -0
  160. flock/themes/andromeda.toml +1 -1
  161. flock/themes/apple-system-colors.toml +1 -1
  162. flock/themes/arcoiris.toml +1 -1
  163. flock/themes/atomonelight.toml +1 -1
  164. flock/themes/ayu copy.toml +1 -1
  165. flock/themes/ayu-light.toml +1 -1
  166. flock/themes/belafonte-day.toml +1 -1
  167. flock/themes/belafonte-night.toml +1 -1
  168. flock/themes/blulocodark.toml +1 -1
  169. flock/themes/breeze.toml +1 -1
  170. flock/themes/broadcast.toml +1 -1
  171. flock/themes/brogrammer.toml +1 -1
  172. flock/themes/builtin-dark.toml +1 -1
  173. flock/themes/builtin-pastel-dark.toml +1 -1
  174. flock/themes/catppuccin-latte.toml +1 -1
  175. flock/themes/catppuccin-macchiato.toml +1 -1
  176. flock/themes/catppuccin-mocha.toml +1 -1
  177. flock/themes/cga.toml +1 -1
  178. flock/themes/chalk.toml +1 -1
  179. flock/themes/ciapre.toml +1 -1
  180. flock/themes/coffee-theme.toml +1 -1
  181. flock/themes/cyberpunkscarletprotocol.toml +1 -1
  182. flock/themes/dark+.toml +1 -1
  183. flock/themes/darkermatrix.toml +1 -1
  184. flock/themes/darkside.toml +1 -1
  185. flock/themes/desert.toml +1 -1
  186. flock/themes/django.toml +1 -1
  187. flock/themes/djangosmooth.toml +1 -1
  188. flock/themes/doomone.toml +1 -1
  189. flock/themes/dotgov.toml +1 -1
  190. flock/themes/dracula+.toml +1 -1
  191. flock/themes/duckbones.toml +1 -1
  192. flock/themes/encom.toml +1 -1
  193. flock/themes/espresso.toml +1 -1
  194. flock/themes/everblush.toml +1 -1
  195. flock/themes/fairyfloss.toml +1 -1
  196. flock/themes/fideloper.toml +1 -1
  197. flock/themes/fishtank.toml +1 -1
  198. flock/themes/flexoki-light.toml +1 -1
  199. flock/themes/floraverse.toml +1 -1
  200. flock/themes/framer.toml +1 -1
  201. flock/themes/galizur.toml +1 -1
  202. flock/themes/github.toml +1 -1
  203. flock/themes/grass.toml +1 -1
  204. flock/themes/grey-green.toml +1 -1
  205. flock/themes/gruvboxlight.toml +1 -1
  206. flock/themes/guezwhoz.toml +1 -1
  207. flock/themes/harper.toml +1 -1
  208. flock/themes/hax0r-blue.toml +1 -1
  209. flock/themes/hopscotch.256.toml +1 -1
  210. flock/themes/ic-green-ppl.toml +1 -1
  211. flock/themes/iceberg-dark.toml +1 -1
  212. flock/themes/japanesque.toml +1 -1
  213. flock/themes/jubi.toml +1 -1
  214. flock/themes/kibble.toml +1 -1
  215. flock/themes/kolorit.toml +1 -1
  216. flock/themes/kurokula.toml +1 -1
  217. flock/themes/materialdesigncolors.toml +1 -1
  218. flock/themes/matrix.toml +1 -1
  219. flock/themes/mellifluous.toml +1 -1
  220. flock/themes/midnight-in-mojave.toml +1 -1
  221. flock/themes/monokai-remastered.toml +1 -1
  222. flock/themes/monokai-soda.toml +1 -1
  223. flock/themes/neon.toml +1 -1
  224. flock/themes/neopolitan.toml +1 -1
  225. flock/themes/nord-light.toml +1 -1
  226. flock/themes/ocean.toml +1 -1
  227. flock/themes/onehalfdark.toml +1 -1
  228. flock/themes/onehalflight.toml +1 -1
  229. flock/themes/palenighthc.toml +1 -1
  230. flock/themes/paulmillr.toml +1 -1
  231. flock/themes/pencildark.toml +1 -1
  232. flock/themes/pnevma.toml +1 -1
  233. flock/themes/purple-rain.toml +1 -1
  234. flock/themes/purplepeter.toml +1 -1
  235. flock/themes/raycast-dark.toml +1 -1
  236. flock/themes/red-sands.toml +1 -1
  237. flock/themes/relaxed.toml +1 -1
  238. flock/themes/retro.toml +1 -1
  239. flock/themes/rose-pine.toml +1 -1
  240. flock/themes/royal.toml +1 -1
  241. flock/themes/ryuuko.toml +1 -1
  242. flock/themes/sakura.toml +1 -1
  243. flock/themes/scarlet-protocol.toml +1 -1
  244. flock/themes/seoulbones-dark.toml +1 -1
  245. flock/themes/shades-of-purple.toml +1 -1
  246. flock/themes/smyck.toml +1 -1
  247. flock/themes/softserver.toml +1 -1
  248. flock/themes/solarized-darcula.toml +1 -1
  249. flock/themes/square.toml +1 -1
  250. flock/themes/sugarplum.toml +1 -1
  251. flock/themes/thayer-bright.toml +1 -1
  252. flock/themes/tokyonight.toml +1 -1
  253. flock/themes/tomorrow.toml +1 -1
  254. flock/themes/ubuntu.toml +1 -1
  255. flock/themes/ultradark.toml +1 -1
  256. flock/themes/ultraviolent.toml +1 -1
  257. flock/themes/unikitty.toml +1 -1
  258. flock/themes/urple.toml +1 -1
  259. flock/themes/vesper.toml +1 -1
  260. flock/themes/vimbones.toml +1 -1
  261. flock/themes/wildcherry.toml +1 -1
  262. flock/themes/wilmersdorf.toml +1 -1
  263. flock/themes/wryan.toml +1 -1
  264. flock/themes/xcodedarkhc.toml +1 -1
  265. flock/themes/xcodelight.toml +1 -1
  266. flock/themes/zenbones-light.toml +1 -1
  267. flock/themes/zenwritten-dark.toml +1 -1
  268. flock/utilities.py +301 -0
  269. flock/{components/utility → utility}/output_utility_component.py +68 -53
  270. flock/visibility.py +107 -0
  271. flock_core-0.5.0b51.dist-info/METADATA +747 -0
  272. flock_core-0.5.0b51.dist-info/RECORD +508 -0
  273. flock_core-0.5.0b51.dist-info/entry_points.txt +2 -0
  274. {flock_core-0.5.0b28.dist-info → flock_core-0.5.0b51.dist-info}/licenses/LICENSE +1 -1
  275. flock/adapter/__init__.py +0 -14
  276. flock/adapter/azure_adapter.py +0 -68
  277. flock/adapter/chroma_adapter.py +0 -73
  278. flock/adapter/faiss_adapter.py +0 -97
  279. flock/adapter/pinecone_adapter.py +0 -51
  280. flock/adapter/vector_base.py +0 -47
  281. flock/cli/assets/release_notes.md +0 -140
  282. flock/cli/config.py +0 -8
  283. flock/cli/constants.py +0 -36
  284. flock/cli/create_agent.py +0 -1
  285. flock/cli/create_flock.py +0 -280
  286. flock/cli/execute_flock.py +0 -620
  287. flock/cli/load_agent.py +0 -1
  288. flock/cli/load_examples.py +0 -1
  289. flock/cli/load_flock.py +0 -192
  290. flock/cli/load_release_notes.py +0 -20
  291. flock/cli/loaded_flock_cli.py +0 -254
  292. flock/cli/manage_agents.py +0 -459
  293. flock/cli/registry_management.py +0 -889
  294. flock/cli/runner.py +0 -41
  295. flock/cli/settings.py +0 -857
  296. flock/cli/utils.py +0 -135
  297. flock/cli/view_results.py +0 -29
  298. flock/cli/yaml_editor.py +0 -396
  299. flock/components/__init__.py +0 -30
  300. flock/components/evaluation/__init__.py +0 -9
  301. flock/components/evaluation/declarative_evaluation_component.py +0 -606
  302. flock/components/routing/__init__.py +0 -15
  303. flock/components/routing/conditional_routing_component.py +0 -494
  304. flock/components/routing/default_routing_component.py +0 -103
  305. flock/components/routing/llm_routing_component.py +0 -206
  306. flock/components/utility/__init__.py +0 -22
  307. flock/components/utility/example_utility_component.py +0 -250
  308. flock/components/utility/feedback_utility_component.py +0 -206
  309. flock/components/utility/memory_utility_component.py +0 -550
  310. flock/components/utility/metrics_utility_component.py +0 -700
  311. flock/config.py +0 -61
  312. flock/core/__init__.py +0 -110
  313. flock/core/agent/__init__.py +0 -16
  314. flock/core/agent/default_agent.py +0 -216
  315. flock/core/agent/flock_agent_components.py +0 -104
  316. flock/core/agent/flock_agent_execution.py +0 -101
  317. flock/core/agent/flock_agent_integration.py +0 -260
  318. flock/core/agent/flock_agent_lifecycle.py +0 -186
  319. flock/core/agent/flock_agent_serialization.py +0 -381
  320. flock/core/api/__init__.py +0 -10
  321. flock/core/api/custom_endpoint.py +0 -45
  322. flock/core/api/endpoints.py +0 -254
  323. flock/core/api/main.py +0 -162
  324. flock/core/api/models.py +0 -97
  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/component/__init__.py +0 -15
  329. flock/core/component/agent_component_base.py +0 -309
  330. flock/core/component/evaluation_component.py +0 -62
  331. flock/core/component/routing_component.py +0 -74
  332. flock/core/component/utility_component.py +0 -69
  333. flock/core/config/flock_agent_config.py +0 -58
  334. flock/core/config/scheduled_agent_config.py +0 -40
  335. flock/core/context/context.py +0 -213
  336. flock/core/context/context_manager.py +0 -37
  337. flock/core/context/context_vars.py +0 -10
  338. flock/core/evaluation/utils.py +0 -396
  339. flock/core/execution/batch_executor.py +0 -369
  340. flock/core/execution/evaluation_executor.py +0 -438
  341. flock/core/execution/local_executor.py +0 -31
  342. flock/core/execution/opik_executor.py +0 -103
  343. flock/core/execution/temporal_executor.py +0 -164
  344. flock/core/flock.py +0 -634
  345. flock/core/flock_agent.py +0 -336
  346. flock/core/flock_factory.py +0 -613
  347. flock/core/flock_scheduler.py +0 -166
  348. flock/core/flock_server_manager.py +0 -136
  349. flock/core/interpreter/python_interpreter.py +0 -689
  350. flock/core/mcp/__init__.py +0 -1
  351. flock/core/mcp/flock_mcp_server.py +0 -680
  352. flock/core/mcp/mcp_client_manager.py +0 -201
  353. flock/core/mcp/types/__init__.py +0 -1
  354. flock/core/mixin/dspy_integration.py +0 -403
  355. flock/core/mixin/prompt_parser.py +0 -125
  356. flock/core/orchestration/__init__.py +0 -15
  357. flock/core/orchestration/flock_batch_processor.py +0 -94
  358. flock/core/orchestration/flock_evaluator.py +0 -113
  359. flock/core/orchestration/flock_execution.py +0 -295
  360. flock/core/orchestration/flock_initialization.py +0 -149
  361. flock/core/orchestration/flock_server_manager.py +0 -67
  362. flock/core/orchestration/flock_web_server.py +0 -117
  363. flock/core/registry/__init__.py +0 -45
  364. flock/core/registry/agent_registry.py +0 -69
  365. flock/core/registry/callable_registry.py +0 -139
  366. flock/core/registry/component_discovery.py +0 -142
  367. flock/core/registry/component_registry.py +0 -64
  368. flock/core/registry/config_mapping.py +0 -64
  369. flock/core/registry/decorators.py +0 -137
  370. flock/core/registry/registry_hub.py +0 -205
  371. flock/core/registry/server_registry.py +0 -57
  372. flock/core/registry/type_registry.py +0 -86
  373. flock/core/serialization/__init__.py +0 -13
  374. flock/core/serialization/callable_registry.py +0 -52
  375. flock/core/serialization/flock_serializer.py +0 -832
  376. flock/core/serialization/json_encoder.py +0 -41
  377. flock/core/serialization/secure_serializer.py +0 -175
  378. flock/core/serialization/serializable.py +0 -342
  379. flock/core/serialization/serialization_utils.py +0 -412
  380. flock/core/util/file_path_utils.py +0 -223
  381. flock/core/util/hydrator.py +0 -309
  382. flock/core/util/input_resolver.py +0 -164
  383. flock/core/util/loader.py +0 -59
  384. flock/core/util/splitter.py +0 -219
  385. flock/di.py +0 -27
  386. flock/platform/docker_tools.py +0 -49
  387. flock/platform/jaeger_install.py +0 -86
  388. flock/webapp/__init__.py +0 -1
  389. flock/webapp/app/__init__.py +0 -0
  390. flock/webapp/app/api/__init__.py +0 -0
  391. flock/webapp/app/api/agent_management.py +0 -241
  392. flock/webapp/app/api/execution.py +0 -709
  393. flock/webapp/app/api/flock_management.py +0 -129
  394. flock/webapp/app/api/registry_viewer.py +0 -30
  395. flock/webapp/app/chat.py +0 -665
  396. flock/webapp/app/config.py +0 -104
  397. flock/webapp/app/dependencies.py +0 -117
  398. flock/webapp/app/main.py +0 -1070
  399. flock/webapp/app/middleware.py +0 -113
  400. flock/webapp/app/models_ui.py +0 -7
  401. flock/webapp/app/services/__init__.py +0 -0
  402. flock/webapp/app/services/feedback_file_service.py +0 -363
  403. flock/webapp/app/services/flock_service.py +0 -337
  404. flock/webapp/app/services/sharing_models.py +0 -81
  405. flock/webapp/app/services/sharing_store.py +0 -762
  406. flock/webapp/app/templates/theme_mapper.html +0 -326
  407. flock/webapp/app/theme_mapper.py +0 -812
  408. flock/webapp/app/utils.py +0 -85
  409. flock/webapp/run.py +0 -215
  410. flock/webapp/static/css/chat.css +0 -301
  411. flock/webapp/static/css/components.css +0 -167
  412. flock/webapp/static/css/header.css +0 -39
  413. flock/webapp/static/css/layout.css +0 -46
  414. flock/webapp/static/css/sidebar.css +0 -127
  415. flock/webapp/static/css/two-pane.css +0 -48
  416. flock/webapp/templates/base.html +0 -200
  417. flock/webapp/templates/chat.html +0 -152
  418. flock/webapp/templates/chat_settings.html +0 -19
  419. flock/webapp/templates/flock_editor.html +0 -16
  420. flock/webapp/templates/index.html +0 -12
  421. flock/webapp/templates/partials/_agent_detail_form.html +0 -93
  422. flock/webapp/templates/partials/_agent_list.html +0 -18
  423. flock/webapp/templates/partials/_agent_manager_view.html +0 -51
  424. flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
  425. flock/webapp/templates/partials/_chat_container.html +0 -15
  426. flock/webapp/templates/partials/_chat_messages.html +0 -57
  427. flock/webapp/templates/partials/_chat_settings_form.html +0 -85
  428. flock/webapp/templates/partials/_create_flock_form.html +0 -50
  429. flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
  430. flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
  431. flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
  432. flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
  433. flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
  434. flock/webapp/templates/partials/_env_vars_table.html +0 -23
  435. flock/webapp/templates/partials/_execution_form.html +0 -118
  436. flock/webapp/templates/partials/_execution_view_container.html +0 -28
  437. flock/webapp/templates/partials/_flock_file_list.html +0 -23
  438. flock/webapp/templates/partials/_flock_properties_form.html +0 -52
  439. flock/webapp/templates/partials/_flock_upload_form.html +0 -16
  440. flock/webapp/templates/partials/_header_flock_status.html +0 -5
  441. flock/webapp/templates/partials/_load_manager_view.html +0 -49
  442. flock/webapp/templates/partials/_registry_table.html +0 -25
  443. flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
  444. flock/webapp/templates/partials/_results_display.html +0 -78
  445. flock/webapp/templates/partials/_settings_env_content.html +0 -9
  446. flock/webapp/templates/partials/_settings_theme_content.html +0 -14
  447. flock/webapp/templates/partials/_settings_view.html +0 -36
  448. flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
  449. flock/webapp/templates/partials/_share_link_snippet.html +0 -35
  450. flock/webapp/templates/partials/_sidebar.html +0 -74
  451. flock/webapp/templates/partials/_streaming_results_container.html +0 -195
  452. flock/webapp/templates/partials/_structured_data_view.html +0 -40
  453. flock/webapp/templates/partials/_theme_preview.html +0 -36
  454. flock/webapp/templates/registry_viewer.html +0 -84
  455. flock/webapp/templates/shared_run_page.html +0 -140
  456. flock/workflow/__init__.py +0 -0
  457. flock/workflow/activities.py +0 -196
  458. flock/workflow/agent_activities.py +0 -24
  459. flock/workflow/agent_execution_activity.py +0 -202
  460. flock/workflow/flock_workflow.py +0 -214
  461. flock/workflow/temporal_config.py +0 -96
  462. flock/workflow/temporal_setup.py +0 -68
  463. flock_core-0.5.0b28.dist-info/METADATA +0 -274
  464. flock_core-0.5.0b28.dist-info/RECORD +0 -561
  465. flock_core-0.5.0b28.dist-info/entry_points.txt +0 -2
  466. /flock/{core/logging → logging}/formatters/themes.py +0 -0
  467. /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
  468. /flock/{core/mcp → mcp}/util/__init__.py +0 -0
  469. {flock_core-0.5.0b28.dist-info → flock_core-0.5.0b51.dist-info}/WHEEL +0 -0
@@ -1,206 +0,0 @@
1
- # src/flock/components/routing/llm_routing_component.py
2
- """LLM-based routing component implementation for the unified component architecture."""
3
-
4
- import json
5
- from typing import TYPE_CHECKING, Any
6
-
7
- import litellm
8
- from pydantic import Field
9
-
10
- from flock.core.component.agent_component_base import AgentComponentConfig
11
- from flock.core.component.routing_component import RoutingComponent
12
- from flock.core.context.context import FlockContext
13
-
14
- # HandOffRequest removed - using agent.next_agent directly
15
- from flock.core.logging.logging import get_logger
16
- from flock.core.registry import flock_component
17
-
18
- if TYPE_CHECKING:
19
- from flock.core.flock_agent import FlockAgent
20
-
21
- logger = get_logger("components.routing.llm")
22
-
23
-
24
- class LLMRoutingConfig(AgentComponentConfig):
25
- """Configuration for the LLM routing component."""
26
-
27
- temperature: float = Field(
28
- default=0.2, description="Temperature for LLM routing decisions"
29
- )
30
- max_tokens: int = Field(
31
- default=500, description="Maximum tokens for LLM response"
32
- )
33
- confidence_threshold: float = Field(
34
- default=0.5, description="Minimum confidence threshold for routing"
35
- )
36
- model: str = Field(
37
- default="azure/gpt-4.1", description="Model to use for routing decisions"
38
- )
39
- prompt_template: str = Field(
40
- default="""You are a workflow routing assistant. Given the current agent's output and available next agents, determine which agent should execute next.
41
-
42
- Current Agent: {current_agent_name}
43
- Current Output: {current_output}
44
-
45
- Available Agents:
46
- {available_agents}
47
-
48
- Select the most appropriate next agent based on the current output. Respond with JSON in this exact format:
49
- {{"next_agent": "agent_name", "confidence": 0.8, "reasoning": "explanation"}}
50
-
51
- If no agent is suitable, use "next_agent": "" to end the workflow.""",
52
- description="Template for LLM routing prompt"
53
- )
54
-
55
-
56
- @flock_component(config_class=LLMRoutingConfig)
57
- class LLMRoutingComponent(RoutingComponent):
58
- """Router that uses an LLM to determine the next agent in a workflow.
59
-
60
- This component analyzes the current agent's output and uses an LLM to
61
- intelligently select the most appropriate next agent from available options.
62
- """
63
-
64
- config: LLMRoutingConfig = Field(
65
- default_factory=LLMRoutingConfig
66
- )
67
-
68
- def __init__(
69
- self,
70
- name: str = "llm_router",
71
- config: LLMRoutingConfig | None = None,
72
- **data,
73
- ):
74
- if config is None:
75
- config = LLMRoutingConfig()
76
- super().__init__(name=name, config=config, **data)
77
-
78
- def _get_available_agents(
79
- self, agent_definitions: dict[str, Any], current_agent_name: str
80
- ) -> list[str]:
81
- """Get list of available agent names except the current one."""
82
- available = []
83
- for agent_name in agent_definitions:
84
- if agent_name != current_agent_name:
85
- available.append(agent_name)
86
- return available
87
-
88
- def _create_selection_prompt(
89
- self,
90
- current_agent: "FlockAgent",
91
- result: dict[str, Any],
92
- available_agents: list[str],
93
- ) -> str:
94
- """Create the prompt for LLM agent selection."""
95
- # Format available agents
96
- agents_list = []
97
- for agent_name in available_agents:
98
- agents_list.append(f"- {agent_name}")
99
-
100
- available_agents_str = "\n".join(agents_list) if agents_list else "None available"
101
-
102
- # Format current output
103
- current_output = json.dumps(result, indent=2) if result else "No output"
104
-
105
- return self.config.prompt_template.format(
106
- current_agent_name=current_agent.name,
107
- current_output=current_output,
108
- available_agents=available_agents_str
109
- )
110
-
111
- async def _select_next_agent(
112
- self,
113
- current_agent: "FlockAgent",
114
- result: dict[str, Any],
115
- available_agents: list[str],
116
- ) -> tuple[str, float]:
117
- """Use an LLM to select the best next agent."""
118
- if not available_agents:
119
- logger.warning("No available agents for LLM routing")
120
- return "", 0.0
121
-
122
- # Create the selection prompt
123
- prompt = self._create_selection_prompt(current_agent, result, available_agents)
124
-
125
- try:
126
- # Call the LLM
127
- response = await litellm.acompletion(
128
- model=self.config.model,
129
- messages=[
130
- {"role": "user", "content": prompt}
131
- ],
132
- temperature=self.config.temperature,
133
- max_tokens=self.config.max_tokens,
134
- )
135
-
136
- response_content = response.choices[0].message.content.strip()
137
- logger.debug(f"LLM routing response: {response_content}")
138
-
139
- # Parse the JSON response
140
- try:
141
- routing_decision = json.loads(response_content)
142
- next_agent = routing_decision.get("next_agent", "")
143
- confidence = routing_decision.get("confidence", 0.0)
144
- reasoning = routing_decision.get("reasoning", "No reasoning provided")
145
-
146
- logger.info(f"LLM routing decision: {next_agent} (confidence: {confidence}) - {reasoning}")
147
-
148
- # Validate the selected agent is available
149
- if next_agent and next_agent not in available_agents and next_agent != "":
150
- logger.warning(f"LLM selected unavailable agent '{next_agent}', ending workflow")
151
- return "", 0.0
152
-
153
- return next_agent, confidence
154
-
155
- except json.JSONDecodeError as e:
156
- logger.error(f"Failed to parse LLM response as JSON: {e}")
157
- return "", 0.0
158
-
159
- except Exception as e:
160
- logger.error(f"Error calling LLM for routing: {e}")
161
- return "", 0.0
162
-
163
- async def determine_next_step(
164
- self,
165
- agent: "FlockAgent",
166
- result: dict[str, Any],
167
- context: FlockContext | None = None,
168
- ) -> None:
169
- """Use LLM to determine the next agent based on current output."""
170
- if not context:
171
- logger.warning("No context provided for LLM routing")
172
- return
173
-
174
- logger.info(f"LLM routing from agent '{agent.name}'")
175
-
176
- # Get available agents from context
177
- agent_definitions = getattr(context, 'agent_definitions', {})
178
- available_agents = self._get_available_agents(agent_definitions, agent.name)
179
-
180
- logger.debug(f"Available agents for LLM routing: {available_agents}")
181
-
182
- if not available_agents:
183
- logger.warning("No available agents for LLM routing")
184
- return
185
-
186
- # Use LLM to select the next agent
187
- next_agent_name, confidence = await self._select_next_agent(
188
- agent, result, available_agents
189
- )
190
-
191
- logger.info(f"LLM routing result: {next_agent_name} (confidence: {confidence})")
192
-
193
- # Check confidence threshold
194
- if not next_agent_name or confidence < self.config.confidence_threshold:
195
- logger.warning(
196
- f"LLM routing confidence {confidence} below threshold {self.config.confidence_threshold}"
197
- )
198
- return
199
-
200
- # Validate the selected agent exists
201
- if next_agent_name not in agent_definitions:
202
- logger.error(f"LLM selected non-existent agent '{next_agent_name}'")
203
- return
204
-
205
- logger.info(f"Successfully routed to agent '{next_agent_name}' with confidence {confidence}")
206
- agent.next_agent = next_agent_name
@@ -1,22 +0,0 @@
1
- # src/flock/components/utility/__init__.py
2
- """Utility components for the Flock framework."""
3
-
4
- from .example_utility_component import ExampleUtilityComponent, ExampleUtilityConfig, ExampleRecord
5
- from .feedback_utility_component import FeedbackUtilityComponent, FeedbackUtilityConfig
6
- from .memory_utility_component import MemoryUtilityComponent, MemoryUtilityConfig
7
- from .metrics_utility_component import MetricsUtilityComponent, MetricsUtilityConfig
8
- from .output_utility_component import OutputUtilityComponent, OutputUtilityConfig
9
-
10
- __all__ = [
11
- "ExampleUtilityComponent",
12
- "ExampleUtilityConfig",
13
- "ExampleRecord",
14
- "FeedbackUtilityComponent",
15
- "FeedbackUtilityConfig",
16
- "MemoryUtilityComponent",
17
- "MemoryUtilityConfig",
18
- "MetricsUtilityComponent",
19
- "MetricsUtilityConfig",
20
- "OutputUtilityComponent",
21
- "OutputUtilityConfig",
22
- ]
@@ -1,250 +0,0 @@
1
- """Example utility component for n-shot learning."""
2
-
3
- from datetime import datetime, timedelta
4
- from typing import Any, Literal
5
-
6
- from pydantic import Field
7
-
8
- from flock.core.component.agent_component_base import AgentComponentConfig
9
- from flock.core.component.utility_component import UtilityComponent
10
- from flock.core.context.context import FlockContext
11
- from flock.core.logging.logging import get_logger
12
- from flock.core.registry import flock_component
13
-
14
- if TYPE_CHECKING:
15
- from flock.core.flock_agent import FlockAgent
16
- from flock.webapp.app.services.sharing_store import SharedLinkStoreInterface
17
-
18
- logger = get_logger("components.utility.example")
19
-
20
-
21
- class ExampleUtilityConfig(AgentComponentConfig):
22
- """Configuration for the ExampleUtilityComponent."""
23
-
24
- # Storage configuration
25
- storage_type: Literal["sqlite", "azure"] = Field(
26
- default="sqlite",
27
- description="Type of storage backend for example data"
28
- )
29
-
30
- # SQLite configuration
31
- sqlite_db_path: str = Field(
32
- default="./flock_examples.db",
33
- description="Path to SQLite database file"
34
- )
35
-
36
- # Azure Table Storage configuration
37
- azure_connection_string: str | None = Field(
38
- default=None,
39
- description="Azure Table Storage connection string"
40
- )
41
- azure_table_name: str = Field(
42
- default="flockexamples",
43
- description="Azure Table Storage table name"
44
- )
45
-
46
- # Example selection criteria
47
- max_examples: int = Field(
48
- default=5,
49
- description="Maximum number of examples to include"
50
- )
51
- example_timeframe_days: int = Field(
52
- default=30,
53
- description="Only include examples from the last N days"
54
- )
55
-
56
- # Example injection settings
57
- example_input_key: str = Field(
58
- default="examples_context",
59
- description="Input key to use for injected examples"
60
- )
61
-
62
- # Example filtering
63
- example_filter_keywords: list[str] = Field(
64
- default_factory=list,
65
- description="Keywords to filter examples (only include examples containing these)"
66
- )
67
- example_exclude_keywords: list[str] = Field(
68
- default_factory=list,
69
- description="Keywords to exclude examples containing these"
70
- )
71
-
72
-
73
- @flock_component(config_class=ExampleUtilityConfig)
74
- class ExampleUtilityComponent(UtilityComponent):
75
- """Utility component that injects relevant examples into agent inputs for n-shot learning."""
76
-
77
- config: ExampleUtilityConfig = Field(
78
- default_factory=ExampleUtilityConfig,
79
- description="Example component configuration"
80
- )
81
-
82
- def __init__(self, name: str = "examples", config: ExampleUtilityConfig | None = None, **data):
83
- super().__init__(name=name, config=config or ExampleUtilityConfig(), **data)
84
- self._store: SharedLinkStoreInterface | None = None
85
-
86
- async def _get_store(self) -> SharedLinkStoreInterface:
87
- """Get the appropriate example store based on configuration."""
88
- if self._store is None:
89
- if self.config.storage_type == "sqlite":
90
- from flock.webapp.app.services.sharing_store import SQLiteSharedLinkStore
91
- self._store = SQLiteSharedLinkStore(self.config.sqlite_db_path)
92
- elif self.config.storage_type == "azure":
93
- if not self.config.azure_connection_string:
94
- raise ValueError("Azure connection string is required for Azure storage")
95
- from flock.webapp.app.services.sharing_store import AzureTableSharedLinkStore
96
- self._store = AzureTableSharedLinkStore(
97
- connection_string=self.config.azure_connection_string,
98
- table_name=self.config.azure_table_name
99
- )
100
- else:
101
- raise ValueError(f"Unsupported storage type: {self.config.storage_type}")
102
-
103
- await self._store.initialize()
104
-
105
- return self._store
106
-
107
- @staticmethod
108
- def seed_examples(examples: list["ExampleRecord"]) -> None:
109
- """Seed examples into the storage system.
110
-
111
- Args:
112
- examples: List of ExampleRecord objects to seed
113
- """
114
- import asyncio
115
-
116
- async def _seed_examples():
117
- # Create a default component for seeding
118
- component = ExampleUtilityComponent()
119
- store = await component._get_store()
120
-
121
- for example in examples:
122
- await store.save_example(example)
123
-
124
- logger.info(f"Seeded {len(examples)} examples into storage")
125
-
126
- # Run the async function
127
- asyncio.run(_seed_examples())
128
-
129
- async def _get_relevant_examples(
130
- self,
131
- agent_name: str,
132
- inputs: dict[str, Any]
133
- ) -> list["ExampleRecord"]:
134
- """Get relevant examples for the given agent and inputs."""
135
- store = await self._get_store()
136
-
137
- # Get all examples for this agent
138
- all_examples = await store.get_all_examples_for_agent(agent_name)
139
-
140
- # Filter by timeframe
141
- cutoff_date = datetime.utcnow() - timedelta(days=self.config.example_timeframe_days)
142
- filtered_examples = [
143
- ex for ex in all_examples
144
- if ex.created_at >= cutoff_date
145
- ]
146
-
147
- # Filter by keywords if specified
148
- if self.config.example_filter_keywords:
149
- filtered_examples = [
150
- ex for ex in filtered_examples
151
- if any(keyword.lower() in ex.content.lower() for keyword in self.config.example_filter_keywords)
152
- ]
153
-
154
- # Exclude by keywords if specified
155
- if self.config.example_exclude_keywords:
156
- filtered_examples = [
157
- ex for ex in filtered_examples
158
- if not any(keyword.lower() in ex.content.lower() for keyword in self.config.example_exclude_keywords)
159
- ]
160
-
161
- # Sort by recency and limit
162
- filtered_examples.sort(key=lambda ex: ex.created_at, reverse=True)
163
- return filtered_examples[:self.config.max_examples]
164
-
165
- def _format_examples_for_injection(
166
- self,
167
- example_records: list["ExampleRecord"]
168
- ) -> str:
169
- """Format example records for injection into agent input."""
170
- if not example_records:
171
- return "No relevant examples available."
172
-
173
- formatted_parts = []
174
- formatted_parts.append(f"Here are {len(example_records)} examples to guide your response:")
175
-
176
- for i, ex in enumerate(example_records, 1):
177
- ex_text = f"\nExample {i} (ID: {ex.example_id}):"
178
- ex_text += f"\n{ex.content}"
179
- ex_text += f"\nDate: {ex.created_at.strftime('%Y-%m-%d')}"
180
- formatted_parts.append(ex_text)
181
-
182
- return "\n".join(formatted_parts)
183
-
184
- async def on_pre_evaluate(
185
- self,
186
- agent: "FlockAgent",
187
- inputs: dict[str, Any],
188
- context: FlockContext | None = None,
189
- ) -> dict[str, Any]:
190
- """Inject relevant examples into agent inputs before evaluation."""
191
- logger.debug(f"Injecting examples for agent '{agent.name}'")
192
-
193
- try:
194
- # Get relevant examples for this agent
195
- example_records = await self._get_relevant_examples(agent.name, inputs)
196
-
197
- # Format examples for injection
198
- formatted_examples = self._format_examples_for_injection(example_records)
199
-
200
- # Create a copy of inputs to avoid modifying the original
201
- enhanced_inputs = inputs.copy()
202
-
203
- # Inject examples using the configured key
204
- enhanced_inputs[self.config.example_input_key] = formatted_examples
205
-
206
- logger.debug(f"Injected {len(example_records)} examples into '{self.config.example_input_key}'")
207
-
208
- return enhanced_inputs
209
-
210
- except Exception as e:
211
- logger.error(f"Error injecting examples: {e}")
212
- # Return original inputs if example injection fails
213
- return inputs
214
-
215
-
216
- # Example record model
217
- class ExampleRecord:
218
- """Record for storing example data."""
219
-
220
- def __init__(
221
- self,
222
- agent_name: str,
223
- example_id: str,
224
- content: str,
225
- created_at: datetime | None = None
226
- ):
227
- self.agent_name = agent_name
228
- self.example_id = example_id
229
- self.content = content
230
- self.created_at = created_at or datetime.utcnow()
231
-
232
- def to_dict(self) -> dict[str, Any]:
233
- """Convert to dictionary for storage."""
234
- return {
235
- "agent_name": self.agent_name,
236
- "example_id": self.example_id,
237
- "content": self.content,
238
- "created_at": self.created_at.isoformat(),
239
- "context_type": "example"
240
- }
241
-
242
- @classmethod
243
- def from_dict(cls, data: dict[str, Any]) -> "ExampleRecord":
244
- """Create from dictionary from storage."""
245
- return cls(
246
- agent_name=data["agent_name"],
247
- example_id=data["example_id"],
248
- content=data["content"],
249
- created_at=datetime.fromisoformat(data["created_at"])
250
- )
@@ -1,206 +0,0 @@
1
- """Feedback utility component for learning from user feedback."""
2
-
3
- from datetime import datetime, timedelta
4
- from typing import TYPE_CHECKING, Any, Literal
5
-
6
- from pydantic import Field
7
-
8
- from flock.core.component.agent_component_base import AgentComponentConfig
9
- from flock.core.component.utility_component import UtilityComponent
10
- from flock.core.context.context import FlockContext
11
- from flock.core.logging.logging import get_logger
12
- from flock.core.registry import flock_component
13
-
14
- if TYPE_CHECKING:
15
- from flock.core.flock_agent import FlockAgent
16
- from flock.webapp.app.services.sharing_models import FeedbackRecord
17
- from flock.webapp.app.services.sharing_store import SharedLinkStoreInterface
18
-
19
- logger = get_logger("components.utility.feedback")
20
-
21
-
22
- class FeedbackUtilityConfig(AgentComponentConfig):
23
- """Configuration for the FeedbackUtilityComponent."""
24
-
25
- # Storage configuration
26
- storage_type: Literal["sqlite", "azure"] = Field(
27
- default="sqlite",
28
- description="Type of storage backend for feedback data"
29
- )
30
-
31
- # SQLite configuration
32
- sqlite_db_path: str = Field(
33
- default="./flock_feedback.db",
34
- description="Path to SQLite database file"
35
- )
36
-
37
- # Azure Table Storage configuration
38
- azure_connection_string: str | None = Field(
39
- default=None,
40
- description="Azure Table Storage connection string"
41
- )
42
- azure_table_name: str = Field(
43
- default="flockfeedback",
44
- description="Azure Table Storage table name"
45
- )
46
-
47
- # Feedback selection criteria
48
- max_feedback_items: int = Field(
49
- default=5,
50
- description="Maximum number of feedback items to include"
51
- )
52
- feedback_timeframe_days: int = Field(
53
- default=30,
54
- description="Only include feedback from the last N days"
55
- )
56
-
57
- # Feedback injection settings
58
- feedback_input_key: str = Field(
59
- default="feedback_context",
60
- description="Input key to use for injected feedback"
61
- )
62
- include_expected_responses: bool = Field(
63
- default=True,
64
- description="Whether to include expected responses from feedback"
65
- )
66
- include_actual_responses: bool = Field(
67
- default=False,
68
- description="Whether to include actual responses from feedback"
69
- )
70
-
71
- # Feedback filtering
72
- feedback_filter_keywords: list[str] = Field(
73
- default_factory=list,
74
- description="Keywords to filter feedback (only include feedback containing these)"
75
- )
76
- feedback_exclude_keywords: list[str] = Field(
77
- default_factory=list,
78
- description="Keywords to exclude feedback containing these"
79
- )
80
-
81
-
82
- @flock_component(config_class=FeedbackUtilityConfig)
83
- class FeedbackUtilityComponent(UtilityComponent):
84
- """Utility component that injects relevant feedback into agent inputs."""
85
-
86
- config: FeedbackUtilityConfig = Field(
87
- default_factory=FeedbackUtilityConfig,
88
- description="Feedback component configuration"
89
- )
90
-
91
- def __init__(self, name: str = "feedback", config: FeedbackUtilityConfig | None = None, **data):
92
- super().__init__(name=name, config=config or FeedbackUtilityConfig(), **data)
93
- self._store: SharedLinkStoreInterface | None = None
94
-
95
- async def _get_store(self) -> SharedLinkStoreInterface:
96
- """Get the appropriate feedback store based on configuration."""
97
- if self._store is None:
98
- if self.config.storage_type == "sqlite":
99
- from flock.webapp.app.services.sharing_store import SQLiteSharedLinkStore
100
- self._store = SQLiteSharedLinkStore(self.config.sqlite_db_path)
101
- elif self.config.storage_type == "azure":
102
- if not self.config.azure_connection_string:
103
- raise ValueError("Azure connection string is required for Azure storage")
104
- from flock.webapp.app.services.sharing_store import AzureTableSharedLinkStore
105
- self._store = AzureTableSharedLinkStore(
106
- connection_string=self.config.azure_connection_string,
107
- table_name=self.config.azure_table_name
108
- )
109
- else:
110
- raise ValueError(f"Unsupported storage type: {self.config.storage_type}")
111
-
112
- await self._store.initialize()
113
-
114
- return self._store
115
-
116
- async def _get_relevant_feedback(
117
- self,
118
- agent_name: str,
119
- inputs: dict[str, Any]
120
- ) -> list["FeedbackRecord"]:
121
- """Get relevant feedback for the given agent and inputs."""
122
- store = await self._get_store()
123
-
124
- # Get all feedback for this agent
125
- all_feedback = await store.get_all_feedback_records_for_agent(agent_name)
126
-
127
- # Filter by timeframe
128
- cutoff_date = datetime.utcnow() - timedelta(days=self.config.feedback_timeframe_days)
129
- filtered_feedback = [
130
- fb for fb in all_feedback
131
- if fb.created_at >= cutoff_date
132
- ]
133
-
134
- # Filter by keywords if specified
135
- if self.config.feedback_filter_keywords:
136
- filtered_feedback = [
137
- fb for fb in filtered_feedback
138
- if any(keyword.lower() in fb.reason.lower() for keyword in self.config.feedback_filter_keywords)
139
- ]
140
-
141
- # Exclude by keywords if specified
142
- if self.config.feedback_exclude_keywords:
143
- filtered_feedback = [
144
- fb for fb in filtered_feedback
145
- if not any(keyword.lower() in fb.reason.lower() for keyword in self.config.feedback_exclude_keywords)
146
- ]
147
-
148
- # Sort by recency and limit
149
- filtered_feedback.sort(key=lambda fb: fb.created_at, reverse=True)
150
- return filtered_feedback[:self.config.max_feedback_items]
151
-
152
- def _format_feedback_for_injection(
153
- self,
154
- feedback_records: list["FeedbackRecord"]
155
- ) -> str:
156
- """Format feedback records for injection into agent input."""
157
- if not feedback_records:
158
- return "No relevant feedback available."
159
-
160
- formatted_parts = []
161
- formatted_parts.append(f"Here are {len(feedback_records)} pieces of relevant feedback from previous interactions:")
162
-
163
- for i, fb in enumerate(feedback_records, 1):
164
- fb_text = f"\n{i}. Feedback: {fb.reason}"
165
-
166
- if self.config.include_expected_responses and fb.expected_response:
167
- fb_text += f"\n Expected response: {fb.expected_response}"
168
-
169
- if self.config.include_actual_responses and fb.actual_response:
170
- fb_text += f"\n Actual response: {fb.actual_response}"
171
-
172
- fb_text += f"\n Date: {fb.created_at.strftime('%Y-%m-%d')}"
173
- formatted_parts.append(fb_text)
174
-
175
- return "\n".join(formatted_parts)
176
-
177
- async def on_pre_evaluate(
178
- self,
179
- agent: "FlockAgent",
180
- inputs: dict[str, Any],
181
- context: FlockContext | None = None,
182
- ) -> dict[str, Any]:
183
- """Inject relevant feedback into agent inputs before evaluation."""
184
- logger.debug(f"Injecting feedback for agent '{agent.name}'")
185
-
186
- try:
187
- # Get relevant feedback for this agent
188
- feedback_records = await self._get_relevant_feedback(agent.name, inputs)
189
-
190
- # Format feedback for injection
191
- formatted_feedback = self._format_feedback_for_injection(feedback_records)
192
-
193
- # Create a copy of inputs to avoid modifying the original
194
- enhanced_inputs = inputs.copy()
195
-
196
- # Inject feedback using the configured key
197
- enhanced_inputs[self.config.feedback_input_key] = formatted_feedback
198
-
199
- logger.debug(f"Injected {len(feedback_records)} feedback items into '{self.config.feedback_input_key}'")
200
-
201
- return enhanced_inputs
202
-
203
- except Exception as e:
204
- logger.error(f"Error injecting feedback: {e}")
205
- # Return original inputs if feedback injection fails
206
- return inputs