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.
@@ -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
- # OSC 11 detection: use fast path (<100ms timeout)
97
- osc11_bg: str | None = await _detect_osc11_fast()
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
  Metadata-Version: 2.4
2
2
  Name: glaip-sdk
3
- Version: 0.7.10
3
+ Version: 0.7.11
4
4
  Summary: Python SDK and CLI for GL AIP (GDP Labs AI Agent Package) - Build, run, and manage AI agents
5
5
  Author-email: Raymond Christopher <raymond.christopher@gdplabs.id>
6
6
  License: MIT
@@ -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=tLqYCIHMkUf8p2smpuAGNptwaKUN38G4mlh0A0DOl_w,7823
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=Zn2hXND_Tfameh_PI8g4VIMd7GPWxwhtPNMN9p6cF7M,65081
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=w_9w2dXxjopMed-3_SWZ3KJiOYNa8hReW6DEKRprcic,1344
84
- glaip_sdk/cli/slash/tui/accounts_app.py,sha256=hYpxOTG3zwS_t41WaCv9K-fPYL6b380EeAUCjNUtbJo,43520
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=XgHsXPl8LDDwIueP_jhP6xqpx_zHOk0FF19rWob_z5Q,3128
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=iC31XChTL34gXY6vXdSIX3HmD36tuA9EYTPZ2Sn4uOI,12108
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.10.dist-info/METADATA,sha256=2UcLS7TmXIdgiLE6Ab3U_FtpompLMq4bshiGrqRi3jI,8528
214
- glaip_sdk-0.7.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
215
- glaip_sdk-0.7.10.dist-info/entry_points.txt,sha256=NkhO6FfgX9Zrjn63GuKphf-dLw7KNJvucAcXc7P3aMk,54
216
- glaip_sdk-0.7.10.dist-info/top_level.txt,sha256=td7yXttiYX2s94-4wFhv-5KdT0rSZ-pnJRSire341hw,10
217
- glaip_sdk-0.7.10.dist-info/RECORD,,
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,,