lionagi 0.1.1__tar.gz → 0.1.2__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (215) hide show
  1. {lionagi-0.1.1/lionagi.egg-info → lionagi-0.1.2}/PKG-INFO +1 -1
  2. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/execute/structure_executor.py +21 -1
  3. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/monoflow/ReAct.py +3 -1
  4. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/monoflow/followup.py +3 -1
  5. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/component.py +197 -120
  6. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/condition.py +2 -0
  7. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/edge.py +33 -33
  8. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/graph/graph.py +1 -1
  9. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/tool/tool_manager.py +10 -9
  10. lionagi-0.1.2/lionagi/experimental/report/form.py +64 -0
  11. lionagi-0.1.2/lionagi/experimental/report/report.py +138 -0
  12. lionagi-0.1.2/lionagi/experimental/report/util.py +47 -0
  13. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/tool/schema.py +3 -3
  14. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/tool/tool_manager.py +1 -1
  15. lionagi-0.1.2/lionagi/experimental/validator/rule.py +139 -0
  16. lionagi-0.1.2/lionagi/experimental/validator/validator.py +56 -0
  17. lionagi-0.1.2/lionagi/experimental/work/__init__.py +10 -0
  18. lionagi-0.1.2/lionagi/experimental/work/async_queue.py +54 -0
  19. lionagi-0.1.2/lionagi/experimental/work/schema.py +73 -0
  20. lionagi-0.1.2/lionagi/experimental/work/work_function.py +67 -0
  21. lionagi-0.1.2/lionagi/experimental/work/worker.py +56 -0
  22. lionagi-0.1.2/lionagi/experimental/work2/form.py +371 -0
  23. lionagi-0.1.2/lionagi/experimental/work2/report.py +289 -0
  24. {lionagi-0.1.1/lionagi/experimental/work → lionagi-0.1.2/lionagi/experimental/work2}/tests.py +1 -1
  25. {lionagi-0.1.1/lionagi/experimental/work → lionagi-0.1.2/lionagi/experimental/work2}/work_function.py +1 -1
  26. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/storage/storage_util.py +4 -4
  27. lionagi-0.1.2/lionagi/integrations/storage/structure_excel.py +268 -0
  28. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/storage/to_excel.py +18 -9
  29. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/__init__.py +4 -0
  30. lionagi-0.1.2/lionagi/tests/libs/test_async.py +0 -0
  31. lionagi-0.1.2/lionagi/tests/test_core/__init__.py +0 -0
  32. lionagi-0.1.2/lionagi/tests/test_core/generic/__init__.py +0 -0
  33. lionagi-0.1.2/lionagi/tests/test_core/generic/test_component.py +89 -0
  34. lionagi-0.1.2/lionagi/version.py +1 -0
  35. {lionagi-0.1.1 → lionagi-0.1.2/lionagi.egg-info}/PKG-INFO +1 -1
  36. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi.egg-info/SOURCES.txt +21 -5
  37. lionagi-0.1.1/lionagi/experimental/work/_logger.py +0 -25
  38. lionagi-0.1.1/lionagi/version.py +0 -1
  39. {lionagi-0.1.1 → lionagi-0.1.2}/LICENSE +0 -0
  40. {lionagi-0.1.1 → lionagi-0.1.2}/README.md +0 -0
  41. {lionagi-0.1.1 → lionagi-0.1.2}/README.rst +0 -0
  42. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/__init__.py +0 -0
  43. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/__init__.py +0 -0
  44. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/agent/__init__.py +0 -0
  45. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/agent/base_agent.py +0 -0
  46. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/branch/__init__.py +0 -0
  47. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/branch/base.py +0 -0
  48. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/branch/branch.py +0 -0
  49. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/branch/executable_branch.py +0 -0
  50. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/branch/flow_mixin.py +0 -0
  51. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/branch/util.py +0 -0
  52. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/__init__.py +0 -0
  53. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/cot.py +0 -0
  54. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/plan.py +0 -0
  55. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/predict.py +0 -0
  56. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/react.py +0 -0
  57. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/score.py +0 -0
  58. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/select.py +0 -0
  59. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/sentiment.py +0 -0
  60. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/utils.py +0 -0
  61. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/direct/vote.py +0 -0
  62. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/execute/__init__.py +0 -0
  63. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/execute/base_executor.py +0 -0
  64. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/execute/branch_executor.py +0 -0
  65. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/execute/instruction_map_executor.py +0 -0
  66. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/execute/neo4j_executor.py +0 -0
  67. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/__init__.py +0 -0
  68. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/baseflow.py +0 -0
  69. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/mono_chat_mixin.py +0 -0
  70. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/monoflow/__init__.py +0 -0
  71. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/monoflow/chat.py +0 -0
  72. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/monoflow/chat_mixin.py +0 -0
  73. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/polyflow/__init__.py +0 -0
  74. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/flow/polyflow/chat.py +0 -0
  75. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/form/__init__.py +0 -0
  76. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/form/action_form.py +0 -0
  77. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/form/field_validator.py +0 -0
  78. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/form/form.py +0 -0
  79. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/form/mixin.py +0 -0
  80. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/form/scored_form.py +0 -0
  81. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/__init__.py +0 -0
  82. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/action.py +0 -0
  83. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/data_logger.py +0 -0
  84. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/mail.py +0 -0
  85. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/mailbox.py +0 -0
  86. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/node.py +0 -0
  87. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/relation.py +0 -0
  88. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/signal.py +0 -0
  89. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/structure.py +0 -0
  90. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/transfer.py +0 -0
  91. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/generic/work.py +0 -0
  92. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/graph/__init__.py +0 -0
  93. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/graph/tree.py +0 -0
  94. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/mail/__init__.py +0 -0
  95. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/mail/mail_manager.py +0 -0
  96. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/mail/schema.py +0 -0
  97. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/messages/__init__.py +0 -0
  98. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/messages/schema.py +0 -0
  99. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/session/__init__.py +0 -0
  100. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/session/session.py +0 -0
  101. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/tool/__init__.py +0 -0
  102. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/core/tool/tool.py +0 -0
  103. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/__init__.py +0 -0
  104. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/__init__.py +0 -0
  105. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/evaluator/__init__.py +0 -0
  106. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/evaluator/ast_evaluator.py +0 -0
  107. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/evaluator/base_evaluator.py +0 -0
  108. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/evaluator/sandbox_.py +0 -0
  109. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/evaluator/script_engine.py +0 -0
  110. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/parser/__init__.py +0 -0
  111. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/parser/base_parser.py +0 -0
  112. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/schema.py +0 -0
  113. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/template_/__init__.py +0 -0
  114. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/directive/template_/base_template.py +0 -0
  115. {lionagi-0.1.1/lionagi/experimental/tool → lionagi-0.1.2/lionagi/experimental/report}/__init__.py +0 -0
  116. {lionagi-0.1.1/lionagi/experimental/work → lionagi-0.1.2/lionagi/experimental/tool}/__init__.py +0 -0
  117. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/tool/function_calling.py +0 -0
  118. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/tool/manual.py +0 -0
  119. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/experimental/tool/util.py +0 -0
  120. {lionagi-0.1.1/lionagi/integrations/bridge/autogen_ → lionagi-0.1.2/lionagi/experimental/validator}/__init__.py +0 -0
  121. {lionagi-0.1.1/lionagi/integrations/bridge/langchain_ → lionagi-0.1.2/lionagi/experimental/work2}/__init__.py +0 -0
  122. {lionagi-0.1.1/lionagi/experimental/work → lionagi-0.1.2/lionagi/experimental/work2}/schema.py +0 -0
  123. {lionagi-0.1.1/lionagi/experimental/work → lionagi-0.1.2/lionagi/experimental/work2}/util.py +0 -0
  124. /lionagi-0.1.1/lionagi/experimental/work/exchange.py → /lionagi-0.1.2/lionagi/experimental/work2/work.py +0 -0
  125. {lionagi-0.1.1/lionagi/experimental/work → lionagi-0.1.2/lionagi/experimental/work2}/worker.py +0 -0
  126. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/__init__.py +0 -0
  127. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/__init__.py +0 -0
  128. {lionagi-0.1.1/lionagi/integrations/bridge/llamaindex_ → lionagi-0.1.2/lionagi/integrations/bridge/autogen_}/__init__.py +0 -0
  129. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/autogen_/autogen_.py +0 -0
  130. {lionagi-0.1.1/lionagi/integrations/bridge/pydantic_ → lionagi-0.1.2/lionagi/integrations/bridge/langchain_}/__init__.py +0 -0
  131. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/langchain_/documents.py +0 -0
  132. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/langchain_/langchain_bridge.py +0 -0
  133. {lionagi-0.1.1/lionagi/integrations/bridge/transformers_ → lionagi-0.1.2/lionagi/integrations/bridge/llamaindex_}/__init__.py +0 -0
  134. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/llamaindex_/get_index.py +0 -0
  135. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/llamaindex_/index.py +0 -0
  136. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +0 -0
  137. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/llamaindex_/llama_pack.py +0 -0
  138. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/llamaindex_/node_parser.py +0 -0
  139. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/llamaindex_/reader.py +0 -0
  140. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/llamaindex_/textnode.py +0 -0
  141. {lionagi-0.1.1/lionagi/integrations/chunker → lionagi-0.1.2/lionagi/integrations/bridge/pydantic_}/__init__.py +0 -0
  142. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/pydantic_/pydantic_bridge.py +0 -0
  143. {lionagi-0.1.1/lionagi/integrations/loader → lionagi-0.1.2/lionagi/integrations/bridge/transformers_}/__init__.py +0 -0
  144. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/bridge/transformers_/install_.py +0 -0
  145. {lionagi-0.1.1/lionagi/lions → lionagi-0.1.2/lionagi/integrations/chunker}/__init__.py +0 -0
  146. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/chunker/chunk.py +0 -0
  147. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/config/__init__.py +0 -0
  148. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/config/mlx_configs.py +0 -0
  149. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/config/oai_configs.py +0 -0
  150. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/config/ollama_configs.py +0 -0
  151. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/config/openrouter_configs.py +0 -0
  152. {lionagi-0.1.1/lionagi/lions/coder → lionagi-0.1.2/lionagi/integrations/loader}/__init__.py +0 -0
  153. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/loader/load.py +0 -0
  154. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/loader/load_util.py +0 -0
  155. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/__init__.py +0 -0
  156. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/litellm.py +0 -0
  157. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/mistralai.py +0 -0
  158. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/mlx_service.py +0 -0
  159. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/oai.py +0 -0
  160. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/ollama.py +0 -0
  161. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/openrouter.py +0 -0
  162. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/services.py +0 -0
  163. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/provider/transformers.py +0 -0
  164. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/storage/__init__.py +0 -0
  165. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/storage/neo4j.py +0 -0
  166. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/integrations/storage/to_csv.py +0 -0
  167. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_api.py +0 -0
  168. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_async.py +0 -0
  169. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_convert.py +0 -0
  170. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_dataframe.py +0 -0
  171. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_func_call.py +0 -0
  172. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_knowledge_graph.py +0 -0
  173. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_nested.py +0 -0
  174. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_parse.py +0 -0
  175. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_queue.py +0 -0
  176. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_tokenizer.py +0 -0
  177. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/ln_validate.py +0 -0
  178. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/libs/sys_util.py +0 -0
  179. {lionagi-0.1.1/lionagi/lions/researcher → lionagi-0.1.2/lionagi/lions}/__init__.py +0 -0
  180. {lionagi-0.1.1/lionagi/lions/researcher/data_source → lionagi-0.1.2/lionagi/lions/coder}/__init__.py +0 -0
  181. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/lions/coder/add_feature.py +0 -0
  182. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/lions/coder/base_prompts.py +0 -0
  183. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/lions/coder/coder.py +0 -0
  184. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/lions/coder/util.py +0 -0
  185. {lionagi-0.1.1/lionagi/tests → lionagi-0.1.2/lionagi/lions/researcher}/__init__.py +0 -0
  186. {lionagi-0.1.1/lionagi/tests/integrations → lionagi-0.1.2/lionagi/lions/researcher/data_source}/__init__.py +0 -0
  187. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/lions/researcher/data_source/finhub_.py +0 -0
  188. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/lions/researcher/data_source/google_.py +0 -0
  189. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/lions/researcher/data_source/wiki_.py +0 -0
  190. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/lions/researcher/data_source/yfinance_.py +0 -0
  191. {lionagi-0.1.1/lionagi/tests/libs → lionagi-0.1.2/lionagi/tests}/__init__.py +0 -0
  192. {lionagi-0.1.1/lionagi/tests/test_core → lionagi-0.1.2/lionagi/tests/integrations}/__init__.py +0 -0
  193. /lionagi-0.1.1/lionagi/tests/libs/test_async.py → /lionagi-0.1.2/lionagi/tests/libs/__init__.py +0 -0
  194. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/libs/test_api.py +0 -0
  195. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/libs/test_convert.py +0 -0
  196. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/libs/test_field_validators.py +0 -0
  197. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/libs/test_func_call.py +0 -0
  198. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/libs/test_nested.py +0 -0
  199. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/libs/test_parse.py +0 -0
  200. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/libs/test_queue.py +0 -0
  201. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/libs/test_sys_util.py +0 -0
  202. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/test_core/test_base_branch.py +0 -0
  203. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/test_core/test_branch.py +0 -0
  204. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/test_core/test_chat_flow.py +0 -0
  205. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/test_core/test_mail_manager.py +0 -0
  206. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/test_core/test_prompts.py +0 -0
  207. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/test_core/test_session.py +0 -0
  208. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/test_core/test_session_base_util.py +0 -0
  209. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi/tests/test_core/test_tool_manager.py +0 -0
  210. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi.egg-info/dependency_links.txt +0 -0
  211. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi.egg-info/requires.txt +0 -0
  212. {lionagi-0.1.1 → lionagi-0.1.2}/lionagi.egg-info/top_level.txt +0 -0
  213. {lionagi-0.1.1 → lionagi-0.1.2}/pyproject.toml +0 -0
  214. {lionagi-0.1.1 → lionagi-0.1.2}/setup.cfg +0 -0
  215. {lionagi-0.1.1 → lionagi-0.1.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lionagi
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Towards automated general intelligence.
5
5
  Author: HaiyangLi
6
6
  Author-email: Haiyang Li <ocean@lionagi.ai>
@@ -288,7 +288,7 @@ class StructureExecutor(BaseExecutor, Graph):
288
288
  while self.pending_ins[key]:
289
289
  mail: BaseMail = self.pending_ins[key].popleft()
290
290
  try:
291
- if mail == "end":
291
+ if mail.category == "end":
292
292
  self.execute_stop = True
293
293
  return
294
294
  next_nodes = await self._handle_mail(mail)
@@ -312,3 +312,23 @@ class StructureExecutor(BaseExecutor, Graph):
312
312
  while not self.execute_stop:
313
313
  await self.forward()
314
314
  await AsyncUtil.sleep(refresh_time)
315
+
316
+ def to_excel(self, structure_name, dir="structure_storage"):
317
+ """
318
+ Exports the current structure to an Excel file using a specified structure name and directory.
319
+
320
+ This method utilizes the `to_excel` function from the `lionagi.integrations.storage.to_excel` module,
321
+ saving the current structure instance into an Excel file format. The Excel file will contain details
322
+ about nodes, edges, and other relevant data as separate sheets within the file.
323
+
324
+ Args:
325
+ structure_name (str): The name to assign to the structure within the Excel file. This name is
326
+ used as part of the file naming convention.
327
+ dir (str, optional): The directory where the Excel file will be saved. Defaults to "structure_storage".
328
+
329
+ Raises:
330
+ Exception: Propagates any exceptions raised by the `to_excel` function, which might occur during
331
+ the file writing process or data formatting.
332
+ """
333
+ from lionagi.integrations.storage.to_excel import to_excel
334
+ to_excel(self, structure_name, dir)
@@ -145,7 +145,9 @@ class MonoReAct(MonoChat):
145
145
  if not self.branch.tool_manager.has_tools:
146
146
  raise ValueError("No tools found. You need to register tools.")
147
147
 
148
- config = self.branch.tool_manager.parse_tool(tools=True, **kwargs)
148
+ if tools is None:
149
+ tools = True
150
+ config = self.branch.tool_manager.parse_tool(tools=tools, **kwargs)
149
151
  config["tool_parsed"] = True
150
152
  config["tool_choice"] = tool_choice
151
153
  return config
@@ -137,7 +137,9 @@ class MonoFollowup(MonoChat):
137
137
  if not self.branch.tool_manager.has_tools:
138
138
  raise ValueError("No tools found. You need to register tools.")
139
139
 
140
- config = self.branch.tool_manager.parse_tool(tools=True, **kwargs)
140
+ if tools is None:
141
+ tools = True
142
+ config = self.branch.tool_manager.parse_tool(tools=tools, **kwargs)
141
143
  config["tool_parsed"] = True
142
144
  config["tool_choice"] = tool_choice
143
145
  return config
@@ -1,13 +1,12 @@
1
- """This module provides base components used in lionagi"""
1
+ """base components in lionagi"""
2
2
 
3
3
  from abc import ABC
4
4
  from functools import singledispatchmethod
5
- from typing import Any, TypeVar
6
-
5
+ from typing import Any, TypeVar, Type
7
6
  from pydantic import AliasChoices, BaseModel, Field, ValidationError
8
7
  from pandas import DataFrame, Series
9
8
 
10
- from lionagi.libs import SysUtil, func_call, convert, ParseUtil, nested
9
+ from lionagi.libs import SysUtil, convert, ParseUtil, nested, func_call
11
10
 
12
11
 
13
12
  T = TypeVar("T")
@@ -28,24 +27,38 @@ class BaseComponent(BaseModel, ABC):
28
27
  validation_alias=AliasChoices("node_id", "ID", "id"),
29
28
  description="A 32-char unique hash identifier for the node.",
30
29
  )
