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.
- {aline_ai-0.5.13.dist-info → aline_ai-0.6.1.dist-info}/METADATA +1 -1
- {aline_ai-0.5.13.dist-info → aline_ai-0.6.1.dist-info}/RECORD +24 -19
- realign/__init__.py +1 -1
- realign/auth.py +21 -0
- realign/cli.py +293 -6
- realign/commands/auth.py +110 -0
- realign/commands/import_shares.py +6 -0
- realign/commands/watcher.py +8 -0
- realign/commands/worker.py +8 -0
- realign/dashboard/app.py +68 -6
- realign/dashboard/backends/__init__.py +6 -0
- realign/dashboard/backends/iterm2.py +599 -0
- realign/dashboard/backends/kitty.py +372 -0
- realign/dashboard/layout.py +320 -0
- realign/dashboard/terminal_backend.py +110 -0
- realign/dashboard/widgets/events_table.py +44 -5
- realign/dashboard/widgets/sessions_table.py +76 -16
- realign/dashboard/widgets/terminal_panel.py +566 -104
- realign/watcher_daemon.py +11 -0
- realign/worker_daemon.py +11 -0
- {aline_ai-0.5.13.dist-info → aline_ai-0.6.1.dist-info}/WHEEL +0 -0
- {aline_ai-0.5.13.dist-info → aline_ai-0.6.1.dist-info}/entry_points.txt +0 -0
- {aline_ai-0.5.13.dist-info → aline_ai-0.6.1.dist-info}/licenses/LICENSE +0 -0
- {aline_ai-0.5.13.dist-info → aline_ai-0.6.1.dist-info}/top_level.txt +0 -0
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
|
-
|
|
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:
|