langflow-base-nightly 0.5.0.dev36__py3-none-any.whl → 0.5.0.dev38__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.
Files changed (343) hide show
  1. langflow/__main__.py +1 -1
  2. langflow/alembic/versions/4e5980a44eaa_fix_date_times_again.py +24 -30
  3. langflow/alembic/versions/58b28437a398_modify_nullable.py +6 -6
  4. langflow/alembic/versions/79e675cb6752_change_datetime_type.py +24 -30
  5. langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py +12 -13
  6. langflow/api/build.py +21 -26
  7. langflow/api/health_check_router.py +3 -3
  8. langflow/api/utils.py +3 -3
  9. langflow/api/v1/callback.py +2 -2
  10. langflow/api/v1/chat.py +19 -31
  11. langflow/api/v1/endpoints.py +10 -10
  12. langflow/api/v1/flows.py +1 -1
  13. langflow/api/v1/knowledge_bases.py +19 -12
  14. langflow/api/v1/mcp.py +12 -12
  15. langflow/api/v1/mcp_projects.py +45 -81
  16. langflow/api/v1/mcp_utils.py +8 -8
  17. langflow/api/v1/schemas.py +1 -5
  18. langflow/api/v1/store.py +1 -1
  19. langflow/api/v1/validate.py +2 -2
  20. langflow/api/v1/voice_mode.py +58 -62
  21. langflow/api/v2/files.py +5 -3
  22. langflow/api/v2/mcp.py +10 -9
  23. langflow/base/composio/composio_base.py +21 -2
  24. langflow/base/data/docling_utils.py +194 -0
  25. langflow/base/data/kb_utils.py +33 -0
  26. langflow/base/embeddings/aiml_embeddings.py +1 -1
  27. langflow/base/flow_processing/utils.py +1 -2
  28. langflow/base/io/__init__.py +0 -1
  29. langflow/base/langwatch/utils.py +2 -1
  30. langflow/base/mcp/util.py +49 -47
  31. langflow/base/models/model.py +3 -3
  32. langflow/base/prompts/api_utils.py +1 -1
  33. langflow/base/tools/flow_tool.py +2 -2
  34. langflow/base/tools/run_flow.py +2 -6
  35. langflow/components/Notion/add_content_to_page.py +2 -2
  36. langflow/components/Notion/list_database_properties.py +2 -2
  37. langflow/components/Notion/list_pages.py +2 -2
  38. langflow/components/Notion/page_content_viewer.py +2 -2
  39. langflow/components/Notion/update_page_property.py +1 -1
  40. langflow/components/agentql/agentql_api.py +2 -10
  41. langflow/components/agents/agent.py +3 -3
  42. langflow/components/agents/mcp_component.py +54 -69
  43. langflow/components/anthropic/anthropic.py +5 -4
  44. langflow/components/assemblyai/assemblyai_get_subtitles.py +2 -2
  45. langflow/components/assemblyai/assemblyai_lemur.py +2 -2
  46. langflow/components/assemblyai/assemblyai_list_transcripts.py +2 -2
  47. langflow/components/assemblyai/assemblyai_poll_transcript.py +2 -2
  48. langflow/components/assemblyai/assemblyai_start_transcript.py +2 -2
  49. langflow/components/data/file.py +575 -55
  50. langflow/components/data/kb_ingest.py +116 -43
  51. langflow/components/data/kb_retrieval.py +24 -26
  52. langflow/components/data/url.py +1 -1
  53. langflow/components/datastax/astra_assistant_manager.py +3 -3
  54. langflow/components/datastax/create_assistant.py +1 -2
  55. langflow/components/deactivated/merge_data.py +1 -2
  56. langflow/components/deactivated/sub_flow.py +6 -7
  57. langflow/components/deactivated/vectara_self_query.py +3 -3
  58. langflow/components/docling/__init__.py +0 -198
  59. langflow/components/docling/docling_inline.py +1 -1
  60. langflow/components/embeddings/text_embedder.py +3 -3
  61. langflow/components/firecrawl/firecrawl_extract_api.py +2 -9
  62. langflow/components/google/gmail.py +1 -1
  63. langflow/components/google/google_generative_ai.py +5 -11
  64. langflow/components/groq/groq.py +4 -3
  65. langflow/components/helpers/current_date.py +2 -3
  66. langflow/components/helpers/memory.py +1 -1
  67. langflow/components/ibm/watsonx.py +1 -1
  68. langflow/components/ibm/watsonx_embeddings.py +1 -1
  69. langflow/components/langwatch/langwatch.py +3 -3
  70. langflow/components/logic/flow_tool.py +2 -2
  71. langflow/components/logic/notify.py +1 -1
  72. langflow/components/logic/run_flow.py +2 -3
  73. langflow/components/logic/sub_flow.py +4 -5
  74. langflow/components/mem0/mem0_chat_memory.py +2 -8
  75. langflow/components/nvidia/nvidia.py +3 -3
  76. langflow/components/olivya/olivya.py +7 -7
  77. langflow/components/ollama/ollama.py +8 -6
  78. langflow/components/processing/batch_run.py +8 -8
  79. langflow/components/processing/data_operations.py +2 -2
  80. langflow/components/processing/merge_data.py +1 -2
  81. langflow/components/processing/message_to_data.py +2 -3
  82. langflow/components/processing/parse_json_data.py +1 -1
  83. langflow/components/processing/save_file.py +6 -32
  84. langflow/components/prototypes/python_function.py +2 -3
  85. langflow/components/serpapi/serp.py +1 -1
  86. langflow/components/tavily/tavily_extract.py +1 -1
  87. langflow/components/tavily/tavily_search.py +1 -1
  88. langflow/components/tools/calculator.py +2 -2
  89. langflow/components/tools/python_code_structured_tool.py +3 -10
  90. langflow/components/tools/python_repl.py +2 -2
  91. langflow/components/tools/searxng.py +3 -3
  92. langflow/components/tools/serp_api.py +2 -2
  93. langflow/components/tools/tavily_search_tool.py +2 -2
  94. langflow/components/tools/yahoo_finance.py +1 -1
  95. langflow/components/twelvelabs/video_embeddings.py +4 -4
  96. langflow/components/vectorstores/astradb.py +30 -19
  97. langflow/components/vectorstores/local_db.py +1 -1
  98. langflow/components/yahoosearch/yahoo.py +1 -1
  99. langflow/components/youtube/trending.py +3 -4
  100. langflow/custom/attributes.py +2 -1
  101. langflow/custom/code_parser/code_parser.py +1 -1
  102. langflow/custom/custom_component/base_component.py +1 -1
  103. langflow/custom/custom_component/component.py +16 -2
  104. langflow/custom/directory_reader/directory_reader.py +7 -7
  105. langflow/custom/directory_reader/utils.py +1 -2
  106. langflow/custom/utils.py +30 -30
  107. langflow/events/event_manager.py +1 -1
  108. langflow/frontend/assets/{SlackIcon-B260Qg_R.js → SlackIcon-BhW6H3JR.js} +1 -1
  109. langflow/frontend/assets/{Wikipedia-BB2mbgyd.js → Wikipedia-Dx5jbiy3.js} +1 -1
  110. langflow/frontend/assets/{Wolfram-DytXC9hF.js → Wolfram-CIyonzwo.js} +1 -1
  111. langflow/frontend/assets/{index-DPX6X_bw.js → index-0XQqYgdG.js} +1 -1
  112. langflow/frontend/assets/{index-DtJyCbzF.js → index-1Q3VBqKn.js} +1 -1
  113. langflow/frontend/assets/{index-DztLFiip.js → index-35sspuLu.js} +1 -1
  114. langflow/frontend/assets/{index-BeNby7qF.js → index-7hzXChQz.js} +1 -1
  115. langflow/frontend/assets/{index-BOEf7-ty.js → index-8cuhogZP.js} +1 -1
  116. langflow/frontend/assets/{index-D0s9f6Re.js → index-B0m53xKd.js} +1 -1
  117. langflow/frontend/assets/{index-DpJiH-Rk.js → index-B1XqWJhG.js} +1 -1
  118. langflow/frontend/assets/{index-DuAeoC-H.js → index-B3KCdQ91.js} +1 -1
  119. langflow/frontend/assets/{index-Bxml6wXu.js → index-B7uEuOPK.js} +1 -1
  120. langflow/frontend/assets/{index-CDFLVFB4.js → index-B8UR8v-Q.js} +1 -1
  121. langflow/frontend/assets/{index-ci4XHjbJ.js → index-BD7Io1hL.js} +6 -6
  122. langflow/frontend/assets/{index-DasrI03Y.js → index-BDQrd7Tj.js} +1 -1
  123. langflow/frontend/assets/{index-CkQ-bJ4G.js → index-BDuk0d7P.js} +1 -1
  124. langflow/frontend/assets/{index-C_1RBTul.js → index-BFQ8KFK0.js} +1 -1
  125. langflow/frontend/assets/{index-DqSH4x-R.js → index-BFf0HTFI.js} +1 -1
  126. langflow/frontend/assets/{index-BXMhmvTj.js → index-BHhnpSkW.js} +1 -1
  127. langflow/frontend/assets/{index-Uq2ij_SS.js → index-BKKrUElc.js} +1 -1
  128. langflow/frontend/assets/{index-3TJWUdmx.js → index-BKeZt2hQ.js} +1 -1
  129. langflow/frontend/assets/{index-DHlEwAxb.js → index-BKlQbl-6.js} +1 -1
  130. langflow/frontend/assets/{index-Bisa4IQF.js → index-BLYw9MK2.js} +1 -1
  131. langflow/frontend/assets/{index-GODbXlHC.js → index-BLsVo9iW.js} +1 -1
  132. langflow/frontend/assets/{index-CHFO5O4g.js → index-BNQIbda3.js} +1 -1
  133. langflow/frontend/assets/{index-3uOAA_XX.js → index-BPR2mEFC.js} +1 -1
  134. langflow/frontend/assets/{index-3qMh9x6K.js → index-BPfdqCc_.js} +1 -1
  135. langflow/frontend/assets/{index-rcdQpNcU.js → index-BQrVDjR1.js} +1 -1
  136. langflow/frontend/assets/{index-4eRtaV45.js → index-BRmSeoWR.js} +1 -1
  137. langflow/frontend/assets/{index-Ct9_T9ox.js → index-BUse-kxM.js} +1 -1
  138. langflow/frontend/assets/{index-BdYgKk1d.js → index-BVFaF7HW.js} +1 -1
  139. langflow/frontend/assets/{index-CWWo2zOA.js → index-BWgIWfv2.js} +1 -1
  140. langflow/frontend/assets/{index-Du9aJK7m.js → index-BWt5xGeA.js} +1 -1
  141. langflow/frontend/assets/{index-Baka5dKE.js → index-BYhcGLTV.js} +1 -1
  142. langflow/frontend/assets/{index-BWq9GTzt.js → index-BYjw7Gk3.js} +1 -1
  143. langflow/frontend/assets/{index-r1LZg-PY.js → index-BZFljdMa.js} +1 -1
  144. langflow/frontend/assets/index-BcAgItH4.js +1 -0
  145. langflow/frontend/assets/{index-B8TlNgn-.js → index-Bct1s6__.js} +1 -1
  146. langflow/frontend/assets/{index-DZzbmg3J.js → index-Bhv79Zso.js} +1 -1
  147. langflow/frontend/assets/{index-CqDUqHfd.js → index-Bj3lSwvZ.js} +1 -1
  148. langflow/frontend/assets/{index-dkS0ek2S.js → index-Bk4mTwnI.js} +1 -1
  149. langflow/frontend/assets/{index-tOy_uloT.js → index-BmIx1cws.js} +1 -1
  150. langflow/frontend/assets/{index-BVtf6m9S.js → index-BmYJJ5YS.js} +1 -1
  151. langflow/frontend/assets/{index-mBjJYD9q.js → index-BnAFhkSN.js} +1 -1
  152. langflow/frontend/assets/{index-Ba3RTMXI.js → index-Bo-ww0Bb.js} +1 -1
  153. langflow/frontend/assets/{index-BsBWP-Dh.js → index-BpmqDOeZ.js} +1 -1
  154. langflow/frontend/assets/{index-BqUeOc7Y.js → index-BrVhdPZb.js} +1 -1
  155. langflow/frontend/assets/{index-DWkMJnbd.js → index-BvGQfVBD.js} +1 -1
  156. langflow/frontend/assets/{index-DdzVmJHE.js → index-Bwi4flFg.js} +1 -1
  157. langflow/frontend/assets/{index-Ccb5B8zG.js → index-BzoRPtTY.js} +1 -1
  158. langflow/frontend/assets/{index-Ym6gz0T6.js → index-C--IDAyc.js} +1 -1
  159. langflow/frontend/assets/{index-CvQ0w8Pj.js → index-C0E3_MIK.js} +1 -1
  160. langflow/frontend/assets/{index-DxIs8VSp.js → index-C27Jj_26.js} +1 -1
  161. langflow/frontend/assets/{index-BxWXWRmZ.js → index-C2eQmQsn.js} +1 -1
  162. langflow/frontend/assets/{index-B536IPXH.js → index-C8K0r39B.js} +1 -1
  163. langflow/frontend/assets/{index-BEDxAk3N.js → index-CEJNWPhA.js} +1 -1
  164. langflow/frontend/assets/{index-G_U_kPAd.js → index-CFNTYfFK.js} +1 -1
  165. langflow/frontend/assets/{index-CMGZGIx_.js → index-CMHpjHZl.js} +1 -1
  166. langflow/frontend/assets/{index-C76aBV_h.js → index-CSu8KHOi.js} +1 -1
  167. langflow/frontend/assets/{index-B-c82Fnu.js → index-CUKmGsI6.js} +1 -1
  168. langflow/frontend/assets/{index-DX7XsAcx.js → index-CWYiSeWV.js} +1 -1
  169. langflow/frontend/assets/{index-COL0eiWI.js → index-CY7_TBTC.js} +1 -1
  170. langflow/frontend/assets/{index-BlBl2tvQ.js → index-CbnWRlYY.js} +1 -1
  171. langflow/frontend/assets/{index-BQB-iDYl.js → index-CfPBgkqg.js} +1 -1
  172. langflow/frontend/assets/{index-DWr_zPkx.js → index-Cg53lrYh.js} +1 -1
  173. langflow/frontend/assets/{index-BcgB3rXH.js → index-CgU7KF4I.js} +1 -1
  174. langflow/frontend/assets/{index-CkSzjCqM.js → index-CgwykVGh.js} +1 -1
  175. langflow/frontend/assets/{index-BbsND1Qg.js → index-Ch5r0oW6.js} +1 -1
  176. langflow/frontend/assets/{index-AY5Dm2mG.js → index-CjsommIr.js} +1 -1
  177. langflow/frontend/assets/{index-BtJ2o21k.js → index-CkK25zZO.js} +1 -1
  178. langflow/frontend/assets/{index-BKvKC-12.js → index-CkjwSTSM.js} +1 -1
  179. langflow/frontend/assets/{index-BVHvIhT5.js → index-CmSFKgiD.js} +1 -1
  180. langflow/frontend/assets/{index-D-zkHcob.js → index-Cr5v2ave.js} +1 -1
  181. langflow/frontend/assets/{index-js8ceOaP.js → index-CrAF-31Y.js} +1 -1
  182. langflow/frontend/assets/{index-BNbWMmAV.js → index-CsLQiWNf.js} +1 -1
  183. langflow/frontend/assets/{index-VcXZzovW.js → index-CuCM7Wu7.js} +1 -1
  184. langflow/frontend/assets/{index-DzeIsaBm.js → index-Cxy9sEpy.js} +1 -1
  185. langflow/frontend/assets/{index-LrMzDsq9.js → index-CyP3py8K.js} +1 -1
  186. langflow/frontend/assets/{index-C8KD3LPb.js → index-CzHzeZuA.js} +1 -1
  187. langflow/frontend/assets/{index-DS1EgA10.js → index-D1oynC8a.js} +1 -1
  188. langflow/frontend/assets/{index-ByFXr9Iq.js → index-D4tjMhfY.js} +1 -1
  189. langflow/frontend/assets/{index-DyJDHm2D.js → index-D6CSIrp1.js} +1 -1
  190. langflow/frontend/assets/{index-DIqSyDVO.js → index-D9kwEzPB.js} +1 -1
  191. langflow/frontend/assets/{index-D5PeCofu.js → index-DDXsm8tz.js} +1 -1
  192. langflow/frontend/assets/{index-CJwYfDBz.js → index-DDhJVVel.js} +1 -1
  193. langflow/frontend/assets/{index-C7x9R_Yo.js → index-DH6o91_s.js} +1 -1
  194. langflow/frontend/assets/{index-DpQKtcXu.js → index-DHngW1k8.js} +1 -1
  195. langflow/frontend/assets/{index-VZnN0P6C.js → index-DIKUsGLF.js} +1 -1
  196. langflow/frontend/assets/{index-VHmUHUUU.js → index-DJESSNJi.js} +1 -1
  197. langflow/frontend/assets/{index-BdIWbCEL.js → index-DMCWDJOl.js} +1 -1
  198. langflow/frontend/assets/{index-DK8vNpXK.js → index-DOEvKC2X.js} +1 -1
  199. langflow/frontend/assets/{index-C7V5U9yH.js → index-DOQDkSoK.js} +1 -1
  200. langflow/frontend/assets/{index-D0HmkH0H.js → index-DXAfIEvs.js} +1 -1
  201. langflow/frontend/assets/{index-C9N80hP8.js → index-DZP_SaHb.js} +1 -1
  202. langflow/frontend/assets/{index-B2ggrBuR.js → index-DZxUIhWh.js} +1 -1
  203. langflow/frontend/assets/{index-DS9I4y48.js → index-Dda2u_yz.js} +1 -1
  204. langflow/frontend/assets/{index-BLROcaSz.js → index-Dg8N3NSO.js} +1 -1
  205. langflow/frontend/assets/{index-Dpz3oBf5.js → index-DkGhPNeA.js} +1 -1
  206. langflow/frontend/assets/{index-BnLT29qW.js → index-Dka_Rk4-.js} +1 -1
  207. langflow/frontend/assets/{index-B5ed-sAv.js → index-DljpLeCW.js} +1 -1
  208. langflow/frontend/assets/{index-Cx__T92e.js → index-DnVYJtVO.js} +1 -1
  209. langflow/frontend/assets/{index-hOkEW3JP.js → index-DqbzUcI5.js} +1 -1
  210. langflow/frontend/assets/{index-BxkZkBgQ.js → index-Dr6pVDPI.js} +1 -1
  211. langflow/frontend/assets/{index-BIkqesA-.js → index-DsoX2o1S.js} +1 -1
  212. langflow/frontend/assets/{index-Cpgkb0Q3.js → index-DwfHWnX7.js} +1 -1
  213. langflow/frontend/assets/{index-B9Mo3ndZ.js → index-Dx-Z87KT.js} +1 -1
  214. langflow/frontend/assets/{index-R7q8cAek.js → index-DyqITq51.js} +1 -1
  215. langflow/frontend/assets/{index-DKEXZFUO.js → index-DzIv3RyR.js} +1 -1
  216. langflow/frontend/assets/{index-BJrY2Fiu.js → index-G4ro0MjT.js} +1 -1
  217. langflow/frontend/assets/{index-IFGgPiye.js → index-H7J7w7fa.js} +1 -1
  218. langflow/frontend/assets/{index-lKEJpUsF.js → index-KWY77KfV.js} +1 -1
  219. langflow/frontend/assets/{index-DDNNv4C0.js → index-U9GWm1eH.js} +1 -1
  220. langflow/frontend/assets/{index-BRWNIt9F.js → index-Un9pWxnP.js} +1 -1
  221. langflow/frontend/assets/{index-BCK-ZyIh.js → index-Xi4TplbI.js} +1 -1
  222. langflow/frontend/assets/{index-BEKoRwsX.js → index-_cbGmjF4.js} +1 -1
  223. langflow/frontend/assets/{index-7xXgqu09.js → index-cEXY6V06.js} +1 -1
  224. langflow/frontend/assets/{index-D87Zw62M.js → index-dyXKnkMi.js} +1 -1
  225. langflow/frontend/assets/{index-CG7cp0nD.js → index-eUkS6iJM.js} +1 -1
  226. langflow/frontend/assets/{index-CoUlHbtg.js → index-ekfMOqrF.js} +1 -1
  227. langflow/frontend/assets/{index-DhzEUXfr.js → index-gdb7XMS8.js} +1 -1
  228. langflow/frontend/assets/{index-D9eflZfP.js → index-hZUcL0MZ.js} +1 -1
  229. langflow/frontend/assets/{index-CwIxqYlT.js → index-kkA-qHB_.js} +1 -1
  230. langflow/frontend/assets/{index-sS6XLk3j.js → index-mzl9ULw5.js} +1 -1
  231. langflow/frontend/assets/{index-BjENqyKe.js → index-oxHBZk2v.js} +1 -1
  232. langflow/frontend/assets/{index-BejHxU5W.js → index-p2kStSPe.js} +1 -1
  233. langflow/frontend/assets/{index-BOYTBrh9.js → index-paQEWYGT.js} +1 -1
  234. langflow/frontend/assets/{index-Cd5zuUUK.js → index-r_8gs4nL.js} +1 -1
  235. langflow/frontend/assets/{index-AlJ7td-D.js → index-uiKla4UR.js} +1 -1
  236. langflow/frontend/assets/{index-B8y58M9b.js → index-vJOO5U8M.js} +1 -1
  237. langflow/frontend/assets/{index-CF4dtI6S.js → index-w72fDjpG.js} +1 -1
  238. langflow/frontend/assets/{index-C2Xd7UkR.js → index-zV82kQ6k.js} +1 -1
  239. langflow/frontend/assets/lazyIconImports-DTNgvPE-.js +2 -0
  240. langflow/frontend/assets/{use-post-add-user-HN0rRnhv.js → use-post-add-user-CvtuazTg.js} +1 -1
  241. langflow/frontend/index.html +1 -1
  242. langflow/graph/edge/base.py +2 -3
  243. langflow/graph/graph/base.py +14 -12
  244. langflow/graph/graph/constants.py +3 -0
  245. langflow/graph/utils.py +6 -6
  246. langflow/graph/vertex/base.py +4 -5
  247. langflow/graph/vertex/param_handler.py +1 -1
  248. langflow/graph/vertex/vertex_types.py +2 -2
  249. langflow/helpers/flow.py +1 -1
  250. langflow/initial_setup/setup.py +32 -30
  251. langflow/initial_setup/starter_projects/Blog Writer.json +2 -2
  252. langflow/initial_setup/starter_projects/Custom Component Generator.json +2 -2
  253. langflow/initial_setup/starter_projects/Document Q&A.json +1 -1
  254. langflow/initial_setup/starter_projects/Hybrid Search RAG.json +2 -2
  255. langflow/initial_setup/starter_projects/Instagram Copywriter.json +3 -3
  256. langflow/initial_setup/starter_projects/Invoice Summarizer.json +1 -1
  257. langflow/initial_setup/starter_projects/Knowledge Ingestion.json +4 -4
  258. langflow/initial_setup/starter_projects/Knowledge Retrieval.json +2 -2
  259. langflow/initial_setup/starter_projects/Market Research.json +3 -3
  260. langflow/initial_setup/starter_projects/Meeting Summary.json +6 -6
  261. langflow/initial_setup/starter_projects/Memory Chatbot.json +2 -2
  262. langflow/initial_setup/starter_projects/News Aggregator.json +5 -22
  263. langflow/initial_setup/starter_projects/Nvidia Remix.json +3 -20
  264. langflow/initial_setup/starter_projects/Pok/303/251dex Agent.json" +1 -1
  265. langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json +1 -1
  266. langflow/initial_setup/starter_projects/Price Deal Finder.json +5 -5
  267. langflow/initial_setup/starter_projects/Research Agent.json +3 -3
  268. langflow/initial_setup/starter_projects/SaaS Pricing.json +1 -1
  269. langflow/initial_setup/starter_projects/Search agent.json +1 -1
  270. langflow/initial_setup/starter_projects/Sequential Tasks Agents.json +7 -7
  271. langflow/initial_setup/starter_projects/Simple Agent.json +3 -3
  272. langflow/initial_setup/starter_projects/Social Media Agent.json +1 -1
  273. langflow/initial_setup/starter_projects/Text Sentiment Analysis.json +1 -1
  274. langflow/initial_setup/starter_projects/Travel Planning Agents.json +3 -3
  275. langflow/initial_setup/starter_projects/Vector Store RAG.json +5 -5
  276. langflow/initial_setup/starter_projects/Youtube Analysis.json +3 -3
  277. langflow/interface/components.py +23 -22
  278. langflow/interface/initialize/loading.py +5 -5
  279. langflow/interface/run.py +1 -1
  280. langflow/interface/utils.py +1 -1
  281. langflow/io/__init__.py +0 -1
  282. langflow/langflow_launcher.py +1 -1
  283. langflow/load/load.py +2 -7
  284. langflow/logging/__init__.py +0 -1
  285. langflow/logging/logger.py +191 -115
  286. langflow/logging/setup.py +1 -1
  287. langflow/main.py +37 -52
  288. langflow/memory.py +7 -7
  289. langflow/middleware.py +1 -1
  290. langflow/processing/process.py +4 -4
  291. langflow/schema/artifact.py +2 -2
  292. langflow/schema/data.py +10 -2
  293. langflow/schema/dataframe.py +1 -1
  294. langflow/schema/message.py +1 -1
  295. langflow/serialization/serialization.py +1 -1
  296. langflow/services/auth/utils.py +2 -2
  297. langflow/services/cache/disk.py +1 -1
  298. langflow/services/cache/service.py +3 -3
  299. langflow/services/database/models/flow/model.py +2 -7
  300. langflow/services/database/models/transactions/crud.py +2 -2
  301. langflow/services/database/models/user/crud.py +2 -2
  302. langflow/services/database/service.py +8 -8
  303. langflow/services/database/utils.py +6 -5
  304. langflow/services/deps.py +2 -3
  305. langflow/services/factory.py +1 -1
  306. langflow/services/flow/flow_runner.py +7 -12
  307. langflow/services/job_queue/service.py +16 -15
  308. langflow/services/manager.py +3 -4
  309. langflow/services/settings/auth.py +1 -1
  310. langflow/services/settings/base.py +3 -8
  311. langflow/services/settings/manager.py +1 -1
  312. langflow/services/settings/utils.py +1 -1
  313. langflow/services/socket/__init__.py +0 -1
  314. langflow/services/socket/service.py +3 -3
  315. langflow/services/socket/utils.py +4 -4
  316. langflow/services/state/service.py +1 -2
  317. langflow/services/storage/factory.py +1 -1
  318. langflow/services/storage/local.py +9 -8
  319. langflow/services/storage/s3.py +11 -10
  320. langflow/services/store/service.py +3 -3
  321. langflow/services/store/utils.py +3 -2
  322. langflow/services/task/temp_flow_cleanup.py +7 -7
  323. langflow/services/telemetry/service.py +10 -10
  324. langflow/services/tracing/arize_phoenix.py +2 -2
  325. langflow/services/tracing/langfuse.py +1 -1
  326. langflow/services/tracing/langsmith.py +1 -1
  327. langflow/services/tracing/langwatch.py +1 -1
  328. langflow/services/tracing/opik.py +1 -1
  329. langflow/services/tracing/service.py +25 -6
  330. langflow/services/tracing/traceloop.py +245 -0
  331. langflow/services/utils.py +7 -7
  332. langflow/services/variable/kubernetes.py +3 -3
  333. langflow/services/variable/kubernetes_secrets.py +2 -1
  334. langflow/services/variable/service.py +5 -5
  335. langflow/utils/component_utils.py +9 -6
  336. langflow/utils/util.py +5 -5
  337. langflow/utils/validate.py +3 -3
  338. langflow/utils/voice_utils.py +2 -2
  339. {langflow_base_nightly-0.5.0.dev36.dist-info → langflow_base_nightly-0.5.0.dev38.dist-info}/METADATA +2 -1
  340. {langflow_base_nightly-0.5.0.dev36.dist-info → langflow_base_nightly-0.5.0.dev38.dist-info}/RECORD +342 -340
  341. langflow/frontend/assets/lazyIconImports-Bh1TFfvH.js +0 -2
  342. {langflow_base_nightly-0.5.0.dev36.dist-info → langflow_base_nightly-0.5.0.dev38.dist-info}/WHEEL +0 -0
  343. {langflow_base_nightly-0.5.0.dev36.dist-info → langflow_base_nightly-0.5.0.dev38.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,10 @@
1
+ import signal
2
+ import sys
3
+ import traceback
4
+ from contextlib import suppress
5
+
1
6
  from docling_core.types.doc import DoclingDocument
7
+ from loguru import logger
2
8
 
3
9
  from langflow.schema.data import Data
4
10
  from langflow.schema.dataframe import DataFrame
@@ -49,3 +55,191 @@ def extract_docling_documents(data_inputs: Data | list[Data] | DataFrame, doc_ke
49
55
  msg = f"Invalid input type in collection: {e}"
50
56
  raise TypeError(msg) from e
51
57
  return documents
58
+
59
+
60
+ def docling_worker(file_paths: list[str], queue, pipeline: str, ocr_engine: str):
61
+ """Worker function for processing files with Docling in a separate process."""
62
+ # Signal handling for graceful shutdown
63
+ shutdown_requested = False
64
+
65
+ def signal_handler(signum: int, frame) -> None: # noqa: ARG001
66
+ """Handle shutdown signals gracefully."""
67
+ nonlocal shutdown_requested
68
+ signal_names: dict[int, str] = {signal.SIGTERM: "SIGTERM", signal.SIGINT: "SIGINT"}
69
+ signal_name = signal_names.get(signum, f"signal {signum}")
70
+
71
+ logger.debug(f"Docling worker received {signal_name}, initiating graceful shutdown...")
72
+ shutdown_requested = True
73
+
74
+ # Send shutdown notification to parent process
75
+ with suppress(Exception):
76
+ queue.put({"error": f"Worker interrupted by {signal_name}", "shutdown": True})
77
+
78
+ # Exit gracefully
79
+ sys.exit(0)
80
+
81
+ def check_shutdown() -> None:
82
+ """Check if shutdown was requested and exit if so."""
83
+ if shutdown_requested:
84
+ logger.info("Shutdown requested, exiting worker...")
85
+
86
+ with suppress(Exception):
87
+ queue.put({"error": "Worker shutdown requested", "shutdown": True})
88
+
89
+ sys.exit(0)
90
+
91
+ # Register signal handlers early
92
+ try:
93
+ signal.signal(signal.SIGTERM, signal_handler)
94
+ signal.signal(signal.SIGINT, signal_handler)
95
+ logger.debug("Signal handlers registered for graceful shutdown")
96
+ except (OSError, ValueError) as e:
97
+ # Some signals might not be available on all platforms
98
+ logger.warning(f"Warning: Could not register signal handlers: {e}")
99
+
100
+ # Check for shutdown before heavy imports
101
+ check_shutdown()
102
+
103
+ try:
104
+ from docling.datamodel.base_models import ConversionStatus, InputFormat
105
+ from docling.datamodel.pipeline_options import OcrOptions, PdfPipelineOptions, VlmPipelineOptions
106
+ from docling.document_converter import DocumentConverter, FormatOption, PdfFormatOption
107
+ from docling.models.factories import get_ocr_factory
108
+ from docling.pipeline.vlm_pipeline import VlmPipeline
109
+
110
+ # Check for shutdown after imports
111
+ check_shutdown()
112
+ logger.debug("Docling dependencies loaded successfully")
113
+
114
+ except ModuleNotFoundError:
115
+ msg = (
116
+ "Docling is an optional dependency of Langflow. "
117
+ "Install with `uv pip install 'langflow[docling]'` "
118
+ "or refer to the documentation"
119
+ )
120
+ queue.put({"error": msg})
121
+ return
122
+ except ImportError as e:
123
+ # A different import failed (e.g., a transitive dependency); preserve details.
124
+ queue.put({"error": f"Failed to import a Docling dependency: {e}"})
125
+ return
126
+ except KeyboardInterrupt:
127
+ logger.warning("KeyboardInterrupt during imports, exiting...")
128
+ queue.put({"error": "Worker interrupted during imports", "shutdown": True})
129
+ return
130
+
131
+ # Configure the standard PDF pipeline
132
+ def _get_standard_opts() -> PdfPipelineOptions:
133
+ check_shutdown() # Check before heavy operations
134
+
135
+ pipeline_options = PdfPipelineOptions()
136
+ pipeline_options.do_ocr = ocr_engine != ""
137
+ if pipeline_options.do_ocr:
138
+ ocr_factory = get_ocr_factory(
139
+ allow_external_plugins=False,
140
+ )
141
+
142
+ ocr_options: OcrOptions = ocr_factory.create_options(
143
+ kind=ocr_engine,
144
+ )
145
+ pipeline_options.ocr_options = ocr_options
146
+ return pipeline_options
147
+
148
+ # Configure the VLM pipeline
149
+ def _get_vlm_opts() -> VlmPipelineOptions:
150
+ check_shutdown() # Check before heavy operations
151
+ return VlmPipelineOptions()
152
+
153
+ # Configure the main format options and create the DocumentConverter()
154
+ def _get_converter() -> DocumentConverter:
155
+ check_shutdown() # Check before heavy operations
156
+
157
+ if pipeline == "standard":
158
+ pdf_format_option = PdfFormatOption(
159
+ pipeline_options=_get_standard_opts(),
160
+ )
161
+ elif pipeline == "vlm":
162
+ pdf_format_option = PdfFormatOption(pipeline_cls=VlmPipeline, pipeline_options=_get_vlm_opts())
163
+ else:
164
+ msg = f"Unknown pipeline: {pipeline!r}"
165
+ raise ValueError(msg)
166
+
167
+ format_options: dict[InputFormat, FormatOption] = {
168
+ InputFormat.PDF: pdf_format_option,
169
+ InputFormat.IMAGE: pdf_format_option,
170
+ }
171
+
172
+ return DocumentConverter(format_options=format_options)
173
+
174
+ try:
175
+ # Check for shutdown before creating converter (can be slow)
176
+ check_shutdown()
177
+ logger.info(f"Initializing {pipeline} pipeline with OCR: {ocr_engine or 'disabled'}")
178
+
179
+ converter = _get_converter()
180
+
181
+ # Check for shutdown before processing files
182
+ check_shutdown()
183
+ logger.info(f"Starting to process {len(file_paths)} files...")
184
+
185
+ # Process files with periodic shutdown checks
186
+ results = []
187
+ for i, file_path in enumerate(file_paths):
188
+ # Check for shutdown before processing each file
189
+ check_shutdown()
190
+
191
+ logger.debug(f"Processing file {i + 1}/{len(file_paths)}: {file_path}")
192
+
193
+ try:
194
+ # Process single file (we can't easily interrupt convert_all)
195
+ single_result = converter.convert_all([file_path])
196
+ results.extend(single_result)
197
+
198
+ # Check for shutdown after each file
199
+ check_shutdown()
200
+
201
+ except (OSError, ValueError, RuntimeError, ImportError) as file_error:
202
+ # Handle specific file processing errors
203
+ logger.error(f"Error processing file {file_path}: {file_error}")
204
+ # Continue with other files, but check for shutdown
205
+ check_shutdown()
206
+ except Exception as file_error: # noqa: BLE001
207
+ # Catch any other unexpected errors to prevent worker crash
208
+ logger.error(f"Unexpected error processing file {file_path}: {file_error}")
209
+ # Continue with other files, but check for shutdown
210
+ check_shutdown()
211
+
212
+ # Final shutdown check before sending results
213
+ check_shutdown()
214
+
215
+ # Process the results while maintaining the original structure
216
+ processed_data = [
217
+ {"document": res.document, "file_path": str(res.input.file), "status": res.status.name}
218
+ if res.status == ConversionStatus.SUCCESS
219
+ else None
220
+ for res in results
221
+ ]
222
+
223
+ logger.info(f"Successfully processed {len([d for d in processed_data if d])} files")
224
+ queue.put(processed_data)
225
+
226
+ except KeyboardInterrupt:
227
+ logger.warning("KeyboardInterrupt during processing, exiting gracefully...")
228
+ queue.put({"error": "Worker interrupted during processing", "shutdown": True})
229
+ return
230
+ except Exception as e: # noqa: BLE001
231
+ if shutdown_requested:
232
+ logger.exception("Exception occurred during shutdown, exiting...")
233
+ return
234
+
235
+ # Send any processing error to the main process with traceback
236
+ error_info = {"error": str(e), "traceback": traceback.format_exc()}
237
+ logger.error(f"Error in worker: {error_info}")
238
+ queue.put(error_info)
239
+ finally:
240
+ logger.info("Docling worker finishing...")
241
+ # Ensure we don't leave any hanging processes
242
+ if shutdown_requested:
243
+ logger.debug("Worker shutdown completed")
244
+ else:
245
+ logger.debug("Worker completed normally")
@@ -1,5 +1,10 @@
1
1
  import math
2
2
  from collections import Counter
3
+ from pathlib import Path
4
+ from uuid import UUID
5
+
6
+ from langflow.services.database.models.user.crud import get_user_by_id
7
+ from langflow.services.deps import session_scope
3
8
 
4
9
 
5
10
  def compute_tfidf(documents: list[str], query_terms: list[str]) -> list[float]:
@@ -102,3 +107,31 @@ def compute_bm25(documents: list[str], query_terms: list[str], k1: float = 1.2,
102
107
  scores.append(doc_score)
103
108
 
104
109
  return scores
110
+
111
+
112
+ async def get_knowledge_bases(kb_root: Path, user_id: UUID | str) -> list[str]:
113
+ """Retrieve a list of available knowledge bases.
114
+
115
+ Returns:
116
+ A list of knowledge base names.
117
+ """
118
+ if not kb_root.exists():
119
+ return []
120
+
121
+ # Get the current user
122
+ async with session_scope() as db:
123
+ if not user_id:
124
+ msg = "User ID is required for fetching knowledge bases."
125
+ raise ValueError(msg)
126
+ user_id = UUID(user_id) if isinstance(user_id, str) else user_id
127
+ current_user = await get_user_by_id(db, user_id)
128
+ if not current_user:
129
+ msg = f"User with ID {user_id} not found."
130
+ raise ValueError(msg)
131
+ kb_user = current_user.username
132
+ kb_path = kb_root / kb_user
133
+
134
+ if not kb_path.exists():
135
+ return []
136
+
137
+ return [str(d.name) for d in kb_path.iterdir() if not d.name.startswith(".") and d.is_dir()]
@@ -2,10 +2,10 @@ import concurrent.futures
2
2
  import json
3
3
 
4
4
  import httpx
5
- from loguru import logger
6
5
  from pydantic import BaseModel, SecretStr
7
6
 
8
7
  from langflow.field_typing import Embeddings
8
+ from langflow.logging.logger import logger
9
9
 
10
10
 
11
11
  class AIMLEmbeddingsImpl(BaseModel, Embeddings):
@@ -1,6 +1,5 @@
1
- from loguru import logger
2
-
3
1
  from langflow.graph.schema import ResultData, RunOutputs
2
+ from langflow.logging.logger import logger
4
3
  from langflow.schema.data import Data
5
4
  from langflow.schema.message import Message
6
5
 
@@ -1 +0,0 @@
1
- # noqa: A005
@@ -2,7 +2,8 @@ from functools import lru_cache
2
2
  from typing import Any
3
3
 
4
4
  import httpx
5
- from loguru import logger
5
+
6
+ from langflow.logging.logger import logger
6
7
 
7
8
 
8
9
  @lru_cache(maxsize=1)
langflow/base/mcp/util.py CHANGED
@@ -15,12 +15,12 @@ import httpx
15
15
  from anyio import ClosedResourceError
16
16
  from httpx import codes as httpx_codes
17
17
  from langchain_core.tools import StructuredTool
18
- from loguru import logger
19
18
  from mcp import ClientSession
20
19
  from mcp.shared.exceptions import McpError
21
20
  from pydantic import BaseModel, Field, create_model
22
21
  from sqlmodel import select
23
22
 
23
+ from langflow.logging.logger import logger
24
24
  from langflow.services.database.models.flow.model import Flow
25
25
  from langflow.services.deps import get_settings_service
26
26
 
@@ -214,7 +214,7 @@ def create_tool_coroutine(tool_name: str, arg_schema: type[BaseModel], client) -
214
214
  try:
215
215
  return await client.run_tool(tool_name, arguments=validated.model_dump())
216
216
  except Exception as e:
217
- logger.error(f"Tool '{tool_name}' execution failed: {e}")
217
+ await logger.aerror(f"Tool '{tool_name}' execution failed: {e}")
218
218
  # Re-raise with more context
219
219
  msg = f"Tool '{tool_name}' execution failed: {e}"
220
220
  raise ValueError(msg) from e
@@ -264,7 +264,7 @@ def get_unique_name(base_name, max_length, existing_names):
264
264
  i += 1
265
265
 
266
266
 
267
- async def get_flow_snake_case(flow_name: str, user_id: str, session, is_action: bool | None = None) -> Flow | None:
267
+ async def get_flow_snake_case(flow_name: str, user_id: str, session, *, is_action: bool | None = None) -> Flow | None:
268
268
  uuid_user_id = UUID(user_id) if isinstance(user_id, str) else user_id
269
269
  stmt = select(Flow).where(Flow.user_id == uuid_user_id).where(Flow.is_component == False) # noqa: E712
270
270
  flows = (await session.exec(stmt)).all()
@@ -506,7 +506,7 @@ class MCPSessionManager:
506
506
  break
507
507
  except (RuntimeError, KeyError, ClosedResourceError, ValueError, asyncio.TimeoutError) as e:
508
508
  # Handle common recoverable errors without stopping the cleanup loop
509
- logger.warning(f"Error in periodic cleanup: {e}")
509
+ await logger.awarning(f"Error in periodic cleanup: {e}")
510
510
 
511
511
  async def _cleanup_idle_sessions(self):
512
512
  """Clean up sessions that have been idle for too long."""
@@ -523,7 +523,7 @@ class MCPSessionManager:
523
523
 
524
524
  # Clean up idle sessions
525
525
  for session_id in sessions_to_remove:
526
- logger.info(f"Cleaning up idle session {session_id} for server {server_key}")
526
+ await logger.ainfo(f"Cleaning up idle session {session_id} for server {server_key}")
527
527
  await self._cleanup_session_by_id(server_key, session_id)
528
528
 
529
529
  # Remove server entry if no sessions left
@@ -561,7 +561,7 @@ class MCPSessionManager:
561
561
  # Use a shorter timeout for the connectivity test to fail fast
562
562
  response = await asyncio.wait_for(session.list_tools(), timeout=3.0)
563
563
  except (asyncio.TimeoutError, ConnectionError, OSError, ValueError) as e:
564
- logger.debug(f"Session connectivity test failed (standard error): {e}")
564
+ await logger.adebug(f"Session connectivity test failed (standard error): {e}")
565
565
  return False
566
566
  except Exception as e:
567
567
  # Handle MCP-specific errors that might not be in the standard list
@@ -574,27 +574,27 @@ class MCPSessionManager:
574
574
  or "Transport closed" in error_str
575
575
  or "Stream closed" in error_str
576
576
  ):
577
- logger.debug(f"Session connectivity test failed (MCP connection error): {e}")
577
+ await logger.adebug(f"Session connectivity test failed (MCP connection error): {e}")
578
578
  return False
579
579
  # Re-raise unexpected errors
580
- logger.warning(f"Unexpected error in connectivity test: {e}")
580
+ await logger.awarning(f"Unexpected error in connectivity test: {e}")
581
581
  raise
582
582
  else:
583
583
  # Validate that we got a meaningful response
584
584
  if response is None:
585
- logger.debug("Session connectivity test failed: received None response")
585
+ await logger.adebug("Session connectivity test failed: received None response")
586
586
  return False
587
587
  try:
588
588
  # Check if we can access the tools list (even if empty)
589
589
  tools = getattr(response, "tools", None)
590
590
  if tools is None:
591
- logger.debug("Session connectivity test failed: no tools attribute in response")
591
+ await logger.adebug("Session connectivity test failed: no tools attribute in response")
592
592
  return False
593
593
  except (AttributeError, TypeError) as e:
594
- logger.debug(f"Session connectivity test failed while validating response: {e}")
594
+ await logger.adebug(f"Session connectivity test failed while validating response: {e}")
595
595
  return False
596
596
  else:
597
- logger.debug(f"Session connectivity test passed: found {len(tools)} tools")
597
+ await logger.adebug(f"Session connectivity test passed: found {len(tools)} tools")
598
598
  return True
599
599
 
600
600
  async def get_session(self, context_id: str, connection_params, transport_type: str):
@@ -625,32 +625,32 @@ class MCPSessionManager:
625
625
 
626
626
  # Quick health check
627
627
  if await self._validate_session_connectivity(session):
628
- logger.debug(f"Reusing existing session {session_id} for server {server_key}")
628
+ await logger.adebug(f"Reusing existing session {session_id} for server {server_key}")
629
629
  # record mapping & bump ref-count for backwards compatibility
630
630
  self._context_to_session[context_id] = (server_key, session_id)
631
631
  self._session_refcount[(server_key, session_id)] = (
632
632
  self._session_refcount.get((server_key, session_id), 0) + 1
633
633
  )
634
634
  return session
635
- logger.info(f"Session {session_id} for server {server_key} failed health check, cleaning up")
635
+ await logger.ainfo(f"Session {session_id} for server {server_key} failed health check, cleaning up")
636
636
  await self._cleanup_session_by_id(server_key, session_id)
637
637
  else:
638
638
  # Task is done, clean up
639
- logger.info(f"Session {session_id} for server {server_key} task is done, cleaning up")
639
+ await logger.ainfo(f"Session {session_id} for server {server_key} task is done, cleaning up")
640
640
  await self._cleanup_session_by_id(server_key, session_id)
641
641
 
642
642
  # Check if we've reached the maximum number of sessions for this server
643
643
  if len(sessions) >= MAX_SESSIONS_PER_SERVER:
644
644
  # Remove the oldest session
645
645
  oldest_session_id = min(sessions.keys(), key=lambda x: sessions[x]["last_used"])
646
- logger.info(
646
+ await logger.ainfo(
647
647
  f"Maximum sessions reached for server {server_key}, removing oldest session {oldest_session_id}"
648
648
  )
649
649
  await self._cleanup_session_by_id(server_key, oldest_session_id)
650
650
 
651
651
  # Create new session
652
652
  session_id = f"{server_key}_{len(sessions)}"
653
- logger.info(f"Creating new session {session_id} for server {server_key}")
653
+ await logger.ainfo(f"Creating new session {session_id} for server {server_key}")
654
654
 
655
655
  if transport_type == "stdio":
656
656
  session, task = await self._create_stdio_session(session_id, connection_params)
@@ -700,7 +700,7 @@ class MCPSessionManager:
700
700
  try:
701
701
  await event.wait()
702
702
  except asyncio.CancelledError:
703
- logger.info(f"Session {session_id} is shutting down")
703
+ await logger.ainfo(f"Session {session_id} is shutting down")
704
704
  except Exception as e: # noqa: BLE001
705
705
  if not session_future.done():
706
706
  session_future.set_exception(e)
@@ -723,7 +723,7 @@ class MCPSessionManager:
723
723
  await task
724
724
  self._background_tasks.discard(task)
725
725
  msg = f"Timeout waiting for STDIO session {session_id} to initialize"
726
- logger.error(msg)
726
+ await logger.aerror(msg)
727
727
  raise ValueError(msg) from timeout_err
728
728
 
729
729
  return session, task
@@ -759,7 +759,7 @@ class MCPSessionManager:
759
759
  try:
760
760
  await event.wait()
761
761
  except asyncio.CancelledError:
762
- logger.info(f"Session {session_id} is shutting down")
762
+ await logger.ainfo(f"Session {session_id} is shutting down")
763
763
  except Exception as e: # noqa: BLE001
764
764
  if not session_future.done():
765
765
  session_future.set_exception(e)
@@ -782,7 +782,7 @@ class MCPSessionManager:
782
782
  await task
783
783
  self._background_tasks.discard(task)
784
784
  msg = f"Timeout waiting for SSE session {session_id} to initialize"
785
- logger.error(msg)
785
+ await logger.aerror(msg)
786
786
  raise ValueError(msg) from timeout_err
787
787
 
788
788
  return session, task
@@ -813,9 +813,9 @@ class MCPSessionManager:
813
813
  if hasattr(session, "aclose"):
814
814
  try:
815
815
  await session.aclose()
816
- logger.debug("Successfully closed session %s using aclose()", session_id)
816
+ await logger.adebug("Successfully closed session %s using aclose()", session_id)
817
817
  except Exception as e: # noqa: BLE001
818
- logger.debug("Error closing session %s with aclose(): %s", session_id, e)
818
+ await logger.adebug("Error closing session %s with aclose(): %s", session_id, e)
819
819
 
820
820
  # If no aclose, try regular close method
821
821
  elif hasattr(session, "close"):
@@ -824,18 +824,20 @@ class MCPSessionManager:
824
824
  if inspect.iscoroutinefunction(session.close):
825
825
  # It's an async method
826
826
  await session.close()
827
- logger.debug("Successfully closed session %s using async close()", session_id)
827
+ await logger.adebug("Successfully closed session %s using async close()", session_id)
828
828
  else:
829
829
  # Try calling it and check if result is awaitable
830
830
  close_result = session.close()
831
831
  if inspect.isawaitable(close_result):
832
832
  await close_result
833
- logger.debug("Successfully closed session %s using awaitable close()", session_id)
833
+ await logger.adebug(
834
+ "Successfully closed session %s using awaitable close()", session_id
835
+ )
834
836
  else:
835
837
  # It's a synchronous close
836
- logger.debug("Successfully closed session %s using sync close()", session_id)
838
+ await logger.adebug("Successfully closed session %s using sync close()", session_id)
837
839
  except Exception as e: # noqa: BLE001
838
- logger.debug("Error closing session %s with close(): %s", session_id, e)
840
+ await logger.adebug("Error closing session %s with close(): %s", session_id, e)
839
841
 
840
842
  # Cancel the background task which will properly close the session
841
843
  if "task" in session_info:
@@ -845,9 +847,9 @@ class MCPSessionManager:
845
847
  try:
846
848
  await task
847
849
  except asyncio.CancelledError:
848
- logger.info(f"Cancelled task for session {session_id}")
850
+ await logger.ainfo(f"Cancelled task for session {session_id}")
849
851
  except Exception as e: # noqa: BLE001
850
- logger.warning(f"Error cleaning up session {session_id}: {e}")
852
+ await logger.awarning(f"Error cleaning up session {session_id}: {e}")
851
853
  finally:
852
854
  # Remove from sessions dict
853
855
  del sessions[session_id]
@@ -900,7 +902,7 @@ class MCPSessionManager:
900
902
  """
901
903
  mapping = self._context_to_session.get(context_id)
902
904
  if not mapping:
903
- logger.debug(f"No session mapping found for context_id {context_id}")
905
+ await logger.adebug(f"No session mapping found for context_id {context_id}")
904
906
  return
905
907
 
906
908
  server_key, session_id = mapping
@@ -1031,7 +1033,7 @@ class MCPStdioClient:
1031
1033
 
1032
1034
  for attempt in range(max_retries):
1033
1035
  try:
1034
- logger.debug(f"Attempting to run tool '{tool_name}' (attempt {attempt + 1}/{max_retries})")
1036
+ await logger.adebug(f"Attempting to run tool '{tool_name}' (attempt {attempt + 1}/{max_retries})")
1035
1037
  # Get or create persistent session
1036
1038
  session = await self._get_or_create_session()
1037
1039
 
@@ -1041,7 +1043,7 @@ class MCPStdioClient:
1041
1043
  )
1042
1044
  except Exception as e:
1043
1045
  current_error_type = type(e).__name__
1044
- logger.warning(f"Tool '{tool_name}' failed on attempt {attempt + 1}: {current_error_type} - {e}")
1046
+ await logger.awarning(f"Tool '{tool_name}' failed on attempt {attempt + 1}: {current_error_type} - {e}")
1045
1047
 
1046
1048
  # Import specific MCP error types for detection
1047
1049
  try:
@@ -1056,14 +1058,14 @@ class MCPStdioClient:
1056
1058
 
1057
1059
  # If we're getting the same error type repeatedly, don't retry
1058
1060
  if last_error_type == current_error_type and attempt > 0:
1059
- logger.error(f"Repeated {current_error_type} error for tool '{tool_name}', not retrying")
1061
+ await logger.aerror(f"Repeated {current_error_type} error for tool '{tool_name}', not retrying")
1060
1062
  break
1061
1063
 
1062
1064
  last_error_type = current_error_type
1063
1065
 
1064
1066
  # If it's a connection error (ClosedResourceError or MCP connection closed) and we have retries left
1065
1067
  if (is_closed_resource_error or is_mcp_connection_error) and attempt < max_retries - 1:
1066
- logger.warning(
1068
+ await logger.awarning(
1067
1069
  f"MCP session connection issue for tool '{tool_name}', retrying with fresh session..."
1068
1070
  )
1069
1071
  # Clean up the dead session
@@ -1076,7 +1078,7 @@ class MCPStdioClient:
1076
1078
 
1077
1079
  # If it's a timeout error and we have retries left, try once more
1078
1080
  if is_timeout_error and attempt < max_retries - 1:
1079
- logger.warning(f"Tool '{tool_name}' timed out, retrying...")
1081
+ await logger.awarning(f"Tool '{tool_name}' timed out, retrying...")
1080
1082
  # Don't clean up session for timeouts, might just be a slow response
1081
1083
  await asyncio.sleep(1.0)
1082
1084
  continue
@@ -1089,7 +1091,7 @@ class MCPStdioClient:
1089
1091
  or is_timeout_error
1090
1092
  ):
1091
1093
  msg = f"Failed to run tool '{tool_name}' after {attempt + 1} attempts: {e}"
1092
- logger.error(msg)
1094
+ await logger.aerror(msg)
1093
1095
  # Clean up failed session from cache
1094
1096
  if self._session_context and self._component_cache:
1095
1097
  cache_key = f"mcp_session_stdio_{self._session_context}"
@@ -1099,12 +1101,12 @@ class MCPStdioClient:
1099
1101
  # Re-raise unexpected errors
1100
1102
  raise
1101
1103
  else:
1102
- logger.debug(f"Tool '{tool_name}' completed successfully")
1104
+ await logger.adebug(f"Tool '{tool_name}' completed successfully")
1103
1105
  return result
1104
1106
 
1105
1107
  # This should never be reached due to the exception handling above
1106
1108
  msg = f"Failed to run tool '{tool_name}': Maximum retries exceeded with repeated {last_error_type} errors"
1107
- logger.error(msg)
1109
+ await logger.aerror(msg)
1108
1110
  raise ValueError(msg)
1109
1111
 
1110
1112
  async def disconnect(self):
@@ -1213,7 +1215,7 @@ class MCPSseClient:
1213
1215
  return response.headers.get("Location", url)
1214
1216
  # Don't treat 404 as an error here - let the main connection handle it
1215
1217
  except (httpx.RequestError, httpx.HTTPError) as e:
1216
- logger.warning(f"Error checking redirects: {e}")
1218
+ await logger.awarning(f"Error checking redirects: {e}")
1217
1219
  return url
1218
1220
 
1219
1221
  async def _connect_to_server(
@@ -1336,7 +1338,7 @@ class MCPSseClient:
1336
1338
 
1337
1339
  for attempt in range(max_retries):
1338
1340
  try:
1339
- logger.debug(f"Attempting to run tool '{tool_name}' (attempt {attempt + 1}/{max_retries})")
1341
+ await logger.adebug(f"Attempting to run tool '{tool_name}' (attempt {attempt + 1}/{max_retries})")
1340
1342
  # Get or create persistent session
1341
1343
  session = await self._get_or_create_session()
1342
1344
 
@@ -1349,7 +1351,7 @@ class MCPSseClient:
1349
1351
  )
1350
1352
  except Exception as e:
1351
1353
  current_error_type = type(e).__name__
1352
- logger.warning(f"Tool '{tool_name}' failed on attempt {attempt + 1}: {current_error_type} - {e}")
1354
+ await logger.awarning(f"Tool '{tool_name}' failed on attempt {attempt + 1}: {current_error_type} - {e}")
1353
1355
 
1354
1356
  # Import specific MCP error types for detection
1355
1357
  try:
@@ -1367,14 +1369,14 @@ class MCPSseClient:
1367
1369
 
1368
1370
  # If we're getting the same error type repeatedly, don't retry
1369
1371
  if last_error_type == current_error_type and attempt > 0:
1370
- logger.error(f"Repeated {current_error_type} error for tool '{tool_name}', not retrying")
1372
+ await logger.aerror(f"Repeated {current_error_type} error for tool '{tool_name}', not retrying")
1371
1373
  break
1372
1374
 
1373
1375
  last_error_type = current_error_type
1374
1376
 
1375
1377
  # If it's a connection error (ClosedResourceError or MCP connection closed) and we have retries left
1376
1378
  if (is_closed_resource_error or is_mcp_connection_error) and attempt < max_retries - 1:
1377
- logger.warning(
1379
+ await logger.awarning(
1378
1380
  f"MCP session connection issue for tool '{tool_name}', retrying with fresh session..."
1379
1381
  )
1380
1382
  # Clean up the dead session
@@ -1387,7 +1389,7 @@ class MCPSseClient:
1387
1389
 
1388
1390
  # If it's a timeout error and we have retries left, try once more
1389
1391
  if is_timeout_error and attempt < max_retries - 1:
1390
- logger.warning(f"Tool '{tool_name}' timed out, retrying...")
1392
+ await logger.awarning(f"Tool '{tool_name}' timed out, retrying...")
1391
1393
  # Don't clean up session for timeouts, might just be a slow response
1392
1394
  await asyncio.sleep(1.0)
1393
1395
  continue
@@ -1400,7 +1402,7 @@ class MCPSseClient:
1400
1402
  or is_timeout_error
1401
1403
  ):
1402
1404
  msg = f"Failed to run tool '{tool_name}' after {attempt + 1} attempts: {e}"
1403
- logger.error(msg)
1405
+ await logger.aerror(msg)
1404
1406
  # Clean up failed session from cache
1405
1407
  if self._session_context and self._component_cache:
1406
1408
  cache_key = f"mcp_session_sse_{self._session_context}"
@@ -1410,12 +1412,12 @@ class MCPSseClient:
1410
1412
  # Re-raise unexpected errors
1411
1413
  raise
1412
1414
  else:
1413
- logger.debug(f"Tool '{tool_name}' completed successfully")
1415
+ await logger.adebug(f"Tool '{tool_name}' completed successfully")
1414
1416
  return result
1415
1417
 
1416
1418
  # This should never be reached due to the exception handling above
1417
1419
  msg = f"Failed to run tool '{tool_name}': Maximum retries exceeded with repeated {last_error_type} errors"
1418
- logger.error(msg)
1420
+ await logger.aerror(msg)
1419
1421
  raise ValueError(msg)
1420
1422
 
1421
1423
  async def disconnect(self):
@@ -252,7 +252,7 @@ class LCModelComponent(Component):
252
252
  if stream:
253
253
  lf_message, result = await self._handle_stream(runnable, inputs)
254
254
  else:
255
- message = runnable.invoke(inputs)
255
+ message = await runnable.ainvoke(inputs)
256
256
  result = message.content if hasattr(message, "content") else message
257
257
  if isinstance(message, AIMessage):
258
258
  status_message = self.build_status_message(message)
@@ -288,7 +288,7 @@ class LCModelComponent(Component):
288
288
  else:
289
289
  session_id = None
290
290
  model_message = Message(
291
- text=runnable.stream(inputs),
291
+ text=runnable.astream(inputs),
292
292
  sender=MESSAGE_SENDER_AI,
293
293
  sender_name="AI",
294
294
  properties={"icon": self.icon, "state": "partial"},
@@ -298,7 +298,7 @@ class LCModelComponent(Component):
298
298
  lf_message = await self.send_message(model_message)
299
299
  result = lf_message.text
300
300
  else:
301
- message = runnable.invoke(inputs)
301
+ message = await runnable.ainvoke(inputs)
302
302
  result = message.content if hasattr(message, "content") else message
303
303
  return lf_message, result
304
304