31
-
32
30
  timestamp: str = Field(
33
31
  default_factory=lambda: SysUtil.get_timestamp(sep=None),
34
32
  description="The timestamp of when the node was created.",
35
33
  )
36
34
 
35
+ extra_fields: dict[str, Any] = Field(
36
+ default_factory=dict,
37
+ validation_alias=AliasChoices(
38
+ "extra", "additional_fields", "schema_extra", "extra_schema"
39
+ ),
40
+ description="Additional fields for the component.",
41
+ )
42
+
37
43
  class Config:
38
44
  """Model configuration settings."""
39
45
 
40
46
  extra = "allow"
41
47
  arbitrary_types_allowed = True
42
48
  populate_by_name = True
43
- validate_assignment = True
44
- validate_return = True
45
- str_strip_whitespace = True
49
+
50
+ @property
51
+ def class_name(self) -> str:
52
+ """
53
+ Retrieve the name of the class.
54
+
55
+ Returns:
56
+ str: The name of the class.
57
+ """
58
+ return self._class_name()
46
59
 
47
60
  @classmethod
48
- def class_name(cls) -> str:
61
+ def _class_name(cls) -> str:
49
62
  """
50
63
  Retrieve the name of the class.
51
64
 
@@ -54,6 +67,101 @@ class BaseComponent(BaseModel, ABC):
54
67
  """
