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
@@ -14,13 +14,12 @@ import logging
14
14
  import sys
15
15
  from typing import Literal
16
16
 
17
- from opentelemetry import trace
18
-
19
17
  # Always import Temporal workflow (since it's part of the project)
20
- from temporalio import workflow
18
+ # from temporalio import workflow
19
+ # with workflow.unsafe.imports_passed_through():
20
+ from loguru import logger as loguru_logger
21
+ from opentelemetry import trace
21
22
 
22
- with workflow.unsafe.imports_passed_through():
23
- from loguru import logger as loguru_logger
24
23
 
25
24
  # ENABLED_FLOCK_LOGGER_LEVELS constant removed
26
25
 
@@ -42,13 +41,14 @@ def in_workflow_context() -> bool:
42
41
  It does this by attempting to call workflow.info() and returning True
43
42
  if successful. Otherwise, it returns False.
44
43
  """
45
- try:
46
- workflow.logger.debug("Checking if in workflow context...")
47
- # loguru_logger.debug("Checking if in workflow context...")
48
- # This call will succeed only if we're in a workflow context.
49
- return bool(hasattr(workflow.info(), "is_replaying"))
50
- except Exception:
51
- return False
44
+ return False
45
+ # try:
46
+ # workflow.logger.debug("Checking if in workflow context...")
47
+ # # loguru_logger.debug("Checking if in workflow context...")
48
+ # # This call will succeed only if we're in a workflow context.
49
+ # return bool(hasattr(workflow.info(), "is_replaying"))
50
+ # except Exception:
51
+ # return False
52
52
 
53
53
 
54
54
  def get_current_trace_id() -> str:
@@ -108,7 +108,7 @@ COLOR_MAP = {
108
108
 
109
109
  LOGGERS = [
110
110
  "flock", # Core Flock orchestration
111
- "flock.api", # Flock API specific logs
111
+ "flock.api", # Flock API specific logs
112
112
  "agent", # General agent operations
113
113
  "context", # Context management
114
114
  "registry", # Unified registry operations (new)
@@ -154,6 +154,7 @@ def color_for_category(category: str) -> str:
154
154
  if category in COLOR_MAP:
155
155
  return COLOR_MAP[category]
156
156
  parts = category.split(".")
157
+ # Try progressively shorter parent categories
157
158
  for i in range(len(parts) - 1, 0, -1):
158
159
  parent_category = ".".join(parts[:i])
159
160
  if parent_category in COLOR_MAP:
@@ -176,9 +177,7 @@ def custom_format(record):
176
177
  # MAX_LENGTH = 500 # Example value
177
178
  if len(message) > MAX_LENGTH:
178
179
  truncated_chars = len(message) - MAX_LENGTH
179
- message = (
180
- message[:MAX_LENGTH] + f"<yellow>...+({truncated_chars} chars)</yellow>"
181
- )
180
+ message = message[:MAX_LENGTH] + f"<yellow>...+({truncated_chars} chars)</yellow>"
182
181
 
183
182
  # Determine if category needs bolding (can refine this logic)
184
183
  needs_bold = category in BOLD_CATEGORIES
@@ -246,7 +245,6 @@ class PrintAndFlushSink:
246
245
 
247
246
  Already flushed on every write call.
248
247
  """
249
- pass
250
248
 
251
249
 
252
250
  # Configure Loguru for non-workflow (local/worker) contexts.
@@ -263,7 +261,9 @@ logging.basicConfig(level=LOG_LEVELS["ERROR"]) # Default to ERROR level for fal
263
261
  # loguru_logger.add("logs/flock.log", rotation="100 MB", retention="30 days", level="DEBUG")
264
262
 
265
263
 
