langflow-base-nightly 0.5.0.dev38__py3-none-any.whl → 0.5.0.dev39__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 (233) hide show
  1. langflow/alembic/versions/0882f9657f22_encrypt_existing_mcp_auth_settings_.py +122 -0
  2. langflow/api/v1/mcp_projects.py +373 -52
  3. langflow/api/v1/schemas.py +1 -2
  4. langflow/components/FAISS/__init__.py +34 -0
  5. langflow/components/agents/agent.py +246 -52
  6. langflow/components/cassandra/__init__.py +40 -0
  7. langflow/components/chroma/__init__.py +34 -0
  8. langflow/components/clickhouse/__init__.py +34 -0
  9. langflow/components/couchbase/__init__.py +34 -0
  10. langflow/components/datastax/__init__.py +3 -3
  11. langflow/components/elastic/__init__.py +37 -0
  12. langflow/components/milvus/__init__.py +34 -0
  13. langflow/components/mongodb/__init__.py +34 -0
  14. langflow/components/ollama/ollama.py +1 -0
  15. langflow/components/perplexity/perplexity.py +3 -13
  16. langflow/components/pgvector/__init__.py +34 -0
  17. langflow/components/pinecone/__init__.py +34 -0
  18. langflow/components/qdrant/__init__.py +34 -0
  19. langflow/components/redis/__init__.py +36 -2
  20. langflow/components/redis/redis.py +75 -29
  21. langflow/components/redis/redis_chat.py +43 -0
  22. langflow/components/supabase/__init__.py +37 -0
  23. langflow/components/upstash/__init__.py +34 -0
  24. langflow/components/vectara/__init__.py +37 -0
  25. langflow/components/vectorstores/__init__.py +0 -69
  26. langflow/components/vectorstores/local_db.py +1 -0
  27. langflow/components/weaviate/__init__.py +34 -0
  28. langflow/custom/dependency_analyzer.py +165 -0
  29. langflow/custom/utils.py +34 -16
  30. langflow/frontend/assets/{SlackIcon-BhW6H3JR.js → SlackIcon-Cr3Q15Px.js} +1 -1
  31. langflow/frontend/assets/{Wikipedia-Dx5jbiy3.js → Wikipedia-GxM5sPdM.js} +1 -1
  32. langflow/frontend/assets/{Wolfram-CIyonzwo.js → Wolfram-BN3-VOCA.js} +1 -1
  33. langflow/frontend/assets/{index-DOEvKC2X.js → index-28oOcafk.js} +1 -1
  34. langflow/frontend/assets/{index-Bhv79Zso.js → index-2wSXqBtB.js} +1 -1
  35. langflow/frontend/assets/{index-BRmSeoWR.js → index-3wW7BClE.js} +1 -1
  36. langflow/frontend/assets/{index-eUkS6iJM.js → index-6pyH3ZJB.js} +1 -1
  37. langflow/frontend/assets/{index-Cr5v2ave.js → index-AWCSdofD.js} +1 -1
  38. langflow/frontend/assets/{index-C27Jj_26.js → index-B2Zgv_xv.js} +1 -1
  39. langflow/frontend/assets/{index-BKKrUElc.js → index-B2ptVQGM.js} +1 -1
  40. langflow/frontend/assets/{index-BnAFhkSN.js → index-B3TANVes.js} +1 -1
  41. langflow/frontend/assets/{index-hZUcL0MZ.js → index-B4yCvZKV.js} +1 -1
  42. langflow/frontend/assets/{index-BPR2mEFC.js → index-BC65VuWx.js} +1 -1
  43. langflow/frontend/assets/{index-CgU7KF4I.js → index-BCDSei1q.js} +1 -1
  44. langflow/frontend/assets/{index-CzHzeZuA.js → index-BJy50PvP.js} +1 -1
  45. langflow/frontend/assets/{index-DkGhPNeA.js → index-BKseQQ2I.js} +1 -1
  46. langflow/frontend/assets/{index-BVFaF7HW.js → index-BLTxEeTi.js} +1 -1
  47. langflow/frontend/assets/{index-cEXY6V06.js → index-BRg1f4Mu.js} +1 -1
  48. langflow/frontend/assets/{index-C2eQmQsn.js → index-BS8Vo8nc.js} +1 -1
  49. langflow/frontend/assets/{index-gdb7XMS8.js → index-BTKOU4xC.js} +1 -1
  50. langflow/frontend/assets/{index-U9GWm1eH.js → index-BVwJDmw-.js} +1 -1
  51. langflow/frontend/assets/{index-BWt5xGeA.js → index-BWYuQ2Sj.js} +1 -1
  52. langflow/frontend/assets/{index-Dx-Z87KT.js → index-BWdLILDG.js} +1 -1
  53. langflow/frontend/assets/{index-paQEWYGT.js → index-BZcw4827.js} +1 -1
  54. langflow/frontend/assets/{index-BDQrd7Tj.js → index-Bbi87Ve4.js} +1 -1
  55. langflow/frontend/assets/{index-vJOO5U8M.js → index-Bf0IYKLd.js} +1 -1
  56. langflow/frontend/assets/{index-1Q3VBqKn.js → index-Bg5nrMRh.js} +1 -1
  57. langflow/frontend/assets/{index-BFQ8KFK0.js → index-BiC280Nx.js} +1 -1
  58. langflow/frontend/assets/{index-CFNTYfFK.js → index-BiKKN6FR.js} +1 -1
  59. langflow/frontend/assets/{index-BPfdqCc_.js → index-Bief6eyJ.js} +1 -1
  60. langflow/frontend/assets/{index-Cxy9sEpy.js → index-BkXec1Yf.js} +1 -1
  61. langflow/frontend/assets/{index-D4tjMhfY.js → index-Bnl6QHtP.js} +1 -1
  62. langflow/frontend/assets/{index-BD7Io1hL.js → index-BpxbUiZD.js} +1978 -1978
  63. langflow/frontend/assets/{index-Ch5r0oW6.js → index-BrJV8psX.js} +1 -1
  64. langflow/frontend/assets/{index-DOQDkSoK.js → index-BwLWcUXL.js} +1 -1
  65. langflow/frontend/assets/{index-CMHpjHZl.js → index-Bx7dBY26.js} +1 -1
  66. langflow/frontend/assets/{index-CbnWRlYY.js → index-C-EdnFdA.js} +1 -1
  67. langflow/frontend/assets/{index-DljpLeCW.js → index-C-Xfg4cD.js} +1 -1
  68. langflow/frontend/assets/{index-Bwi4flFg.js → index-C1f2wMat.js} +1 -1
  69. langflow/frontend/assets/index-C1xroOlH.css +1 -0
  70. langflow/frontend/assets/{index-D6CSIrp1.js → index-C3KequvP.js} +1 -1
  71. langflow/frontend/assets/{index-BYjw7Gk3.js → index-C3ZjKdCD.js} +1 -1
  72. langflow/frontend/assets/{index-DIKUsGLF.js → index-C3l0zYn0.js} +1 -1
  73. langflow/frontend/assets/{index-CfPBgkqg.js → index-C3yvArUT.js} +1 -1
  74. langflow/frontend/assets/{index-CsLQiWNf.js → index-C9Cxnkl8.js} +1 -1
  75. langflow/frontend/assets/{index-mzl9ULw5.js → index-CBc8fEAE.js} +1 -1
  76. langflow/frontend/assets/{index-CEJNWPhA.js → index-CBvrGgID.js} +1 -1
  77. langflow/frontend/assets/{index-DwfHWnX7.js → index-CD-PqGCY.js} +1 -1
  78. langflow/frontend/assets/{index-dyXKnkMi.js → index-CGO1CiUr.js} +1 -1
  79. langflow/frontend/assets/{index-Dka_Rk4-.js → index-CH5UVA9b.js} +1 -1
  80. langflow/frontend/assets/{index-uiKla4UR.js → index-CLJeJYjH.js} +1 -1
  81. langflow/frontend/assets/{index-D9kwEzPB.js → index-CMZ79X-Y.js} +1 -1
  82. langflow/frontend/assets/{index-BrVhdPZb.js → index-CMzfJKiW.js} +1 -1
  83. langflow/frontend/assets/{index-Bct1s6__.js → index-CNw1H-Wc.js} +1 -1
  84. langflow/frontend/assets/{index-B7uEuOPK.js → index-CPHEscq9.js} +1 -1
  85. langflow/frontend/assets/{index-ekfMOqrF.js → index-CRPKJZw9.js} +1 -1
  86. langflow/frontend/assets/{index-G4ro0MjT.js → index-CRPyCfYy.js} +1 -1
  87. langflow/frontend/assets/{index-CSu8KHOi.js → index-CRcMqCIj.js} +1 -1
  88. langflow/frontend/assets/{index-DsoX2o1S.js → index-CUVDws8F.js} +1 -1
  89. langflow/frontend/assets/{index-r_8gs4nL.js → index-CVWQfRYZ.js} +1 -1
  90. langflow/frontend/assets/{index-7hzXChQz.js → index-CVl6MbaM.js} +1 -1
  91. langflow/frontend/assets/{index-B8UR8v-Q.js → index-CVwWoX99.js} +1 -1
  92. langflow/frontend/assets/{index-Dda2u_yz.js → index-CWPzZtSx.js} +1 -1
  93. langflow/frontend/assets/{index-BKeZt2hQ.js → index-CZqRL9DE.js} +1 -1
  94. langflow/frontend/assets/{index-DHngW1k8.js → index-CdIf07Rw.js} +1 -1
  95. langflow/frontend/assets/{index-C--IDAyc.js → index-Cewy7JZE.js} +1 -1
  96. langflow/frontend/assets/{index-DZP_SaHb.js → index-CfwLpbMM.js} +1 -1
  97. langflow/frontend/assets/{index-CuCM7Wu7.js → index-CiR1dxI4.js} +1 -1
  98. langflow/frontend/assets/{index-Xi4TplbI.js → index-CiixOzDG.js} +1 -1
  99. langflow/frontend/assets/{index-BLYw9MK2.js → index-ClsuDmR6.js} +1 -1
  100. langflow/frontend/assets/{index-DMCWDJOl.js → index-CmEYYRN1.js} +1 -1
  101. langflow/frontend/assets/{index-CrAF-31Y.js → index-Co20d-eQ.js} +1 -1
  102. langflow/frontend/assets/{index-DXAfIEvs.js → index-CpzXS6md.js} +1 -1
  103. langflow/frontend/assets/{index-BmYJJ5YS.js → index-Cqpzl1J4.js} +1 -1
  104. langflow/frontend/assets/{index-KWY77KfV.js → index-CtVIONP2.js} +1 -1
  105. langflow/frontend/assets/{index-B3KCdQ91.js → index-CuFXdTx4.js} +1 -1
  106. langflow/frontend/assets/{index-p2kStSPe.js → index-Cyd2HtHK.js} +1 -1
  107. langflow/frontend/assets/{index-CkjwSTSM.js → index-D-1tA8Dt.js} +1 -1
  108. langflow/frontend/assets/{index-BFf0HTFI.js → index-D-KY3kkq.js} +1 -1
  109. langflow/frontend/assets/{index-BYhcGLTV.js → index-D-_B1a8v.js} +1 -1
  110. langflow/frontend/assets/{index-Dr6pVDPI.js → index-D14EWPyZ.js} +1 -1
  111. langflow/frontend/assets/{index-BDuk0d7P.js → index-D2N3l-cw.js} +1 -1
  112. langflow/frontend/assets/{index-BvGQfVBD.js → index-D5ETnvJa.js} +1 -1
  113. langflow/frontend/assets/{index-D1oynC8a.js → index-D7kquVv2.js} +1 -1
  114. langflow/frontend/assets/{index-B1XqWJhG.js → index-DA6-bvgN.js} +1 -1
  115. langflow/frontend/assets/{index-DzIv3RyR.js → index-DDWBeudF.js} +1 -1
  116. langflow/frontend/assets/{index-BKlQbl-6.js → index-DDcMAaG4.js} +1 -1
  117. langflow/frontend/assets/{index-CkK25zZO.js → index-DHgomBdh.js} +1 -1
  118. langflow/frontend/assets/{index-Bj3lSwvZ.js → index-DJP-ss47.js} +1 -1
  119. langflow/frontend/assets/{index-DDXsm8tz.js → index-DQ7VYqQc.js} +1 -1
  120. langflow/frontend/assets/{index-BNQIbda3.js → index-DTqbvGC0.js} +1 -1
  121. langflow/frontend/assets/{index-BzoRPtTY.js → index-DUpri6zF.js} +1 -1
  122. langflow/frontend/assets/{index-35sspuLu.js → index-DV3utZDZ.js} +1 -1
  123. langflow/frontend/assets/{index-BpmqDOeZ.js → index-DXRfN4HV.js} +1 -1
  124. langflow/frontend/assets/{index-C0E3_MIK.js → index-Db9dYSzy.js} +1 -1
  125. langflow/frontend/assets/{index-C8K0r39B.js → index-DdtMEn6I.js} +1 -1
  126. langflow/frontend/assets/{index-BLsVo9iW.js → index-DfDhMHgQ.js} +1 -1
  127. langflow/frontend/assets/{index-BZFljdMa.js → index-Dfe7qfvf.js} +1 -1
  128. langflow/frontend/assets/{index-CyP3py8K.js → index-DhtZ5hx8.js} +1 -1
  129. langflow/frontend/assets/{index-w72fDjpG.js → index-DiB3CTo8.js} +1 -1
  130. langflow/frontend/assets/{index-CY7_TBTC.js → index-DiGWASY5.js} +1 -1
  131. langflow/frontend/assets/{index-CmSFKgiD.js → index-Dl5amdBz.js} +1 -1
  132. langflow/frontend/assets/{index-B0m53xKd.js → index-DlD4dXlZ.js} +1 -1
  133. langflow/frontend/assets/{index-DnVYJtVO.js → index-DmeiHnfl.js} +1 -1
  134. langflow/frontend/assets/index-Dmu-X5-4.js +1 -0
  135. langflow/frontend/assets/{index-CWYiSeWV.js → index-DpVWih90.js} +1 -1
  136. langflow/frontend/assets/{index-CjsommIr.js → index-DrDrcajG.js} +1 -1
  137. langflow/frontend/assets/{index-Un9pWxnP.js → index-Du-pc0KE.js} +1 -1
  138. langflow/frontend/assets/{index-oxHBZk2v.js → index-DwPkMTaY.js} +1 -1
  139. langflow/frontend/assets/{index-CgwykVGh.js → index-DwQEZe3C.js} +1 -1
  140. langflow/frontend/assets/{index-BmIx1cws.js → index-DyJFTK24.js} +1 -1
  141. langflow/frontend/assets/{index-0XQqYgdG.js → index-J38wh62w.js} +1 -1
  142. langflow/frontend/assets/{index-H7J7w7fa.js → index-Kwdl-e29.js} +1 -1
  143. langflow/frontend/assets/{index-CUKmGsI6.js → index-OwPvCmpW.js} +1 -1
  144. langflow/frontend/assets/{index-zV82kQ6k.js → index-Tw3Os-DN.js} +1 -1
  145. langflow/frontend/assets/{index-8cuhogZP.js → index-X0guhYF8.js} +1 -1
  146. langflow/frontend/assets/{index-BUse-kxM.js → index-dJWNxIRH.js} +1 -1
  147. langflow/frontend/assets/{index-DyqITq51.js → index-dcJ8-agu.js} +1 -1
  148. langflow/frontend/assets/{index-Cg53lrYh.js → index-eo2mAtL-.js} +1 -1
  149. langflow/frontend/assets/{index-DqbzUcI5.js → index-hG24k5xJ.js} +1 -1
  150. langflow/frontend/assets/{index-BQrVDjR1.js → index-h_aSZHf3.js} +1 -1
  151. langflow/frontend/assets/{index-kkA-qHB_.js → index-hbndqB9B.js} +1 -1
  152. langflow/frontend/assets/{index-DZxUIhWh.js → index-iJngutFo.js} +1 -1
  153. langflow/frontend/assets/{index-Dg8N3NSO.js → index-lTpteg8t.js} +1 -1
  154. langflow/frontend/assets/{index-DDhJVVel.js → index-lZX9AvZW.js} +1 -1
  155. langflow/frontend/assets/{index-BHhnpSkW.js → index-m8QA6VNM.js} +1 -1
  156. langflow/frontend/assets/{index-Bk4mTwnI.js → index-o0D2S7xW.js} +1 -1
  157. langflow/frontend/assets/{index-DJESSNJi.js → index-ovFJ_0J6.js} +1 -1
  158. langflow/frontend/assets/{index-DH6o91_s.js → index-pYJJOcma.js} +1 -1
  159. langflow/frontend/assets/{index-Bo-ww0Bb.js → index-sI75DsdM.js} +1 -1
  160. langflow/frontend/assets/{index-BcAgItH4.js → index-xvFOmxx4.js} +1 -1
  161. langflow/frontend/assets/{index-_cbGmjF4.js → index-z3SRY-mX.js} +1 -1
  162. langflow/frontend/assets/lazyIconImports-D97HEZkE.js +2 -0
  163. langflow/frontend/assets/{use-post-add-user-CvtuazTg.js → use-post-add-user-C0MdTpQ5.js} +1 -1
  164. langflow/frontend/index.html +2 -2
  165. langflow/graph/graph/base.py +1 -1
  166. langflow/initial_setup/starter_projects/Basic Prompt Chaining.json +26 -0
  167. langflow/initial_setup/starter_projects/Basic Prompting.json +26 -0
  168. langflow/initial_setup/starter_projects/Blog Writer.json +56 -0
  169. langflow/initial_setup/starter_projects/Custom Component Generator.json +35 -0
  170. langflow/initial_setup/starter_projects/Document Q&A.json +26 -0
  171. langflow/initial_setup/starter_projects/Financial Report Parser.json +43 -0
  172. langflow/initial_setup/starter_projects/Hybrid Search RAG.json +83 -1
  173. langflow/initial_setup/starter_projects/Image Sentiment Analysis.json +43 -0
  174. langflow/initial_setup/starter_projects/Instagram Copywriter.json +49 -1
  175. langflow/initial_setup/starter_projects/Invoice Summarizer.json +40 -1
  176. langflow/initial_setup/starter_projects/Knowledge Ingestion.json +71 -0
  177. langflow/initial_setup/starter_projects/Knowledge Retrieval.json +63 -0
  178. langflow/initial_setup/starter_projects/Market Research.json +57 -1
  179. langflow/initial_setup/starter_projects/Meeting Summary.json +95 -0
  180. langflow/initial_setup/starter_projects/Memory Chatbot.json +35 -0
  181. langflow/initial_setup/starter_projects/News Aggregator.json +61 -1
  182. langflow/initial_setup/starter_projects/Nvidia Remix.json +67 -2
  183. langflow/initial_setup/starter_projects/Pok/303/251dex Agent.json" +48 -1
  184. langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json +43 -0
  185. langflow/initial_setup/starter_projects/Price Deal Finder.json +53 -1
  186. langflow/initial_setup/starter_projects/Research Agent.json +40 -1
  187. langflow/initial_setup/starter_projects/Research Translation Loop.json +66 -0
  188. langflow/initial_setup/starter_projects/SEO Keyword Generator.json +17 -0
  189. langflow/initial_setup/starter_projects/SaaS Pricing.json +27 -1
  190. langflow/initial_setup/starter_projects/Search agent.json +40 -1
  191. langflow/initial_setup/starter_projects/Sequential Tasks Agents.json +72 -3
  192. langflow/initial_setup/starter_projects/Simple Agent.json +57 -1
  193. langflow/initial_setup/starter_projects/Social Media Agent.json +77 -1
  194. langflow/initial_setup/starter_projects/Text Sentiment Analysis.json +34 -0
  195. langflow/initial_setup/starter_projects/Travel Planning Agents.json +51 -3
  196. langflow/initial_setup/starter_projects/Twitter Thread Generator.json +80 -0
  197. langflow/initial_setup/starter_projects/Vector Store RAG.json +109 -2
  198. langflow/initial_setup/starter_projects/Youtube Analysis.json +82 -1
  199. langflow/initial_setup/starter_projects/vector_store_rag.py +1 -1
  200. langflow/processing/process.py +3 -0
  201. langflow/services/auth/mcp_encryption.py +104 -0
  202. langflow/services/settings/feature_flags.py +1 -1
  203. {langflow_base_nightly-0.5.0.dev38.dist-info → langflow_base_nightly-0.5.0.dev39.dist-info}/METADATA +1 -1
  204. {langflow_base_nightly-0.5.0.dev38.dist-info → langflow_base_nightly-0.5.0.dev39.dist-info}/RECORD +229 -211
  205. langflow/components/vectorstores/redis.py +0 -89
  206. langflow/frontend/assets/index-BWgIWfv2.js +0 -1
  207. langflow/frontend/assets/index-CqS7zir1.css +0 -1
  208. langflow/frontend/assets/lazyIconImports-DTNgvPE-.js +0 -2
  209. /langflow/components/{vectorstores → FAISS}/faiss.py +0 -0
  210. /langflow/components/{vectorstores → cassandra}/cassandra.py +0 -0
  211. /langflow/components/{datastax/cassandra.py → cassandra/cassandra_chat.py} +0 -0
  212. /langflow/components/{vectorstores → cassandra}/cassandra_graph.py +0 -0
  213. /langflow/components/{vectorstores → chroma}/chroma.py +0 -0
  214. /langflow/components/{vectorstores → clickhouse}/clickhouse.py +0 -0
  215. /langflow/components/{vectorstores → couchbase}/couchbase.py +0 -0
  216. /langflow/components/{vectorstores → datastax}/astradb.py +0 -0
  217. /langflow/components/{vectorstores → datastax}/astradb_graph.py +0 -0
  218. /langflow/components/{vectorstores → datastax}/graph_rag.py +0 -0
  219. /langflow/components/{vectorstores → datastax}/hcd.py +0 -0
  220. /langflow/components/{vectorstores → elastic}/elasticsearch.py +0 -0
  221. /langflow/components/{vectorstores → elastic}/opensearch.py +0 -0
  222. /langflow/components/{vectorstores → milvus}/milvus.py +0 -0
  223. /langflow/components/{vectorstores → mongodb}/mongodb_atlas.py +0 -0
  224. /langflow/components/{vectorstores → pgvector}/pgvector.py +0 -0
  225. /langflow/components/{vectorstores → pinecone}/pinecone.py +0 -0
  226. /langflow/components/{vectorstores → qdrant}/qdrant.py +0 -0
  227. /langflow/components/{vectorstores → supabase}/supabase.py +0 -0
  228. /langflow/components/{vectorstores → upstash}/upstash.py +0 -0
  229. /langflow/components/{vectorstores → vectara}/vectara.py +0 -0
  230. /langflow/components/{vectorstores → vectara}/vectara_rag.py +0 -0
  231. /langflow/components/{vectorstores → weaviate}/weaviate.py +0 -0
  232. {langflow_base_nightly-0.5.0.dev38.dist-info → langflow_base_nightly-0.5.0.dev39.dist-info}/WHEEL +0 -0
  233. {langflow_base_nightly-0.5.0.dev38.dist-info → langflow_base_nightly-0.5.0.dev39.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,165 @@
1
+ """Dependency analysis utilities for custom components."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ast
6
+ import importlib.metadata as md
7
+ import sys
8
+ from dataclasses import asdict, dataclass
9
+ from functools import lru_cache
10
+
11
+ try:
12
+ STDLIB_MODULES: set[str] = set(sys.stdlib_module_names) # 3.10+
13
+ except AttributeError:
14
+ # Fallback heuristic if running on <3.10
15
+ STDLIB_MODULES = set(sys.builtin_module_names)
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class DependencyInfo:
20
+ """Information about a dependency imported in Python code."""
21
+
22
+ name: str # package name (e.g. "numpy", "requests")
23
+ version: str | None # package version if available
24
+ is_local: bool # True for relative imports (from .module import ...)
25
+
26
+
27
+ def _top_level(pkg: str) -> str:
28
+ """Extract top-level package name."""
29
+ return pkg.split(".", 1)[0]
30
+
31
+
32
+ def _is_relative(module: str | None) -> bool:
33
+ """Check if module is a relative import."""
34
+ return module is not None and module.startswith(".")
35
+
36
+
37
+ class _ImportVisitor(ast.NodeVisitor):
38
+ """AST visitor to extract import information."""
39
+
40
+ def __init__(self):
41
+ self.results: list[DependencyInfo] = []
42
+
43
+ def visit_Import(self, node: ast.Import):
44
+ for alias in node.names:
45
+ full = alias.name
46
+ dep = DependencyInfo(
47
+ name=_top_level(full),
48
+ version=None,
49
+ is_local=False, # Regular imports are not local
50
+ )
51
+ self.results.append(dep)
52
+
53
+ def visit_ImportFrom(self, node: ast.ImportFrom):
54
+ # Reconstruct full module name with proper relative import handling
55
+ if node.level > 0:
56
+ # Relative import: from .module import x or from ..parent import x
57
+ dots = "." * node.level
58
+ full_module = dots + (node.module or "")
59
+ else:
60
+ # Absolute import: from module import x
61
+ full_module = node.module or ""
62
+ for _alias in node.names:
63
+ dep = DependencyInfo(
64
+ name=_top_level(full_module.lstrip(".")) if full_module else "",
65
+ version=None,
66
+ is_local=_is_relative(full_module), # Check if it's a relative import
67
+ )
68
+ self.results.append(dep)
69
+
70
+
71
+ def _classify_dependency(dep: DependencyInfo) -> DependencyInfo:
72
+ """Resolve version information for external dependencies."""
73
+ version = None
74
+ if not dep.is_local and dep.name:
75
+ version = _get_distribution_version(dep.name)
76
+
77
+ return DependencyInfo(
78
+ name=dep.name,
79
+ version=version,
80
+ is_local=dep.is_local,
81
+ )
82
+
83
+
84
+ def analyze_dependencies(source: str, *, resolve_versions: bool = True) -> list[dict]:
85
+ """Return a list[dict] of dependencies imported by the given Python source code.
86
+
87
+ Args:
88
+ source: Python source code string
89
+ resolve_versions: Whether to resolve version information
90
+
91
+ Returns:
92
+ List of dependency dictionaries
93
+ """
94
+ code = source
95
+
96
+ # Parse the code and extract imports
97
+ tree = ast.parse(code)
98
+ visitor = _ImportVisitor()
99
+ visitor.visit(tree)
100
+
101
+ # Process and deduplicate dependencies by package name only
102
+ unique_packages: dict[str, DependencyInfo] = {}
103
+ for raw_dep in visitor.results:
104
+ processed_dep = _classify_dependency(raw_dep) if resolve_versions else raw_dep
105
+
106
+ # Skip stdlib imports and local imports - we only care about external dependencies
107
+ if processed_dep.name in STDLIB_MODULES or processed_dep.is_local:
108
+ continue
109
+
110
+ # Deduplicate by package name only (not full_module)
111
+ if processed_dep.name not in unique_packages:
112
+ unique_packages[processed_dep.name] = processed_dep
113
+
114
+ return [asdict(d) for d in unique_packages.values()]
115
+
116
+
117
+ def analyze_component_dependencies(component_code: str) -> dict:
118
+ """Analyze dependencies for a custom component.
119
+
120
+ Args:
121
+ component_code: The component's source code
122
+
123
+ Returns:
124
+ Dictionary with dependency analysis results
125
+ """
126
+ try:
127
+ deps = analyze_dependencies(component_code, resolve_versions=True)
128
+
129
+ return {
130
+ "total_dependencies": len(deps),
131
+ "dependencies": [{"name": d["name"], "version": d["version"]} for d in deps if d["name"]],
132
+ }
133
+ except (SyntaxError, TypeError, ValueError, ImportError):
134
+ # If analysis fails, return minimal info
135
+ return {
136
+ "total_dependencies": 0,
137
+ "dependencies": [],
138
+ }
139
+
140
+
141
+ # Cache the expensive packages_distributions() call globally
142
+ @lru_cache(maxsize=1)
143
+ def _get_packages_distributions():
144
+ """Cache the expensive packages_distributions() call."""
145
+ try:
146
+ return md.packages_distributions()
147
+ except (OSError, AttributeError, ValueError):
148
+ return {}
149
+
150
+
151
+ # Helper function to cache version lookups for installed distributions
152
+ @lru_cache(maxsize=128)
153
+ def _get_distribution_version(import_name: str):
154
+ try:
155
+ # Reverse-lookup: which distribution(s) provide this importable name?
156
+ reverse_map = _get_packages_distributions()
157
+ dist_names = reverse_map.get(import_name)
158
+ if not dist_names:
159
+ return None
160
+
161
+ # Take the first matching distribution
162
+ dist_name = dist_names[0]
163
+ return md.distribution(dist_name).version
164
+ except (ImportError, AttributeError, OSError, ValueError):
165
+ return None
langflow/custom/utils.py CHANGED
@@ -1,4 +1,6 @@
1
1
  # mypy: ignore-errors
2
+ from __future__ import annotations
3
+
2
4
  import ast
3
5
  import asyncio
4
6
  import contextlib
@@ -7,14 +9,13 @@ import inspect
7
9
  import re
8
10
  import traceback
9
11
  from pathlib import Path
10
- from typing import Any
11
- from uuid import UUID
12
+ from typing import TYPE_CHECKING, Any
12
13
 
13
14
  from fastapi import HTTPException
14
15
  from pydantic import BaseModel
15
16
 
16
17
  from langflow.custom.custom_component.component import Component
17
- from langflow.custom.custom_component.custom_component import CustomComponent
18
+ from langflow.custom.dependency_analyzer import analyze_component_dependencies
18
19
  from langflow.custom.directory_reader.utils import (
19
20
  abuild_custom_component_list_from_path,
20
21
  build_custom_component_list_from_path,
@@ -32,6 +33,11 @@ from langflow.type_extraction.type_extraction import extract_inner_type
32
33
  from langflow.utils import validate
33
34
  from langflow.utils.util import get_base_classes
34
35
 
36
+ if TYPE_CHECKING:
37
+ from uuid import UUID
38
+
39
+ from langflow.custom.custom_component.custom_component import CustomComponent
40
+
35
41
 
36
42
  def _generate_code_hash(source_code: str, modname: str) -> str:
37
43
  """Generate a hash of the component source code.
@@ -488,6 +494,15 @@ def build_custom_component_template_from_inputs(
488
494
  # ! This should be removed when we have a better way to handle this
489
495
  frontend_node.set_base_classes_from_outputs()
490
496
  reorder_fields(frontend_node, cc_instance._get_field_order())
497
+ frontend_node = build_component_metadata(frontend_node, cc_instance, module_name, ctype_name)
498
+
499
+ return frontend_node.to_dict(keep_name=False), cc_instance
500
+
501
+
502
+ def build_component_metadata(
503
+ frontend_node: CustomComponentFrontendNode, custom_component: CustomComponent, module_name: str, ctype_name: str
504
+ ):
505
+ """Build the metadata for a custom component."""
491
506
  if module_name:
492
507
  frontend_node.metadata["module"] = module_name
493
508
  else:
@@ -502,7 +517,19 @@ def build_custom_component_template_from_inputs(
502
517
  except Exception as exc: # noqa: BLE001
503
518
  logger.debug(f"Error generating code hash for {custom_component.__class__.__name__}", exc_info=exc)
504
519
 
505
- return frontend_node.to_dict(keep_name=False), cc_instance
520
+ # Analyze component dependencies
521
+ try:
522
+ dependency_info = analyze_component_dependencies(custom_component._code)
523
+ frontend_node.metadata["dependencies"] = dependency_info
524
+ except (SyntaxError, TypeError, ValueError, ImportError) as exc:
525
+ logger.warning(f"Failed to analyze dependencies for component {ctype_name}: {exc}")
526
+ # Set minimal dependency info on failure
527
+ frontend_node.metadata["dependencies"] = {
528
+ "total_dependencies": 0,
529
+ "dependencies": [],
530
+ }
531
+
532
+ return frontend_node
506
533
 
507
534
 
508
535
  def build_custom_component_template(
@@ -562,18 +589,9 @@ def build_custom_component_template(
562
589
  reorder_fields(frontend_node, custom_instance._get_field_order())
563
590
 
564
591
  if module_name:
565
- frontend_node.metadata["module"] = module_name
566
- else:
567
- module_name = get_module_name_from_display_name(frontend_node.display_name)
568
- frontend_node.metadata["module"] = f"custom_components.{module_name}"
569
-
570
- # Generate code hash for cache invalidation and debugging
571
- try:
572
- code_hash = _generate_code_hash(custom_component._code, module_name)
573
- if code_hash:
574
- frontend_node.metadata["code_hash"] = code_hash
575
- except Exception as exc: # noqa: BLE001
576
- logger.debug(f"Error generating code hash for {custom_component.__class__.__name__}", exc_info=exc)
592
+ frontend_node = build_component_metadata(
593
+ frontend_node, custom_component, module_name, custom_component.__class__.__name__
594
+ )
577
595
 
578
596
  return frontend_node.to_dict(keep_name=False), custom_instance
579
597
  except Exception as exc:
@@ -1 +1 @@
1
- import{j as a}from"./index-BD7Io1hL.js";const s=l=>a.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 54 54",width:"1em",height:"1em",...l,children:a.jsxs("g",{fill:"none",fillRule:"evenodd",children:[a.jsx("path",{fill:"#36C5F0",d:"M19.712.133a5.381 5.381 0 0 0-5.376 5.387 5.381 5.381 0 0 0 5.376 5.386h5.376V5.52A5.381 5.381 0 0 0 19.712.133m0 14.365H5.376A5.381 5.381 0 0 0 0 19.884a5.381 5.381 0 0 0 5.376 5.387h14.336a5.381 5.381 0 0 0 5.376-5.387 5.381 5.381 0 0 0-5.376-5.386"}),a.jsx("path",{fill:"#2EB67D",d:"M53.76 19.884a5.381 5.381 0 0 0-5.376-5.386 5.381 5.381 0 0 0-5.376 5.386v5.387h5.376a5.381 5.381 0 0 0 5.376-5.387m-14.336 0V5.52A5.381 5.381 0 0 0 34.048.133a5.381 5.381 0 0 0-5.376 5.387v14.364a5.381 5.381 0 0 0 5.376 5.387 5.381 5.381 0 0 0 5.376-5.387"}),a.jsx("path",{fill:"#ECB22E",d:"M34.048 54a5.381 5.381 0 0 0 5.376-5.387 5.381 5.381 0 0 0-5.376-5.386h-5.376v5.386A5.381 5.381 0 0 0 34.048 54m0-14.365h14.336a5.381 5.381 0 0 0 5.376-5.386 5.381 5.381 0 0 0-5.376-5.387H34.048a5.381 5.381 0 0 0-5.376 5.387 5.381 5.381 0 0 0 5.376 5.386"}),a.jsx("path",{fill:"#E01E5A",d:"M0 34.249a5.381 5.381 0 0 0 5.376 5.386 5.381 5.381 0 0 0 5.376-5.386v-5.387H5.376A5.381 5.381 0 0 0 0 34.25m14.336-.001v14.364A5.381 5.381 0 0 0 19.712 54a5.381 5.381 0 0 0 5.376-5.387V34.25a5.381 5.381 0 0 0-5.376-5.387 5.381 5.381 0 0 0-5.376 5.387"})]})});export{s as default};
1
+ import{j as a}from"./index-BpxbUiZD.js";const s=l=>a.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 54 54",width:"1em",height:"1em",...l,children:a.jsxs("g",{fill:"none",fillRule:"evenodd",children:[a.jsx("path",{fill:"#36C5F0",d:"M19.712.133a5.381 5.381 0 0 0-5.376 5.387 5.381 5.381 0 0 0 5.376 5.386h5.376V5.52A5.381 5.381 0 0 0 19.712.133m0 14.365H5.376A5.381 5.381 0 0 0 0 19.884a5.381 5.381 0 0 0 5.376 5.387h14.336a5.381 5.381 0 0 0 5.376-5.387 5.381 5.381 0 0 0-5.376-5.386"}),a.jsx("path",{fill:"#2EB67D",d:"M53.76 19.884a5.381 5.381 0 0 0-5.376-5.386 5.381 5.381 0 0 0-5.376 5.386v5.387h5.376a5.381 5.381 0 0 0 5.376-5.387m-14.336 0V5.52A5.381 5.381 0 0 0 34.048.133a5.381 5.381 0 0 0-5.376 5.387v14.364a5.381 5.381 0 0 0 5.376 5.387 5.381 5.381 0 0 0 5.376-5.387"}),a.jsx("path",{fill:"#ECB22E",d:"M34.048 54a5.381 5.381 0 0 0 5.376-5.387 5.381 5.381 0 0 0-5.376-5.386h-5.376v5.386A5.381 5.381 0 0 0 34.048 54m0-14.365h14.336a5.381 5.381 0 0 0 5.376-5.386 5.381 5.381 0 0 0-5.376-5.387H34.048a5.381 5.381 0 0 0-5.376 5.387 5.381 5.381 0 0 0 5.376 5.386"}),a.jsx("path",{fill:"#E01E5A",d:"M0 34.249a5.381 5.381 0 0 0 5.376 5.386 5.381 5.381 0 0 0 5.376-5.386v-5.387H5.376A5.381 5.381 0 0 0 0 34.25m14.336-.001v14.364A5.381 5.381 0 0 0 19.712 54a5.381 5.381 0 0 0 5.376-5.387V34.25a5.381 5.381 0 0 0-5.376-5.387 5.381 5.381 0 0 0-5.376 5.387"})]})});export{s as default};