55
68
  return cls.__name__
56
69
 
70
+ def to_json_str(self, *args, **kwargs) -> str:
71
+ """
72
+ Convert the component to a JSON string.
73
+
74
+ Returns:
75
+ str: The JSON string representation of the component.
76
+ """
77
+ dict_ = self.to_dict(*args, **kwargs)
78
+ return convert.to_str(dict_)
79
+
80
+ def to_dict(self, *args, **kwargs) -> dict[str, Any]:
81
+ """
82
+ Convert the component to a dictionary.
83
+
84
+ Returns:
85
+ dict[str, Any]: The dictionary representation of the component.
86
+ """
87
+ dict_ = self.model_dump(*args, by_alias=True, **kwargs)
88
+ for field_name in list(self.extra_fields.keys()):
89
+ if field_name not in dict_:
90
+ dict_[field_name] = getattr(self, field_name, None)
91
+ dict_.pop("extra_fields", None)
92
+ return dict_
93
+
94
+ def to_xml(self, *args, **kwargs) -> str:
95
+ """
96
+ Convert the component to an XML string.
97
+
98
+ Returns:
99
+ str: The XML string representation of the component.
100
+ """
101
+ import xml.etree.ElementTree as ET
102
+
103
+ root = ET.Element(self.__class__.__name__)
104
+
105
+ def convert(dict_obj: dict, parent: ET.Element) -> None:
106
+ for key, val in dict_obj.items():
107
+ if isinstance(val, dict):
108
+ element = ET.SubElement(parent, key)
109
+ convert(val, element)
110
+ else:
111
+ element = ET.SubElement(parent, key)
112
+ element.text = str(val)
113
+
114
+ convert(self.to_dict(*args, **kwargs), root)
115
+ return ET.tostring(root, encoding="unicode")
116
+
117
+ def to_pd_series(self, *args, pd_kwargs: dict | None = None, **kwargs) -> Series:
118
+ """
119
+ Convert the node to a Pandas Series.
120
+
121
+ Args:
122
+ pd_kwargs (dict | None): Additional keyword arguments for Pandas Series.
123
+
124
+ Returns:
125
+ Series: The Pandas Series representation of the node.
126
+ """
127
+ pd_kwargs = {} if pd_kwargs is None else pd_kwargs
128
+ dict_ = self.to_dict(*args, **kwargs)
129
+ return Series(dict_, **pd_kwargs)
130
+
131
+ def _add_field(
132
+ self,
133
+ field_name: str,
134
+ annotation: Any | Type | None = Any,
135
+ default: Any | None = None,
136
+ value: Any | None = None,
137
+ field: Any = None,
138
+ **kwargs,
139
+ ) -> None:
140
+ """
141
+ Add a field to the model after initialization.
142
+
143
+ Args:
144
+ field_name (str): The name of the field.
145
+ annotation (Any | Type | None): The type annotation for the field.
146
+ default (Any | None): The default value for the field.
147
+ value (Any | None): The initial value for the field.
148
+ field (Any): The Field object for the field.
149
+ **kwargs: Additional keyword arguments for the Field object.
150
+ """
151
+ field = field or Field(default=default, **kwargs)
152
+ self.extra_fields[field_name] = field
153
+ if annotation:
154
+ self.extra_fields[field_name].annotation = annotation
155
+
156
+ if not value and (a := self._get_field_attr(field_name, "default", None)):
157
+ value = a
158
+
159
+ self.__setattr__(field_name, value)
160
+
161
+ @property
162
+ def _all_fields(self):
163
+ return {**self.model_fields, **self.extra_fields}
164
+
57
165
  @property
