lionagi 0.17.11__py3-none-any.whl → 0.18.1__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 (109) hide show
  1. lionagi/_errors.py +0 -5
  2. lionagi/fields.py +83 -0
  3. lionagi/libs/schema/minimal_yaml.py +98 -0
  4. lionagi/ln/__init__.py +3 -1
  5. lionagi/ln/concurrency/primitives.py +4 -4
  6. lionagi/ln/concurrency/task.py +1 -0
  7. lionagi/ln/types.py +32 -5
  8. lionagi/models/field_model.py +21 -4
  9. lionagi/models/hashable_model.py +2 -3
  10. lionagi/operations/ReAct/ReAct.py +475 -238
  11. lionagi/operations/ReAct/utils.py +3 -0
  12. lionagi/operations/act/act.py +206 -0
  13. lionagi/operations/builder.py +5 -7
  14. lionagi/operations/chat/chat.py +130 -114
  15. lionagi/operations/communicate/communicate.py +101 -42
  16. lionagi/operations/fields.py +380 -0
  17. lionagi/operations/flow.py +8 -10
  18. lionagi/operations/interpret/interpret.py +65 -20
  19. lionagi/operations/node.py +4 -4
  20. lionagi/operations/operate/operate.py +216 -108
  21. lionagi/{protocols/operatives → operations/operate}/operative.py +4 -5
  22. lionagi/{protocols/operatives → operations/operate}/step.py +34 -39
  23. lionagi/operations/parse/parse.py +170 -142
  24. lionagi/operations/select/select.py +79 -18
  25. lionagi/operations/select/utils.py +8 -2
  26. lionagi/operations/types.py +119 -23
  27. lionagi/protocols/action/manager.py +5 -6
  28. lionagi/protocols/contracts.py +2 -2
  29. lionagi/protocols/generic/__init__.py +22 -0
  30. lionagi/protocols/generic/element.py +36 -127
  31. lionagi/protocols/generic/log.py +3 -2
  32. lionagi/protocols/generic/pile.py +9 -10
  33. lionagi/protocols/generic/progression.py +23 -22
  34. lionagi/protocols/graph/edge.py +6 -5
  35. lionagi/protocols/ids.py +6 -49
  36. lionagi/protocols/messages/__init__.py +29 -0
  37. lionagi/protocols/messages/action_request.py +86 -184
  38. lionagi/protocols/messages/action_response.py +73 -131
  39. lionagi/protocols/messages/assistant_response.py +130 -159
  40. lionagi/protocols/messages/base.py +31 -22
  41. lionagi/protocols/messages/instruction.py +280 -625
  42. lionagi/protocols/messages/manager.py +112 -62
  43. lionagi/protocols/messages/message.py +87 -197
  44. lionagi/protocols/messages/system.py +52 -123
  45. lionagi/protocols/types.py +1 -13
  46. lionagi/service/connections/__init__.py +3 -0
  47. lionagi/service/connections/endpoint.py +0 -8
  48. lionagi/service/connections/providers/claude_code_cli.py +3 -2
  49. lionagi/service/connections/providers/oai_.py +29 -94
  50. lionagi/service/connections/providers/ollama_.py +3 -2
  51. lionagi/service/hooks/_types.py +1 -1
  52. lionagi/service/hooks/_utils.py +1 -1
  53. lionagi/service/hooks/hook_event.py +3 -8
  54. lionagi/service/hooks/hook_registry.py +5 -5
  55. lionagi/service/hooks/hooked_event.py +63 -3
  56. lionagi/service/imodel.py +24 -20
  57. lionagi/service/third_party/claude_code.py +3 -3
  58. lionagi/service/third_party/openai_models.py +435 -0
  59. lionagi/service/token_calculator.py +1 -94
  60. lionagi/session/branch.py +190 -400
  61. lionagi/session/session.py +8 -99
  62. lionagi/tools/file/reader.py +2 -2
  63. lionagi/version.py +1 -1
  64. {lionagi-0.17.11.dist-info → lionagi-0.18.1.dist-info}/METADATA +6 -6
  65. lionagi-0.18.1.dist-info/RECORD +164 -0
  66. lionagi/fields/__init__.py +0 -47
  67. lionagi/fields/action.py +0 -188
  68. lionagi/fields/base.py +0 -153
  69. lionagi/fields/code.py +0 -239
  70. lionagi/fields/file.py +0 -234
  71. lionagi/fields/instruct.py +0 -135
  72. lionagi/fields/reason.py +0 -55
  73. lionagi/fields/research.py +0 -52
  74. lionagi/operations/_act/act.py +0 -86
  75. lionagi/operations/brainstorm/__init__.py +0 -2
  76. lionagi/operations/brainstorm/brainstorm.py +0 -498
  77. lionagi/operations/brainstorm/prompt.py +0 -11
  78. lionagi/operations/instruct/__init__.py +0 -2
  79. lionagi/operations/instruct/instruct.py +0 -28
  80. lionagi/operations/plan/__init__.py +0 -6
  81. lionagi/operations/plan/plan.py +0 -386
  82. lionagi/operations/plan/prompt.py +0 -25
  83. lionagi/operations/utils.py +0 -45
  84. lionagi/protocols/forms/__init__.py +0 -2
  85. lionagi/protocols/forms/base.py +0 -85
  86. lionagi/protocols/forms/flow.py +0 -79
  87. lionagi/protocols/forms/form.py +0 -86
  88. lionagi/protocols/forms/report.py +0 -48
  89. lionagi/protocols/mail/__init__.py +0 -2
  90. lionagi/protocols/mail/exchange.py +0 -220
  91. lionagi/protocols/mail/mail.py +0 -51
  92. lionagi/protocols/mail/mailbox.py +0 -103
  93. lionagi/protocols/mail/manager.py +0 -218
  94. lionagi/protocols/mail/package.py +0 -101
  95. lionagi/protocols/messages/templates/README.md +0 -28
  96. lionagi/protocols/messages/templates/action_request.jinja2 +0 -5
  97. lionagi/protocols/messages/templates/action_response.jinja2 +0 -9
  98. lionagi/protocols/messages/templates/assistant_response.jinja2 +0 -6
  99. lionagi/protocols/messages/templates/instruction_message.jinja2 +0 -61
  100. lionagi/protocols/messages/templates/system_message.jinja2 +0 -11
  101. lionagi/protocols/messages/templates/tool_schemas.jinja2 +0 -7
  102. lionagi/protocols/operatives/__init__.py +0 -2
  103. lionagi/service/connections/providers/types.py +0 -28
  104. lionagi/service/third_party/openai_model_names.py +0 -198
  105. lionagi/service/types.py +0 -58
  106. lionagi-0.17.11.dist-info/RECORD +0 -199
  107. /lionagi/operations/{_act → act}/__init__.py +0 -0
  108. {lionagi-0.17.11.dist-info → lionagi-0.18.1.dist-info}/WHEEL +0 -0
  109. {lionagi-0.17.11.dist-info → lionagi-0.18.1.dist-info}/licenses/LICENSE +0 -0
