aline-ai 0.5.13__py3-none-any.whl → 0.6.1__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.
realign/dashboard/app.py CHANGED
@@ -1,5 +1,6 @@
1
1
  """Aline Dashboard - Main Application."""
2
2
 
3
+ import os
3
4
  import subprocess
4
5
  import sys
5
6
  import time
@@ -22,6 +23,9 @@ from .widgets import (
22
23
  TerminalPanel,
23
24
  )
24
25
 
26
+ # Environment variable to control terminal mode
27
+ ENV_TERMINAL_MODE = "ALINE_TERMINAL_MODE"
28
+
25
29
  # Set up dashboard logger - logs to ~/.aline/.logs/dashboard.log
26
30
  logger = setup_logger("realign.dashboard", "dashboard.log")
27
31
 
@@ -74,15 +78,31 @@ class AlineDashboard(App):
74
78
 
75
79
  _quit_confirm_window_s: float = 1.2
76
80
 
77
- def __init__(self, dev_mode: bool = False):
81
+ def __init__(self, dev_mode: bool = False, use_native_terminal: bool | None = None):
78
82
  """Initialize the dashboard.
79
83
 
80
84
  Args:
81
85
  dev_mode: If True, shows developer tabs (Watcher, Worker).
86
+ use_native_terminal: If True, use native terminal backend (iTerm2/Kitty).
87
+ If False, use tmux.
88
+ If None (default), auto-detect from ALINE_TERMINAL_MODE env var.
82
89
  """
83
90
  super().__init__()
84
91
  self.dev_mode = dev_mode
85
- logger.info(f"AlineDashboard initialized (dev_mode={dev_mode})")
92
+ self.use_native_terminal = use_native_terminal
93
+ self._native_terminal_mode = self._detect_native_mode()
94
+ logger.info(
95
+ f"AlineDashboard initialized (dev_mode={dev_mode}, "
96
+ f"native_terminal={self._native_terminal_mode})"
97
+ )
98
+
99
+ def _detect_native_mode(self) -> bool:
100
+ """Detect if native terminal mode should be used."""
101
+ if self.use_native_terminal is not None:
102
+ return self.use_native_terminal
103
+
104
+ mode = os.environ.get(ENV_TERMINAL_MODE, "").strip().lower()
105
+ return mode in {"native", "iterm2", "iterm", "kitty"}
86
106
 
87
107
  def compose(self) -> ComposeResult:
88
108
  """Compose the dashboard layout."""
@@ -92,7 +112,7 @@ class AlineDashboard(App):
92
112
  tab_ids = self._tab_ids()
93
113
  with TabbedContent(initial=tab_ids[0] if tab_ids else "terminal"):
94
114
  with TabPane("Agents", id="terminal"):
95
- yield TerminalPanel()
115
+ yield TerminalPanel(use_native_terminal=self.use_native_terminal)
96
116
  if self.dev_mode:
97
117
  with TabPane("Watcher", id="watcher"):
98
118
  yield WatcherPanel()
@@ -125,11 +145,47 @@ class AlineDashboard(App):
125
145
  # Check for system theme changes every 2 seconds
126
146
  self.set_interval(2, self._sync_theme)
127
147
  self._quit_confirm_deadline: float | None = None
148
+
149
+ # Set up side-by-side layout for native terminal mode
150
+ if self._native_terminal_mode:
151
+ self._setup_native_terminal_layout()
152
+
128
153
  logger.info("on_mount() completed successfully")
129
154
  except Exception as e:
130
155
  logger.error(f"on_mount() failed: {e}\n{traceback.format_exc()}")
131
156
  raise
132
157
 
158
+ def _setup_native_terminal_layout(self) -> None:
159
+ """Set up side-by-side layout for Dashboard and native terminal."""
160
+ # Skip if using iTerm2 split pane mode (already set up by CLI)
161
+ if os.environ.get("ALINE_ITERM2_RIGHT_PANE"):
162
+ logger.info("Using iTerm2 split pane mode, skipping window layout")
163
+ return
164
+
165
+ try:
166
+ from .layout import setup_side_by_side_layout
167
+
168
+ # Determine the target terminal app
169
+ mode = os.environ.get(ENV_TERMINAL_MODE, "").strip().lower()
170
+ if mode == "kitty":
171
+ terminal_app = "Kitty"
172
+ else:
173
+ terminal_app = "iTerm2"
174
+
175
+ # Set up side-by-side layout (Dashboard on left, terminal on right)
176
+ success = setup_side_by_side_layout(
177
+ terminal_app=terminal_app,
178
+ dashboard_on_left=True,
179
+ dashboard_width_percent=40, # Dashboard takes 40%, terminal takes 60%
180
+ )
181
+
182
+ if success:
183
+ logger.info(f"Set up side-by-side layout with {terminal_app}")
184
+ else:
185
+ logger.warning("Failed to set up side-by-side layout")
186
+ except Exception as e:
187
+ logger.warning(f"Could not set up native terminal layout: {e}")
188
+
133
189
  def _sync_theme(self) -> None:
134
190
  """Sync app theme with system theme."""
135
191
  target_theme = "textual-dark" if _detect_system_dark_mode() else "textual-light"
@@ -357,11 +413,17 @@ class AlineDashboard(App):
357
413
  self.notify(f"Loaded {what} into {context_id}", title="Load Context", timeout=3)
358
414
 
359
415
 
360
- def run_dashboard() -> None:
361
- """Run the Aline Dashboard."""
416
+ def run_dashboard(use_native_terminal: bool | None = None) -> None:
417
+ """Run the Aline Dashboard.
418
+
419
+ Args:
420
+ use_native_terminal: If True, use native terminal backend (iTerm2/Kitty).
421
+ If False, use tmux.
422
+ If None (default), auto-detect from ALINE_TERMINAL_MODE env var.
423
+ """
362
424
  logger.info("Starting Aline Dashboard")
363
425
  try:
364
- app = AlineDashboard()
426
+ app = AlineDashboard(use_native_terminal=use_native_terminal)
365
427
  app.run()
366
428
  logger.info("Aline Dashboard exited normally")
367
429
  except Exception as e:
@@ -0,0 +1,6 @@
1
+ """Terminal backends for native terminal support."""
2
+
3
+ from .iterm2 import ITermBackend
4
+ from .kitty import KittyBackend
5
+
6
+ __all__ = ["ITermBackend", "KittyBackend"]