58
166
  def _field_annotations(self) -> dict:
59
167
  """
@@ -62,21 +170,20 @@ class BaseComponent(BaseModel, ABC):
62
170
  Returns:
63
171
  dict: A dictionary mapping field names to their annotations.
64
172
  """
65
- return self._get_field_annotation(list(self.model_fields.keys()))
66
173
 
67
- def _get_field_attr(self, k: str, attr: str, default=False) -> Any:
174
+ return self._get_field_annotation(list(self._all_fields.keys()))
175
+
176
+ def _get_field_attr(self, k: str, attr: str, default: Any = False) -> Any:
68
177
  """
69
178
  Get the value of a field attribute.
70
179
 
71
180
  Args:
72
181
  k (str): The field name.
73
182
  attr (str): The attribute name.
74
- default (Any): Default value to return if the attribute is not
75
- found.
183
+ default (Any): Default value to return if the attribute is not found.
76
184
 
77
185
  Returns:
78
- Any: The value of the field attribute, or the default value if not
79
- found.
186
+ Any: The value of the field attribute, or the default value if not found.
80
187
 
81
188
  Raises:
82
189
  ValueError: If the field does not have the specified attribute.
@@ -84,8 +191,9 @@ class BaseComponent(BaseModel, ABC):
84
191
  try:
85
192
  if not self._field_has_attr(k, attr):
86
193
  raise ValueError(f"field {k} has no attribute {attr}")
87
- field = self.model_fields[k]
88
- a = getattr(field, attr)
194
+
195
+ field = self._all_fields[k]
196
+ a = getattr(field, attr, None)
89
197
  if not a:
90
198
  try:
91
199
  a = field.json_schema_extra[attr]
@@ -99,7 +207,7 @@ class BaseComponent(BaseModel, ABC):
99
207
  raise e
100
208
 
101
209
  @singledispatchmethod
102
- def _get_field_annotation(self, field_name: str) -> Any:
210
+ def _get_field_annotation(self, field_name: Any) -> Any:
103
211
  """
