genailit 0.0.1__tar.gz

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.
@@ -0,0 +1,53 @@
1
+ Metadata-Version: 2.4
2
+ Name: genailit
3
+ Version: 0.0.1
4
+ Summary: Open source Python library for multi-agent web interfaces.
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: pydantic>=2
7
+ Provides-Extra: dev
8
+ Requires-Dist: pytest; extra == 'dev'
9
+ Description-Content-Type: text/markdown
10
+
11
+ # GenAILit
12
+
13
+ GenAILit is a small Python base for building web interfaces for multi-agent systems.
14
+
15
+ This milestone only includes the package foundation:
16
+
17
+ - `GenAILitEvent`
18
+ - `TelemetryStore`
19
+ - `AdapterContext`
20
+ - `BaseAgentAdapter`
21
+
22
+ ## Requirements
23
+
24
+ - Python 3.10+
25
+ - `pydantic>=2`
26
+ - `pytest` for tests
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ pip install genailit
32
+ ```
33
+
34
+ ## Example
35
+
36
+ ```python
37
+ from genailit import AdapterContext, BaseAgentAdapter, GenAILitEvent, TelemetryStore
38
+
39
+
40
+ class EchoAdapter(BaseAgentAdapter):
41
+ def build_events(self, context: AdapterContext):
42
+ yield GenAILitEvent(name="ready")
43
+
44
+
45
+ telemetry = TelemetryStore()
46
+ context = AdapterContext(session_id="demo", telemetry=telemetry)
47
+ events = EchoAdapter().run(context)
48
+ ```
49
+
50
+ ## Scope
51
+
52
+ This milestone intentionally does not add LangGraph, React, CLI commands, or FastAPI application code.
53
+
@@ -0,0 +1,43 @@
1
+ # GenAILit
2
+
3
+ GenAILit is a small Python base for building web interfaces for multi-agent systems.
4
+
5
+ This milestone only includes the package foundation:
6
+
7
+ - `GenAILitEvent`
8
+ - `TelemetryStore`
9
+ - `AdapterContext`
10
+ - `BaseAgentAdapter`
11
+
12
+ ## Requirements
13
+
14
+ - Python 3.10+
15
+ - `pydantic>=2`
16
+ - `pytest` for tests
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ pip install genailit
22
+ ```
23
+
24
+ ## Example
25
+
26
+ ```python
27
+ from genailit import AdapterContext, BaseAgentAdapter, GenAILitEvent, TelemetryStore
28
+
29
+
30
+ class EchoAdapter(BaseAgentAdapter):
31
+ def build_events(self, context: AdapterContext):
32
+ yield GenAILitEvent(name="ready")
33
+
34
+
35
+ telemetry = TelemetryStore()
36
+ context = AdapterContext(session_id="demo", telemetry=telemetry)
37
+ events = EchoAdapter().run(context)
38
+ ```
39
+
40
+ ## Scope
41
+
42
+ This milestone intentionally does not add LangGraph, React, CLI commands, or FastAPI application code.
43
+
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "genailit"
7
+ version = "0.0.1"
8
+ description = "Open source Python library for multi-agent web interfaces."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "pydantic>=2",
13
+ ]
14
+
15
+ [project.optional-dependencies]
16
+ dev = [
17
+ "pytest",
18
+ ]
19
+
20
+ [tool.hatch.build.targets.wheel]
21
+ packages = ["src/genailit"]
22
+
23
+ [tool.pytest.ini_options]
24
+ testpaths = ["tests"]
25
+
@@ -0,0 +1,13 @@
1
+ from .adapters import AdapterContext, BaseAgentAdapter
2
+ from .events import GenAILitEvent
3
+ from .telemetry import TelemetryStore
4
+
5
+ __all__ = [
6
+ "AdapterContext",
7
+ "BaseAgentAdapter",
8
+ "GenAILitEvent",
9
+ "TelemetryStore",
10
+ ]
11
+
12
+ __version__ = "0.0.1"
13
+
@@ -0,0 +1,7 @@
1
+ from .base import AdapterContext, BaseAgentAdapter
2
+
3
+ __all__ = [
4
+ "AdapterContext",
5
+ "BaseAgentAdapter",
6
+ ]
7
+
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from dataclasses import dataclass, field
5
+ from collections.abc import Iterable, Mapping
6
+ from typing import Any
7
+
8
+ from ..events import GenAILitEvent
9
+ from ..telemetry import TelemetryStore
10
+
11
+
12
+ @dataclass(frozen=True, slots=True)
13
+ class AdapterContext:
14
+ session_id: str
15
+ telemetry: TelemetryStore | None = None
16
+ metadata: Mapping[str, Any] = field(default_factory=dict)
17
+
18
+ def with_metadata(self, **items: Any) -> "AdapterContext":
19
+ merged = dict(self.metadata)
20
+ merged.update(items)
21
+ return AdapterContext(
22
+ session_id=self.session_id,
23
+ telemetry=self.telemetry,
24
+ metadata=merged,
25
+ )
26
+
27
+
28
+ class BaseAgentAdapter(ABC):
29
+ @abstractmethod
30
+ def build_events(self, context: AdapterContext) -> Iterable[GenAILitEvent]:
31
+ raise NotImplementedError
32
+
33
+ def run(self, context: AdapterContext) -> tuple[GenAILitEvent, ...]:
34
+ events = tuple(self.build_events(context))
35
+ if context.telemetry is not None:
36
+ context.telemetry.extend(events)
37
+ return events
38
+
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import BaseModel, ConfigDict, Field
6
+
7
+
8
+ class GenAILitEvent(BaseModel):
9
+ model_config = ConfigDict(extra="forbid", frozen=True)
10
+
11
+ name: str
12
+ payload: dict[str, Any] = Field(default_factory=dict)
13
+
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterable
4
+
5
+ from .events import GenAILitEvent
6
+
7
+
8
+ class TelemetryStore:
9
+ def __init__(self) -> None:
10
+ self._events: list[GenAILitEvent] = []
11
+
12
+ def record(self, event: GenAILitEvent) -> None:
13
+ self._events.append(event)
14
+
15
+ def extend(self, events: Iterable[GenAILitEvent]) -> None:
16
+ self._events.extend(events)
17
+
18
+ def snapshot(self) -> tuple[GenAILitEvent, ...]:
19
+ return tuple(self._events)
20
+
21
+ def clear(self) -> None:
22
+ self._events.clear()
23
+
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from pathlib import Path
5
+
6
+
7
+ ROOT = Path(__file__).resolve().parents[1]
8
+ SRC = ROOT / "src"
9
+
10
+ if str(SRC) not in sys.path:
11
+ sys.path.insert(0, str(SRC))
12
+
@@ -0,0 +1,33 @@
1
+ import pytest
2
+
3
+ from genailit import AdapterContext, BaseAgentAdapter, GenAILitEvent, TelemetryStore
4
+
5
+
6
+ def test_base_agent_adapter_is_abstract() -> None:
7
+ with pytest.raises(TypeError):
8
+ BaseAgentAdapter() # type: ignore[abstract]
9
+
10
+
11
+ def test_base_agent_adapter_runs_and_records_telemetry() -> None:
12
+ class DemoAdapter(BaseAgentAdapter):
13
+ def build_events(self, context: AdapterContext):
14
+ yield GenAILitEvent(name="ready", payload={"session_id": context.session_id})
15
+
16
+ telemetry = TelemetryStore()
17
+ context = AdapterContext(session_id="abc", telemetry=telemetry)
18
+
19
+ events = DemoAdapter().run(context)
20
+
21
+ assert events == (GenAILitEvent(name="ready", payload={"session_id": "abc"}),)
22
+ assert telemetry.snapshot() == events
23
+
24
+
25
+ def test_adapter_context_merges_metadata() -> None:
26
+ context = AdapterContext(session_id="abc", metadata={"alpha": 1})
27
+
28
+ updated = context.with_metadata(beta=2)
29
+
30
+ assert updated.session_id == "abc"
31
+ assert updated.metadata == {"alpha": 1, "beta": 2}
32
+ assert context.metadata == {"alpha": 1}
33
+
@@ -0,0 +1,16 @@
1
+ import pytest
2
+
3
+ from genailit import GenAILitEvent
4
+
5
+
6
+ def test_genailit_event_models_name_and_payload() -> None:
7
+ event = GenAILitEvent(name="step_started", payload={"step": 1})
8
+
9
+ assert event.name == "step_started"
10
+ assert event.payload == {"step": 1}
11
+
12
+
13
+ def test_genailit_event_rejects_unknown_fields() -> None:
14
+ with pytest.raises(ValueError):
15
+ GenAILitEvent(name="x", unknown=True) # type: ignore[call-arg]
16
+
@@ -0,0 +1,17 @@
1
+ from genailit import GenAILitEvent, TelemetryStore
2
+
3
+
4
+ def test_telemetry_store_records_and_clears_events() -> None:
5
+ store = TelemetryStore()
6
+ first = GenAILitEvent(name="a")
7
+ second = GenAILitEvent(name="b")
8
+
9
+ store.record(first)
10
+ store.extend([second])
11
+
12
+ assert store.snapshot() == (first, second)
13
+
14
+ store.clear()
15
+
16
+ assert store.snapshot() == ()
17
+