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,678 +0,0 @@
1
- """Performance and metrics tracking for Flock agents."""
2
-
3
- import json
4
- import os
5
- import time
6
- from collections import defaultdict
7
- from datetime import datetime
8
- from typing import Any, Literal
9
-
10
- import numpy as np
11
- import psutil
12
- from pydantic import BaseModel, Field, validator
13
-
14
- from flock.core.context.context import FlockContext
15
- from flock.core.flock_agent import FlockAgent
16
- from flock.core.flock_module import FlockModule, FlockModuleConfig
17
- from flock.core.flock_registry import flock_component
18
- from flock.core.mcp.flock_mcp_server import FlockMCPServerBase
19
-
20
-
21
- class MetricPoint(BaseModel):
22
- """Single metric measurement."""
23
-
24
- timestamp: datetime
25
- value: int | float | str
26
- tags: dict[str, str] = {}
27
-
28
- class Config:
29
- arbitrary_types_allowed = True
30
-
31
-
32
- class MetricsModuleConfig(FlockModuleConfig):
33
- """Configuration for performance metrics collection."""
34
-
35
- # Collection settings
36
- collect_timing: bool = Field(
37
- default=True, description="Collect timing metrics"
38
- )
39
- collect_memory: bool = Field(
40
- default=True, description="Collect memory usage"
41
- )
42
- collect_token_usage: bool = Field(
43
- default=True, description="Collect token usage stats"
44
- )
45
- collect_cpu: bool = Field(default=True, description="Collect CPU usage")
46
-
47
- # Storage settings
48
- storage_type: Literal["json", "prometheus", "memory"] = Field(
49
- default="json", description="Where to store metrics"
50
- )
51
- metrics_dir: str = Field(
52
- default=".flock/metrics/", description="Directory for metrics storage"
53
- )
54
-
55
- # Aggregation settings
56
- aggregation_interval: str = Field(
57
- default="1h", description="Interval for metric aggregation"
58
- )
59
- retention_days: int = Field(default=30, description="Days to keep metrics")
60
-
61
- # Alerting settings
62
- alert_on_high_latency: bool = Field(
63
- default=True, description="Alert on high latency"
64
- )
65
- latency_threshold_ms: int = Field(
66
- default=1000, description="Threshold for latency alerts"
67
- )
68
-
69
- @validator("aggregation_interval")
70
- def validate_interval(cls, v):
71
- """Validate time interval format."""
72
- if v[-1] not in ["s", "m", "h", "d"]:
73
- raise ValueError("Interval must end with s, m, h, or d")
74
- return v
75
-
76
-
77
- @flock_component(config_class=MetricsModuleConfig)
78
- class MetricsModule(FlockModule):
79
- """Module for collecting and analyzing agent performance metrics."""
80
-
81
- # --- Singleton holder for convenient static access ---
82
- _INSTANCE: "MetricsModule | None" = None
83
-
84
- name: str = "performance_metrics"
85
- config: MetricsModuleConfig = Field(
86
- default_factory=MetricsModuleConfig,
87
- description="Performance metrics configuration",
88
- )
89
-
90
- def __init__(self, name, config):
91
- super().__init__(name=name, config=config)
92
- # Register singleton for static helpers
93
- MetricsModule._INSTANCE = self
94
- self._metrics = defaultdict(list)
95
- self._start_time: float | None = None
96
- self._server_start_time: float | None = None
97
- self._start_memory: int | None = None
98
- self._server_start_memory: int | None = None
99
- self._client_refreshs: int = 0
100
-
101
- # Set up storage
102
- if self.config.storage_type == "json":
103
- os.makedirs(self.config.metrics_dir, exist_ok=True)
104
-
105
- # Set up prometheus if needed
106
- if self.config.storage_type == "prometheus":
107
- try:
108
- from prometheus_client import Counter, Gauge, Histogram
109
-
110
- self._prom_latency = Histogram(
111
- "flock_agent_latency_seconds",
112
- "Time taken for agent evaluation",
113
- ["agent_name"],
114
- )
115
- self._prom_memory = Gauge(
116
- "flock_agent_memory_bytes",
117
- "Memory usage by agent",
118
- ["agent_name"],
119
- )
120
- self._prom_tokens = Counter(
121
- "flock_agent_tokens_total",
122
- "Token usage by agent",
123
- ["agent_name", "type"],
124
- )
125
- self._prom_errors = Counter(
126
- "flock_agent_errors_total",
127
- "Error count by agent",
128
- ["agent_name", "error_type"],
129
- )
130
- except ImportError:
131
- self.config.storage_type = "json"
132
-
133
- """Fixes for metrics summary calculation."""
134
-
135
- def _load_metrics_from_files(
136
- self, metric_name: str = None
137
- ) -> dict[str, list[MetricPoint]]:
138
- """Load metrics from JSON files."""
139
- metrics = defaultdict(list)
140
-
141
- try:
142
- # Get all metric files
143
- files = [
144
- f
145
- for f in os.listdir(self.config.metrics_dir)
146
- if f.endswith(".json") and not f.startswith("summary_")
147
- ]
148
-
149
- # Filter by metric name if specified
150
- if metric_name:
151
- files = [f for f in files if f.startswith(f"{metric_name}_")]
152
-
153
- for filename in files:
154
- filepath = os.path.join(self.config.metrics_dir, filename)
155
- with open(filepath) as f:
156
- for line in f:
157
- try:
158
- data = json.loads(line)
159
- point = MetricPoint(
160
- timestamp=datetime.fromisoformat(
161
- data["timestamp"]
162
- ),
163
- value=data["value"],
164
- tags=data["tags"],
165
- )
166
- name = filename.split("_")[
167
- 0
168
- ] # Get metric name from filename
169
- metrics[name].append(point)
170
- except json.JSONDecodeError:
171
- continue
172
-
173
- return dict(metrics)
174
- except Exception as e:
175
- print(f"Error loading metrics from files: {e}")
176
- return {}
177
-
178
- def get_metrics(
179
- self,
180
- metric_name: str | None = None,
181
- start_time: datetime | None = None,
182
- end_time: datetime | None = None,
183
- ) -> dict[str, list[MetricPoint]]:
184
- """Get recorded metrics with optional filtering."""
185
- # Get metrics from appropriate source
186
- if self.config.storage_type == "json":
187
- metrics = self._load_metrics_from_files(metric_name)
188
- else:
189
- metrics = self._metrics
190
- if metric_name:
191
- metrics = {metric_name: metrics[metric_name]}
192
-
193
- # Apply time filtering if needed
194
- if start_time or end_time:
195
- filtered_metrics = defaultdict(list)
196
- for name, points in metrics.items():
197
- filtered_points = [
198
- p
199
- for p in points
200
- if (not start_time or p.timestamp >= start_time)
201
- and (not end_time or p.timestamp <= end_time)
202
- ]
203
- filtered_metrics[name] = filtered_points
204
- metrics = filtered_metrics
205
-
206
- return dict(metrics)
207
-
208
- def get_statistics(
209
- self, metric_name: str, percentiles: list[float] = [50, 90, 95, 99]
210
- ) -> dict[str, float]:
211
- """Calculate statistics for a metric."""
212
- # Get all points for this metric
213
- metrics = self.get_metrics(metric_name=metric_name)
214
- points = metrics.get(metric_name, [])
215
-
216
- if not points:
217
- return {}
218
-
219
- values = [p.value for p in points if isinstance(p.value, (int, float))]
220
- if not values:
221
- return {}
222
-
223
- stats = {
224
- "min": min(values),
225
- "max": max(values),
226
- "mean": float(
227
- np.mean(values)
228
- ), # Convert to float for JSON serialization
229
- "std": float(np.std(values)),
230
- "count": len(values),
231
- "last_value": values[-1],
232
- }
233
-
234
- for p in percentiles:
235
- stats[f"p{p}"] = float(np.percentile(values, p))
236
-
237
- return stats
238
-
239
- async def on_terminate(
240
- self,
241
- agent: FlockAgent,
242
- inputs: dict[str, Any],
243
- context: FlockContext | None = None,
244
- result: dict[str, Any] | None = None,
245
- ) -> None:
246
- """Clean up and final metric recording."""
247
- if self.config.storage_type == "json":
248
- # Save aggregated metrics
249
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
250
- summary_file = os.path.join(
251
- self.config.metrics_dir,
252
- f"summary_{agent.name}_{timestamp}.json",
253
- )
254
-
255
- # Calculate summary for all metrics
256
- summary = {
257
- "agent": agent.name,
258
- "timestamp": timestamp,
259
- "metrics": {},
260
- }
261
-
262
- # Get all unique metric names from files
263
- all_metrics = self._load_metrics_from_files()
264
-
265
- for metric_name in all_metrics:
266
- stats = self.get_statistics(metric_name)
267
- if stats: # Only include metrics that have data
268
- summary["metrics"][metric_name] = stats
269
-
270
- with open(summary_file, "w") as f:
271
- json.dump(summary, f, indent=2)
272
-
273
- def _record_metric(
274
- self, name: str, value: int | float | str, tags: dict[str, str] = None
275
- ) -> None:
276
- """Record a single metric point."""
277
- point = MetricPoint(
278
- timestamp=datetime.now(), value=value, tags=tags or {}
279
- )
280
-
281
- # Store metric
282
- if self.config.storage_type == "memory":
283
- self._metrics[name].append(point)
284
-
285
- elif self.config.storage_type == "prometheus":
286
- if name == "latency":
287
- self._prom_latency.labels(**tags).observe(value)
288
- elif name == "memory":
289
- self._prom_memory.labels(**tags).set(value)
290
- elif name == "tokens":
291
- self._prom_tokens.labels(**tags).inc(value)
292
-
293
- elif self.config.storage_type == "json":
294
- self._save_metric_to_file(name, point)
295
-
296
- def _save_metric_to_file(self, name: str, point: MetricPoint) -> None:
297
- """Save metric to JSON file."""
298
- filename = f"{name}_{point.timestamp.strftime('%Y%m')}.json"
299
- filepath = os.path.join(self.config.metrics_dir, filename)
300
-
301
- data = {
302
- "timestamp": point.timestamp.isoformat(),
303
- "value": point.value,
304
- "tags": point.tags,
305
- }
306
-
307
- # Append to file
308
- with open(filepath, "a") as f:
309
- f.write(json.dumps(data) + "\n")
310
-
311
- def _get_tokenizer(self, model: str):
312
- """Get the appropriate tokenizer for the model."""
313
- try:
314
- import tiktoken
315
-
316
- # Handle different model naming conventions
317
- if model.startswith("openai/"):
318
- model = model[7:] # Strip 'openai/' prefix
319
-
320
- try:
321
- return tiktoken.encoding_for_model(model)
322
- except KeyError:
323
- # Fallback to cl100k_base for unknown models
324
- return tiktoken.get_encoding("cl100k_base")
325
-
326
- except ImportError:
327
- return None
328
-
329
- def _calculate_token_usage(self, text: str, model: str = "gpt-4") -> int:
330
- """Calculate token count using tiktoken when available."""
331
- tokenizer = self._get_tokenizer(model)
332
-
333
- if tokenizer:
334
- # Use tiktoken for accurate count
335
- return len(tokenizer.encode(text))
336
- else:
337
- # Fallback to estimation if tiktoken not available
338
- # Simple estimation - words / 0.75 for average tokens per word
339
- token_estimate = int(len(text.split()) / 0.75)
340
-
341
- # Log warning about estimation
342
- print(
343
- f"Warning: Using estimated token count. Install tiktoken for accurate counting."
344
- )
345
-
346
- def _should_alert(self, metric: str, value: float) -> bool:
347
- """Check if metric should trigger alert."""
348
- if metric == "latency" and self.config.alert_on_high_latency:
349
- return value * 1000 > self.config.latency_threshold_ms
350
- return False
351
-
352
- async def on_initialize(
353
- self,
354
- agent: FlockAgent,
355
- inputs: dict[str, Any],
356
- context: FlockContext | None = None,
357
- ) -> None:
358
- """Initialize metrics collection."""
359
- self._start_time = time.time()
360
-
361
- if self.config.collect_memory:
362
- self._start_memory = psutil.Process().memory_info().rss
363
- self._record_metric(
364
- "memory",
365
- self._start_memory,
366
- {"agent": agent.name, "phase": "start"},
367
- )
368
-
369
- def _calculate_cost(
370
- self, text: str, model: str, is_completion: bool = False
371
- ) -> tuple[int, float]:
372
- """Calculate both token count and cost."""
373
- # Get token count
374
- try:
375
- from litellm import cost_per_token
376
-
377
- token_count = self._calculate_token_usage(text, model)
378
- # Calculate total cost
379
- if is_completion:
380
- total_cost = token_count * cost_per_token(
381
- model, completion_tokens=token_count
382
- )
383
- else:
384
- total_cost = token_count * cost_per_token(
385
- model, prompt_tokens=token_count
386
- )
387
-
388
- return token_count, total_cost
389
- except Exception:
390
- token_count = 0
391
- total_cost = 0.0
392
- return token_count, total_cost
393
-
394
- async def on_pre_evaluate(
395
- self,
396
- agent: FlockAgent,
397
- inputs: dict[str, Any],
398
- context: FlockContext | None = None,
399
- ) -> dict[str, Any]:
400
- """Record pre-evaluation metrics."""
401
- if self.config.collect_token_usage:
402
- # Calculate input tokens and cost
403
- total_input_tokens = 0
404
- total_input_cost = 0.0
405
-
406
- for v in inputs.values():
407
- tokens, cost = self._calculate_cost(
408
- str(v), agent.model, is_completion=False
409
- )
410
- total_input_tokens += tokens
411
- if isinstance(cost, float):
412
- total_input_cost += cost
413
- else:
414
- total_input_cost += cost[1]
415
-
416
- self._record_metric(
417
- "tokens",
418
- total_input_tokens,
419
- {"agent": agent.name, "type": "input"},
420
- )
421
- self._record_metric(
422
- "cost", total_input_cost, {"agent": agent.name, "type": "input"}
423
- )
424
-
425
- if self.config.collect_cpu:
426
- cpu_percent = psutil.Process().cpu_percent()
427
- self._record_metric(
428
- "cpu",
429
- cpu_percent,
430
- {"agent": agent.name, "phase": "pre_evaluate"},
431
- )
432
-
433
- return inputs
434
-
435
- async def on_post_evaluate(
436
- self,
437
- agent: FlockAgent,
438
- inputs: dict[str, Any],
439
- context: FlockContext | None = None,
440
- result: dict[str, Any] | None = None,
441
- ) -> dict[str, Any]:
442
- """Record post-evaluation metrics."""
443
- if self.config.collect_timing and self._start_time:
444
- latency = time.time() - self._start_time
445
- self._record_metric("latency", latency, {"agent": agent.name})
446
-
447
- # Check for alerts
448
- if self._should_alert("latency", latency):
449
- # In practice, you'd want to integrate with a proper alerting system
450
- print(f"ALERT: High latency detected: {latency * 1000:.2f}ms")
451
-
452
- if self.config.collect_token_usage:
453
- # Calculate output tokens and cost
454
- total_output_tokens = 0
455
- total_output_cost = 0.0
456
-
457
- for v in result.values():
458
- tokens, cost = self._calculate_cost(
459
- str(v), agent.model, is_completion=True
460
- )
461
- total_output_tokens += tokens
462
- if isinstance(cost, float):
463
- total_output_cost += cost
464
- else:
465
- total_output_cost += cost[1]
466
-
467
- self._record_metric(
468
- "tokens",
469
- total_output_tokens,
470
- {"agent": agent.name, "type": "output"},
471
- )
472
- self._record_metric(
473
- "cost",
474
- total_output_cost,
475
- {"agent": agent.name, "type": "output"},
476
- )
477
-
478
- # Record total cost for this operation
479
- self._record_metric(
480
- "total_cost",
481
- total_output_cost + total_output_cost,
482
- {"agent": agent.name},
483
- )
484
-
485
- if self.config.collect_memory and self._start_memory:
486
- current_memory = psutil.Process().memory_info().rss
487
- memory_diff = current_memory - self._start_memory
488
- self._record_metric(
489
- "memory", memory_diff, {"agent": agent.name, "phase": "end"}
490
- )
491
-
492
- return result
493
-
494
- async def on_error(
495
- self,
496
- agent: FlockAgent,
497
- error: Exception,
498
- inputs: dict[str, Any],
499
- context: FlockContext | None = None,
500
- ) -> None:
501
- """Record error metrics."""
502
- self._record_metric(
503
- "errors",
504
- 1,
505
- {"agent": agent.name, "error_type": type(error).__name__},
506
- )
507
-
508
- # --------------------------------------------------
509
- # Public helper for external modules
510
- # --------------------------------------------------
511
- @classmethod
512
- def record(cls, name: str, value: int | float | str, tags: dict[str, str] | None = None):
513
- """Record a metric from anywhere in the codebase.
514
-
515
- Example:
516
- MetricsModule.record("custom_latency", 123, {"stage": "inference"})
517
- The call will forward to the *first* instantiated MetricsModule. If no
518
- instance exists in the current run the call is a no-op so that importing
519
- this helper never crashes test-code.
520
- """
521
- instance = cls._INSTANCE
522
- if instance is None:
523
- return # silently ignore if module isn't active
524
- instance._record_metric(name, value, tags or {})
525
-
526
- # --- MCP Server Lifecycle Hooks ---
527
- async def on_server_error(
528
- self, server: FlockMCPServerBase, error: Exception
529
- ) -> None:
530
- """Record server error metrics."""
531
- self._record_metric(
532
- "errors",
533
- 1,
534
- {
535
- "server": server.config.name,
536
- "error_type": type(error).__name__,
537
- },
538
- )
539
-
540
- async def on_pre_server_init(self, server: FlockMCPServerBase):
541
- """Initialize metrics collection for server."""
542
- self._server_start_time = time.time()
543
-
544
- if self.config.collect_memory:
545
- self._server_start_memory = psutil.Process().memory_info().rss
546
- self._record_metric(
547
- "server_memory",
548
- self._server_start_memory,
549
- {"server": server.config.name, "phase": "pre_init"},
550
- )
551
-
552
- async def on_post_server_init(self, server: FlockMCPServerBase):
553
- """Collect metrics after server starts."""
554
- if self.config.collect_memory:
555
- checkpoint_memory = psutil.Process().memory_info().rss
556
- self._record_metric(
557
- "server_memory",
558
- checkpoint_memory,
559
- {"server": server.config.name, "phase": "post_init"},
560
- )
561
-
562
- async def on_pre_server_terminate(self, server: FlockMCPServerBase):
563
- """Collect metrics before server terminates."""
564
- if self.config.collect_memory:
565
- checkpoint_memory = psutil.Process().memory_info().rss
566
- self._record_metric(
567
- "server_memory",
568
- checkpoint_memory,
569
- {"server": server.config.name, "phase": "pre_terminate"},
570
- )
571
-
572
- async def on_post_server_terminate(self, server: FlockMCPServerBase):
573
- """Collect metrics after server terminates.
574
-
575
- Clean up and final metric recording.
576
- """
577
- if self.config.storage_type == "json":
578
- # Save aggregated metrics
579
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
580
- summary_file = os.path.join(
581
- self.config.metrics_dir,
582
- f"summary_{server.config.name}_{timestamp}.json",
583
- )
584
-
585
- # Calculate summary for all metrics
586
- summary = {
587
- "server": server.config.name,
588
- "timestamp": timestamp,
589
- "metrics": {},
590
- }
591
-
592
- # Get all unique metric names from files
593
- all_metrics = self._load_metrics_from_files()
594
-
595
- for metric_name in all_metrics:
596
- stats = self.get_statistics(metric_name)
597
- if stats: # Only include metrics that have data
598
- summary["metrics"][metric_name] = stats
599
- with open(summary_file, "w") as f:
600
- json.dump(summary, f, indent=2)
601
-
602
- async def on_pre_mcp_call(
603
- self, server: FlockMCPServerBase, arguments: Any | None = None
604
- ):
605
- """Record pre-call metrics."""
606
- if self.config.collect_cpu:
607
- cpu_percent = psutil.Process().cpu_percent()
608
- self._record_metric(
609
- "cpu",
610
- cpu_percent,
611
- {"server": server.config.name, "phase": "pre_mcp_call"},
612
- )
613
- if self.config.collect_memory:
614
- current_memory = psutil.Process().memory_info().rss
615
- memory_diff = current_memory - self._server_start_memory
616
- self._record_metric(
617
- "memory",
618
- memory_diff,
619
- {"server": server.config.name, "phase": "pre_mcp_call"},
620
- )
621
-
622
- if isinstance(arguments, dict):
623
- self._record_metric(
624
- "arguments",
625
- len(arguments),
626
- {
627
- "server": server.config.name,
628
- "phase": "pre_mcp_call",
629
- }.update(arguments),
630
- )
631
-
632
- async def on_post_mcp_call(
633
- self, server: FlockMCPServerBase, result: Any | None = None
634
- ):
635
- """Record post-call metrics."""
636
- if self.config.collect_timing and self._server_start_time:
637
- latency = time.time() - self._server_start_time
638
- self._record_metric(
639
- "latency", latency, {"server": server.config.name}
640
- )
641
-
642
- # Check for alerts
643
- if self._should_alert("latency", latency):
644
- # In practice, you'd want to integrate with a proper alerting system
645
- print(f"ALERT: High latency detected: {latency * 1000:.2f}ms")
646
-
647
- if self.config.collect_cpu:
648
- cpu_percent = psutil.Process().cpu_percent()
649
- self._record_metric(
650
- "cpu",
651
- cpu_percent,
652
- {"server": server.config.name, "phase": "post_mcp_call"},
653
- )
654
- if self.config.collect_memory:
655
- current_memory = psutil.Process().memory_info().rss
656
- memory_diff = current_memory - self._server_start_memory
657
- self._record_metric(
658
- "memory",
659
- memory_diff,
660
- {"server": server.config.name, "phase": "post_mcp_call"},
661
- )
662
-
663
- async def on_connect(
664
- self, server: FlockMCPServerBase, additional_params: dict[str, Any]
665
- ) -> dict[str, Any]:
666
- """Collect metrics during connect."""
667
- # We should track the refresh rate for clients
668
- if "refresh_client" in additional_params and additional_params.get(
669
- "refresh_client", False
670
- ):
671
- self._client_refreshs += 1
672
- self._record_metric(
673
- "client_refreshs",
674
- self._client_refreshs,
675
- {"server": server.config.name, "phase": "connect"},
676
- )
677
-
678
- return additional_params
@@ -1 +0,0 @@
1
- # Package for modules