104
212
  Get the annotation for a field.
105
213
 
@@ -112,7 +220,7 @@ class BaseComponent(BaseModel, ABC):
112
220
  raise TypeError(f"Unsupported type {type(field_name)}")
113
221
 
114
222
  @_get_field_annotation.register(str)
115
- def _(self, field_name) -> dict[str, Any]:
223
+ def _(self, field_name: str) -> dict[str, Any]:
116
224
  """
117
225
  Get the annotation for a field as a dictionary.
118
226
 
@@ -120,10 +228,9 @@ class BaseComponent(BaseModel, ABC):
120
228
  field_name (str): The name of the field.
121
229
 
122
230
  Returns:
123
- dict[str, Any]: A dictionary mapping the field name to its
124
- annotation.
231
+ dict[str, Any]: A dictionary mapping the field name to its annotation.
125
232
  """
126
- dict_ = {field_name: self.model_fields[field_name].annotation}
233
+ dict_ = {field_name: self._all_fields[field_name].annotation}
127
234
  for k, v in dict_.items():
128
235
  if "|" in str(v):
129
236
  v = str(v)
@@ -134,37 +241,20 @@ class BaseComponent(BaseModel, ABC):
134
241
  return dict_
135
242
 
136
243
  @_get_field_annotation.register(list)
