flock-core 0.4.542__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of flock-core might be problematic. Click here for more details.

Files changed (501) hide show
  1. flock/__init__.py +12 -217
  2. flock/agent.py +1079 -0
  3. flock/api/themes.py +71 -0
  4. flock/artifacts.py +86 -0
  5. flock/cli.py +147 -0
  6. flock/components.py +189 -0
  7. flock/dashboard/__init__.py +30 -0
  8. flock/dashboard/collector.py +559 -0
  9. flock/dashboard/events.py +188 -0
  10. flock/dashboard/graph_builder.py +563 -0
  11. flock/dashboard/launcher.py +235 -0
  12. flock/dashboard/models/graph.py +156 -0
  13. flock/dashboard/service.py +991 -0
  14. flock/dashboard/static_v2/assets/index-DFRnI_mt.js +111 -0
  15. flock/dashboard/static_v2/assets/index-fPLNdmp1.css +1 -0
  16. flock/dashboard/static_v2/index.html +13 -0
  17. flock/dashboard/websocket.py +246 -0
  18. flock/engines/__init__.py +6 -0
  19. flock/engines/dspy_engine.py +932 -0
  20. flock/examples.py +131 -0
  21. flock/frontend/README.md +778 -0
  22. flock/frontend/docs/DESIGN_SYSTEM.md +1980 -0
  23. flock/frontend/index.html +12 -0
  24. flock/frontend/package-lock.json +4337 -0
  25. flock/frontend/package.json +48 -0
  26. flock/frontend/src/App.tsx +139 -0
  27. flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +647 -0
  28. flock/frontend/src/__tests__/integration/indexeddb-persistence.test.tsx +699 -0
  29. flock/frontend/src/components/common/BuildInfo.tsx +39 -0
  30. flock/frontend/src/components/common/EmptyState.module.css +115 -0
  31. flock/frontend/src/components/common/EmptyState.tsx +128 -0
  32. flock/frontend/src/components/common/ErrorBoundary.module.css +169 -0
  33. flock/frontend/src/components/common/ErrorBoundary.tsx +118 -0
  34. flock/frontend/src/components/common/KeyboardShortcutsDialog.css +251 -0
  35. flock/frontend/src/components/common/KeyboardShortcutsDialog.tsx +151 -0
  36. flock/frontend/src/components/common/LoadingSpinner.module.css +97 -0
  37. flock/frontend/src/components/common/LoadingSpinner.tsx +29 -0
  38. flock/frontend/src/components/controls/PublishControl.css +547 -0
  39. flock/frontend/src/components/controls/PublishControl.test.tsx +543 -0
  40. flock/frontend/src/components/controls/PublishControl.tsx +432 -0
  41. flock/frontend/src/components/details/DetailWindowContainer.tsx +58 -0
  42. flock/frontend/src/components/details/LiveOutputTab.test.tsx +792 -0
  43. flock/frontend/src/components/details/LiveOutputTab.tsx +220 -0
  44. flock/frontend/src/components/details/MessageDetailWindow.tsx +439 -0
  45. flock/frontend/src/components/details/MessageHistoryTab.tsx +374 -0
  46. flock/frontend/src/components/details/NodeDetailWindow.test.tsx +501 -0
  47. flock/frontend/src/components/details/NodeDetailWindow.tsx +218 -0
  48. flock/frontend/src/components/details/RunStatusTab.tsx +348 -0
  49. flock/frontend/src/components/details/tabs.test.tsx +1015 -0
  50. flock/frontend/src/components/filters/ArtifactTypeFilter.tsx +21 -0
  51. flock/frontend/src/components/filters/CorrelationIDFilter.module.css +102 -0
  52. flock/frontend/src/components/filters/CorrelationIDFilter.test.tsx +197 -0
  53. flock/frontend/src/components/filters/CorrelationIDFilter.tsx +121 -0
  54. flock/frontend/src/components/filters/FilterFlyout.module.css +104 -0
  55. flock/frontend/src/components/filters/FilterFlyout.tsx +80 -0
  56. flock/frontend/src/components/filters/FilterPills.module.css +220 -0
  57. flock/frontend/src/components/filters/FilterPills.test.tsx +189 -0
  58. flock/frontend/src/components/filters/FilterPills.tsx +143 -0
  59. flock/frontend/src/components/filters/ProducerFilter.tsx +21 -0
  60. flock/frontend/src/components/filters/SavedFiltersControl.module.css +60 -0
  61. flock/frontend/src/components/filters/SavedFiltersControl.test.tsx +158 -0
  62. flock/frontend/src/components/filters/SavedFiltersControl.tsx +159 -0
  63. flock/frontend/src/components/filters/TagFilter.tsx +21 -0
  64. flock/frontend/src/components/filters/TimeRangeFilter.module.css +115 -0
  65. flock/frontend/src/components/filters/TimeRangeFilter.test.tsx +154 -0
  66. flock/frontend/src/components/filters/TimeRangeFilter.tsx +110 -0
  67. flock/frontend/src/components/filters/VisibilityFilter.tsx +21 -0
  68. flock/frontend/src/components/graph/AgentNode.test.tsx +77 -0
  69. flock/frontend/src/components/graph/AgentNode.tsx +324 -0
  70. flock/frontend/src/components/graph/GraphCanvas.tsx +613 -0
  71. flock/frontend/src/components/graph/MessageFlowEdge.tsx +128 -0
  72. flock/frontend/src/components/graph/MessageNode.test.tsx +64 -0
  73. flock/frontend/src/components/graph/MessageNode.tsx +129 -0
  74. flock/frontend/src/components/graph/MiniMap.tsx +47 -0
  75. flock/frontend/src/components/graph/TransformEdge.tsx +123 -0
  76. flock/frontend/src/components/layout/DashboardLayout.css +420 -0
  77. flock/frontend/src/components/layout/DashboardLayout.tsx +287 -0
  78. flock/frontend/src/components/layout/Header.module.css +88 -0
  79. flock/frontend/src/components/layout/Header.tsx +52 -0
  80. flock/frontend/src/components/modules/HistoricalArtifactsModule.module.css +288 -0
  81. flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +450 -0
  82. flock/frontend/src/components/modules/HistoricalArtifactsModuleWrapper.tsx +13 -0
  83. flock/frontend/src/components/modules/JsonAttributeRenderer.tsx +140 -0
  84. flock/frontend/src/components/modules/ModuleRegistry.test.ts +333 -0
  85. flock/frontend/src/components/modules/ModuleRegistry.ts +93 -0
  86. flock/frontend/src/components/modules/ModuleWindow.tsx +223 -0
  87. flock/frontend/src/components/modules/TraceModuleJaeger.tsx +1971 -0
  88. flock/frontend/src/components/modules/TraceModuleJaegerWrapper.tsx +13 -0
  89. flock/frontend/src/components/modules/registerModules.ts +29 -0
  90. flock/frontend/src/components/settings/AdvancedSettings.tsx +175 -0
  91. flock/frontend/src/components/settings/AppearanceSettings.tsx +185 -0
  92. flock/frontend/src/components/settings/GraphSettings.tsx +110 -0
  93. flock/frontend/src/components/settings/MultiSelect.tsx +235 -0
  94. flock/frontend/src/components/settings/SettingsPanel.css +327 -0
  95. flock/frontend/src/components/settings/SettingsPanel.tsx +131 -0
  96. flock/frontend/src/components/settings/ThemeSelector.tsx +298 -0
  97. flock/frontend/src/components/settings/TracingSettings.tsx +404 -0
  98. flock/frontend/src/hooks/useKeyboardShortcuts.ts +148 -0
  99. flock/frontend/src/hooks/useModulePersistence.test.ts +442 -0
  100. flock/frontend/src/hooks/useModulePersistence.ts +154 -0
  101. flock/frontend/src/hooks/useModules.ts +157 -0
  102. flock/frontend/src/hooks/usePersistence.ts +141 -0
  103. flock/frontend/src/main.tsx +13 -0
  104. flock/frontend/src/services/api.ts +337 -0
  105. flock/frontend/src/services/graphService.test.ts +330 -0
  106. flock/frontend/src/services/graphService.ts +75 -0
  107. flock/frontend/src/services/indexeddb.test.ts +793 -0
  108. flock/frontend/src/services/indexeddb.ts +848 -0
  109. flock/frontend/src/services/layout.test.ts +437 -0
  110. flock/frontend/src/services/layout.ts +357 -0
  111. flock/frontend/src/services/themeApplicator.ts +140 -0
  112. flock/frontend/src/services/themeService.ts +77 -0
  113. flock/frontend/src/services/websocket.ts +650 -0
  114. flock/frontend/src/store/filterStore.test.ts +250 -0
  115. flock/frontend/src/store/filterStore.ts +272 -0
  116. flock/frontend/src/store/graphStore.test.ts +570 -0
  117. flock/frontend/src/store/graphStore.ts +462 -0
  118. flock/frontend/src/store/moduleStore.test.ts +253 -0
  119. flock/frontend/src/store/moduleStore.ts +75 -0
  120. flock/frontend/src/store/settingsStore.ts +188 -0
  121. flock/frontend/src/store/streamStore.ts +68 -0
  122. flock/frontend/src/store/uiStore.test.ts +54 -0
  123. flock/frontend/src/store/uiStore.ts +122 -0
  124. flock/frontend/src/store/wsStore.ts +34 -0
  125. flock/frontend/src/styles/index.css +15 -0
  126. flock/frontend/src/styles/scrollbar.css +47 -0
  127. flock/frontend/src/styles/variables.css +488 -0
  128. flock/frontend/src/test/setup.ts +1 -0
  129. flock/frontend/src/types/filters.ts +47 -0
  130. flock/frontend/src/types/graph.ts +95 -0
  131. flock/frontend/src/types/modules.ts +10 -0
  132. flock/frontend/src/types/theme.ts +55 -0
  133. flock/frontend/src/utils/artifacts.ts +24 -0
  134. flock/frontend/src/utils/mockData.ts +98 -0
  135. flock/frontend/src/utils/performance.ts +16 -0
  136. flock/frontend/src/vite-env.d.ts +17 -0
  137. flock/frontend/tsconfig.json +27 -0
  138. flock/frontend/tsconfig.node.json +11 -0
  139. flock/frontend/vite.config.ts +25 -0
  140. flock/frontend/vitest.config.ts +11 -0
  141. flock/{core/util → helper}/cli_helper.py +9 -5
  142. flock/{core/logging → logging}/__init__.py +2 -3
  143. flock/logging/auto_trace.py +159 -0
  144. flock/{core/logging → logging}/formatters/enum_builder.py +3 -4
  145. flock/{core/logging → logging}/formatters/theme_builder.py +19 -44
  146. flock/{core/logging → logging}/formatters/themed_formatter.py +69 -107
  147. flock/{core/logging → logging}/logging.py +78 -61
  148. flock/{core/logging → logging}/telemetry.py +66 -26
  149. flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
  150. flock/logging/telemetry_exporter/duckdb_exporter.py +216 -0
  151. flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +13 -10
  152. flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
  153. flock/logging/trace_and_logged.py +304 -0
  154. flock/mcp/__init__.py +91 -0
  155. flock/{core/mcp/mcp_client.py → mcp/client.py} +131 -158
  156. flock/{core/mcp/mcp_config.py → mcp/config.py} +86 -132
  157. flock/mcp/manager.py +286 -0
  158. flock/mcp/servers/sse/__init__.py +1 -1
  159. flock/mcp/servers/sse/flock_sse_server.py +16 -58
  160. flock/mcp/servers/stdio/__init__.py +1 -1
  161. flock/mcp/servers/stdio/flock_stdio_server.py +13 -53
  162. flock/mcp/servers/streamable_http/flock_streamable_http_server.py +22 -67
  163. flock/mcp/servers/websockets/flock_websocket_server.py +12 -45
  164. flock/{core/mcp/flock_mcp_tool_base.py → mcp/tool.py} +24 -78
  165. flock/mcp/types/__init__.py +42 -0
  166. flock/{core/mcp → mcp}/types/callbacks.py +12 -15
  167. flock/{core/mcp → mcp}/types/factories.py +7 -6
  168. flock/{core/mcp → mcp}/types/handlers.py +13 -18
  169. flock/{core/mcp → mcp}/types/types.py +70 -74
  170. flock/{core/mcp → mcp}/util/helpers.py +3 -3
  171. flock/orchestrator.py +970 -0
  172. flock/registry.py +148 -0
  173. flock/runtime.py +262 -0
  174. flock/service.py +277 -0
  175. flock/store.py +1214 -0
  176. flock/subscription.py +111 -0
  177. flock/themes/andromeda.toml +1 -1
  178. flock/themes/apple-system-colors.toml +1 -1
  179. flock/themes/arcoiris.toml +1 -1
  180. flock/themes/atomonelight.toml +1 -1
  181. flock/themes/ayu copy.toml +1 -1
  182. flock/themes/ayu-light.toml +1 -1
  183. flock/themes/belafonte-day.toml +1 -1
  184. flock/themes/belafonte-night.toml +1 -1
  185. flock/themes/blulocodark.toml +1 -1
  186. flock/themes/breeze.toml +1 -1
  187. flock/themes/broadcast.toml +1 -1
  188. flock/themes/brogrammer.toml +1 -1
  189. flock/themes/builtin-dark.toml +1 -1
  190. flock/themes/builtin-pastel-dark.toml +1 -1
  191. flock/themes/catppuccin-latte.toml +1 -1
  192. flock/themes/catppuccin-macchiato.toml +1 -1
  193. flock/themes/catppuccin-mocha.toml +1 -1
  194. flock/themes/cga.toml +1 -1
  195. flock/themes/chalk.toml +1 -1
  196. flock/themes/ciapre.toml +1 -1
  197. flock/themes/coffee-theme.toml +1 -1
  198. flock/themes/cyberpunkscarletprotocol.toml +1 -1
  199. flock/themes/dark+.toml +1 -1
  200. flock/themes/darkermatrix.toml +1 -1
  201. flock/themes/darkmatrix.toml +2 -2
  202. flock/themes/darkside.toml +1 -1
  203. flock/themes/deep.toml +2 -2
  204. flock/themes/desert.toml +1 -1
  205. flock/themes/django.toml +1 -1
  206. flock/themes/djangosmooth.toml +1 -1
  207. flock/themes/doomone.toml +1 -1
  208. flock/themes/dotgov.toml +1 -1
  209. flock/themes/dracula+.toml +1 -1
  210. flock/themes/duckbones.toml +1 -1
  211. flock/themes/encom.toml +1 -1
  212. flock/themes/espresso.toml +1 -1
  213. flock/themes/everblush.toml +1 -1
  214. flock/themes/fairyfloss.toml +1 -1
  215. flock/themes/fideloper.toml +1 -1
  216. flock/themes/fishtank.toml +1 -1
  217. flock/themes/flexoki-light.toml +1 -1
  218. flock/themes/floraverse.toml +1 -1
  219. flock/themes/framer.toml +1 -1
  220. flock/themes/galizur.toml +1 -1
  221. flock/themes/github.toml +1 -1
  222. flock/themes/grass.toml +1 -1
  223. flock/themes/grey-green.toml +1 -1
  224. flock/themes/gruvboxlight.toml +1 -1
  225. flock/themes/guezwhoz.toml +1 -1
  226. flock/themes/harper.toml +1 -1
  227. flock/themes/hax0r-blue.toml +1 -1
  228. flock/themes/hopscotch.256.toml +1 -1
  229. flock/themes/ic-green-ppl.toml +1 -1
  230. flock/themes/iceberg-dark.toml +1 -1
  231. flock/themes/japanesque.toml +1 -1
  232. flock/themes/jubi.toml +1 -1
  233. flock/themes/kibble.toml +1 -1
  234. flock/themes/kolorit.toml +1 -1
  235. flock/themes/kurokula.toml +1 -1
  236. flock/themes/materialdesigncolors.toml +1 -1
  237. flock/themes/matrix.toml +1 -1
  238. flock/themes/mellifluous.toml +1 -1
  239. flock/themes/midnight-in-mojave.toml +1 -1
  240. flock/themes/monokai-remastered.toml +1 -1
  241. flock/themes/monokai-soda.toml +1 -1
  242. flock/themes/neon.toml +1 -1
  243. flock/themes/neopolitan.toml +5 -5
  244. flock/themes/nord-light.toml +1 -1
  245. flock/themes/ocean.toml +1 -1
  246. flock/themes/onehalfdark.toml +1 -1
  247. flock/themes/onehalflight.toml +1 -1
  248. flock/themes/palenighthc.toml +1 -1
  249. flock/themes/paulmillr.toml +1 -1
  250. flock/themes/pencildark.toml +1 -1
  251. flock/themes/pnevma.toml +1 -1
  252. flock/themes/purple-rain.toml +1 -1
  253. flock/themes/purplepeter.toml +1 -1
  254. flock/themes/raycast-dark.toml +1 -1
  255. flock/themes/red-sands.toml +1 -1
  256. flock/themes/relaxed.toml +1 -1
  257. flock/themes/retro.toml +1 -1
  258. flock/themes/rose-pine.toml +1 -1
  259. flock/themes/royal.toml +1 -1
  260. flock/themes/ryuuko.toml +1 -1
  261. flock/themes/sakura.toml +1 -1
  262. flock/themes/scarlet-protocol.toml +1 -1
  263. flock/themes/seoulbones-dark.toml +1 -1
  264. flock/themes/shades-of-purple.toml +1 -1
  265. flock/themes/smyck.toml +1 -1
  266. flock/themes/softserver.toml +1 -1
  267. flock/themes/solarized-darcula.toml +1 -1
  268. flock/themes/square.toml +1 -1
  269. flock/themes/sugarplum.toml +1 -1
  270. flock/themes/thayer-bright.toml +1 -1
  271. flock/themes/tokyonight.toml +1 -1
  272. flock/themes/tomorrow.toml +1 -1
  273. flock/themes/ubuntu.toml +1 -1
  274. flock/themes/ultradark.toml +1 -1
  275. flock/themes/ultraviolent.toml +1 -1
  276. flock/themes/unikitty.toml +1 -1
  277. flock/themes/urple.toml +1 -1
  278. flock/themes/vesper.toml +1 -1
  279. flock/themes/vimbones.toml +1 -1
  280. flock/themes/wildcherry.toml +1 -1
  281. flock/themes/wilmersdorf.toml +1 -1
  282. flock/themes/wryan.toml +1 -1
  283. flock/themes/xcodedarkhc.toml +1 -1
  284. flock/themes/xcodelight.toml +1 -1
  285. flock/themes/zenbones-light.toml +1 -1
  286. flock/themes/zenwritten-dark.toml +1 -1
  287. flock/utilities.py +301 -0
  288. flock/utility/output_utility_component.py +226 -0
  289. flock/visibility.py +107 -0
  290. flock_core-0.5.0.dist-info/METADATA +964 -0
  291. flock_core-0.5.0.dist-info/RECORD +525 -0
  292. flock_core-0.5.0.dist-info/entry_points.txt +2 -0
  293. {flock_core-0.4.542.dist-info → flock_core-0.5.0.dist-info}/licenses/LICENSE +1 -1
  294. flock/adapter/__init__.py +0 -14
  295. flock/adapter/azure_adapter.py +0 -68
  296. flock/adapter/chroma_adapter.py +0 -73
  297. flock/adapter/faiss_adapter.py +0 -97
  298. flock/adapter/pinecone_adapter.py +0 -51
  299. flock/adapter/vector_base.py +0 -47
  300. flock/cli/assets/release_notes.md +0 -140
  301. flock/cli/config.py +0 -8
  302. flock/cli/constants.py +0 -36
  303. flock/cli/create_agent.py +0 -1
  304. flock/cli/create_flock.py +0 -280
  305. flock/cli/execute_flock.py +0 -620
  306. flock/cli/load_agent.py +0 -1
  307. flock/cli/load_examples.py +0 -1
  308. flock/cli/load_flock.py +0 -192
  309. flock/cli/load_release_notes.py +0 -20
  310. flock/cli/loaded_flock_cli.py +0 -254
  311. flock/cli/manage_agents.py +0 -459
  312. flock/cli/registry_management.py +0 -889
  313. flock/cli/runner.py +0 -41
  314. flock/cli/settings.py +0 -857
  315. flock/cli/utils.py +0 -135
  316. flock/cli/view_results.py +0 -29
  317. flock/cli/yaml_editor.py +0 -396
  318. flock/config.py +0 -56
  319. flock/core/__init__.py +0 -44
  320. flock/core/api/__init__.py +0 -10
  321. flock/core/api/custom_endpoint.py +0 -45
  322. flock/core/api/endpoints.py +0 -262
  323. flock/core/api/main.py +0 -162
  324. flock/core/api/models.py +0 -101
  325. flock/core/api/run_store.py +0 -224
  326. flock/core/api/runner.py +0 -44
  327. flock/core/api/service.py +0 -214
  328. flock/core/config/flock_agent_config.py +0 -11
  329. flock/core/config/scheduled_agent_config.py +0 -40
  330. flock/core/context/context.py +0 -214
  331. flock/core/context/context_manager.py +0 -40
  332. flock/core/context/context_vars.py +0 -11
  333. flock/core/evaluation/utils.py +0 -395
  334. flock/core/execution/batch_executor.py +0 -369
  335. flock/core/execution/evaluation_executor.py +0 -438
  336. flock/core/execution/local_executor.py +0 -31
  337. flock/core/execution/opik_executor.py +0 -103
  338. flock/core/execution/temporal_executor.py +0 -166
  339. flock/core/flock.py +0 -1003
  340. flock/core/flock_agent.py +0 -1258
  341. flock/core/flock_evaluator.py +0 -60
  342. flock/core/flock_factory.py +0 -513
  343. flock/core/flock_module.py +0 -207
  344. flock/core/flock_registry.py +0 -702
  345. flock/core/flock_router.py +0 -83
  346. flock/core/flock_scheduler.py +0 -166
  347. flock/core/flock_server_manager.py +0 -136
  348. flock/core/interpreter/python_interpreter.py +0 -689
  349. flock/core/logging/live_capture.py +0 -137
  350. flock/core/logging/trace_and_logged.py +0 -59
  351. flock/core/mcp/__init__.py +0 -1
  352. flock/core/mcp/flock_mcp_server.py +0 -640
  353. flock/core/mcp/mcp_client_manager.py +0 -201
  354. flock/core/mcp/types/__init__.py +0 -1
  355. flock/core/mixin/dspy_integration.py +0 -445
  356. flock/core/mixin/prompt_parser.py +0 -125
  357. flock/core/serialization/__init__.py +0 -13
  358. flock/core/serialization/callable_registry.py +0 -52
  359. flock/core/serialization/flock_serializer.py +0 -854
  360. flock/core/serialization/json_encoder.py +0 -41
  361. flock/core/serialization/secure_serializer.py +0 -175
  362. flock/core/serialization/serializable.py +0 -342
  363. flock/core/serialization/serialization_utils.py +0 -409
  364. flock/core/util/file_path_utils.py +0 -223
  365. flock/core/util/hydrator.py +0 -309
  366. flock/core/util/input_resolver.py +0 -141
  367. flock/core/util/loader.py +0 -59
  368. flock/core/util/splitter.py +0 -219
  369. flock/di.py +0 -41
  370. flock/evaluators/__init__.py +0 -1
  371. flock/evaluators/declarative/__init__.py +0 -1
  372. flock/evaluators/declarative/declarative_evaluator.py +0 -217
  373. flock/evaluators/memory/memory_evaluator.py +0 -90
  374. flock/evaluators/test/test_case_evaluator.py +0 -38
  375. flock/evaluators/zep/zep_evaluator.py +0 -59
  376. flock/modules/__init__.py +0 -1
  377. flock/modules/assertion/__init__.py +0 -1
  378. flock/modules/assertion/assertion_module.py +0 -286
  379. flock/modules/callback/__init__.py +0 -1
  380. flock/modules/callback/callback_module.py +0 -91
  381. flock/modules/enterprise_memory/README.md +0 -99
  382. flock/modules/enterprise_memory/enterprise_memory_module.py +0 -526
  383. flock/modules/mem0/__init__.py +0 -1
  384. flock/modules/mem0/mem0_module.py +0 -126
  385. flock/modules/mem0_async/__init__.py +0 -1
  386. flock/modules/mem0_async/async_mem0_module.py +0 -126
  387. flock/modules/memory/__init__.py +0 -1
  388. flock/modules/memory/memory_module.py +0 -429
  389. flock/modules/memory/memory_parser.py +0 -125
  390. flock/modules/memory/memory_storage.py +0 -736
  391. flock/modules/output/__init__.py +0 -1
  392. flock/modules/output/output_module.py +0 -196
  393. flock/modules/performance/__init__.py +0 -1
  394. flock/modules/performance/metrics_module.py +0 -678
  395. flock/modules/zep/__init__.py +0 -1
  396. flock/modules/zep/zep_module.py +0 -192
  397. flock/platform/docker_tools.py +0 -49
  398. flock/platform/jaeger_install.py +0 -86
  399. flock/routers/__init__.py +0 -1
  400. flock/routers/agent/__init__.py +0 -1
  401. flock/routers/agent/agent_router.py +0 -236
  402. flock/routers/agent/handoff_agent.py +0 -58
  403. flock/routers/conditional/conditional_router.py +0 -486
  404. flock/routers/default/__init__.py +0 -1
  405. flock/routers/default/default_router.py +0 -80
  406. flock/routers/feedback/feedback_router.py +0 -114
  407. flock/routers/list_generator/list_generator_router.py +0 -166
  408. flock/routers/llm/__init__.py +0 -1
  409. flock/routers/llm/llm_router.py +0 -365
  410. flock/tools/__init__.py +0 -0
  411. flock/tools/azure_tools.py +0 -781
  412. flock/tools/code_tools.py +0 -167
  413. flock/tools/file_tools.py +0 -149
  414. flock/tools/github_tools.py +0 -157
  415. flock/tools/markdown_tools.py +0 -205
  416. flock/tools/system_tools.py +0 -9
  417. flock/tools/text_tools.py +0 -810
  418. flock/tools/web_tools.py +0 -92
  419. flock/tools/zendesk_tools.py +0 -501
  420. flock/webapp/__init__.py +0 -1
  421. flock/webapp/app/__init__.py +0 -0
  422. flock/webapp/app/api/__init__.py +0 -0
  423. flock/webapp/app/api/agent_management.py +0 -237
  424. flock/webapp/app/api/execution.py +0 -503
  425. flock/webapp/app/api/flock_management.py +0 -125
  426. flock/webapp/app/api/registry_viewer.py +0 -29
  427. flock/webapp/app/chat.py +0 -662
  428. flock/webapp/app/config.py +0 -104
  429. flock/webapp/app/dependencies.py +0 -117
  430. flock/webapp/app/main.py +0 -1086
  431. flock/webapp/app/middleware.py +0 -113
  432. flock/webapp/app/models_ui.py +0 -7
  433. flock/webapp/app/services/__init__.py +0 -0
  434. flock/webapp/app/services/feedback_file_service.py +0 -363
  435. flock/webapp/app/services/flock_service.py +0 -345
  436. flock/webapp/app/services/sharing_models.py +0 -81
  437. flock/webapp/app/services/sharing_store.py +0 -597
  438. flock/webapp/app/templates/theme_mapper.html +0 -326
  439. flock/webapp/app/theme_mapper.py +0 -811
  440. flock/webapp/app/utils.py +0 -85
  441. flock/webapp/run.py +0 -219
  442. flock/webapp/static/css/chat.css +0 -301
  443. flock/webapp/static/css/components.css +0 -167
  444. flock/webapp/static/css/header.css +0 -39
  445. flock/webapp/static/css/layout.css +0 -281
  446. flock/webapp/static/css/sidebar.css +0 -127
  447. flock/webapp/static/css/two-pane.css +0 -48
  448. flock/webapp/templates/base.html +0 -389
  449. flock/webapp/templates/chat.html +0 -152
  450. flock/webapp/templates/chat_settings.html +0 -19
  451. flock/webapp/templates/flock_editor.html +0 -16
  452. flock/webapp/templates/index.html +0 -12
  453. flock/webapp/templates/partials/_agent_detail_form.html +0 -93
  454. flock/webapp/templates/partials/_agent_list.html +0 -18
  455. flock/webapp/templates/partials/_agent_manager_view.html +0 -51
  456. flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
  457. flock/webapp/templates/partials/_chat_container.html +0 -15
  458. flock/webapp/templates/partials/_chat_messages.html +0 -57
  459. flock/webapp/templates/partials/_chat_settings_form.html +0 -85
  460. flock/webapp/templates/partials/_create_flock_form.html +0 -50
  461. flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
  462. flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
  463. flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
  464. flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
  465. flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
  466. flock/webapp/templates/partials/_env_vars_table.html +0 -23
  467. flock/webapp/templates/partials/_execution_form.html +0 -127
  468. flock/webapp/templates/partials/_execution_view_container.html +0 -28
  469. flock/webapp/templates/partials/_flock_file_list.html +0 -23
  470. flock/webapp/templates/partials/_flock_properties_form.html +0 -52
  471. flock/webapp/templates/partials/_flock_upload_form.html +0 -16
  472. flock/webapp/templates/partials/_header_flock_status.html +0 -5
  473. flock/webapp/templates/partials/_live_logs.html +0 -13
  474. flock/webapp/templates/partials/_load_manager_view.html +0 -49
  475. flock/webapp/templates/partials/_registry_table.html +0 -25
  476. flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
  477. flock/webapp/templates/partials/_results_display.html +0 -78
  478. flock/webapp/templates/partials/_settings_env_content.html +0 -9
  479. flock/webapp/templates/partials/_settings_theme_content.html +0 -14
  480. flock/webapp/templates/partials/_settings_view.html +0 -36
  481. flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
  482. flock/webapp/templates/partials/_share_link_snippet.html +0 -35
  483. flock/webapp/templates/partials/_sidebar.html +0 -74
  484. flock/webapp/templates/partials/_structured_data_view.html +0 -40
  485. flock/webapp/templates/partials/_theme_preview.html +0 -36
  486. flock/webapp/templates/registry_viewer.html +0 -84
  487. flock/webapp/templates/shared_run_page.html +0 -140
  488. flock/workflow/__init__.py +0 -0
  489. flock/workflow/activities.py +0 -237
  490. flock/workflow/agent_activities.py +0 -24
  491. flock/workflow/agent_execution_activity.py +0 -240
  492. flock/workflow/flock_workflow.py +0 -225
  493. flock/workflow/temporal_config.py +0 -96
  494. flock/workflow/temporal_setup.py +0 -60
  495. flock_core-0.4.542.dist-info/METADATA +0 -676
  496. flock_core-0.4.542.dist-info/RECORD +0 -572
  497. flock_core-0.4.542.dist-info/entry_points.txt +0 -2
  498. /flock/{core/logging → logging}/formatters/themes.py +0 -0
  499. /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
  500. /flock/{core/mcp → mcp}/util/__init__.py +0 -0
  501. {flock_core-0.4.542.dist-info → flock_core-0.5.0.dist-info}/WHEEL +0 -0
