lionherd-core 1.0.0a3__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 (64) hide show
  1. lionherd_core/__init__.py +84 -0
  2. lionherd_core/base/__init__.py +30 -0
  3. lionherd_core/base/_utils.py +295 -0
  4. lionherd_core/base/broadcaster.py +128 -0
  5. lionherd_core/base/element.py +300 -0
  6. lionherd_core/base/event.py +322 -0
  7. lionherd_core/base/eventbus.py +112 -0
  8. lionherd_core/base/flow.py +236 -0
  9. lionherd_core/base/graph.py +616 -0
  10. lionherd_core/base/node.py +212 -0
  11. lionherd_core/base/pile.py +811 -0
  12. lionherd_core/base/progression.py +261 -0
  13. lionherd_core/errors.py +104 -0
  14. lionherd_core/libs/__init__.py +2 -0
  15. lionherd_core/libs/concurrency/__init__.py +60 -0
  16. lionherd_core/libs/concurrency/_cancel.py +85 -0
  17. lionherd_core/libs/concurrency/_errors.py +80 -0
  18. lionherd_core/libs/concurrency/_patterns.py +238 -0
  19. lionherd_core/libs/concurrency/_primitives.py +253 -0
  20. lionherd_core/libs/concurrency/_priority_queue.py +135 -0
  21. lionherd_core/libs/concurrency/_resource_tracker.py +66 -0
  22. lionherd_core/libs/concurrency/_task.py +58 -0
  23. lionherd_core/libs/concurrency/_utils.py +61 -0
  24. lionherd_core/libs/schema_handlers/__init__.py +35 -0
  25. lionherd_core/libs/schema_handlers/_function_call_parser.py +122 -0
  26. lionherd_core/libs/schema_handlers/_minimal_yaml.py +88 -0
  27. lionherd_core/libs/schema_handlers/_schema_to_model.py +251 -0
  28. lionherd_core/libs/schema_handlers/_typescript.py +153 -0
  29. lionherd_core/libs/string_handlers/__init__.py +15 -0
  30. lionherd_core/libs/string_handlers/_extract_json.py +65 -0
  31. lionherd_core/libs/string_handlers/_fuzzy_json.py +103 -0
  32. lionherd_core/libs/string_handlers/_string_similarity.py +347 -0
  33. lionherd_core/libs/string_handlers/_to_num.py +63 -0
  34. lionherd_core/ln/__init__.py +45 -0
  35. lionherd_core/ln/_async_call.py +314 -0
  36. lionherd_core/ln/_fuzzy_match.py +166 -0
  37. lionherd_core/ln/_fuzzy_validate.py +151 -0
  38. lionherd_core/ln/_hash.py +141 -0
  39. lionherd_core/ln/_json_dump.py +347 -0
  40. lionherd_core/ln/_list_call.py +110 -0
  41. lionherd_core/ln/_to_dict.py +373 -0
  42. lionherd_core/ln/_to_list.py +190 -0
  43. lionherd_core/ln/_utils.py +156 -0
  44. lionherd_core/lndl/__init__.py +62 -0
  45. lionherd_core/lndl/errors.py +30 -0
  46. lionherd_core/lndl/fuzzy.py +321 -0
  47. lionherd_core/lndl/parser.py +427 -0
  48. lionherd_core/lndl/prompt.py +137 -0
  49. lionherd_core/lndl/resolver.py +323 -0
  50. lionherd_core/lndl/types.py +287 -0
  51. lionherd_core/protocols.py +181 -0
  52. lionherd_core/py.typed +0 -0
  53. lionherd_core/types/__init__.py +46 -0
  54. lionherd_core/types/_sentinel.py +131 -0
  55. lionherd_core/types/base.py +341 -0
  56. lionherd_core/types/operable.py +133 -0
  57. lionherd_core/types/spec.py +313 -0
  58. lionherd_core/types/spec_adapters/__init__.py +10 -0
  59. lionherd_core/types/spec_adapters/_protocol.py +125 -0
  60. lionherd_core/types/spec_adapters/pydantic_field.py +177 -0
  61. lionherd_core-1.0.0a3.dist-info/METADATA +502 -0
  62. lionherd_core-1.0.0a3.dist-info/RECORD +64 -0
  63. lionherd_core-1.0.0a3.dist-info/WHEEL +4 -0
  64. lionherd_core-1.0.0a3.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,177 @@
