lionagi 0.0.306__py3-none-any.whl → 0.0.308__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 (78) hide show
  1. lionagi/__init__.py +2 -5
  2. lionagi/core/__init__.py +7 -5
  3. lionagi/core/agent/__init__.py +3 -0
  4. lionagi/core/agent/base_agent.py +10 -12
  5. lionagi/core/branch/__init__.py +4 -0
  6. lionagi/core/branch/base_branch.py +81 -81
  7. lionagi/core/branch/branch.py +16 -28
  8. lionagi/core/branch/branch_flow_mixin.py +3 -7
  9. lionagi/core/branch/executable_branch.py +86 -56
  10. lionagi/core/branch/util.py +77 -162
  11. lionagi/core/{flow/direct → direct}/__init__.py +1 -1
  12. lionagi/core/{flow/direct/predict.py → direct/parallel_predict.py} +39 -17
  13. lionagi/core/direct/parallel_react.py +0 -0
  14. lionagi/core/direct/parallel_score.py +0 -0
  15. lionagi/core/direct/parallel_select.py +0 -0
  16. lionagi/core/direct/parallel_sentiment.py +0 -0
  17. lionagi/core/direct/predict.py +174 -0
  18. lionagi/core/{flow/direct → direct}/react.py +2 -2
  19. lionagi/core/{flow/direct → direct}/score.py +28 -23
  20. lionagi/core/{flow/direct → direct}/select.py +48 -45
  21. lionagi/core/direct/utils.py +83 -0
  22. lionagi/core/flow/monoflow/ReAct.py +6 -5
  23. lionagi/core/flow/monoflow/__init__.py +9 -0
  24. lionagi/core/flow/monoflow/chat.py +10 -10
  25. lionagi/core/flow/monoflow/chat_mixin.py +11 -10
  26. lionagi/core/flow/monoflow/followup.py +6 -5
  27. lionagi/core/flow/polyflow/__init__.py +1 -0
  28. lionagi/core/flow/polyflow/chat.py +15 -3
  29. lionagi/core/mail/mail_manager.py +18 -19
  30. lionagi/core/mail/schema.py +5 -4
  31. lionagi/core/messages/schema.py +18 -20
  32. lionagi/core/prompt/__init__.py +0 -0
  33. lionagi/core/prompt/prompt_template.py +0 -0
  34. lionagi/core/schema/__init__.py +2 -2
  35. lionagi/core/schema/action_node.py +11 -3
  36. lionagi/core/schema/base_mixin.py +56 -59
  37. lionagi/core/schema/base_node.py +34 -37
  38. lionagi/core/schema/condition.py +24 -0
  39. lionagi/core/schema/data_logger.py +96 -99
  40. lionagi/core/schema/data_node.py +19 -19
  41. lionagi/core/schema/prompt_template.py +0 -0
  42. lionagi/core/schema/structure.py +171 -169
  43. lionagi/core/session/__init__.py +1 -3
  44. lionagi/core/session/session.py +196 -214
  45. lionagi/core/tool/tool_manager.py +95 -103
  46. lionagi/integrations/__init__.py +1 -3
  47. lionagi/integrations/bridge/langchain_/documents.py +17 -18
  48. lionagi/integrations/bridge/langchain_/langchain_bridge.py +14 -14
  49. lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +22 -22
  50. lionagi/integrations/bridge/llamaindex_/node_parser.py +12 -12
  51. lionagi/integrations/bridge/llamaindex_/reader.py +11 -11
  52. lionagi/integrations/bridge/llamaindex_/textnode.py +7 -7
  53. lionagi/integrations/config/openrouter_configs.py +0 -1
  54. lionagi/integrations/provider/oai.py +26 -26
  55. lionagi/integrations/provider/services.py +38 -38
  56. lionagi/libs/__init__.py +34 -1
  57. lionagi/libs/ln_api.py +211 -221
  58. lionagi/libs/ln_async.py +53 -60
  59. lionagi/libs/ln_convert.py +118 -120
  60. lionagi/libs/ln_dataframe.py +32 -33
  61. lionagi/libs/ln_func_call.py +334 -342
  62. lionagi/libs/ln_nested.py +99 -107
  63. lionagi/libs/ln_parse.py +161 -165
  64. lionagi/libs/sys_util.py +52 -52
  65. lionagi/tests/test_core/test_session.py +254 -266
  66. lionagi/tests/test_core/test_session_base_util.py +299 -300
  67. lionagi/tests/test_core/test_tool_manager.py +70 -74
  68. lionagi/tests/test_libs/test_nested.py +2 -7
  69. lionagi/tests/test_libs/test_parse.py +2 -2
  70. lionagi/version.py +1 -1
  71. {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/METADATA +4 -2
  72. lionagi-0.0.308.dist-info/RECORD +115 -0
  73. lionagi/core/flow/direct/utils.py +0 -43
  74. lionagi-0.0.306.dist-info/RECORD +0 -106
  75. /lionagi/core/{flow/direct → direct}/sentiment.py +0 -0
  76. {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/LICENSE +0 -0
  77. {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/WHEEL +0 -0
  78. {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/top_level.txt +0 -0
@@ -5,10 +5,7 @@ from typing import Any, TypeVar, Type, Callable
5
5
  import pandas as pd
6
6
  from pydantic import BaseModel, ValidationError
7
7
 
8
- import lionagi.libs.ln_nested as nested
9
- import lionagi.libs.ln_convert as convert
10
- from lionagi.libs.ln_parse import ParseUtil
11
- from lionagi.libs.sys_util import SysUtil
8
+ from lionagi.libs import nested, convert, ParseUtil, SysUtil
12
9
 
13
10
  T = TypeVar("T") # Generic type for return type of from_obj method
14
11
 
@@ -24,12 +21,12 @@ class BaseToObjectMixin(ABC, BaseModel):
24
21
  string. It supports passing arbitrary arguments to the underlying `model_dump_json` method.
25
22
 
26
23
  Args:
27
- *args: Variable-length argument list to be passed to `model_dump_json`.
28
- **kwargs: Arbitrary keyword arguments, with `by_alias=True` set by default to use
29
- model field aliases in the output JSON, if any.
24
+ *args: Variable-length argument list to be passed to `model_dump_json`.
25
+ **kwargs: Arbitrary keyword arguments, with `by_alias=True` set by default to use
26
+ model field aliases in the output JSON, if any.
30
27
 
31
28
  Returns:
32
- str: A JSON string representation of the model instance.
29
+ str: A JSON string representation of the model instance.
33
30
  """
34
31
  return self.model_dump_json(*args, by_alias=True, **kwargs)
35
32
 
@@ -42,12 +39,12 @@ class BaseToObjectMixin(ABC, BaseModel):
42
39
  aliases instead of the original field names.
43
40
 
44
41
  Args:
45
- *args: Variable-length argument list for the `model_dump` method.
46
- **kwargs: Arbitrary keyword arguments. By default, `by_alias=True` is applied, indicating
47
- that field aliases should be used as keys in the resulting dictionary.
42
+ *args: Variable-length argument list for the `model_dump` method.
43
+ **kwargs: Arbitrary keyword arguments. By default, `by_alias=True` is applied, indicating
44
+ that field aliases should be used as keys in the resulting dictionary.
48
45
 
49
46
  Returns:
50
- dict[str, Any]: The dictionary representation of the model instance.
47
+ dict[str, Any]: The dictionary representation of the model instance.
51
48
  """
52
49
  return self.model_dump(*args, by_alias=True, **kwargs)
53
50
 
@@ -60,7 +57,7 @@ class BaseToObjectMixin(ABC, BaseModel):
60
57
  The root element of the XML tree is named after the class of the model instance.
61
58
 
62
59
  Returns:
63
- str: An XML string representation of the model instance.
60
+ str: An XML string representation of the model instance.
64
61
  """
65
62
 
66
63
  import xml.etree.ElementTree as ET
@@ -88,15 +85,15 @@ class BaseToObjectMixin(ABC, BaseModel):
88
85
  customize the Series creation through `pd_kwargs`.
89
86
 
90
87
  Args:
91
- *args: Variable-length argument list for the `to_dict` method.
92
- pd_kwargs (dict | None): Optional dictionary of keyword arguments to pass to the pandas
93
- Series constructor. Defaults to None, in which case an empty
94
- dictionary is used.
95
- **kwargs: Arbitrary keyword arguments for the `to_dict` method, influencing the dictionary
96
- representation used for Series creation.
88
+ *args: Variable-length argument list for the `to_dict` method.
89
+ pd_kwargs (dict | None): Optional dictionary of keyword arguments to pass to the pandas
90
+ Series constructor. Defaults to None, in which case an empty
91
+ dictionary is used.
92
+ **kwargs: Arbitrary keyword arguments for the `to_dict` method, influencing the dictionary
93
+ representation used for Series creation.
97
94
 
98
95
  Returns:
99
- pd.Series: A pandas Series representation of the model instance.
96
+ pd.Series: A pandas Series representation of the model instance.
100
97
  """
101
98
  pd_kwargs = {} if pd_kwargs is None else pd_kwargs
102
99
  dict_ = self.to_dict(*args, **kwargs)
@@ -118,15 +115,11 @@ class BaseFromObjectMixin(ABC, BaseModel):
118
115
  @from_obj.register(str)
119
116
  @classmethod
120
117
  def _from_str(cls, obj: str, *args, fuzzy_parse=False, **kwargs) -> T:
121
- if fuzzy_parse:
122
- obj = ParseUtil.fuzzy_parse_json(obj)
123
- else:
124
- obj = convert.to_dict(obj)
125
-
118
+ obj = ParseUtil.fuzzy_parse_json(obj) if fuzzy_parse else convert.to_dict(obj)
126
119
  try:
127
120
  return cls.from_obj(obj, *args, **kwargs)
128
121
  except ValidationError as e:
129
- raise ValueError(f"Invalid JSON for deserialization: {e}")
122
+ raise ValueError(f"Invalid JSON for deserialization: {e}") from e
130
123
 
131
124
  @from_obj.register(list)
132
125
  @classmethod
@@ -135,23 +128,27 @@ class BaseFromObjectMixin(ABC, BaseModel):
135
128
 
136
129
  @from_obj.register(pd.Series)
137
130
  @classmethod
138
- def _from_pd_series(cls, obj: pd.Series, *args, pd_kwargs={}, **kwargs) -> T:
131
+ def _from_pd_series(cls, obj: pd.Series, *args, pd_kwargs=None, **kwargs) -> T:
132
+ if pd_kwargs is None:
133
+ pd_kwargs = {}
139
134
  return cls.from_obj(obj.to_dict(**pd_kwargs), *args, **kwargs)
140
135
 
141
136
  @from_obj.register(pd.DataFrame)
142
137
  @classmethod
143
138
  def _from_pd_dataframe(
144
- cls, obj: pd.DataFrame, *args, pd_kwargs={}, **kwargs
139
+ cls, obj: pd.DataFrame, *args, pd_kwargs=None, **kwargs
145
140
  ) -> list[T]:
141
+ if pd_kwargs is None:
142
+ pd_kwargs = {}
146
143
  return [
147
144
  cls.from_obj(row, *args, **pd_kwargs, **kwargs) for _, row in obj.iterrows()
148
145
  ]
149
146
 
150
147
  @from_obj.register(BaseModel)
151
148
  @classmethod
152
- def _from_base_model(
153
- cls, obj: BaseModel, pydantic_kwargs={"by_alias": True}, **kwargs
154
- ) -> T:
149
+ def _from_base_model(cls, obj: BaseModel, pydantic_kwargs=None, **kwargs) -> T:
150
+ if pydantic_kwargs is None:
151
+ pydantic_kwargs = {"by_alias": True}
155
152
  config_ = {**obj.model_dump(**pydantic_kwargs), **kwargs}
156
153
  return cls.from_obj(**config_)
157
154
 
@@ -163,11 +160,11 @@ class BaseMetaManageMixin(ABC, BaseModel):
163
160
  Retrieves a list of metadata keys.
164
161
 
165
162
  Args:
166
- flattened (bool): If True, returns keys from a flattened metadata structure.
167
- **kwargs: Additional keyword arguments passed to the flattening function.
163
+ flattened (bool): If True, returns keys from a flattened metadata structure.
164
+ **kwargs: Additional keyword arguments passed to the flattening function.
168
165
 
169
166
  Returns:
170
- list[str]: List of metadata keys.
167
+ list[str]: List of metadata keys.
171
168
  """
172
169
  if flattened:
173
170
  return nested.get_flattened_keys(self.metadata, **kwargs)
@@ -178,12 +175,12 @@ class BaseMetaManageMixin(ABC, BaseModel):
178
175
  Checks if a specified key exists in the metadata.
179
176
 
180
177
  Args:
181
- key (str): The key to check.
182
- flattened (bool): If True, checks within a flattened metadata structure.
183
- **kwargs: Additional keyword arguments for flattening.
178
+ key (str): The key to check.
179
+ flattened (bool): If True, checks within a flattened metadata structure.
180
+ **kwargs: Additional keyword arguments for flattening.
184
181
 
185
182
  Returns:
186
- bool: True if key exists, False otherwise.
183
+ bool: True if key exists, False otherwise.
187
184
  """
188
185
  if flattened:
189
186
  return key in nested.get_flattened_keys(self.metadata, **kwargs)
@@ -196,12 +193,12 @@ class BaseMetaManageMixin(ABC, BaseModel):
196
193
  Retrieves the value associated with a given key from the metadata.
197
194
 
198
195
  Args:
199
- key (str): The key for the desired value.
200
- indices: Optional indices for nested retrieval.
201
- default (Any): The default value to return if the key is not found.
196
+ key (str): The key for the desired value.
197
+ indices: Optional indices for nested retrieval.
198
+ default (Any): The default value to return if the key is not found.
202
199
 
203
200
  Returns:
204
- Any: The value associated with the key or the default value.
201
+ Any: The value associated with the key or the default value.
205
202
  """
206
203
  if indices:
207
204
  return nested.nget(self.metadata, key, indices, default)
@@ -212,11 +209,11 @@ class BaseMetaManageMixin(ABC, BaseModel):
212
209
  Renames a key in the metadata.
213
210
 
214
211
  Args:
215
- old_key (str): The current key name.
216
- new_key (str): The new key name.
212
+ old_key (str): The current key name.
213
+ new_key (str): The new key name.
217
214
 
218
215
  Returns:
219
- bool: True if the key was changed, False otherwise.
216
+ bool: True if the key was changed, False otherwise.
220
217
  """
221
218
  if old_key in self.metadata:
222
219
  SysUtil.change_dict_key(self.metadata, old_key, new_key)
@@ -228,12 +225,12 @@ class BaseMetaManageMixin(ABC, BaseModel):
228
225
  Inserts a value into the metadata at specified indices.
229
226
 
230
227
  Args:
231
- indices (str | list): The indices where the value should be inserted.
232
- value (Any): The value to insert.
233
- **kwargs: Additional keyword arguments.
228
+ indices (str | list): The indices where the value should be inserted.
229
+ value (Any): The value to insert.
230
+ **kwargs: Additional keyword arguments.
234
231
 
235
232
  Returns:
236
- bool: True if the insertion was successful, False otherwise.
233
+ bool: True if the insertion was successful, False otherwise.
237
234
  """
238
235
  return nested.ninsert(self.metadata, indices, value, **kwargs)
239
236
 
@@ -243,11 +240,11 @@ class BaseMetaManageMixin(ABC, BaseModel):
243
240
  Removes a key from the metadata and returns its value.
244
241
 
245
242
  Args:
246
- key (str): The key to remove.
247
- default (Any): The default value to return if the key is not found.
243
+ key (str): The key to remove.
244
+ default (Any): The default value to return if the key is not found.
248
245
 
249
246
  Returns:
250
- Any: The value of the removed key or the default value.
247
+ Any: The value of the removed key or the default value.
251
248
  """
252
249
  return self.metadata.pop(key, default)
253
250
 
@@ -258,12 +255,12 @@ class BaseMetaManageMixin(ABC, BaseModel):
258
255
  Merges additional metadata into the existing metadata.
259
256
 
260
257
  Args:
261
- additional_metadata (dict[str, Any]): The metadata to merge in.
262
- overwrite (bool): If True, existing keys will be overwritten by those in additional_metadata.
263
- **kwargs: Additional keyword arguments for the merge.
258
+ additional_metadata (dict[str, Any]): The metadata to merge in.
259
+ overwrite (bool): If True, existing keys will be overwritten by those in additional_metadata.
260
+ **kwargs: Additional keyword arguments for the merge.
264
261
 
265
262
  Returns:
266
- None
263
+ None
267
264
  """
268
265
  nested.nmerge(
269
266
  [self.metadata, additional_metadata], overwrite=overwrite, **kwargs
@@ -278,7 +275,7 @@ class BaseMetaManageMixin(ABC, BaseModel):
278
275
  Clears all metadata.
279
276
 
280
277
  Returns:
281
- None
278
+ None
282
279
  """
283
280
  self.metadata.clear()
284
281
 
@@ -287,10 +284,10 @@ class BaseMetaManageMixin(ABC, BaseModel):
287
284
  Filters the metadata based on a condition.
288
285
 
289
286
  Args:
290
- condition (Callable[[Any, Any], bool]): The condition function to apply.
287
+ condition (Callable[[Any, Any], bool]): The condition function to apply.
291
288
 
292
289
  Returns:
293
- dict[str, Any]: The filtered metadata.
290
+ dict[str, Any]: The filtered metadata.
294
291
  """
295
292
  return nested.nfilter(self.metadata, condition)
296
293
 
@@ -5,14 +5,11 @@ Module for base component model definition using Pydantic.
5
5
  from abc import ABC
6
6
  from typing import Any, TypeVar
7
7
 
8
- import lionagi.integrations.bridge.pydantic_.base_model as pyd
9
- from lionagi.libs.sys_util import SysUtil
10
-
11
- from lionagi.libs import ln_convert as convert
8
+ from pydantic import Field, field_serializer, AliasChoices
9
+ from lionagi.libs import SysUtil, convert
12
10
 
13
11
  from .base_mixin import BaseComponentMixin
14
12
 
15
-
16
13
  T = TypeVar("T", bound="BaseComponent")
17
14
 
18
15
 
@@ -23,14 +20,14 @@ class BaseComponent(BaseComponentMixin, ABC):
23
20
  and validating metadata keys and values.
24
21
 
25
22
  Attributes:
26
- id_ (str): Unique identifier, defaulted using SysUtil.create_id.
27
- timestamp (str | None): Timestamp of creation or modification.
28
- metadata (dict[str, Any]): Metadata associated with the component.
23
+ id_ (str): Unique identifier, defaulted using SysUtil.create_id.
24
+ timestamp (str | None): Timestamp of creation or modification.
25
+ metadata (dict[str, Any]): Metadata associated with the component.
29
26
  """
30
27
 
31
- id_: str = pyd.ln_Field(default_factory=SysUtil.create_id, alias="node_id")
32
- timestamp: str | None = pyd.ln_Field(default_factory=SysUtil.get_timestamp)
33
- metadata: dict[str, Any] = pyd.ln_Field(default_factory=dict, alias="meta")
28
+ id_: str = Field(default_factory=SysUtil.create_id, alias="node_id")
29
+ timestamp: str | None = Field(default_factory=SysUtil.get_timestamp)
30
+ metadata: dict[str, Any] = Field(default_factory=dict, alias="meta")
34
31
 
35
32
  class Config:
36
33
  """Model configuration settings."""
@@ -46,11 +43,11 @@ class BaseComponent(BaseComponentMixin, ABC):
46
43
  Creates a deep copy of the instance, with an option to update specific fields.
47
44
 
48
45
  Args:
49
- *args: Variable length argument list for additional options.
50
- **kwargs: Arbitrary keyword arguments specifying updates to the instance.
46
+ *args: Variable length argument list for additional options.
47
+ **kwargs: Arbitrary keyword arguments specifying updates to the instance.
51
48
 
52
49
  Returns:
53
- BaseComponent: A new instance of BaseComponent as a deep copy of the original, with updates applied.
50
+ BaseComponent: A new instance of BaseComponent as a deep copy of the original, with updates applied.
54
51
  """
55
52
  return self.model_copy(*args, **kwargs)
56
53
 
@@ -64,15 +61,15 @@ class BaseNode(BaseComponent):
64
61
  extending BaseComponent with content handling capabilities.
65
62
 
66
63
  Attributes:
67
- content: The content of the node, which can be a string, a dictionary with any structure,
68
- None, or any other type. It is flexible to accommodate various types of content.
69
- This attribute also supports aliasing through validation_alias for compatibility with
70
- different naming conventions like "text", "page_content", or "chunk_content".
64
+ content: The content of the node, which can be a string, a dictionary with any structure,
65
+ None, or any other type. It is flexible to accommodate various types of content.
66
+ This attribute also supports aliasing through validation_alias for compatibility with
67
+ different naming conventions like "text", "page_content", or "chunk_content".
71
68
  """
72
69
 
73
- content: str | dict[str, Any] | None | Any = pyd.ln_Field(
70
+ content: str | dict[str, Any] | None | Any = Field(
74
71
  default=None,
75
- validation_alias=pyd.ln_AliasChoices("text", "page_content", "chunk_content"),
72
+ validation_alias=AliasChoices("text", "page_content", "chunk_content"),
76
73
  )
77
74
 
78
75
  @property
@@ -81,8 +78,8 @@ class BaseNode(BaseComponent):
81
78
  Attempts to serialize the node's content to a string.
82
79
 
83
80
  Returns:
84
- str: The serialized content string. If serialization fails, returns "null" and
85
- logs an error message indicating the content is not serializable.
81
+ str: The serialized content string. If serialization fails, returns "null" and
82
+ logs an error message indicating the content is not serializable.
86
83
  """
87
84
  try:
88
85
  return convert.to_str(self.content)
@@ -98,17 +95,17 @@ class BaseNode(BaseComponent):
98
95
  metadata preview, and optionally the timestamp if present.
99
96
 
100
97
  Returns:
101
- str: A string representation of the instance.
98
+ str: A string representation of the instance.
102
99
  """
103
100
  timestamp = f" ({self.timestamp})" if self.timestamp else ""
104
101
  if self.content:
105
102
  content_preview = (
106
- self.content[:50] + "..." if len(self.content) > 50 else self.content
103
+ f"{self.content[:50]}..." if len(self.content) > 50 else self.content
107
104
  )
108
105
  else:
109
106
  content_preview = ""
110
107
  meta_preview = (
111
- str(self.metadata)[:50] + "..."
108
+ f"{str(self.metadata)[:50]}..."
112
109
  if len(str(self.metadata)) > 50
113
110
  else str(self.metadata)
114
111
  )
@@ -123,11 +120,11 @@ class BaseRelatableNode(BaseNode):
123
120
  Extends BaseNode with functionality to manage relationships with other nodes.
124
121
 
125
122
  Attributes:
126
- related_nodes: A list of identifiers (str) for nodes that are related to this node.
127
- label: An optional label for the node, providing additional context or classification.
123
+ related_nodes: A list of identifiers (str) for nodes that are related to this node.
124
+ label: An optional label for the node, providing additional context or classification.
128
125
  """
129
126
 
130
- related_nodes: list[str] = pyd.ln_Field(default_factory=list)
127
+ related_nodes: list[str] = Field(default_factory=list)
131
128
  label: str | None = None
132
129
 
133
130
  def add_related_node(self, node_id: str) -> bool:
@@ -135,10 +132,10 @@ class BaseRelatableNode(BaseNode):
135
132
  Adds a node to the list of related nodes if it's not already present.
136
133
 
137
134
  Args:
138
- node_id: The identifier of the node to add.
135
+ node_id: The identifier of the node to add.
139
136
 
140
137
  Returns:
141
- bool: True if the node was added, False if it was already in the list.
138
+ bool: True if the node was added, False if it was already in the list.
142
139
  """
143
140
  if node_id not in self.related_nodes:
144
141
  self.related_nodes.append(node_id)
@@ -150,10 +147,10 @@ class BaseRelatableNode(BaseNode):
150
147
  Removes a node from the list of related nodes if it's present.
151
148
 
152
149
  Args:
153
- node_id: The identifier of the node to remove.
150
+ node_id: The identifier of the node to remove.
154
151
 
155
152
  Returns:
156
- bool: True if the node was removed, False if it was not found in the list.
153
+ bool: True if the node was removed, False if it was not found in the list.
157
154
  """
158
155
 
159
156
  if node_id in self.related_nodes:
@@ -167,10 +164,10 @@ class Tool(BaseRelatableNode):
167
164
  Represents a tool, extending BaseRelatableNode with specific functionalities and configurations.
168
165
 
169
166
  Attributes:
170
- func: The main function or capability of the tool.
171
- schema_: An optional schema defining the structure and constraints of data the tool works with.
172
- manual: Optional documentation or manual for using the tool.
173
- parser: An optional parser associated with the tool for data processing or interpretation.
167
+ func: The main function or capability of the tool.
168
+ schema_: An optional schema defining the structure and constraints of data the tool works with.
169
+ manual: Optional documentation or manual for using the tool.
170
+ parser: An optional parser associated with the tool for data processing or interpretation.
174
171
  """
175
172
 
176
173
  func: Any
@@ -178,7 +175,7 @@ class Tool(BaseRelatableNode):
178
175
  manual: Any | None = None
179
176
  parser: Any | None = None
180
177
 
181
- @pyd.ln_field_serializer("func")
178
+ @field_serializer("func")
182
179
  def serialize_func(self, func):
183
180
  return func.__name__
184
181
 
@@ -0,0 +1,24 @@
1
+ from abc import ABC, abstractmethod
2
+ from enum import Enum
3
+
4
+
5
+ class SourceType(str, Enum):
6
+ STRUCTURE = "structure"
7
+ EXECUTABLE = "executable"
8
+
9
+
10
+ class Condition(ABC):
11
+ def __init__(self, source_type):
12
+ try:
13
+ if isinstance(source_type, str):
14
+ source_type = SourceType(source_type)
15
+ if isinstance(source_type, SourceType):
16
+ self.source_type = source_type
17
+ except:
18
+ raise ValueError(
19
+ f"Invalid source_type. Valid source types are {list(SourceType)}"
20
+ )
21
+
22
+ @abstractmethod
23
+ def __call__(self, source_obj):
24
+ pass