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

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

Potentially problematic release.


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

Files changed (501) hide show
  1. flock/__init__.py +12 -217
  2. flock/agent.py +1079 -0
  3. flock/api/themes.py +71 -0
  4. flock/artifacts.py +86 -0
  5. flock/cli.py +147 -0
  6. flock/components.py +189 -0
  7. flock/dashboard/__init__.py +30 -0
  8. flock/dashboard/collector.py +559 -0
  9. flock/dashboard/events.py +188 -0
  10. flock/dashboard/graph_builder.py +563 -0
  11. flock/dashboard/launcher.py +235 -0
  12. flock/dashboard/models/graph.py +156 -0
  13. flock/dashboard/service.py +991 -0
  14. flock/dashboard/static_v2/assets/index-DFRnI_mt.js +111 -0
  15. flock/dashboard/static_v2/assets/index-fPLNdmp1.css +1 -0
  16. flock/dashboard/static_v2/index.html +13 -0
  17. flock/dashboard/websocket.py +246 -0
  18. flock/engines/__init__.py +6 -0
  19. flock/engines/dspy_engine.py +932 -0
  20. flock/examples.py +131 -0
  21. flock/frontend/README.md +778 -0
  22. flock/frontend/docs/DESIGN_SYSTEM.md +1980 -0
  23. flock/frontend/index.html +12 -0
  24. flock/frontend/package-lock.json +4337 -0
  25. flock/frontend/package.json +48 -0
  26. flock/frontend/src/App.tsx +139 -0
  27. flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +647 -0
  28. flock/frontend/src/__tests__/integration/indexeddb-persistence.test.tsx +699 -0
  29. flock/frontend/src/components/common/BuildInfo.tsx +39 -0
  30. flock/frontend/src/components/common/EmptyState.module.css +115 -0
  31. flock/frontend/src/components/common/EmptyState.tsx +128 -0
  32. flock/frontend/src/components/common/ErrorBoundary.module.css +169 -0
  33. flock/frontend/src/components/common/ErrorBoundary.tsx +118 -0
  34. flock/frontend/src/components/common/KeyboardShortcutsDialog.css +251 -0
  35. flock/frontend/src/components/common/KeyboardShortcutsDialog.tsx +151 -0
  36. flock/frontend/src/components/common/LoadingSpinner.module.css +97 -0
  37. flock/frontend/src/components/common/LoadingSpinner.tsx +29 -0
  38. flock/frontend/src/components/controls/PublishControl.css +547 -0
  39. flock/frontend/src/components/controls/PublishControl.test.tsx +543 -0
  40. flock/frontend/src/components/controls/PublishControl.tsx +432 -0
  41. flock/frontend/src/components/details/DetailWindowContainer.tsx +58 -0
  42. flock/frontend/src/components/details/LiveOutputTab.test.tsx +792 -0
  43. flock/frontend/src/components/details/LiveOutputTab.tsx +220 -0
  44. flock/frontend/src/components/details/MessageDetailWindow.tsx +439 -0
  45. flock/frontend/src/components/details/MessageHistoryTab.tsx +374 -0
  46. flock/frontend/src/components/details/NodeDetailWindow.test.tsx +501 -0
  47. flock/frontend/src/components/details/NodeDetailWindow.tsx +218 -0
  48. flock/frontend/src/components/details/RunStatusTab.tsx +348 -0
  49. flock/frontend/src/components/details/tabs.test.tsx +1015 -0
  50. flock/frontend/src/components/filters/ArtifactTypeFilter.tsx +21 -0
  51. flock/frontend/src/components/filters/CorrelationIDFilter.module.css +102 -0
  52. flock/frontend/src/components/filters/CorrelationIDFilter.test.tsx +197 -0
  53. flock/frontend/src/components/filters/CorrelationIDFilter.tsx +121 -0
  54. flock/frontend/src/components/filters/FilterFlyout.module.css +104 -0
  55. flock/frontend/src/components/filters/FilterFlyout.tsx +80 -0
  56. flock/frontend/src/components/filters/FilterPills.module.css +220 -0
  57. flock/frontend/src/components/filters/FilterPills.test.tsx +189 -0
  58. flock/frontend/src/components/filters/FilterPills.tsx +143 -0
  59. flock/frontend/src/components/filters/ProducerFilter.tsx +21 -0
  60. flock/frontend/src/components/filters/SavedFiltersControl.module.css +60 -0
  61. flock/frontend/src/components/filters/SavedFiltersControl.test.tsx +158 -0
  62. flock/frontend/src/components/filters/SavedFiltersControl.tsx +159 -0
  63. flock/frontend/src/components/filters/TagFilter.tsx +21 -0
  64. flock/frontend/src/components/filters/TimeRangeFilter.module.css +115 -0
  65. flock/frontend/src/components/filters/TimeRangeFilter.test.tsx +154 -0
  66. flock/frontend/src/components/filters/TimeRangeFilter.tsx +110 -0
  67. flock/frontend/src/components/filters/VisibilityFilter.tsx +21 -0
  68. flock/frontend/src/components/graph/AgentNode.test.tsx +77 -0
  69. flock/frontend/src/components/graph/AgentNode.tsx +324 -0
  70. flock/frontend/src/components/graph/GraphCanvas.tsx +613 -0
  71. flock/frontend/src/components/graph/MessageFlowEdge.tsx +128 -0
  72. flock/frontend/src/components/graph/MessageNode.test.tsx +64 -0
  73. flock/frontend/src/components/graph/MessageNode.tsx +129 -0
  74. flock/frontend/src/components/graph/MiniMap.tsx +47 -0
  75. flock/frontend/src/components/graph/TransformEdge.tsx +123 -0
  76. flock/frontend/src/components/layout/DashboardLayout.css +420 -0
  77. flock/frontend/src/components/layout/DashboardLayout.tsx +287 -0
  78. flock/frontend/src/components/layout/Header.module.css +88 -0
  79. flock/frontend/src/components/layout/Header.tsx +52 -0
  80. flock/frontend/src/components/modules/HistoricalArtifactsModule.module.css +288 -0
  81. flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +450 -0
  82. flock/frontend/src/components/modules/HistoricalArtifactsModuleWrapper.tsx +13 -0
  83. flock/frontend/src/components/modules/JsonAttributeRenderer.tsx +140 -0
  84. flock/frontend/src/components/modules/ModuleRegistry.test.ts +333 -0
  85. flock/frontend/src/components/modules/ModuleRegistry.ts +93 -0
  86. flock/frontend/src/components/modules/ModuleWindow.tsx +223 -0
  87. flock/frontend/src/components/modules/TraceModuleJaeger.tsx +1971 -0
  88. flock/frontend/src/components/modules/TraceModuleJaegerWrapper.tsx +13 -0
  89. flock/frontend/src/components/modules/registerModules.ts +29 -0
  90. flock/frontend/src/components/settings/AdvancedSettings.tsx +175 -0
  91. flock/frontend/src/components/settings/AppearanceSettings.tsx +185 -0
  92. flock/frontend/src/components/settings/GraphSettings.tsx +110 -0
  93. flock/frontend/src/components/settings/MultiSelect.tsx +235 -0
  94. flock/frontend/src/components/settings/SettingsPanel.css +327 -0
  95. flock/frontend/src/components/settings/SettingsPanel.tsx +131 -0
  96. flock/frontend/src/components/settings/ThemeSelector.tsx +298 -0
  97. flock/frontend/src/components/settings/TracingSettings.tsx +404 -0
  98. flock/frontend/src/hooks/useKeyboardShortcuts.ts +148 -0
  99. flock/frontend/src/hooks/useModulePersistence.test.ts +442 -0
  100. flock/frontend/src/hooks/useModulePersistence.ts +154 -0
  101. flock/frontend/src/hooks/useModules.ts +157 -0
  102. flock/frontend/src/hooks/usePersistence.ts +141 -0
  103. flock/frontend/src/main.tsx +13 -0
  104. flock/frontend/src/services/api.ts +337 -0
  105. flock/frontend/src/services/graphService.test.ts +330 -0
  106. flock/frontend/src/services/graphService.ts +75 -0
  107. flock/frontend/src/services/indexeddb.test.ts +793 -0
  108. flock/frontend/src/services/indexeddb.ts +848 -0
  109. flock/frontend/src/services/layout.test.ts +437 -0
  110. flock/frontend/src/services/layout.ts +357 -0
  111. flock/frontend/src/services/themeApplicator.ts +140 -0
  112. flock/frontend/src/services/themeService.ts +77 -0
  113. flock/frontend/src/services/websocket.ts +650 -0
  114. flock/frontend/src/store/filterStore.test.ts +250 -0
  115. flock/frontend/src/store/filterStore.ts +272 -0
  116. flock/frontend/src/store/graphStore.test.ts +570 -0
  117. flock/frontend/src/store/graphStore.ts +462 -0
  118. flock/frontend/src/store/moduleStore.test.ts +253 -0
  119. flock/frontend/src/store/moduleStore.ts +75 -0
  120. flock/frontend/src/store/settingsStore.ts +188 -0
  121. flock/frontend/src/store/streamStore.ts +68 -0
  122. flock/frontend/src/store/uiStore.test.ts +54 -0
  123. flock/frontend/src/store/uiStore.ts +122 -0
  124. flock/frontend/src/store/wsStore.ts +34 -0
  125. flock/frontend/src/styles/index.css +15 -0
  126. flock/frontend/src/styles/scrollbar.css +47 -0
  127. flock/frontend/src/styles/variables.css +488 -0
  128. flock/frontend/src/test/setup.ts +1 -0
  129. flock/frontend/src/types/filters.ts +47 -0
  130. flock/frontend/src/types/graph.ts +95 -0
  131. flock/frontend/src/types/modules.ts +10 -0
  132. flock/frontend/src/types/theme.ts +55 -0
  133. flock/frontend/src/utils/artifacts.ts +24 -0
  134. flock/frontend/src/utils/mockData.ts +98 -0
  135. flock/frontend/src/utils/performance.ts +16 -0
  136. flock/frontend/src/vite-env.d.ts +17 -0
  137. flock/frontend/tsconfig.json +27 -0
  138. flock/frontend/tsconfig.node.json +11 -0
  139. flock/frontend/vite.config.ts +25 -0
  140. flock/frontend/vitest.config.ts +11 -0
  141. flock/{core/util → helper}/cli_helper.py +9 -5
  142. flock/{core/logging → logging}/__init__.py +2 -3
  143. flock/logging/auto_trace.py +159 -0
  144. flock/{core/logging → logging}/formatters/enum_builder.py +3 -4
  145. flock/{core/logging → logging}/formatters/theme_builder.py +19 -44
  146. flock/{core/logging → logging}/formatters/themed_formatter.py +69 -107
  147. flock/{core/logging → logging}/logging.py +78 -61
  148. flock/{core/logging → logging}/telemetry.py +66 -26
  149. flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
  150. flock/logging/telemetry_exporter/duckdb_exporter.py +216 -0
  151. flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +13 -10
  152. flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
  153. flock/logging/trace_and_logged.py +304 -0
  154. flock/mcp/__init__.py +91 -0
  155. flock/{core/mcp/mcp_client.py → mcp/client.py} +131 -158
  156. flock/{core/mcp/mcp_config.py → mcp/config.py} +86 -132
  157. flock/mcp/manager.py +286 -0
  158. flock/mcp/servers/sse/__init__.py +1 -1
  159. flock/mcp/servers/sse/flock_sse_server.py +16 -58
  160. flock/mcp/servers/stdio/__init__.py +1 -1
  161. flock/mcp/servers/stdio/flock_stdio_server.py +13 -53
  162. flock/mcp/servers/streamable_http/flock_streamable_http_server.py +22 -67
  163. flock/mcp/servers/websockets/flock_websocket_server.py +12 -45
  164. flock/{core/mcp/flock_mcp_tool_base.py → mcp/tool.py} +24 -78
  165. flock/mcp/types/__init__.py +42 -0
  166. flock/{core/mcp → mcp}/types/callbacks.py +12 -15
  167. flock/{core/mcp → mcp}/types/factories.py +7 -6
  168. flock/{core/mcp → mcp}/types/handlers.py +13 -18
  169. flock/{core/mcp → mcp}/types/types.py +70 -74
  170. flock/{core/mcp → mcp}/util/helpers.py +3 -3
  171. flock/orchestrator.py +970 -0
  172. flock/registry.py +148 -0
  173. flock/runtime.py +262 -0
  174. flock/service.py +277 -0
  175. flock/store.py +1214 -0
  176. flock/subscription.py +111 -0
  177. flock/themes/andromeda.toml +1 -1
  178. flock/themes/apple-system-colors.toml +1 -1
  179. flock/themes/arcoiris.toml +1 -1
  180. flock/themes/atomonelight.toml +1 -1
  181. flock/themes/ayu copy.toml +1 -1
  182. flock/themes/ayu-light.toml +1 -1
  183. flock/themes/belafonte-day.toml +1 -1
  184. flock/themes/belafonte-night.toml +1 -1
  185. flock/themes/blulocodark.toml +1 -1
  186. flock/themes/breeze.toml +1 -1
  187. flock/themes/broadcast.toml +1 -1
  188. flock/themes/brogrammer.toml +1 -1
  189. flock/themes/builtin-dark.toml +1 -1
  190. flock/themes/builtin-pastel-dark.toml +1 -1
  191. flock/themes/catppuccin-latte.toml +1 -1
  192. flock/themes/catppuccin-macchiato.toml +1 -1
  193. flock/themes/catppuccin-mocha.toml +1 -1
  194. flock/themes/cga.toml +1 -1
  195. flock/themes/chalk.toml +1 -1
  196. flock/themes/ciapre.toml +1 -1
  197. flock/themes/coffee-theme.toml +1 -1
  198. flock/themes/cyberpunkscarletprotocol.toml +1 -1
  199. flock/themes/dark+.toml +1 -1
  200. flock/themes/darkermatrix.toml +1 -1
  201. flock/themes/darkmatrix.toml +2 -2
  202. flock/themes/darkside.toml +1 -1
  203. flock/themes/deep.toml +2 -2
  204. flock/themes/desert.toml +1 -1
  205. flock/themes/django.toml +1 -1
  206. flock/themes/djangosmooth.toml +1 -1
  207. flock/themes/doomone.toml +1 -1
  208. flock/themes/dotgov.toml +1 -1
  209. flock/themes/dracula+.toml +1 -1
  210. flock/themes/duckbones.toml +1 -1
  211. flock/themes/encom.toml +1 -1
  212. flock/themes/espresso.toml +1 -1
  213. flock/themes/everblush.toml +1 -1
  214. flock/themes/fairyfloss.toml +1 -1
  215. flock/themes/fideloper.toml +1 -1
  216. flock/themes/fishtank.toml +1 -1
  217. flock/themes/flexoki-light.toml +1 -1
  218. flock/themes/floraverse.toml +1 -1
  219. flock/themes/framer.toml +1 -1
  220. flock/themes/galizur.toml +1 -1
  221. flock/themes/github.toml +1 -1
  222. flock/themes/grass.toml +1 -1
  223. flock/themes/grey-green.toml +1 -1
  224. flock/themes/gruvboxlight.toml +1 -1
  225. flock/themes/guezwhoz.toml +1 -1
  226. flock/themes/harper.toml +1 -1
  227. flock/themes/hax0r-blue.toml +1 -1
  228. flock/themes/hopscotch.256.toml +1 -1
  229. flock/themes/ic-green-ppl.toml +1 -1
  230. flock/themes/iceberg-dark.toml +1 -1
  231. flock/themes/japanesque.toml +1 -1
  232. flock/themes/jubi.toml +1 -1
  233. flock/themes/kibble.toml +1 -1
  234. flock/themes/kolorit.toml +1 -1
  235. flock/themes/kurokula.toml +1 -1
  236. flock/themes/materialdesigncolors.toml +1 -1
  237. flock/themes/matrix.toml +1 -1
  238. flock/themes/mellifluous.toml +1 -1
  239. flock/themes/midnight-in-mojave.toml +1 -1
  240. flock/themes/monokai-remastered.toml +1 -1
  241. flock/themes/monokai-soda.toml +1 -1
  242. flock/themes/neon.toml +1 -1
  243. flock/themes/neopolitan.toml +5 -5
  244. flock/themes/nord-light.toml +1 -1
  245. flock/themes/ocean.toml +1 -1
  246. flock/themes/onehalfdark.toml +1 -1
  247. flock/themes/onehalflight.toml +1 -1
  248. flock/themes/palenighthc.toml +1 -1
  249. flock/themes/paulmillr.toml +1 -1
  250. flock/themes/pencildark.toml +1 -1
  251. flock/themes/pnevma.toml +1 -1
  252. flock/themes/purple-rain.toml +1 -1
  253. flock/themes/purplepeter.toml +1 -1
  254. flock/themes/raycast-dark.toml +1 -1
  255. flock/themes/red-sands.toml +1 -1
  256. flock/themes/relaxed.toml +1 -1
  257. flock/themes/retro.toml +1 -1
  258. flock/themes/rose-pine.toml +1 -1
  259. flock/themes/royal.toml +1 -1
  260. flock/themes/ryuuko.toml +1 -1
  261. flock/themes/sakura.toml +1 -1
  262. flock/themes/scarlet-protocol.toml +1 -1
  263. flock/themes/seoulbones-dark.toml +1 -1
  264. flock/themes/shades-of-purple.toml +1 -1
  265. flock/themes/smyck.toml +1 -1
  266. flock/themes/softserver.toml +1 -1
  267. flock/themes/solarized-darcula.toml +1 -1
  268. flock/themes/square.toml +1 -1
  269. flock/themes/sugarplum.toml +1 -1
  270. flock/themes/thayer-bright.toml +1 -1
  271. flock/themes/tokyonight.toml +1 -1
  272. flock/themes/tomorrow.toml +1 -1
  273. flock/themes/ubuntu.toml +1 -1
  274. flock/themes/ultradark.toml +1 -1
  275. flock/themes/ultraviolent.toml +1 -1
  276. flock/themes/unikitty.toml +1 -1
  277. flock/themes/urple.toml +1 -1
  278. flock/themes/vesper.toml +1 -1
  279. flock/themes/vimbones.toml +1 -1
  280. flock/themes/wildcherry.toml +1 -1
  281. flock/themes/wilmersdorf.toml +1 -1
  282. flock/themes/wryan.toml +1 -1
  283. flock/themes/xcodedarkhc.toml +1 -1
  284. flock/themes/xcodelight.toml +1 -1
  285. flock/themes/zenbones-light.toml +1 -1
  286. flock/themes/zenwritten-dark.toml +1 -1
  287. flock/utilities.py +301 -0
  288. flock/utility/output_utility_component.py +226 -0
  289. flock/visibility.py +107 -0
  290. flock_core-0.5.0.dist-info/METADATA +964 -0
  291. flock_core-0.5.0.dist-info/RECORD +525 -0
  292. flock_core-0.5.0.dist-info/entry_points.txt +2 -0
  293. {flock_core-0.4.543.dist-info → flock_core-0.5.0.dist-info}/licenses/LICENSE +1 -1
  294. flock/adapter/__init__.py +0 -14
  295. flock/adapter/azure_adapter.py +0 -68
  296. flock/adapter/chroma_adapter.py +0 -73
  297. flock/adapter/faiss_adapter.py +0 -97
  298. flock/adapter/pinecone_adapter.py +0 -51
  299. flock/adapter/vector_base.py +0 -47
  300. flock/cli/assets/release_notes.md +0 -140
  301. flock/cli/config.py +0 -8
  302. flock/cli/constants.py +0 -36
  303. flock/cli/create_agent.py +0 -1
  304. flock/cli/create_flock.py +0 -280
  305. flock/cli/execute_flock.py +0 -620
  306. flock/cli/load_agent.py +0 -1
  307. flock/cli/load_examples.py +0 -1
  308. flock/cli/load_flock.py +0 -192
  309. flock/cli/load_release_notes.py +0 -20
  310. flock/cli/loaded_flock_cli.py +0 -254
  311. flock/cli/manage_agents.py +0 -459
  312. flock/cli/registry_management.py +0 -889
  313. flock/cli/runner.py +0 -41
  314. flock/cli/settings.py +0 -857
  315. flock/cli/utils.py +0 -135
  316. flock/cli/view_results.py +0 -29
  317. flock/cli/yaml_editor.py +0 -396
  318. flock/config.py +0 -56
  319. flock/core/__init__.py +0 -44
  320. flock/core/api/__init__.py +0 -10
  321. flock/core/api/custom_endpoint.py +0 -45
  322. flock/core/api/endpoints.py +0 -262
  323. flock/core/api/main.py +0 -162
  324. flock/core/api/models.py +0 -101
  325. flock/core/api/run_store.py +0 -224
  326. flock/core/api/runner.py +0 -44
  327. flock/core/api/service.py +0 -214
  328. flock/core/config/flock_agent_config.py +0 -11
  329. flock/core/config/scheduled_agent_config.py +0 -40
  330. flock/core/context/context.py +0 -214
  331. flock/core/context/context_manager.py +0 -40
  332. flock/core/context/context_vars.py +0 -11
  333. flock/core/evaluation/utils.py +0 -395
  334. flock/core/execution/batch_executor.py +0 -369
  335. flock/core/execution/evaluation_executor.py +0 -438
  336. flock/core/execution/local_executor.py +0 -31
  337. flock/core/execution/opik_executor.py +0 -103
  338. flock/core/execution/temporal_executor.py +0 -166
  339. flock/core/flock.py +0 -1003
  340. flock/core/flock_agent.py +0 -1258
  341. flock/core/flock_evaluator.py +0 -60
  342. flock/core/flock_factory.py +0 -513
  343. flock/core/flock_module.py +0 -207
  344. flock/core/flock_registry.py +0 -702
  345. flock/core/flock_router.py +0 -83
  346. flock/core/flock_scheduler.py +0 -166
  347. flock/core/flock_server_manager.py +0 -136
  348. flock/core/interpreter/python_interpreter.py +0 -689
  349. flock/core/logging/live_capture.py +0 -137
  350. flock/core/logging/trace_and_logged.py +0 -59
  351. flock/core/mcp/__init__.py +0 -1
  352. flock/core/mcp/flock_mcp_server.py +0 -640
  353. flock/core/mcp/mcp_client_manager.py +0 -201
  354. flock/core/mcp/types/__init__.py +0 -1
  355. flock/core/mixin/dspy_integration.py +0 -445
  356. flock/core/mixin/prompt_parser.py +0 -125
  357. flock/core/serialization/__init__.py +0 -13
  358. flock/core/serialization/callable_registry.py +0 -52
  359. flock/core/serialization/flock_serializer.py +0 -854
  360. flock/core/serialization/json_encoder.py +0 -41
  361. flock/core/serialization/secure_serializer.py +0 -175
  362. flock/core/serialization/serializable.py +0 -342
  363. flock/core/serialization/serialization_utils.py +0 -409
  364. flock/core/util/file_path_utils.py +0 -223
  365. flock/core/util/hydrator.py +0 -309
  366. flock/core/util/input_resolver.py +0 -141
  367. flock/core/util/loader.py +0 -59
  368. flock/core/util/splitter.py +0 -219
  369. flock/di.py +0 -41
  370. flock/evaluators/__init__.py +0 -1
  371. flock/evaluators/declarative/__init__.py +0 -1
  372. flock/evaluators/declarative/declarative_evaluator.py +0 -217
  373. flock/evaluators/memory/memory_evaluator.py +0 -90
  374. flock/evaluators/test/test_case_evaluator.py +0 -38
  375. flock/evaluators/zep/zep_evaluator.py +0 -59
  376. flock/modules/__init__.py +0 -1
  377. flock/modules/assertion/__init__.py +0 -1
  378. flock/modules/assertion/assertion_module.py +0 -286
  379. flock/modules/callback/__init__.py +0 -1
  380. flock/modules/callback/callback_module.py +0 -91
  381. flock/modules/enterprise_memory/README.md +0 -99
  382. flock/modules/enterprise_memory/enterprise_memory_module.py +0 -526
  383. flock/modules/mem0/__init__.py +0 -1
  384. flock/modules/mem0/mem0_module.py +0 -126
  385. flock/modules/mem0_async/__init__.py +0 -1
  386. flock/modules/mem0_async/async_mem0_module.py +0 -126
  387. flock/modules/memory/__init__.py +0 -1
  388. flock/modules/memory/memory_module.py +0 -429
  389. flock/modules/memory/memory_parser.py +0 -125
  390. flock/modules/memory/memory_storage.py +0 -736
  391. flock/modules/output/__init__.py +0 -1
  392. flock/modules/output/output_module.py +0 -196
  393. flock/modules/performance/__init__.py +0 -1
  394. flock/modules/performance/metrics_module.py +0 -678
  395. flock/modules/zep/__init__.py +0 -1
  396. flock/modules/zep/zep_module.py +0 -192
  397. flock/platform/docker_tools.py +0 -49
  398. flock/platform/jaeger_install.py +0 -86
  399. flock/routers/__init__.py +0 -1
  400. flock/routers/agent/__init__.py +0 -1
  401. flock/routers/agent/agent_router.py +0 -236
  402. flock/routers/agent/handoff_agent.py +0 -58
  403. flock/routers/conditional/conditional_router.py +0 -486
  404. flock/routers/default/__init__.py +0 -1
  405. flock/routers/default/default_router.py +0 -80
  406. flock/routers/feedback/feedback_router.py +0 -114
  407. flock/routers/list_generator/list_generator_router.py +0 -166
  408. flock/routers/llm/__init__.py +0 -1
  409. flock/routers/llm/llm_router.py +0 -365
  410. flock/tools/__init__.py +0 -0
  411. flock/tools/azure_tools.py +0 -781
  412. flock/tools/code_tools.py +0 -167
  413. flock/tools/file_tools.py +0 -149
  414. flock/tools/github_tools.py +0 -157
  415. flock/tools/markdown_tools.py +0 -205
  416. flock/tools/system_tools.py +0 -9
  417. flock/tools/text_tools.py +0 -810
  418. flock/tools/web_tools.py +0 -92
  419. flock/tools/zendesk_tools.py +0 -501
  420. flock/webapp/__init__.py +0 -1
  421. flock/webapp/app/__init__.py +0 -0
  422. flock/webapp/app/api/__init__.py +0 -0
  423. flock/webapp/app/api/agent_management.py +0 -237
  424. flock/webapp/app/api/execution.py +0 -503
  425. flock/webapp/app/api/flock_management.py +0 -125
  426. flock/webapp/app/api/registry_viewer.py +0 -29
  427. flock/webapp/app/chat.py +0 -662
  428. flock/webapp/app/config.py +0 -104
  429. flock/webapp/app/dependencies.py +0 -117
  430. flock/webapp/app/main.py +0 -1086
  431. flock/webapp/app/middleware.py +0 -113
  432. flock/webapp/app/models_ui.py +0 -7
  433. flock/webapp/app/services/__init__.py +0 -0
  434. flock/webapp/app/services/feedback_file_service.py +0 -363
  435. flock/webapp/app/services/flock_service.py +0 -345
  436. flock/webapp/app/services/sharing_models.py +0 -81
  437. flock/webapp/app/services/sharing_store.py +0 -597
  438. flock/webapp/app/templates/theme_mapper.html +0 -326
  439. flock/webapp/app/theme_mapper.py +0 -811
  440. flock/webapp/app/utils.py +0 -85
  441. flock/webapp/run.py +0 -219
  442. flock/webapp/static/css/chat.css +0 -301
  443. flock/webapp/static/css/components.css +0 -167
  444. flock/webapp/static/css/header.css +0 -39
  445. flock/webapp/static/css/layout.css +0 -281
  446. flock/webapp/static/css/sidebar.css +0 -127
  447. flock/webapp/static/css/two-pane.css +0 -48
  448. flock/webapp/templates/base.html +0 -389
  449. flock/webapp/templates/chat.html +0 -152
  450. flock/webapp/templates/chat_settings.html +0 -19
  451. flock/webapp/templates/flock_editor.html +0 -16
  452. flock/webapp/templates/index.html +0 -12
  453. flock/webapp/templates/partials/_agent_detail_form.html +0 -93
  454. flock/webapp/templates/partials/_agent_list.html +0 -18
  455. flock/webapp/templates/partials/_agent_manager_view.html +0 -51
  456. flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
  457. flock/webapp/templates/partials/_chat_container.html +0 -15
  458. flock/webapp/templates/partials/_chat_messages.html +0 -57
  459. flock/webapp/templates/partials/_chat_settings_form.html +0 -85
  460. flock/webapp/templates/partials/_create_flock_form.html +0 -50
  461. flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
  462. flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
  463. flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
  464. flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
  465. flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
  466. flock/webapp/templates/partials/_env_vars_table.html +0 -23
  467. flock/webapp/templates/partials/_execution_form.html +0 -127
  468. flock/webapp/templates/partials/_execution_view_container.html +0 -28
  469. flock/webapp/templates/partials/_flock_file_list.html +0 -23
  470. flock/webapp/templates/partials/_flock_properties_form.html +0 -52
  471. flock/webapp/templates/partials/_flock_upload_form.html +0 -16
  472. flock/webapp/templates/partials/_header_flock_status.html +0 -5
  473. flock/webapp/templates/partials/_live_logs.html +0 -13
  474. flock/webapp/templates/partials/_load_manager_view.html +0 -49
  475. flock/webapp/templates/partials/_registry_table.html +0 -25
  476. flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
  477. flock/webapp/templates/partials/_results_display.html +0 -78
  478. flock/webapp/templates/partials/_settings_env_content.html +0 -9
  479. flock/webapp/templates/partials/_settings_theme_content.html +0 -14
  480. flock/webapp/templates/partials/_settings_view.html +0 -36
  481. flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
  482. flock/webapp/templates/partials/_share_link_snippet.html +0 -35
  483. flock/webapp/templates/partials/_sidebar.html +0 -74
  484. flock/webapp/templates/partials/_structured_data_view.html +0 -40
  485. flock/webapp/templates/partials/_theme_preview.html +0 -36
  486. flock/webapp/templates/registry_viewer.html +0 -84
  487. flock/webapp/templates/shared_run_page.html +0 -140
  488. flock/workflow/__init__.py +0 -0
  489. flock/workflow/activities.py +0 -237
  490. flock/workflow/agent_activities.py +0 -24
  491. flock/workflow/agent_execution_activity.py +0 -240
  492. flock/workflow/flock_workflow.py +0 -225
  493. flock/workflow/temporal_config.py +0 -96
  494. flock/workflow/temporal_setup.py +0 -60
  495. flock_core-0.4.543.dist-info/METADATA +0 -676
  496. flock_core-0.4.543.dist-info/RECORD +0 -572
  497. flock_core-0.4.543.dist-info/entry_points.txt +0 -2
  498. /flock/{core/logging → logging}/formatters/themes.py +0 -0
  499. /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
  500. /flock/{core/mcp → mcp}/util/__init__.py +0 -0
  501. {flock_core-0.4.543.dist-info → flock_core-0.5.0.dist-info}/WHEEL +0 -0
