lionagi 0.13.2__py3-none-any.whl → 0.13.4__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 (50) hide show
  1. lionagi/config.py +1 -1
  2. lionagi/fields/action.py +0 -1
  3. lionagi/fields/reason.py +0 -1
  4. lionagi/libs/file/save.py +1 -1
  5. lionagi/libs/schema/as_readable.py +142 -196
  6. lionagi/libs/schema/extract_docstring.py +1 -2
  7. lionagi/libs/token_transform/synthlang_/base.py +0 -2
  8. lionagi/libs/validate/string_similarity.py +1 -2
  9. lionagi/models/hashable_model.py +0 -1
  10. lionagi/models/schema_model.py +0 -1
  11. lionagi/operations/ReAct/utils.py +0 -1
  12. lionagi/operations/__init__.py +2 -0
  13. lionagi/operations/_act/act.py +0 -1
  14. lionagi/operations/flow.py +436 -0
  15. lionagi/operations/interpret/interpret.py +1 -4
  16. lionagi/operations/manager.py +0 -1
  17. lionagi/operations/node.py +107 -0
  18. lionagi/operations/plan/plan.py +0 -1
  19. lionagi/operations/select/utils.py +0 -2
  20. lionagi/protocols/forms/flow.py +3 -1
  21. lionagi/protocols/generic/pile.py +1 -2
  22. lionagi/protocols/generic/processor.py +0 -1
  23. lionagi/protocols/graph/__init__.py +6 -0
  24. lionagi/protocols/graph/graph.py +1 -3
  25. lionagi/protocols/mail/package.py +0 -1
  26. lionagi/protocols/messages/assistant_response.py +0 -2
  27. lionagi/protocols/messages/message.py +0 -1
  28. lionagi/service/connections/endpoint_config.py +6 -0
  29. lionagi/service/connections/match_endpoint.py +26 -8
  30. lionagi/service/connections/providers/claude_code_.py +8 -9
  31. lionagi/service/connections/providers/claude_code_cli.py +411 -0
  32. lionagi/service/connections/providers/oai_.py +1 -1
  33. lionagi/service/manager.py +0 -1
  34. lionagi/service/rate_limited_processor.py +0 -2
  35. lionagi/service/token_calculator.py +0 -3
  36. lionagi/session/__init__.py +5 -0
  37. lionagi/session/branch.py +0 -2
  38. lionagi/session/session.py +47 -1
  39. lionagi/settings.py +2 -3
  40. lionagi/utils.py +6 -9
  41. lionagi/version.py +1 -1
  42. {lionagi-0.13.2.dist-info → lionagi-0.13.4.dist-info}/METADATA +15 -10
  43. {lionagi-0.13.2.dist-info → lionagi-0.13.4.dist-info}/RECORD +45 -47
  44. lionagi/traits/__init__.py +0 -58
  45. lionagi/traits/base.py +0 -216
  46. lionagi/traits/composer.py +0 -343
  47. lionagi/traits/protocols.py +0 -495
  48. lionagi/traits/registry.py +0 -1071
  49. {lionagi-0.13.2.dist-info → lionagi-0.13.4.dist-info}/WHEEL +0 -0
  50. {lionagi-0.13.2.dist-info → lionagi-0.13.4.dist-info}/licenses/LICENSE +0 -0
lionagi/config.py CHANGED
@@ -68,7 +68,7 @@ class AppSettings(BaseSettings, frozen=True):
68
68
  LIONAGI_EMBEDDING_MODEL: str = "text-embedding-3-small"
69
69
 
70
70
  LIONAGI_CHAT_PROVIDER: str = "openai"
71
- LIONAGI_CHAT_MODEL: str = "gpt-4o"
71
+ LIONAGI_CHAT_MODEL: str = "gpt-4.1-nano"
72
72
 
73
73
  # default storage
74
74
  LIONAGI_AUTO_STORE_EVENT: bool = False