137
- def _(self, field_name) -> dict[str, Any]:
138
- """
139
- Get the annotations for multiple fields as a dictionary.
140
-
141
- Args:
142
- field_name (list): A list or tuple of field names.
143
-
144
- Returns:
145
- dict[str, Any]: A dictionary mapping field names to their
146
- annotations.
147
- """
148
- dict_ = {}
149
- for i in field_name:
150
- dict_.update(self._get_field_annotation(i))
151
- return dict_
152
-
153
244
  @_get_field_annotation.register(tuple)
154
- def _(self, field_name) -> dict[str, Any]:
245
+ def _(self, field_names: list | tuple) -> dict[str, Any]:
155
246
  """
156
247
  Get the annotations for multiple fields as a dictionary.
157
248
 
158
249
  Args:
159
- field_name (tuple): A list or tuple of field names.
250
+ field_names (list | tuple): A list or tuple of field names.
160
251
 
161
252
  Returns:
162
- dict[str, Any]: A dictionary mapping field names to their
163
- annotations.
253
+ dict[str, Any]: A dictionary mapping field names to their annotations.
164
254
  """
165
255
  dict_ = {}
166
- for i in field_name:
167
- dict_.update(self._get_field_annotation(i))
256
+ for field_name in field_names:
257
+ dict_.update(self._get_field_annotation(field_name))
168
258
  return dict_
169
259
 
170
260
  def _field_has_attr(self, k: str, attr: str) -> bool:
@@ -178,7 +268,7 @@ class BaseComponent(BaseModel, ABC):
178
268
  Returns:
179
269
  bool: True if the field has the attribute, False otherwise.
