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,12 +1,12 @@
1
1
  """Base Config for MCP Clients."""
2
2
 
3
3
  import importlib
4
- from typing import Any, Literal, TypeVar
4
+ from typing import TYPE_CHECKING, Any, Literal, TypeVar
5
5
 
6
- import httpx
7
6
  from pydantic import BaseModel, ConfigDict, Field, create_model
7
+ from typing_extensions import Self
8
8
 
9
- from flock.core.mcp.types.types import (
9
+ from flock.mcp.types import (
10
10
  FlockListRootsMCPCallback,
11
11
  FlockLoggingMCPCallback,
12
12
  FlockMessageHandlerMCPCallback,
@@ -18,11 +18,11 @@ from flock.core.mcp.types.types import (
18
18
  StreamableHttpServerParameters,
19
19
  WebsocketServerParameters,
20
20
  )
21
- from flock.core.serialization.serializable import Serializable
22
- from flock.core.serialization.serialization_utils import (
23
- deserialize_item,
24
- serialize_item,
25
- )
21
+
22
+
23
+ if TYPE_CHECKING:
24
+ import httpx
25
+
26
26
 
27
27
  LoggingLevel = Literal[
28
28
  "debug",
@@ -43,7 +43,7 @@ D = TypeVar("D", bound="FlockMCPCachingConfiguration")
43
43
  E = TypeVar("E", bound="FlockMCPFeatureConfiguration")
44
44
 
45
45
 
46
- class FlockMCPCachingConfiguration(BaseModel, Serializable):
46
+ class FlockMCPCachingConfiguration(BaseModel):
47
47
  """Configuration for Caching in Clients."""
48
48
 
49
49
  tool_cache_max_size: float = Field(
@@ -98,19 +98,17 @@ class FlockMCPCachingConfiguration(BaseModel, Serializable):
98
98
  )
99
99
 
100
100
  @classmethod
101
- def from_dict(cls: type[D], data: dict[str, Any]) -> D:
101
+ def from_dict(cls, data: dict[str, Any]) -> Self:
102
102
  """Deserialize from a dict."""
103
- return cls(**{k: v for k, v in data.items()})
103
+ return cls(**dict(data.items()))
104
104
 
105
105
  @classmethod
106
- def with_fields(cls: type[D], **field_definitions) -> type[D]:
106
+ def with_fields(cls, **field_definitions) -> type[Self]:
107
107
  """Create a new config class with additional fields."""
108
- return create_model(
109
- f"Dynamic{cls.__name__}", __base__=cls, **field_definitions
110
- )
108
+ return create_model(f"Dynamic{cls.__name__}", __base__=cls, **field_definitions)
111
109
 
112
110
 
113
- class FlockMCPCallbackConfiguration(BaseModel, Serializable):
111
+ class FlockMCPCallbackConfiguration(BaseModel):
114
112
  """Base Configuration Class for Callbacks for Clients."""
115
113
 
116
114
  sampling_callback: FlockSamplingMCPCallback | None = Field(
@@ -136,59 +134,21 @@ class FlockMCPCallbackConfiguration(BaseModel, Serializable):
136
134
 
137
135
  def to_dict(self, path_type: str = "relative"):
138
136
  """Serialize the object."""
139
- # we need to register callables.
140
- data: dict[str, Any] = {}
141
- if self.sampling_callback:
142
- sampling_callback_data = serialize_item(self.sampling_callback)
143
- data["sampling_callback"] = sampling_callback_data
144
-
145
- if self.list_roots_callback:
146
- list_roots_callback_data = serialize_item(self.list_roots_callback)
147
- data["list_roots_callback"] = list_roots_callback_data
148
-
149
- if self.logging_callback:
150
- logging_callback_data = serialize_item(self.logging_callback)
151
- data["logging_callback"] = logging_callback_data
152
-
153
- if self.message_handler:
154
- message_handler_data = serialize_item(self.message_handler)
155
- data["message_handler"] = message_handler_data
156
-
157
- return data
137
+ # Callbacks are set programmatically and cannot be serialized
138
+ return {}
158
139
 
159
140
  @classmethod
160
- def from_dict(cls: type[A], data: dict[str, Any]) -> A:
141
+ def from_dict(cls, data: dict[str, Any]) -> Self:
161
142
  """Deserialize from a dict."""
162
- instance = cls()
163
- if data:
164
- if "sampling_callback" in data:
165
- instance.sampling_callback = deserialize_item(
166
- data["sampling_callback"]
167
- )
168
- if "list_roots_callback" in data:
169
- instance.list_roots_callback = deserialize_item(
170
- data["list_roots_callback"]
171
- )
172
- if "logging_callback" in data:
173
- instance.logging_callback = deserialize_item(
174
- data["logging_callback"]
175
- )
176
- if "message_handler" in data:
177
- instance.message_handler = deserialize_item(
178
- data["message_handler"]
179
- )
180
-
181
- return instance
143
+ return cls()
182
144
 
183
145
  @classmethod
184
- def with_fields(cls: type[A], **field_definitions) -> type[A]:
146
+ def with_fields(cls, **field_definitions) -> type[Self]:
185
147
  """Create a new config class with additional fields."""
186
- return create_model(
187
- f"Dynamic{cls.__name__}", __base__=cls, **field_definitions
188
- )
148
+ return create_model(f"Dynamic{cls.__name__}", __base__=cls, **field_definitions)
189
149
 
190
150
 
191
- class FlockMCPConnectionConfiguration(BaseModel, Serializable):
151
+ class FlockMCPConnectionConfiguration(BaseModel):
192
152
  """Base Configuration Class for Connection Parameters for a client."""
193
153
 
194
154
  max_retries: int = Field(
@@ -200,17 +160,15 @@ class FlockMCPConnectionConfiguration(BaseModel, Serializable):
200
160
  ..., description="Connection parameters for the server."
201
161
  )
202
162
 
203
- transport_type: Literal[
204
- "stdio", "websockets", "sse", "streamable_http", "custom"
205
- ] = Field(..., description="Type of transport to use.")
163
+ transport_type: Literal["stdio", "websockets", "sse", "streamable_http", "custom"] = Field(
164
+ ..., description="Type of transport to use."
165
+ )
206
166
 
207
167
  mount_points: list[MCPRoot] | None = Field(
208
168
  default=None, description="Initial Mountpoints to operate under."
209
169
  )
210
170
 
211
- read_timeout_seconds: float | int = Field(
212
- default=60 * 5, description="Read Timeout."
213
- )
171
+ read_timeout_seconds: float | int = Field(default=60 * 5, description="Read Timeout.")
214
172
 
215
173
  server_logging_level: LoggingLevel = Field(
216
174
  default="error",
@@ -230,14 +188,12 @@ class FlockMCPConnectionConfiguration(BaseModel, Serializable):
230
188
  mode="json",
231
189
  )
232
190
 
233
- data["connection_parameters"] = self.connection_parameters.to_dict(
234
- path_type=path_type
235
- )
191
+ data["connection_parameters"] = self.connection_parameters.to_dict(path_type=path_type)
236
192
 
237
193
  return data
238
194
 
239
195
  @classmethod
240
- def from_dict(cls: type[B], data: dict[str, Any]) -> B:
196
+ def from_dict(cls, data: dict[str, Any]) -> Self:
241
197
  """Deserialize from dict."""
242
198
  connection_params = data.get("connection_parameters")
243
199
  connection_params_obj = None
@@ -248,13 +204,13 @@ class FlockMCPConnectionConfiguration(BaseModel, Serializable):
248
204
  if auth_spec:
249
205
  # find the concrete implementation and
250
206
  # instantiate it.
251
- # find the concrete implementation for auth and instatiate it.
207
+ # find the concrete implementation for auth and instatiate it.
252
208
  impl = auth_spec.get("implementation", None)
253
209
  params = auth_spec.get("params", None)
254
210
  if impl and params:
255
- mod = importlib.import_module(impl["module_path"])
256
- real_cls = getattr(mod, impl["class_name"])
257
- auth_obj = real_cls(**{k: v for k, v in params.items()})
211
+ mod = importlib.import_module(impl["module_path"])
212
+ real_cls = getattr(mod, impl["class_name"])
213
+ auth_obj = real_cls(**dict(params.items()))
258
214
 
259
215
  if auth_obj:
260
216
  connection_params["auth"] = auth_obj
@@ -264,41 +220,36 @@ class FlockMCPConnectionConfiguration(BaseModel, Serializable):
264
220
  match kind:
265
221
  case "stdio":
266
222
  connection_params_obj = StdioServerParameters(
267
- **{k: v for k, v in connection_params.items()}
223
+ **dict(connection_params.items())
268
224
  )
269
225
  case "websockets":
270
226
  connection_params_obj = WebsocketServerParameters(
271
- **{k: v for k, v in connection_params.items()}
227
+ **dict(connection_params.items())
272
228
  )
273
229
  case "streamable_http":
274
230
  connection_params_obj = StreamableHttpServerParameters(
275
- **{k: v for k, v in connection_params.items()}
231
+ **dict(connection_params.items())
276
232
  )
277
233
  case "sse":
278
234
  connection_params_obj = SseServerParameters(
279
- **{k: v for k, v in connection_params.items()}
235
+ **dict(connection_params.items())
280
236
  )
281
237
  case _:
282
238
  # handle custom server params
283
- connection_params_obj = ServerParameters(
284
- **{k: v for k, v in connection_params.items()}
285
- )
239
+ connection_params_obj = ServerParameters(**dict(connection_params.items()))
286
240
 
287
241
  if connection_params_obj:
288
242
  data["connection_parameters"] = connection_params_obj
289
- return cls(**{k: v for k, v in data.items()})
290
- else:
291
- raise ValueError("No connection parameters provided.")
243
+ return cls(**dict(data.items()))
244
+ raise ValueError("No connection parameters provided.")
292
245
 
293
246
  @classmethod
294
- def with_fields(cls: type[B], **field_definitions) -> type[B]:
247
+ def with_fields(cls, **field_definitions) -> type[Self]:
295
248
  """Create a new config class with additional fields."""
296
- return create_model(
297
- f"Dynamic{cls.__name__}", __base__=cls, **field_definitions
298
- )
249
+ return create_model(f"Dynamic{cls.__name__}", __base__=cls, **field_definitions)
299
250
 
300
251
 
301
- class FlockMCPFeatureConfiguration(BaseModel, Serializable):
252
+ class FlockMCPFeatureConfiguration(BaseModel):
302
253
  """Base Configuration Class for switching MCP Features on and off."""
303
254
 
304
255
  roots_enabled: bool = Field(
@@ -319,10 +270,10 @@ class FlockMCPFeatureConfiguration(BaseModel, Serializable):
319
270
  tool_whitelist: list[str] | None = Field(
320
271
  default=None,
321
272
  description="Whitelist of tool names that are enabled for this MCP server. "
322
- "If provided, only tools with names in this list will be available "
323
- "from this server. Used in conjunction with allow_all_tools setting. "
324
- "Note: Agent-level tool filtering is generally preferred over "
325
- "server-level filtering for better granular control."
273
+ "If provided, only tools with names in this list will be available "
274
+ "from this server. Used in conjunction with allow_all_tools setting. "
275
+ "Note: Agent-level tool filtering is generally preferred over "
276
+ "server-level filtering for better granular control.",
326
277
  )
327
278
 
328
279
  prompts_enabled: bool = Field(
@@ -345,34 +296,30 @@ class FlockMCPFeatureConfiguration(BaseModel, Serializable):
345
296
  @classmethod
346
297
  def from_dict(cls, data: dict[str, Any]):
347
298
  """Deserialize from a dict."""
348
- return cls(**{k: v for k, v in data.items()})
299
+ return cls(**dict(data.items()))
349
300
 
350
301
  @classmethod
351
- def with_fields(cls: type[E], **field_definitions) -> type[E]:
302
+ def with_fields(cls, **field_definitions) -> type[Self]:
352
303
  """Create a new config class with additional fields."""
353
- return create_model(
354
- f"Dynamic{cls.__name__}", __base__=cls, **field_definitions
355
- )
304
+ return create_model(f"Dynamic{cls.__name__}", __base__=cls, **field_definitions)
356
305
 
357
306
 
358
- class FlockMCPConfiguration(BaseModel, Serializable):
307
+ class FlockMCPConfiguration(BaseModel):
359
308
  """Base Configuration Class for MCP Clients.
360
309
 
361
310
  Each Client should implement their own config
362
311
  model by inheriting from this class.
363
312
  """
364
313
 
365
- name: str = Field(
366
- ..., description="Name of the server the client connects to."
367
- )
314
+ name: str = Field(..., description="Name of the server the client connects to.")
368
315
 
369
316
  allow_all_tools: bool = Field(
370
317
  default=True,
371
318
  description="Whether to allow usage of all tools from this MCP server. "
372
- "When True (default), all tools are available unless restricted "
373
- "by tool_whitelist. When False, tool access is controlled entirely "
374
- "by tool_whitelist (if provided). Setting to False with no whitelist "
375
- "will block all tools from this server."
319
+ "When True (default), all tools are available unless restricted "
320
+ "by tool_whitelist. When False, tool access is controlled entirely "
321
+ "by tool_whitelist (if provided). Setting to False with no whitelist "
322
+ "will block all tools from this server.",
376
323
  )
377
324
 
378
325
  connection_config: FlockMCPConnectionConfiguration = Field(
@@ -425,16 +372,14 @@ class FlockMCPConfiguration(BaseModel, Serializable):
425
372
  return data
426
373
 
427
374
  @classmethod
428
- def from_dict(cls: type[C], data: dict[str, Any]) -> C:
375
+ def from_dict(cls, data: dict[str, Any]) -> Self:
429
376
  """Deserialize the class."""
430
377
  connection_config = data.pop("connection_config", None)
431
378
  caching_config = data.pop("caching_config", None)
432
379
  feature_config = data.pop("feature_config", None)
433
380
  callback_config = data.pop("callback_config", None)
434
381
 
435
- instance_data: dict[str, Any] = {
436
- "name": data["name"]
437
- }
382
+ instance_data: dict[str, Any] = {"name": data["name"]}
438
383
 
439
384
  if connection_config:
440
385
  # Forcing a square into a round hole
@@ -446,7 +391,9 @@ class FlockMCPConfiguration(BaseModel, Serializable):
446
391
  config_cls = FlockMCPConnectionConfiguration
447
392
  instance_data["connection_config"] = config_cls.from_dict(connection_config)
448
393
  else:
449
- raise ValueError(f"connection_config MUST be specified for '{data.get('name', 'unknown_server')}")
394
+ raise ValueError(
395
+ f"connection_config MUST be specified for '{data.get('name', 'unknown_server')}"
396
+ )
450
397
 
451
398
  if caching_config:
452
399
  try:
@@ -481,11 +428,9 @@ class FlockMCPConfiguration(BaseModel, Serializable):
481
428
  else:
482
429
  instance_data["callback_config"] = FlockMCPCallbackConfiguration()
483
430
 
484
- return cls(**{k: v for k, v in instance_data.items()})
431
+ return cls(**dict(instance_data.items()))
485
432
 
486
433
  @classmethod
487
- def with_fields(cls: type[C], **field_definitions) -> type[C]:
434
+ def with_fields(cls, **field_definitions) -> type[Self]:
488
435
  """Create a new config class with additional fields."""
489
- return create_model(
490
- f"Dynamic{cls.__name__}", __base__=cls, **field_definitions
491
- )
436
+ return create_model(f"Dynamic{cls.__name__}", __base__=cls, **field_definitions)
flock/mcp/manager.py ADDED
@@ -0,0 +1,255 @@
1
+ """MCP Client Manager for Connection Pooling and Lifecycle Management.
2
+
3
+ This module provides the FlockMCPClientManager class which manages MCP client
4
+ connections with per-(agent_id, run_id) isolation and lazy connection establishment.
5
+
6
+ Architecture Decisions:
7
+ - AD004: Per-(agent_id, run_id) Connection Isolation
8
+ Each unique (agent_id, run_id) pair gets its own set of isolated MCP connections
9
+ - AD005: Lazy Connection Establishment
10
+ Connections are only established when first requested
11
+ - AD007: Graceful Degradation on MCP Failures
12
+ Failures to connect to individual servers don't prevent agent execution
13
+ """
14
+
15
+ import asyncio
16
+ from typing import Any
17
+
18
+ from flock.logging.logging import get_logger
19
+ from flock.mcp.client import FlockMCPClient
20
+ from flock.mcp.config import FlockMCPConfiguration
21
+
22
+
23
+ logger = get_logger(__name__)
24
+
25
+
26
+ class FlockMCPClientManager:
27
+ """Manages MCP client connections with per-(agent_id, run_id) isolation.
28
+
29
+ This manager implements lazy connection pooling where clients are only
30
+ initialized when first requested. Each unique (agent_id, run_id) pair
31
+ gets its own set of isolated MCP connections.
32
+
33
+ Architecture Decision: AD004 - Per-(agent_id, run_id) Connection Isolation
34
+
35
+ Example:
36
+ ```python
37
+ # Initialize manager with configurations
38
+ configs = {
39
+ "filesystem": FlockMCPConfiguration(
40
+ name="filesystem",
41
+ connection_config=connection_config,
42
+ feature_config=feature_config
43
+ )
44
+ }
45
+ manager = FlockMCPClientManager(configs)
46
+
47
+ # Get client for specific agent and run
48
+ client = await manager.get_client("filesystem", "agent_1", "run_123")
49
+
50
+ # Get all tools for agent
51
+ tools = await manager.get_tools_for_agent(
52
+ "agent_1", "run_123", {"filesystem"}
53
+ )
54
+
55
+ # Cleanup after run completes
56
+ await manager.cleanup_run("agent_1", "run_123")
57
+ ```
58
+ """
59
+
60
+ def __init__(self, configs: dict[str, FlockMCPConfiguration]):
61
+ """Initialize the manager with MCP server configurations.
62
+
63
+ Args:
64
+ configs: Dictionary mapping server names to their configurations
65
+ """
66
+ self._configs = configs
67
+ # Pool structure: (agent_id, run_id) → server_name → FlockMCPClient
68
+ self._pool: dict[tuple[str, str], dict[str, FlockMCPClient]] = {}
69
+ self._lock = asyncio.Lock()
70
+
71
+ async def get_client(self, server_name: str, agent_id: str, run_id: str) -> FlockMCPClient:
72
+ """Get or create an MCP client for the given context.
73
+
74
+ Architecture Decision: AD005 - Lazy Connection Establishment
75
+ Connections are only established when first requested.
76
+
77
+ Args:
78
+ server_name: Name of the MCP server
79
+ agent_id: Agent requesting the client
80
+ run_id: Current run identifier
81
+
82
+ Returns:
83
+ FlockMCPClient instance ready for use
84
+
85
+ Raises:
86
+ ValueError: If server_name not registered
87
+ """
88
+ if server_name not in self._configs:
89
+ raise ValueError(
90
+ f"MCP server '{server_name}' not registered. "
91
+ f"Available servers: {list(self._configs.keys())}"
92
+ )
93
+
94
+ key = (agent_id, run_id)
95
+
96
+ async with self._lock:
97
+ # Check if we have a client pool for this (agent, run)
98
+ if key not in self._pool:
99
+ self._pool[key] = {}
100
+
101
+ # Check if we have a client for this server
102
+ if server_name not in self._pool[key]:
103
+ logger.info(
104
+ f"Creating new MCP client for server '{server_name}' "
105
+ f"(agent={agent_id}, run={run_id})"
106
+ )
107
+ config = self._configs[server_name]
108
+
109
+ # Instantiate the correct concrete client class based on transport type
110
+ # Lazy import to avoid requiring all dependencies
111
+ transport_type = config.connection_config.transport_type
112
+ if transport_type == "stdio":
113
+ from flock.mcp.servers.stdio.flock_stdio_server import (
114
+ FlockStdioClient,
115
+ )
116
+
117
+ client = FlockStdioClient(config=config)
118
+ elif transport_type == "sse":
119
+ from flock.mcp.servers.sse.flock_sse_server import (
120
+ FlockSSEClient,
121
+ )
122
+
123
+ client = FlockSSEClient(config=config)
124
+ elif transport_type == "websocket":
125
+ from flock.mcp.servers.websockets.flock_websocket_server import (
126
+ FlockWSClient,
127
+ )
128
+
129
+ client = FlockWSClient(config=config)
130
+ elif transport_type == "streamable_http":
131
+ from flock.mcp.servers.streamable_http.flock_streamable_http_server import (
132
+ FlockStreamableHttpClient,
133
+ )
134
+
135
+ client = FlockStreamableHttpClient(config=config)
136
+ else:
137
+ raise ValueError(
138
+ f"Unsupported transport type: {transport_type}. "
139
+ f"Supported types: stdio, sse, websocket, streamable_http"
140
+ )
141
+
142
+ await client._connect()
143
+ self._pool[key][server_name] = client
144
+
145
+ return self._pool[key][server_name]
146
+
147
+ async def get_tools_for_agent(
148
+ self, agent_id: str, run_id: str, server_names: set[str]
149
+ ) -> dict[str, Any]:
150
+ """Get all tools from specified servers for an agent.
151
+
152
+ Architecture Decision: AD003 - Tool Namespacing
153
+ All tools are returned with format: {server}__{tool}
154
+
155
+ Args:
156
+ agent_id: Agent requesting tools
157
+ run_id: Current run identifier
158
+ server_names: Set of MCP server names to fetch tools from
159
+
160
+ Returns:
161
+ Dictionary mapping namespaced tool names to tool definitions
162
+
163
+ Note:
164
+ Architecture Decision: AD007 - Graceful Degradation
165
+ If a server fails to load, we log the error and continue with
166
+ other servers rather than failing the entire operation.
167
+ """
168
+ tools = {}
169
+
170
+ for server_name in server_names:
171
+ try:
172
+ client = await self.get_client(server_name, agent_id, run_id)
173
+ server_tools = await client.get_tools(agent_id, run_id)
174
+
175
+ # Apply namespacing: AD003
176
+ for tool in server_tools:
177
+ namespaced_name = f"{server_name}__{tool.name}"
178
+ tools[namespaced_name] = {
179
+ "server_name": server_name,
180
+ "original_name": tool.name,
181
+ "tool": tool,
182
+ "client": client,
183
+ }
184
+
185
+ logger.debug(
186
+ f"Loaded {len(server_tools)} tools from server '{server_name}' "
187
+ f"for agent {agent_id}"
188
+ )
189
+
190
+ except Exception as e:
191
+ # Architecture Decision: AD007 - Graceful Degradation
192
+ logger.exception(
193
+ f"Failed to load tools from MCP server '{server_name}': {e}. "
194
+ f"Agent {agent_id} will continue without these tools."
195
+ )
196
+ # Continue loading other servers
197
+ continue
198
+
199
+ return tools
200
+
201
+ async def cleanup_run(self, agent_id: str, run_id: str) -> None:
202
+ """Clean up all MCP connections for a completed run.
203
+
204
+ Args:
205
+ agent_id: Agent identifier
206
+ run_id: Run identifier to clean up
207
+ """
208
+ key = (agent_id, run_id)
209
+
210
+ async with self._lock:
211
+ if key in self._pool:
212
+ logger.info(f"Cleaning up MCP connections for run {run_id}")
213
+ clients = self._pool[key]
214
+
215
+ # Disconnect all clients for this run
216
+ for server_name, client in clients.items():
217
+ try:
218
+ await client.disconnect()
219
+ logger.debug(f"Disconnected from MCP server '{server_name}'")
220
+ except Exception as e:
221
+ logger.warning(f"Error disconnecting from '{server_name}': {e}")
222
+
223
+ # Remove from pool
224
+ del self._pool[key]
225
+
226
+ async def cleanup_all(self) -> None:
227
+ """Clean up all MCP connections (orchestrator shutdown)."""
228
+ async with self._lock:
229
+ logger.info("Shutting down all MCP connections")
230
+
231
+ for _key, clients in self._pool.items():
232
+ for server_name, client in clients.items():
233
+ try:
234
+ await client.disconnect()
235
+ except Exception as e:
236
+ logger.warning(f"Error disconnecting from '{server_name}': {e}")
237
+
238
+ self._pool.clear()
239
+ logger.info("All MCP connections closed")
240
+
241
+ def list_servers(self) -> dict[str, dict[str, Any]]:
242
+ """List all registered MCP servers with their configurations.
243
+
244
+ Returns:
245
+ Dictionary mapping server names to configuration metadata
246
+ """
247
+ return {
248
+ name: {
249
+ "transport_type": config.connection_config.transport_type,
250
+ "tools_enabled": config.feature_config.tools_enabled,
251
+ "prompts_enabled": config.feature_config.prompts_enabled,
252
+ "sampling_enabled": config.feature_config.sampling_enabled,
253
+ }
254
+ for name, config in self._configs.items()
255
+ }
@@ -1 +1 @@
1
- """Default SSE Server Implementation for Flock."""
1
+ """Default SSE Server Implementation for flock."""