feat(interactive): host task-based ConPTY sessions in Command Center
Adds an 'Open ConPTY session' entry that fetches a task's launch spec and hosts an embedded ConPTY terminal as a Mission Control pane, coexisting with the streamed-log monitor panes (streaming stack untouched). Introduces IMissionControlPane + ConPtyPaneViewModel, a non-destructive Panes mirror (Monitors prefix + ConPtySessions suffix) so unrelated monitor churn never tears down a live terminal, and a grid<->tabs layout toggle. Launch failures surface via the footer error strip.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using ClaudeDo.Ui.Services;
|
||||
|
||||
namespace ClaudeDo.Ui.ViewModels.MissionControl;
|
||||
|
||||
/// <summary>
|
||||
/// Command Center pane hosting an embedded ConPTY terminal for one task's interactive Claude
|
||||
/// session (task-based only — no ad-hoc/free sessions yet). Distinct from the streamed-log
|
||||
/// <see cref="ClaudeDo.Ui.ViewModels.Islands.TaskMonitorViewModel"/> pane; the two coexist until
|
||||
/// the streaming interactive stack is removed.
|
||||
/// </summary>
|
||||
public sealed partial class ConPtyPaneViewModel : ViewModelBase, IMissionControlPane, IDisposable
|
||||
{
|
||||
public string TaskId { get; }
|
||||
|
||||
[ObservableProperty] private string _displayTitle;
|
||||
|
||||
public InteractiveTerminalViewModel Terminal { get; } = new();
|
||||
|
||||
/// <summary>Raised when the terminal failed to start — the host surfaces this via the footer error strip.</summary>
|
||||
public event Action<string>? ErrorReported;
|
||||
|
||||
/// <summary>Set by the host (Mission Control) to remove this pane from its collection.</summary>
|
||||
public Action<ConPtyPaneViewModel>? CloseRequested { get; set; }
|
||||
|
||||
public ConPtyPaneViewModel(string taskId, string displayTitle, TerminalLaunchDescriptor descriptor)
|
||||
{
|
||||
TaskId = taskId;
|
||||
_displayTitle = displayTitle;
|
||||
Terminal.PropertyChanged += OnTerminalPropertyChanged;
|
||||
Terminal.Start(descriptor);
|
||||
}
|
||||
|
||||
private void OnTerminalPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(InteractiveTerminalViewModel.StartError) && Terminal.StartError is { Length: > 0 } error)
|
||||
ErrorReported?.Invoke(error);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Close() => CloseRequested?.Invoke(this);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Terminal.PropertyChanged -= OnTerminalPropertyChanged;
|
||||
Terminal.Kill();
|
||||
Terminal.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace ClaudeDo.Ui.ViewModels.MissionControl;
|
||||
|
||||
/// <summary>
|
||||
/// Common contract for anything hosted as a pane in the Command Center — implemented by both
|
||||
/// the streamed-log <see cref="ClaudeDo.Ui.ViewModels.Islands.TaskMonitorViewModel"/> and the
|
||||
/// embedded ConPTY <see cref="ConPtyPaneViewModel"/> — so the layout toggle (grid/tabs) can
|
||||
/// bind one heterogeneous pane collection.
|
||||
/// </summary>
|
||||
public interface IMissionControlPane
|
||||
{
|
||||
string DisplayTitle { get; }
|
||||
}
|
||||
Reference in New Issue
Block a user