180
270
  """
181
- field = self.model_fields.get(k, None)
271
+ field = self._all_fields.get(k, None)
182
272
  if field is None:
183
273
  raise ValueError(f"Field {k} not found in model fields.")
184
274
 
@@ -186,65 +276,16 @@ class BaseComponent(BaseModel, ABC):
186
276
  if not a:
187
277
  try:
188
278
  a = (
189
- self.model_fields[k].json_schema_extra[attr] is not None
190
- and attr in self.model_fields[k].json_schema_extra
279
+ self._all_fields[k].json_schema_extra[attr] is not None
280
+ and attr in self._all_fields[k].json_schema_extra
191
281
  )
192
282
  return a if isinstance(a, bool) else False
193
283
  except Exception:
194
284
  return False
195
285
  return a
196
286
 
197
- def to_json_str(self, *args, **kwargs) -> str:
198
- """
199
- Convert the component to a JSON string.
200
-
201
- Returns:
202
- str: The JSON string representation of the component.
203
- """
204
- return self.model_dump_json(*args, by_alias=True, **kwargs)
205
-
206
- def to_dict(self, *args, **kwargs) -> dict[str, Any]:
207
- """
208
- Convert the component to a dictionary.
209
-
210
- Returns:
211
- dict[str, Any]: The dictionary representation of the component.
212
- """
213
- return self.model_dump(*args, by_alias=True, **kwargs)
214
-
215
- def to_xml(self) -> str:
216
- """
217
- Convert the component to an XML string.
218
-
219
- Returns:
220
- str: The XML string representation of the component.
221
- """
222
- import xml.etree.ElementTree as ET
223
-
224
- root = ET.Element(self.__class__.__name__)
225
-
226
- def convert(dict_obj, parent):
227
- for key, val in dict_obj.items():
228
- if isinstance(val, dict):
229
- element = ET.SubElement(parent, key)
230
- convert(val, element)
231
- else:
232
- element = ET.SubElement(parent, key)
233
- element.text = str(val)
234
-
235
- convert(self.to_dict(), root)
236
- return ET.tostring(root, encoding="unicode")
237
-
238
- def to_pd_series(self, *args, pd_kwargs: dict | None = None, **kwargs) -> Series:
239
- """
240
- Convert the node to a Pandas Series.
241
-
242
- Returns:
243
- Series: The Pandas Series representation of the node.
244
- """
245
- pd_kwargs = {} if pd_kwargs is None else pd_kwargs
246
- dict_ = self.to_dict(*args, **kwargs)
247
- return Series(dict_, **pd_kwargs)
287
+ def __str__(self):
288
+ return f"{self.__class__.__name__}({self.to_json_str()})"
248
289
 
249
290
 
250
291
  class BaseNode(BaseComponent):
@@ -264,7 +305,7 @@ class BaseNode(BaseComponent):
264
305
 
265
306
  metadata: dict[str, Any] = Field(
266
307
  default_factory=dict,
267
- alias="meta",
308
+ validation_alias="meta",
268
309
  description="Additional metadata for the node.",
269
310
  )
270
311
 
@@ -276,20 +317,36 @@ class BaseNode(BaseComponent):
276
317
 
277
318
  Args:
278
319
  obj (Any): The object to create the node from.
320
+ *args: Additional positional arguments.
321
+ **kwargs: Additional keyword arguments.
279
322
 
280
323
  Raises:
281
324
  NotImplementedError: If the object type is not supported.
282
325
  """
326
+ if not isinstance(obj, (dict, str, list, Series, DataFrame, BaseModel)):
327
+ type_ = str(type(obj))
328
+ if "llama_index" in type_:
329
+ return cls.from_obj(obj.to_dict())
330
+ elif "langchain" in type_:
331
+ langchain_json = obj.to_json()
332
+ langchain_dict = {
333
+ "lc_id": langchain_json["id"],
334
+ **langchain_json["kwargs"],
335
+ }
336
+ return cls.from_obj(langchain_dict)
337
+
283
338
  raise NotImplementedError(f"Unsupported type: {type(obj)}")
284
339
 
285
340
  @from_obj.register(dict)
286
341
  @classmethod
287
- def _from_dict(cls, obj, *args, **kwargs) -> T:
342
+ def _from_dict(cls, obj: dict, *args, **kwargs) -> T:
288
343
  """
289
344
  Create a node instance from a dictionary.
290
345
 
291
346
  Args:
292
347
  obj (dict): The dictionary to create the node from.
348
+ *args: Additional positional arguments.
349
+ **kwargs: Additional keyword arguments.
293
350
 
294
351
  Returns:
295
352
  T: The created node instance.
@@ -298,13 +355,15 @@ class BaseNode(BaseComponent):
298
355
 
299
356
  @from_obj.register(str)
300
357
  @classmethod
301
- def _from_str(cls, obj, *args, fuzzy_parse=False, **kwargs) -> T:
358
+ def _from_str(cls, obj: str, *args, fuzzy_parse: bool = False, **kwargs) -> T:
302
359
  """
303
360
  Create a node instance from a JSON string.
304
361
 
305
362
  Args:
306
363
  obj (str): The JSON string to create the node from.
364
+ *args: Additional positional arguments.
307
365
  fuzzy_parse (bool): Whether to perform fuzzy parsing.
366
+ **kwargs: Additional keyword arguments.
308
367
 
309
368
  Returns:
310
369
  T: The created node instance.
@@ -317,12 +376,14 @@ class BaseNode(BaseComponent):
317
376
 
318
377
  @from_obj.register(list)
319
378
  @classmethod
320
- def _from_list(cls, obj, *args, **kwargs) -> list[T]:
379
+ def _from_list(cls, obj: list, *args, **kwargs) -> list[T]:
321
380
  """
322
381
  Create a list of node instances from a list of objects.
323
382
 
324
383
  Args:
325
384
  obj (list): The list of objects to create nodes from.
385
+ *args: Additional positional arguments.
386
+ **kwargs: Additional keyword arguments.
326
387
 
327
388
  Returns:
328
389
  list[T]: The list of created node instances.
@@ -331,37 +392,51 @@ class BaseNode(BaseComponent):
331
392
 
332
393
  @from_obj.register(Series)
333
394
  @classmethod
334
- def _from_pd_series(cls, obj, *args, pd_kwargs=None, **kwargs) -> T:
395
+ def _from_pd_series(
396
+ cls, obj: Series, *args, pd_kwargs: dict | None = None, **kwargs
397
+ ) -> T:
335
398
  """
