openconstruct-jupyter 0.1.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.
@@ -0,0 +1,59 @@
1
+ """
2
+ openconstruct-jupyter — Jupyter notebook integration for OpenConstruct.
3
+ """
4
+
5
+ __version__ = "0.1.0"
6
+
7
+ from .magic import load_ipython_extension, unload_ipython_extension
8
+ from .widgets import (
9
+ AgentConfigWidget,
10
+ FleetStatusWidget,
11
+ SenseShadowWidget,
12
+ RoomGraphWidget,
13
+ TickBoardWidget,
14
+ PolicyWidget,
15
+ )
16
+ from .kernel import OCClient
17
+
18
+ # Module-level convenience functions backed by a default OCClient
19
+ _default_client: OCClient | None = None
20
+
21
+
22
+ def _get_client() -> OCClient:
23
+ global _default_client
24
+ if _default_client is None:
25
+ _default_client = OCClient()
26
+ return _default_client
27
+
28
+
29
+ def connect(**kwargs) -> OCClient:
30
+ """Connect this notebook to OpenConstruct. Returns the active client."""
31
+ global _default_client
32
+ _default_client = OCClient(**kwargs)
33
+ _default_client.connect()
34
+ return _default_client
35
+
36
+
37
+ def from_dataframe(df, *, name: str = "data"):
38
+ """Convert a DataFrame into a Plato room."""
39
+ return _get_client().from_dataframe(df, name=name)
40
+
41
+
42
+ def from_function(func, *, name: str = "tool"):
43
+ """Wrap a Python function as an agent tool."""
44
+ return _get_client().from_function(func, name=name)
45
+
46
+
47
+ def from_model(model, *, name: str = "model"):
48
+ """Wrap an ML model as a sense module."""
49
+ return _get_client().from_model(model, name=name)
50
+
51
+
52
+ def from_api(url: str, *, name: str = "api"):
53
+ """Register a REST API as an agent resource."""
54
+ return _get_client().from_api(url, name=name)
55
+
56
+
57
+ def publish_room():
58
+ """Publish the notebook's room with the fleet."""
59
+ return _get_client().publish_room()
@@ -0,0 +1,86 @@
1
+ """
2
+ Rich display rendering for sense shadows, fleet topology, rooms, ticks, and config.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import html as html_lib
8
+ from typing import Any
9
+
10
+
11
+ def render_fleet(fleet_data: list[dict]) -> str:
12
+ """Render fleet topology as a styled HTML table."""
13
+ if not fleet_data:
14
+ return "<div style='color:#888'>No fleet agents discovered.</div>"
15
+ rows = "".join(
16
+ f"<tr><td>{a['agent_id']}</td><td><b>{a['name']}</b></td>"
17
+ f"<td style='color:{'#4a9' if a['status']=='online' else '#a44'}'>{a['status']}</td>"
18
+ f"<td>{', '.join(a.get('modules', []))}</td></tr>"
19
+ for a in fleet_data
20
+ )
21
+ return (
22
+ "<div style='font-family:monospace;background:#1e1e1e;color:#ddd;padding:12px;border-radius:6px'>"
23
+ "<b>🏗 Fleet Topology</b><br><br>"
24
+ "<table style='border-collapse:collapse'>"
25
+ "<tr><th style='padding:4px 12px;border-bottom:1px solid #555'>ID</th>"
26
+ "<th style='padding:4px 12px;border-bottom:1px solid #555'>Name</th>"
27
+ "<th style='padding:4px 12px;border-bottom:1px solid #555'>Status</th>"
28
+ "<th style='padding:4px 12px;border-bottom:1px solid #555'>Modules</th></tr>"
29
+ f"{rows}</table></div>"
30
+ )
31
+
32
+
33
+ def render_room(room_data: dict) -> str:
34
+ """Render a Plato room as an SVG-style node graph."""
35
+ name = html_lib.escape(room_data.get("name", "?"))
36
+ tiles = room_data.get("tiles", [])
37
+ nodes_html = "".join(
38
+ f'<div style="border:1px solid #4a9;padding:4px 10px;margin:3px;border-radius:6px;'
39
+ f'background:#1a2a1a;display:inline-block">'
40
+ f'{html_lib.escape(t["name"])} <small style="color:#8ac">CR {t.get("cr_score", 0)}</small></div>'
41
+ for t in tiles
42
+ )
43
+ return (
44
+ f"<div style='font-family:monospace;background:#1a1a2a;color:#ddd;padding:12px;border-radius:6px'>"
45
+ f"<b>🏠 Room: {name}</b> <small>({len(tiles)} tiles)</small><br><br>"
46
+ f"{nodes_html}</div>"
47
+ )
48
+
49
+
50
+ def render_tick(message: str) -> str:
51
+ """Render a tick as a chat bubble."""
52
+ safe = html_lib.escape(message)
53
+ return (
54
+ f"<div style='background:#2a3a5a;color:#ddd;padding:8px 14px;margin:4px 0;"
55
+ f"border-radius:10px;max-width:75%;font-family:monospace;display:inline-block'>"
56
+ f"✅ {safe}</div><br>"
57
+ )
58
+
59
+
60
+ def render_shadow(shadow) -> str:
61
+ """Render a sense shadow as styled HTML."""
62
+ sense_type = getattr(shadow, "sense_type", "text")
63
+ output = html_lib.escape(str(getattr(shadow, "output", "")))
64
+ status = "✓" if getattr(shadow, "success", True) else "✗"
65
+ color = "#4a9" if getattr(shadow, "success", True) else "#a44"
66
+ return (
67
+ f"<div style='font-family:monospace;background:#1a1a1a;color:#ddd;padding:10px;"
68
+ f"border-left:3px solid {color};border-radius:4px;margin:4px 0'>"
69
+ f"<b>🔍 Sense: {html_lib.escape(sense_type)}</b> {status}<br>"
70
+ f"<pre style='margin:4px 0;color:#aaa'>{output[:500]}</pre></div>"
71
+ )
72
+
73
+
74
+ def render_config_yaml(config: dict) -> str:
75
+ """Render config as syntax-highlighted YAML-ish HTML."""
76
+ lines = []
77
+ for k, v in config.items():
78
+ if isinstance(v, bool):
79
+ color = "#4a9" if v else "#a44"
80
+ lines.append(f'<span style="color:#88f">{k}</span>: <span style="color:{color}">{v}</span>')
81
+ elif isinstance(v, str):
82
+ lines.append(f'<span style="color:#88f">{k}</span>: <span style="color:#aa4">"{html_lib.escape(v)}"</span>')
83
+ else:
84
+ lines.append(f'<span style="color:#88f">{k}</span>: <span style="color:#ddd">{v}</span>')
85
+ body = "<br>".join(lines)
86
+ return f"<div style='font-family:monospace;background:#1e1e1e;color:#ddd;padding:10px;border-radius:4px'>{body}</div>"
@@ -0,0 +1,38 @@
1
+ """
2
+ Fleet status dashboard widget — a higher-level convenience wrapper.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import ipywidgets as widgets
8
+ from IPython.display import display
9
+
10
+ from .kernel import OCClient
11
+ from .display import render_fleet
12
+
13
+
14
+ class FleetPanel(widgets.VBox):
15
+ """Full fleet status dashboard with auto-refresh capability."""
16
+
17
+ def __init__(self, client: OCClient | None = None, **kwargs):
18
+ self._client = client or OCClient()
19
+ self.header = widgets.HTML(value="<h3>🏗 OpenConstruct Fleet</h3>")
20
+ self.body = widgets.HTML(value="<i>Click Refresh to discover fleet agents.</i>")
21
+ self.refresh_btn = widgets.Button(
22
+ description="🔄 Refresh", button_style="info", layout=widgets.Layout(width="120px")
23
+ )
24
+ self.refresh_btn.on_click(self._refresh)
25
+ self.connect_btn = widgets.Button(
26
+ description="⚡ Connect", button_style="success", layout=widgets.Layout(width="120px")
27
+ )
28
+ self.connect_btn.on_click(self._connect)
29
+ button_row = widgets.HBox(children=[self.connect_btn, self.refresh_btn])
30
+ super().__init__(children=[self.header, button_row, self.body], **kwargs)
31
+
32
+ def _connect(self, btn):
33
+ self._client.connect()
34
+ self._refresh(btn)
35
+
36
+ def _refresh(self, btn):
37
+ fleet = self._client.discover_fleet()
38
+ self.body.value = render_fleet(fleet)
@@ -0,0 +1,170 @@
1
+ """
2
+ Agent-aware kernel hooks and OCClient — the brain behind the magic.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import json
8
+ import time
9
+ import uuid
10
+ from dataclasses import dataclass, field
11
+ from typing import Any, Callable
12
+
13
+
14
+ @dataclass
15
+ class SenseShadow:
16
+ """A captured sense shadow."""
17
+ shadow_id: str = field(default_factory=lambda: uuid.uuid4().hex[:12])
18
+ sense_type: str = "text"
19
+ output: str = ""
20
+ success: bool = True
21
+ timestamp: float = field(default_factory=time.time)
22
+
23
+
24
+ @dataclass
25
+ class PlatoTile:
26
+ """A tile in a Plato room."""
27
+ tile_id: str = field(default_factory=lambda: uuid.uuid4().hex[:8])
28
+ name: str = ""
29
+ value: Any = None
30
+ cr_score: float = 0.0
31
+ source: str = "notebook"
32
+
33
+
34
+ @dataclass
35
+ class PlatoRoom:
36
+ """A Plato room — a shared knowledge space."""
37
+ room_id: str = field(default_factory=lambda: uuid.uuid4().hex[:8])
38
+ name: str = "default"
39
+ tiles: list[PlatoTile] = field(default_factory=list)
40
+ created: float = field(default_factory=time.time)
41
+
42
+ def add_tile(self, tile: PlatoTile):
43
+ self.tiles.append(tile)
44
+
45
+ def to_dict(self) -> dict:
46
+ return {
47
+ "room_id": self.room_id,
48
+ "name": self.name,
49
+ "tiles": [
50
+ {"tile_id": t.tile_id, "name": t.name, "cr_score": t.cr_score, "source": t.source}
51
+ for t in self.tiles
52
+ ],
53
+ }
54
+
55
+
56
+ @dataclass
57
+ class FleetAgent:
58
+ """An agent in the fleet."""
59
+ agent_id: str = ""
60
+ name: str = ""
61
+ status: str = "online"
62
+ modules: list[str] = field(default_factory=list)
63
+
64
+
65
+ @dataclass
66
+ class Tick:
67
+ """A tick message."""
68
+ tick_id: str = field(default_factory=lambda: uuid.uuid4().hex[:8])
69
+ message: str = ""
70
+ timestamp: float = field(default_factory=time.time)
71
+
72
+
73
+ class OCClient:
74
+ """
75
+ The core OpenConstruct client for Jupyter notebooks.
76
+
77
+ Maintains local state (rooms, shadows, fleet) and provides
78
+ the Python API surface (from_dataframe, from_function, etc.).
79
+ """
80
+
81
+ def __init__(self, notebook: bool = False, **kwargs):
82
+ self.connected = False
83
+ self.notebook = notebook
84
+ self.shadows: list[SenseShadow] = []
85
+ self.rooms: dict[str, PlatoRoom] = {}
86
+ self.fleet: list[FleetAgent] = []
87
+ self.ticks: list[Tick] = []
88
+ self.tools: dict[str, Callable] = {}
89
+ self.api_resources: dict[str, dict] = {}
90
+ self._default_room = PlatoRoom(name="notebook")
91
+
92
+ # --- Connection ---
93
+
94
+ def connect(self) -> dict:
95
+ """Connect to the OpenConstruct network."""
96
+ self.connected = True
97
+ self.fleet = [
98
+ FleetAgent(agent_id="self", name="notebook-agent", status="online", modules=["vision", "text"]),
99
+ ]
100
+ return {"status": "connected", "agent_id": "self"}
101
+
102
+ # --- Fleet ---
103
+
104
+ def discover_fleet(self) -> list[dict]:
105
+ """Return fleet topology."""
106
+ return [
107
+ {"agent_id": a.agent_id, "name": a.name, "status": a.status, "modules": a.modules}
108
+ for a in self.fleet
109
+ ]
110
+
111
+ # --- Shadows ---
112
+
113
+ def register_shadow(self, sense_type: str, output: str, success: bool = True) -> SenseShadow:
114
+ shadow = SenseShadow(sense_type=sense_type, output=output, success=success)
115
+ self.shadows.append(shadow)
116
+ return shadow
117
+
118
+ # --- Rooms ---
119
+
120
+ def load_room(self, name: str, context: str = "") -> PlatoRoom:
121
+ if name not in self.rooms:
122
+ self.rooms[name] = PlatoRoom(name=name)
123
+ if context:
124
+ tile = PlatoTile(name="cell_context", value=context, cr_score=0.5)
125
+ self.rooms[name].add_tile(tile)
126
+ return self.rooms[name]
127
+
128
+ def publish_room(self) -> dict:
129
+ """Publish the default room to the fleet."""
130
+ self._default_room.name = "published-notebook"
131
+ return self._default_room.to_dict()
132
+
133
+ # --- Ticks ---
134
+
135
+ def post_tick(self, message: str) -> Tick:
136
+ tick = Tick(message=message)
137
+ self.ticks.append(tick)
138
+ return tick
139
+
140
+ # --- Integration helpers ---
141
+
142
+ def from_dataframe(self, df, *, name: str = "data") -> PlatoTile:
143
+ """Convert a DataFrame into a Plato room tile with CR score."""
144
+ try:
145
+ rows = len(df)
146
+ cols = len(df.columns)
147
+ cr = min(1.0, (rows * cols) / 1000)
148
+ except Exception:
149
+ cr = 0.1
150
+ tile = PlatoTile(name=name, value=df, cr_score=round(cr, 2), source="dataframe")
151
+ self._default_room.add_tile(tile)
152
+ return tile
153
+
154
+ def from_function(self, func: Callable, *, name: str = "tool") -> dict:
155
+ """Register a Python function as an agent tool."""
156
+ self.tools[name] = func
157
+ return {"name": name, "type": "function", "registered": True}
158
+
159
+ def from_model(self, model, *, name: str = "model") -> dict:
160
+ """Register an ML model as a sense module."""
161
+ self.fleet.append(
162
+ FleetAgent(agent_id=name, name=name, status="online", modules=["inference"])
163
+ )
164
+ return {"name": name, "type": "model", "registered": True}
165
+
166
+ def from_api(self, url: str, *, name: str = "api") -> dict:
167
+ """Register a REST API as an agent resource."""
168
+ entry = {"url": url, "name": name, "type": "api"}
169
+ self.api_resources[name] = entry
170
+ return entry
@@ -0,0 +1,81 @@
1
+ """
2
+ %%openconstruct cell magic for IPython / Jupyter.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import argparse
8
+ import json
9
+ import sys
10
+ from typing import Any
11
+
12
+ from IPython.core.magic import Magics, magics_class, cell_magic, line_magic
13
+ from IPython.core.magic_arguments import argument, magic_arguments, parse_argstring
14
+ from IPython.display import display, HTML, Javascript
15
+
16
+ from .kernel import OCClient
17
+ from .display import render_fleet, render_room, render_tick, render_shadow
18
+
19
+
20
+ @magics_class
21
+ class OpenConstructMagics(Magics):
22
+ """IPython magics for OpenConstruct."""
23
+
24
+ def __init__(self, shell=None, **kwargs):
25
+ super().__init__(shell, **kwargs)
26
+ self._client: OCClient | None = None
27
+
28
+ def _get_client(self) -> OCClient:
29
+ if self._client is None:
30
+ self._client = OCClient()
31
+ return self._client
32
+
33
+ @magic_arguments()
34
+ @argument("--sense", type=str, default=None, help="Capture cell output as a sense shadow (e.g. vision, text)")
35
+ @argument("--tick", type=str, default=None, help="Post a tick message")
36
+ @argument("--room", type=str, default=None, help="Create or load a Plato room")
37
+ @argument("--fleet", action="store_true", help="Show fleet discovery inline")
38
+ @cell_magic
39
+ def openconstruct(self, line: str, cell: str):
40
+ """OpenConstruct cell magic."""
41
+ args = parse_argstring(self.openconstruct, line)
42
+ client = self._get_client()
43
+
44
+ if args.fleet:
45
+ fleet_data = client.discover_fleet()
46
+ display(HTML(render_fleet(fleet_data)))
47
+ return
48
+
49
+ if args.tick:
50
+ client.post_tick(args.tick)
51
+ display(HTML(render_tick(args.tick)))
52
+ return
53
+
54
+ if args.room:
55
+ room_data = client.load_room(args.room, context=cell)
56
+ display(HTML(render_room(room_data)))
57
+ return
58
+
59
+ if args.sense:
60
+ # Execute cell, capture output as a sense shadow
61
+ result = self.shell.run_cell(cell)
62
+ shadow = client.register_shadow(
63
+ sense_type=args.sense,
64
+ output=str(result.result) if result.result else "",
65
+ success=result.success,
66
+ )
67
+ display(HTML(render_shadow(shadow)))
68
+ return
69
+
70
+ # Default: execute and show raw output
71
+ self.shell.run_cell(cell)
72
+
73
+
74
+ def load_ipython_extension(ipython):
75
+ """Register the OpenConstruct magics with IPython."""
76
+ ipython.register_magics(OpenConstructMagics)
77
+
78
+
79
+ def unload_ipython_extension(ipython):
80
+ """Unregister the OpenConstruct magics (no-op, IPython handles it)."""
81
+ pass
@@ -0,0 +1,44 @@
1
+ """
2
+ Plato Room visualizer widget.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import ipywidgets as widgets
8
+ from IPython.display import display
9
+
10
+ from .kernel import OCClient, PlatoRoom
11
+ from .display import render_room
12
+
13
+
14
+ class RoomViewer(widgets.VBox):
15
+ """Interactive Plato Room visualizer."""
16
+
17
+ def __init__(self, client: OCClient | None = None, **kwargs):
18
+ self._client = client or OCClient()
19
+ self.header = widgets.HTML(value="<h3>🏠 Plato Room Viewer</h3>")
20
+ self.room_select = widgets.Dropdown(
21
+ options=["(no rooms)"],
22
+ description="Room:",
23
+ layout=widgets.Layout(width="300px"),
24
+ )
25
+ self.load_btn = widgets.Button(description="Load", button_style="primary")
26
+ self.load_btn.on_click(self._load)
27
+ self.body = widgets.HTML(value="<i>Select a room to visualize.</i>")
28
+ controls = widgets.HBox(children=[self.room_select, self.load_btn])
29
+ super().__init__(children=[self.header, controls, self.body], **kwargs)
30
+
31
+ def _refresh_rooms(self):
32
+ names = list(self._client.rooms.keys())
33
+ if not names:
34
+ names = ["(no rooms)"]
35
+ self.room_select.options = names
36
+
37
+ def _load(self, btn):
38
+ self._refresh_rooms()
39
+ name = self.room_select.value
40
+ if name in self._client.rooms:
41
+ room = self._client.rooms[name]
42
+ self.body.value = render_room(room.to_dict())
43
+ else:
44
+ self.body.value = "<i>No room selected.</i>"
@@ -0,0 +1,134 @@
1
+ """
2
+ IPython widgets for interactive agent control.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ import ipywidgets as widgets
10
+ from IPython.display import display
11
+
12
+ from .kernel import OCClient, FleetAgent
13
+
14
+
15
+ class AgentConfigWidget(widgets.VBox):
16
+ """Dropdown configuration for modules and interface type."""
17
+
18
+ def __init__(self, client: OCClient | None = None, **kwargs):
19
+ self._client = client or OCClient()
20
+ self.module_dropdown = widgets.Dropdown(
21
+ options=["vision", "text", "inference", "analysis"],
22
+ value="vision",
23
+ description="Module:",
24
+ )
25
+ self.interface_dropdown = widgets.Dropdown(
26
+ options=["magic", "api", "widget", "cli"],
27
+ value="magic",
28
+ description="Interface:",
29
+ )
30
+ self.apply_btn = widgets.Button(description="Apply", button_style="primary")
31
+ self.apply_btn.on_click(self._on_apply)
32
+ self.output = widgets.Output()
33
+ super().__init__(
34
+ children=[self.module_dropdown, self.interface_dropdown, self.apply_btn, self.output],
35
+ **kwargs,
36
+ )
37
+
38
+ def _on_apply(self, btn):
39
+ with self.output:
40
+ print(f"Configured: module={self.module_dropdown.value}, interface={self.interface_dropdown.value}")
41
+
42
+
43
+ class FleetStatusWidget(widgets.VBox):
44
+ """Live fleet health dashboard."""
45
+
46
+ def __init__(self, client: OCClient | None = None, **kwargs):
47
+ self._client = client or OCClient()
48
+ self.refresh_btn = widgets.Button(description="Refresh", button_style="info")
49
+ self.refresh_btn.on_click(self._refresh)
50
+ self.status_html = widgets.HTML(value="<i>No fleet data</i>")
51
+ super().__init__(children=[self.refresh_btn, self.status_html], **kwargs)
52
+
53
+ def _refresh(self, btn):
54
+ fleet = self._client.discover_fleet()
55
+ rows = "".join(
56
+ f"<tr><td>{a['name']}</td><td>{a['status']}</td><td>{', '.join(a['modules'])}</td></tr>"
57
+ for a in fleet
58
+ )
59
+ self.status_html.value = (
60
+ "<table><tr><th>Agent</th><th>Status</th><th>Modules</th></tr>"
61
+ f"{rows}</table>"
62
+ )
63
+
64
+
65
+ class SenseShadowWidget(widgets.VBox):
66
+ """Rendered sense output (HTML / ANSI)."""
67
+
68
+ def __init__(self, **kwargs):
69
+ self.shadow_output = widgets.HTML(value="<i>No shadow captured</i>")
70
+ super().__init__(children=[self.shadow_output], **kwargs)
71
+
72
+ def show(self, html: str):
73
+ self.shadow_output.value = html
74
+
75
+
76
+ class RoomGraphWidget(widgets.VBox):
77
+ """Plato room knowledge graph visualization."""
78
+
79
+ def __init__(self, client: OCClient | None = None, **kwargs):
80
+ self._client = client or OCClient()
81
+ self.graph_output = widgets.HTML(value="<i>No room loaded</i>")
82
+ super().__init__(children=[self.graph_output], **kwargs)
83
+
84
+ def show_room(self, room: dict):
85
+ tiles = room.get("tiles", [])
86
+ nodes = "".join(
87
+ f'<div style="border:1px solid #4a9;padding:4px 8px;margin:2px;border-radius:4px;'
88
+ f'background:#1a2a1a;display:inline-block">{t["name"]} <small>(CR {t["cr_score"]})</small></div>'
89
+ for t in tiles
90
+ )
91
+ self.graph_output.value = (
92
+ f'<div style="font-family:monospace">'
93
+ f'<b>Room: {room.get("name","?")}</b><br>{nodes}</div>'
94
+ )
95
+
96
+
97
+ class TickBoardWidget(widgets.VBox):
98
+ """Scrolling tick messages."""
99
+
100
+ def __init__(self, **kwargs):
101
+ self.tick_area = widgets.HTML(value="<i>No ticks</i>")
102
+ self._messages: list[str] = []
103
+ super().__init__(children=[self.tick_area], **kwargs)
104
+
105
+ def add_tick(self, message: str):
106
+ self._messages.append(message)
107
+ bubbles = "".join(
108
+ f'<div style="background:#2a3a5a;color:#ddd;padding:6px 10px;margin:3px 0;'
109
+ f'border-radius:8px;max-width:70%">{m}</div>'
110
+ for m in self._messages[-20:]
111
+ )
112
+ self.tick_area.value = bubbles
113
+
114
+
115
+ class PolicyWidget(widgets.VBox):
116
+ """Policy configuration with toggles."""
117
+
118
+ def __init__(self, **kwargs):
119
+ self.auto_register = widgets.ToggleButton(value=True, description="Auto-register")
120
+ self.auto_capture = widgets.ToggleButton(value=True, description="Auto-capture")
121
+ self.verbose = widgets.ToggleButton(value=False, description="Verbose")
122
+ self.output = widgets.Output()
123
+ super().__init__(
124
+ children=[self.auto_register, self.auto_capture, self.verbose, self.output],
125
+ **kwargs,
126
+ )
127
+
128
+ @property
129
+ def policy(self) -> dict:
130
+ return {
131
+ "auto_register": self.auto_register.value,
132
+ "auto_capture": self.auto_capture.value,
133
+ "verbose": self.verbose.value,
134
+ }
@@ -0,0 +1,91 @@
1
+ Metadata-Version: 2.4
2
+ Name: openconstruct-jupyter
3
+ Version: 0.1.0
4
+ Summary: Jupyter notebook integration for OpenConstruct — connect, sense, and build with agents
5
+ Author: SuperInstance
6
+ License-Expression: MIT
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Framework :: Jupyter
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: ipython>=7.0
15
+ Requires-Dist: ipywidgets>=8.0
16
+ Requires-Dist: rich>=13.0
17
+ Provides-Extra: dev
18
+ Requires-Dist: pytest>=7.0; extra == "dev"
19
+ Requires-Dist: pytest-asyncio; extra == "dev"
20
+
21
+ # openconstruct-jupyter — Jupyter Integration for OpenConstruct
22
+
23
+ Connect OpenConstruct to your Jupyter notebooks in one line. Cell magic, widgets, fleet panels, and DataFrame-to-room conversion.
24
+
25
+ **Part of [SuperInstance OpenConstruct](https://github.com/SuperInstance/OpenConstruct).**
26
+
27
+ ## What This Gives You
28
+
29
+ - **Cell magic** — `%%openconstruct --sense vision` captures output as a sense shadow
30
+ - **DataFrame → Plato room** — turn any pandas DataFrame into a knowledge graph
31
+ - **Python function → agent tool** — `oc.from_function(greet, name="my_tool")`
32
+ - **Fleet panel** — inline widget showing discovered fleet nodes
33
+ - **Room viewer** — visualize Plato room tiles and dependencies
34
+
35
+ ## Quick Start
36
+
37
+ ```python
38
+ # Load the extension
39
+ %load_ext openconstruct_jupyter
40
+
41
+ # Connect
42
+ import openconstruct_jupyter as oc
43
+ oc.connect(notebook=True)
44
+ ```
45
+
46
+ ### Cell Magic
47
+
48
+ ```python
49
+ %%openconstruct --sense vision
50
+ # Cell output captured as a vision shadow
51
+
52
+ %%openconstruct --tick "analysis complete"
53
+ # Post a tick to the fleet
54
+
55
+ %%openconstruct --room my-analysis
56
+ # Create or load a Plato room
57
+ ```
58
+
59
+ ### Python API
60
+
61
+ ```python
62
+ import pandas as pd
63
+
64
+ # DataFrame → room
65
+ df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
66
+ oc.from_dataframe(df, name="my_data")
67
+
68
+ # Function → agent tool
69
+ def greet(name):
70
+ return f"Hello, {name}!"
71
+ oc.from_function(greet, name="greet_tool")
72
+
73
+ # REST API → agent resource
74
+ oc.from_api("https://api.example.com/data", name="external_data")
75
+ ```
76
+
77
+ ## Installation
78
+
79
+ ```bash
80
+ pip install openconstruct-jupyter
81
+ ```
82
+
83
+ ## Testing
84
+
85
+ ```bash
86
+ pytest tests/ -v
87
+ ```
88
+
89
+ ## License
90
+
91
+ MIT
@@ -0,0 +1,12 @@
1
+ openconstruct_jupyter/__init__.py,sha256=_BBAFb238o4O0-D17dWa-uxKozHbSHUUXrvQqF8X6Ac,1584
2
+ openconstruct_jupyter/display.py,sha256=G3SSgkpW4M6XFbznstuORwQ7UurWhg2Cr-e0J6PQNi0,3739
3
+ openconstruct_jupyter/fleet_panel.py,sha256=X8Q__3JHv9VKZCOjMwheFp39ZMKWTAFCQTt6xCfleRE,1399
4
+ openconstruct_jupyter/kernel.py,sha256=VW04NZcxpFFM4DyiW-tu9JKKZFPk04Vc1HeAaZO6GPA,5294
5
+ openconstruct_jupyter/magic.py,sha256=Ahfbu1CYHTD4ytq5itZBUa7j33h6FvjUVKQVbedfn58,2619
6
+ openconstruct_jupyter/room_viewer.py,sha256=MekoHLz2dtRZsIaKB-tysSLmvS2D8M4YPlWapili-0w,1497
7
+ openconstruct_jupyter/widgets.py,sha256=8oKOnLB2JlkuvnbU945P93jrr1V9S09wI4xJLgipZfM,4760
8
+ openconstruct_jupyter-0.1.0.dist-info/METADATA,sha256=D8eGOgxKFn55BWvlnGdKpL3fOCpDFT6xRZG7gTAy284,2307
9
+ openconstruct_jupyter-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
+ openconstruct_jupyter-0.1.0.dist-info/entry_points.txt,sha256=JYXTaurf4V1zHb5a6LZxp-MVqZyNcCnMVIUVMmnyATU,84
11
+ openconstruct_jupyter-0.1.0.dist-info/top_level.txt,sha256=Iq3ltnRV2khCRScenBXtYtJF483QTAI6-quo_MR4rgY,22
12
+ openconstruct_jupyter-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [IPython.kernel]
2
+ openconstruct = openconstruct_jupyter.magic:load_ipython_extension
@@ -0,0 +1 @@
1
+ openconstruct_jupyter