yera 0.1.1__py3-none-any.whl → 0.2.1__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.
- infra_mvp/base_client.py +29 -0
- infra_mvp/base_server.py +68 -0
- infra_mvp/monitoring/__init__.py +15 -0
- infra_mvp/monitoring/metrics.py +185 -0
- infra_mvp/stream/README.md +56 -0
- infra_mvp/stream/__init__.py +14 -0
- infra_mvp/stream/__main__.py +101 -0
- infra_mvp/stream/agents/demos/financial/chart_additions_plan.md +170 -0
- infra_mvp/stream/agents/demos/financial/portfolio_assistant_stream.json +1571 -0
- infra_mvp/stream/agents/reference/blocks/action.json +170 -0
- infra_mvp/stream/agents/reference/blocks/button.json +66 -0
- infra_mvp/stream/agents/reference/blocks/date.json +65 -0
- infra_mvp/stream/agents/reference/blocks/input_prompt.json +94 -0
- infra_mvp/stream/agents/reference/blocks/layout.json +288 -0
- infra_mvp/stream/agents/reference/blocks/markdown.json +344 -0
- infra_mvp/stream/agents/reference/blocks/slider.json +67 -0
- infra_mvp/stream/agents/reference/blocks/spinner.json +110 -0
- infra_mvp/stream/agents/reference/blocks/table.json +56 -0
- infra_mvp/stream/agents/reference/chat_dynamics/branching_test_stream.json +145 -0
- infra_mvp/stream/app.py +49 -0
- infra_mvp/stream/container.py +112 -0
- infra_mvp/stream/schemas/__init__.py +16 -0
- infra_mvp/stream/schemas/agent.py +24 -0
- infra_mvp/stream/schemas/interaction.py +28 -0
- infra_mvp/stream/schemas/session.py +30 -0
- infra_mvp/stream/server.py +321 -0
- infra_mvp/stream/services/__init__.py +12 -0
- infra_mvp/stream/services/agent_service.py +40 -0
- infra_mvp/stream/services/event_converter.py +83 -0
- infra_mvp/stream/services/session_service.py +247 -0
- yera/__init__.py +50 -1
- yera/agents/__init__.py +2 -0
- yera/agents/context.py +41 -0
- yera/agents/dataclasses.py +69 -0
- yera/agents/decorator.py +207 -0
- yera/agents/discovery.py +124 -0
- yera/agents/typing/__init__.py +0 -0
- yera/agents/typing/coerce.py +408 -0
- yera/agents/typing/utils.py +19 -0
- yera/agents/typing/validate.py +206 -0
- yera/cli.py +377 -0
- yera/config/__init__.py +1 -0
- yera/config/config_utils.py +164 -0
- yera/config/function_config.py +55 -0
- yera/config/logging.py +18 -0
- yera/config/tool_config.py +8 -0
- yera/config2/__init__.py +8 -0
- yera/config2/dataclasses.py +534 -0
- yera/config2/keyring.py +270 -0
- yera/config2/paths.py +28 -0
- yera/config2/read.py +113 -0
- yera/config2/setup.py +109 -0
- yera/config2/setup_handlers/__init__.py +1 -0
- yera/config2/setup_handlers/anthropic.py +126 -0
- yera/config2/setup_handlers/azure.py +236 -0
- yera/config2/setup_handlers/base.py +125 -0
- yera/config2/setup_handlers/llama_cpp.py +205 -0
- yera/config2/setup_handlers/ollama.py +157 -0
- yera/config2/setup_handlers/openai.py +137 -0
- yera/config2/write.py +87 -0
- yera/dsl/__init__.py +0 -0
- yera/dsl/functions.py +94 -0
- yera/dsl/struct.py +20 -0
- yera/dsl/workspace.py +79 -0
- yera/events/__init__.py +57 -0
- yera/events/blocks/__init__.py +68 -0
- yera/events/blocks/action.py +57 -0
- yera/events/blocks/bar_chart.py +92 -0
- yera/events/blocks/base/__init__.py +20 -0
- yera/events/blocks/base/base.py +166 -0
- yera/events/blocks/base/chart.py +288 -0
- yera/events/blocks/base/layout.py +111 -0
- yera/events/blocks/buttons.py +37 -0
- yera/events/blocks/columns.py +26 -0
- yera/events/blocks/container.py +24 -0
- yera/events/blocks/date_picker.py +50 -0
- yera/events/blocks/exit.py +39 -0
- yera/events/blocks/form.py +24 -0
- yera/events/blocks/input_echo.py +22 -0
- yera/events/blocks/input_request.py +31 -0
- yera/events/blocks/line_chart.py +97 -0
- yera/events/blocks/markdown.py +67 -0
- yera/events/blocks/slider.py +54 -0
- yera/events/blocks/spinner.py +55 -0
- yera/events/blocks/system_prompt.py +22 -0
- yera/events/blocks/table.py +291 -0
- yera/events/models/__init__.py +39 -0
- yera/events/models/block_data.py +112 -0
- yera/events/models/in_event.py +7 -0
- yera/events/models/out_event.py +75 -0
- yera/events/runtime.py +187 -0
- yera/events/stream.py +91 -0
- yera/models/__init__.py +0 -0
- yera/models/data_classes.py +20 -0
- yera/models/llm_atlas_proxy.py +44 -0
- yera/models/llm_context.py +99 -0
- yera/models/llm_interfaces/__init__.py +0 -0
- yera/models/llm_interfaces/anthropic.py +153 -0
- yera/models/llm_interfaces/aws_bedrock.py +14 -0
- yera/models/llm_interfaces/azure_openai.py +143 -0
- yera/models/llm_interfaces/base.py +26 -0
- yera/models/llm_interfaces/interface_registry.py +74 -0
- yera/models/llm_interfaces/llama_cpp.py +136 -0
- yera/models/llm_interfaces/mock.py +29 -0
- yera/models/llm_interfaces/ollama_interface.py +118 -0
- yera/models/llm_interfaces/open_ai.py +150 -0
- yera/models/llm_workspace.py +19 -0
- yera/models/model_atlas.py +139 -0
- yera/models/model_definition.py +38 -0
- yera/models/model_factory.py +33 -0
- yera/opaque/__init__.py +9 -0
- yera/opaque/base.py +20 -0
- yera/opaque/decorator.py +8 -0
- yera/opaque/markdown.py +57 -0
- yera/opaque/opaque_function.py +25 -0
- yera/tools/__init__.py +29 -0
- yera/tools/atlas_tool.py +20 -0
- yera/tools/base.py +24 -0
- yera/tools/decorated_tool.py +18 -0
- yera/tools/decorator.py +35 -0
- yera/tools/tool_atlas.py +51 -0
- yera/tools/tool_utils.py +361 -0
- yera/ui/dist/404.html +1 -0
- yera/ui/dist/__next.__PAGE__.txt +10 -0
- yera/ui/dist/__next._full.txt +23 -0
- yera/ui/dist/__next._head.txt +6 -0
- yera/ui/dist/__next._index.txt +5 -0
- yera/ui/dist/__next._tree.txt +7 -0
- yera/ui/dist/_next/static/T8WGYqDMoHDKKoHj0O3HK/_buildManifest.js +11 -0
- yera/ui/dist/_next/static/T8WGYqDMoHDKKoHj0O3HK/_clientMiddlewareManifest.json +1 -0
- yera/ui/dist/_next/static/T8WGYqDMoHDKKoHj0O3HK/_ssgManifest.js +1 -0
- yera/ui/dist/_next/static/chunks/4c4688e1ff21ad98.js +1 -0
- yera/ui/dist/_next/static/chunks/652cd53c27924d50.js +4 -0
- yera/ui/dist/_next/static/chunks/786d2107b51e8499.css +1 -0
- yera/ui/dist/_next/static/chunks/7de9141b1af425c3.js +1 -0
- yera/ui/dist/_next/static/chunks/87ef65064d3524c1.js +2 -0
- yera/ui/dist/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- yera/ui/dist/_next/static/chunks/a6dad97d9634a72d.js.map +1 -0
- yera/ui/dist/_next/static/chunks/c4c79d5d0b280aeb.js +1 -0
- yera/ui/dist/_next/static/chunks/dc2d2a247505d66f.css +5 -0
- yera/ui/dist/_next/static/chunks/f773f714b55ec620.js +37 -0
- yera/ui/dist/_next/static/chunks/turbopack-98b3031e1b1dbc33.js +4 -0
- yera/ui/dist/_next/static/media/14e23f9b59180572-s.9c448f3c.woff2 +0 -0
- yera/ui/dist/_next/static/media/2a65768255d6b625-s.p.d19752fb.woff2 +0 -0
- yera/ui/dist/_next/static/media/2b2eb4836d2dad95-s.f36de3af.woff2 +0 -0
- yera/ui/dist/_next/static/media/31183d9fd602dc89-s.c4ff9b73.woff2 +0 -0
- yera/ui/dist/_next/static/media/3fcb63a1ac6a562e-s.2f77a576.woff2 +0 -0
- yera/ui/dist/_next/static/media/45ec8de98929b0f6-s.81056204.woff2 +0 -0
- yera/ui/dist/_next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
- yera/ui/dist/_next/static/media/65c558afe41e89d6-s.e2c8389a.woff2 +0 -0
- yera/ui/dist/_next/static/media/67add6cc0f54b8cf-s.8ce53448.woff2 +0 -0
- yera/ui/dist/_next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
- yera/ui/dist/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
- yera/ui/dist/_next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
- yera/ui/dist/_next/static/media/a8ff2d5d0ccb0d12-s.fc5b72a7.woff2 +0 -0
- yera/ui/dist/_next/static/media/aae5f0be330e13db-s.p.853e26d6.woff2 +0 -0
- yera/ui/dist/_next/static/media/b11a6ccf4a3edec7-s.2113d282.woff2 +0 -0
- yera/ui/dist/_next/static/media/b49b0d9b851e4899-s.4f3fa681.woff2 +0 -0
- yera/ui/dist/_next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
- yera/ui/dist/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
- yera/ui/dist/_next/static/media/favicon.0b3bf435.ico +0 -0
- yera/ui/dist/_not-found/__next._full.txt +14 -0
- yera/ui/dist/_not-found/__next._head.txt +6 -0
- yera/ui/dist/_not-found/__next._index.txt +5 -0
- yera/ui/dist/_not-found/__next._not-found.__PAGE__.txt +5 -0
- yera/ui/dist/_not-found/__next._not-found.txt +4 -0
- yera/ui/dist/_not-found/__next._tree.txt +2 -0
- yera/ui/dist/_not-found.html +1 -0
- yera/ui/dist/_not-found.txt +14 -0
- yera/ui/dist/agent-icon.svg +3 -0
- yera/ui/dist/favicon.ico +0 -0
- yera/ui/dist/file.svg +1 -0
- yera/ui/dist/globe.svg +1 -0
- yera/ui/dist/index.html +1 -0
- yera/ui/dist/index.txt +23 -0
- yera/ui/dist/logo/full_logo.png +0 -0
- yera/ui/dist/logo/rune_logo.png +0 -0
- yera/ui/dist/logo/rune_logo_borderless.png +0 -0
- yera/ui/dist/logo/text_logo.png +0 -0
- yera/ui/dist/next.svg +1 -0
- yera/ui/dist/send.png +0 -0
- yera/ui/dist/send_single.png +0 -0
- yera/ui/dist/vercel.svg +1 -0
- yera/ui/dist/window.svg +1 -0
- yera/utils/__init__.py +1 -0
- yera/utils/path_utils.py +38 -0
- yera-0.2.1.dist-info/METADATA +65 -0
- yera-0.2.1.dist-info/RECORD +190 -0
- {yera-0.1.1.dist-info → yera-0.2.1.dist-info}/WHEEL +1 -1
- yera-0.2.1.dist-info/entry_points.txt +2 -0
- yera-0.1.1.dist-info/METADATA +0 -11
- yera-0.1.1.dist-info/RECORD +0 -4
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""Table block implementation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Literal
|
|
6
|
+
|
|
7
|
+
from yera.events.blocks.base import _BlockFactory, _StreamHandle
|
|
8
|
+
from yera.events.models import OutputEvent, TableData
|
|
9
|
+
from yera.events.stream import push_output
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _is_pandas_like(data: Any) -> bool:
|
|
13
|
+
"""Check if data is a pandas-like object (has .columns and .values)."""
|
|
14
|
+
return hasattr(data, "columns") and hasattr(data, "values")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _is_dict_of_lists(data: Any) -> bool:
|
|
18
|
+
"""Check if data is a dict where all values are lists (Streamlit column format)."""
|
|
19
|
+
return isinstance(data, dict) and all(
|
|
20
|
+
isinstance(v, list) for v in data.values() if v is not None
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _is_non_empty_list(data: Any) -> bool:
|
|
25
|
+
"""Check if data is a non-empty list."""
|
|
26
|
+
return isinstance(data, list) and len(data) > 0
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _is_list_of_dicts(data: Any) -> bool:
|
|
30
|
+
"""Check if data is a non-empty list where the first element is a dict."""
|
|
31
|
+
return _is_non_empty_list(data) and isinstance(data[0], dict)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _is_list_of_lists(data: Any) -> bool:
|
|
35
|
+
"""Check if data is a non-empty list where the first element is also a list."""
|
|
36
|
+
return _is_non_empty_list(data) and isinstance(data[0], list)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _is_iterable_but_not_string(item: Any) -> bool:
|
|
40
|
+
"""Check if item is iterable but not a string."""
|
|
41
|
+
return hasattr(item, "__iter__") and not isinstance(item, str)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _generate_columns(num_cols: int) -> list[str]:
|
|
45
|
+
"""Generate default column names."""
|
|
46
|
+
return [f"Column {i + 1}" for i in range(num_cols)]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _pad_rows(rows: list[list]) -> tuple[list[str], list[list]]:
|
|
50
|
+
"""Pad rows to same length and generate column names."""
|
|
51
|
+
if not rows:
|
|
52
|
+
return [], []
|
|
53
|
+
|
|
54
|
+
num_cols = max(len(row) for row in rows)
|
|
55
|
+
columns = _generate_columns(num_cols)
|
|
56
|
+
padded_rows = [row + [None] * (num_cols - len(row)) for row in rows]
|
|
57
|
+
return columns, padded_rows
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _convert_pandas(data) -> tuple[list[str], list[list]]:
|
|
61
|
+
"""Convert pandas DataFrame."""
|
|
62
|
+
columns = list(data.columns)
|
|
63
|
+
rows = [[cell for cell in row] for row in data.values.tolist()]
|
|
64
|
+
return columns, rows
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _convert_dict(data: dict) -> tuple[list[str], list[list]]:
|
|
68
|
+
"""Convert dict to table format."""
|
|
69
|
+
columns = list(data.keys())
|
|
70
|
+
|
|
71
|
+
if _is_dict_of_lists(data):
|
|
72
|
+
# Transpose: column-oriented -> row-oriented
|
|
73
|
+
max_len = max(len(v) for v in data.values() if isinstance(v, list))
|
|
74
|
+
rows = [
|
|
75
|
+
[data[col][i] if i < len(data[col]) else None for col in columns]
|
|
76
|
+
for i in range(max_len)
|
|
77
|
+
]
|
|
78
|
+
return columns, rows
|
|
79
|
+
|
|
80
|
+
# Single row fallback
|
|
81
|
+
return columns, [[data[col] for col in columns]]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _convert_list_of_dicts(data: list) -> tuple[list[str], list[list]]:
|
|
85
|
+
"""Convert list of dicts."""
|
|
86
|
+
columns = list(data[0].keys())
|
|
87
|
+
rows = [[row.get(col) for col in columns] for row in data]
|
|
88
|
+
return columns, rows
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _convert_list_of_lists(data: list) -> tuple[list[str], list[list]]:
|
|
92
|
+
"""Convert list of lists."""
|
|
93
|
+
rows = [[cell for cell in row] for row in data]
|
|
94
|
+
return _pad_rows(rows)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _convert_iterable(data) -> tuple[list[str], list[list]]:
|
|
98
|
+
"""Try to convert generic iterable."""
|
|
99
|
+
try:
|
|
100
|
+
data_list = list(data)
|
|
101
|
+
if _is_non_empty_list(data_list) and _is_iterable_but_not_string(data_list[0]):
|
|
102
|
+
rows = [[cell for cell in row] for row in data_list]
|
|
103
|
+
return _pad_rows(rows)
|
|
104
|
+
except (TypeError, ValueError):
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
raise ValueError(
|
|
108
|
+
f"Unsupported data type for table: {type(data)}. "
|
|
109
|
+
"Supported types: pandas DataFrame, dict with list values, "
|
|
110
|
+
"list of dicts, list of lists, iterables."
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _convert_data_to_table_format(
|
|
115
|
+
data: Any,
|
|
116
|
+
) -> tuple[list[str], list[list[str | int | float]]]:
|
|
117
|
+
"""Convert various data formats to table format (columns, rows).
|
|
118
|
+
|
|
119
|
+
Matches Streamlit's st.table behavior:
|
|
120
|
+
- pandas DataFrame: uses .columns and .values
|
|
121
|
+
- dict: keys are column names, values are lists of column data
|
|
122
|
+
e.g., {"Name": ["Alice", "Bob"], "Age": [25, 30]}
|
|
123
|
+
- list of dicts: keys from first dict become columns, each dict becomes a row
|
|
124
|
+
- list of lists: all lists are treated as rows (no automatic header row)
|
|
125
|
+
- numpy arrays, iterables: converted to rows
|
|
126
|
+
"""
|
|
127
|
+
if data is None:
|
|
128
|
+
return [], []
|
|
129
|
+
|
|
130
|
+
if _is_pandas_like(data):
|
|
131
|
+
return _convert_pandas(data)
|
|
132
|
+
|
|
133
|
+
if isinstance(data, dict):
|
|
134
|
+
return _convert_dict(data)
|
|
135
|
+
|
|
136
|
+
if _is_list_of_dicts(data):
|
|
137
|
+
return _convert_list_of_dicts(data)
|
|
138
|
+
|
|
139
|
+
if _is_non_empty_list(data):
|
|
140
|
+
if _is_list_of_lists(data):
|
|
141
|
+
return _convert_list_of_lists(data)
|
|
142
|
+
return [], [[cell for cell in data]]
|
|
143
|
+
|
|
144
|
+
return _convert_iterable(data)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _normalize_border(
|
|
148
|
+
border: bool | Literal["horizontal"],
|
|
149
|
+
) -> Literal["all", "none", "horizontal"]:
|
|
150
|
+
"""Convert Streamlit-style border (bool | "horizontal") to internal string format."""
|
|
151
|
+
if border is True:
|
|
152
|
+
return "all"
|
|
153
|
+
if border is False:
|
|
154
|
+
return "none"
|
|
155
|
+
# border == "horizontal"
|
|
156
|
+
return "horizontal"
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class TableStream(_StreamHandle):
|
|
160
|
+
"""Stream handle for a table block that supports incremental row additions.
|
|
161
|
+
|
|
162
|
+
Returned by `yr.table()` to enable `add_rows()` functionality.
|
|
163
|
+
Maintains table metadata (columns, border, block_id) and streams incremental
|
|
164
|
+
row updates to the frontend. The frontend accumulates these rows to build the
|
|
165
|
+
complete table state.
|
|
166
|
+
|
|
167
|
+
Example:
|
|
168
|
+
my_table = yr.table({"Name": ["Alice"], "Age": [25]})
|
|
169
|
+
my_table.add_rows([["Bob", 30]]) # Streams only the new rows
|
|
170
|
+
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
def __init__(
|
|
174
|
+
self,
|
|
175
|
+
block_id: str,
|
|
176
|
+
columns: list[str],
|
|
177
|
+
border: bool | Literal["horizontal"],
|
|
178
|
+
):
|
|
179
|
+
super().__init__(block_id, "table")
|
|
180
|
+
self.columns = columns
|
|
181
|
+
# Convert border to internal string format
|
|
182
|
+
self.border = _normalize_border(border)
|
|
183
|
+
|
|
184
|
+
def _emit_table_event(
|
|
185
|
+
self, rows_to_send: list[list[str | int | float]]
|
|
186
|
+
) -> OutputEvent:
|
|
187
|
+
"""Create and add an event with the given rows."""
|
|
188
|
+
event = self._create_chunk_event(
|
|
189
|
+
data=TableData(columns=self.columns, rows=rows_to_send, border=self.border),
|
|
190
|
+
)
|
|
191
|
+
push_output(event)
|
|
192
|
+
return event
|
|
193
|
+
|
|
194
|
+
def _convert_data_to_rows_for_columns(
|
|
195
|
+
self, data: Any
|
|
196
|
+
) -> list[list[str | int | float]]:
|
|
197
|
+
"""Convert various data formats into rows aligned to the given columns.
|
|
198
|
+
|
|
199
|
+
Used for incremental updates (add_rows), where the column schema is
|
|
200
|
+
already known from the initial table.
|
|
201
|
+
"""
|
|
202
|
+
if _is_pandas_like(data):
|
|
203
|
+
return [[cell for cell in row] for row in data.values.tolist()]
|
|
204
|
+
|
|
205
|
+
# Handle list inputs
|
|
206
|
+
if _is_non_empty_list(data):
|
|
207
|
+
first = data[0]
|
|
208
|
+
if _is_list_of_dicts(data):
|
|
209
|
+
# List of dicts - align to existing columns
|
|
210
|
+
return [[row.get(col, "") for col in self.columns] for row in data]
|
|
211
|
+
if _is_list_of_lists(data):
|
|
212
|
+
# List of lists - treat all as rows
|
|
213
|
+
return [[cell for cell in row] for row in data]
|
|
214
|
+
# Single list - treat as one row
|
|
215
|
+
return [[cell for cell in data]]
|
|
216
|
+
|
|
217
|
+
if isinstance(data, dict):
|
|
218
|
+
return [[data.get(col, "") for col in self.columns]]
|
|
219
|
+
|
|
220
|
+
raise ValueError(
|
|
221
|
+
f"Unsupported data type for add_rows: {type(data)}. "
|
|
222
|
+
"Supported: list of lists, list of dicts, pandas DataFrame, single list/dict."
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
def add_rows(self, data: Any) -> None:
|
|
226
|
+
"""Add rows to the table, matching Streamlit's element.add_rows() behavior.
|
|
227
|
+
|
|
228
|
+
Supports:
|
|
229
|
+
- list of lists: each inner list is a row
|
|
230
|
+
- list of dicts: each dict becomes a row (keys should match existing columns)
|
|
231
|
+
- pandas DataFrame: adds all rows
|
|
232
|
+
- single list: treated as a single row
|
|
233
|
+
"""
|
|
234
|
+
new_rows = self._convert_data_to_rows_for_columns(data)
|
|
235
|
+
|
|
236
|
+
# Send only the new rows, not the entire table
|
|
237
|
+
# Frontend maintains full table state by appending these rows
|
|
238
|
+
self._emit_table_event(new_rows)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class _TableBlockFactory(_BlockFactory):
|
|
242
|
+
"""Factory for creating table blocks, matching Streamlit's st.table API."""
|
|
243
|
+
|
|
244
|
+
def __init__(self):
|
|
245
|
+
super().__init__("table")
|
|
246
|
+
|
|
247
|
+
def __call__(
|
|
248
|
+
self,
|
|
249
|
+
data: Any = None,
|
|
250
|
+
*,
|
|
251
|
+
border: bool | Literal["horizontal"] = True,
|
|
252
|
+
) -> TableStream:
|
|
253
|
+
"""Create a table block, matching Streamlit's st.table() signature.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
data: Table data. Supports (matching Streamlit):
|
|
257
|
+
- pandas DataFrame: primary format
|
|
258
|
+
- dict with list values: {"Name": ["Alice", "Bob"], "Age": [25, 30]}
|
|
259
|
+
- list of dicts: [{"Name": "Alice", "Age": 25}, ...]
|
|
260
|
+
- list of lists: all lists are rows (no header row)
|
|
261
|
+
- numpy arrays, iterables: converted to rows
|
|
262
|
+
- None: creates an empty table
|
|
263
|
+
border: Whether to show borders. Can be True, False, or "horizontal".
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
TableStream that supports add_rows() method, matching Streamlit's element.add_rows()
|
|
267
|
+
|
|
268
|
+
Example:
|
|
269
|
+
# Streamlit-style usage:
|
|
270
|
+
my_table = yr.table({"Name": ["Alice", "Bob"], "Age": [25, 30]})
|
|
271
|
+
my_table.add_rows([["Charlie", 35]])
|
|
272
|
+
|
|
273
|
+
"""
|
|
274
|
+
block_id = self._generate_block_id()
|
|
275
|
+
|
|
276
|
+
if data is None:
|
|
277
|
+
columns, rows = [], []
|
|
278
|
+
else:
|
|
279
|
+
columns, rows = _convert_data_to_table_format(data)
|
|
280
|
+
|
|
281
|
+
# Create table stream and immediately create the event
|
|
282
|
+
stream = TableStream(block_id, columns, border)
|
|
283
|
+
if columns or rows:
|
|
284
|
+
stream._emit_table_event(rows)
|
|
285
|
+
return stream
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
# Create the table callable/context manager
|
|
289
|
+
table = _TableBlockFactory()
|
|
290
|
+
|
|
291
|
+
__all__ = ["table"]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Data models for events blocks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from yera.events.models.block_data import (
|
|
6
|
+
ActionData,
|
|
7
|
+
BarChartData,
|
|
8
|
+
ButtonsData,
|
|
9
|
+
ColumnsData,
|
|
10
|
+
ContainerData,
|
|
11
|
+
DatePickerData,
|
|
12
|
+
ExitEventData,
|
|
13
|
+
InputRequestData,
|
|
14
|
+
LayoutEndData,
|
|
15
|
+
LineChartData,
|
|
16
|
+
MarkdownData,
|
|
17
|
+
SliderData,
|
|
18
|
+
SpinnerData,
|
|
19
|
+
TableData,
|
|
20
|
+
)
|
|
21
|
+
from yera.events.models.out_event import OutputEvent
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"ActionData",
|
|
25
|
+
"BarChartData",
|
|
26
|
+
"ButtonsData",
|
|
27
|
+
"ColumnsData",
|
|
28
|
+
"ContainerData",
|
|
29
|
+
"DatePickerData",
|
|
30
|
+
"ExitEventData",
|
|
31
|
+
"InputRequestData",
|
|
32
|
+
"LayoutEndData",
|
|
33
|
+
"LineChartData",
|
|
34
|
+
"MarkdownData",
|
|
35
|
+
"OutputEvent",
|
|
36
|
+
"SliderData",
|
|
37
|
+
"SpinnerData",
|
|
38
|
+
"TableData",
|
|
39
|
+
]
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Block data models for events blocks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import date
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MarkdownData(BaseModel):
|
|
12
|
+
content: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ButtonsData(BaseModel):
|
|
16
|
+
options: list[str]
|
|
17
|
+
label: str | None = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ActionData(BaseModel):
|
|
21
|
+
status: Literal["active", "complete"]
|
|
22
|
+
message: str | None = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SpinnerData(BaseModel):
|
|
26
|
+
status: Literal["active", "complete"]
|
|
27
|
+
message: str | None = None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DatePickerData(BaseModel):
|
|
31
|
+
value: date # Pydantic will serialize to YYYY-MM-DD string automatically
|
|
32
|
+
label: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SliderData(BaseModel):
|
|
36
|
+
min_value: float
|
|
37
|
+
max_value: float
|
|
38
|
+
initial_value: float
|
|
39
|
+
label: str
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class TableData(BaseModel):
|
|
43
|
+
columns: list[str]
|
|
44
|
+
rows: list[list[str | int | float]]
|
|
45
|
+
border: Literal["all", "none", "horizontal"] = "all"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ContainerData(BaseModel):
|
|
49
|
+
showBorder: bool
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ColumnsData(BaseModel):
|
|
53
|
+
showBorder: bool
|
|
54
|
+
column_count: int
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class LayoutEndData(BaseModel):
|
|
58
|
+
"""Empty data for layout_end control event; layout identified by block_id."""
|
|
59
|
+
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class BarChartData(BaseModel):
|
|
64
|
+
x_label: str | None
|
|
65
|
+
x_categories: list[str]
|
|
66
|
+
y_label: str | None
|
|
67
|
+
y_values: list[list[int | float | None]]
|
|
68
|
+
colour_label: str | None
|
|
69
|
+
colour_categories: list[str]
|
|
70
|
+
colour_values: list[str]
|
|
71
|
+
horizontal: bool
|
|
72
|
+
stack: bool
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class LineChartData(BaseModel):
|
|
76
|
+
x_label: str | None = None
|
|
77
|
+
x_ticks: list[str] | None = None
|
|
78
|
+
y_label: str | None = None
|
|
79
|
+
y_values: list[list[float | None]]
|
|
80
|
+
colour_label: str | None = None
|
|
81
|
+
colour_series: list[str]
|
|
82
|
+
colour_values: list[str]
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class InputRequestData(BaseModel):
|
|
86
|
+
type: Literal["text"]
|
|
87
|
+
message: str | None = None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class ExitEventData(BaseModel):
|
|
91
|
+
exit_code: int
|
|
92
|
+
reason: str | None
|
|
93
|
+
return_type: str
|
|
94
|
+
return_value: str | None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
__all__ = [
|
|
98
|
+
"ActionData",
|
|
99
|
+
"BarChartData",
|
|
100
|
+
"ButtonsData",
|
|
101
|
+
"ColumnsData",
|
|
102
|
+
"ContainerData",
|
|
103
|
+
"DatePickerData",
|
|
104
|
+
"ExitEventData",
|
|
105
|
+
"InputRequestData",
|
|
106
|
+
"LayoutEndData",
|
|
107
|
+
"LineChartData",
|
|
108
|
+
"MarkdownData",
|
|
109
|
+
"SliderData",
|
|
110
|
+
"SpinnerData",
|
|
111
|
+
"TableData",
|
|
112
|
+
]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Event model for events block events."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
from yera.agents.dataclasses import AgentInstance
|
|
11
|
+
from yera.events.models import InputRequestData
|
|
12
|
+
from yera.events.models.block_data import (
|
|
13
|
+
ActionData,
|
|
14
|
+
BarChartData,
|
|
15
|
+
ButtonsData,
|
|
16
|
+
ColumnsData,
|
|
17
|
+
ContainerData,
|
|
18
|
+
DatePickerData,
|
|
19
|
+
ExitEventData,
|
|
20
|
+
LayoutEndData,
|
|
21
|
+
LineChartData,
|
|
22
|
+
MarkdownData,
|
|
23
|
+
SliderData,
|
|
24
|
+
SpinnerData,
|
|
25
|
+
TableData,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class OutputEvent(BaseModel):
|
|
30
|
+
message_type: Literal["informational", "await_user", "await_agent", "layout"]
|
|
31
|
+
block_type: Literal[
|
|
32
|
+
"markdown",
|
|
33
|
+
"buttons",
|
|
34
|
+
"action",
|
|
35
|
+
"table",
|
|
36
|
+
"slider",
|
|
37
|
+
"date_picker",
|
|
38
|
+
"date",
|
|
39
|
+
"spinner",
|
|
40
|
+
"layout",
|
|
41
|
+
"container",
|
|
42
|
+
"columns",
|
|
43
|
+
"form",
|
|
44
|
+
"input_echo",
|
|
45
|
+
"input_request",
|
|
46
|
+
"system_prompt",
|
|
47
|
+
"bar_chart",
|
|
48
|
+
"line_chart",
|
|
49
|
+
"exit",
|
|
50
|
+
"layout_end",
|
|
51
|
+
]
|
|
52
|
+
block_id: str
|
|
53
|
+
data: (
|
|
54
|
+
MarkdownData
|
|
55
|
+
| ButtonsData
|
|
56
|
+
| ActionData
|
|
57
|
+
| SpinnerData
|
|
58
|
+
| DatePickerData
|
|
59
|
+
| SliderData
|
|
60
|
+
| TableData
|
|
61
|
+
| ContainerData
|
|
62
|
+
| ColumnsData
|
|
63
|
+
| BarChartData
|
|
64
|
+
| LineChartData
|
|
65
|
+
| InputRequestData
|
|
66
|
+
| ExitEventData
|
|
67
|
+
| LayoutEndData
|
|
68
|
+
)
|
|
69
|
+
chunk_id: int
|
|
70
|
+
agent_instance: AgentInstance
|
|
71
|
+
parent_block_id: str | None = None
|
|
72
|
+
timestamp: datetime = Field(default_factory=datetime.now)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
__all__ = ["OutputEvent"]
|