dyui 0.1.0__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.
dyui-0.1.0/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ # Python
2
+ .venv/
3
+ __pycache__/
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ build/
7
+ dist/
8
+
9
+ # Node
10
+ node_modules/
11
+ react/dist/
12
+ *.tsbuildinfo
13
+
14
+ # DyUI CLI scratch + exports
15
+ .dyui/
16
+ build_out/
17
+
18
+ # Env
19
+ .env
dyui-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Soham Das
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
dyui-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.4
2
+ Name: dyui
3
+ Version: 0.1.0
4
+ Summary: A dynamic-UI layer for any LangGraph agent: emit live UI cards from any node or tool, with any LLM.
5
+ Project-URL: Homepage, https://github.com/sohammmzzz/dyui
6
+ Project-URL: Repository, https://github.com/sohammmzzz/dyui
7
+ Project-URL: Issues, https://github.com/sohammmzzz/dyui/issues
8
+ Author-email: Soham Das <sohamdas1300@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,dynamic-ui,fastapi,generative-ui,langgraph,llm,sse,ui
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
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 :: User Interfaces
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: langgraph>=0.2.40
25
+ Requires-Dist: pydantic>=2
26
+ Provides-Extra: dev
27
+ Requires-Dist: fastapi>=0.110; extra == 'dev'
28
+ Requires-Dist: httpx; extra == 'dev'
29
+ Requires-Dist: pytest>=8; extra == 'dev'
30
+ Requires-Dist: uvicorn; extra == 'dev'
31
+ Provides-Extra: server
32
+ Requires-Dist: fastapi>=0.110; extra == 'server'
33
+ Requires-Dist: uvicorn>=0.30; extra == 'server'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # dyui
37
+
38
+ A **dynamic-UI layer for any LangGraph agent.** Emit rich, live UI "cards" from
39
+ inside any LangGraph node or tool — with any LLM, or none — and render them on
40
+ the frontend with the companion [`@dyui/react`](../react) package.
41
+
42
+ DyUI rides LangGraph's first-class `custom` stream channel, so it is
43
+ transport-, model-, and framework-agnostic. No voice, no vendor lock-in.
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ pip install dyui # core (langgraph + pydantic)
49
+ pip install "dyui[server]" # + FastAPI SSE server
50
+ ```
51
+
52
+ ## Emit cards from your agent
53
+
54
+ ```python
55
+ from dyui import emit, ui_tool, Card
56
+
57
+ # 1. Imperative — call anywhere inside a node:
58
+ emit("table", {"columns": ["city", "temp"], "rows": [["Berlin", 21]]},
59
+ title="Weather", icon="cloud", accent="cyan")
60
+
61
+ # 2. Decorator — auto pending -> done/error around a tool:
62
+ @ui_tool("stat", title="Sum", icon="plus", accent="emerald")
63
+ def add(a: float, b: float) -> dict:
64
+ return {"label": f"{a} + {b}", "value": a + b}
65
+
66
+ # 3. Context manager — long-running work, one card updated in place:
67
+ with Card("progress", title="Indexing") as card:
68
+ for i in range(1, 4):
69
+ card.progress({"value": i, "max": 3})
70
+ card.done({"value": 3, "max": 3, "label": "Done"})
71
+ ```
72
+
73
+ Each event carries an `id` (auto or yours), a `component` key (which card to
74
+ render), `props` (the data), a `status` (`pending`/`active`/`done`/`error`), and
75
+ an optional `surface` (which screen region hosts it).
76
+
77
+ ## Zero frontend: serve a UI from Python
78
+
79
+ You don't need React or npm to get a working screen. `create_dyui_app` hosts a
80
+ built-in single-file UI at `GET /` that renders every built-in card **and your
81
+ raw HTML cards**:
82
+
83
+ ```python
84
+ from dyui.server import create_dyui_app
85
+
86
+ app = create_dyui_app(my_compiled_graph) # uvicorn my_module:app --port 8008
87
+ # open http://localhost:8008 -> a live dynamic-UI screen, no frontend code
88
+ ```
89
+
90
+ ### Use your own HTML files as cards
91
+
92
+ Drop `.html` templates in a folder and emit them by name — placeholders are
93
+ filled from props (`{{ key }}` escaped, `{{{ key }}}` raw):
94
+
95
+ ```python
96
+ from dyui import HtmlTemplates
97
+
98
+ cards = HtmlTemplates("cards") # ./cards/invoice.html, weather.html, ...
99
+
100
+ def my_node(state):
101
+ cards.emit("invoice",
102
+ {"number": 42, "total": "$1,200", "customer": "Acme"},
103
+ title="Invoice", accent="emerald")
104
+ ```
105
+
106
+ That's the whole "one Python file + HTML templates → dynamic UI" path. See
107
+ [`examples/html_agent.py`](examples/html_agent.py) and [`examples/cards/`](examples/cards).
108
+
109
+ > The served UI renders the built-in card types and `html` cards. Bespoke
110
+ > *React* card components live in `@dyui/react`; for the no-frontend path, model
111
+ > custom cards as HTML templates instead.
112
+
113
+ ## Connect a React frontend (optional)
114
+
115
+ `POST /dyui/stream` is a plain SSE endpoint the `@dyui/react` `useDyUIAgent` hook
116
+ consumes directly. Or mount onto an existing app:
117
+
118
+ ```python
119
+ from dyui.server import add_dyui_routes
120
+ add_dyui_routes(existing_fastapi_app, my_graph, path="/agent/stream")
121
+ ```
122
+
123
+ ## Test / consume without HTTP
124
+
125
+ ```python
126
+ from dyui import collect_events
127
+ for ev in collect_events(my_graph, {"query": "berlin"}):
128
+ print(ev["status"], ev["component"], ev["props"])
129
+ ```
130
+
131
+ ## Built-in card components (frontend)
132
+
133
+ `text`, `markdown`, `table`, `stat`, `progress`, `list`, `keyvalue`, `json`,
134
+ `alert`, `image`, and `html` (sanitized custom markup). Register your own React
135
+ components for any `component` key to fully customise — see the React package.
136
+
137
+ ## Development
138
+
139
+ ```bash
140
+ python -m venv .venv && . .venv/Scripts/activate # Windows
141
+ pip install -e ".[dev]"
142
+ pytest
143
+ ```
dyui-0.1.0/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # dyui
2
+
3
+ A **dynamic-UI layer for any LangGraph agent.** Emit rich, live UI "cards" from
4
+ inside any LangGraph node or tool — with any LLM, or none — and render them on
5
+ the frontend with the companion [`@dyui/react`](../react) package.
6
+
7
+ DyUI rides LangGraph's first-class `custom` stream channel, so it is
8
+ transport-, model-, and framework-agnostic. No voice, no vendor lock-in.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pip install dyui # core (langgraph + pydantic)
14
+ pip install "dyui[server]" # + FastAPI SSE server
15
+ ```
16
+
17
+ ## Emit cards from your agent
18
+
19
+ ```python
20
+ from dyui import emit, ui_tool, Card
21
+
22
+ # 1. Imperative — call anywhere inside a node:
23
+ emit("table", {"columns": ["city", "temp"], "rows": [["Berlin", 21]]},
24
+ title="Weather", icon="cloud", accent="cyan")
25
+
26
+ # 2. Decorator — auto pending -> done/error around a tool:
27
+ @ui_tool("stat", title="Sum", icon="plus", accent="emerald")
28
+ def add(a: float, b: float) -> dict:
29
+ return {"label": f"{a} + {b}", "value": a + b}
30
+
31
+ # 3. Context manager — long-running work, one card updated in place:
32
+ with Card("progress", title="Indexing") as card:
33
+ for i in range(1, 4):
34
+ card.progress({"value": i, "max": 3})
35
+ card.done({"value": 3, "max": 3, "label": "Done"})
36
+ ```
37
+
38
+ Each event carries an `id` (auto or yours), a `component` key (which card to
39
+ render), `props` (the data), a `status` (`pending`/`active`/`done`/`error`), and
40
+ an optional `surface` (which screen region hosts it).
41
+
42
+ ## Zero frontend: serve a UI from Python
43
+
44
+ You don't need React or npm to get a working screen. `create_dyui_app` hosts a
45
+ built-in single-file UI at `GET /` that renders every built-in card **and your
46
+ raw HTML cards**:
47
+
48
+ ```python
49
+ from dyui.server import create_dyui_app
50
+
51
+ app = create_dyui_app(my_compiled_graph) # uvicorn my_module:app --port 8008
52
+ # open http://localhost:8008 -> a live dynamic-UI screen, no frontend code
53
+ ```
54
+
55
+ ### Use your own HTML files as cards
56
+
57
+ Drop `.html` templates in a folder and emit them by name — placeholders are
58
+ filled from props (`{{ key }}` escaped, `{{{ key }}}` raw):
59
+
60
+ ```python
61
+ from dyui import HtmlTemplates
62
+
63
+ cards = HtmlTemplates("cards") # ./cards/invoice.html, weather.html, ...
64
+
65
+ def my_node(state):
66
+ cards.emit("invoice",
67
+ {"number": 42, "total": "$1,200", "customer": "Acme"},
68
+ title="Invoice", accent="emerald")
69
+ ```
70
+
71
+ That's the whole "one Python file + HTML templates → dynamic UI" path. See
72
+ [`examples/html_agent.py`](examples/html_agent.py) and [`examples/cards/`](examples/cards).
73
+
74
+ > The served UI renders the built-in card types and `html` cards. Bespoke
75
+ > *React* card components live in `@dyui/react`; for the no-frontend path, model
76
+ > custom cards as HTML templates instead.
77
+
78
+ ## Connect a React frontend (optional)
79
+
80
+ `POST /dyui/stream` is a plain SSE endpoint the `@dyui/react` `useDyUIAgent` hook
81
+ consumes directly. Or mount onto an existing app:
82
+
83
+ ```python
84
+ from dyui.server import add_dyui_routes
85
+ add_dyui_routes(existing_fastapi_app, my_graph, path="/agent/stream")
86
+ ```
87
+
88
+ ## Test / consume without HTTP
89
+
90
+ ```python
91
+ from dyui import collect_events
92
+ for ev in collect_events(my_graph, {"query": "berlin"}):
93
+ print(ev["status"], ev["component"], ev["props"])
94
+ ```
95
+
96
+ ## Built-in card components (frontend)
97
+
98
+ `text`, `markdown`, `table`, `stat`, `progress`, `list`, `keyvalue`, `json`,
99
+ `alert`, `image`, and `html` (sanitized custom markup). Register your own React
100
+ components for any `component` key to fully customise — see the React package.
101
+
102
+ ## Development
103
+
104
+ ```bash
105
+ python -m venv .venv && . .venv/Scripts/activate # Windows
106
+ pip install -e ".[dev]"
107
+ pytest
108
+ ```
dyui-0.1.0/conftest.py ADDED
@@ -0,0 +1,6 @@
1
+ import sys
2
+ from pathlib import Path
3
+
4
+ # Ensure the package root (this directory) is importable so tests can do
5
+ # ``import dyui`` and ``import examples.agent`` without installing the package.
6
+ sys.path.insert(0, str(Path(__file__).parent))
@@ -0,0 +1,61 @@
1
+ """DyUI -- a dynamic-UI layer for any LangGraph agent.
2
+
3
+ Emit rich, live UI "cards" from inside any LangGraph node or tool, with any LLM
4
+ (or none). The companion ``@dyui/react`` package renders those cards on the
5
+ frontend via a pluggable registry that also supports raw custom HTML.
6
+
7
+ Quick start (agent side)::
8
+
9
+ from dyui import emit, ui_tool
10
+
11
+ @ui_tool("stat", title="Weather", icon="cloud", accent="cyan")
12
+ def get_weather(city: str) -> dict:
13
+ return {"label": city, "value": 21, "unit": "C"}
14
+
15
+ # or imperatively, anywhere inside a node:
16
+ emit("table", {"columns": ["a", "b"], "rows": [[1, 2]]}, title="Results")
17
+
18
+ Quick start (server side)::
19
+
20
+ from dyui.server import create_dyui_app
21
+ app = create_dyui_app(my_compiled_graph) # uvicorn dyui_app:app
22
+ """
23
+
24
+ from .__version__ import __version__
25
+ from .emit import Card, emit, ui_tool, update
26
+ from .events import DYUI_KEY, Status, UIEvent, is_dyui_payload, parse_envelope
27
+ from .stream import astream_ui, collect, collect_events
28
+ from .templates import HtmlTemplates, render_template
29
+
30
+ __all__ = [
31
+ "__version__",
32
+ "emit",
33
+ "update",
34
+ "ui_tool",
35
+ "Card",
36
+ "UIEvent",
37
+ "Status",
38
+ "DYUI_KEY",
39
+ "is_dyui_payload",
40
+ "parse_envelope",
41
+ "astream_ui",
42
+ "collect",
43
+ "collect_events",
44
+ "HtmlTemplates",
45
+ "render_template",
46
+ # lazily provided (need FastAPI):
47
+ "create_dyui_app",
48
+ "add_dyui_routes",
49
+ "mount_ui",
50
+ "render_ui_page",
51
+ ]
52
+
53
+
54
+ def __getattr__(name: str):
55
+ # Lazily expose the FastAPI helpers so importing ``dyui`` never hard-requires
56
+ # FastAPI (it's an optional ``[server]`` extra).
57
+ if name in {"create_dyui_app", "add_dyui_routes", "mount_ui", "render_ui_page"}:
58
+ from . import server
59
+
60
+ return getattr(server, name)
61
+ raise AttributeError(f"module 'dyui' has no attribute {name!r}")
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"