lionagi 0.15.8__py3-none-any.whl → 0.15.9__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/libs/file/save.py +3 -2
- lionagi/libs/schema/load_pydantic_model_from_schema.py +2 -1
- lionagi/ln/__init__.py +10 -0
- lionagi/ln/_json_dump.py +75 -0
- lionagi/ln/_models.py +0 -1
- lionagi/protocols/generic/element.py +39 -48
- lionagi/protocols/generic/event.py +46 -67
- lionagi/protocols/messages/message.py +3 -1
- lionagi/service/connections/providers/claude_code_.py +9 -7
- lionagi/service/third_party/claude_code.py +3 -2
- lionagi/session/session.py +14 -2
- lionagi/version.py +1 -1
- {lionagi-0.15.8.dist-info → lionagi-0.15.9.dist-info}/METADATA +1 -1
- {lionagi-0.15.8.dist-info → lionagi-0.15.9.dist-info}/RECORD +16 -15
- {lionagi-0.15.8.dist-info → lionagi-0.15.9.dist-info}/WHEEL +0 -0
- {lionagi-0.15.8.dist-info → lionagi-0.15.9.dist-info}/licenses/LICENSE +0 -0
lionagi/libs/file/save.py
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
-
import json
|
6
5
|
import logging
|
7
6
|
from pathlib import Path
|
8
7
|
from typing import Any
|
@@ -78,6 +77,8 @@ def save_chunks(
|
|
78
77
|
random_hash_digits: int,
|
79
78
|
) -> None:
|
80
79
|
"""Helper function to save chunks to files."""
|
80
|
+
from lionagi import ln
|
81
|
+
|
81
82
|
output_path = Path(output_dir)
|
82
83
|
for i, chunk in enumerate(chunks):
|
83
84
|
file_path = create_path(
|
@@ -88,7 +89,7 @@ def save_chunks(
|
|
88
89
|
random_hash_digits=random_hash_digits,
|
89
90
|
)
|
90
91
|
save_to_file(
|
91
|
-
|
92
|
+
ln.json_dumps(chunk),
|
92
93
|
directory=file_path.parent,
|
93
94
|
filename=file_path.name,
|
94
95
|
verbose=verbose,
|
@@ -11,6 +11,7 @@ from typing import Any, TypeVar
|
|
11
11
|
|
12
12
|
from pydantic import BaseModel, PydanticUserError
|
13
13
|
|
14
|
+
from lionagi import ln
|
14
15
|
from lionagi.utils import is_import_installed
|
15
16
|
|
16
17
|
_HAS_DATAMODEL_CODE_GENERATOR = is_import_installed("datamodel_code_generator")
|
@@ -98,7 +99,7 @@ def load_pydantic_model_from_schema(
|
|
98
99
|
sanitized_title # Update the name to use
|
99
100
|
)
|
100
101
|
schema_dict = schema
|
101
|
-
schema_input_data =
|
102
|
+
schema_input_data = ln.json_dumps(schema_dict)
|
102
103
|
except TypeError as e:
|
103
104
|
error_msg = "Invalid dictionary provided for schema"
|
104
105
|
raise ValueError(error_msg) from e
|
lionagi/ln/__init__.py
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
from ._async_call import AlcallParams, BcallParams, alcall, bcall
|
2
2
|
from ._hash import hash_dict
|
3
|
+
from ._json_dump import (
|
4
|
+
DEFAULT_SERIALIZER,
|
5
|
+
DEFAULT_SERIALIZER_OPTION,
|
6
|
+
get_orjson_default,
|
7
|
+
json_dumps,
|
8
|
+
)
|
3
9
|
from ._list_call import LcallParams, lcall
|
4
10
|
from ._models import DataClass, Params
|
5
11
|
from ._to_list import ToListParams, to_list
|
@@ -46,4 +52,8 @@ __all__ = (
|
|
46
52
|
"bcall",
|
47
53
|
"AlcallParams",
|
48
54
|
"BcallParams",
|
55
|
+
"get_orjson_default",
|
56
|
+
"DEFAULT_SERIALIZER",
|
57
|
+
"DEFAULT_SERIALIZER_OPTION",
|
58
|
+
"json_dumps",
|
49
59
|
)
|
lionagi/ln/_json_dump.py
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
import datetime as dt
|
2
|
+
import decimal
|
3
|
+
from collections.abc import Callable
|
4
|
+
from pathlib import Path
|
5
|
+
from uuid import UUID
|
6
|
+
|
7
|
+
import orjson
|
8
|
+
|
9
|
+
|
10
|
+
def _get_default_serializers():
|
11
|
+
return {
|
12
|
+
dt.datetime: lambda o: o.isoformat(),
|
13
|
+
Path: lambda o: str(o),
|
14
|
+
UUID: lambda o: str(o),
|
15
|
+
decimal.Decimal: lambda o: str(o),
|
16
|
+
set: lambda o: list(o),
|
17
|
+
frozenset: lambda o: list(o),
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
def _get_default_serializer_order():
|
22
|
+
return [dt.datetime, Path, UUID, decimal.Decimal, set, frozenset]
|
23
|
+
|
24
|
+
|
25
|
+
def get_orjson_default(
|
26
|
+
order: list[type] = None,
|
27
|
+
additional: dict[type, Callable] = None,
|
28
|
+
extend_default: bool = True,
|
29
|
+
) -> Callable:
|
30
|
+
"""get the default function for orjson.dumps
|
31
|
+
Args:
|
32
|
+
order: order of types to check. Defaults to None.
|
33
|
+
additional: additional serializers
|
34
|
+
extend_default: when order is provided, whether to extend the default order or replace it.
|
35
|
+
"""
|
36
|
+
dict_ = _get_default_serializers()
|
37
|
+
dict_.update(additional or {})
|
38
|
+
order_ = _get_default_serializer_order()
|
39
|
+
|
40
|
+
if order:
|
41
|
+
if len(additional or {}) > 0 and extend_default:
|
42
|
+
order_.extend([k for k in order if k not in order_])
|
43
|
+
else:
|
44
|
+
order_ = list(order)
|
45
|
+
else:
|
46
|
+
if len(additional or {}) > 0:
|
47
|
+
order_.extend([k for k in additional.keys() if k not in order_])
|
48
|
+
|
49
|
+
def default(obj):
|
50
|
+
for t in order_:
|
51
|
+
if isinstance(obj, t) and t in dict_:
|
52
|
+
return dict_[t](obj)
|
53
|
+
raise TypeError(f"Object of type {type(obj)} is not JSON serializable")
|
54
|
+
|
55
|
+
return default
|
56
|
+
|
57
|
+
|
58
|
+
DEFAULT_SERIALIZER = get_orjson_default()
|
59
|
+
DEFAULT_SERIALIZER_OPTION = (
|
60
|
+
orjson.OPT_INDENT_2
|
61
|
+
| orjson.OPT_SORT_KEYS
|
62
|
+
| orjson.OPT_APPEND_NEWLINE
|
63
|
+
| orjson.OPT_SERIALIZE_DATACLASS
|
64
|
+
)
|
65
|
+
|
66
|
+
|
67
|
+
def json_dumps(d_, decode=True, /) -> str:
|
68
|
+
by_ = orjson.dumps(
|
69
|
+
d_,
|
70
|
+
default=DEFAULT_SERIALIZER,
|
71
|
+
option=DEFAULT_SERIALIZER_OPTION,
|
72
|
+
)
|
73
|
+
if decode:
|
74
|
+
return by_.decode("utf-8")
|
75
|
+
return by_
|
lionagi/ln/_models.py
CHANGED
@@ -4,11 +4,12 @@
|
|
4
4
|
|
5
5
|
from __future__ import annotations
|
6
6
|
|
7
|
+
import datetime as dt
|
7
8
|
from collections.abc import Mapping, Sequence
|
8
|
-
from datetime import datetime
|
9
9
|
from typing import Any, Generic, TypeAlias, TypeVar
|
10
10
|
from uuid import UUID, uuid4
|
11
11
|
|
12
|
+
import orjson
|
12
13
|
from pydantic import (
|
13
14
|
BaseModel,
|
14
15
|
ConfigDict,
|
@@ -17,10 +18,11 @@ from pydantic import (
|
|
17
18
|
field_validator,
|
18
19
|
)
|
19
20
|
|
21
|
+
from lionagi import ln
|
20
22
|
from lionagi._class_registry import get_class
|
21
23
|
from lionagi._errors import IDError
|
22
24
|
from lionagi.settings import Settings
|
23
|
-
from lionagi.utils import
|
25
|
+
from lionagi.utils import time, to_dict
|
24
26
|
|
25
27
|
from .._concepts import Collective, Observable, Ordering
|
26
28
|
|
@@ -29,6 +31,7 @@ __all__ = (
|
|
29
31
|
"Element",
|
30
32
|
"ID",
|
31
33
|
"validate_order",
|
34
|
+
"DEFAULT_ELEMENT_SERIALIZER",
|
32
35
|
)
|
33
36
|
|
34
37
|
|
@@ -173,15 +176,6 @@ class Element(BaseModel, Observable):
|
|
173
176
|
If a `lion_class` field is present in `metadata`, it must match the
|
174
177
|
fully qualified name of this class. Converts `metadata` to a dict
|
175
178
|
if needed.
|
176
|
-
|
177
|
-
Args:
|
178
|
-
val (dict): The initial metadata value.
|
179
|
-
|
180
|
-
Returns:
|
181
|
-
dict: A valid dictionary of metadata.
|
182
|
-
|
183
|
-
Raises:
|
184
|
-
ValueError: If the metadata is invalid or has a class mismatch.
|
185
179
|
"""
|
186
180
|
if not val:
|
187
181
|
return {}
|
@@ -196,7 +190,7 @@ class Element(BaseModel, Observable):
|
|
196
190
|
return val
|
197
191
|
|
198
192
|
@field_validator("created_at", mode="before")
|
199
|
-
def _coerce_created_at(cls, val: float | datetime | None) -> float:
|
193
|
+
def _coerce_created_at(cls, val: float | dt.datetime | None) -> float:
|
200
194
|
"""Coerces `created_at` to a float-based timestamp.
|
201
195
|
|
202
196
|
Args:
|
@@ -212,7 +206,7 @@ class Element(BaseModel, Observable):
|
|
212
206
|
return time(tz=Settings.Config.TIMEZONE, type_="timestamp")
|
213
207
|
if isinstance(val, float):
|
214
208
|
return val
|
215
|
-
if isinstance(val, datetime):
|
209
|
+
if isinstance(val, dt.datetime):
|
216
210
|
return val.timestamp()
|
217
211
|
try:
|
218
212
|
return float(val) # type: ignore
|
@@ -245,33 +239,24 @@ class Element(BaseModel, Observable):
|
|
245
239
|
return str(val)
|
246
240
|
|
247
241
|
@property
|
248
|
-
def created_datetime(self) -> datetime:
|
242
|
+
def created_datetime(self) -> dt.datetime:
|
249
243
|
"""Returns the creation time as a datetime object.
|
250
244
|
|
251
245
|
Returns:
|
252
246
|
datetime: The creation time in UTC.
|
253
247
|
"""
|
254
|
-
return datetime.fromtimestamp(self.created_at)
|
248
|
+
return dt.datetime.fromtimestamp(self.created_at)
|
255
249
|
|
256
250
|
def __eq__(self, other: Any) -> bool:
|
257
|
-
"""Compares two Element instances by their ID.
|
258
|
-
|
259
|
-
Args:
|
260
|
-
other (Any): Another object for comparison.
|
261
|
-
|
262
|
-
Returns:
|
263
|
-
bool: True if both share the same ID, False otherwise.
|
264
|
-
"""
|
251
|
+
"""Compares two Element instances by their ID."""
|
265
252
|
if not isinstance(other, Element):
|
266
|
-
|
253
|
+
raise NotImplementedError(
|
254
|
+
f"Cannot compare Element with {type(other)}"
|
255
|
+
)
|
267
256
|
return self.id == other.id
|
268
257
|
|
269
258
|
def __hash__(self) -> int:
|
270
|
-
"""Returns a hash of this element's ID.
|
271
|
-
|
272
|
-
Returns:
|
273
|
-
int: The hash of the ID, making elements usable as dictionary keys.
|
274
|
-
"""
|
259
|
+
"""Returns a hash of this element's ID."""
|
275
260
|
return hash(self.id)
|
276
261
|
|
277
262
|
def __bool__(self) -> bool:
|
@@ -282,42 +267,28 @@ class Element(BaseModel, Observable):
|
|
282
267
|
def class_name(cls, full: bool = False) -> str:
|
283
268
|
"""Returns this class's name.
|
284
269
|
|
285
|
-
|
286
|
-
|
287
|
-
If True, returns the fully qualified class name; otherwise,
|
288
|
-
returns only the class name.
|
289
|
-
|
290
|
-
Returns:
|
291
|
-
str: The class name or fully qualified name.
|
270
|
+
full (bool): If True, returns the fully qualified class name; otherwise,
|
271
|
+
returns only the class name.
|
292
272
|
"""
|
293
273
|
if full:
|
294
274
|
return str(cls).split("'")[1]
|
295
275
|
return cls.__name__
|
296
276
|
|
297
277
|
def to_dict(self) -> dict:
|
298
|
-
"""Converts this Element to a dictionary.
|
299
|
-
|
300
|
-
All fields are included except those set to `UNDEFINED`.
|
301
|
-
|
302
|
-
Returns:
|
303
|
-
dict: The dictionary representation of this Element.
|
304
|
-
"""
|
278
|
+
"""Converts this Element to a dictionary."""
|
305
279
|
dict_ = self.model_dump()
|
306
280
|
dict_["metadata"].update({"lion_class": self.class_name(full=True)})
|
307
|
-
return {k: v for k, v in dict_.items() if v
|
281
|
+
return {k: v for k, v in dict_.items() if ln.not_sentinel(v)}
|
308
282
|
|
309
283
|
@classmethod
|
310
284
|
def from_dict(cls, data: dict, /) -> Element:
|
311
285
|
"""Deserializes a dictionary into an Element or subclass of Element.
|
312
286
|
|
313
287
|
If `lion_class` in `metadata` refers to a subclass, this method
|
314
|
-
|
288
|
+
is polymorphic, it will attempt to create an instance of that subclass.
|
315
289
|
|
316
290
|
Args:
|
317
291
|
data (dict): A dictionary of field data.
|
318
|
-
|
319
|
-
Returns:
|
320
|
-
Element: An Element or a subclass instance loaded from `data`.
|
321
292
|
"""
|
322
293
|
metadata = data.pop("metadata", {})
|
323
294
|
if "lion_class" in metadata:
|
@@ -350,6 +321,26 @@ class Element(BaseModel, Observable):
|
|
350
321
|
data["metadata"] = metadata
|
351
322
|
return cls.model_validate(data)
|
352
323
|
|
324
|
+
def to_json(self) -> str:
|
325
|
+
"""Converts this Element to a JSON string."""
|
326
|
+
dict_ = self.to_dict()
|
327
|
+
return orjson.dumps(dict_, default=DEFAULT_ELEMENT_SERIALIZER).decode()
|
328
|
+
|
329
|
+
def from_json(cls, json_str: str) -> Element:
|
330
|
+
"""Deserializes a JSON string into an Element or subclass of Element."""
|
331
|
+
data = orjson.loads(json_str)
|
332
|
+
return cls.from_dict(data)
|
333
|
+
|
334
|
+
|
335
|
+
DEFAULT_ELEMENT_SERIALIZER = ln.get_orjson_default(
|
336
|
+
order=[IDType, Element, BaseModel],
|
337
|
+
additional={
|
338
|
+
IDType: lambda o: str(o),
|
339
|
+
Element: lambda o: o.to_dict(),
|
340
|
+
BaseModel: lambda o: o.model_dump(mode="json"),
|
341
|
+
},
|
342
|
+
)
|
343
|
+
|
353
344
|
|
354
345
|
def validate_order(order: Any) -> list[IDType]:
|
355
346
|
"""Validates and flattens an ordering into a list of IDType objects.
|
@@ -2,14 +2,15 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
+
from __future__ import annotations
|
6
|
+
|
5
7
|
import contextlib
|
6
|
-
import json
|
7
8
|
from enum import Enum
|
8
9
|
from typing import Any
|
9
10
|
|
10
11
|
from pydantic import Field, field_serializer
|
11
12
|
|
12
|
-
from lionagi
|
13
|
+
from lionagi import ln
|
13
14
|
from lionagi.utils import to_dict
|
14
15
|
|
15
16
|
from .element import Element
|
@@ -24,7 +25,7 @@ __all__ = (
|
|
24
25
|
_SIMPLE_TYPE = (str, bytes, bytearray, int, float, type(None), Enum)
|
25
26
|
|
26
27
|
|
27
|
-
class EventStatus(str, Enum):
|
28
|
+
class EventStatus(str, ln.Enum):
|
28
29
|
"""Status states for tracking action execution progress.
|
29
30
|
|
30
31
|
Attributes:
|
@@ -95,29 +96,30 @@ class Execution:
|
|
95
96
|
Returns:
|
96
97
|
dict: A dictionary representation of the execution state.
|
97
98
|
"""
|
98
|
-
res_ = Unset
|
99
|
+
res_ = ln.Unset
|
99
100
|
json_serializable = True
|
100
101
|
|
101
102
|
if not isinstance(self.response, _SIMPLE_TYPE):
|
102
103
|
json_serializable = False
|
103
104
|
try:
|
104
105
|
# check whether response is JSON serializable
|
105
|
-
|
106
|
+
ln.json_dumps(self.response)
|
106
107
|
res_ = self.response
|
107
108
|
json_serializable = True
|
108
109
|
except Exception:
|
109
110
|
with contextlib.suppress(Exception):
|
110
|
-
# attempt to convert to dict
|
111
|
+
# attempt to force convert to dict
|
111
112
|
d_ = to_dict(
|
112
113
|
self.response,
|
113
114
|
recursive=True,
|
114
115
|
recursive_python_only=False,
|
116
|
+
use_enum_values=True,
|
115
117
|
)
|
116
|
-
|
118
|
+
ln.json_dumps(d_)
|
117
119
|
res_ = d_
|
118
120
|
json_serializable = True
|
119
121
|
|
120
|
-
if res_ is Unset and not json_serializable:
|
122
|
+
if res_ is ln.Unset and not json_serializable:
|
121
123
|
res_ = "<unserializable>"
|
122
124
|
|
123
125
|
return {
|
@@ -140,93 +142,70 @@ class Event(Element):
|
|
140
142
|
|
141
143
|
@field_serializer("execution")
|
142
144
|
def _serialize_execution(self, val: Execution) -> dict:
|
143
|
-
"""Serializes the Execution object into a dictionary.
|
144
|
-
|
145
|
-
Args:
|
146
|
-
val (Execution): The Execution object to serialize.
|
147
|
-
|
148
|
-
Returns:
|
149
|
-
dict: The serialized data containing status, duration, response,
|
150
|
-
and error fields.
|
151
|
-
"""
|
145
|
+
"""Serializes the Execution object into a dictionary."""
|
152
146
|
return val.to_dict()
|
153
147
|
|
154
148
|
@property
|
155
149
|
def response(self) -> Any:
|
156
|
-
"""Gets or sets the execution response.
|
157
|
-
|
158
|
-
Returns:
|
159
|
-
Any: The current response for this event.
|
160
|
-
"""
|
150
|
+
"""Gets or sets the execution response."""
|
161
151
|
return self.execution.response
|
162
152
|
|
163
153
|
@response.setter
|
164
154
|
def response(self, val: Any) -> None:
|
165
|
-
"""Sets the execution response.
|
166
|
-
|
167
|
-
Args:
|
168
|
-
val (Any): The new response value for this event.
|
169
|
-
"""
|
155
|
+
"""Sets the execution response."""
|
170
156
|
self.execution.response = val
|
171
157
|
|
172
158
|
@property
|
173
159
|
def status(self) -> EventStatus:
|
174
|
-
"""Gets or sets the event status.
|
175
|
-
|
176
|
-
Returns:
|
177
|
-
EventStatus: The current status of this event.
|
178
|
-
"""
|
160
|
+
"""Gets or sets the event status."""
|
179
161
|
return self.execution.status
|
180
162
|
|
181
163
|
@status.setter
|
182
|
-
def status(self, val: EventStatus) -> None:
|
183
|
-
"""Sets the event status.
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
164
|
+
def status(self, val: EventStatus | str) -> None:
|
165
|
+
"""Sets the event status."""
|
166
|
+
if isinstance(val, str):
|
167
|
+
if val not in EventStatus.allowed():
|
168
|
+
raise ValueError(f"Invalid status: {val}")
|
169
|
+
val = EventStatus(val)
|
170
|
+
if isinstance(val, EventStatus):
|
171
|
+
self.execution.status = val
|
172
|
+
else:
|
173
|
+
raise ValueError(
|
174
|
+
f"Invalid status type: {type(val)}. Expected EventStatus or str."
|
175
|
+
)
|
189
176
|
|
190
177
|
@property
|
191
178
|
def request(self) -> dict:
|
192
|
-
"""Gets the request for this event.
|
193
|
-
|
194
|
-
Returns:
|
195
|
-
dict: An empty dictionary by default. Override in subclasses
|
196
|
-
if needed.
|
197
|
-
"""
|
179
|
+
"""Gets the request for this event. Override in subclasses"""
|
198
180
|
return {}
|
199
181
|
|
200
182
|
async def invoke(self) -> None:
|
201
|
-
"""Performs the event action asynchronously.
|
202
|
-
|
203
|
-
Raises:
|
204
|
-
NotImplementedError: This base method must be overridden by
|
205
|
-
subclasses.
|
206
|
-
"""
|
183
|
+
"""Performs the event action asynchronously."""
|
207
184
|
raise NotImplementedError("Override in subclass.")
|
208
185
|
|
209
186
|
async def stream(self) -> None:
|
210
|
-
"""Performs the event action asynchronously, streaming results.
|
211
|
-
|
212
|
-
Raises:
|
213
|
-
NotImplementedError: This base method must be overridden by
|
214
|
-
subclasses.
|
215
|
-
"""
|
187
|
+
"""Performs the event action asynchronously, streaming results."""
|
216
188
|
raise NotImplementedError("Override in subclass.")
|
217
189
|
|
218
190
|
@classmethod
|
219
|
-
def from_dict(cls, data: dict) ->
|
220
|
-
"""Not implemented. Events cannot be fully recreated once done.
|
221
|
-
|
222
|
-
Args:
|
223
|
-
data (dict): Event data (unused).
|
224
|
-
|
225
|
-
Raises:
|
226
|
-
NotImplementedError: Always, because recreating an event is
|
227
|
-
disallowed.
|
228
|
-
"""
|
191
|
+
def from_dict(cls, data: dict) -> Event:
|
192
|
+
"""Not implemented. Events cannot be fully recreated once done."""
|
229
193
|
raise NotImplementedError("Cannot recreate an event once it's done.")
|
230
194
|
|
195
|
+
def as_fresh_event(self, copy_meta: bool = False) -> Event:
|
196
|
+
"""Creates a clone of this event with the same execution state."""
|
197
|
+
d_ = self.to_dict()
|
198
|
+
for i in ["execution", "created_at", "id", "metadata"]:
|
199
|
+
d_.pop(i, None)
|
200
|
+
fresh = self.__class__(**d_)
|
201
|
+
if copy_meta:
|
202
|
+
meta = self.metadata.copy()
|
203
|
+
fresh.metadata = meta
|
204
|
+
fresh.metadata["original"] = {
|
205
|
+
"id": str(self.id),
|
206
|
+
"created_at": self.created_at,
|
207
|
+
}
|
208
|
+
return fresh
|
209
|
+
|
231
210
|
|
232
211
|
# File: lionagi/protocols/generic/event.py
|
@@ -11,6 +11,8 @@ from typing import Any
|
|
11
11
|
from jinja2 import Environment, FileSystemLoader, Template
|
12
12
|
from pydantic import Field, PrivateAttr, field_serializer
|
13
13
|
|
14
|
+
from lionagi import ln
|
15
|
+
|
14
16
|
from .._concepts import Sendable
|
15
17
|
from ..generic.element import Element, IDType
|
16
18
|
from ..generic.log import Log
|
@@ -114,7 +116,7 @@ class RoledMessage(Node, Sendable):
|
|
114
116
|
if isinstance(self.template, Template):
|
115
117
|
return self.template.render(**self.content)
|
116
118
|
except Exception:
|
117
|
-
return
|
119
|
+
return ln.json_dumps(self.content)
|
118
120
|
|
119
121
|
@classmethod
|
120
122
|
def create(cls, **kwargs):
|
@@ -4,11 +4,11 @@
|
|
4
4
|
|
5
5
|
from __future__ import annotations
|
6
6
|
|
7
|
-
import json
|
8
7
|
import warnings
|
9
8
|
|
10
9
|
from pydantic import BaseModel
|
11
10
|
|
11
|
+
from lionagi import ln
|
12
12
|
from lionagi.libs.schema.as_readable import as_readable
|
13
13
|
from lionagi.service.connections.endpoint import Endpoint
|
14
14
|
from lionagi.service.connections.endpoint_config import EndpointConfig
|
@@ -264,12 +264,14 @@ def _verbose_output(res) -> str:
|
|
264
264
|
str_ += f"Claude:\n{text}"
|
265
265
|
|
266
266
|
if isinstance(block, cc_types.ToolUseBlock):
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
267
|
+
inp_ = None
|
268
|
+
|
269
|
+
if isinstance(block.input, dict | list):
|
270
|
+
inp_ = ln.json_dumps(block.input)
|
271
|
+
else:
|
272
|
+
inp_ = str(block.input)
|
273
|
+
|
274
|
+
input = inp_[:200] + "..." if len(inp_) > 200 else inp_
|
273
275
|
str_ += (
|
274
276
|
f"Tool Use: {block.name} - {block.id}\n - Input: {input}"
|
275
277
|
)
|
@@ -22,6 +22,7 @@ from typing import Any, Literal
|
|
22
22
|
from json_repair import repair_json
|
23
23
|
from pydantic import BaseModel, Field, field_validator, model_validator
|
24
24
|
|
25
|
+
from lionagi import ln
|
25
26
|
from lionagi.libs.schema.as_readable import as_readable
|
26
27
|
from lionagi.utils import is_coro_func, is_import_installed
|
27
28
|
|
@@ -238,7 +239,7 @@ class ClaudeCodeRequest(BaseModel):
|
|
238
239
|
continue_conversation = True
|
239
240
|
prompt = messages[-1]["content"]
|
240
241
|
if isinstance(prompt, (dict, list)):
|
241
|
-
prompt =
|
242
|
+
prompt = ln.json_dumps(prompt)
|
242
243
|
|
243
244
|
# 2. else, use entire messages except system message
|
244
245
|
else:
|
@@ -248,7 +249,7 @@ class ClaudeCodeRequest(BaseModel):
|
|
248
249
|
if message["role"] != "system":
|
249
250
|
content = message["content"]
|
250
251
|
prompts.append(
|
251
|
-
|
252
|
+
ln.json_dumps(content)
|
252
253
|
if isinstance(content, (dict, list))
|
253
254
|
else content
|
254
255
|
)
|
lionagi/session/session.py
CHANGED
@@ -7,7 +7,13 @@ from collections.abc import Callable
|
|
7
7
|
from typing import Any
|
8
8
|
|
9
9
|
import pandas as pd
|
10
|
-
from pydantic import
|
10
|
+
from pydantic import (
|
11
|
+
Field,
|
12
|
+
JsonValue,
|
13
|
+
PrivateAttr,
|
14
|
+
field_serializer,
|
15
|
+
model_validator,
|
16
|
+
)
|
11
17
|
from typing_extensions import Self
|
12
18
|
|
13
19
|
from lionagi.protocols.types import (
|
@@ -51,7 +57,7 @@ class Session(Node, Communicatable, Relational):
|
|
51
57
|
default_factory=lambda: Pile(item_type={Branch}, strict_type=False)
|
52
58
|
)
|
53
59
|
default_branch: Any = Field(default=None, exclude=True)
|
54
|
-
mail_transfer: Exchange = Field(default_factory=Exchange)
|
60
|
+
mail_transfer: Exchange = Field(default_factory=Exchange, exclude=True)
|
55
61
|
mail_manager: MailManager = Field(
|
56
62
|
default_factory=MailManager, exclude=True
|
57
63
|
)
|
@@ -61,6 +67,12 @@ class Session(Node, Communicatable, Relational):
|
|
61
67
|
default_factory=OperationManager
|
62
68
|
)
|
63
69
|
|
70
|
+
@field_serializer("user")
|
71
|
+
def _serialize_user(self, value: SenderRecipient | None) -> JsonValue:
|
72
|
+
if value is None:
|
73
|
+
return None
|
74
|
+
return str(value)
|
75
|
+
|
64
76
|
async def ainclude_branches(self, branches: ID[Branch].ItemSeq):
|
65
77
|
async with self.branches:
|
66
78
|
self.include_branches(branches)
|
lionagi/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.15.
|
1
|
+
__version__ = "0.15.9"
|
@@ -6,7 +6,7 @@ lionagi/config.py,sha256=W3JOC_TFad8hFkpTG8yv0-GNupa7x3wX4NAUfWpB59U,3763
|
|
6
6
|
lionagi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
lionagi/settings.py,sha256=HDuKCEJCpc4HudKodBnhoQUGuTGhRHdlIFhbtf3VBtY,1633
|
8
8
|
lionagi/utils.py,sha256=LxsMXyXbj5DC64y7QTmg8XzjE6hogxaed5FHw2PyK_M,39811
|
9
|
-
lionagi/version.py,sha256=
|
9
|
+
lionagi/version.py,sha256=k-GJzgMV-c2ATHbR4wgw0IKwlkANiQ4VvTZ6xMxt9UA,23
|
10
10
|
lionagi/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
lionagi/adapters/_utils.py,sha256=n4DS27CZfC-0O_UFaYtlUdjiMx9IeYsGpP7MVaFO5ZA,885
|
12
12
|
lionagi/adapters/async_postgres_adapter.py,sha256=QKzEnzGR5_HNxxmnHhyuPELHv6yvQ-p7cfaX1bWRAQU,12722
|
@@ -29,7 +29,7 @@ lionagi/libs/file/concat_files.py,sha256=FoI983oWFzp9VfFDP7kmbRb3t1CPe5F5LCtsux0
|
|
29
29
|
lionagi/libs/file/file_ops.py,sha256=HBiIh1EljIJ5VTIXuyvJM0ppSs0YYOPUWmgDMJT634U,3430
|
30
30
|
lionagi/libs/file/params.py,sha256=SZ5DkoffWfxWudOAYCfCxpL8UIm-1UjeyTtploo-Lqs,5824
|
31
31
|
lionagi/libs/file/process.py,sha256=EsnEJcQUm4ReP7qkCeMvL4Qe6fLRcENVWZndh9TSUsc,8692
|
32
|
-
lionagi/libs/file/save.py,sha256=
|
32
|
+
lionagi/libs/file/save.py,sha256=Qy39YWtudJM7AfgPAeiXv06HS8mKjPnfy3WBUWk9O4Q,2854
|
33
33
|
lionagi/libs/nested/__init__.py,sha256=5y5joOZzfFWERl75auAcNcKC3lImVJ5ZZGvvHZUFCJM,112
|
34
34
|
lionagi/libs/nested/flatten.py,sha256=sB4jxZRoaUbjak9RbIWVWNKz2hzkhQJPFffV_Ws1GA0,5479
|
35
35
|
lionagi/libs/nested/nfilter.py,sha256=kF7AWjLFHr22SOjRBSTx-7iRPaR7gs0FY5Y4XF2sWJ8,1768
|
@@ -51,7 +51,7 @@ lionagi/libs/schema/extract_code_block.py,sha256=PuJbJj1JnqR5fSZudowPcVPpEoKISLr
|
|
51
51
|
lionagi/libs/schema/extract_docstring.py,sha256=uWyUevXS4JSN60tfouoBBAyE4_jyE-fz45CiS-fvKeI,5714
|
52
52
|
lionagi/libs/schema/function_to_schema.py,sha256=XAB031WbYu3a7eFJyYjXVMAjmtWYSYr5kC_DYgjiuyM,5604
|
53
53
|
lionagi/libs/schema/json_schema.py,sha256=cuHcaMr748O9g6suNGmRx4tRXcidd5-c7AMGjTIZyHM,7670
|
54
|
-
lionagi/libs/schema/load_pydantic_model_from_schema.py,sha256=
|
54
|
+
lionagi/libs/schema/load_pydantic_model_from_schema.py,sha256=WIgJPmOu558az35CfOHvwyyTYQ5OBlk0hchvaEOADjQ,10109
|
55
55
|
lionagi/libs/token_transform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
56
56
|
lionagi/libs/token_transform/base.py,sha256=LBnaDgi4HNgaJJGwIzWcQjVMdu49i_93rRvOvMU22Rw,1545
|
57
57
|
lionagi/libs/token_transform/llmlingua.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
|
@@ -85,11 +85,12 @@ lionagi/libs/validate/string_similarity.py,sha256=ymuqTKd95_h8ywD9VTzf24gIPyMz1M
|
|
85
85
|
lionagi/libs/validate/to_num.py,sha256=ZRHDjpTCykPfDIZZa4rZKNaR_8ZHbPDFlw9rc02DrII,11610
|
86
86
|
lionagi/libs/validate/validate_boolean.py,sha256=bjiX_WZ3Bg8XcqoWLzE1G9BpO0AisrlZUxrpye_mlGk,3614
|
87
87
|
lionagi/libs/validate/xml_parser.py,sha256=PHBYAre4hhthPpDP9Yrp3UYSWdANPx60F1qhxe0m4uw,7004
|
88
|
-
lionagi/ln/__init__.py,sha256=
|
88
|
+
lionagi/ln/__init__.py,sha256=4W1i0D4nP7d51GCdIAYibdcP-Rwpnz7gqIQ88mu6nho,1132
|
89
89
|
lionagi/ln/_async_call.py,sha256=N8vpXPDyonVqfszVEgOTQS8M1MohYJH9vcf1xwuo4JU,9367
|
90
90
|
lionagi/ln/_hash.py,sha256=g20yJfuVhAsfsBOWlkO889DHte6cbUCl6vV5QMT8nUo,3499
|
91
|
+
lionagi/ln/_json_dump.py,sha256=M4ceccjkU7AN6wd5fUWKFmHytE-EVe8wqoQEFP0OkoA,2026
|
91
92
|
lionagi/ln/_list_call.py,sha256=oDCyTzz7F7KVAMjekKftJp7qgIZ9Yo8BUNMHasKoJhU,3935
|
92
|
-
lionagi/ln/_models.py,sha256=
|
93
|
+
lionagi/ln/_models.py,sha256=Txhdtp2YNq6ZsK9kLza40hRpWu27DzaVNMthCG7-zJM,4786
|
93
94
|
lionagi/ln/_to_list.py,sha256=DKjZAah6pm6frHls773yTMVK1I3OY7qxwLemOjRPr5A,5600
|
94
95
|
lionagi/ln/_types.py,sha256=usVaL2tGnYVQ2W12eUhJYiXY-m55b_5e0tUOFcuDtkc,3607
|
95
96
|
lionagi/ln/concurrency/__init__.py,sha256=Sv1LEvwN1hRESLtuYM5UltyJqx6DRsHvGmr8aof16cA,1286
|
@@ -156,8 +157,8 @@ lionagi/protocols/forms/flow.py,sha256=t9Ycvmb-stj0rCyvXXwd7WBcDtuCCTEKYst2aqFDV
|
|
156
157
|
lionagi/protocols/forms/form.py,sha256=B4903km_Ljz-OxYkb1ZT_cpHZSaAYYJpZMsffWlooo8,3062
|
157
158
|
lionagi/protocols/forms/report.py,sha256=SvJJjOSCTfVuqK7AKaY8ldQIGJeSK2zoyPWUV41ge2c,1609
|
158
159
|
lionagi/protocols/generic/__init__.py,sha256=5y5joOZzfFWERl75auAcNcKC3lImVJ5ZZGvvHZUFCJM,112
|
159
|
-
lionagi/protocols/generic/element.py,sha256=
|
160
|
-
lionagi/protocols/generic/event.py,sha256=
|
160
|
+
lionagi/protocols/generic/element.py,sha256=MKEPaWchiRgwRGvyaGN_NgWcY1WDLa6uwOa3JTUbv7I,14374
|
161
|
+
lionagi/protocols/generic/event.py,sha256=Rwke4sNLddQlJ8PTu-dTPZYBy1qmwaLAERbOLd_udpg,6512
|
161
162
|
lionagi/protocols/generic/log.py,sha256=Y06zAQewkNlaIWjut_c6c45KY_LJfLHwzUaDGLULaas,8212
|
162
163
|
lionagi/protocols/generic/pile.py,sha256=vTBxA40mhhDhoifQm1qQkVF-VuPACVhOt90a4wRHZYk,35461
|
163
164
|
lionagi/protocols/generic/processor.py,sha256=GvHblXvOaZJ485L3bWcV3S4w9x0GYxWH-LkPXv00zMI,11700
|
@@ -179,7 +180,7 @@ lionagi/protocols/messages/assistant_response.py,sha256=jrzRPVHHDnPw86Xp0IHnPy0t
|
|
179
180
|
lionagi/protocols/messages/base.py,sha256=Ng1Q8yIIIFauUv53LnwDeyOrM-cSCfsHM1GwkxChf2o,2317
|
180
181
|
lionagi/protocols/messages/instruction.py,sha256=0dUsUYd6xYsbOHU7GafvqBkpDQQoFOXJXT-UoJArYWU,21146
|
181
182
|
lionagi/protocols/messages/manager.py,sha256=e1jW5JH_3jZpZbFCvWZX0TG0DCgzANRUejW_6NqbtDc,17182
|
182
|
-
lionagi/protocols/messages/message.py,sha256=
|
183
|
+
lionagi/protocols/messages/message.py,sha256=OV9jnRRvhwIib5Sg8Md6XlFk-V7dTvKdLcf1K-l7vZE,7784
|
183
184
|
lionagi/protocols/messages/system.py,sha256=x0F1C57SFHaO2-Z9cy1QshYlxv8wjl7VppooaGKbMIg,4658
|
184
185
|
lionagi/protocols/messages/templates/README.md,sha256=Ch4JrKSjd85fLitAYO1OhZjNOGKHoEwaKQlcV16jiUI,1286
|
185
186
|
lionagi/protocols/messages/templates/action_request.jinja2,sha256=d6OmxHKyvvNDSK4bnBM3TGSUk_HeE_Q2EtLAQ0ZBEJg,120
|
@@ -206,7 +207,7 @@ lionagi/service/connections/header_factory.py,sha256=IYeTQQk7r8FXcdhmW7orCxHjNO-
|
|
206
207
|
lionagi/service/connections/match_endpoint.py,sha256=kHAs6FmWJWjIn4CO7FwZVi8w1lYcvu2vGSf9ww2sCG4,2470
|
207
208
|
lionagi/service/connections/providers/__init__.py,sha256=3lzOakDoBWmMaNnT2g-YwktPKa_Wme4lnPRSmOQfayY,105
|
208
209
|
lionagi/service/connections/providers/anthropic_.py,sha256=vok8mIyFiuV3K83tOjdYfruA6cv1h_57ML6RtpuW-bU,3157
|
209
|
-
lionagi/service/connections/providers/claude_code_.py,sha256=
|
210
|
+
lionagi/service/connections/providers/claude_code_.py,sha256=dix4VoR2YwRabJ0F8I3mV8sVtRQEquExqP6mfbE_rGk,10435
|
210
211
|
lionagi/service/connections/providers/claude_code_cli.py,sha256=kqEOnCUOOh2O_3NGi6W7r-gdLsbW-Jcp11tm30VEv4Q,4455
|
211
212
|
lionagi/service/connections/providers/exa_.py,sha256=kuWD7yyYRqIa4ChSn0TsxFA5V5LwvFUD-w8TZ6mx4rk,1048
|
212
213
|
lionagi/service/connections/providers/oai_.py,sha256=3x5d6Ei1hKu8Mix0N2V2K21O9dd-2jtAELHhHXj5iHk,6071
|
@@ -221,21 +222,21 @@ lionagi/service/hooks/hook_registry.py,sha256=JNpbn_Vl4oACVt0inYxunLlRftVUpjD-8N
|
|
221
222
|
lionagi/service/third_party/README.md,sha256=qFjWnI8rmLivIyr6Tc-hRZh-rQwntROp76af4MBNJJc,2214
|
222
223
|
lionagi/service/third_party/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
223
224
|
lionagi/service/third_party/anthropic_models.py,sha256=oqSPSlcayYG-fS5BLiLeTtkrpaxgkPhEK_YgneumrOo,4004
|
224
|
-
lionagi/service/third_party/claude_code.py,sha256=
|
225
|
+
lionagi/service/third_party/claude_code.py,sha256=wRqNBSy4kc-pHkuntNJnstyqOVdSKK9NV1s2x3Ia704,24794
|
225
226
|
lionagi/service/third_party/exa_models.py,sha256=G_hnekcy-DillPLzMoDQ8ZisVAL8Mp7iMAK4xqAT_3w,5470
|
226
227
|
lionagi/service/third_party/openai_model_names.py,sha256=C44tnqexgc4ZU2-3I_sn5d688hf3WWx-25xBd50bvas,5121
|
227
228
|
lionagi/service/third_party/pplx_models.py,sha256=-EhyJgOWR6rzSv3zczUtk80X6c19p18Dg9KC6l8BFRQ,6473
|
228
229
|
lionagi/session/__init__.py,sha256=kDypY6L3kGPnatAw7YNQAykgg-9MlIBnlhHExaXvt-c,202
|
229
230
|
lionagi/session/branch.py,sha256=79l014dCsyOdI4daBLOzyTTLnfYv89Bg7uf9qcg_Bwg,68449
|
230
231
|
lionagi/session/prompts.py,sha256=GPr0jibyAAqS3awDzGC8SoCL6aWJLLCCbXY0JUuxOC0,3170
|
231
|
-
lionagi/session/session.py,sha256=
|
232
|
+
lionagi/session/session.py,sha256=PN9tIFA7H9fMtEbwhWoTNgFoqNQ1r6TEXTABI5bc548,13580
|
232
233
|
lionagi/tools/__init__.py,sha256=5y5joOZzfFWERl75auAcNcKC3lImVJ5ZZGvvHZUFCJM,112
|
233
234
|
lionagi/tools/base.py,sha256=hEGnE4MD0CM4UqnF0xsDRKB0aM-pyrTFHl8utHhyJLU,1897
|
234
235
|
lionagi/tools/types.py,sha256=XtJLY0m-Yi_ZLWhm0KycayvqMCZd--HxfQ0x9vFUYDE,230
|
235
236
|
lionagi/tools/file/__init__.py,sha256=5y5joOZzfFWERl75auAcNcKC3lImVJ5ZZGvvHZUFCJM,112
|
236
237
|
lionagi/tools/file/reader.py,sha256=jnSHVSQ66AHZXQrgRuGmlbwKT5JHYoo-1zv1hKgTEfc,9544
|
237
238
|
lionagi/tools/memory/tools.py,sha256=earYkKxSOz_iXkqVZYTEDfE3dwZYIWPXZrqQ1DYGz4I,15941
|
238
|
-
lionagi-0.15.
|
239
|
-
lionagi-0.15.
|
240
|
-
lionagi-0.15.
|
241
|
-
lionagi-0.15.
|
239
|
+
lionagi-0.15.9.dist-info/METADATA,sha256=8zWmhVz7G1nNINa9D6-eG0vqCsMq3Rfj4z39DDH_bv4,22895
|
240
|
+
lionagi-0.15.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
241
|
+
lionagi-0.15.9.dist-info/licenses/LICENSE,sha256=VXFWsdoN5AAknBCgFqQNgPWYx7OPp-PFEP961zGdOjc,11288
|
242
|
+
lionagi-0.15.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|