nthlayer-bench 1.0.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,6 @@
1
+ """NthLayer Bench — Tier 3 operator TUI.
2
+
3
+ Textual-based terminal UI for case management, situation board,
4
+ and system health monitoring. Communicates with nthlayer-core
5
+ exclusively via HTTP API.
6
+ """
nthlayer_bench/app.py ADDED
@@ -0,0 +1,86 @@
1
+ """NthLayer Bench Textual application.
2
+
3
+ Single-screen TUI that connects to core's HTTP API and displays
4
+ connection status. Foundation for situation board, case bench,
5
+ and case detail screens (Phase 4).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import httpx
11
+ from textual.app import App, ComposeResult
12
+ from textual.containers import Container
13
+ from textual.widgets import Footer, Header, Static
14
+
15
+
16
+ class ConnectionStatus(Static):
17
+ """Displays connection status to nthlayer-core."""
18
+
19
+ CONNECTED = "[green]● Connected[/green]"
20
+ DISCONNECTED = "[red]● Disconnected[/red] — Core unreachable"
21
+ DEGRADED = "[yellow]● Degraded[/yellow] — Data may be stale"
22
+
23
+ def __init__(self, core_url: str) -> None:
24
+ super().__init__(self.DISCONNECTED)
25
+ self.core_url = core_url.rstrip("/")
26
+ self._connected = False
27
+
28
+ def on_mount(self) -> None:
29
+ self.set_interval(5.0, self._check_health)
30
+ # Check immediately on mount
31
+ self.call_later(self._check_health)
32
+
33
+ async def _check_health(self) -> None:
34
+ try:
35
+ async with httpx.AsyncClient(timeout=5.0) as client:
36
+ resp = await client.get(f"{self.core_url}/health")
37
+ if resp.status_code == 200:
38
+ self._connected = True
39
+ self.update(self.CONNECTED)
40
+ else:
41
+ self._connected = False
42
+ self.update(self.DEGRADED)
43
+ except (httpx.RequestError, OSError):
44
+ self._connected = False
45
+ self.update(self.DISCONNECTED)
46
+
47
+ @property
48
+ def is_connected(self) -> bool:
49
+ return self._connected
50
+
51
+
52
+ class BenchApp(App):
53
+ """NthLayer Bench — operator terminal UI."""
54
+
55
+ TITLE = "NthLayer Bench"
56
+ CSS = """
57
+ #status-bar {
58
+ dock: top;
59
+ height: 3;
60
+ padding: 1;
61
+ background: $surface;
62
+ }
63
+ #main {
64
+ padding: 1;
65
+ }
66
+ """
67
+
68
+ BINDINGS = [
69
+ ("q", "quit", "Quit"),
70
+ ]
71
+
72
+ def __init__(self, core_url: str = "http://localhost:8000") -> None:
73
+ super().__init__()
74
+ self.core_url = core_url
75
+
76
+ def compose(self) -> ComposeResult:
77
+ yield Header()
78
+ yield Container(
79
+ ConnectionStatus(self.core_url),
80
+ id="status-bar",
81
+ )
82
+ yield Container(
83
+ Static("NthLayer Bench v1.5.0a1\n\nPhase 4 screens coming soon: Situation Board, Case Bench, Case Detail"),
84
+ id="main",
85
+ )
86
+ yield Footer()
nthlayer_bench/cli.py ADDED
@@ -0,0 +1,21 @@
1
+ """NthLayer Bench CLI — start the operator TUI."""
2
+
3
+ import argparse
4
+
5
+
6
+ def main():
7
+ parser = argparse.ArgumentParser(description="NthLayer Bench — operator TUI")
8
+ parser.add_argument("-V", "--version", action="version", version="%(prog)s 1.5.0a1")
9
+ parser.add_argument("--core-url", default="http://localhost:8000",
10
+ help="Core API URL (default: http://localhost:8000)")
11
+
12
+ args = parser.parse_args()
13
+
14
+ from nthlayer_bench.app import BenchApp
15
+
16
+ app = BenchApp(core_url=args.core_url)
17
+ app.run()
18
+
19
+
20
+ if __name__ == "__main__":
21
+ main()
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: nthlayer-bench
3
+ Version: 1.0.0
4
+ Summary: NthLayer Bench — Tier 3 operator TUI for case management and situation awareness
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: nthlayer-common>=0.1.8
8
+ Requires-Dist: textual>=1.0
9
+ Requires-Dist: httpx>=0.27
10
+ Provides-Extra: dev
11
+ Requires-Dist: pytest>=8.2; extra == "dev"
12
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
13
+ Requires-Dist: ruff>=0.8; extra == "dev"
@@ -0,0 +1,8 @@
1
+ nthlayer_bench/__init__.py,sha256=YezdN1vaIBB9kLbaKGy3m5ZtP1lDO8GyLeoum2z2shg,200
2
+ nthlayer_bench/app.py,sha256=FfHe_SIe2w3wvrmVmITGuPiKVTH-KDEUBNVWUz8fL3k,2484
3
+ nthlayer_bench/cli.py,sha256=SFhpd44AScqvLWQk1raZQ3PRKdmh_8BrT5PnyCmlr74,581
4
+ nthlayer_bench-1.0.0.dist-info/METADATA,sha256=Z1-T2nrEoYSx8Z0TgYYhHkSW70-M_mJO_GNQ8AMLC2c,463
5
+ nthlayer_bench-1.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
6
+ nthlayer_bench-1.0.0.dist-info/entry_points.txt,sha256=rFr1LVxt_mMZN5bLWKJQhAU3Too3SUU_-Gs3JWHi7bk,59
7
+ nthlayer_bench-1.0.0.dist-info/top_level.txt,sha256=DgrsmUZOu5NGnWpDBB8PZ0egpmsFEFGNrYT1wPphaOg,15
8
+ nthlayer_bench-1.0.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
+ [console_scripts]
2
+ nthlayer-bench = nthlayer_bench.cli:main
@@ -0,0 +1 @@
1
+ nthlayer_bench