mirror of
https://github.com/mistralai/mistral-vibe
synced 2026-04-26 01:24:55 +02:00
Co-authored-by: Quentin Torroba <quentin.torroba@mistral.ai> Co-authored-by: Clement Sirieix <clem.sirieix@gmail.com> Co-authored-by: Kim-Adeline Miguel <kimadeline.miguel@mistral.ai> Co-authored-by: Mistral Vibe <vibe@mistral.ai>
123 lines
4.3 KiB
Python
123 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import ClassVar
|
|
|
|
from textual import events
|
|
from textual.app import ComposeResult
|
|
from textual.binding import Binding, BindingType
|
|
from textual.containers import Container, Vertical
|
|
from textual.message import Message
|
|
from textual.widgets import Input, Static
|
|
|
|
from vibe.cli.textual_ui.widgets.no_markup_static import NoMarkupStatic
|
|
from vibe.cli.textual_ui.widgets.vscode_compat import VscodeCompatInput
|
|
from vibe.core.proxy_setup import (
|
|
SUPPORTED_PROXY_VARS,
|
|
get_current_proxy_settings,
|
|
set_proxy_var,
|
|
unset_proxy_var,
|
|
)
|
|
|
|
|
|
class ProxySetupApp(Container):
|
|
can_focus = True
|
|
can_focus_children = True
|
|
|
|
BINDINGS: ClassVar[list[BindingType]] = [
|
|
Binding("up", "focus_previous", "Up", show=False),
|
|
Binding("down", "focus_next", "Down", show=False),
|
|
]
|
|
|
|
class ProxySetupClosed(Message):
|
|
def __init__(self, saved: bool, error: str | None = None) -> None:
|
|
super().__init__()
|
|
self.saved = saved
|
|
self.error = error
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__(id="proxysetup-app")
|
|
self.inputs: dict[str, Input] = {}
|
|
self.initial_values: dict[str, str | None] = {}
|
|
|
|
def compose(self) -> ComposeResult:
|
|
self.initial_values = get_current_proxy_settings()
|
|
|
|
with Vertical(id="proxysetup-content"):
|
|
yield NoMarkupStatic("Proxy Configuration", classes="settings-title")
|
|
|
|
for key, description in SUPPORTED_PROXY_VARS.items():
|
|
yield Static(f"[bold ansi_blue]{key}[/]", classes="proxy-label-line")
|
|
|
|
initial_value = self.initial_values.get(key) or ""
|
|
input_widget = VscodeCompatInput(
|
|
value=initial_value,
|
|
placeholder=description,
|
|
id=f"proxy-input-{key}",
|
|
classes="proxy-input",
|
|
)
|
|
self.inputs[key] = input_widget
|
|
yield input_widget
|
|
|
|
yield NoMarkupStatic(
|
|
"↑↓ navigate Enter save & exit ESC cancel", classes="settings-help"
|
|
)
|
|
|
|
def focus(self, scroll_visible: bool = True) -> ProxySetupApp:
|
|
"""Override focus to focus the first input widget."""
|
|
if self.inputs:
|
|
first_input = list(self.inputs.values())[0]
|
|
first_input.focus(scroll_visible=scroll_visible)
|
|
else:
|
|
super().focus(scroll_visible=scroll_visible)
|
|
return self
|
|
|
|
def action_focus_next(self) -> None:
|
|
inputs = list(self.inputs.values())
|
|
focused = self.screen.focused
|
|
if focused is not None and isinstance(focused, Input) and focused in inputs:
|
|
idx = inputs.index(focused)
|
|
next_idx = (idx + 1) % len(inputs)
|
|
inputs[next_idx].focus()
|
|
|
|
def action_focus_previous(self) -> None:
|
|
inputs = list(self.inputs.values())
|
|
focused = self.screen.focused
|
|
if focused is not None and isinstance(focused, Input) and focused in inputs:
|
|
idx = inputs.index(focused)
|
|
prev_idx = (idx - 1) % len(inputs)
|
|
inputs[prev_idx].focus()
|
|
|
|
def on_input_submitted(self, _event: Input.Submitted) -> None:
|
|
self._save_and_close()
|
|
|
|
def on_blur(self, _event: events.Blur) -> None:
|
|
self.call_after_refresh(self._refocus_if_needed)
|
|
|
|
def on_input_blurred(self, _event: Input.Blurred) -> None:
|
|
self.call_after_refresh(self._refocus_if_needed)
|
|
|
|
def _refocus_if_needed(self) -> None:
|
|
if self.has_focus or any(inp.has_focus for inp in self.inputs.values()):
|
|
return
|
|
self.focus()
|
|
|
|
def _save_and_close(self) -> None:
|
|
try:
|
|
for key, input_widget in self.inputs.items():
|
|
new_value = input_widget.value.strip()
|
|
old_value = self.initial_values.get(key) or ""
|
|
|
|
if new_value != old_value:
|
|
if new_value:
|
|
set_proxy_var(key, new_value)
|
|
else:
|
|
unset_proxy_var(key)
|
|
except Exception as e:
|
|
self.post_message(self.ProxySetupClosed(saved=False, error=str(e)))
|
|
return
|
|
|
|
self.post_message(self.ProxySetupClosed(saved=True))
|
|
|
|
def action_close(self) -> None:
|
|
self.post_message(self.ProxySetupClosed(saved=False))
|