336
399
  Create a node instance from a Pandas Series.
337
400
 
338
401
  Args:
339
402
  obj (Series): The Pandas Series to create the node from.
403
+ *args: Additional positional arguments.
404
+ pd_kwargs (dict | None): Additional keyword arguments for Pandas Series.
405
+ **kwargs: Additional keyword arguments.
340
406
 
341
407
  Returns:
342
408
  T: The created node instance.
343
409
  """
344
- if pd_kwargs is None:
345
- pd_kwargs = {}
410
+ pd_kwargs = pd_kwargs or {}
346
411
  return cls.from_obj(obj.to_dict(**pd_kwargs), *args, **kwargs)
347
412
 
348
413
  @from_obj.register(DataFrame)
349
414
  @classmethod
350
- def _from_pd_dataframe(cls, obj, *args, pd_kwargs=None, **kwargs) -> list[T]:
415
+ def _from_pd_dataframe(
416
+ cls, obj: DataFrame, *args, pd_kwargs: dict | None = None, **kwargs
417
+ ) -> list[T]:
351
418
  """
352
419
  Create a list of node instances from a Pandas DataFrame.
353
420
 
354
421
  Args:
355
422
  obj (DataFrame): The Pandas DataFrame to create nodes from.
423
+ *args: Additional positional arguments.
424
+ pd_kwargs (dict | None): Additional keyword arguments for Pandas DataFrame.
425
+ **kwargs: Additional keyword arguments.
356
426
 
357
427
  Returns:
358
428
  list[T]: The list of created node instances.
359
429
  """
360
430
  if pd_kwargs is None:
361
431
  pd_kwargs = {}
362
- return [
363
- cls.from_obj(row, *args, **pd_kwargs, **kwargs) for _, row in obj.iterrows()
364
- ]
432
+
433
+ _objs = []
434
+ for index, row in obj.iterrows():
435
+ _obj = cls.from_obj(row, *args, **pd_kwargs, **kwargs)
436
+ _obj.metadata["df_index"] = index
437
+ _objs.append(_obj)
438
+
439
+ return _objs
365
440
 
366
441
  @from_obj.register(BaseModel)
367
442
  @classmethod
@@ -375,27 +450,29 @@ class BaseNode(BaseComponent):
375
450
  Returns:
376
451
  T: The created node instance.
377
452
  """
378
- if pydantic_kwargs is None:
379
- pydantic_kwargs = {"by_alias": True}
380
-
381
- config_ = {}
453
+ pydantic_kwargs = pydantic_kwargs or {"by_alias": True}
382
454
  try:
383
- config_ = obj.model_dump(**pydantic_kwargs)
384
- except:
385
- config_ = obj.dict(**pydantic_kwargs)
455
+ config_ = {}
456
+ try:
457
+ config_ = obj.model_dump(**pydantic_kwargs)
458
+ except:
459
+ config_ = obj.to_dict(**pydantic_kwargs)
460
+ else:
461
+ config_ = obj.dict(**pydantic_kwargs)
462
+ except Exception as e:
463
+ raise ValueError(f"Invalid Pydantic model for deserialization: {e}") from e
386
464
 
387
465
  return cls.from_obj(config_ | kwargs)
388
466
 
389
467
  def meta_get(
390
- self, key: str, indices: list[str | int] = None, default: Any = None
468
+ self, key: str, indices: list[str | int] | None = None, default: Any = None
391
469
  ) -> Any:
392
470
  """
393
471
  Get a value from the metadata dictionary.
394
472
 
395
473
  Args:
396
474
  key (str): The key to retrieve the value for.
397
- indices (list[str | int]): Optional list of indices for nested
398
- retrieval.
475
+ indices (list[str | int] | None): Optional list of indices for nested retrieval.
399
476
  default (Any): The default value to return if the key is not found.
400
477
 
401
478
  Returns:
@@ -452,4 +529,4 @@ class BaseNode(BaseComponent):
452
529
  """
453
530
  self.metadata = nested.nmerge(
454
531
  [self.metadata, additional_metadata], overwrite=overwrite, **kwargs
455
- )
532
+ )
@@ -1,5 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from enum import Enum
3
+ from typing import Callable
3
4
  from pydantic import BaseModel, Field
4
5
 
5
6
 
@@ -14,6 +15,7 @@ class ConditionSource(str, Enum):
14
15
 
15
16
  STRUCTURE = "structure"
16
17
  EXECUTABLE = "executable"
18
+ RULE = "rule"
17
19
 
18
20
 
19
21
  class Condition(BaseModel, ABC):