lionagi/fields/action.py CHANGED
@@ -21,7 +21,6 @@ __all__ = (
21
21
 
22
22
 
23
23
  def parse_action_request(content: str | dict) -> list[dict]:
24
-
25
24
  json_blocks = []
26
25
 
27
26
  if isinstance(content, BaseModel):
lionagi/fields/reason.py CHANGED
@@ -11,7 +11,6 @@ __all__ = ("Reason",)
11
11
 
12
12
 
13
13
  class Reason(HashableModel):
14
-
15
14
  title: str | None = None
16
15
  content: str | None = None
17
16
  confidence_score: float | None = Field(
lionagi/libs/file/save.py CHANGED
@@ -82,7 +82,7 @@ def save_chunks(
82
82
  for i, chunk in enumerate(chunks):
83
83
  file_path = create_path(
84
84
  directory=output_path,
85
- filename=f"chunk_{i+1}",
85
+ filename=f"chunk_{i + 1}",
86
86
  extension="json",
87
87
  timestamp=timestamp,
88
88
  random_hash_digits=random_hash_digits,
@@ -11,81 +11,84 @@ from lionagi.utils import to_dict
11
11
  # Try to import rich for enhanced console output
12
12
  try:
13
13
  from rich.align import Align
14
- from rich.box import ROUNDED
14
+ from rich.box import MINIMAL, ROUNDED
15
15
  from rich.console import Console
16
+ from rich.markdown import Markdown
16
17
  from rich.padding import Padding
17
18
  from rich.panel import Panel
19
+ from rich.style import Style
18
20
  from rich.syntax import Syntax
21
+ from rich.text import Text
19
22
  from rich.theme import Theme
20
23
 
24
+ DARK_THEME = Theme(
25
+ {
26
+ "info": "bright_cyan",
27
+ "warning": "bright_yellow",
28
+ "error": "bold bright_red",
29
+ "success": "bold bright_green",
30
+ "panel.border": "bright_blue",
31
+ "panel.title": "bold bright_cyan",
32
+ "markdown.h1": "bold bright_magenta",
33
+ "markdown.h2": "bold bright_blue",
34
+ "markdown.h3": "bold bright_cyan",
35
+ "markdown.h4": "bold bright_green",
36
+ "markdown.code": "bright_yellow on grey23",
37
+ "markdown.code_block": "bright_white on grey15",
38
+ "markdown.paragraph": "bright_white",
39
+ "markdown.text": "bright_white",
40
+ "markdown.emph": "italic bright_yellow",
41
+ "markdown.strong": "bold bright_white",
42
+ "markdown.item": "bright_cyan",
43
+ "markdown.item.bullet": "bright_blue",
44
+ "json.key": "bright_cyan",
45
+ "json.string": "bright_green",
46
+ "json.number": "bright_yellow",
47
+ "json.boolean": "bright_magenta",
48
+ "json.null": "bright_red",
49
+ "yaml.key": "bright_cyan",
50
+ "yaml.string": "bright_green",
51
+ "yaml.number": "bright_yellow",
52
+ "yaml.boolean": "bright_magenta",
53
+ }
54
+ )
55
+
56
+ LIGHT_THEME = Theme(
57
+ {
58
+ "info": "blue",
59
+ "warning": "dark_orange",
60
+ "error": "bold red",
61
+ "success": "bold green4",
62
+ "panel.border": "blue",
63
+ "panel.title": "bold blue",
64
+ "markdown.h1": "bold dark_magenta",
65
+ "markdown.h2": "bold dark_blue",
66
+ "markdown.h3": "bold dark_cyan",
67
+ "markdown.h4": "bold dark_green",
68
+ "markdown.code": "dark_orange on grey93",
69
+ "markdown.code_block": "black on grey82",
70
+ "markdown.paragraph": "black",
71
+ "markdown.text": "black",
72
+ "markdown.emph": "italic dark_orange",
73
+ "markdown.strong": "bold black",
74
+ "markdown.item": "dark_blue",
75
+ "markdown.item.bullet": "blue",
76
+ "json.key": "dark_blue",
77
+ "json.string": "dark_green",
78
+ "json.number": "dark_orange",
79
+ "json.boolean": "dark_magenta",
80
+ "json.null": "dark_red",
81
+ "yaml.key": "dark_blue",
82
+ "yaml.string": "dark_green",
83
+ "yaml.number": "dark_orange",
84
+ "yaml.boolean": "dark_magenta",
85
+ }
86
+ )
21
87
  RICH_AVAILABLE = True
22
88
  except ImportError:
23
89
  RICH_AVAILABLE = False
24
-
25
- # Custom themes for dark and light modes
26
- DARK_THEME = Theme(
27
- {
28
- "info": "bright_cyan",
29
- "warning": "bright_yellow",
30
- "error": "bold bright_red",
31
- "success": "bold bright_green",
32
- "panel.border": "bright_blue",
33
- "panel.title": "bold bright_cyan",
34
- "markdown.h1": "bold bright_magenta",
35
- "markdown.h2": "bold bright_blue",
36
- "markdown.h3": "bold bright_cyan",
37
- "markdown.h4": "bold bright_green",
38
- "markdown.code": "bright_yellow on grey23",
39
- "markdown.code_block": "bright_white on grey15",
40
- "markdown.paragraph": "bright_white",
41
- "markdown.text": "bright_white",
42
- "markdown.emph": "italic bright_yellow",
43
- "markdown.strong": "bold bright_white",
44
- "markdown.item": "bright_cyan",
45
- "markdown.item.bullet": "bright_blue",
46
- "json.key": "bright_cyan",
47
- "json.string": "bright_green",
48
- "json.number": "bright_yellow",
49
- "json.boolean": "bright_magenta",
50
- "json.null": "bright_red",
51
- "yaml.key": "bright_cyan",
52
- "yaml.string": "bright_green",
53
- "yaml.number": "bright_yellow",
54
- "yaml.boolean": "bright_magenta",
55
- }
56
- )
57
-
58
- LIGHT_THEME = Theme(
59
- {
60
- "info": "blue",
61
- "warning": "dark_orange",
62
- "error": "bold red",
63
- "success": "bold green4",
64
- "panel.border": "blue",
65
- "panel.title": "bold blue",
66
- "markdown.h1": "bold dark_magenta",
67
- "markdown.h2": "bold dark_blue",
68
- "markdown.h3": "bold dark_cyan",
69
- "markdown.h4": "bold dark_green",
70
- "markdown.code": "dark_orange on grey93",
71
- "markdown.code_block": "black on grey82",
72
- "markdown.paragraph": "black",
73
- "markdown.text": "black",
74
- "markdown.emph": "italic dark_orange",
75
- "markdown.strong": "bold black",
76
- "markdown.item": "dark_blue",
77
- "markdown.item.bullet": "blue",
78
- "json.key": "dark_blue",
79
- "json.string": "dark_green",
80
- "json.number": "dark_orange",
81
- "json.boolean": "dark_magenta",
82
- "json.null": "dark_red",
83
- "yaml.key": "dark_blue",
84
- "yaml.string": "dark_green",
85
- "yaml.number": "dark_orange",
86
- "yaml.boolean": "dark_magenta",
87
- }
88
- )
90
+ DARK_THEME = None
91
+ LIGHT_THEME = None
89
92
 
90
93
 
91
94
  def in_notebook() -> bool:
@@ -172,6 +175,8 @@ def as_readable(
172
175
  use_rich: bool = True,
173
176
  theme: str = "dark",
174
177
  max_panel_width: int = 140,
178
+ panel: bool = True,
179
+ border: bool = True,
175
180
  ) -> str:
176
181
  """
177
182
  Convert `input_` into a human-readable string. If `format_curly=True`, uses
@@ -191,6 +196,7 @@ def as_readable(
191
196
  theme: Color theme - "dark" (default) or "light". Dark uses GitHub Dark Dimmed,
192
197
  light uses Solarized Light inspired colors.
193
198
  max_panel_width: Maximum width for panels and code blocks in characters.
199
+ panel: If True, wraps the output in a panel for better visibility.
194
200
 
195
201
  Returns:
196
202
  A formatted string representation of `input_` (unless display_str=True).
@@ -249,7 +255,6 @@ def as_readable(
249
255
  final_str = "\n\n".join(rendered).strip()
250
256
 
251
257
  # 4) If Markdown requested, wrap with code fences
252
- # - If we used format_curly, we might do "```yaml" instead. But user specifically asked for JSON code blocks previously
253
258
  if md:
254
259
  if format_curly:
255
260
  return f"```yaml\n{final_str}\n```"
@@ -260,137 +265,78 @@ def as_readable(
260
265
 
261
266
  str_ = _inner(input_).strip()
262
267
  if max_chars is not None and len(str_) > max_chars:
263
- str1 = str_[:max_chars] + "...\n\n[Truncated output]\n\n"
264
- if str_.endswith("\n```"):
265
- str1 += "```"
266
- str_ = str1
267
- if display_str:
268
- if md and in_notebook():
269
- # If in IPython environment, display Markdown
270
- from IPython.display import Markdown, display
271
-
272
- display(Markdown(str_))
273
- elif RICH_AVAILABLE and in_console() and use_rich:
274
- # Use rich for enhanced console output
275
- # Select theme and syntax highlighting based on user preference
276
- console_theme = DARK_THEME if theme == "dark" else LIGHT_THEME
277
- syntax_theme = (
278
- "github-dark" if theme == "dark" else "solarized-light"
279
- )
280
- panel_style = "bright_blue" if theme == "dark" else "blue"
281
-
282
- console = Console(theme=console_theme)
283
-
284
- # Check if content looks like markdown prose (not code)
285
- is_markdown_prose = isinstance(str_, str) and (
286
- str_.startswith("#")
287
- or str_.startswith("**")
288
- or str_.startswith("- ")
289
- or str_.startswith("1.")
290
- or "<multi_reasoning>" in str_
291
- or "\n### " in str_
292
- or "\n## " in str_
293
- or "\n# " in str_
294
- or "│" in str_ # Rich table content
295
- )
296
-
297
- if md and is_markdown_prose:
298
- # Display as formatted markdown
299
- # Create markdown with max width
300
- from rich.markdown import Markdown as RichMarkdown
301
-
302
- md_content = RichMarkdown(str_, code_theme=syntax_theme)
303
-
304
- # Calculate appropriate width
305
- console_width = console.width
306
- panel_width = min(console_width - 4, max_panel_width)
307
-
308
- # Add left margin padding for better alignment
309
- panel = Panel(
310
- Padding(md_content, (0, 2)),
311
- border_style=panel_style,
312
- box=ROUNDED,
313
- width=panel_width,
314
- expand=False,
315
- )
316
-
317
- # Left align with margin
318
- aligned_panel = Align.left(panel, pad=True)
319
- console.print(Padding(aligned_panel, (0, 0, 0, 4)))
320
-
321
- elif md:
322
- # Extract content from markdown code blocks if present
323
- content = str_
324
- if content.startswith("```") and content.endswith("```"):
325
- # Remove code fences
326
- lines = content.split("\n")
327
- if len(lines) > 2:
328
- lang = lines[0][3:].strip() or "json"
329
- content = "\n".join(lines[1:-1])
330
- else:
331
- lang = "json"
332
- else:
333
- lang = "yaml" if format_curly else "json"
334
-
335
- # Calculate appropriate width
336
- console_width = console.width
337
- panel_width = min(console_width - 4, max_panel_width)
338
-
339
- # Create syntax highlighted output
340
- syntax = Syntax(
341
- content,
342
- lang,
343
- theme=syntax_theme,
344
- line_numbers=True,
345
- background_color="default",
346
- word_wrap=True,
268
+ trunc = str_[:max_chars] + "...\n\n[Truncated output]"
269
+ str_ = trunc + ("\n```" if str_.endswith("\n```") else "")
270
+
271
+ # -------------------- PRINT / DISPLAY LOGIC ---------------------------
272
+ if not display_str:
273
+ return str_ # caller will handle printing
274
+
275
+ # (1) IPython notebook --------------------------------------------------
276
+ if md and in_notebook():
277
+ from IPython.display import Markdown, display
278
+
279
+ display(Markdown(str_))
280
+ return
281
+
282
+ # (2) Rich console ------------------------------------------------------
283
+ if RICH_AVAILABLE and in_console() and use_rich:
284
+ console_theme = DARK_THEME if theme == "dark" else LIGHT_THEME
285
+ syntax_theme = "github-dark" if theme == "dark" else "solarized-light"
286
+ console = Console(theme=console_theme)
287
+
288
+ # determine prose / fenced code
289
+ is_fenced_code = (
290
+ md and str_.startswith("```") and str_.rstrip().endswith("```")
291
+ )
292
+ is_prose_md = md and not is_fenced_code
293
+ panel_width = min(console.width - 4, max_panel_width)
294
+
295
+ def _out(rich_obj):
296
+ if not panel:
297
+ console.print(Padding(rich_obj, (0, 0, 0, 2)))
298
+ return
299
+
300
+ console.print(
301
+ Padding(
302
+ Panel(
303
+ Align.left(rich_obj, pad=False),
304
+ border_style="panel.border" if border else "",
305
+ box=ROUNDED if border else MINIMAL,
306
+ width=panel_width,
307
+ expand=False,
308
+ ),
309
+ (0, 0, 0, 4),
347
310
  )
311
+ )
348
312
 
349
- # Add left margin padding for better alignment
350
- panel = Panel(
351
- syntax,
352
- border_style=panel_style,
353
- box=ROUNDED,
354
- width=panel_width,
355
- expand=False,
356
- )
313
+ # 2‑a prose markdown ------------------------------------------------
314
+ if is_prose_md:
315
+ from rich.markdown import Markdown as RichMarkdown
357
316
 
358
- # Left align with margin
359
- aligned_panel = Align.left(panel, pad=True)
360
- console.print(Padding(aligned_panel, (0, 0, 0, 4)))
317
+ _out(RichMarkdown(str_, code_theme=syntax_theme))
318
+ return
361
319
 
362
- else:
363
- # Plain text output with rich formatting
364
- if format_curly:
365
- syntax = Syntax(
366
- str_,
367
- "yaml",
368
- theme=syntax_theme,
369
- background_color="default",
370
- word_wrap=True,
371
- )
372
- else:
373
- syntax = Syntax(
374
- str_,
375
- "json",
376
- theme=syntax_theme,
377
- background_color="default",
378
- word_wrap=True,
379
- )
380
-
381
- # For plain syntax, add left margin
382
- # Create a constrained width container if console is too wide
383
- if console.width > max_panel_width:
384
- content = Align.left(
385
- syntax, width=max_panel_width, pad=False
386
- )
387
- # Add left margin
388
- console.print(Padding(content, (0, 0, 0, 4)))
389
- else:
390
- # Just add left margin
391
- console.print(Padding(syntax, (0, 0, 0, 4)))
320
+ # 2‑b code (fenced or explicit) -------------------------------------
321
+ if is_fenced_code:
322
+ lines = str_.splitlines()
323
+ lang, code = (
324
+ (lines[0][3:].strip() or ("yaml" if format_curly else "json")),
325
+ "\n".join(lines[1:-1]),
326
+ )
392
327
  else:
393
- # Fallback to regular print
394
- print(str_)
395
- else:
396
- return str_
328
+ lang, code = ("yaml" if format_curly else "json"), str_
329
+
330
+ syntax = Syntax(
331
+ code,
332
+ lang,
333
+ theme=syntax_theme,
334
+ line_numbers=False,
335
+ word_wrap=True,
336
+ background_color="default",
337
+ )
338
+ _out(syntax)
339
+ return
340
+
341
+ # (3) Plain fallback ----------------------------------------------------
342
+ print(str_)
@@ -52,8 +52,7 @@ def extract_docstring(
52
52
  )
53
53
  else:
54
54
  raise ValueError(
55
- f'{style} is not supported. Please choose either "google" or'
56
- ' "reST".'
55
+ f'{style} is not supported. Please choose either "google" or "reST".'
57
56
  )
58
57
  return func_description, params_description
59
58
 
@@ -21,7 +21,6 @@ __all__ = (
21
21
 
22
22
 
23
23
  class SynthlangFramework(Resource):
24
-
25
24
  category: ResourceCategory = Field(
26
25
  default=ResourceCategory.FRAMEWORK, frozen=True
27
26
  )
@@ -72,7 +71,6 @@ class SynthlangFramework(Resource):
72
71
  framework_options: list[FRAMEWORK_CHOICES] = None,
73
72
  additional_text: str = "",
74
73
  ) -> str:
75
-
76
74
  framework_options_text = self.build_framework_text(framework_options)
77
75
  base_prompt = self.load_base_system_prompt()
78
76
  template_details = (
@@ -297,8 +297,7 @@ def string_similarity(
297
297
  score_func = algorithm
298
298
  else:
299
299
  raise ValueError(
300
- "algorithm must be a string specifying a built-in algorithm or "
301
- "a callable"
300
+ "algorithm must be a string specifying a built-in algorithm or a callable"
302
301
  )
303
302
 
304
303
  # Calculate similarities
@@ -5,7 +5,6 @@ from lionagi.utils import UNDEFINED, hash_dict
5
5
 
6
6
 
7
7
  class HashableModel(BaseModel):
8
-
9
8
  def to_dict(self, **kwargs) -> dict:
10
9
  """provides interface, specific methods need to be implemented in subclass kwargs for pydantic model_dump"""
11
10
  return {
@@ -10,7 +10,6 @@ __all__ = ("SchemaModel",)
10
10
 
11
11
 
12
12
  class SchemaModel(HashableModel):
13
-
14
13
  model_config = ConfigDict(
15
14
  extra="forbid",
16
15
  validate_default=False,
@@ -113,7 +113,6 @@ class ReActAnalysis(HashableModel):
113
113
 
114
114
 
115
115
  class Analysis(HashableModel):
116
-
117
116
  answer: str | None = None
118
117
 
119
118
  @field_validator("answer", mode="before")
@@ -2,4 +2,6 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
+ from .flow import flow
6
+ from .node import BranchOperations, Operation
5
7
  from .types import *
@@ -20,7 +20,6 @@ async def _act(
20
20
  suppress_errors: bool = False,
21
21
  verbose_action: bool = False,
22
22
  ) -> "ActionResponseModel":
23
-
24
23
  _request = {}
25
24
 
26
25
  if isinstance(action_request, BaseModel):