@@ -4,7 +4,8 @@
4
4
  import logging
5
5
  from typing import Any
6
6
 
7
- from lionagi.fields.action import ActionRequestModel
7
+ from pydantic import BaseModel
8
+
8
9
  from lionagi.protocols._concepts import Manager
9
10
  from lionagi.protocols.messages.action_request import ActionRequest
10
11
  from lionagi.utils import to_list
@@ -121,7 +122,7 @@ class ActionManager(Manager):
121
122
  self.register_tool(t, update=update)
122
123
 
123
124
  def match_tool(
124
- self, action_request: ActionRequest | ActionRequestModel | dict
125
+ self, action_request: ActionRequest | BaseModel | dict
125
126
  ) -> FunctionCalling:
126
127
  """
127
128
  Convert an ActionRequest (or dict with "function"/"arguments")
@@ -134,9 +135,7 @@ class ActionManager(Manager):
134
135
  Returns:
135
136
  FunctionCalling: The event object that can be invoked.
136
137
  """
137
- if not isinstance(
138
- action_request, ActionRequest | ActionRequestModel | dict
139
- ):
138
+ if not isinstance(action_request, ActionRequest | BaseModel | dict):
140
139
  raise TypeError(f"Unsupported type {type(action_request)}")
141
140
 
142
141
  func, args = None, None
@@ -155,7 +154,7 @@ class ActionManager(Manager):
155
154
 