1
+ # Copyright (c) 2025, HaiyangLi <quantocean.li at gmail dot com>
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ import functools
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from .._sentinel import Unset, is_sentinel
8
+ from ._protocol import SpecAdapter
9
+
10
+ if TYPE_CHECKING:
11
+ from pydantic import BaseModel
12
+ from pydantic.fields import FieldInfo
13
+
14
+ from ..operable import Operable
15
+ from ..spec import Spec
16
+
17
+
18
+ @functools.lru_cache(maxsize=1)
19
+ def _get_pydantic_field_params() -> set[str]:
20
+ """Get valid Pydantic Field params (cached)."""
21
+ import inspect
22
+
23
+ from pydantic import Field as PydanticField
24
+
25
+ params = set(inspect.signature(PydanticField).parameters.keys())
26
+ params.discard("kwargs")
27
+ return params
28
+
29
+
30
+ class PydanticSpecAdapter(SpecAdapter["BaseModel"]):
31
+ """Pydantic adapter: Spec → FieldInfo → BaseModel."""
32
+
33
+ @classmethod
34
+ def create_field(cls, spec: "Spec") -> "FieldInfo":
35
+ """Create Pydantic FieldInfo from Spec."""
36
+ from pydantic import Field as PydanticField
37
+
38
+ # Get valid Pydantic Field parameters (cached)
39
+ pydantic_field_params = _get_pydantic_field_params()
40
+
41
+ # Extract metadata for FieldInfo
42
+ field_kwargs = {}
43
+
44
+ if not is_sentinel(spec.metadata, none_as_sentinel=True):
45
+ for meta in spec.metadata:
46
+ if meta.key == "default":
47
+ # Handle callable defaults as default_factory
48
+ if callable(meta.value):
49
+ field_kwargs["default_factory"] = meta.value
50
+ else:
51
+ field_kwargs["default"] = meta.value
52
+ elif meta.key == "validator":
53
+ # Validators are handled separately in create_model
54
+ continue
55
+ elif meta.key in pydantic_field_params:
56
+ # Pass through standard Pydantic field attributes
57
+ field_kwargs[meta.key] = meta.value
58
+ elif meta.key in {"nullable", "listable"}:
59
+ # These are FieldTemplate markers, don't pass to FieldInfo
60
+ pass
61
+ else:
62
+ # Filter out unserializable objects from json_schema_extra
63
+ if isinstance(meta.value, type):
64
+ # Skip type objects - can't be serialized
65
+ continue
66
+
67
+ # Any other metadata goes in json_schema_extra
68
+ if "json_schema_extra" not in field_kwargs:
69
+ field_kwargs["json_schema_extra"] = {}
70
+ field_kwargs["json_schema_extra"][meta.key] = meta.value
71
+
72
+ # Handle nullable case - ensure default is set if not already
73
+ if (
74
+ spec.is_nullable
75
+ and "default" not in field_kwargs
76
+ and "default_factory" not in field_kwargs
77
+ ):
78
+ field_kwargs["default"] = None
79
+
80
+ field_info = PydanticField(**field_kwargs)
81
+ field_info.annotation = spec.annotation
82
+
83
+ return field_info
84
+
85
+ @classmethod
86
+ def create_validator(cls, spec: "Spec") -> dict[str, Any] | None:
87
+ """Create Pydantic field_validator from Spec metadata."""
88
+ from .._sentinel import Undefined
89
+
90
+ v = spec.get("validator")
91
+ if v is Unset or v is Undefined:
92
+ return None
93
+
94
+ from pydantic import field_validator
95
+
96
+ field_name = spec.name or "field"
97
+ # check_fields=False allows the validator to be defined in a base class before the field exists
98
+ return {f"{field_name}_validator": field_validator(field_name, check_fields=False)(v)}
99
+
100
+ @classmethod
101
+ def create_model(
102
+ cls,
103
+ op: "Operable",
104
+ model_name: str,
105
+ include: set[str] | None = None,
106
+ exclude: set[str] | None = None,
107
+ base_type: type["BaseModel"] | None = None,
108
+ doc: str | None = None,
109
+ ) -> type["BaseModel"]:
110
+ """Generate Pydantic BaseModel from Operable using pydantic.create_model()."""
111
+ from pydantic import BaseModel, create_model
112
+
113
+ use_specs = op.get_specs(include=include, exclude=exclude)
114
+ use_fields = {i.name: cls.create_field(i) for i in use_specs if i.name}
115
+
116
+ # Convert fields to (type, FieldInfo) tuples for create_model
117
+ field_definitions = {
118
+ name: (field_info.annotation, field_info) for name, field_info in use_fields.items()
119
+ }
120
+
121
+ # Collect validators
122
+ validators = {}
123
+ for spec in use_specs:
124
+ if spec.name and (validator := cls.create_validator(spec)):
125
+ validators.update(validator)
126
+
127
+ # If we have validators, create a base class with them
128
+ # Otherwise use the provided base_type or BaseModel
129
+ if validators:
130
+ # Create a temporary base class with validators as class attributes
131
+ base_with_validators = type(
132
+ f"{model_name}Base",
133
+ (base_type or BaseModel,),
134
+ validators,
135
+ )
136
+ actual_base = base_with_validators
137
+ else:
138
+ actual_base = base_type or BaseModel
139
+
140
+ # Create model using pydantic's create_model
141
+ model_cls = create_model(
142
+ model_name,
143
+ __base__=actual_base,
144
+ __doc__=doc,
145
+ **field_definitions,
146
+ )
147
+
148
+ model_cls.model_rebuild()
149
+ return model_cls
150
+
151
+ @classmethod
152
+ def fuzzy_match_fields(
153
+ cls, data: dict, model_cls: type["BaseModel"], strict: bool = False
154
+ ) -> dict[str, Any]:
155
+ """Match data keys to Pydantic fields (fuzzy). Filters sentinels. Args: data, model_cls, strict."""
156
+ from lionherd_core.ln._fuzzy_match import fuzzy_match_keys
157
+
158
+ from .._sentinel import not_sentinel
159
+
160
+ # "ignore" mode only includes successfully matched fields (no sentinel injection)
161
+ # "raise" mode raises on unmatched keys for strict validation
162
+ handle_mode = "raise" if strict else "ignore"
163
+
164
+ matched = fuzzy_match_keys(data, model_cls.model_fields, handle_unmatched=handle_mode)
165
+
166
+ # Filter out sentinel values (Unset, Undefined)
167
+ return {k: v for k, v in matched.items() if not_sentinel(v)}
168
+
169
+ @classmethod
170
+ def validate_model(cls, model_cls: type["BaseModel"], data: dict) -> "BaseModel":
171
+ """Validate dict → Pydantic model via model_validate()."""
172
+ return model_cls.model_validate(data)
173
+
174
+ @classmethod
175
+ def dump_model(cls, instance: "BaseModel") -> dict[str, Any]:
176
+ """Dump Pydantic model → dict via model_dump()."""
177
+ return instance.model_dump()
@@ -0,0 +1,502 @@
1
+ Metadata-Version: 2.4
2
+ Name: lionherd-core
3
+ Version: 1.0.0a3
4
+ Summary: The kernel layer for production AI agents - protocol-based, type-safe, zero framework lock-in
5
+ Project-URL: Homepage, https://github.com/khive-ai/lionherd-core
6
+ Project-URL: Documentation, https://github.com/khive-ai/lionherd-core/blob/main/README.md
7
+ Project-URL: Repository, https://github.com/khive-ai/lionherd-core
8
+ Project-URL: Issues, https://github.com/khive-ai/lionherd-core/issues
9
+ Project-URL: Changelog, https://github.com/khive-ai/lionherd-core/blob/main/CHANGELOG.md
10
+ Author-email: HaiyangLi <quantocean.li@gmail.com>
11
+ License: Apache-2.0
12
+ License-File: LICENSE
13
+ Keywords: agents,ai,async,llm,multi-agent,orchestration,protocols,type-safety
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: anyio>=4.7.0
26
+ Requires-Dist: pydapter>=1.2.0
27
+ Provides-Extra: schema-gen
28
+ Requires-Dist: datamodel-code-generator>=0.25.0; extra == 'schema-gen'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # lionherd-core
32
+
33
+ > The kernel layer for production AI agents
34
+
35
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
36
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
37
+ [![codecov](https://codecov.io/github/khive-ai/lionherd-core/graph/badge.svg?token=FAE47FY26T)](https://codecov.io/github/khive-ai/lionherd-core)
38
+ [![PyPI version](https://img.shields.io/pypi/v/lionherd-core.svg)](https://pypi.org/project/lionherd-core/)
39
+
40
+ ---
41
+
42
+ ## Why lionherd-core
43
+
44
+ Zero framework lock-in. Use what you need, ignore the rest. Build production AI
45
+ systems your way.
46
+
47
+ - ✅ **Protocol-based architecture** (Rust-inspired) - compose capabilities
48
+ without inheritance hell
49
+ - ✅ **Type-safe runtime validation** (Pydantic V2) - catch bugs before they
50
+ bite
51
+ - ✅ **Async-first** with thread-safe operations - scale without tears
52
+ - ✅ **99% test coverage** - production-ready from day one
53
+ - ✅ **Minimal dependencies** (pydapter + anyio) - no dependency hell
54
+
55
+ lionherd-core gives you composable primitives that work exactly how you want
56
+ them to.
57
+
58
+ ---
59
+
60
+ ## When to use this
61
+
62
+ ### Perfect for
63
+
64
+ 1. **Multi-agent orchestration**
65
+ - Define workflow DAGs with conditional edges
66
+ - Type-safe agent state management
67
+ - Protocol-based capability composition
68
+
69
+ 2. **Structured LLM outputs**
70
+ - Parse messy LLM responses → validated Python objects
71
+ - Fuzzy parsing tolerates formatting variations
72
+ - Declarative schemas with Pydantic integration
73
+
74
+ 3. **Production AI systems**
75
+ - Thread-safe collections for concurrent operations
76
+ - Async-first architecture scales naturally
77
+ - Protocol system enables clean interfaces
78
+
79
+ 4. **Custom AI frameworks**
80
+ - Build your own framework on solid primitives
81
+ - Protocol composition beats inheritance
82
+ - Adapter pattern for storage/serialization flexibility
83
+
84
+ ### Not for
85
+
86
+ - Quick prototypes (try LangChain)
87
+ - Learning AI agents (too low-level)
88
+ - No-code solutions (this is code-first)
89
+
90
+ ---
91
+
92
+ ## Installation
93
+
94
+ ```bash
95
+ pip install lionherd-core
96
+ ```
97
+
98
+ **Requirements**: Python ≥3.11
99
+
100
+ ---
101
+
102
+ ## Quick Examples
103
+
104
+ ### 1. Type-Safe Agent Collections
105
+
106
+ ```python
107
+ from lionherd_core import Element, Pile
108
+ from uuid import uuid4
109
+
110
+ class Agent(Element):
111
+ name: str
112
+ role: str
113
+ status: str = "idle"
114
+
115
+ # Type-safe collection
116
+ agents = Pile[Agent](item_type=Agent)
117
+ researcher = Agent(id=uuid4(), name="Alice", role="researcher")
118
+ agents.include(researcher)
119
+
120
+ # O(1) UUID lookup
121
+ found = agents[researcher.id]
122
+
123
+ # Predicate queries
124
+ idle_agents = agents.get(lambda a: a.status == "idle")
125
+ ```
126
+
127
+ ### 2. Directed Graphs
128
+
129
+ ```python
130
+ from lionherd_core import Graph, Node, Edge
131
+
132
+ graph = Graph()
133
+
134
+ # Add nodes
135
+ research = Node(content="Research")
136
+ analyze = Node(content="Analyze")
137
+ report = Node(content="Report")
138
+
139
+ graph.add_node(research)
140
+ graph.add_node(analyze)
141
+ graph.add_node(report)
142
+
143
+ # Define execution flow with edges
144
+ graph.add_edge(Edge(head=research.id, tail=analyze.id))
145
+ graph.add_edge(Edge(head=analyze.id, tail=report.id))
146
+
147
+ # Traverse graph
148
+ current = research
149
+ while current:
150
+ print(f"Executing: {current.content}")
151
+ successors = graph.get_successors(current.id)
152
+ current = successors[0] if successors else None
153
+ ```
154
+
155
+ ### 3. Structured LLM Outputs (LNDL)
156
+
157
+ ```python
158
+ from lionherd_core import Spec, Operable
159
+ from lionherd_core.lndl import parse_lndl_fuzzy
160
+ from pydantic import BaseModel
161
+
162
+ class Research(BaseModel):
163
+ query: str
164
+ findings: list[str]
165
+ confidence: float = 0.8
166
+
167
+ # Define schema
168
+ operable = Operable([Spec(Research, name="research")])
169
+
170
+ # Parse LLM output (tolerates typos and formatting variations)
171
+ llm_response = """
172
+ <lvar Research.query q>AI architectures</lvar>
173
+ <lvar Research.findings f>["Protocol-based", "Async-first"]</lvar>
174
+ <lvar Research.confidence c>0.92</lvar>
175
+ OUT{research: [q, f, c]}
176
+ """
177
+
178
+ result = parse_lndl_fuzzy(llm_response, operable)
179
+ print(result.research.confidence) # 0.92
180
+ print(result.research.query) # "AI architectures"
181
+ ```
182
+
183
+ ### 4. Protocol-Based Design
184
+
185
+ ```python
186
+ from lionherd_core.protocols import Observable, Serializable, Adaptable
187
+
188
+ # Check capabilities at runtime
189
+ if isinstance(obj, Observable):
190
+ print(obj.id) # UUID guaranteed
191
+
192
+ if isinstance(obj, Serializable):
193
+ data = obj.to_dict() # Serialization guaranteed
194
+
195
+ # Compose capabilities without inheritance
196
+ from lionherd_core.protocols import implements
197
+
198
+ @implements(Observable, Serializable, Adaptable)
199
+ class CustomAgent:
200
+ def __init__(self):
201
+ self.id = uuid4()
202
+
203
+ def to_dict(self):
204
+ return {"id": str(self.id)}
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Core Components
210
+
211
+ | Component | Purpose | Use When |
212
+ |-----------|---------|----------|
213
+ | **Element** | UUID + metadata | You need unique identity |
214
+ | **Node** | Polymorphic content | You need flexible content storage |
215
+ | **Pile[T]** | Type-safe collections | You need thread-safe typed collections |
216
+ | **Graph** | Directed graph with edges | You need workflow DAGs |
217
+ | **Flow** | Pile of progressions + items | You need ordered sequences |
218
+ | **Progression** | Ordered UUID sequence | You need to track execution order |
219
+ | **LNDL** | LLM output parser | You need structured LLM outputs |
220
+
221
+ ### Protocols (Rust-Inspired)
222
+
223
+ ```python
224
+ from lionherd_core.protocols import (
225
+ Observable, # UUID + metadata
226
+ Serializable, # to_dict(), to_json()
227
+ Deserializable, # from_dict()
228
+ Adaptable, # Multi-format conversion
229
+ AsyncAdaptable, # Async adaptation
230
+ )
231
+ ```
232
+
233
+ **Why protocols?**
234
+
235
+ - Structural typing beats inheritance
236
+ - Runtime checks with `isinstance()`
237
+ - Compose capabilities à la carte
238
+ - Zero performance overhead
239
+
240
+ ---
241
+
242
+ ## Use Cases in Detail
243
+
244
+ ### Multi-Agent Systems
245
+
246
+ ```python
247
+ # Define agent types with protocols
248
+ class ResearchAgent(Element):
249
+ expertise: str
250
+ status: str
251
+
252
+ class AnalystAgent(Element):
253
+ domain: str
254
+ status: str
255
+
256
+ # Type-safe agent registry
257
+ researchers = Pile[ResearchAgent](item_type=ResearchAgent)
258
+ analysts = Pile[AnalystAgent](item_type=AnalystAgent)
259
+
260
+ # Workflow orchestration with Graph
261
+ workflow = Graph()
262
+ research_phase = Node(content="research")
263
+ analysis_phase = Node(content="analysis")
264
+
265
+ workflow.add_node(research_phase)
266
+ workflow.add_node(analysis_phase)
267
+ workflow.add_edge(Edge(head=research_phase.id, tail=analysis_phase.id))
268
+
269
+ # Execute with conditional branching
270
+ current = research_phase
271
+ while current:
272
+ # Dispatch to appropriate agents
273
+ if current.content == "research":
274
+ execute_research(researchers)
275
+ elif current.content == "analysis":
276
+ execute_analysis(analysts)
277
+
278
+ # Progress workflow
279
+ successors = workflow.get_successors(current.id)
280
+ current = successors[0] if successors else None
281
+ ```
282
+
283
+ ### Tool Calling & Function Execution
284
+
285
+ ```python
286
+ from lionherd_core import Element, Pile, Spec, Operable
287
+ from lionherd_core.lndl import parse_lndl_fuzzy
288
+ from collections.abc import Callable
289
+ from pydantic import BaseModel
290
+ from typing import Any
291
+
292
+ class Tool(Element):
293
+ name: str
294
+ description: str
295
+ func: Callable[..., Any]
296
+
297
+ class Config:
298
+ arbitrary_types_allowed = True
299
+
300
+ # Tool registry
301
+ tools = Pile[Tool](item_type=Tool)
302
+ tools.include([
303
+ Tool(name="search", description="Search web", func=search_fn),
304
+ Tool(name="calculate", description="Math ops", func=calc_fn),
305
+ ])
306
+
307
+ # Parse LLM tool call
308
+ class ToolCall(BaseModel):
309
+ tool: str
310
+ args: dict
311
+
312
+ operable = Operable([Spec(ToolCall, name="call")])
313
+
314
+ llm_output = """
315
+ <lvar ToolCall.tool t>search</lvar>
316
+ <lvar ToolCall.args a>{"query": "AI agents"}</lvar>
317
+ OUT{call: [t, a]}
318
+ """
319
+
320
+ parsed = parse_lndl_fuzzy(llm_output, operable)
321
+
322
+ # Execute
323
+ tool = tools.get(lambda t: t.name == parsed.call.tool)[0]
324
+ result = tool.func(**parsed.call.args)
325
+ ```
326
+
327
+ ### Memory Systems
328
+
329
+ ```python
330
+ from lionherd_core import Node, Graph, Edge
331
+ from datetime import datetime
332
+
333
+ class Memory(Node):
334
+ timestamp: datetime
335
+ importance: float
336
+ tags: list[str]
337
+
338
+ # Memory graph (semantic connections)
339
+ memory_graph = Graph()
340
+
341
+ # Add memories
342
+ mem1 = Memory(
343
+ content="User likes Python",
344
+ timestamp=datetime.now(),
345
+ importance=0.9,
346
+ tags=["preference"]
347
+ )
348
+ mem2 = Memory(
349
+ content="User dislikes Java",
350
+ timestamp=datetime.now(),
351
+ importance=0.7,
352
+ tags=["preference"]
353
+ )
354
+
355
+ memory_graph.add_node(mem1)
356
+ memory_graph.add_node(mem2)
357
+
358
+ # Connect related memories
359
+ memory_graph.add_edge(Edge(head=mem1.id, tail=mem2.id, label=["preference"]))
360
+
361
+ # Query by importance
362
+ important_memories = memory_graph.nodes.get(lambda m: m.importance > 0.8)
363
+
364
+ # Traverse connections
365
+ related = memory_graph.get_successors(mem1.id)
366
+ ```
367
+
368
+ ### RAG Pipelines
369
+
370
+ ```python
371
+ from lionherd_core import Pile, Element
372
+
373
+ class Document(Element):
374
+ content: str
375
+ embedding: list[float]
376
+ metadata: dict
377
+
378
+ # Document store
379
+ docs = Pile[Document](item_type=Document)
380
+
381
+ # Add documents with embeddings
382
+ doc = Document(
383
+ content="Protocol-based design enables...",
384
+ embedding=get_embedding(content),
385
+ metadata={"source": "paper.pdf", "page": 12}
386
+ )
387
+ docs.include(doc)
388
+
389
+ # Retrieve by predicate
390
+ results = docs.get(lambda d: d.metadata["source"] == "paper.pdf")
391
+
392
+ # Integrate with vector DB via adapters
393
+ doc_dict = doc.to_dict()
394
+ vector_db.insert(doc_dict)
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Architecture
400
+
401
+ ```text
402
+ Your Application
403
+
404
+ lionherd-core ← You are here
405
+ ├── Protocols (Observable, Serializable, Adaptable)
406
+ ├── Base Classes (Element, Node, Pile, Graph, Flow)
407
+ ├── LNDL Parser (LLM output → Python objects)
408
+ └── Utilities (async, serialization, adapters)
409
+
410
+ Python Ecosystem (Pydantic, asyncio, pydapter)
411
+ ```
412
+
413
+ **Design Principles:**
414
+
415
+ 1. **Protocols over inheritance** - Compose capabilities structurally
416
+ 2. **Operations as morphisms** - Preserve semantics through composition
417
+ 3. **Async-first** - Native asyncio with thread-safe operations
418
+ 4. **Isolated adapters** - Per-class registries, zero pollution
419
+ 5. **Minimal dependencies** - Only pydapter + anyio
420
+
421
+ ---
422
+
423
+ ## Development
424
+
425
+ ```bash
426
+ # Setup
427
+ git clone https://github.com/khive-ai/lionherd-core.git
428
+ cd lionherd-core
429
+ uv sync --all-extras
430
+
431
+ # Test
432
+ uv run pytest --cov=lionherd_core
433
+
434
+ # Lint
435
+ uv run ruff check .
436
+ uv run ruff format .
437
+
438
+ # Type check
439
+ uv run mypy src/
440
+ ```
441
+
442
+ **Test Coverage**: Maintained at 99%+ with comprehensive test suite
443
+
444
+ ---
445
+
446
+ ## Roadmap
447
+
448
+ ### v1.0.0-beta (Q1 2025)
449
+
450
+ - API stabilization
451
+ - Comprehensive docs
452
+ - Performance benchmarks
453
+ - Additional adapters (Protobuf, MessagePack)
454
+
455
+ ### v1.0.0 (Q2 2025)
456
+
457
+ - Frozen public API
458
+ - Production-hardened
459
+ - Ecosystem integrations
460
+
461
+ ---
462
+
463
+ ## Related Projects
464
+
465
+ Part of the Lion ecosystem:
466
+
467
+ - **[lionagi](https://github.com/khive-ai/lionagi)**: v0 of the Lion ecosystem
468
+ - full agentic AI framework with advanced orchestration capabilities
469
+ - **[pydapter](https://github.com/khive-ai/pydapter)**: Universal data adapter
470
+ (JSON/YAML/TOML/SQL/Neo4j/Redis/MongoDB/Weaviate/etc.)
471
+
472
+ ---
473
+
474
+ ## License
475
+
476
+ Apache 2.0 - Free for commercial use, no strings attached.
477
+
478
+ ---
479
+
480
+ ## Support
481
+
482
+ - [GitHub Issues](https://github.com/khive-ai/lionherd-core/issues)
483
+ - [Discussions](https://github.com/khive-ai/lionherd-core/discussions)
484
+ - [Contributing Guide](./CONTRIBUTING.md)
485
+
486
+ ---
487
+
488
+ ## Created by
489
+
490
+ **[HaiyangLi (Ocean)](https://github.com/ohdearquant)** - [khive.ai](https://khive.ai)
491
+
492
+ Inspired by Rust traits, Pydantic validation, and functional programming.
493
+
494
+ ---
495
+
496
+ **Ready to build?**
497
+
498
+ ```bash
499
+ pip install lionherd-core
500
+ ```
501
+
502
+ *Alpha release - APIs may evolve. Feedback shapes the future.*