@@ -1,409 +0,0 @@
1
- # src/flock/core/serialization/serialization_utils.py
2
- """Utilities for recursive serialization/deserialization with callable handling."""
3
-
4
- import ast
5
- import builtins
6
- import importlib
7
- import sys
8
- import types
9
- import typing
10
- from collections.abc import Mapping, Sequence
11
- from enum import Enum
12
- from typing import (
13
- TYPE_CHECKING,
14
- Any,
15
- Literal,
16
- Union,
17
- get_args,
18
- get_origin,
19
- )
20
-
21
- from pydantic import BaseModel
22
-
23
- # Use TYPE_CHECKING to avoid circular imports
24
- if TYPE_CHECKING:
25
- pass
26
-
27
- from flock.core.flock_registry import get_registry
28
- from flock.core.logging.logging import get_logger
29
-
30
- logger = get_logger("serialization.utils")
31
-
32
- # Remove this line to avoid circular import at module level
33
- # FlockRegistry = get_registry() # Get singleton instance
34
-
35
- # --- Serialization Helper ---
36
-
37
- # src/flock/util/hydrator.py (or import from serialization_utils)
38
-
39
-
40
- def _format_type_to_string(type_hint: type) -> str:
41
- """Converts a Python type object back into its string representation."""
42
- # This needs to handle various typing scenarios (List, Dict, Union, Optional, Literal, custom types)
43
- origin = typing.get_origin(type_hint)
44
- args = typing.get_args(type_hint)
45
-
46
- # Handle common cases first
47
- if origin is list or origin is list:
48
- if args:
49
- return f"list[{_format_type_to_string(args[0])}]"
50
- return "list[Any]" # Or just "list"
51
- elif origin is dict or origin is dict:
52
- if args and len(args) == 2:
53
- return f"dict[{_format_type_to_string(args[0])}, {_format_type_to_string(args[1])}]"
54
- return "dict[Any, Any]" # Or just "dict"
55
- elif origin is Union or origin is types.UnionType:
56
- # Handle Optional[T] as Union[T, NoneType]
57
- if len(args) == 2 and type(None) in args:
58
- inner_type = next(t for t in args if t is not type(None))
59
- return _format_type_to_string(inner_type)
60
- # return f"Optional[{_format_type_to_string(inner_type)}]"
61
- return (
62
- f"Union[{', '.join(_format_type_to_string(arg) for arg in args)}]"
63
- )
64
- elif origin is Literal:
65
- formatted_args = []
66
- for arg in args:
67
- if isinstance(arg, str):
68
- formatted_args.append(f"'{arg}'")
69
- else:
70
- formatted_args.append(str(arg))
71
- return f"Literal[{', '.join(formatted_args)}]"
72
- elif hasattr(
73
- type_hint, "__forward_arg__"
74
- ): # Handle ForwardRefs if necessary
75
- return type_hint.__forward_arg__
76
- elif hasattr(type_hint, "__name__"):
77
- # Handle custom types registered in registry (get preferred name)
78
- registry = get_registry()
79
- for (
80
- name,
81
- reg_type,
82
- ) in registry._types.items(): # Access internal for lookup
83
- if reg_type == type_hint:
84
- return name # Return registered name
85
- return type_hint.__name__ # Fallback to class name if not registered
86
- else:
87
- # Fallback for complex types or types not handled above
88
- type_repr = str(type_hint).replace("typing.", "") # Basic cleanup
89
- type_repr = str(type_hint).replace("| None", "")
90
- type_repr = type_repr.strip()
91
- logger.debug(
92
- f"Using fallback string representation for type: {type_repr}"
93
- )
94
- return type_repr
95
-
96
-
97
- def extract_identifiers_from_type_str(type_str: str) -> set[str]:
98
- """Extract all identifiers from a type annotation string using the AST."""
99
- tree = ast.parse(type_str, mode="eval")
100
- identifiers = set()
101
-
102
- class IdentifierVisitor(ast.NodeVisitor):
103
- def visit_Name(self, node):
104
- identifiers.add(node.id)
105
-
106
- def visit_Attribute(self, node):
107
- # Optionally support dotted names like mymodule.MyModel
108
- full_name = []
109
- while isinstance(node, ast.Attribute):
110
- full_name.append(node.attr)
111
- node = node.value
112
- if isinstance(node, ast.Name):
113
- full_name.append(node.id)
114
- identifiers.add(".".join(reversed(full_name)))
115
-
116
- IdentifierVisitor().visit(tree)
117
- return identifiers
118
-
119
-
120
- def resolve_name(name: str):
121
- """Resolve a name to a Python object from loaded modules."""
122
- # Try dotted names first
123
- parts = name.split(".")
124
- obj = None
125
-
126
- if len(parts) == 1:
127
- # Search globals and builtins
128
- if parts[0] in globals():
129
- return globals()[parts[0]]
130
- if parts[0] in builtins.__dict__:
131
- return builtins.__dict__[parts[0]]
132
- else:
133
- try:
134
- obj = sys.modules[parts[0]]
135
- for part in parts[1:]:
136
- obj = getattr(obj, part)
137
- return obj
138
- except Exception:
139
- return None
140
-
141
- # Try all loaded modules' symbols
142
- for module in list(sys.modules.values()):
143
- if module is None or not hasattr(module, "__dict__"):
144
- continue
145
- if parts[0] in module.__dict__:
146
- return module.__dict__[parts[0]]
147
-
148
- return None
149
-
150
-
151
- def extract_pydantic_models_from_type_string(
152
- type_str: str,
153
- ) -> list[type[BaseModel]]:
154
- identifiers = extract_identifiers_from_type_str(type_str)
155
- models = []
156
- for name in identifiers:
157
- resolved = resolve_name(name)
158
- if (
159
- isinstance(resolved, type)
160
- and issubclass(resolved, BaseModel)
161
- and resolved is not BaseModel
162
- ):
163
- models.append(resolved)
164
- return models
165
-
166
-
167
- def collect_pydantic_models(
168
- type_hint, seen: set[type[BaseModel]] | None = None
169
- ) -> set[type[BaseModel]]:
170
- if seen is None:
171
- seen = set()
172
-
173
- origin = get_origin(type_hint)
174
- args = get_args(type_hint)
175
-
176
- # Direct BaseModel
177
- if isinstance(type_hint, type) and issubclass(type_hint, BaseModel):
178
- seen.add(type_hint)
179
- return seen
180
-
181
- # For Unions, Lists, Dicts, Tuples, etc.
182
- if origin is not None:
183
- for arg in args:
184
- collect_pydantic_models(arg, seen)
185
-
186
- return seen
187
-
188
-
189
- def serialize_item(item: Any) -> Any:
190
- """Recursively prepares an item for serialization (e.g., to dict for YAML/JSON).
191
- Converts known callables to their path strings using FlockRegistry.
192
- Converts Pydantic models using model_dump.
193
- """
194
- # Import the registry lazily when needed
195
- from flock.core.flock_registry import get_registry
196
-
197
- FlockRegistry = get_registry()
198
-
199
- if callable(item) and not isinstance(item, type):
200
- path_str = FlockRegistry.get_callable_path_string(
201
- item
202
- ) # Use registry helper
203
- if path_str:
204
- # Store the simple name (last part of the path) for cleaner YAML/JSON
205
- simple_name = path_str.split(".")[-1]
206
- logger.debug(
207
- f"Serializing callable '{getattr(item, '__name__', 'unknown')}' as reference: '{simple_name}' (from path '{path_str}')"
208
- )
209
- return {
210
- "__callable_ref__": simple_name
211
- } # Use simple name convention
212
- else:
213
- # Handle unregistered callables (e.g., lambdas defined inline)
214
- # Option 1: Raise error (stricter)
215
- # raise ValueError(f"Cannot serialize unregistered callable: {getattr(item, '__name__', item)}")
216
- # Option 2: Store string representation with warning (more lenient)
217
- logger.warning(
218
- f"Cannot serialize unregistered callable {getattr(item, '__name__', item)}, storing as string."
219
- )
220
- return str(item)
221
- elif isinstance(item, BaseModel):
222
- logger.debug(
223
- f"Serializing Pydantic model instance: {item.__class__.__name__}"
224
- )
225
- serialized_dict = {}
226
- # Iterate through defined fields in the model
227
- fields_to_iterate = {}
228
- if hasattr(item, "model_fields"): # Pydantic v2
229
- fields_to_iterate = item.model_fields
230
-
231
- for field_name in fields_to_iterate:
232
- # Get the value *from the instance*
233
- try:
234
- value = getattr(item, field_name)
235
- if value is not None: # Exclude None values
236
- # Recursively serialize the field's value
237
- serialized_dict[field_name] = serialize_item(value)
238
- except AttributeError:
239
- # Should not happen if iterating model_fields/__fields__ but handle defensively
240
- logger.warning(
241
- f"Attribute '{field_name}' not found on instance of {item.__class__.__name__} during serialization."
242
- )
243
- return serialized_dict
244
- elif isinstance(item, Mapping):
245
- return {key: serialize_item(value) for key, value in item.items()}
246
- elif isinstance(item, Sequence) and not isinstance(item, str):
247
- return [serialize_item(sub_item) for sub_item in item]
248
- elif isinstance(
249
- item, type
250
- ): # Handle type objects themselves (e.g. if stored directly)
251
- type_name = FlockRegistry.get_component_type_name(
252
- item
253
- ) # Check components first
254
- if type_name:
255
- return {"__component_ref__": type_name}
256
- type_name = FlockRegistry._get_path_string(
257
- item
258
- ) # Check regular types/classes by path
259
- if type_name:
260
- return {"__type_ref__": type_name}
261
- logger.warning(
262
- f"Could not serialize type object {item}, storing as string."
263
- )
264
- return str(item)
265
- elif isinstance(item, Enum):
266
- return item.value
267
- else:
268
- # Return basic types as is
269
- return item
270
-
271
-
272
- # --- Deserialization Helper ---
273
-
274
-
275
- def deserialize_item(item: Any) -> Any:
276
- """Recursively processes a deserialized item (e.g., from YAML/JSON dict).
277
- Converts reference dicts back to actual callables or types using FlockRegistry.
278
- Handles nested lists and dicts.
279
- """
280
- # Import the registry lazily when needed
281
- from flock.core.flock_registry import get_registry
282
-
283
- FlockRegistry = get_registry()
284
-
285
- if isinstance(item, Mapping):
286
- if "__callable_ref__" in item and len(item) == 1:
287
- ref_name = item["__callable_ref__"]
288
- try:
289
- # The registry's get_callable needs to handle lookup by simple name OR full path
290
- # Or we assume get_callable handles finding the right function from the simple name
291
- resolved_callable = FlockRegistry.get_callable(ref_name)
292
- logger.debug(
293
- f"Deserialized callable reference '{ref_name}' to {resolved_callable}"
294
- )
295
- return resolved_callable
296
- except KeyError:
297
- logger.error(
298
- f"Callable reference '{ref_name}' not found during deserialization."
299
- )
300
- return None # Or raise?
301
- except Exception as e:
302
- logger.error(
303
- f"Error resolving callable reference '{ref_name}': {e}",
304
- exc_info=True,
305
- )
306
- return None
307
- elif "__component_ref__" in item and len(item) == 1:
308
- type_name = item["__component_ref__"]
309
- try:
310
- return FlockRegistry.get_component(type_name)
311
- except KeyError:
312
- logger.error(
313
- f"Component reference '{type_name}' not found during deserialization."
314
- )
315
- return None
316
- elif "__type_ref__" in item and len(item) == 1:
317
- type_name = item["__type_ref__"]
318
- try:
319
- # For general types, use get_type or fallback to dynamic import like get_callable
320
- # Using get_type for now, assuming it needs registration
321
- return FlockRegistry.get_type(type_name)
322
- except KeyError:
323
- # Attempt dynamic import as fallback if get_type fails (similar to get_callable)
324
- try:
325
- if "." not in type_name: # Builtins?
326
- mod = importlib.import_module("builtins")
327
- else:
328
- module_name, class_name = type_name.rsplit(".", 1)
329
- mod = importlib.import_module(module_name)
330
- type_obj = getattr(mod, class_name)
331
- if isinstance(type_obj, type):
332
- FlockRegistry.register_type(
333
- type_obj, type_name
334
- ) # Cache it
335
- return type_obj
336
- else:
337
- raise TypeError()
338
- except Exception:
339
- logger.error(
340
- f"Type reference '{type_name}' not found in registry or via dynamic import."
341
- )
342
- return None
343
-
344
- else:
345
- # Recursively deserialize dictionary values
346
- return {key: deserialize_item(value) for key, value in item.items()}
347
- elif isinstance(item, Sequence) and not isinstance(item, str):
348
- return [deserialize_item(sub_item) for sub_item in item]
349
- else:
350
- # Return basic types as is
351
- return item
352
-
353
-
354
- # --- Component Deserialization Helper ---
355
- def deserialize_component(
356
- data: dict | None, expected_base_type: type
357
- ) -> Any | None:
358
- """Deserializes a component (Module, Evaluator, Router) from its dict representation.
359
- Uses the 'type' field to find the correct class via FlockRegistry.
360
- """
361
- # Import the registry and COMPONENT_BASE_TYPES lazily when needed
362
- from flock.core.flock_registry import COMPONENT_BASE_TYPES, get_registry
363
-
364
- FlockRegistry = get_registry()
365
-
366
- if data is None:
367
- return None
368
- if not isinstance(data, dict):
369
- logger.error(
370
- f"Expected dict for component deserialization, got {type(data)}"
371
- )
372
- return None
373
-
374
- type_name = data.get(
375
- "type"
376
- ) # Assuming 'type' key holds the class name string
377
- if not type_name:
378
- logger.error(f"Component data missing 'type' field: {data}")
379
- return None
380
-
381
- try:
382
- ComponentClass = FlockRegistry.get_component(type_name) # Use registry
383
- # Optional: Keep the base type check
384
- if COMPONENT_BASE_TYPES and not issubclass(
385
- ComponentClass, expected_base_type
386
- ):
387
- raise TypeError(
388
- f"Deserialized class {type_name} is not a subclass of {expected_base_type.__name__}"
389
- )
390
-
391
- # Recursively deserialize the data *before* passing to Pydantic constructor
392
- # This handles nested callables/types within the component's config/data
393
- deserialized_data_for_init = {}
394
- for k, v in data.items():
395
- # Don't pass the 'type' field itself to the constructor if it matches class name
396
- if k == "type" and v == ComponentClass.__name__:
397
- continue
398
- deserialized_data_for_init[k] = deserialize_item(v)
399
-
400
- # Use Pydantic constructor directly. Assumes keys match field names.
401
- # from_dict could be added to components for more complex logic if needed.
402
- return ComponentClass(**deserialized_data_for_init)
403
-
404
- except (KeyError, TypeError, Exception) as e:
405
- logger.error(
406
- f"Failed to deserialize component of type '{type_name}': {e}",
407
- exc_info=True,
408
- )
409
- return None
@@ -1,223 +0,0 @@
1
- """Utility functions for handling file paths in Flock.
2
-
3
- This module provides utilities for working with file paths,
4
- especially for components that may be loaded from file system paths
5
- rather than module imports.
6
- """
7
-
8
- import importlib.util
9
- import inspect
10
- import os
11
- import sys
12
- from pathlib import Path
13
- from typing import Any
14
-
15
-
16
- def get_file_path(obj: Any) -> str | None:
17
- """Get the file path for a Python object.
18
-
19
- Args:
20
- obj: The object to get the file path for
21
-
22
- Returns:
23
- The file path if it can be determined, None otherwise
24
- """
25
- try:
26
- if inspect.ismodule(obj):
27
- return obj.__file__
28
- elif inspect.isclass(obj) or inspect.isfunction(obj):
29
- return inspect.getfile(obj)
30
- return None
31
- except (TypeError, ValueError):
32
- return None
33
-
34
-
35
- def normalize_path(path: str) -> str:
36
- """Normalize a path for consistent representation.
37
-
38
- Args:
39
- path: The path to normalize
40
-
41
- Returns:
42
- The normalized path
43
- """
44
- return os.path.normpath(path)
45
-
46
-
47
- def is_same_path(path1: str, path2: str) -> bool:
48
- """Check if two paths point to the same file.
49
-
50
- Args:
51
- path1: The first path
52
- path2: The second path
53
-
54
- Returns:
55
- True if the paths point to the same file, False otherwise
56
- """
57
- return os.path.normpath(os.path.abspath(path1)) == os.path.normpath(
58
- os.path.abspath(path2)
59
- )
60
-
61
-
62
- def get_relative_path(path: str, base_path: str | None = None) -> str:
63
- """Get a path relative to a base path.
64
-
65
- Args:
66
- path: The path to make relative
67
- base_path: The base path (defaults to current working directory)
68
-
69
- Returns:
70
- The relative path
71
- """
72
- if base_path is None:
73
- base_path = os.getcwd()
74
-
75
- return os.path.relpath(path, base_path)
76
-
77
-
78
- def load_class_from_file(file_path: str, class_name: str) -> type | None:
79
- """Load a class from a file.
80
-
81
- Args:
82
- file_path: The path to the file
83
- class_name: The name of the class to load
84
-
85
- Returns:
86
- The loaded class, or None if it could not be loaded
87
- """
88
- try:
89
- # Generate a unique module name to avoid conflicts
90
- module_name = f"flock_dynamic_import_{hash(file_path)}"
91
-
92
- # Create a spec for the module
93
- spec = importlib.util.spec_from_file_location(module_name, file_path)
94
- if not spec or not spec.loader:
95
- return None
96
-
97
- # Create and load the module
98
- module = importlib.util.module_from_spec(spec)
99
- sys.modules[module_name] = module
100
- spec.loader.exec_module(module)
101
-
102
- # Get the class from the module
103
- if not hasattr(module, class_name):
104
- return None
105
-
106
- return getattr(module, class_name)
107
- except Exception:
108
- return None
109
-
110
-
111
- def get_project_root() -> Path:
112
- """Get the project root directory.
113
-
114
- Returns:
115
- The project root path
116
- """
117
- # Try to find the directory containing pyproject.toml or setup.py
118
- current_dir = Path(os.getcwd())
119
-
120
- # Walk up the directory tree looking for project markers
121
- for path in [current_dir, *current_dir.parents]:
122
- if (path / "pyproject.toml").exists() or (path / "setup.py").exists():
123
- return path
124
-
125
- # Default to current directory if no project markers found
126
- return current_dir
127
-
128
-
129
- def component_path_to_file_path(component_path: str) -> str | None:
130
- """Convert a component path (module.ClassName) to a file path.
131
-
132
- Args:
133
- component_path: The component path in the form module.ClassName
134
-
135
- Returns:
136
- The file path if it can be determined, None otherwise
137
- """
138
- try:
139
- # Split into module path and class name
140
- if "." not in component_path:
141
- return None
142
-
143
- module_path, class_name = component_path.rsplit(".", 1)
144
-
145
- # Import the module
146
- module = importlib.import_module(module_path)
147
-
148
- # Get the file path
149
- if hasattr(module, "__file__"):
150
- return module.__file__
151
-
152
- return None
153
- except (ImportError, AttributeError):
154
- return None
155
-
156
-
157
- def file_path_to_component_path(file_path: str, class_name: str) -> str | None:
158
- """Convert a file path and class name to a component path (module.ClassName).
159
-
160
- This is approximate and may not work in all cases, especially for non-standard
161
- module structures.
162
-
163
- Args:
164
- file_path: The file path to the module
165
- class_name: The name of the class
166
-
167
- Returns:
168
- The component path if it can be determined, None otherwise
169
- """
170
- try:
171
- # Convert the file path to an absolute path
172
- abs_path = os.path.abspath(file_path)
173
-
174
- # Get the project root
175
- root = get_project_root()
176
-
177
- # Get the relative path from the project root
178
- rel_path = os.path.relpath(abs_path, root)
179
-
180
- # Convert to a module path
181
- module_path = os.path.splitext(rel_path)[0].replace(os.sep, ".")
182
-
183
- # Remove 'src.' prefix if present (common in Python projects)
184
- if module_path.startswith("src."):
185
- module_path = module_path[4:]
186
-
187
- # Combine with the class name
188
- return f"{module_path}.{class_name}"
189
- except Exception:
190
- return None
191
-
192
-
193
- def register_file_paths_in_registry(
194
- component_paths: dict[str, str], registry: Any | None = None
195
- ) -> bool:
196
- """Register file paths in the registry.
197
-
198
- Args:
199
- component_paths: Dictionary mapping component paths to file paths
200
- registry: The registry to register in (defaults to the global registry)
201
-
202
- Returns:
203
- True if all paths were registered, False otherwise
204
- """
205
- try:
206
- # Get the global registry if none provided
207
- if registry is None:
208
- from flock.core.flock_registry import get_registry
209
-
210
- registry = get_registry()
211
-
212
- # Initialize component_file_paths if needed
213
- if not hasattr(registry, "_component_file_paths"):
214
- registry._component_file_paths = {}
215
-
216
- # Register each path
217
- for component_name, file_path in component_paths.items():
218
- if component_name in registry._components:
219
- registry._component_file_paths[component_name] = file_path
220
-
221
- return True
222
- except Exception:
223
- return False