156
155
  async def invoke(
157
156
  self,
158
- func_call: ActionRequestModel | ActionRequest,
157
+ func_call: BaseModel | ActionRequest,
159
158
  ) -> FunctionCalling:
160
159
  """
161
160
  High-level API to parse and run a function call.
@@ -24,7 +24,7 @@ class ObservableProto(Protocol):
24
24
 
25
25
  This protocol defines the minimal contract for observable objects:
26
26
  they must have an 'id' property. The return type is permissive (Any)
27
- to maintain compatibility with V0's IDType wrapper while enabling
27
+ to maintain compatibility with V0's UUID wrapper while enabling
28
28
  V1 evolution.
29
29
 
30
30
  All V0 Element subclasses automatically satisfy this protocol without
@@ -33,7 +33,7 @@ class ObservableProto(Protocol):
33
33
 
34
34
  @property
35
35
  def id(self) -> object:
36
- """Unique identifier. Accepts IDType, UUID, or string."""
36
+ """Unique identifier. Accepts UUID, UUID, or string."""
37
37
  ...
38
38
 
39
39
 
@@ -1,2 +1,24 @@
1
1
  # Copyright (c) 2023-2025, HaiyangLi <quantocean.li at gmail dot com>
2
2
  # SPDX-License-Identifier: Apache-2.0
3
+
4
+ from .element import ID, Element
5
+ from .event import Event, EventStatus, Execution
6
+ from .log import DataLogger, DataLoggerConfig, Log
7
+ from .pile import Pile
8
+ from .processor import Executor, Processor
9
+ from .progression import Progression
10
+
11
+ __all__ = (
12
+ "Element",
13
+ "ID",
14
+ "Event",
15
+ "Execution",
16
+ "Log",
17
+ "DataLogger",
18
+ "DataLoggerConfig",
19
+ "Pile",
20
+ "Progression",
21
+ "Processor",
22
+ "Executor",
23
+ "EventStatus",
24
+ )
@@ -19,98 +19,16 @@ from pydantic import (
19
19
 
20
20
  from lionagi import ln
21
21
  from lionagi._class_registry import get_class
22
- from lionagi._errors import IDError
23
22
  from lionagi.utils import import_module, to_dict
24
23
 
25
24
  from .._concepts import Collective, Observable, Ordering
26
25
 
27
26
  __all__ = (
28
- "IDType",
29
27
  "Element",
30
- "ID",
31
28
  "validate_order",
32
- "DEFAULT_ELEMENT_SERIALIZER",
33
29
  )
34
30
 
35
31
 
36
- class IDType:
37
- """Represents a UUIDv4-based identifier.
38
-
39
- This class wraps a UUID object and provides helper methods for
40
- validating and creating UUID version 4. It also implements equality
41
- and hashing so that it can be used as dictionary keys or in sets.
42
-
43
- Attributes:
44
- _id (UUID): The wrapped UUID object.
45
- """
46
-
47
- __slots__ = ("_id",)
48
-
49
- def __init__(self, id: UUID) -> None:
50
- """Initializes an IDType instance."""
51
- self._id = id
52
-
53
- @classmethod
54
- def validate(cls, value: str | UUID | IDType) -> IDType:
55
- """Validates and converts a value into an IDType.
56
-
57
- Returns:
58
- IDType: The validated IDType object.
59
-
60
- Raises:
61
- IDError: If the provided value is not a valid UUIDv4.
62
- """
63
- if isinstance(value, IDType):
64
- return value
65
- try:
66
- return cls(UUID(str(value), version=4))
67
- except ValueError:
68
- raise IDError(f"Invalid ID: {value}") from None
69
-
70
- @classmethod
71
- def create(cls) -> IDType:
72
- """Creates a new IDType with a randomly generated UUIDv4.
73
-
74
- Returns:
75
- IDType: A new IDType instance with a random UUIDv4.
76
- """
77
- return cls(uuid4())
78
-
79
- def __str__(self) -> str:
80
- """Returns the string representation of the underlying UUID.
81
-
82
- Returns:
83
- str: The string form of this IDType's UUID.
84
- """
85
- return str(self._id)
86
-
87
- def __repr__(self) -> str:
88
- """Returns the unambiguous string representation of this IDType.
89
-
90
- Returns:
91
- str: A developer-friendly string for debugging.
92
- """
93
- return f"IDType({self._id})"
94
-
95
- def __eq__(self, other: Any) -> bool:
96
- """Checks equality with another IDType based on UUID value.
97
-
98
- Returns:
99
- bool: True if both have the same underlying UUID; False otherwise.
100
- """
101
- if not isinstance(other, IDType):
102
- return NotImplemented
103
- return self._id == other._id
104
-
105
- def __hash__(self) -> int:
106
- """Returns a hash based on the underlying UUID.
107
-
108
- Returns:
109
- int: The hash of this object, allowing IDType to be dictionary keys.
110
- """
111
- return hash(self._id)
112
-
113
-
114
32
  class Element(BaseModel, Observable):
115
33
  """Basic identifiable, timestamped element.
