flock-core 0.1.2__py3-none-any.whl → 0.2.2__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 (407) hide show
  1. flock/__init__.py +1 -4
  2. flock/core/__init__.py +1 -7
  3. flock/core/context/context.py +182 -0
  4. flock/core/context/context_manager.py +34 -0
  5. flock/core/{context_vars.py → context/context_vars.py} +8 -6
  6. flock/core/execution/local_executor.py +27 -0
  7. flock/core/execution/temporal_executor.py +56 -0
  8. flock/core/flock.py +232 -208
  9. flock/core/flock_agent.py +574 -0
  10. flock/core/logging/__init__.py +2 -18
  11. flock/core/logging/formatters/base_formatter.py +36 -0
  12. flock/core/logging/formatters/formatter_factory.py +38 -0
  13. flock/core/logging/formatters/pprint_formatter.py +18 -0
  14. flock/core/logging/formatters/rich_formatters.py +132 -0
  15. flock/core/logging/formatters/theme_builder.py +480 -0
  16. flock/core/logging/formatters/themed_formatter.py +442 -0
  17. flock/core/logging/logging.py +141 -0
  18. flock/core/logging/telemetry.py +21 -0
  19. flock/core/logging/trace_and_logged.py +55 -0
  20. flock/core/mixin/dspy_integration.py +197 -0
  21. flock/core/mixin/prompt_parser.py +125 -0
  22. flock/core/registry/agent_registry.py +118 -0
  23. flock/core/tools/basic_tools.py +296 -98
  24. flock/core/tools/dev_tools/github.py +190 -0
  25. flock/core/util/cli_helper.py +25 -0
  26. flock/core/util/input_resolver.py +156 -0
  27. flock/core/util/serializable.py +93 -0
  28. flock/themes/3024-day.toml +39 -0
  29. flock/themes/3024-night.toml +77 -0
  30. flock/themes/aardvark-blue.toml +77 -0
  31. flock/themes/abernathy.toml +77 -0
  32. flock/themes/adventure.toml +77 -0
  33. flock/themes/adventuretime.toml +77 -0
  34. flock/themes/afterglow.toml +77 -0
  35. flock/themes/alabaster.toml +77 -0
  36. flock/themes/alienblood.toml +77 -0
  37. flock/themes/andromeda.toml +77 -0
  38. flock/themes/apple-classic.toml +77 -0
  39. flock/themes/apple-system-colors.toml +77 -0
  40. flock/themes/arcoiris.toml +77 -0
  41. flock/themes/argonaut copy.toml +77 -0
  42. flock/themes/argonaut.toml +39 -0
  43. flock/themes/arthur.toml +77 -0
  44. flock/themes/ateliersulphurpool.toml +77 -0
  45. flock/themes/atom.toml +38 -0
  46. flock/themes/atom_test.toml +65 -0
  47. flock/themes/atomonelight.toml +77 -0
  48. flock/themes/aurora.toml +77 -0
  49. flock/themes/ayu copy.toml +77 -0
  50. flock/themes/ayu-light.toml +77 -0
  51. flock/themes/ayu-mirage.toml +77 -0
  52. flock/themes/ayu.toml +39 -0
  53. flock/themes/banana-blueberry.toml +77 -0
  54. flock/themes/batman.toml +77 -0
  55. flock/themes/belafonte-day.toml +77 -0
  56. flock/themes/belafonte-night.toml +77 -0
  57. flock/themes/birdsofparadise.toml +77 -0
  58. flock/themes/blazer.toml +77 -0
  59. flock/themes/blue-matrix.toml +77 -0
  60. flock/themes/blueberrypie.toml +77 -0
  61. flock/themes/bluedolphin.toml +77 -0
  62. flock/themes/blulocodark.toml +77 -0
  63. flock/themes/blulocolight.toml +77 -0
  64. flock/themes/borland.toml +77 -0
  65. flock/themes/breeze.toml +77 -0
  66. flock/themes/bright-lights.toml +77 -0
  67. flock/themes/broadcast.toml +77 -0
  68. flock/themes/brogrammer.toml +77 -0
  69. flock/themes/builtin-dark.toml +77 -0
  70. flock/themes/builtin-light.toml +77 -0
  71. flock/themes/builtin-pastel-dark.toml +77 -0
  72. flock/themes/builtin-solarized-dark.toml +77 -0
  73. flock/themes/builtin-solarized-light.toml +77 -0
  74. flock/themes/builtin-tango-dark.toml +77 -0
  75. flock/themes/builtin-tango-light.toml +77 -0
  76. flock/themes/c64.toml +77 -0
  77. flock/themes/calamity.toml +77 -0
  78. flock/themes/catppuccin-frappe.toml +77 -0
  79. flock/themes/catppuccin-latte.toml +77 -0
  80. flock/themes/catppuccin-macchiato.toml +77 -0
  81. flock/themes/catppuccin-mocha.toml +77 -0
  82. flock/themes/cga.toml +77 -0
  83. flock/themes/chalk.toml +77 -0
  84. flock/themes/chalkboard.toml +77 -0
  85. flock/themes/challengerdeep.toml +77 -0
  86. flock/themes/chester.toml +77 -0
  87. flock/themes/ciapre.toml +77 -0
  88. flock/themes/clrs.toml +77 -0
  89. flock/themes/cobalt-neon.toml +77 -0
  90. flock/themes/cobalt2.toml +77 -0
  91. flock/themes/coffee-theme.toml +77 -0
  92. flock/themes/crayonponyfish.toml +77 -0
  93. flock/themes/cutiepro.toml +77 -0
  94. flock/themes/cyberdyne.toml +77 -0
  95. flock/themes/cyberpunk.toml +77 -0
  96. flock/themes/cyberpunkscarletprotocol.toml +77 -0
  97. flock/themes/dark+.toml +77 -0
  98. flock/themes/dark-pastel.toml +77 -0
  99. flock/themes/darkermatrix.toml +77 -0
  100. flock/themes/darkmatrix.toml +77 -0
  101. flock/themes/darkside.toml +77 -0
  102. flock/themes/dayfox.toml +77 -0
  103. flock/themes/deep.toml +77 -0
  104. flock/themes/desert.toml +77 -0
  105. flock/themes/dimidium.toml +77 -0
  106. flock/themes/dimmedmonokai.toml +77 -0
  107. flock/themes/django.toml +77 -0
  108. flock/themes/djangorebornagain.toml +77 -0
  109. flock/themes/djangosmooth.toml +77 -0
  110. flock/themes/doom-peacock.toml +77 -0
  111. flock/themes/doomone.toml +77 -0
  112. flock/themes/dotgov.toml +77 -0
  113. flock/themes/dracula+.toml +77 -0
  114. flock/themes/dracula.toml +77 -0
  115. flock/themes/duckbones.toml +77 -0
  116. flock/themes/duotone-dark.toml +77 -0
  117. flock/themes/earthsong.toml +77 -0
  118. flock/themes/elemental.toml +77 -0
  119. flock/themes/elementary.toml +77 -0
  120. flock/themes/encom.toml +77 -0
  121. flock/themes/espresso-libre.toml +77 -0
  122. flock/themes/espresso.toml +77 -0
  123. flock/themes/everblush.toml +77 -0
  124. flock/themes/fahrenheit.toml +77 -0
  125. flock/themes/fairyfloss.toml +77 -0
  126. flock/themes/farmhouse-dark.toml +77 -0
  127. flock/themes/farmhouse-light.toml +77 -0
  128. flock/themes/fideloper.toml +77 -0
  129. flock/themes/firefly-traditional.toml +77 -0
  130. flock/themes/firefoxdev.toml +77 -0
  131. flock/themes/firewatch.toml +77 -0
  132. flock/themes/fishtank.toml +77 -0
  133. flock/themes/flat.toml +77 -0
  134. flock/themes/flatland.toml +77 -0
  135. flock/themes/flexoki-dark.toml +77 -0
  136. flock/themes/flexoki-light.toml +77 -0
  137. flock/themes/floraverse.toml +77 -0
  138. flock/themes/forestblue.toml +77 -0
  139. flock/themes/framer.toml +77 -0
  140. flock/themes/frontenddelight.toml +77 -0
  141. flock/themes/funforrest.toml +77 -0
  142. flock/themes/galaxy.toml +77 -0
  143. flock/themes/galizur.toml +77 -0
  144. flock/themes/github-dark.toml +77 -0
  145. flock/themes/github.toml +77 -0
  146. flock/themes/glacier.toml +77 -0
  147. flock/themes/grape.toml +77 -0
  148. flock/themes/grass.toml +77 -0
  149. flock/themes/grey-green.toml +77 -0
  150. flock/themes/gruber-darker.toml +77 -0
  151. flock/themes/gruvboxdark.toml +77 -0
  152. flock/themes/gruvboxdarkhard.toml +77 -0
  153. flock/themes/gruvboxlight.toml +77 -0
  154. flock/themes/guezwhoz.toml +77 -0
  155. flock/themes/hacktober.toml +77 -0
  156. flock/themes/hardcore.toml +77 -0
  157. flock/themes/harper.toml +77 -0
  158. flock/themes/hax0r-blue.toml +77 -0
  159. flock/themes/hax0r-gr33n.toml +77 -0
  160. flock/themes/hax0r-r3d.toml +77 -0
  161. flock/themes/highway.toml +77 -0
  162. flock/themes/hipster-green.toml +77 -0
  163. flock/themes/hivacruz.toml +77 -0
  164. flock/themes/homebrew.toml +77 -0
  165. flock/themes/hopscotch.256.toml +77 -0
  166. flock/themes/hopscotch.toml +77 -0
  167. flock/themes/hurtado.toml +77 -0
  168. flock/themes/hybrid.toml +77 -0
  169. flock/themes/ic-green-ppl.toml +77 -0
  170. flock/themes/ic-orange-ppl.toml +77 -0
  171. flock/themes/iceberg-dark.toml +77 -0
  172. flock/themes/iceberg-light.toml +77 -0
  173. flock/themes/idea.toml +77 -0
  174. flock/themes/idletoes.toml +77 -0
  175. flock/themes/ir-black.toml +77 -0
  176. flock/themes/iterm2-dark-background.toml +77 -0
  177. flock/themes/iterm2-default.toml +77 -0
  178. flock/themes/iterm2-light-background.toml +77 -0
  179. flock/themes/iterm2-pastel-dark-background.toml +77 -0
  180. flock/themes/iterm2-smoooooth.toml +77 -0
  181. flock/themes/iterm2-solarized-dark.toml +77 -0
  182. flock/themes/iterm2-solarized-light.toml +77 -0
  183. flock/themes/iterm2-tango-dark.toml +77 -0
  184. flock/themes/iterm2-tango-light.toml +77 -0
  185. flock/themes/jackie-brown.toml +77 -0
  186. flock/themes/japanesque.toml +77 -0
  187. flock/themes/jellybeans.toml +77 -0
  188. flock/themes/jetbrains-darcula.toml +77 -0
  189. flock/themes/jubi.toml +77 -0
  190. flock/themes/kanagawabones.toml +77 -0
  191. flock/themes/kibble.toml +77 -0
  192. flock/themes/kolorit.toml +77 -0
  193. flock/themes/konsolas.toml +77 -0
  194. flock/themes/kurokula.toml +77 -0
  195. flock/themes/lab-fox.toml +77 -0
  196. flock/themes/laser.toml +77 -0
  197. flock/themes/later-this-evening.toml +77 -0
  198. flock/themes/lavandula.toml +77 -0
  199. flock/themes/liquidcarbon.toml +77 -0
  200. flock/themes/liquidcarbontransparent.toml +77 -0
  201. flock/themes/liquidcarbontransparentinverse.toml +77 -0
  202. flock/themes/lovelace.toml +77 -0
  203. flock/themes/man-page.toml +77 -0
  204. flock/themes/mariana.toml +77 -0
  205. flock/themes/material.toml +77 -0
  206. flock/themes/materialdark.toml +77 -0
  207. flock/themes/materialdarker.toml +77 -0
  208. flock/themes/materialdesigncolors.toml +77 -0
  209. flock/themes/materialocean.toml +77 -0
  210. flock/themes/mathias.toml +77 -0
  211. flock/themes/matrix.toml +77 -0
  212. flock/themes/medallion.toml +77 -0
  213. flock/themes/mellifluous.toml +77 -0
  214. flock/themes/midnight-in-mojave.toml +77 -0
  215. flock/themes/mirage.toml +77 -0
  216. flock/themes/misterioso.toml +77 -0
  217. flock/themes/molokai.toml +77 -0
  218. flock/themes/monalisa.toml +77 -0
  219. flock/themes/monokai-remastered.toml +77 -0
  220. flock/themes/monokai-soda.toml +77 -0
  221. flock/themes/monokai-vivid.toml +77 -0
  222. flock/themes/n0tch2k.toml +77 -0
  223. flock/themes/neobones-dark.toml +77 -0
  224. flock/themes/neobones-light.toml +77 -0
  225. flock/themes/neon.toml +77 -0
  226. flock/themes/neopolitan.toml +77 -0
  227. flock/themes/neutron.toml +77 -0
  228. flock/themes/night-owlish-light.toml +77 -0
  229. flock/themes/nightfox.toml +77 -0
  230. flock/themes/nightlion-v1.toml +77 -0
  231. flock/themes/nightlion-v2.toml +77 -0
  232. flock/themes/niji.toml +77 -0
  233. flock/themes/nocturnal-winter.toml +77 -0
  234. flock/themes/nord-light.toml +77 -0
  235. flock/themes/nord.toml +77 -0
  236. flock/themes/novel.toml +77 -0
  237. flock/themes/nvimdark.toml +77 -0
  238. flock/themes/nvimlight.toml +77 -0
  239. flock/themes/obsidian.toml +77 -0
  240. flock/themes/ocean.toml +77 -0
  241. flock/themes/oceanic-next.toml +77 -0
  242. flock/themes/oceanicmaterial.toml +77 -0
  243. flock/themes/ollie.toml +77 -0
  244. flock/themes/onehalfdark.toml +77 -0
  245. flock/themes/onehalflight.toml +77 -0
  246. flock/themes/operator-mono-dark.toml +77 -0
  247. flock/themes/overnight-slumber.toml +77 -0
  248. flock/themes/oxocarbon.toml +77 -0
  249. flock/themes/palenighthc.toml +77 -0
  250. flock/themes/pandora.toml +77 -0
  251. flock/themes/paraiso-dark.toml +77 -0
  252. flock/themes/paulmillr.toml +77 -0
  253. flock/themes/pencildark.toml +77 -0
  254. flock/themes/pencillight.toml +77 -0
  255. flock/themes/peppermint.toml +77 -0
  256. flock/themes/piatto-light.toml +77 -0
  257. flock/themes/pnevma.toml +77 -0
  258. flock/themes/popping-and-locking.toml +77 -0
  259. flock/themes/primary.toml +77 -0
  260. flock/themes/pro-light.toml +77 -0
  261. flock/themes/pro.toml +77 -0
  262. flock/themes/purple-rain.toml +77 -0
  263. flock/themes/purplepeter.toml +77 -0
  264. flock/themes/rapture.toml +77 -0
  265. flock/themes/raycast-dark.toml +77 -0
  266. flock/themes/raycast-light.toml +77 -0
  267. flock/themes/rebecca.toml +77 -0
  268. flock/themes/red-alert.toml +77 -0
  269. flock/themes/red-planet.toml +77 -0
  270. flock/themes/red-sands.toml +77 -0
  271. flock/themes/relaxed.toml +77 -0
  272. flock/themes/retro.toml +77 -0
  273. flock/themes/rippedcasts.toml +77 -0
  274. flock/themes/rose-pine-dawn.toml +77 -0
  275. flock/themes/rose-pine-moon.toml +77 -0
  276. flock/themes/rose-pine.toml +77 -0
  277. flock/themes/rouge-2.toml +77 -0
  278. flock/themes/royal.toml +77 -0
  279. flock/themes/ryuuko.toml +77 -0
  280. flock/themes/sakura.toml +77 -0
  281. flock/themes/scarlet-protocol.toml +77 -0
  282. flock/themes/seafoam-pastel.toml +77 -0
  283. flock/themes/seashells.toml +77 -0
  284. flock/themes/seoulbones-dark.toml +77 -0
  285. flock/themes/seoulbones-light.toml +77 -0
  286. flock/themes/seti.toml +77 -0
  287. flock/themes/shades-of-purple.toml +77 -0
  288. flock/themes/shaman.toml +77 -0
  289. flock/themes/slate.toml +77 -0
  290. flock/themes/sleepyhollow.toml +77 -0
  291. flock/themes/smyck.toml +77 -0
  292. flock/themes/snazzy.toml +77 -0
  293. flock/themes/softserver.toml +77 -0
  294. flock/themes/solarized-darcula.toml +77 -0
  295. flock/themes/solarized-dark---patched.toml +77 -0
  296. flock/themes/solarized-dark-higher-contrast.toml +77 -0
  297. flock/themes/spacedust.toml +77 -0
  298. flock/themes/spacegray-eighties-dull.toml +77 -0
  299. flock/themes/spacegray-eighties.toml +77 -0
  300. flock/themes/spacegray.toml +77 -0
  301. flock/themes/spiderman.toml +77 -0
  302. flock/themes/spring.toml +77 -0
  303. flock/themes/square.toml +77 -0
  304. flock/themes/sublette.toml +77 -0
  305. flock/themes/subliminal.toml +77 -0
  306. flock/themes/sugarplum.toml +77 -0
  307. flock/themes/sundried.toml +77 -0
  308. flock/themes/symfonic.toml +77 -0
  309. flock/themes/synthwave-everything.toml +77 -0
  310. flock/themes/synthwave.toml +77 -0
  311. flock/themes/synthwavealpha.toml +77 -0
  312. flock/themes/tango-adapted.toml +77 -0
  313. flock/themes/tango-half-adapted.toml +77 -0
  314. flock/themes/teerb.toml +77 -0
  315. flock/themes/terafox.toml +77 -0
  316. flock/themes/terminal-basic.toml +77 -0
  317. flock/themes/thayer-bright.toml +77 -0
  318. flock/themes/the-hulk.toml +77 -0
  319. flock/themes/tinacious-design-(dark).toml +77 -0
  320. flock/themes/tinacious-design-(light).toml +77 -0
  321. flock/themes/tokyonight-day.toml +77 -0
  322. flock/themes/tokyonight-storm.toml +77 -0
  323. flock/themes/tokyonight.toml +77 -0
  324. flock/themes/tomorrow-night-blue.toml +77 -0
  325. flock/themes/tomorrow-night-bright.toml +77 -0
  326. flock/themes/tomorrow-night-burns.toml +77 -0
  327. flock/themes/tomorrow-night-eighties.toml +77 -0
  328. flock/themes/tomorrow-night.toml +77 -0
  329. flock/themes/tomorrow.toml +77 -0
  330. flock/themes/toychest.toml +77 -0
  331. flock/themes/treehouse.toml +77 -0
  332. flock/themes/twilight.toml +77 -0
  333. flock/themes/ubuntu.toml +77 -0
  334. flock/themes/ultradark.toml +77 -0
  335. flock/themes/ultraviolent.toml +77 -0
  336. flock/themes/underthesea.toml +77 -0
  337. flock/themes/unikitty.toml +77 -0
  338. flock/themes/urple.toml +77 -0
  339. flock/themes/vaughn.toml +77 -0
  340. flock/themes/vesper.toml +77 -0
  341. flock/themes/vibrantink.toml +77 -0
  342. flock/themes/vimbones.toml +77 -0
  343. flock/themes/violet-dark.toml +77 -0
  344. flock/themes/violet-light.toml +77 -0
  345. flock/themes/warmneon.toml +77 -0
  346. flock/themes/wez.toml +77 -0
  347. flock/themes/whimsy.toml +77 -0
  348. flock/themes/wildcherry.toml +77 -0
  349. flock/themes/wilmersdorf.toml +77 -0
  350. flock/themes/wombat.toml +77 -0
  351. flock/themes/wryan.toml +77 -0
  352. flock/themes/xcodedark.toml +77 -0
  353. flock/themes/xcodedarkhc.toml +77 -0
  354. flock/themes/xcodelight.toml +77 -0
  355. flock/themes/xcodelighthc.toml +77 -0
  356. flock/themes/xcodewwdc.toml +77 -0
  357. flock/themes/zenbones-dark.toml +77 -0
  358. flock/themes/zenbones-light.toml +77 -0
  359. flock/themes/zenbones.toml +77 -0
  360. flock/themes/zenburn.toml +77 -0
  361. flock/themes/zenburned.toml +77 -0
  362. flock/themes/zenwritten-dark.toml +77 -0
  363. flock/themes/zenwritten-light.toml +77 -0
  364. flock/workflow/activities.py +175 -115
  365. flock/workflow/agent_activities.py +24 -26
  366. flock/workflow/temporal_setup.py +38 -37
  367. flock/workflow/workflow.py +58 -53
  368. flock_core-0.2.2.dist-info/METADATA +320 -0
  369. flock_core-0.2.2.dist-info/RECORD +372 -0
  370. {flock_core-0.1.2.dist-info → flock_core-0.2.2.dist-info}/licenses/LICENSE +21 -21
  371. flock/agents/__init__.py +0 -3
  372. flock/agents/batch_agent.py +0 -175
  373. flock/agents/declarative_agent.py +0 -166
  374. flock/agents/loop_agent.py +0 -178
  375. flock/agents/trigger_agent.py +0 -191
  376. flock/agents/user_agent.py +0 -230
  377. flock/app/components/__init__.py +0 -14
  378. flock/app/components/charts/agent_workflow.py +0 -14
  379. flock/app/components/charts/core_architecture.py +0 -14
  380. flock/app/components/charts/tool_system.py +0 -14
  381. flock/app/components/history_grid.py +0 -168
  382. flock/app/components/history_grid_alt.py +0 -189
  383. flock/app/components/sidebar.py +0 -19
  384. flock/app/components/theme.py +0 -9
  385. flock/app/components/util.py +0 -18
  386. flock/app/hive_app.py +0 -118
  387. flock/app/html/d3.html +0 -179
  388. flock/app/modules/__init__.py +0 -12
  389. flock/app/modules/about.py +0 -17
  390. flock/app/modules/agent_detail.py +0 -70
  391. flock/app/modules/agent_list.py +0 -59
  392. flock/app/modules/playground.py +0 -322
  393. flock/app/modules/settings.py +0 -96
  394. flock/core/agent.py +0 -150
  395. flock/core/agent_registry.py +0 -162
  396. flock/core/context.py +0 -279
  397. flock/core/handoff/handoff_base.py +0 -12
  398. flock/core/logging/error_handler.py +0 -84
  399. flock/core/logging/formatters.py +0 -122
  400. flock/core/logging/handlers.py +0 -117
  401. flock/core/logging/logger.py +0 -107
  402. flock/core/serializable.py +0 -206
  403. flock_core-0.1.2.dist-info/METADATA +0 -476
  404. flock_core-0.1.2.dist-info/RECORD +0 -48
  405. flock_core-0.1.2.dist-info/entry_points.txt +0 -2
  406. /flock/{core/config/declarative_agent_config.py → workflow/__init__.py} +0 -0
  407. {flock_core-0.1.2.dist-info → flock_core-0.2.2.dist-info}/WHEEL +0 -0
