ellements 0.2.0__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.
- ellements/__init__.py +57 -0
- ellements/agents/__init__.py +45 -0
- ellements/agents/backend.py +100 -0
- ellements/agents/builder.py +303 -0
- ellements/agents/claude_backend.py +200 -0
- ellements/agents/controller.py +237 -0
- ellements/agents/openai_backend.py +187 -0
- ellements/agents/py.typed +0 -0
- ellements/agents/runner.py +358 -0
- ellements/agents/tools.py +30 -0
- ellements/benchmarking/__init__.py +52 -0
- ellements/benchmarking/harness.py +342 -0
- ellements/benchmarking/py.typed +0 -0
- ellements/benchmarking/results.py +173 -0
- ellements/cli/__init__.py +80 -0
- ellements/cli/adapters.py +73 -0
- ellements/cli/agent_tui.py +1178 -0
- ellements/cli/components.py +411 -0
- ellements/cli/printer.py +229 -0
- ellements/cli/py.typed +0 -0
- ellements/core/__init__.py +112 -0
- ellements/core/async_utils.py +42 -0
- ellements/core/budgeting/__init__.py +43 -0
- ellements/core/budgeting/client.py +276 -0
- ellements/core/budgeting/protocol.py +51 -0
- ellements/core/budgeting/trackers.py +177 -0
- ellements/core/caching/__init__.py +51 -0
- ellements/core/caching/cache.py +73 -0
- ellements/core/caching/client.py +300 -0
- ellements/core/caching/disk.py +128 -0
- ellements/core/caching/keys.py +97 -0
- ellements/core/caching/memory.py +104 -0
- ellements/core/chunking.py +262 -0
- ellements/core/config.py +180 -0
- ellements/core/exceptions.py +145 -0
- ellements/core/llm/__init__.py +46 -0
- ellements/core/llm/client.py +1124 -0
- ellements/core/llm/images.py +226 -0
- ellements/core/llm/messages.py +202 -0
- ellements/core/llm/model_params.py +66 -0
- ellements/core/llm/protocol.py +146 -0
- ellements/core/llm/requests.py +100 -0
- ellements/core/llm/structured.py +91 -0
- ellements/core/llm/wrapper.py +79 -0
- ellements/core/observability/__init__.py +39 -0
- ellements/core/observability/events.py +169 -0
- ellements/core/observability/jsonl_logger.py +244 -0
- ellements/core/observability/markdown_formatter.py +197 -0
- ellements/core/observability/observer.py +56 -0
- ellements/core/prompting/__init__.py +14 -0
- ellements/core/prompting/context.py +185 -0
- ellements/core/prompting/guideline.py +133 -0
- ellements/core/prompting/persona.py +267 -0
- ellements/core/prompting/sources.py +92 -0
- ellements/core/py.typed +0 -0
- ellements/core/rate_limit/__init__.py +44 -0
- ellements/core/rate_limit/bucket.py +85 -0
- ellements/core/rate_limit/client.py +216 -0
- ellements/core/rate_limit/protocol.py +27 -0
- ellements/core/templating.py +126 -0
- ellements/core/tools/__init__.py +51 -0
- ellements/core/tools/dialects.py +136 -0
- ellements/core/tools/executor.py +48 -0
- ellements/core/tools/protocol.py +36 -0
- ellements/core/tools/records.py +28 -0
- ellements/core/tools/registry.py +205 -0
- ellements/core/tools/schemas.py +80 -0
- ellements/core/tools/simple.py +119 -0
- ellements/core/tools/spec.py +33 -0
- ellements/domain_specific/__init__.py +7 -0
- ellements/domain_specific/finance/__init__.py +188 -0
- ellements/domain_specific/finance/calculations.py +837 -0
- ellements/domain_specific/finance/charts.py +426 -0
- ellements/domain_specific/finance/portfolio.py +129 -0
- ellements/domain_specific/finance/quant_analysis.py +279 -0
- ellements/domain_specific/finance/risk.py +362 -0
- ellements/domain_specific/finance/technical_indicators.py +241 -0
- ellements/domain_specific/finance/tools.py +483 -0
- ellements/domain_specific/finance/valuation.py +312 -0
- ellements/domain_specific/finance/yahoo_finance.py +1523 -0
- ellements/domain_specific/finance/yahoo_finance_models.py +321 -0
- ellements/domain_specific/py.typed +0 -0
- ellements/execution/__init__.py +56 -0
- ellements/execution/callbacks.py +149 -0
- ellements/execution/catalog.py +70 -0
- ellements/execution/collaborative.py +191 -0
- ellements/execution/config.py +135 -0
- ellements/execution/py.typed +0 -0
- ellements/execution/reflection.py +156 -0
- ellements/execution/self_consistency.py +189 -0
- ellements/execution/single_call.py +48 -0
- ellements/execution/strategies.py +237 -0
- ellements/execution/tree_of_thought.py +541 -0
- ellements/fslm/__init__.py +108 -0
- ellements/fslm/builtins.py +103 -0
- ellements/fslm/cli.py +199 -0
- ellements/fslm/context.py +50 -0
- ellements/fslm/definition.py +163 -0
- ellements/fslm/det.py +173 -0
- ellements/fslm/dsl.py +458 -0
- ellements/fslm/errors.py +38 -0
- ellements/fslm/evaluators.py +141 -0
- ellements/fslm/kernel.py +603 -0
- ellements/fslm/loading.py +123 -0
- ellements/fslm/models.py +623 -0
- ellements/fslm/nl.py +87 -0
- ellements/fslm/observers.py +107 -0
- ellements/fslm/persistence.py +72 -0
- ellements/fslm/py.typed +0 -0
- ellements/fslm/rendering.py +551 -0
- ellements/fslm/visualization.py +25 -0
- ellements/reporting/__init__.py +12 -0
- ellements/reporting/charts.py +364 -0
- ellements/reporting/html_generation.py +132 -0
- ellements/reporting/py.typed +0 -0
- ellements/reporting/visualization.py +73 -0
- ellements/standard_tools/__init__.py +22 -0
- ellements/standard_tools/py.typed +0 -0
- ellements/standard_tools/terminal.py +205 -0
- ellements/standard_tools/web/__init__.py +37 -0
- ellements/standard_tools/web/browser_viewer.py +214 -0
- ellements/standard_tools/web/crawler.py +454 -0
- ellements/standard_tools/web/search.py +399 -0
- ellements/standard_tools/web/youtube.py +1297 -0
- ellements-0.2.0.dist-info/METADATA +368 -0
- ellements-0.2.0.dist-info/RECORD +130 -0
- ellements-0.2.0.dist-info/WHEEL +5 -0
- ellements-0.2.0.dist-info/entry_points.txt +2 -0
- ellements-0.2.0.dist-info/licenses/LICENSE +42 -0
- ellements-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Observer protocol and built-in observers for FSLM runtime events."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import json
|
|
7
|
+
from datetime import UTC, datetime
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any, Protocol, runtime_checkable
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FSLMEventRecord(BaseModel):
|
|
15
|
+
"""One machine-level observer event."""
|
|
16
|
+
|
|
17
|
+
model_config = ConfigDict(extra="forbid")
|
|
18
|
+
|
|
19
|
+
type: str
|
|
20
|
+
ts: datetime = Field(default_factory=lambda: datetime.now(UTC))
|
|
21
|
+
machine_id: str
|
|
22
|
+
step_id: str | None = None
|
|
23
|
+
payload: dict[str, Any] = Field(default_factory=dict)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@runtime_checkable
|
|
27
|
+
class FSLMObserver(Protocol):
|
|
28
|
+
"""Receives machine-level FSLM events."""
|
|
29
|
+
|
|
30
|
+
async def on_event(self, event: FSLMEventRecord) -> None:
|
|
31
|
+
"""Handle one FSLM event."""
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class RecordingFSLMObserver:
|
|
35
|
+
"""In-memory observer useful for tests."""
|
|
36
|
+
|
|
37
|
+
def __init__(self) -> None:
|
|
38
|
+
self.events: list[FSLMEventRecord] = []
|
|
39
|
+
|
|
40
|
+
async def on_event(self, event: FSLMEventRecord) -> None:
|
|
41
|
+
self.events.append(event)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class JsonlFSLMObserver:
|
|
45
|
+
"""Append FSLM observer events as JSON lines."""
|
|
46
|
+
|
|
47
|
+
def __init__(self, path: str | Path) -> None:
|
|
48
|
+
self._path = Path(path)
|
|
49
|
+
self._path.parent.mkdir(parents=True, exist_ok=True)
|
|
50
|
+
self._lock = asyncio.Lock()
|
|
51
|
+
|
|
52
|
+
async def on_event(self, event: FSLMEventRecord) -> None:
|
|
53
|
+
line = json.dumps(event.model_dump(mode="json"), separators=(",", ":")) + "\n"
|
|
54
|
+
async with self._lock:
|
|
55
|
+
await asyncio.to_thread(self._append, line)
|
|
56
|
+
|
|
57
|
+
def _append(self, line: str) -> None:
|
|
58
|
+
with self._path.open("a", encoding="utf-8") as handle:
|
|
59
|
+
handle.write(line)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class RichConsoleFSLMObserver:
|
|
63
|
+
"""Pretty console observer for watching machines run."""
|
|
64
|
+
|
|
65
|
+
def __init__(self) -> None:
|
|
66
|
+
from rich.console import Console
|
|
67
|
+
|
|
68
|
+
self._console = Console()
|
|
69
|
+
|
|
70
|
+
async def on_event(self, event: FSLMEventRecord) -> None:
|
|
71
|
+
if event.type == "EventReceived":
|
|
72
|
+
self._console.print(
|
|
73
|
+
f"[bold cyan]event[/] {event.payload.get('event_type')} "
|
|
74
|
+
f"[dim]in {event.payload.get('state')}[/]"
|
|
75
|
+
)
|
|
76
|
+
elif event.type == "TransitionSelected":
|
|
77
|
+
self._console.print(
|
|
78
|
+
f"[bold green]transition[/] {event.payload.get('transition')} "
|
|
79
|
+
f"[dim]{event.payload.get('source')} -> "
|
|
80
|
+
f"{event.payload.get('target')}[/]"
|
|
81
|
+
)
|
|
82
|
+
elif event.type == "GuardEvaluated":
|
|
83
|
+
status = "ok" if event.payload.get("allowed") else "blocked"
|
|
84
|
+
self._console.print(
|
|
85
|
+
f" [magenta]guard[/] {event.payload.get('id')}: {status} "
|
|
86
|
+
f"[dim]confidence={event.payload.get('confidence')}[/]"
|
|
87
|
+
)
|
|
88
|
+
elif event.type == "InvariantChecked":
|
|
89
|
+
status = "ok" if event.payload.get("allowed") else "violation"
|
|
90
|
+
self._console.print(
|
|
91
|
+
f" [yellow]invariant[/] {event.payload.get('id')}: {status}"
|
|
92
|
+
)
|
|
93
|
+
elif event.type == "StepCompleted":
|
|
94
|
+
self._console.print(
|
|
95
|
+
f"[bold blue]step[/] {event.payload.get('status')} "
|
|
96
|
+
f"[dim]state={event.payload.get('state')}[/]"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
__all__ = [
|
|
101
|
+
"FSLMEventRecord",
|
|
102
|
+
"FSLMObserver",
|
|
103
|
+
"JsonlFSLMObserver",
|
|
104
|
+
"RecordingFSLMObserver",
|
|
105
|
+
"RichConsoleFSLMObserver",
|
|
106
|
+
]
|
|
107
|
+
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""In-memory and local-file persistence for FSLM runtime records."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from .models import FSLMEvent, MachineSnapshot, StepResult
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class InMemoryFSLMStore:
|
|
13
|
+
"""Lightweight in-memory store for snapshots/events/results/traces."""
|
|
14
|
+
|
|
15
|
+
def __init__(self) -> None:
|
|
16
|
+
self.snapshot: MachineSnapshot | None = None
|
|
17
|
+
self.events: list[FSLMEvent] = []
|
|
18
|
+
self.results: list[StepResult] = []
|
|
19
|
+
self.traces: list[dict[str, Any]] = []
|
|
20
|
+
|
|
21
|
+
async def save_snapshot(self, snapshot: MachineSnapshot) -> None:
|
|
22
|
+
self.snapshot = snapshot
|
|
23
|
+
|
|
24
|
+
async def load_snapshot(self) -> MachineSnapshot | None:
|
|
25
|
+
return self.snapshot
|
|
26
|
+
|
|
27
|
+
async def append_event(self, event: FSLMEvent) -> None:
|
|
28
|
+
self.events.append(event)
|
|
29
|
+
|
|
30
|
+
async def append_result(self, result: StepResult) -> None:
|
|
31
|
+
self.results.append(result)
|
|
32
|
+
|
|
33
|
+
async def append_trace(self, trace: dict[str, Any]) -> None:
|
|
34
|
+
self.traces.append(trace)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class LocalFSLMStore:
|
|
38
|
+
"""Local JSON/JSONL store using the `.fslm/` layout."""
|
|
39
|
+
|
|
40
|
+
def __init__(self, root: str | Path) -> None:
|
|
41
|
+
self.root = Path(root)
|
|
42
|
+
self.root.mkdir(parents=True, exist_ok=True)
|
|
43
|
+
|
|
44
|
+
async def save_snapshot(self, snapshot: MachineSnapshot) -> None:
|
|
45
|
+
self._write_json(self.root / "snapshot.json", snapshot.model_dump(mode="json"))
|
|
46
|
+
|
|
47
|
+
async def load_snapshot(self) -> MachineSnapshot | None:
|
|
48
|
+
path = self.root / "snapshot.json"
|
|
49
|
+
if not path.is_file():
|
|
50
|
+
return None
|
|
51
|
+
return MachineSnapshot.model_validate(json.loads(path.read_text("utf-8")))
|
|
52
|
+
|
|
53
|
+
async def append_event(self, event: FSLMEvent) -> None:
|
|
54
|
+
self._append_jsonl(self.root / "events.jsonl", event.model_dump(mode="json"))
|
|
55
|
+
|
|
56
|
+
async def append_result(self, result: StepResult) -> None:
|
|
57
|
+
self._append_jsonl(self.root / "results.jsonl", result.model_dump(mode="json"))
|
|
58
|
+
|
|
59
|
+
async def append_trace(self, trace: dict[str, Any]) -> None:
|
|
60
|
+
self._append_jsonl(self.root / "traces.jsonl", trace)
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def _write_json(path: Path, data: dict[str, Any]) -> None:
|
|
64
|
+
path.write_text(json.dumps(data, indent=2, sort_keys=True), encoding="utf-8")
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def _append_jsonl(path: Path, data: dict[str, Any]) -> None:
|
|
68
|
+
with path.open("a", encoding="utf-8") as handle:
|
|
69
|
+
handle.write(json.dumps(data, sort_keys=True) + "\n")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = ["InMemoryFSLMStore", "LocalFSLMStore"]
|
ellements/fslm/py.typed
ADDED
|
File without changes
|