glaip-sdk 0.7.10__py3-none-any.whl → 0.7.11__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.
- glaip_sdk/branding.py +113 -2
- glaip_sdk/cli/slash/session.py +331 -30
- glaip_sdk/cli/slash/tui/accounts.tcss +60 -0
- glaip_sdk/cli/slash/tui/accounts_app.py +765 -74
- glaip_sdk/cli/slash/tui/context.py +5 -2
- glaip_sdk/cli/slash/tui/layouts/__init__.py +14 -0
- glaip_sdk/cli/slash/tui/layouts/harlequin.py +160 -0
- glaip_sdk/cli/slash/tui/terminal.py +8 -3
- {glaip_sdk-0.7.10.dist-info → glaip_sdk-0.7.11.dist-info}/METADATA +1 -1
- {glaip_sdk-0.7.10.dist-info → glaip_sdk-0.7.11.dist-info}/RECORD +13 -11
- {glaip_sdk-0.7.10.dist-info → glaip_sdk-0.7.11.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.7.10.dist-info → glaip_sdk-0.7.11.dist-info}/entry_points.txt +0 -0
- {glaip_sdk-0.7.10.dist-info → glaip_sdk-0.7.11.dist-info}/top_level.txt +0 -0
|
@@ -44,17 +44,20 @@ class TUIContext:
|
|
|
44
44
|
clipboard: ClipboardAdapter | None = None
|
|
45
45
|
|
|
46
46
|
@classmethod
|
|
47
|
-
async def create(cls) -> TUIContext:
|
|
47
|
+
async def create(cls, *, detect_osc11: bool = True) -> TUIContext:
|
|
48
48
|
"""Create a TUIContext instance with detected terminal capabilities.
|
|
49
49
|
|
|
50
50
|
This factory method detects terminal capabilities asynchronously and
|
|
51
51
|
returns a populated TUIContext instance with all services initialized
|
|
52
52
|
(keybinds, theme, toasts, clipboard).
|
|
53
53
|
|
|
54
|
+
Args:
|
|
55
|
+
detect_osc11: When False, skip OSC 11 background detection.
|
|
56
|
+
|
|
54
57
|
Returns:
|
|
55
58
|
TUIContext instance with all services initialized.
|
|
56
59
|
"""
|
|
57
|
-
terminal = await TerminalCapabilities.detect()
|
|
60
|
+
terminal = await TerminalCapabilities.detect(detect_osc11=detect_osc11)
|
|
58
61
|
store = get_account_store()
|
|
59
62
|
settings = load_tui_settings(store=store)
|
|
60
63
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Layout components for TUI applications.
|
|
2
|
+
|
|
3
|
+
This package provides reusable layout components following the Harlequin pattern
|
|
4
|
+
for multi-pane data-rich screens.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
try: # pragma: no cover - optional dependency
|
|
10
|
+
from glaip_sdk.cli.slash.tui.layouts.harlequin import HarlequinScreen
|
|
11
|
+
except Exception: # pragma: no cover - optional dependency
|
|
12
|
+
HarlequinScreen = None # type: ignore[assignment, misc]
|
|
13
|
+
|
|
14
|
+
__all__ = ["HarlequinScreen"]
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Harlequin layout base class for multi-pane TUI screens.
|
|
2
|
+
|
|
3
|
+
This module provides the HarlequinScreen base class, which implements a modern
|
|
4
|
+
multi-pane "Harlequin" layout pattern for data-rich TUI screens. The layout uses
|
|
5
|
+
a 25/75 split with a list on the left and detail content on the right.
|
|
6
|
+
|
|
7
|
+
The Harlequin pattern is inspired by the Harlequin SQL client and provides:
|
|
8
|
+
- Left Pane (25%): ListView or compact table for item selection
|
|
9
|
+
- Right Pane (75%): Detail dashboard showing all fields, status, and action buttons
|
|
10
|
+
- Black background (#000000) that overrides terminal transparency
|
|
11
|
+
- Primary Blue borders (#005CB8)
|
|
12
|
+
|
|
13
|
+
Authors:
|
|
14
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import TYPE_CHECKING, Any
|
|
20
|
+
|
|
21
|
+
try: # pragma: no cover - optional dependency
|
|
22
|
+
from textual.containers import Container, Horizontal, Vertical
|
|
23
|
+
from textual.screen import Screen
|
|
24
|
+
except Exception: # pragma: no cover - optional dependency
|
|
25
|
+
|
|
26
|
+
class Screen: # type: ignore[no-redef]
|
|
27
|
+
"""Fallback Screen stub when Textual is unavailable."""
|
|
28
|
+
|
|
29
|
+
def __class_getitem__(cls, _):
|
|
30
|
+
"""Return the class for typing subscripts."""
|
|
31
|
+
return cls
|
|
32
|
+
|
|
33
|
+
Horizontal = None # type: ignore[assignment]
|
|
34
|
+
Vertical = None # type: ignore[assignment]
|
|
35
|
+
Container = None # type: ignore[assignment]
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from glaip_sdk.cli.slash.tui.context import TUIContext
|
|
39
|
+
|
|
40
|
+
try: # pragma: no cover - optional dependency
|
|
41
|
+
from glaip_sdk.cli.slash.tui.toast import Toast
|
|
42
|
+
except Exception: # pragma: no cover - optional dependency
|
|
43
|
+
Toast = None # type: ignore[assignment, misc]
|
|
44
|
+
|
|
45
|
+
# GDP Labs Brand Palette
|
|
46
|
+
PRIMARY_BLUE = "#005CB8"
|
|
47
|
+
BLACK_BACKGROUND = "#000000"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class HarlequinScreen(Screen[None]): # type: ignore[misc]
|
|
51
|
+
"""Base class for Harlequin-style multi-pane screens.
|
|
52
|
+
|
|
53
|
+
This screen provides a 25/75 split layout with a left pane for navigation
|
|
54
|
+
and a right pane for details. The layout uses a black background that
|
|
55
|
+
overrides terminal transparency and primary blue borders.
|
|
56
|
+
|
|
57
|
+
Subclasses should override `compose()` to add their specific widgets to
|
|
58
|
+
the left and right panes. Use the container IDs "left-pane" and "right-pane"
|
|
59
|
+
to target specific panes in CSS or when querying widgets.
|
|
60
|
+
|
|
61
|
+
Example:
|
|
62
|
+
```python
|
|
63
|
+
class AccountHarlequinScreen(HarlequinScreen):
|
|
64
|
+
def compose(self) -> ComposeResult:
|
|
65
|
+
yield from super().compose()
|
|
66
|
+
# Add widgets to left and right panes
|
|
67
|
+
self.query_one("#left-pane").mount(AccountListView())
|
|
68
|
+
self.query_one("#right-pane").mount(AccountDetailView())
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
CSS:
|
|
72
|
+
The screen includes default styling for the Harlequin layout:
|
|
73
|
+
- Black background (#000000) for the entire screen
|
|
74
|
+
- Primary blue borders (#005CB8) for panes
|
|
75
|
+
- 25% width for left pane, 75% width for right pane
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
CSS = """
|
|
79
|
+
HarlequinScreen {
|
|
80
|
+
background: #000000;
|
|
81
|
+
layers: base toasts;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#harlequin-container {
|
|
85
|
+
width: 100%;
|
|
86
|
+
height: 100%;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#left-pane {
|
|
90
|
+
width: 25%;
|
|
91
|
+
border: solid #005CB8;
|
|
92
|
+
background: #000000;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#right-pane {
|
|
96
|
+
width: 75%;
|
|
97
|
+
border: solid #005CB8;
|
|
98
|
+
background: #000000;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
#toast-container {
|
|
102
|
+
width: 100%;
|
|
103
|
+
height: auto;
|
|
104
|
+
dock: top;
|
|
105
|
+
align: right top;
|
|
106
|
+
layer: toasts;
|
|
107
|
+
}
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
def __init__(
|
|
111
|
+
self,
|
|
112
|
+
*,
|
|
113
|
+
ctx: TUIContext | None = None,
|
|
114
|
+
name: str | None = None,
|
|
115
|
+
id: str | None = None,
|
|
116
|
+
classes: str | None = None,
|
|
117
|
+
) -> None:
|
|
118
|
+
"""Initialize the Harlequin screen.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
ctx: Optional TUI context for accessing services (keybinds, theme, toasts, clipboard).
|
|
122
|
+
name: Optional name for the screen.
|
|
123
|
+
id: Optional ID for the screen.
|
|
124
|
+
classes: Optional CSS classes for the screen.
|
|
125
|
+
"""
|
|
126
|
+
super().__init__(name=name, id=id, classes=classes)
|
|
127
|
+
self._ctx: TUIContext | None = ctx
|
|
128
|
+
|
|
129
|
+
def compose(self) -> Any:
|
|
130
|
+
"""Compose the Harlequin layout with left and right panes.
|
|
131
|
+
|
|
132
|
+
This method creates the base 25/75 split layout. Subclasses should
|
|
133
|
+
call `super().compose()` and then add their specific widgets to the
|
|
134
|
+
left and right panes.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
ComposeResult yielding the base layout containers.
|
|
138
|
+
"""
|
|
139
|
+
if Horizontal is None or Vertical is None or Container is None:
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
# Main container with horizontal split (25/75)
|
|
143
|
+
yield Horizontal(
|
|
144
|
+
Vertical(id="left-pane"),
|
|
145
|
+
Vertical(id="right-pane"),
|
|
146
|
+
id="harlequin-container",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Toast container for notifications
|
|
150
|
+
if Toast is not None and Container is not None:
|
|
151
|
+
yield Container(Toast(), id="toast-container")
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def ctx(self) -> TUIContext | None:
|
|
155
|
+
"""Get the TUI context if available.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
TUIContext instance or None if not provided.
|
|
159
|
+
"""
|
|
160
|
+
return self._ctx
|
|
@@ -71,7 +71,7 @@ class TerminalCapabilities:
|
|
|
71
71
|
return "light" if luminance > 0.5 else "dark"
|
|
72
72
|
|
|
73
73
|
@classmethod
|
|
74
|
-
async def detect(cls) -> TerminalCapabilities:
|
|
74
|
+
async def detect(cls, *, detect_osc11: bool = True) -> TerminalCapabilities:
|
|
75
75
|
"""Detect terminal capabilities asynchronously with fast timeout.
|
|
76
76
|
|
|
77
77
|
This method performs capability detection including OSC 11 background
|
|
@@ -80,6 +80,9 @@ class TerminalCapabilities:
|
|
|
80
80
|
if the terminal doesn't respond within the timeout; use
|
|
81
81
|
detect_terminal_background() for full 1-second timeout when needed.
|
|
82
82
|
|
|
83
|
+
Args:
|
|
84
|
+
detect_osc11: When False, skip OSC 11 background detection.
|
|
85
|
+
|
|
83
86
|
Returns:
|
|
84
87
|
TerminalCapabilities instance with detected capabilities.
|
|
85
88
|
"""
|
|
@@ -93,8 +96,10 @@ class TerminalCapabilities:
|
|
|
93
96
|
mouse = tty_available and term not in ("dumb", "")
|
|
94
97
|
truecolor = colorterm in ("truecolor", "24bit")
|
|
95
98
|
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
osc11_bg: str | None = None
|
|
100
|
+
if detect_osc11 and tty_available and sys.stdin.isatty():
|
|
101
|
+
# OSC 11 detection: use fast path (<100ms timeout)
|
|
102
|
+
osc11_bg = await _detect_osc11_fast()
|
|
98
103
|
|
|
99
104
|
return cls(
|
|
100
105
|
tty=tty_available,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
glaip_sdk/__init__.py,sha256=YpePGKbCjwqCwvb8yig8cc64z876ch1oSlTlu-CiWfs,1722
|
|
2
2
|
glaip_sdk/_version.py,sha256=5CHGCxx_36fgmMWuEx6jJ2CzzM-i9eBFyQWFwBi23XE,2259
|
|
3
|
-
glaip_sdk/branding.py,sha256=
|
|
3
|
+
glaip_sdk/branding.py,sha256=uF_-c-cg_rFjzJr0NibLiE1Dvv0DpXBXN63wl-Ej88c,11651
|
|
4
4
|
glaip_sdk/exceptions.py,sha256=iAChFClkytXRBLP0vZq1_YjoZxA9i4m4bW1gDLiGR1g,2321
|
|
5
5
|
glaip_sdk/icons.py,sha256=J5THz0ReAmDwIiIooh1_G3Le-mwTJyEjhJDdJ13KRxM,524
|
|
6
6
|
glaip_sdk/rich_components.py,sha256=44Z0V1ZQleVh9gUDGwRR5mriiYFnVGOhm7fFxZYbP8c,4052
|
|
@@ -78,18 +78,20 @@ glaip_sdk/cli/slash/accounts_shared.py,sha256=Mq5HxlI0YsVEQ0KKISWvyBZhzOFFWCzwRb
|
|
|
78
78
|
glaip_sdk/cli/slash/agent_session.py,sha256=tuVOme-NbEyr6rwJvsBEKZYWQmsaRf4piJeRvIGu0ns,11384
|
|
79
79
|
glaip_sdk/cli/slash/prompt.py,sha256=q4f1c2zr7ZMUeO6AgOBF2Nz4qgMOXrVPt6WzPRQMbAM,8501
|
|
80
80
|
glaip_sdk/cli/slash/remote_runs_controller.py,sha256=iLl4a-mu9QU7dcedgEILewPtDIVtFUJkbKGtcx1F66U,21445
|
|
81
|
-
glaip_sdk/cli/slash/session.py,sha256=
|
|
81
|
+
glaip_sdk/cli/slash/session.py,sha256=YJ7UIeWyged1znmBVnGweOzH2l4NKeF5lT9VGdDvQWo,75998
|
|
82
82
|
glaip_sdk/cli/slash/tui/__init__.py,sha256=oBUzeoslYwPKVlhqhgg4I7480b77vQNc9ec0NgdTC1s,977
|
|
83
|
-
glaip_sdk/cli/slash/tui/accounts.tcss,sha256=
|
|
84
|
-
glaip_sdk/cli/slash/tui/accounts_app.py,sha256=
|
|
83
|
+
glaip_sdk/cli/slash/tui/accounts.tcss,sha256=eqFMAuN3PI3YVNDUbrCQpO1-Ko5WZpempPq75_Aejq0,2159
|
|
84
|
+
glaip_sdk/cli/slash/tui/accounts_app.py,sha256=thS4r1NELB9K_OoEI4uJdDGSkRyhzek_2Y0k0yoPvss,71799
|
|
85
85
|
glaip_sdk/cli/slash/tui/background_tasks.py,sha256=SAe1mV2vXB3mJcSGhelU950vf8Lifjhws9iomyIVFKw,2422
|
|
86
86
|
glaip_sdk/cli/slash/tui/clipboard.py,sha256=7fEshhTwHYaj-n7n0W0AsWTs8W0RLZw_9luXxrFTrtw,6227
|
|
87
|
-
glaip_sdk/cli/slash/tui/context.py,sha256=
|
|
87
|
+
glaip_sdk/cli/slash/tui/context.py,sha256=v7XOdRtk5AQ4ZE-QWUhc1s9xVROu8_JjdjVnKx0X9p8,3270
|
|
88
88
|
glaip_sdk/cli/slash/tui/keybind_registry.py,sha256=_rK05BxTxNudYc4iJ9gDxpgeUkjDAq8rarIT-9A-jyM,6739
|
|
89
89
|
glaip_sdk/cli/slash/tui/loading.py,sha256=nW5pv_Tnl9FUOPR3Qf2O5gt1AGHSo3b5-Uofg34F6AE,1909
|
|
90
90
|
glaip_sdk/cli/slash/tui/remote_runs_app.py,sha256=DOmUHeaBg8puERn-htDnYAJgcUHETl457HamQkd0nxY,28550
|
|
91
|
-
glaip_sdk/cli/slash/tui/terminal.py,sha256=
|
|
91
|
+
glaip_sdk/cli/slash/tui/terminal.py,sha256=ZAC3sB17TGpl-GFeRVm_nI8DQTN3pyti3ynlZ41wT_A,12323
|
|
92
92
|
glaip_sdk/cli/slash/tui/toast.py,sha256=QLL6BBBMjEagzpSEPf3PNBNzQG_EdN5JeAigk66AjVs,11920
|
|
93
|
+
glaip_sdk/cli/slash/tui/layouts/__init__.py,sha256=KT77pZHa7Wz84QlHYT2mfhQ_AXUA-T0eHv_HtAvc1ac,473
|
|
94
|
+
glaip_sdk/cli/slash/tui/layouts/harlequin.py,sha256=pR5BHdWCVK0QZCyr8q6O-vCL_MTZKjMVASdYzkFUkt4,5122
|
|
93
95
|
glaip_sdk/cli/slash/tui/theme/__init__.py,sha256=rtM2ik83YNCRcI1qh_Sf3rnxco2OvCNNT3NbHY6cLvw,432
|
|
94
96
|
glaip_sdk/cli/slash/tui/theme/catalog.py,sha256=G52eU3h8YI9D8XUALVg1KVZ4Lq65VnZdgPS3F_P7XLE,2544
|
|
95
97
|
glaip_sdk/cli/slash/tui/theme/manager.py,sha256=LBnxEMIwz-8cAlZGYk5tIoAJbOJyGYsmDlyuGJ-LlX4,3945
|
|
@@ -210,8 +212,8 @@ glaip_sdk/utils/rendering/steps/format.py,sha256=Chnq7OBaj8XMeBntSBxrX5zSmrYeGcO
|
|
|
210
212
|
glaip_sdk/utils/rendering/steps/manager.py,sha256=BiBmTeQMQhjRMykgICXsXNYh1hGsss-fH9BIGVMWFi0,13194
|
|
211
213
|
glaip_sdk/utils/rendering/viewer/__init__.py,sha256=XrxmE2cMAozqrzo1jtDFm8HqNtvDcYi2mAhXLXn5CjI,457
|
|
212
214
|
glaip_sdk/utils/rendering/viewer/presenter.py,sha256=mlLMTjnyeyPVtsyrAbz1BJu9lFGQSlS-voZ-_Cuugv0,5725
|
|
213
|
-
glaip_sdk-0.7.
|
|
214
|
-
glaip_sdk-0.7.
|
|
215
|
-
glaip_sdk-0.7.
|
|
216
|
-
glaip_sdk-0.7.
|
|
217
|
-
glaip_sdk-0.7.
|
|
215
|
+
glaip_sdk-0.7.11.dist-info/METADATA,sha256=gciVvZkveuvBnlisXPXr-XdATU28Dm0PPZpzfsqaTAk,8528
|
|
216
|
+
glaip_sdk-0.7.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
217
|
+
glaip_sdk-0.7.11.dist-info/entry_points.txt,sha256=NkhO6FfgX9Zrjn63GuKphf-dLw7KNJvucAcXc7P3aMk,54
|
|
218
|
+
glaip_sdk-0.7.11.dist-info/top_level.txt,sha256=td7yXttiYX2s94-4wFhv-5KdT0rSZ-pnJRSire341hw,10
|
|
219
|
+
glaip_sdk-0.7.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|