@@ -1,640 +0,0 @@
1
- """FlockMCPServer is the core, declarative base class for all types of MCP-Servers in the Flock framework."""
2
-
3
- import asyncio
4
- import importlib
5
- import inspect
6
- import os
7
- from abc import ABC, abstractmethod
8
- from typing import Any, Literal, TypeVar
9
-
10
- from dspy import Tool as DSPyTool
11
- from opentelemetry import trace
12
- from pydantic import (
13
- BaseModel,
14
- ConfigDict,
15
- Field,
16
- )
17
-
18
- from flock.core.flock_module import FlockModule
19
- from flock.core.logging.logging import get_logger
20
- from flock.core.mcp.flock_mcp_tool_base import FlockMCPToolBase
21
- from flock.core.mcp.mcp_client_manager import FlockMCPClientManagerBase
22
- from flock.core.mcp.mcp_config import FlockMCPConfigurationBase
23
- from flock.core.serialization.serializable import Serializable
24
- from flock.core.serialization.serialization_utils import (
25
- deserialize_component,
26
- serialize_item,
27
- )
28
-
29
- logger = get_logger("mcp.server")
30
- tracer = trace.get_tracer(__name__)
31
- T = TypeVar("T", bound="FlockMCPServerBase")
32
-
33
- LoggingLevel = Literal[
34
- "debug",
35
- "info",
36
- "notice",
37
- "warning",
38
- "error",
39
- "critical",
40
- "alert",
41
- "emergency",
42
- ]
43
-
44
-
45
- class FlockMCPServerBase(BaseModel, Serializable, ABC):
46
- """Base class for all Flock MCP Server Types.
47
-
48
- Servers serve as an abstraction-layer between the underlying MCPClientSession
49
- which is the actual connection between Flock and a (remote) MCP-Server.
50
-
51
- Servers hook into the lifecycle of their assigned agents and take care
52
- of establishing sessions, getting and converting tools and other functions
53
- without agents having to worry about the details.
54
-
55
- Tools (if provided) will be injected into the list of tools of any attached
56
- agent automatically.
57
-
58
- Servers provide lifecycle-hooks (`initialize`, `get_tools`, `get_prompts`, `list_resources`, `get_resource_contents`, `set_roots`, etc)
59
- which allow modules to hook into them. This can be used to modify data or
60
- pass headers from authentication-flows to a server.
61
-
62
- Each Server should define its configuration requirements either by:
63
- 1. Creating a subclass of FlockMCPServerConfig
64
- 2. Using FlockMCPServerConfig.with_fields() to create a config class.
65
- """
66
-
67
- config: FlockMCPConfigurationBase = Field(
68
- ..., description="Config for clients connecting to the server."
69
- )
70
-
71
- initialized: bool = Field(
72
- default=False,
73
- exclude=True,
74
- description="Whether or not this Server has already initialized.",
75
- )
76
-
77
- modules: dict[str, FlockModule] = Field(
78
- default={},
79
- description="Dictionary of FlockModules attached to this Server.",
80
- )
81
-
82
- # --- Underlying ConnectionManager ---
83
- # (Manages a pool of ClientConnections and does the actual talking to the MCP Server)
84
- # (Excluded from Serialization)
85
- client_manager: FlockMCPClientManagerBase | None = Field(
86
- default=None,
87
- exclude=True,
88
- description="Underlying Connection Manager. Handles the actual underlying connections to the server.",
89
- )
90
-
91
- condition: asyncio.Condition = Field(
92
- default_factory=asyncio.Condition,
93
- exclude=True,
94
- description="Condition for asynchronous operations.",
95
- )
96
-
97
- model_config = ConfigDict(
98
- arbitrary_types_allowed=True,
99
- )
100
-
101
- def add_module(self, module: FlockModule) -> None:
102
- """Add a module to this server."""
103
- if not module.name:
104
- logger.error("Module must have a name to be added.")
105
- return
106
- if self.modules and module.name in self.modules:
107
- logger.warning(f"Overwriting existing module: {module.name}")
108
-
109
- self.modules[module.name] = module
110
- logger.debug(
111
- f"Added module '{module.name}' to server {self.config.name}"
112
- )
113
- return
114
-
115
- def remove_module(self, module_name: str) -> None:
116
- """Remove a module from this server."""
117
- if module_name in self.modules:
118
- del self.modules[module_name]
119
- logger.debug(
120
- f"Removed module '{module_name}' from server '{self.config.name}'"
121
- )
122
- else:
123
- logger.warning(
124
- f"Module '{module_name}' not found on server '{self.config.name}'"
125
- )
126
- return
127
-
128
- def get_module(self, module_name: str) -> FlockModule | None:
129
- """Get a module by name."""
130
- return self.modules.get(module_name)
131
-
132
- def get_enabled_modules(self) -> list[FlockModule]:
133
- """Get a list of currently enabled modules attached to this server."""
134
- return [m for m in self.modules.values() if m.config.enabled]
135
-
136
- @abstractmethod
137
- async def initialize(self) -> FlockMCPClientManagerBase:
138
- """Called when initializing the server."""
139
- pass
140
-
141
- async def call_tool(
142
- self, agent_id: str, run_id: str, name: str, arguments: dict[str, Any]
143
- ) -> Any:
144
- """Call a tool via the MCP Protocol on the client's server."""
145
- with tracer.start_as_current_span("server.call_tool") as span:
146
- span.set_attribute("agent_id", agent_id)
147
- span.set_attribute("run_id", run_id)
148
- span.set_attribute("tool.name", name)
149
- span.set_attribute("arguments", str(arguments))
150
- if not self.initialized or not self.client_manager:
151
- async with self.condition:
152
- await self.pre_init()
153
- self.client_manager = await self.initialize()
154
- self.initialized = True
155
- await self.post_init()
156
- async with self.condition:
157
- try:
158
- additional_params: dict[str, Any] = {
159
- "refresh_client": False,
160
- "override_headers": False,
161
- } # initialize the additional params as an empty dict.
162
-
163
- await self.before_connect(
164
- additional_params=additional_params
165
- )
166
- pre_call_args = {
167
- "agent_id": agent_id,
168
- "run_id": run_id,
169
- "tool_name": name,
170
- "arguments": arguments,
171
- }
172
- pre_call_args.update(additional_params)
173
- await self.pre_mcp_call(pre_call_args)
174
- result = await self.client_manager.call_tool(
175
- agent_id=agent_id,
176
- run_id=run_id,
177
- name=name,
178
- arguments=arguments,
179
- additional_params=additional_params,
180
- )
181
- # re-set addtional-params, just to be sure.
182
- await self.post_mcp_call(result=result)
183
- return result
184
- except Exception as mcp_error:
185
- logger.error(
186
- "Error during server.call_tool",
187
- server=self.config.name,
188
- error=str(mcp_error),
189
- )
190
- span.record_exception(mcp_error)
191
- return None
192
-
193
- async def get_tools(self, agent_id: str, run_id: str) -> list[DSPyTool]:
194
- """Retrieves a list of available tools from this server."""
195
- with tracer.start_as_current_span("server.get_tools") as span:
196
- span.set_attribute("server.name", self.config.name)
197
- span.set_attribute("agent_id", agent_id)
198
- span.set_attribute("run_id", run_id)
199
- if not self.initialized or not self.client_manager:
200
- async with self.condition:
201
- await self.pre_init()
202
- self.client_manager = await self.initialize()
203
- self.initialized = True
204
- await self.post_init()
205
-
206
- async with self.condition:
207
- try:
208
- await self.pre_mcp_call()
209
- additional_params: dict[str, Any] = {}
210
- additional_params = await self.before_connect(
211
- additional_params=additional_params
212
- )
213
- result: list[
214
- FlockMCPToolBase
215
- ] = await self.client_manager.get_tools(
216
- agent_id=agent_id,
217
- run_id=run_id,
218
- additional_params=additional_params,
219
- )
220
- converted_tools = [
221
- t.as_dspy_tool(server=self) for t in result
222
- ]
223
- await self.post_mcp_call(result=converted_tools)
224
- return converted_tools
225
- except Exception as e:
226
- logger.error(
227
- f"Unexpected Exception ocurred while trying to get tools from server '{self.config.name}': {e}"
228
- )
229
- await self.on_error(error=e)
230
- span.record_exception(e)
231
- return []
232
- finally:
233
- self.condition.notify()
234
-
235
- async def before_connect(
236
- self, additional_params: dict[str, Any]
237
- ) -> dict[str, Any]:
238
- """Run before_connect hooks on modules."""
239
- logger.debug(
240
- f"Running before_connect hooks for modules in server '{self.config.name}'."
241
- )
242
- with tracer.start_as_current_span("server.before_connect") as span:
243
- span.set_attribute("server.name", self.config.name)
244
- try:
245
- if not additional_params:
246
- additional_params = {}
247
- for module in self.get_enabled_modules():
248
- additional_params = await module.on_connect(
249
- server=self, additional_params=additional_params
250
- )
251
- except Exception as module_error:
252
- logger.error(
253
- "Error during before_connect",
254
- server=self.config.name,
255
- error=str(module_error),
256
- )
257
- span.record_exception(module_error)
258
-
259
- async def pre_init(self) -> None:
260
- """Run pre-init hooks on modules."""
261
- logger.debug(
262
- f"Running pre-init hooks for modules in server '{self.config.name}'"
263
- )
264
- with tracer.start_as_current_span("server.pre_init") as span:
265
- span.set_attribute("server.name", self.config.name)
266
- try:
267
- for module in self.get_enabled_modules():
268
- await module.on_pre_server_init(self)
269
- except Exception as module_error:
270
- logger.error(
271
- "Error during pre_init",
272
- server=self.config.name,
273
- error=str(module_error),
274
- )
275
- span.record_exception(module_error)
276
-
277
- async def post_init(self) -> None:
278
- """Run post-init hooks on modules."""
279
- logger.debug(
280
- f"Running post_init hooks for modules in server '{self.config.name}'"
281
- )
282
- with tracer.start_as_current_span("server.post_init") as span:
283
- span.set_attribute("server.name", self.config.name)
284
- try:
285
- for module in self.get_enabled_modules():
286
- await module.on_post_server_init(self)
287
- except Exception as module_error:
288
- logger.error(
289
- "Error during post_init",
290
- server=self.config.name,
291
- error=str(module_error),
292
- )
293
- span.record_exception(module_error)
294
-
295
- async def pre_terminate(self) -> None:
296
- """Run pre-terminate hooks on modules."""
297
- logger.debug(
298
- f"Running post_init hooks for modules in server: '{self.config.name}'"
299
- )
300
- with tracer.start_as_current_span("server.pre_terminate") as span:
301
- span.set_attribute("server.name", self.config.name)
302
- try:
303
- for module in self.get_enabled_modules():
304
- await module.on_pre_server_terminate(self)
305
- except Exception as module_error:
306
- logger.error(
307
- "Error during pre_terminate",
308
- server=self.config.name,
309
- error=str(module_error),
310
- )
311
- span.record_exception(module_error)
312
-
313
- async def post_terminate(self) -> None:
314
- """Run post-terminate hooks on modules."""
315
- logger.debug(
316
- f"Running post_terminate hooks for modules in server: '{self.config.name}'"
317
- )
318
- with tracer.start_as_current_span("server.post_terminate") as span:
319
- span.set_attribute("server.name", self.config.name)
320
- try:
321
- for module in self.get_enabled_modules():
322
- await module.on_post_server_terminate(server=self)
323
- except Exception as module_error:
324
- logger.error(
325
- "Error during post_terminate",
326
- server=self.config.name,
327
- error=str(module_error),
328
- )
329
- span.record_exception(module_error)
330
-
331
- async def on_error(self, error: Exception) -> None:
332
- """Run on_error hooks on modules."""
333
- logger.debug(
334
- f"Running on_error hooks for modules in server '{self.config.name}'"
335
- )
336
- with tracer.start_as_current_span("server.on_error") as span:
337
- span.set_attribute("server.name", self.config.name)
338
- try:
339
- for module in self.get_enabled_modules():
340
- await module.on_server_error(server=self, error=error)
341
- except Exception as module_error:
342
- logger.error(
343
- "Error during on_error",
344
- server=self.config.name,
345
- error=str(module_error),
346
- )
347
- span.record_exception(module_error)
348
-
349
- async def pre_mcp_call(self, arguments: Any | None = None) -> None:
350
- """Run pre_mcp_call-hooks on modules."""
351
- logger.debug(
352
- f"Running pre_mcp_call hooks for modules in server '{self.config.name}'"
353
- )
354
- with tracer.start_as_current_span("server.pre_mcp_call") as span:
355
- span.set_attribute("server.name", self.config.name)
356
- try:
357
- for module in self.get_enabled_modules():
358
- await module.on_pre_mcp_call(
359
- server=self, arguments=arguments
360
- )
361
- except Exception as module_error:
362
- logger.error(
363
- f"Error during pre_mcp_call: {module_error}",
364
- server=self.config.name,
365
- error=str(module_error),
366
- )
367
- span.record_exception(module_error)
368
-
369
- async def post_mcp_call(self, result: Any) -> None:
370
- """Run Post MCP_call hooks on modules."""
371
- logger.debug(
372
- f"Running post_mcp_call hooks for modules in server '{self.config.name}'"
373
- )
374
- with tracer.start_as_current_span("server.post_mcp_call") as span:
375
- span.set_attribute("server.name", self.config.name)
376
- try:
377
- for module in self.get_enabled_modules():
378
- await module.on_post_mcp_call(server=self, result=result)
379
- except Exception as module_error:
380
- logger.error(
381
- "Error during post_mcp_call",
382
- server=self.config.name,
383
- error=str(module_error),
384
- )
385
- span.record_exception(module_error)
386
-
387
- # --- Async Methods ---
388
- async def __aenter__(self) -> "FlockMCPServerBase":
389
- """Enter the asynchronous context for the server."""
390
- # Spin up the client-manager
391
- with tracer.start_as_current_span("server.__aenter__") as span:
392
- span.set_attribute("server.name", self.config.name)
393
- logger.info(f"server.__aenter__", server=self.config.name)
394
- try:
395
- await self.pre_init()
396
- self.client_manager = await self.initialize()
397
- await self.post_init()
398
- self.initialized = True
399
- except Exception as server_error:
400
- logger.error(
401
- f"Error during __aenter__ for server '{self.config.name}'",
402
- server=self.config.name,
403
- error=server_error,
404
- )
405
- span.record_exception(server_error)
406
-
407
- async def __aexit__(self, exc_type, exc, tb) -> None:
408
- """Exit the asynchronous context for the server."""
409
- # tell the underlying client-manager to terminate connections
410
- # and unwind the clients.
411
- with tracer.start_as_current_span("server.__aexit__") as span:
412
- span.set_attribute("server.name", self.config.name)
413
- try:
414
- await self.pre_terminate()
415
- if self.initialized and self.client_manager:
416
- # means we ran through the initialize()-method
417
- # and the client manager is present
418
- await self.client_manager.close_all()
419
- self.client_manager = None
420
- self.initialized = False
421
- await self.post_terminate()
422
- return
423
- except Exception as server_error:
424
- logger.error(
425
- f"Error during __aexit__ for server '{self.config.name}'",
426
- server=self.config.name,
427
- error=server_error,
428
- )
429
- await self.on_error(error=server_error)
430
- span.record_exception(server_error)
431
-
432
- # --- Serialization Implementation ---
433
- def to_dict(self, path_type: str = "relative") -> dict[str, Any]:
434
- """Convert instance to dictionary representation suitable for serialization."""
435
- from flock.core.flock_registry import get_registry
436
-
437
- FlockRegistry = get_registry()
438
-
439
- exclude = ["modules", "config"]
440
-
441
- logger.debug(f"Serializing server '{self.config.name}' to dict.")
442
- # Use Pydantic's dump, exclued manually handled fields.
443
- data = self.model_dump(
444
- exclude=exclude,
445
- mode="json", # Use json mode for better handling of standard types by Pydantic
446
- exclude_none=True, # Exclude None values for cleaner output
447
- )
448
-
449
- # --- Let the config handle its own serialization ---
450
- config_data = self.config.to_dict(path_type=path_type)
451
- data["config"] = config_data
452
-
453
-
454
- builtin_by_transport = {}
455
-
456
- try:
457
- from flock.mcp.servers.sse.flock_sse_server import FlockSSEServer
458
- from flock.mcp.servers.stdio.flock_stdio_server import (
459
- FlockMCPStdioServer,
460
- )
461
- from flock.mcp.servers.streamable_http.flock_streamable_http_server import (
462
- FlockStreamableHttpServer,
463
- )
464
- from flock.mcp.servers.websockets.flock_websocket_server import (
465
- FlockWSServer,
466
- )
467
-
468
- builtin_by_transport = {
469
- "stdio": FlockMCPStdioServer,
470
- "streamable_http": FlockStreamableHttpServer,
471
- "sse": FlockSSEServer,
472
- "websockets": FlockWSServer,
473
- }
474
- except ImportError:
475
- builtin_by_transport = {}
476
-
477
- # --- Only emit full impl for non-builtins ---
478
- transport = getattr(
479
- self.config.connection_config, "transport_type", None
480
- )
481
- builtin_cls = builtin_by_transport.get(transport)
482
-
483
- if type(self) is not builtin_cls:
484
- file_path = inspect.getsourcefile(type(self))
485
- if path_type == "relative":
486
- file_path = os.path.relpath(file_path)
487
- data["implementation"] = {
488
- "class_name": type(self).__name__,
489
- "module_path": type(self).__module__,
490
- "file_path": file_path,
491
- }
492
-
493
- logger.debug(
494
- f"Base server data for '{self.config.name}': {list(data.keys())}"
495
- )
496
- serialized_modules = {}
497
-
498
- def add_serialized_component(component: Any, field_name: str):
499
- if component:
500
- comp_type = type(component)
501
- type_name = FlockRegistry.get_component_type_name(
502
- comp_type
503
- ) # Get registered name
504
-
505
- if type_name:
506
- try:
507
- serialized_component_data = serialize_item(component)
508
-
509
- if not isinstance(serialized_component_data, dict):
510
- logger.error(
511
- f"Serialization of component {type_name} for field '{field_name}' did not result in a dictionary. Got: {type(serialized_component_data)}"
512
- )
513
- serialized_modules[field_name] = {
514
- "type": type_name,
515
- "name": getattr(component, "name", "unknown"),
516
- "error": "serialization_failed_non_dict",
517
- }
518
- else:
519
- serialized_component_data["type"] = type_name
520
- serialized_modules[field_name] = (
521
- serialized_component_data
522
- )
523
- logger.debug(
524
- f"Successfully serialized component for field '{field_name}' (type: {type_name})"
525
- )
526
- except Exception as e:
527
- logger.error(
528
- f"Failed to serialize component {type_name} for field '{field_name}': {e}",
529
- exc_info=True,
530
- )
531
-
532
- else:
533
- logger.warning(
534
- f"Cannot serialize unregistered component {comp_type.__name__} for field '{field_name}'"
535
- )
536
-
537
- serialized_modules = {}
538
- for module in self.modules.values():
539
- add_serialized_component(module, module.name)
540
-
541
- if serialized_modules:
542
- data["modules"] = serialized_modules
543
- logger.debug(
544
- f"Added {len(serialized_modules)} modules to server '{self.config.name}'"
545
- )
546
-
547
- def _clean(obj: Any) -> Any:
548
- if isinstance(obj, dict):
549
- return {
550
- k: _clean(v)
551
- for k, v in obj.items()
552
- if v is not None
553
- and not (isinstance(v, list | dict) and len(v) == 0)
554
- }
555
- if isinstance(obj, list):
556
- return [
557
- _clean(v)
558
- for v in obj
559
- if v is not None
560
- and not (isinstance(v, dict | list) and len(v) == 0)
561
- ]
562
- return obj
563
-
564
- data = _clean(data)
565
- return data
566
-
567
- @classmethod
568
- def from_dict(cls: type[T], data: dict[str, Any]) -> T:
569
- """Deserialize the server from a dictionary, including components."""
570
- logger.debug(
571
- f"Deserializing server from dict. Keys: {list(data.keys())}"
572
- )
573
-
574
- builtin_by_transport = {}
575
-
576
- try:
577
- from flock.mcp.servers.sse.flock_sse_server import FlockSSEServer
578
- from flock.mcp.servers.stdio.flock_stdio_server import (
579
- FlockMCPStdioServer,
580
- )
581
- from flock.mcp.servers.streamable_http.flock_streamable_http_server import (
582
- FlockStreamableHttpServer,
583
- )
584
- from flock.mcp.servers.websockets.flock_websocket_server import (
585
- FlockWSServer,
586
- )
587
-
588
- builtin_by_transport = {
589
- "stdio": FlockMCPStdioServer,
590
- "sse": FlockSSEServer,
591
- "streamable_http": FlockStreamableHttpServer,
592
- "websockets": FlockWSServer,
593
- }
594
- except ImportError:
595
- builtin_by_transport = {}
596
-
597
- # find custom impl or built-in
598
- impl = data.pop("implementation", None)
599
- if impl:
600
- mod = importlib.import_module(impl["module_path"])
601
- real_cls = getattr(mod, impl["class_name"])
602
- else:
603
- # built-in: inspect transport_type in data["config"]
604
- transport = data["config"]["connection_config"]["transport_type"]
605
- real_cls = builtin_by_transport.get(transport, cls)
606
-
607
- # deserialize the config:
608
- config_data = data.pop("config", None)
609
- if config_data:
610
- # Forcing a square into a round hole
611
- # pretty ugly, but gets the job done.
612
- try:
613
- config_field = real_cls.model_fields["config"]
614
- config_cls = config_field.annotation
615
- except (AttributeError, KeyError):
616
- # fallback if Pydantic v1 or missing
617
- config_cls = FlockMCPConfigurationBase
618
- config_object = config_cls.from_dict(config_data)
619
- data["config"] = config_object
620
-
621
- # now construct
622
- server = real_cls(**{k: v for k, v in data.items() if k != "modules"})
623
-
624
- # re-hydrate modules
625
- for mname, mdata in data.get("modules", {}).items():
626
- server.add_module(deserialize_component(mdata, FlockModule))
627
-
628
- # --- Separate Data ---
629
- component_configs = {}
630
- server_data = {}
631
- component_keys = ["modules"]
632
-
633
- for key, value in data.items():
634
- if key in component_keys and value is not None:
635
- component_configs[key] = value
636
- else:
637
- server_data[key] = value
638
-
639
- logger.info(f"Successfully deserialized server '{server.config.name}'")
640
- return server