116
34
 
@@ -119,7 +37,7 @@ class Element(BaseModel, Observable):
119
37
  dictionary.
120
38
 
121
39
  Attributes:
122
- id (IDType):
40
+ id (UUID):
123
41
  A unique ID based on UUIDv4 (defaults to a newly generated one).
124
42
  created_at (float):
125
43
  The creation timestamp as a float (Unix epoch). Defaults to
@@ -135,8 +53,8 @@ class Element(BaseModel, Observable):
135
53
  extra="forbid",
136
54
  )
137
55
 
138
- id: IDType = Field(
139
- default_factory=IDType.create,
56
+ id: UUID = Field(
57
+ default_factory=uuid4,
140
58
  title="ID",
141
59
  description="Unique identifier for this element.",
142
60
  frozen=True,
@@ -211,12 +129,14 @@ class Element(BaseModel, Observable):
211
129
  raise ValueError(f"Invalid created_at: {val}") from None
212
130
 
213
131
  @field_validator("id", mode="before")
214
- def _ensure_idtype(cls, val: IDType | UUID | str) -> IDType:
215
- """Ensures `id` is validated as an IDType."""
216
- return IDType.validate(val)
132
+ def _ensure_UUID(cls, val: UUID | str) -> UUID:
133
+ """Ensures `id` is validated as an UUID."""
134
+ if isinstance(val, UUID):
135
+ return val
136
+ return UUID(str(val))
217
137
 
218
138
  @field_serializer("id")
219
- def _serialize_id_type(self, val: IDType) -> str:
139
+ def _serialize_id_type(self, val: UUID) -> str:
220
140
  """Serializes the `id` field to a string."""
221
141
  return str(val)
222
142
 
@@ -328,28 +248,27 @@ class Element(BaseModel, Observable):
328
248
 
329
249
 
330
250
  DEFAULT_ELEMENT_SERIALIZER = ln.get_orjson_default(
331
- order=[IDType, Element, BaseModel],
251
+ order=[Element, BaseModel],
332
252
  additional={
333
- IDType: lambda o: str(o),
334
253
  Element: lambda o: o.to_dict(),
335
254
  BaseModel: lambda o: o.model_dump(mode="json"),
336
255
  },
337
256
  )
338
257
 
339
258
 
340
- def validate_order(order: Any) -> list[IDType]:
341
- """Validates and flattens an ordering into a list of IDType objects.
259
+ def validate_order(order: Any) -> list[UUID]:
260
+ """Validates and flattens an ordering into a list of UUID objects.
342
261
 
343
262
  This function accepts a variety of possible representations for ordering
344
263
  (e.g., a single Element, a list of Elements, a dictionary with ID keys,
345
- or a nested structure) and returns a flat list of IDType objects.
264
+ or a nested structure) and returns a flat list of UUID objects.
346
265
 
347
266
  Returns:
348
- list[IDType]: A flat list of validated IDType objects.
267
+ list[UUID]: A flat list of validated UUID objects.
349
268
 
350
269
  Raises:
351
270
  ValueError: If an invalid item is encountered or if there's a mixture
352
- of types not all convertible to IDType.
271
+ of types not all convertible to UUID.
353
272
  """
354
273
  if isinstance(order, Element):
355
274
  return [order.id]
@@ -357,89 +276,79 @@ def validate_order(order: Any) -> list[IDType]:
357
276
  order = list(order.keys())
358
277
 
359
278
  stack = [order]
360
- out: list[IDType] = []
279
+ out: list[UUID] = []
361
280
  while stack:
362
281
  cur = stack.pop()
363
282
  if cur is None:
364
283
  continue
365
284
  if isinstance(cur, Element):
366
285
  out.append(cur.id)
367
- elif isinstance(cur, IDType):
368
- out.append(cur)
369
286
  elif isinstance(cur, UUID):
370
- out.append(IDType.validate(cur))
287
+ out.append(cur)
371
288
  elif isinstance(cur, str):
372
- out.append(IDType.validate(cur))
289
+ out.append(UUID(cur))
373
290
  elif isinstance(cur, (list, tuple, set)):
374
291
  stack.extend(reversed(cur))
375
292
  else:
376
293
  raise ValueError("Invalid item in order.")
377
294
 
378
- if not out:
379
- return []
380
-
381
- # Check for consistent IDType usage
382
- first_type = type(out[0])
383
- if first_type is IDType:
384
- for item in out:
385
- if not isinstance(item, IDType):
386
- raise ValueError("Mixed types in order.")
387
- return out
388
- raise ValueError("Unrecognized type(s) in order.")
295
+ return [] if not out else out
389
296
 
390
297
 
391
298
  E = TypeVar("E", bound=Element)
392
299
 
393
300
 
394
301
  class ID(Generic[E]):
395
- """Utility class for working with IDType objects and Elements.
302
+ """Utility class for working with UUID objects and Elements.
396
303
 
397
304
  This class provides helper methods to extract IDs from Elements, strings,
398
305
  or UUIDs, and to test whether a given object can be interpreted as
399
306
  an ID.
400
307
  """
401
308
 
402
- ID: TypeAlias = IDType
309
+ ID: TypeAlias = UUID
403
310
  Item: TypeAlias = E | Element # type: ignore
404
- Ref: TypeAlias = IDType | E | str # type: ignore
405
- IDSeq: TypeAlias = Sequence[IDType] | Ordering[E] # type: ignore
311
+ Ref: TypeAlias = UUID | E | str # type: ignore
312
+ IDSeq: TypeAlias = Sequence[UUID] | Ordering[E] # type: ignore
406
313
  ItemSeq: TypeAlias = Sequence[E] | Collective[E] # type: ignore
407
314
  RefSeq: TypeAlias = ItemSeq | Sequence[Ref] | Ordering[E] # type: ignore
408
315
 
409
316
  @staticmethod
410
- def get_id(item: E) -> IDType:
411
- """Retrieves an IDType from multiple possible item forms.
317
+ def get_id(item: E) -> UUID:
318
+ """Retrieves an UUID from multiple possible item forms.
412
319
 
413
320
  Acceptable item types include:
414
321
  - Element: Uses its `id` attribute.
415
- - IDType: Returns it directly.
322
+ - UUID: Returns it directly.
416
323
  - UUID: Validates and wraps it.
417
324
  - str: Interpreted as a UUID if possible.
418
325
 
419
326
  Returns:
420
- IDType: The validated ID.
327
+ UUID: The validated ID.
421
328
 
422
329
  Raises:
423
- ValueError: If the item cannot be converted to an IDType.
330
+ ValueError: If the item cannot be converted to an UUID.
424
331
  """
332
+ if isinstance(item, UUID):
333
+ return item
425
334
  if isinstance(item, Element):
426
335
  return item.id
427
- if isinstance(item, (IDType, UUID, str)):
428
- return IDType.validate(item)
336
+ if isinstance(item, str):
337
+ return UUID(item)
429
338
  raise ValueError("Cannot get ID from item.")
430
339
 
431
340
  @staticmethod
432
341
  def is_id(item: Any) -> bool:
433
- """Checks if an item can be validated as an IDType.
342
+ """Checks if an item can be validated as an UUID.
434
343
 
435
344
  Returns:
436
- bool: True if `item` is or can be validated as an IDType;
345
+ bool: True if `item` is or can be validated as an UUID;
437
346
  otherwise, False.
438
347
  """
439
348
  try:
440
- IDType.validate(item)
349
+ ID.get_id(item) # type: ignore
441
350
  return True
442
- except IDError:
351
+ except ValueError:
443
352
  return False
444
353
 
445
354
 
@@ -143,10 +143,11 @@ class DataLogger:
143
143
  if self._config.auto_save_on_exit:
144
144
  atexit.register(self.save_at_exit)
145
145
 
146
- def log(self, log_: Log) -> None:
146
+ def log(self, log_: Any) -> None:
147
147
  """
148
148
  Add a log synchronously. If capacity is reached, auto-dump to file.
149
149
  """
150
+ log_ = Log.create(log_) if not isinstance(log_, Log) else log_
150
151
  if self._config.capacity and len(self.logs) >= self._config.capacity:
151
152
  try:
152
153
  self.dump(clear=self._config.clear_after_dump)
@@ -154,7 +155,7 @@ class DataLogger:
154
155
  logger.error(f"Failed to auto-dump logs: {e}")
155
156
  self.logs.include(log_)
156
157
 
157
- async def alog(self, log_: Log) -> None:
158
+ async def alog(self, log_: Any) -> None:
158
159
  """
159
160
  Add a log asynchronously. If capacity is reached, auto-dump to file.
160
161
  """
@@ -16,6 +16,7 @@ from collections.abc import (
16
16
  from functools import wraps
17
17
  from pathlib import Path
18
18
  from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal, TypeVar
19
+ from uuid import UUID
19
20
 
20
21
  from pydantic import Field, field_serializer
21
22
  from pydapter import Adaptable, AsyncAdaptable
@@ -32,7 +33,7 @@ from lionagi.utils import (
32
33
  )
33
34
 
34
35
  from .._concepts import Observable
35
- from .element import ID, Collective, E, Element, IDType, validate_order
36
+ from .element import ID, Collective, E, Element, validate_order
36
37
  from .progression import Progression
37
38
 
38
39
  if TYPE_CHECKING:
@@ -112,7 +113,7 @@ def _validate_item_type(value, /) -> set[type[T]] | None:
112
113
 
113
114
 
114
115
  def _validate_progression(
115
- value: Any, collections: dict[IDType, T], /
116
+ value: Any, collections: dict[UUID, T], /
116
117
  ) -> Progression:
117
118
  if not value:
118
119
  return Progression(order=list(collections.keys()))
@@ -198,7 +199,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
198
199
  strict_type (bool): Whether to enforce strict type checking
199
200
  """
200
201
 
201
- collections: dict[IDType, T] = Field(default_factory=dict)
202
+ collections: dict[UUID, T] = Field(default_factory=dict)
202
203
  item_type: set | None = Field(
203
204
  default=None,
204
205
  description="Set of allowed types for items in the pile.",
@@ -282,9 +283,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
282
283
  super().__init__(**data)
283
284
 
284
285
  @field_serializer("collections")
285
- def _serialize_collections(
286
- self, v: dict[IDType, T]
287
- ) -> list[dict[str, Any]]:
286
+ def _serialize_collections(self, v: dict[UUID, T]) -> list[dict[str, Any]]:
288
287
  return [i.to_dict() for i in v.values()]
289
288
 
290
289
  @field_serializer("progression")
@@ -492,7 +491,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
492
491
  """Get all items in order."""
493
492
  return [self.collections[key] for key in self.progression]
494
493
 
495
- def items(self) -> Sequence[tuple[IDType, T]]:
494
+ def items(self) -> Sequence[tuple[UUID, T]]:
496
495
  """Get all (ID, item) pairs in order."""
497
496
  return [(key, self.collections[key]) for key in self.progression]
498
497
 
@@ -797,7 +796,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
797
796
  except Exception as e:
798
797
  raise ItemNotFoundError(f"index {key}. Error: {e}")
799
798
 
800
- elif isinstance(key, IDType):
799
+ elif isinstance(key, UUID):
801
800
  try:
802
801
  return self.collections[key]
803
802
  except Exception as e:
@@ -904,7 +903,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
904
903
  if isinstance(key, int | slice):
905
904
  try:
906
905
  pops = self.progression[key]
907
- pops = [pops] if isinstance(pops, IDType) else pops
906
+ pops = [pops] if isinstance(pops, UUID) else pops
908
907
  result = []
909
908
  for i in pops:
910
909
  self.progression.remove(i)
@@ -1196,7 +1195,7 @@ def to_list_type(value: Any, /) -> list[Any]:
1196
1195
  """Convert input to a list format"""
1197
1196
  if value is None:
1198
1197
  return []
1199
- if isinstance(value, IDType):
1198
+ if isinstance(value, UUID):
1200
1199
  return [value]
1201
1200
  if isinstance(value, str):
1202
1201
  return ID.get_id(value) if ID.is_id(value) else []
@@ -4,6 +4,7 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  from typing import Any, Generic, TypeVar
7
+ from uuid import UUID
7
8
 
8
9
  from pydantic import Field, field_serializer, field_validator
9
10
  from typing_extensions import Self
@@ -11,7 +12,7 @@ from typing_extensions import Self
11
12
  from lionagi._errors import ItemNotFoundError
12
13
 
13
14
  from .._concepts import Ordering
14
- from .element import ID, Element, IDError, IDType, validate_order
15
+ from .element import ID, Element, validate_order
15
16
 
16
17
  T = TypeVar("T", bound=Element)
17
18
 
@@ -26,7 +27,7 @@ class Progression(Element, Ordering[T], Generic[T]):
26
27
  """Tracks an ordered sequence of item IDs, with optional naming.
27
28
 
28
29
  This class extends `Element` and implements `Ordering`, providing
29
- list-like operations for managing item IDs (based on `IDType`). It
30
+ list-like operations for managing item IDs (based on `UUID`). It
30
31
  supports insertion, removal, slicing, and more. Items are stored in
31
32
  `order`, which is a simple list of IDs, and an optional `name`
32
33
  attribute can be assigned for identification.
@@ -50,23 +51,23 @@ class Progression(Element, Ordering[T], Generic[T]):
50
51
  )
51
52
 
52
53
  @field_validator("order", mode="before")
53
- def _validate_ordering(cls, value: Any) -> list[IDType]:
54
- """Ensures `order` is a valid list of IDTypes.
54
+ def _validate_ordering(cls, value: Any) -> list[UUID]:
55
+ """Ensures `order` is a valid list of UUIDs.
55
56
 
56
57
  Args:
57
58
  value (Any): Input sequence (could be elements, IDs, etc.).
58
59
 
59
60
  Returns:
60
- list[IDType]: The list of validated IDType objects.
61
+ list[UUID]: The list of validated UUID objects.
61
62
  """
62
63
  return validate_order(value)
63
64
 
64
65
  @field_serializer("order")
65
- def _serialize_order(self, value: list[IDType]) -> list[str]:
66
+ def _serialize_order(self, value: list[UUID]) -> list[str]:
66
67
  """Serializes IDs in `order` to string form.
67
68
 
68
69
  Args:
69
- value (list[IDType]): The order list of ID objects.
70
+ value (list[UUID]): The order list of ID objects.
70
71
 
71
72
  Returns:
72
73
  list[str]: A list of stringified IDs.
@@ -85,7 +86,7 @@ class Progression(Element, Ordering[T], Generic[T]):
85
86
  """Checks if one or more IDs exist in the progression.
86
87
 
87
88
  Args:
88
- item (Any): Could be an `Element`, `IDType`, `UUID`, string,
89
+ item (Any): Could be an `Element`, `UUID`, `UUID`, string,
89
90
  or a sequence of these.
90
91
 
91
92
  Returns:
@@ -98,14 +99,14 @@ class Progression(Element, Ordering[T], Generic[T]):
98
99
  except Exception:
99
100
  return False
100
101
 
101
- def __getitem__(self, key: int | slice) -> IDType | list[IDType]:
102
+ def __getitem__(self, key: int | slice) -> UUID | list[UUID]:
102
103
  """Gets one or more items by index or slice.
103
104
 
104
105
  Args:
105
106
  key (int | slice): The index or slice.
106
107
 
107
108
  Returns:
108
- IDType | list[IDType]:
109
+ UUID | list[UUID]:
109
110
  A single ID if `key` is an int; a new `Progression`
110
111
  if `key` is a slice.
111
112
 
@@ -164,15 +165,15 @@ class Progression(Element, Ordering[T], Generic[T]):
164
165
  """Iterates over the IDs in this progression.
165
166
 
166
167
  Returns:
167
- Iterator[IDType]: An iterator over the ID elements.
168
+ Iterator[UUID]: An iterator over the ID elements.
168
169
  """
169
170
  return iter(self.order)
170
171
 
171
- def __next__(self) -> IDType:
172
+ def __next__(self) -> UUID:
172
173
  """Returns the next item if used as an iterator.
173
174
 
174
175
  Returns:
175
- IDType: The next item in the iteration.
176
+ UUID: The next item in the iteration.
176
177
 
177
178
  Raises:
178
179
  StopIteration: If there are no more items.
@@ -182,11 +183,11 @@ class Progression(Element, Ordering[T], Generic[T]):
182
183
  except StopIteration:
183
184
  raise StopIteration("No more items in the progression")
184
185
 
185
- def __list__(self) -> list[IDType]:
186
+ def __list__(self) -> list[UUID]:
186
187
  """Returns a copy of all IDs in the progression.
187
188
 
188
189
  Returns:
189
- list[IDType]: A shallow copy of the ID list.
190
+ list[UUID]: A shallow copy of the ID list.
190
191
  """
191
192
  return self.order[:]
192
193
 
@@ -256,7 +257,7 @@ class Progression(Element, Ordering[T], Generic[T]):
256
257
  refs = validate_order(item)
257
258
  self.order.extend(refs)
258
259
 
259
- def pop(self, index: int = -1) -> IDType:
260
+ def pop(self, index: int = -1) -> UUID:
260
261
  """Removes and returns one ID by index.
261
262
 
262
263
  Args:
@@ -264,7 +265,7 @@ class Progression(Element, Ordering[T], Generic[T]):
264
265
  Position of the item to pop (default is the last item).
265
266
 
266
267
  Returns:
267
- IDType: The removed ID.
268
+ UUID: The removed ID.
268
269
 
269
270
  Raises:
270
271
  ItemNotFoundError: If the index is invalid or out of range.
@@ -274,11 +275,11 @@ class Progression(Element, Ordering[T], Generic[T]):
274
275
  except Exception as e:
275
276
  raise ItemNotFoundError(str(e)) from e
276
277
 
277
- def popleft(self) -> IDType:
278
+ def popleft(self) -> UUID:
278
279
  """Removes and returns the first ID.
279
280
 
280
281
  Returns:
281
- IDType: The ID at the front of the progression.
282
+ UUID: The ID at the front of the progression.
282
283
 
283
284
  Raises:
284
285
  ItemNotFoundError: If the progression is empty.
@@ -300,9 +301,9 @@ class Progression(Element, Ordering[T], Generic[T]):
300
301
  """
301
302
  try:
302
303
  refs = validate_order(item)
303
- except IDError:
304
- raise ItemNotFoundError("Invalid ID(s) provided.")
305
-
304
+ except ValueError as e:
305
+ # Invalid UUID strings are treated as not found
306
+ raise ItemNotFoundError(str(item)) from e
306
307
  if not refs:
307
308
  return
308
309
  missing = [r for r in refs if r not in self.order]
@@ -2,6 +2,7 @@
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  from typing import Any
5
+ from uuid import UUID
5
6
 
6
7
  from pydantic import (
7
8
  BaseModel,
@@ -14,7 +15,7 @@ from pydantic import (
14
15
  from lionagi.utils import is_same_dtype
15
16
 
16
17
  from .._concepts import Condition, Relational
17
- from ..generic.element import ID, Element, IDType
18
+ from ..generic.element import ID, Element
18
19
 
19
20
  __all__ = (
20
21
  "EdgeCondition",
@@ -51,8 +52,8 @@ class Edge(Element):
51
52
  metadata, etc., may be stored in `properties`.
52
53
  """
53
54
 
54
- head: IDType
55
- tail: IDType
55
+ head: UUID
56
+ tail: UUID
56
57
  properties: dict[str, Any] = Field(
57
58
  default_factory=dict,
58
59
  title="Properties",
@@ -106,11 +107,11 @@ class Edge(Element):
106
107
  super().__init__(head=head, tail=tail, properties=kwargs)
107
108
 
108
109
  @field_serializer("head", "tail")
109
- def _serialize_id(self, value: IDType) -> str:
110
+ def _serialize_id(self, value: UUID) -> str:
110
111
  return str(value)
111
112
 
112
113
  @field_validator("head", "tail", mode="before")
113
- def _validate_id(cls, value: str) -> IDType:
114
+ def _validate_id(cls, value: str) -> UUID:
114
115
  return ID.get_id(value)
115
116
 
116
117
  @property