feat(ui): show queued interactive messages above the composer

A queued message now appears in a pending strip above the input box (driven by
InteractiveQueueChanged), not optimistically in the transcript. The transcript
user line is added on delivery via InteractiveMessageSent. SessionTerminalView
gains QueuedMessages/HasQueuedMessages styled props (Mission Control); WorkConsole
binds Monitor.* (task detail). Adds session.composer.queued (en/de).
This commit is contained in:
Mika Kuns
2026-06-26 11:04:25 +02:00
parent 84034e8395
commit 7c9ff18ced
8 changed files with 250 additions and 70 deletions

View File

@@ -263,41 +263,71 @@
Command="{Binding RejectReviewCommand}" />
</Grid>
<!-- Interactive composer — chat with a live in-app session; shell-prompt style,
only while an interactive session is running for this task. -->
<Grid DockPanel.Dock="Bottom"
IsVisible="{Binding Monitor.IsInteractiveLive}"
ColumnDefinitions="Auto,*,Auto,Auto"
Margin="12,2,12,8">
<TextBlock Grid.Column="0" Text="&#x276F;"
<!-- Interactive composer + queued strip — chat with a live in-app session -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Vertical">
<!-- Queued messages strip -->
<Border IsVisible="{Binding Monitor.HasQueuedMessages}"
BorderBrush="{DynamicResource LineBrush}"
BorderThickness="0,1,0,0"
Padding="12,4">
<StackPanel Spacing="2">
<TextBlock Classes="meta"
Text="{loc:Tr session.composer.queued}"
Foreground="{DynamicResource TextMuteBrush}" />
<ItemsControl ItemsSource="{Binding Monitor.QueuedMessages}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Spacing="6">
<TextBlock Text="⧗"
Foreground="{DynamicResource TextMuteBrush}"
FontFamily="{StaticResource MonoFont}"
FontSize="{StaticResource FontSizeMono}"
VerticalAlignment="Center" />
<TextBlock Text="{Binding}"
Foreground="{DynamicResource TextDimBrush}"
FontFamily="{StaticResource MonoFont}"
FontSize="{StaticResource FontSizeMono}"
TextTrimming="CharacterEllipsis" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
<!-- Composer input row -->
<Grid IsVisible="{Binding Monitor.IsInteractiveLive}"
ColumnDefinitions="Auto,*,Auto,Auto"
Margin="12,2,12,8">
<TextBlock Grid.Column="0" Text="&#x276F;"
FontFamily="{StaticResource MonoFont}"
FontSize="{StaticResource FontSizeMono}"
Foreground="{DynamicResource AccentBrush}"
VerticalAlignment="Center" Margin="0,0,8,0" />
<TextBox Grid.Column="1"
Classes="review-prompt"
Text="{Binding Monitor.ComposerDraft, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
AcceptsReturn="False"
TextWrapping="Wrap"
MaxHeight="160"
PlaceholderText="{loc:Tr session.composer.placeholder}"
VerticalContentAlignment="Center"
FontFamily="{StaticResource MonoFont}"
FontSize="{StaticResource FontSizeMono}"
Foreground="{DynamicResource AccentBrush}"
VerticalAlignment="Center" Margin="0,0,8,0" />
<TextBox Grid.Column="1"
Classes="review-prompt"
Text="{Binding Monitor.ComposerDraft, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
AcceptsReturn="False"
TextWrapping="Wrap"
MaxHeight="160"
PlaceholderText="{loc:Tr session.composer.placeholder}"
VerticalContentAlignment="Center"
FontFamily="{StaticResource MonoFont}"
FontSize="{StaticResource FontSizeMono}">
<TextBox.KeyBindings>
<KeyBinding Gesture="Enter" Command="{Binding Monitor.SubmitComposerCommand}" />
</TextBox.KeyBindings>
</TextBox>
<Button Grid.Column="2" Classes="prompt-action"
VerticalAlignment="Center" Margin="12,0,0,0"
Command="{Binding Monitor.InterruptInteractiveCommand}"
ToolTip.Tip="{loc:Tr session.composer.interrupt}">
<PathIcon Data="{StaticResource Icon.Stop}" Width="10" Height="10"/>
</Button>
<Button Grid.Column="3" Classes="prompt-action accent" Content="[Send]"
VerticalAlignment="Center" Margin="4,0,0,0"
Command="{Binding Monitor.SubmitComposerCommand}" />
</Grid>
FontSize="{StaticResource FontSizeMono}">
<TextBox.KeyBindings>
<KeyBinding Gesture="Enter" Command="{Binding Monitor.SubmitComposerCommand}" />
</TextBox.KeyBindings>
</TextBox>
<Button Grid.Column="2" Classes="prompt-action"
VerticalAlignment="Center" Margin="12,0,0,0"
Command="{Binding Monitor.InterruptInteractiveCommand}"
ToolTip.Tip="{loc:Tr session.composer.interrupt}">
<PathIcon Data="{StaticResource Icon.Stop}" Width="10" Height="10"/>
</Button>
<Button Grid.Column="3" Classes="prompt-action accent" Content="[Send]"
VerticalAlignment="Center" Margin="4,0,0,0"
Command="{Binding Monitor.SubmitComposerCommand}" />
</Grid>
</StackPanel>
<ScrollViewer Name="LogScroll"
VerticalScrollBarVisibility="Visible"