lionagi 0.15.14__py3-none-any.whl → 0.16.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.
- lionagi/adapters/async_postgres_adapter.py +1 -1
- lionagi/libs/nested/ninsert.py +3 -6
- lionagi/libs/nested/nmerge.py +1 -2
- lionagi/libs/validate/fuzzy_match_keys.py +5 -182
- lionagi/libs/validate/string_similarity.py +6 -331
- lionagi/ln/__init__.py +56 -66
- lionagi/ln/_async_call.py +13 -10
- lionagi/ln/_hash.py +33 -8
- lionagi/ln/_list_call.py +2 -35
- lionagi/ln/_to_list.py +51 -28
- lionagi/ln/_utils.py +156 -0
- lionagi/ln/concurrency/__init__.py +39 -31
- lionagi/ln/concurrency/_compat.py +65 -0
- lionagi/ln/concurrency/cancel.py +92 -109
- lionagi/ln/concurrency/errors.py +17 -17
- lionagi/ln/concurrency/patterns.py +249 -206
- lionagi/ln/concurrency/primitives.py +257 -216
- lionagi/ln/concurrency/resource_tracker.py +42 -155
- lionagi/ln/concurrency/task.py +55 -73
- lionagi/ln/concurrency/throttle.py +3 -0
- lionagi/ln/concurrency/utils.py +1 -0
- lionagi/ln/fuzzy/__init__.py +15 -0
- lionagi/ln/{_extract_json.py → fuzzy/_extract_json.py} +22 -9
- lionagi/ln/{_fuzzy_json.py → fuzzy/_fuzzy_json.py} +14 -8
- lionagi/ln/fuzzy/_fuzzy_match.py +172 -0
- lionagi/ln/fuzzy/_fuzzy_validate.py +46 -0
- lionagi/ln/fuzzy/_string_similarity.py +332 -0
- lionagi/ln/{_models.py → types.py} +153 -4
- lionagi/operations/ReAct/utils.py +1 -2
- lionagi/operations/flow.py +2 -1
- lionagi/operations/operate/operate.py +26 -16
- lionagi/protocols/action/function_calling.py +1 -4
- lionagi/protocols/contracts.py +46 -0
- lionagi/protocols/generic/element.py +1 -58
- lionagi/protocols/generic/event.py +6 -6
- lionagi/protocols/generic/processor.py +9 -5
- lionagi/protocols/graph/graph.py +1 -2
- lionagi/protocols/graph/node.py +2 -4
- lionagi/protocols/ids.py +82 -0
- lionagi/protocols/messages/instruction.py +1 -2
- lionagi/protocols/messages/manager.py +1 -2
- lionagi/protocols/messages/message.py +1 -4
- lionagi/protocols/types.py +10 -12
- lionagi/service/connections/providers/claude_code_.py +1 -2
- lionagi/service/resilience.py +1 -2
- lionagi/tools/memory/tools.py +2 -4
- lionagi/utils.py +34 -64
- lionagi/version.py +1 -1
- {lionagi-0.15.14.dist-info → lionagi-0.16.1.dist-info}/METADATA +4 -2
- {lionagi-0.15.14.dist-info → lionagi-0.16.1.dist-info}/RECORD +52 -45
- lionagi/ln/_types.py +0 -146
- {lionagi-0.15.14.dist-info → lionagi-0.16.1.dist-info}/WHEEL +0 -0
- {lionagi-0.15.14.dist-info → lionagi-0.16.1.dist-info}/licenses/LICENSE +0 -0
@@ -18,8 +18,7 @@ class PlannedAction(HashableModel):
|
|
18
18
|
action_type: str | None = Field(
|
19
19
|
default=None,
|
20
20
|
description=(
|
21
|
-
"The name or type of tool/action to invoke. "
|
22
|
-
"(e.g., 'search_exa', 'reader_tool')"
|
21
|
+
"The name or type of tool/action to invoke. (e.g., 'search_exa', 'reader_tool')"
|
23
22
|
),
|
24
23
|
)
|
25
24
|
description: str | None = Field(
|
lionagi/operations/flow.py
CHANGED
@@ -12,7 +12,8 @@ using Events for synchronization and CapacityLimiter for concurrency control.
|
|
12
12
|
import os
|
13
13
|
from typing import Any
|
14
14
|
|
15
|
-
from lionagi.ln import AlcallParams
|
15
|
+
from lionagi.ln._async_call import AlcallParams
|
16
|
+
from lionagi.ln.concurrency import CapacityLimiter, ConcurrencyEvent
|
16
17
|
from lionagi.operations.node import Operation
|
17
18
|
from lionagi.protocols.types import EventStatus, Graph
|
18
19
|
from lionagi.session.branch import Branch
|
@@ -23,6 +23,29 @@ if TYPE_CHECKING:
|
|
23
23
|
from lionagi.session.branch import Branch
|
24
24
|
|
25
25
|
|
26
|
+
def _handle_response_format_kwargs(
|
27
|
+
operative_model: type[BaseModel] = None,
|
28
|
+
request_model: type[BaseModel] = None,
|
29
|
+
response_format: type[BaseModel] = None,
|
30
|
+
):
|
31
|
+
if operative_model:
|
32
|
+
logging.warning(
|
33
|
+
"`operative_model` is deprecated. Use `response_format` instead."
|
34
|
+
)
|
35
|
+
if (
|
36
|
+
(operative_model and response_format)
|
37
|
+
or (operative_model and request_model)
|
38
|
+
or (response_format and request_model)
|
39
|
+
):
|
40
|
+
raise ValueError(
|
41
|
+
"Cannot specify both `operative_model` and `response_format` (or `request_model`) "
|
42
|
+
"as they are aliases of each other."
|
43
|
+
)
|
44
|
+
|
45
|
+
# Use the final chosen format
|
46
|
+
return response_format or operative_model or request_model
|
47
|
+
|
48
|
+
|
26
49
|
async def operate(
|
27
50
|
branch: "Branch",
|
28
51
|
*,
|
@@ -66,22 +89,9 @@ async def operate(
|
|
66
89
|
include_token_usage_to_model: bool = False,
|
67
90
|
**kwargs,
|
68
91
|
) -> list | BaseModel | None | dict | str:
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
)
|
73
|
-
if (
|
74
|
-
(operative_model and response_format)
|
75
|
-
or (operative_model and request_model)
|
76
|
-
or (response_format and request_model)
|
77
|
-
):
|
78
|
-
raise ValueError(
|
79
|
-
"Cannot specify both `operative_model` and `response_format` (or `request_model`) "
|
80
|
-
"as they are aliases of each other."
|
81
|
-
)
|
82
|
-
|
83
|
-
# Use the final chosen format
|
84
|
-
response_format = response_format or operative_model or request_model
|
92
|
+
response_format = _handle_response_format_kwargs(
|
93
|
+
operative_model, request_model, response_format
|
94
|
+
)
|
85
95
|
|
86
96
|
# Decide which chat model to use
|
87
97
|
chat_model = chat_model or imodel or branch.chat_model
|
@@ -130,10 +130,7 @@ class FunctionCalling(Event):
|
|
130
130
|
Returns:
|
131
131
|
A string containing the class name and key attributes.
|
132
132
|
"""
|
133
|
-
return (
|
134
|
-
f"FunctionCalling(function={self.func_tool.function}, "
|
135
|
-
f"arguments={self.arguments})"
|
136
|
-
)
|
133
|
+
return f"FunctionCalling(function={self.func_tool.function}, arguments={self.arguments})"
|
137
134
|
|
138
135
|
def to_dict(self) -> dict[str, Any]:
|
139
136
|
"""Convert instance to dictionary.
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copyright (c) 2023 - 2025, HaiyangLi <quantocean.li at gmail dot com>
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
|
5
|
+
"""V1 Observable Protocol for gradual evolution.
|
6
|
+
|
7
|
+
This module provides the runtime-checkable ObservableProto for V1 components
|
8
|
+
while maintaining compatibility with V0's nominal Observable ABC.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
from typing import Protocol, runtime_checkable
|
14
|
+
|
15
|
+
__all__ = (
|
16
|
+
"ObservableProto",
|
17
|
+
"Observable",
|
18
|
+
"LegacyObservable",
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
@runtime_checkable
|
23
|
+
class ObservableProto(Protocol):
|
24
|
+
"""Structural Observable Protocol for V1 components.
|
25
|
+
|
26
|
+
This protocol defines the minimal contract for observable objects:
|
27
|
+
they must have an 'id' property. The return type is permissive (Any)
|
28
|
+
to maintain compatibility with V0's IDType wrapper while enabling
|
29
|
+
V1 evolution.
|
30
|
+
|
31
|
+
All V0 Element subclasses automatically satisfy this protocol without
|
32
|
+
any code changes, enabling zero-risk gradual migration.
|
33
|
+
"""
|
34
|
+
|
35
|
+
@property
|
36
|
+
def id(self) -> object:
|
37
|
+
"""Unique identifier. Accepts IDType, UUID, or string."""
|
38
|
+
...
|
39
|
+
|
40
|
+
|
41
|
+
# Convenience alias for V1 consumers (keeps import names short)
|
42
|
+
Observable = ObservableProto
|
43
|
+
|
44
|
+
# Keep legacy nominal ABC for places that need issubclass checks (e.g., Pile)
|
45
|
+
# Do NOT remove – Pile and others rely on issubclass(..., Observable) nominal checks.
|
46
|
+
from ._concepts import Observable as LegacyObservable
|
@@ -313,7 +313,6 @@ class Element(BaseModel, Observable):
|
|
313
313
|
if mode == "db":
|
314
314
|
dict_ = orjson.loads(self.to_json(decode=False))
|
315
315
|
dict_["node_metadata"] = dict_.pop("metadata", {})
|
316
|
-
dict_["created_at"] = self.created_datetime.isoformat(sep=" ")
|
317
316
|
return dict_
|
318
317
|
|
319
318
|
def as_jsonable(self) -> dict:
|
@@ -321,19 +320,13 @@ class Element(BaseModel, Observable):
|
|
321
320
|
return self.to_dict(mode="json")
|
322
321
|
|
323
322
|
@classmethod
|
324
|
-
def from_dict(cls, data: dict
|
323
|
+
def from_dict(cls, data: dict) -> Element:
|
325
324
|
"""Deserializes a dictionary into an Element or subclass of Element.
|
326
325
|
|
327
326
|
If `lion_class` in `metadata` refers to a subclass, this method
|
328
327
|
is polymorphic, it will attempt to create an instance of that subclass.
|
329
|
-
|
330
|
-
Args:
|
331
|
-
data (dict): A dictionary of field data.
|
332
|
-
mode (str): Format mode - "python" for normal dicts, "db" for database format.
|
333
328
|
"""
|
334
329
|
# Preprocess database format if needed
|
335
|
-
if mode == "db":
|
336
|
-
data = cls._preprocess_db_data(data.copy())
|
337
330
|
metadata = {}
|
338
331
|
|
339
332
|
if "node_metadata" in data:
|
@@ -367,56 +360,6 @@ class Element(BaseModel, Observable):
|
|
367
360
|
data["metadata"] = metadata
|
368
361
|
return cls.model_validate(data)
|
369
362
|
|
370
|
-
@classmethod
|
371
|
-
def _preprocess_db_data(cls, data: dict) -> dict:
|
372
|
-
"""Preprocess raw database data for Element compatibility."""
|
373
|
-
import datetime as dt
|
374
|
-
import json
|
375
|
-
|
376
|
-
# Handle created_at field - convert datetime string to timestamp
|
377
|
-
if "created_at" in data and isinstance(data["created_at"], str):
|
378
|
-
try:
|
379
|
-
# Parse datetime string and convert to timestamp
|
380
|
-
dt_obj = dt.datetime.fromisoformat(
|
381
|
-
data["created_at"].replace(" ", "T")
|
382
|
-
)
|
383
|
-
# Treat as UTC if naive
|
384
|
-
if dt_obj.tzinfo is None:
|
385
|
-
dt_obj = dt_obj.replace(tzinfo=dt.timezone.utc)
|
386
|
-
data["created_at"] = dt_obj.timestamp()
|
387
|
-
except (ValueError, TypeError):
|
388
|
-
# Keep as string if parsing fails
|
389
|
-
pass
|
390
|
-
|
391
|
-
# Handle JSON string fields - parse to dict/list
|
392
|
-
json_fields = ["content", "node_metadata", "embedding"]
|
393
|
-
for field in json_fields:
|
394
|
-
if field in data and isinstance(data[field], str):
|
395
|
-
if data[field] in ("null", ""):
|
396
|
-
data[field] = None if field == "embedding" else {}
|
397
|
-
else:
|
398
|
-
try:
|
399
|
-
data[field] = json.loads(data[field])
|
400
|
-
except (json.JSONDecodeError, TypeError):
|
401
|
-
# Keep as empty dict for metadata fields, None for embedding
|
402
|
-
data[field] = {} if field != "embedding" else None
|
403
|
-
|
404
|
-
# Handle node_metadata -> metadata mapping
|
405
|
-
if "node_metadata" in data:
|
406
|
-
if (
|
407
|
-
data["node_metadata"] == "null"
|
408
|
-
or data["node_metadata"] is None
|
409
|
-
):
|
410
|
-
data["metadata"] = {}
|
411
|
-
else:
|
412
|
-
data["metadata"] = (
|
413
|
-
data["node_metadata"] if data["node_metadata"] else {}
|
414
|
-
)
|
415
|
-
# Remove node_metadata to avoid Pydantic validation error
|
416
|
-
data.pop("node_metadata", None)
|
417
|
-
|
418
|
-
return data
|
419
|
-
|
420
363
|
def to_json(self, decode: bool = True) -> str:
|
421
364
|
"""Converts this Element to a JSON string."""
|
422
365
|
dict_ = self._to_dict()
|
@@ -5,13 +5,13 @@
|
|
5
5
|
from __future__ import annotations
|
6
6
|
|
7
7
|
import contextlib
|
8
|
-
from enum import Enum
|
8
|
+
from enum import Enum as _Enum
|
9
9
|
from typing import Any
|
10
10
|
|
11
11
|
from pydantic import Field, field_serializer
|
12
12
|
|
13
13
|
from lionagi import ln
|
14
|
-
from lionagi.utils import to_dict
|
14
|
+
from lionagi.utils import Unset, to_dict
|
15
15
|
|
16
16
|
from .element import Element
|
17
17
|
|
@@ -22,10 +22,10 @@ __all__ = (
|
|
22
22
|
)
|
23
23
|
|
24
24
|
|
25
|
-
_SIMPLE_TYPE = (str, bytes, bytearray, int, float, type(None),
|
25
|
+
_SIMPLE_TYPE = (str, bytes, bytearray, int, float, type(None), _Enum)
|
26
26
|
|
27
27
|
|
28
|
-
class EventStatus(str, ln.Enum):
|
28
|
+
class EventStatus(str, ln.types.Enum):
|
29
29
|
"""Status states for tracking action execution progress.
|
30
30
|
|
31
31
|
Attributes:
|
@@ -96,7 +96,7 @@ class Execution:
|
|
96
96
|
Returns:
|
97
97
|
dict: A dictionary representation of the execution state.
|
98
98
|
"""
|
99
|
-
res_ =
|
99
|
+
res_ = Unset
|
100
100
|
json_serializable = True
|
101
101
|
|
102
102
|
if not isinstance(self.response, _SIMPLE_TYPE):
|
@@ -119,7 +119,7 @@ class Execution:
|
|
119
119
|
res_ = d_
|
120
120
|
json_serializable = True
|
121
121
|
|
122
|
-
if res_ is
|
122
|
+
if res_ is Unset and not json_serializable:
|
123
123
|
res_ = "<unserializable>"
|
124
124
|
|
125
125
|
return {
|
@@ -5,7 +5,11 @@
|
|
5
5
|
import asyncio
|
6
6
|
from typing import Any, ClassVar
|
7
7
|
|
8
|
-
from lionagi.ln import
|
8
|
+
from lionagi.ln.concurrency import (
|
9
|
+
ConcurrencyEvent,
|
10
|
+
Semaphore,
|
11
|
+
create_task_group,
|
12
|
+
)
|
9
13
|
|
10
14
|
from .._concepts import Observer
|
11
15
|
from .element import ID
|
@@ -166,9 +170,9 @@ class Processor(Observer):
|
|
166
170
|
async with self._concurrency_sem:
|
167
171
|
await consume_stream(event)
|
168
172
|
|
169
|
-
|
173
|
+
tg.start_soon(stream_with_sem, next_event)
|
170
174
|
else:
|
171
|
-
|
175
|
+
tg.start_soon(consume_stream, next_event)
|
172
176
|
else:
|
173
177
|
# For non-streaming, just invoke
|
174
178
|
if self._concurrency_sem:
|
@@ -177,9 +181,9 @@ class Processor(Observer):
|
|
177
181
|
async with self._concurrency_sem:
|
178
182
|
await event.invoke()
|
179
183
|
|
180
|
-
|
184
|
+
tg.start_soon(invoke_with_sem, next_event)
|
181
185
|
else:
|
182
|
-
|
186
|
+
tg.start_soon(next_event.invoke)
|
183
187
|
events_processed += 1
|
184
188
|
|
185
189
|
prev_event = next_event
|
lionagi/protocols/graph/graph.py
CHANGED
@@ -87,8 +87,7 @@ class Graph(Element, Relational, Generic[T]):
|
|
87
87
|
or edge.tail not in self.internal_nodes
|
88
88
|
):
|
89
89
|
raise RelationError(
|
90
|
-
"Failed to add edge: Either edge head or tail node does"
|
91
|
-
" not exist in the graph."
|
90
|
+
"Failed to add edge: Either edge head or tail node does not exist in the graph."
|
92
91
|
)
|
93
92
|
try:
|
94
93
|
self.internal_edges.insert(len(self.internal_edges), edge)
|
lionagi/protocols/graph/node.py
CHANGED
@@ -63,7 +63,7 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
|
|
63
63
|
self, obj_key: str, many=False, **kwargs: Any
|
64
64
|
) -> Any:
|
65
65
|
kwargs["adapt_meth"] = "to_dict"
|
66
|
-
kwargs["
|
66
|
+
kwargs["adapt_kw"] = {"mode": "db"}
|
67
67
|
return await super().adapt_to_async(
|
68
68
|
obj_key=obj_key, many=many, **kwargs
|
69
69
|
)
|
@@ -77,7 +77,6 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
|
|
77
77
|
**kwargs: Any,
|
78
78
|
) -> Node:
|
79
79
|
kwargs["adapt_meth"] = "from_dict"
|
80
|
-
kwargs["mode"] = "db"
|
81
80
|
return await super().adapt_from_async(
|
82
81
|
obj, obj_key=obj_key, many=many, **kwargs
|
83
82
|
)
|
@@ -87,7 +86,7 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
|
|
87
86
|
Convert this Node to another format using a registered adapter.
|
88
87
|
"""
|
89
88
|
kwargs["adapt_meth"] = "to_dict"
|
90
|
-
kwargs["
|
89
|
+
kwargs["adapt_kw"] = {"mode": "db"}
|
91
90
|
return super().adapt_to(obj_key=obj_key, many=many, **kwargs)
|
92
91
|
|
93
92
|
@classmethod
|
@@ -104,7 +103,6 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
|
|
104
103
|
auto-delegate to the correct subclass via from_dict.
|
105
104
|
"""
|
106
105
|
kwargs["adapt_meth"] = "from_dict"
|
107
|
-
kwargs["mode"] = "db"
|
108
106
|
return super().adapt_from(obj, obj_key=obj_key, many=many, **kwargs)
|
109
107
|
|
110
108
|
@field_serializer("content")
|
lionagi/protocols/ids.py
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Copyright (c) 2023 - 2025, HaiyangLi <quantocean.li at gmail dot com>
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
|
5
|
+
"""ID bridge utilities for V0/V1 compatibility.
|
6
|
+
|
7
|
+
This module provides utilities to convert between V0's IDType and V1's
|
8
|
+
canonical UUID representation, enabling seamless interoperability during
|
9
|
+
the gradual evolution process.
|
10
|
+
"""
|
11
|
+
|
12
|
+
from __future__ import annotations
|
13
|
+
|
14
|
+
from typing import Any
|
15
|
+
from uuid import UUID
|
16
|
+
|
17
|
+
from .generic.element import Element, IDType
|
18
|
+
|
19
|
+
__all__ = (
|
20
|
+
"to_uuid",
|
21
|
+
"canonical_id",
|
22
|
+
)
|
23
|
+
|
24
|
+
|
25
|
+
def to_uuid(value: Any) -> UUID:
|
26
|
+
"""Convert ID-like values (IDType | UUID | str | Element) to UUID (v4).
|
27
|
+
|
28
|
+
Optimized version that avoids string conversion when possible by directly
|
29
|
+
accessing IDType's internal UUID. Falls back to V0's IDType.validate()
|
30
|
+
for validation semantics only when necessary.
|
31
|
+
|
32
|
+
Args:
|
33
|
+
value: An ID-like value to convert (IDType, UUID, str, or Element)
|
34
|
+
|
35
|
+
Returns:
|
36
|
+
UUID: A validated UUIDv4
|
37
|
+
|
38
|
+
Raises:
|
39
|
+
IDError: If the value cannot be converted to a valid UUIDv4
|
40
|
+
|
41
|
+
Examples:
|
42
|
+
>>> element = Element()
|
43
|
+
>>> uuid_val = to_uuid(element)
|
44
|
+
>>> isinstance(uuid_val, UUID)
|
45
|
+
True
|
46
|
+
>>> to_uuid("550e8400-e29b-41d4-a716-446655440000")
|
47
|
+
UUID('550e8400-e29b-41d4-a716-446655440000')
|
48
|
+
"""
|
49
|
+
if isinstance(value, Element):
|
50
|
+
return value.id._id
|
51
|
+
if isinstance(value, UUID):
|
52
|
+
return value
|
53
|
+
if hasattr(value, "_id") and isinstance(value._id, UUID):
|
54
|
+
return value._id
|
55
|
+
# Fallback: Validate then access ._id directly (no string conversion)
|
56
|
+
validated_id = IDType.validate(value)
|
57
|
+
return validated_id._id
|
58
|
+
|
59
|
+
|
60
|
+
def canonical_id(obj: Any) -> UUID:
|
61
|
+
"""Accept an Observable-like object or raw ID and return canonical UUID.
|
62
|
+
|
63
|
+
Safe to use across V0/V1 without changing class definitions. Prefers
|
64
|
+
attribute access (.id) but falls back to treating the object as a raw ID.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
obj: An Observable object with .id attribute, or a raw ID value
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
UUID: The canonical UUID representation
|
71
|
+
|
72
|
+
Examples:
|
73
|
+
>>> element = Element()
|
74
|
+
>>> uuid_val = canonical_id(element)
|
75
|
+
>>> isinstance(uuid_val, UUID)
|
76
|
+
True
|
77
|
+
>>> canonical_id("550e8400-e29b-41d4-a716-446655440000")
|
78
|
+
UUID('550e8400-e29b-41d4-a716-446655440000')
|
79
|
+
"""
|
80
|
+
# Prefer attribute access; fall back to treating obj as a raw id
|
81
|
+
id_like = getattr(obj, "id", obj)
|
82
|
+
return to_uuid(id_like)
|
@@ -587,8 +587,7 @@ class Instruction(RoledMessage):
|
|
587
587
|
|
588
588
|
if request_model and request_fields:
|
589
589
|
raise ValueError(
|
590
|
-
"You cannot pass both request_model and request_fields "
|
591
|
-
"to create_instruction"
|
590
|
+
"You cannot pass both request_model and request_fields to create_instruction"
|
592
591
|
)
|
593
592
|
if guidance:
|
594
593
|
self.guidance = guidance
|
@@ -216,8 +216,7 @@ class MessageManager(Manager):
|
|
216
216
|
"""
|
217
217
|
if not isinstance(action_request, ActionRequest):
|
218
218
|
raise ValueError(
|
219
|
-
"Error: please provide a corresponding action request for an "
|
220
|
-
"action response."
|
219
|
+
"Error: please provide a corresponding action request for an action response."
|
221
220
|
)
|
222
221
|
params = {
|
223
222
|
"action_request": action_request,
|
@@ -241,10 +241,7 @@ class RoledMessage(Node, Sendable):
|
|
241
241
|
if len(str(self.content)) > 75
|
242
242
|
else str(self.content)
|
243
243
|
)
|
244
|
-
return (
|
245
|
-
f"Message(role={self.role}, sender={self.sender}, "
|
246
|
-
f"content='{content_preview}')"
|
247
|
-
)
|
244
|
+
return f"Message(role={self.role}, sender={self.sender}, content='{content_preview}')"
|
248
245
|
|
249
246
|
|
250
247
|
# File: lionagi/protocols/messages/message.py
|
lionagi/protocols/types.py
CHANGED
@@ -2,18 +2,11 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
-
from ._concepts import
|
6
|
-
|
7
|
-
|
8
|
-
Condition,
|
9
|
-
Manager,
|
10
|
-
Observable,
|
11
|
-
Observer,
|
12
|
-
Ordering,
|
13
|
-
Relational,
|
14
|
-
Sendable,
|
15
|
-
)
|
5
|
+
from ._concepts import Collective, Communicatable, Condition, Manager
|
6
|
+
from ._concepts import Observable as LegacyObservable
|
7
|
+
from ._concepts import Observer, Ordering, Relational, Sendable
|
16
8
|
from .action.manager import ActionManager, FunctionCalling, Tool, ToolRef
|
9
|
+
from .contracts import Observable, ObservableProto
|
17
10
|
from .forms.flow import FlowDefinition, FlowStep
|
18
11
|
from .forms.report import BaseForm, Form, Report
|
19
12
|
from .generic.element import ID, Element, IDError, IDType, validate_order
|
@@ -30,6 +23,7 @@ from .generic.processor import Executor, Processor
|
|
30
23
|
from .generic.progression import Progression, prog
|
31
24
|
from .graph.edge import EdgeCondition
|
32
25
|
from .graph.graph import Edge, Graph, Node
|
26
|
+
from .ids import canonical_id, to_uuid
|
33
27
|
from .mail.exchange import Exchange, Mail, Mailbox, Package, PackageCategory
|
34
28
|
from .mail.manager import MailManager
|
35
29
|
from .messages.base import (
|
@@ -56,11 +50,15 @@ __all__ = (
|
|
56
50
|
"Communicatable",
|
57
51
|
"Condition",
|
58
52
|
"Manager",
|
59
|
-
"Observable",
|
53
|
+
"Observable", # V1 Protocol (preferred)
|
54
|
+
"ObservableProto", # Explicit V1 Protocol name
|
55
|
+
"LegacyObservable", # V0 ABC (deprecated)
|
60
56
|
"Observer",
|
61
57
|
"Ordering",
|
62
58
|
"Relational",
|
63
59
|
"Sendable",
|
60
|
+
"canonical_id", # V0/V1 bridge utility
|
61
|
+
"to_uuid", # ID conversion utility
|
64
62
|
"ID",
|
65
63
|
"Element",
|
66
64
|
"IDError",
|
@@ -56,8 +56,7 @@ class ClaudeCodeEndpoint(Endpoint):
|
|
56
56
|
"Please install it with `uv pip install lionagi[claude_code_sdk]`."
|
57
57
|
)
|
58
58
|
warnings.warn(
|
59
|
-
"The claude_code `query` endpoint is deprecated. "
|
60
|
-
"Use `query_cli` endpoint instead.",
|
59
|
+
"The claude_code `query` endpoint is deprecated. Use `query_cli` endpoint instead.",
|
61
60
|
DeprecationWarning,
|
62
61
|
)
|
63
62
|
|
lionagi/service/resilience.py
CHANGED
@@ -216,8 +216,7 @@ class CircuitBreaker:
|
|
216
216
|
self._metrics["rejected_count"] += 1
|
217
217
|
|
218
218
|
logger.warning(
|
219
|
-
f"Circuit '{self.name}' is HALF_OPEN and at capacity. "
|
220
|
-
f"Try again later."
|
219
|
+
f"Circuit '{self.name}' is HALF_OPEN and at capacity. Try again later."
|
221
220
|
)
|
222
221
|
|
223
222
|
return False
|
lionagi/tools/memory/tools.py
CHANGED
@@ -63,8 +63,7 @@ class MemoryRequest(BaseModel):
|
|
63
63
|
content: str | None = Field(
|
64
64
|
None,
|
65
65
|
description=(
|
66
|
-
"Content to store. REQUIRED if action='store'. "
|
67
|
-
"For other actions, leave it None."
|
66
|
+
"Content to store. REQUIRED if action='store'. For other actions, leave it None."
|
68
67
|
),
|
69
68
|
)
|
70
69
|
|
@@ -96,8 +95,7 @@ class MemoryRequest(BaseModel):
|
|
96
95
|
query: str | None = Field(
|
97
96
|
None,
|
98
97
|
description=(
|
99
|
-
"Query text for semantic search. "
|
100
|
-
"REQUIRED for actions: 'recall', 'search', 'explore'."
|
98
|
+
"Query text for semantic search. REQUIRED for actions: 'recall', 'search', 'explore'."
|
101
99
|
),
|
102
100
|
)
|
103
101
|
|