266
- def get_default_severity(level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"] | int) -> int:
264
+ def get_default_severity(
265
+ level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"] | int,
266
+ ) -> int:
267
267
  """Get the default severity for a given level."""
268
268
  if isinstance(level, str):
269
269
  level_str = level.upper()
@@ -271,9 +271,17 @@ def get_default_severity(level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CR
271
271
  return level
272
272
 
273
273
 
274
- def configure_logging(flock_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"] | int,
275
- external_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"] | int,
276
- specific_levels: dict[str, Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"] | int] | None = None) -> None:
274
+ def configure_logging(
275
+ flock_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"]
276
+ | int,
277
+ external_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"]
278
+ | int,
279
+ specific_levels: dict[
280
+ str,
281
+ Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NO_LOGS", "SUCCESS"] | int,
282
+ ]
283
+ | None = None,
284
+ ) -> None:
277
285
  """Configure both external and internal Flock logging systems.
278
286
 
279
287
  Args:
@@ -282,19 +290,21 @@ def configure_logging(flock_level: Literal["DEBUG", "INFO", "WARNING", "ERROR",
282
290
  specific_levels (dict[str, str | int] | None, optional): A dictionary mapping
283
291
  logger names to their specific logging levels. Defaults to None.
284
292
  """
285
- # Get default severity
293
+ global _DEFAULT_FLOCK_SEVERITY, _SPECIFIC_SEVERITIES
286
294
 
295
+ # Get default severity
287
296
  external_severity = get_default_severity(external_level)
288
297
  logging.basicConfig(level=external_severity)
289
298
 
290
-
291
299
  flock_severity = get_default_severity(flock_level)
300
+ _DEFAULT_FLOCK_SEVERITY = flock_severity # Store for future loggers
292
301
 
293
302
  specific_severities = {}
294
303
  if specific_levels:
295
304
  for name, logger_level in specific_levels.items():
296
305
  severity = get_default_severity(logger_level)
297
306
  specific_severities[name] = severity
307
+ _SPECIFIC_SEVERITIES[name] = severity # Store for future loggers
298
308
 
299
309
  # Apply to all cached loggers
300
310
  for logger_name, log_instance in _LOGGER_CACHE.items():
@@ -305,28 +315,26 @@ def configure_logging(flock_level: Literal["DEBUG", "INFO", "WARNING", "ERROR",
305
315
  log_instance.min_level_severity = target_severity
306
316
 
307
317
 
308
-
309
-
310
318
  # Define a dummy logger that does nothing
311
319
  class DummyLogger:
312
320
  """A dummy logger that does nothing when called."""
313
321
 
314
- def debug(self, *args, **kwargs): # noqa: D102
322
+ def debug(self, *args, **kwargs):
315
323
  pass
316
324
 
317
- def info(self, *args, **kwargs): # noqa: D102
325
+ def info(self, *args, **kwargs):
318
326
  pass
319
327
 
320
- def warning(self, *args, **kwargs): # noqa: D102
328
+ def warning(self, *args, **kwargs):
321
329
  pass
322
330
 
323
- def error(self, *args, **kwargs): # noqa: D102
331
+ def error(self, *args, **kwargs):
324
332
  pass
325
333
 
326
- def exception(self, *args, **kwargs): # noqa: D102
334
+ def exception(self, *args, **kwargs):
327
335
  pass
328
336
 
329
- def success(self, *args, **kwargs): # noqa: D102
337
+ def success(self, *args, **kwargs):
330
338
  pass
331
339
 
332
340
 
@@ -356,9 +364,9 @@ class FlockLogger:
356
364
  self.min_level_severity = initial_min_level_severity
357
365
 
358
366
  def _get_logger(self):
359
- if in_workflow_context():
360
- # Use Temporal's workflow.logger inside a workflow context.
361
- return workflow.logger
367
+ # if in_workflow_context():
368
+ # # Use Temporal's workflow.logger inside a workflow context.
369
+ # return workflow.logger
362
370
  # Bind our logger with category and trace_id
363
371
  return loguru_logger.bind(
364
372
  name=self.name,
@@ -370,9 +378,7 @@ class FlockLogger:
370
378
  """Truncate a message if it exceeds max_length and add truncation indicator."""
371
379
  if len(message) > max_length:
372
380
  truncated_chars = len(message) - max_length
373
- return (
374
- message[:max_length] + f"...<yellow>+({truncated_chars} chars)</yellow>"
375
- )
381
+ return message[:max_length] + f"...<yellow>+({truncated_chars} chars)</yellow>"
376
382
  return message
377
383
 
378
384
  def debug(
@@ -384,8 +390,10 @@ class FlockLogger:
384
390
  **kwargs,
385
391
  ) -> None:
386
392
  current_method_severity = LOG_LEVELS["DEBUG"]
387
- if self.min_level_severity == LOG_LEVELS["NO_LOGS"] or \
388
- current_method_severity < self.min_level_severity:
393
+ if (
394
+ self.min_level_severity == LOG_LEVELS["NO_LOGS"]
395
+ or current_method_severity < self.min_level_severity
396
+ ):
389
397
  return
390
398
  """Debug a message.
391
399
 
@@ -406,8 +414,10 @@ class FlockLogger:
406
414
  **kwargs,
407
415
  ) -> None:
408
416
  current_method_severity = LOG_LEVELS["INFO"]
409
- if self.min_level_severity == LOG_LEVELS["NO_LOGS"] or \
410
- current_method_severity < self.min_level_severity:
417
+ if (
418
+ self.min_level_severity == LOG_LEVELS["NO_LOGS"]
419
+ or current_method_severity < self.min_level_severity
420
+ ):
411
421
  return
412
422
  """Info a message.
413
423
 
@@ -428,8 +438,10 @@ class FlockLogger:
428
438
  **kwargs,
429
439
  ) -> None:
430
440
  current_method_severity = LOG_LEVELS["WARNING"]
431
- if self.min_level_severity == LOG_LEVELS["NO_LOGS"] or \
432
- current_method_severity < self.min_level_severity:
441
+ if (
442
+ self.min_level_severity == LOG_LEVELS["NO_LOGS"]
443
+ or current_method_severity < self.min_level_severity
444
+ ):
433
445
  return
434
446
  """Warning a message.
435
447
 
@@ -450,8 +462,10 @@ class FlockLogger:
450
462
  **kwargs,
451
463
  ) -> None:
452
464
  current_method_severity = LOG_LEVELS["ERROR"]
453
- if self.min_level_severity == LOG_LEVELS["NO_LOGS"] or \
454
- current_method_severity < self.min_level_severity:
465
+ if (
466
+ self.min_level_severity == LOG_LEVELS["NO_LOGS"]
467
+ or current_method_severity < self.min_level_severity
468
+ ):
455
469
  return
456
470
  """Error a message.
457
471
 
@@ -471,9 +485,11 @@ class FlockLogger:
471
485
  max_length: int = MAX_LENGTH,
472
486
  **kwargs,
473
487
  ) -> None:
474
- current_method_severity = LOG_LEVELS["ERROR"] # Exception implies ERROR level
475
- if self.min_level_severity == LOG_LEVELS["NO_LOGS"] or \
476
- current_method_severity < self.min_level_severity:
488
+ current_method_severity = LOG_LEVELS["ERROR"] # Exception implies ERROR level
489
+ if (
490
+ self.min_level_severity == LOG_LEVELS["NO_LOGS"]
491
+ or current_method_severity < self.min_level_severity
492
+ ):
477
493
  return
478
494
  """Exception a message.
479
495
 
@@ -494,8 +510,10 @@ class FlockLogger:
494
510
  **kwargs,
495
511
  ) -> None:
496
512
  current_method_severity = LOG_LEVELS["SUCCESS"]
497
- if self.min_level_severity == LOG_LEVELS["NO_LOGS"] or \
498
- current_method_severity < self.min_level_severity:
513
+ if (
514
+ self.min_level_severity == LOG_LEVELS["NO_LOGS"]
515
+ or current_method_severity < self.min_level_severity
516
+ ):
499
517
  return
500
518
  """Success a message.
501
519
 
@@ -509,21 +527,22 @@ class FlockLogger:
509
527
 
510
528
 
511
529
  _LOGGER_CACHE: dict[str, FlockLogger] = {}
530
+ _DEFAULT_FLOCK_SEVERITY: int = LOG_LEVELS["ERROR"]
531
+ _SPECIFIC_SEVERITIES: dict[str, int] = {}
512
532
 
513
533
 
514
534
  def get_logger(name: str = "flock") -> FlockLogger:
515
535
  """Return a cached FlockLogger instance for the given name.
516
536
 
517
- If the logger doesn't exist, it is created with 'enable_logging' set to False
518
- by default (i.e., errors-only mode). Its state can then be changed by calling
519
- the `configure_logging()` function.
537
+ If the logger doesn't exist, it is created using the configured severity level
538
+ from configure_logging() (default: ERROR). Respects specific_levels if configured.
520
539
  If a logger with the given name already exists in the cache, its 'min_level_severity'
521
540
  state is NOT modified by this function; it's simply returned.
522
541
  """
523
542
  if name not in _LOGGER_CACHE:
524
- # New loggers default to errors-only (min_level_severity = ERROR_SEVERITY)
525
- # until explicitly configured by configure_logging()
526
- _LOGGER_CACHE[name] = FlockLogger(name, LOG_LEVELS["ERROR"])
543
+ # Check if there's a specific severity configured for this logger
544
+ severity = _SPECIFIC_SEVERITIES.get(name, _DEFAULT_FLOCK_SEVERITY)
545
+ _LOGGER_CACHE[name] = FlockLogger(name, severity)
527
546
  # The min_level_severity state of existing or newly created loggers
528
547
  # should be managed by the configure_logging() function.
529
548
  return _LOGGER_CACHE[name]
@@ -543,15 +562,13 @@ def truncate_for_logging(obj, max_item_length=100, max_items=10):
543
562
  """Truncate large data structures for logging purposes."""
544
563
  if isinstance(obj, str) and len(obj) > max_item_length:
545
564
  return obj[:max_item_length] + f"... ({len(obj) - max_item_length} more chars)"
546
- elif isinstance(obj, dict):
565
+ if isinstance(obj, dict):
547
566
  if len(obj) > max_items:
548
567
  return {
549
- k: truncate_for_logging(v)
550
- for i, (k, v) in enumerate(obj.items())
551
- if i < max_items
568
+ k: truncate_for_logging(v) for i, (k, v) in enumerate(obj.items()) if i < max_items
552
569
  }
553
570
  return {k: truncate_for_logging(v) for k, v in obj.items()}
554
- elif isinstance(obj, list):
571
+ if isinstance(obj, list):
555
572
  if len(obj) > max_items:
556
573
  return [truncate_for_logging(item) for item in obj[:max_items]] + [
557
574
  f"... ({len(obj) - max_items} more items)"
@@ -1,24 +1,28 @@
1
1
  """This module sets up OpenTelemetry tracing for a service."""
2
2
 
3
+ import os
3
4
  import sys
4
5
 
5
6
  from opentelemetry import trace
6
7
  from opentelemetry.sdk.resources import Resource
7
8
  from opentelemetry.sdk.trace import TracerProvider
8
9
  from opentelemetry.sdk.trace.export import SimpleSpanProcessor
9
- from temporalio import workflow
10
10
 
11
- from flock.core.logging.span_middleware.baggage_span_processor import (
11
+ # from temporalio import workflow
12
+ from flock.logging.span_middleware.baggage_span_processor import (
12
13
  BaggageAttributeSpanProcessor,
13
14
  )
15
+ from flock.logging.telemetry_exporter.duckdb_exporter import (
16
+ DuckDBSpanExporter,
17
+ )
14
18
 
15
- with workflow.unsafe.imports_passed_through():
16
- from flock.core.logging.telemetry_exporter.file_exporter import (
17
- FileSpanExporter,
18
- )
19
- from flock.core.logging.telemetry_exporter.sqlite_exporter import (
20
- SqliteTelemetryExporter,
21
- )
19
+ # with workflow.unsafe.imports_passed_through():
20
+ from flock.logging.telemetry_exporter.file_exporter import (
21
+ FileSpanExporter,
22
+ )
23
+ from flock.logging.telemetry_exporter.sqlite_exporter import (
24
+ SqliteTelemetryExporter,
25
+ )
22
26
 
23
27
 
24
28
  class TelemetryConfig:
@@ -39,9 +43,12 @@ class TelemetryConfig:
39
43
  local_logging_dir: str | None = None,
40
44
  file_export_name: str | None = None,
41
45
  sqlite_db_name: str | None = None,
46
+ duckdb_name: str | None = None,
47
+ duckdb_ttl_days: int | None = None,
42
48
  enable_jaeger: bool = True,
43
49
  enable_file: bool = True,
44
50
  enable_sql: bool = True,
51
+ enable_duckdb: bool = True,
45
52
  enable_otlp: bool = True,
46
53
  otlp_protocol: str = "grpc",
47
54
  otlp_endpoint: str = "http://localhost:4317",
@@ -52,6 +59,7 @@ class TelemetryConfig:
52
59
  :param jaeger_endpoint: The Jaeger collector gRPC endpoint (e.g., "localhost:14250").
53
60
  :param file_export_path: If provided, spans will be written to this file.
54
61
  :param sqlite_db_path: If provided, spans will be stored in this SQLite DB.
62
+ :param duckdb_ttl_days: Delete traces older than this many days (default: None = keep forever).
55
63
  :param batch_processor_options: Dict of options for BatchSpanProcessor (e.g., {"max_export_batch_size": 10}).
56
64
  """
57
65
  self.service_name = service_name
@@ -59,18 +67,50 @@ class TelemetryConfig:
59
67
  self.jaeger_transport = jaeger_transport
60
68
  self.file_export_name = file_export_name
61
69
  self.sqlite_db_name = sqlite_db_name
70
+ self.duckdb_name = duckdb_name
71
+ self.duckdb_ttl_days = duckdb_ttl_days
62
72
  self.local_logging_dir = local_logging_dir
63
73
  self.batch_processor_options = batch_processor_options or {}
64
74
  self.enable_jaeger = enable_jaeger
65
75
  self.enable_file = enable_file
66
76
  self.enable_sql = enable_sql
77
+ self.enable_duckdb = enable_duckdb
67
78
  self.enable_otlp = enable_otlp
68
79
  self.otlp_protocol = otlp_protocol
69
80
  self.otlp_endpoint = otlp_endpoint
70
81
  self.global_tracer = None
82
+ self._configured: bool = False
83
+
84
+ def _should_setup(self) -> bool:
85
+ # Respect explicit disable flag for tests and minimal setups
86
+ if os.environ.get("FLOCK_DISABLE_TELEMETRY_AUTOSETUP", "").lower() in {
87
+ "1",
88
+ "true",
89
+ "yes",
90
+ "on",
91
+ }:
92
+ return False
93
+ try:
94
+ # If a provider is already installed (typically by user/tests), don't override it
95
+ from opentelemetry.sdk.trace import (
96
+ TracerProvider as SDKTracerProvider, # type: ignore
97
+ )
98
+
99
+ current = trace.get_tracer_provider()
100
+ if isinstance(current, SDKTracerProvider):
101
+ return False
102
+ except Exception:
103
+ # If SDK isn't available or introspection fails, fall back to enabling
104
+ pass
105
+ return True
71
106
 
72
107
  def setup_tracing(self):
73
108
  """Set up OpenTelemetry tracing with the specified exporters."""
109
+ if self._configured:
110
+ return
111
+ if not self._should_setup():
112
+ return
113
+
74
114
  # Create a Resource with the service name.
75
115
  resource = Resource(attributes={"service.name": self.service_name})
76
116
  provider = TracerProvider(resource=resource)
@@ -97,13 +137,10 @@ class TelemetryConfig:
97
137
  collector_endpoint=self.jaeger_endpoint,
98
138
  )
99
139
  else:
100
- raise ValueError(
101
- "Invalid JAEGER_TRANSPORT specified. Use 'grpc' or 'http'."
102
- )
140
+ raise ValueError("Invalid JAEGER_TRANSPORT specified. Use 'grpc' or 'http'.")
103
141
 
104
142
  span_processors.append(SimpleSpanProcessor(jaeger_exporter))
105
143
 
106
-
107
144
  if self.enable_otlp:
108
145
  if self.otlp_protocol == "grpc":
109
146
  from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
@@ -131,18 +168,21 @@ class TelemetryConfig:
131
168
 
132
169
  # If a file path is provided, add the custom file exporter.
133
170
  if self.file_export_name and self.enable_file:
134
- file_exporter = FileSpanExporter(
135
- self.local_logging_dir, self.file_export_name
136
- )
171
+ file_exporter = FileSpanExporter(self.local_logging_dir, self.file_export_name)
137
172
  span_processors.append(SimpleSpanProcessor(file_exporter))
138
173
 
139
174
  # If a SQLite database path is provided, ensure the DB exists and add the SQLite exporter.
140
175
  if self.sqlite_db_name and self.enable_sql:
141
- sqlite_exporter = SqliteTelemetryExporter(
142
- self.local_logging_dir, self.sqlite_db_name
143
- )
176
+ sqlite_exporter = SqliteTelemetryExporter(self.local_logging_dir, self.sqlite_db_name)
144
177
  span_processors.append(SimpleSpanProcessor(sqlite_exporter))
145
178
 
179
+ # If a DuckDB database path is provided, add the DuckDB exporter.
180
+ if self.duckdb_name and self.enable_duckdb:
181
+ duckdb_exporter = DuckDBSpanExporter(
182
+ self.local_logging_dir, self.duckdb_name, ttl_days=self.duckdb_ttl_days
183
+ )
184
+ span_processors.append(SimpleSpanProcessor(duckdb_exporter))
185
+
146
186
  # Register all span processors with the provider.
147
187
  for processor in span_processors:
148
188
  provider.add_span_processor(processor)
@@ -150,8 +190,9 @@ class TelemetryConfig:
150
190
  provider.add_span_processor(
151
191
  BaggageAttributeSpanProcessor(baggage_keys=["session_id", "run_id"])
152
192
  )
153
- # self.global_tracer = trace.get_tracer("flock")
193
+ self.global_tracer = trace.get_tracer("flock")
154
194
  sys.excepthook = self.log_exception_to_otel
195
+ self._configured = True
155
196
 
156
197
  def log_exception_to_otel(self, exc_type, exc_value, exc_traceback):
157
198
  """Log unhandled exceptions to OpenTelemetry."""
@@ -160,11 +201,10 @@ class TelemetryConfig:
160
201
  sys.__excepthook__(exc_type, exc_value, exc_traceback)
161
202
  return
162
203
 
204
+ if not self.global_tracer:
205
+ return
206
+
163
207
  # Use OpenTelemetry to record the exception
164
- with self.global_tracer.start_as_current_span(
165
- "UnhandledException"
166
- ) as span:
208
+ with self.global_tracer.start_as_current_span("UnhandledException") as span:
167
209
  span.record_exception(exc_value)
168
- span.set_status(
169
- trace.Status(trace.StatusCode.ERROR, str(exc_value))
170
- )
210
+ span.set_status(trace.Status(trace.StatusCode.ERROR, str(exc_value)))
@@ -25,14 +25,14 @@ class TelemetryExporter(SpanExporter, ABC):
25
25
  self.shutdown()
26
26
 
27
27
  @abstractmethod
28
- def export(self, spans) -> SpanExportResult | None:
28
+ def export(self, spans) -> SpanExportResult: # type: ignore[override]
29
29
  """Export spans to the configured backend.
30
30
 
31
31
  To be implemented by subclasses.
32
+ May return SUCCESS, FAILURE, or None (handled by _export wrapper).
32
33
  """
33
34
  raise NotImplementedError("Subclasses must implement the export method")
34
35
 
35
36
  @abstractmethod
36
37
  def shutdown(self):
37
38
  """Cleanup resources, if any. Optional for subclasses."""
38
- pass