@@ -0,0 +1,197 @@
1
+ """Mixin class for integrating with the dspy library."""
2
+
3
+ import sys
4
+ from typing import Any, Literal
5
+
6
+ from flock.core.logging.logging import get_logger
7
+ from flock.core.util.input_resolver import split_top_level
8
+
9
+ logger = get_logger("flock")
10
+
11
+ AgentType = (
12
+ Literal["ReAct"] | Literal["Completion"] | Literal["ChainOfThought"] | None
13
+ )
14
+
15
+
16
+ class DSPyIntegrationMixin:
17
+ """Mixin class for integrating with the dspy library."""
18
+
19
+ def create_dspy_signature_class(
20
+ self, agent_name, description_spec, fields_spec
21
+ ) -> Any:
22
+ """Trying to create a dynamic class using dspy library."""
23
+ # ---------------------------
24
+ # 1. Parse the class specification.
25
+ # ---------------------------
26
+ import dspy
27
+
28
+ base_class = dspy.Signature
29
+
30
+ # Start building the class dictionary with a docstring and annotations dict.
31
+ class_dict = {"__doc__": description_spec, "__annotations__": {}}
32
+
33
+ # ---------------------------
34
+ # 2. Split the fields specification into inputs and outputs.
35
+ # ---------------------------
36
+ if "->" in fields_spec:
37
+ inputs_spec, outputs_spec = fields_spec.split("->", 1)
38
+ else:
39
+ inputs_spec, outputs_spec = fields_spec, ""
40
+
41
+ # ---------------------------
42
+ # 3. Draw the rest of the owl.
43
+ # ---------------------------
44
+ def parse_field(field_str):
45
+ """Parser.
46
+
47
+ Parse a field of the form:
48
+ <name> [ : <type> ] [ | <desc> ]
49
+ Returns a tuple: (name, field_type, desc)
50
+ """
51
+ field_str = field_str.strip()
52
+ if not field_str:
53
+ return None
54
+
55
+ parts = field_str.split("|", 1)
56
+ main_part = parts[0].strip() # contains name and (optionally) type
57
+ desc = parts[1].strip() if len(parts) > 1 else None
58
+
59
+ if ":" in main_part:
60
+ name, type_str = [s.strip() for s in main_part.split(":", 1)]
61
+ else:
62
+ name = main_part
63
+ type_str = "str" # default type
64
+
65
+ # Evaluate the type. Since type can be any valid expression (including custom types),
66
+ # we use eval. (Be cautious if using eval with untrusted input.)
67
+ try:
68
+ # TODO: We have to find a way to avoid using eval here.
69
+ # This is a security risk, as it allows arbitrary code execution.
70
+
71
+ try:
72
+ field_type = eval(type_str, sys.modules[__name__].__dict__)
73
+ except Exception:
74
+ field_type = eval(
75
+ type_str, sys.modules["__main__"].__dict__
76
+ )
77
+
78
+ except Exception:
79
+ # If evaluation fails, default to str.
80
+ field_type = str
81
+
82
+ return name, field_type, desc
83
+
84
+ def process_fields(fields_string, field_kind):
85
+ """Process a comma-separated list of field definitions.
86
+
87
+ field_kind: "input" or "output" determines which Field constructor to use.
88
+ """
89
+ if not fields_string.strip():
90
+ return
91
+
92
+ # Split on commas.
93
+ for field in split_top_level(fields_string):
94
+ if field.strip():
95
+ parsed = parse_field(field)
96
+ if not parsed:
97
+ continue
98
+ name, field_type, desc = parsed
99
+ class_dict["__annotations__"][name] = field_type
100
+
101
+ # Use the proper Field constructor.
102
+ if field_kind == "input":
103
+ if desc is not None:
104
+ class_dict[name] = dspy.InputField(desc=desc)
105
+ else:
106
+ class_dict[name] = dspy.InputField()
107
+ elif field_kind == "output":
108
+ if desc is not None:
109
+ class_dict[name] = dspy.OutputField(desc=desc)
110
+ else:
111
+ class_dict[name] = dspy.OutputField()
112
+ else:
113
+ raise ValueError("Unknown field kind: " + field_kind)
114
+
115
+ # Process input fields (to be used with my.InputField)
116
+ process_fields(inputs_spec, "input")
117
+ # Process output fields (to be used with my.OutputField)
118
+ process_fields(outputs_spec, "output")
119
+
120
+ return type("dspy_" + agent_name, (base_class,), class_dict)
121
+
122
+ def _configure_language_model(self) -> None:
123
+ import dspy
124
+
125
+ """Initialize and configure the language model using dspy."""
126
+ lm = dspy.LM(self.model, cache=self.use_cache)
127
+ dspy.configure(lm=lm)
128
+
129
+ def _select_task(
130
+ self,
131
+ signature: Any,
132
+ agent_type_override: AgentType,
133
+ ) -> Any:
134
+ """Select and instantiate the appropriate task based on tool availability.
135
+
136
+ Args:
137
+ prompt: The detailed prompt string.
138
+ input_desc: Dictionary of input key descriptions.
139
+ output_desc: Dictionary of output key descriptions.
140
+
141
+ Returns:
142
+ An instance of a dspy task (either ReAct or Predict).
143
+ """
144
+ import dspy
145
+
146
+ dspy_solver = None
147
+
148
+ if agent_type_override:
149
+ if agent_type_override == "ChainOfThought":
150
+ dspy_solver = dspy.ChainOfThought(
151
+ signature,
152
+ )
153
+ if agent_type_override == "ReAct":
154
+ dspy.ReAct(
155
+ signature,
156
+ tools=self.tools,
157
+ max_iters=10,
158
+ )
159
+ if agent_type_override == "Completion":
160
+ dspy_solver = dspy.Predict(
161
+ signature,
162
+ )
163
+ else:
164
+ if self.tools:
165
+ dspy_solver = dspy.ReAct(
166
+ signature,
167
+ tools=self.tools,
168
+ max_iters=10,
169
+ )
170
+ else:
171
+ dspy_solver = dspy.Predict(
172
+ signature,
173
+ )
174
+
175
+ return dspy_solver
176
+
177
+ def _process_result(
178
+ self, result: Any, inputs: dict[str, Any]
179
+ ) -> dict[str, Any]:
180
+ """Convert the result to a dictionary and add the inputs for an unified result object.
181
+
182
+ Args:
183
+ result: The raw result from the dspy task.
184
+ inputs: The original inputs provided to the agent.
185
+
186
+ Returns:
187
+ A dictionary containing the processed output.
188
+ """
189
+ try:
190
+ result = result.toDict()
191
+ for key in inputs:
192
+ result.setdefault(key, inputs.get(key))
193
+ except Exception as conv_error:
194
+ logger.warning(
195
+ f"Warning: Failed to convert result to dict in agent '{self.name}': {conv_error}"
196
+ )
197
+ return result
@@ -0,0 +1,125 @@
1
+ """A mixin class for parsing agent prompts and building clean signatures for DSPy."""
2
+
3
+ # DEPRECATED! This mixin is no longer used in the current version of Flock. It was used to parse agent prompts and build clean signatures for DSPy.
4
+ # TODO: DELETE THIS FILE!
5
+
6
+ from flock.core.util.input_resolver import split_top_level
7
+
8
+
9
+ class PromptParserMixin:
10
+ """A mixin class for parsing agent prompts and building clean signatures for DSPy."""
11
+
12
+ def _parse_key_descriptions(self, keys_str: str) -> list[tuple[str, str]]:
13
+ """Parse a comma-separated string into a list of (key, description) tuples.
14
+
15
+ This function processes a configuration string that defines one or more keys, where each key may
16
+ include a type hint and an optional human-readable description. The expected format for each key is:
17
+
18
+ key: type_hint | description
19
+
20
+ If the pipe symbol ("|") is absent, the description is set to an empty string.
21
+
22
+ The splitting is performed using split_top_level() so that commas inside type hints are preserved.
23
+
24
+ For example, given:
25
+ "query: str | The search query, context: dict | The full conversation context"
26
+ it returns:
27
+ [("query", "The search query"), ("context", "The full conversation context")]
28
+
29
+ Args:
30
+ keys_str (str): A comma-separated string of key definitions.
31
+
32
+ Returns:
33
+ List[Tuple[str, str]]: A list of (key, description) tuples.
34
+ """
35
+ key_descs = []
36
+ for part in split_top_level(keys_str):
37
+ if not part:
38
+ continue
39
+ if "|" in part:
40
+ key_type_part, desc = part.split("|", 1)
41
+ desc = desc.strip()
42
+ else:
43
+ key_type_part = part
44
+ desc = ""
45
+ key = key_type_part.split(":", 1)[0].strip()
46
+ key_descs.append((key, desc))
47
+ return key_descs
48
+
49
+ def _build_clean_signature(self, keys_str: str) -> str:
50
+ """Build a clean signature string from the configuration string by removing the description parts.
51
+
52
+ Given a string like:
53
+ "query: str | The search query, context: dict | The full conversation context"
54
+ this method returns:
55
+ "query: str, context: dict"
56
+
57
+ This function uses split_top_level() to avoid splitting on commas that are inside type hints.
58
+
59
+ Args:
60
+ keys_str (str): The configuration string containing keys, type hints, and optional descriptions.
61
+
62
+ Returns:
63
+ str: A clean signature string with only keys and type hints.
64
+ """
65
+ parts = []
66
+ for part in split_top_level(keys_str):
67
+ if not part:
68
+ continue
69
+ if "|" in part:
70
+ clean_part = part.split("|", 1)[0].strip()
71
+ else:
72
+ clean_part = part.strip()
73
+ parts.append(clean_part)
74
+ return ", ".join(parts)
75
+
76
+ def _build_descriptions(self) -> tuple[dict[str, str], dict[str, str]]:
77
+ """Build dictionaries of input and output descriptions from the agent's configuration.
78
+
79
+ Returns:
80
+ A tuple containing:
81
+ - input_desc: A dictionary mapping each input key (without type hints) to its description.
82
+ - output_desc: A dictionary mapping each output key (without type hints) to its description.
83
+ """
84
+ input_desc: dict[str, str] = {}
85
+ if self.input:
86
+ for key, desc in self._parse_key_descriptions(self.input):
87
+ input_desc[key] = desc
88
+
89
+ output_desc: dict[str, str] = {}
90
+ if self.output:
91
+ for key, desc in self._parse_key_descriptions(self.output):
92
+ output_desc[key] = desc
93
+
94
+ return input_desc, output_desc
95
+
96
+ def _build_prompt(
97
+ self, input_desc: dict[str, str], output_desc: dict[str, str]
98
+ ) -> str:
99
+ """Build a clean signature prompt from the agent's configuration.
100
+
101
+ This method uses the original input and output strings (removing the description parts)
102
+ to create a signature string that is passed to DSPy. For example, if:
103
+ - self.input is "query: str | The search query, context: dict | The full conversation context"
104
+ - self.output is "result: str | The result"
105
+ then the prompt will be:
106
+ "query: str, context: dict -> result: str"
107
+
108
+ **Note:** The descriptive metadata is preserved in the dictionaries obtained from _build_descriptions,
109
+ which are passed separately to DSPy.
110
+
111
+ Args:
112
+ input_desc: Dictionary of input key descriptions (for metadata only).
113
+ output_desc: Dictionary of output key descriptions (for metadata only).
114
+
115
+ Returns:
116
+ A clean signature string for DSPy.
117
+ """
118
+ clean_input = (
119
+ self._build_clean_signature(self.input) if self.input else ""
120
+ )
121
+ clean_output = (
122
+ self._build_clean_signature(self.output) if self.output else ""
123
+ )
124
+ # Combine the clean input and output signatures using "->"
125
+ return f"{clean_input} -> {clean_output}"
@@ -0,0 +1,118 @@
1
+ """Registry for storing and managing agents and tools with logging and tracing integration."""
2
+
3
+ from collections.abc import Callable
4
+
5
+ from opentelemetry import trace
6
+
7
+ from flock.core.flock_agent import FlockAgent
8
+ from flock.core.logging.logging import get_logger
9
+
10
+ logger = get_logger("registry")
11
+ tracer = trace.get_tracer(__name__)
12
+
13
+
14
+ class Registry:
15
+ """Registry for storing and managing agents and tools.
16
+
17
+ This singleton class maintains a centralized registry of agents and tools,
18
+ which is particularly important for Temporal workflows where only basic Python
19
+ types can be passed between activities.
20
+ """
21
+
22
+ _instance = None
23
+
24
+ def __new__(cls):
25
+ with tracer.start_as_current_span("Registry.__new__") as span:
26
+ if cls._instance is None:
27
+ cls._instance = super().__new__(cls)
28
+ cls._instance._initialize()
29
+ logger.info("Registry instance created")
30
+ span.set_attribute("instance.created", True)
31
+ return cls._instance
32
+
33
+ def _initialize(self):
34
+ with tracer.start_as_current_span("Registry._initialize"):
35
+ self._agents: list[FlockAgent] = []
36
+ self._tools: list[tuple[str, Callable]] = []
37
+ logger.info("Registry initialized", agents_count=0, tools_count=0)
38
+
39
+ def register_tool(self, tool_name: str, tool: Callable) -> None:
40
+ with tracer.start_as_current_span("Registry.register_tool") as span:
41
+ span.set_attribute("tool_name", tool_name)
42
+ try:
43
+ self._tools.append((tool_name, tool))
44
+ logger.info("Tool registered", tool_name=tool_name)
45
+ except Exception as e:
46
+ logger.error(
47
+ "Error registering tool", tool_name=tool_name, error=str(e)
48
+ )
49
+ span.record_exception(e)
50
+ raise
51
+
52
+ def register_agent(self, agent: FlockAgent) -> None:
53
+ with tracer.start_as_current_span("Registry.register_agent") as span:
54
+ span.set_attribute("agent_name", agent.name)
55
+ try:
56
+ self._agents.append(agent)
57
+ logger.info("Agent registered", agent=agent.name)
58
+ except Exception as e:
59
+ logger.error(
60
+ "Error registering agent", agent=agent.name, error=str(e)
61
+ )
62
+ span.record_exception(e)
63
+ raise
64
+
65
+ def get_agent(self, name: str) -> FlockAgent | None:
66
+ with tracer.start_as_current_span("Registry.get_agent") as span:
67
+ span.set_attribute("search_agent_name", name)
68
+ try:
69
+ for agent in self._agents:
70
+ if agent.name == name:
71
+ logger.info("Agent found", agent=name)
72
+ span.set_attribute("found", True)
73
+ return agent
74
+ logger.warning("Agent not found", agent=name)
75
+ span.set_attribute("found", False)
76
+ return None
77
+ except Exception as e:
78
+ logger.error("Error retrieving agent", agent=name, error=str(e))
79
+ span.record_exception(e)
80
+ raise
81
+
82
+ def get_tool(self, name: str) -> Callable | None:
83
+ with tracer.start_as_current_span("Registry.get_tool") as span:
84
+ span.set_attribute("search_tool_name", name)
85
+ try:
86
+ for tool_name, tool in self._tools:
87
+ if tool_name == name:
88
+ logger.info("Tool found", tool=name)
89
+ span.set_attribute("found", True)
90
+ return tool
91
+ logger.warning("Tool not found", tool=name)
92
+ span.set_attribute("found", False)
93
+ return None
94
+ except Exception as e:
95
+ logger.error("Error retrieving tool", tool=name, error=str(e))
96
+ span.record_exception(e)
97
+ raise
98
+
99
+ def get_tools(self, names: list[str] | None) -> list[Callable]:
100
+ with tracer.start_as_current_span("Registry.get_tools") as span:
101
+ span.set_attribute("search_tool_names", str(names))
102
+ try:
103
+ if not names:
104
+ logger.info("No tool names provided")
105
+ return []
106
+ tools = [self.get_tool(name) for name in names]
107
+ found_tools = [tool for tool in tools if tool is not None]
108
+ logger.info(
109
+ "Tools retrieved", requested=names, found=len(found_tools)
110
+ )
111
+ span.set_attribute("found_tools_count", len(found_tools))
112
+ return found_tools
113
+ except Exception as e:
114
+ logger.error(
115
+ "Error retrieving tools", names=str(names), error=str(e)
116
+ )
117
+ span.record_exception(e)
118
+ raise