Skip to content

Commit 8714381

Browse files
committed
Merge branch 'pr-519'
# Conflicts: # src/OpenClaw.Tray.WinUI/Pages/UsagePage.xaml.cs
2 parents 07b1910 + ae85282 commit 8714381

6 files changed

Lines changed: 77 additions & 45 deletions

File tree

src/OpenClaw.Tray.WinUI/Pages/AgentEventsPage.xaml

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@
1616

1717
<StackPanel Grid.Row="0" Spacing="4" Margin="0,0,0,12">
1818
<StackPanel Orientation="Horizontal" Spacing="8">
19-
<TextBlock x:Uid="AgentEventsPage_TextBlock_18" Text="Agent Events"
20-
Style="{StaticResource TitleTextBlockStyle}"/>
21-
<TextBlock x:Name="CountText" Text="(0)"
22-
VerticalAlignment="Bottom" Margin="0,0,0,6"
19+
<TextBlock x:Uid="AgentEventsPage_TextBlock_18" Text="Event Stream" Style="{StaticResource TitleTextBlockStyle}"/>
20+
<Border x:Name="LiveBadge" CornerRadius="4" Padding="6,2,8,3" VerticalAlignment="Center"
21+
Background="#20FF4444">
22+
<StackPanel Orientation="Horizontal" Spacing="4">
23+
<Ellipse x:Name="LiveDot" Width="6" Height="6" Fill="#FFFF4444" VerticalAlignment="Center"/>
24+
<TextBlock x:Name="LiveText" Text="Live" FontSize="11" FontWeight="SemiBold"
25+
Foreground="#FFFF4444" VerticalAlignment="Center"/>
26+
</StackPanel>
27+
</Border>
28+
<TextBlock x:Name="CountText" Text="(0)" VerticalAlignment="Center"
2329
Style="{StaticResource CaptionTextBlockStyle}"
2430
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
2531
</StackPanel>
@@ -51,21 +57,7 @@
5157
</Button>
5258
</Grid>
5359

54-
<ScrollViewer Grid.Row="2" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled"
55-
Margin="0,0,0,8">
56-
<SelectorBar x:Name="FilterSelector"
57-
SelectionChanged="OnFilterSelectionChanged">
58-
<SelectorBarItem x:Uid="FilterAllButton" x:Name="FilterAllButton" Text="All" Tag="all" IsSelected="True"/>
59-
<SelectorBarItem x:Uid="AgentEventsPage_ToggleButton_36" Text="Tool" Tag="tool"/>
60-
<SelectorBarItem x:Uid="AgentEventsPage_ToggleButton_37" Text="Assistant" Tag="assistant"/>
61-
<SelectorBarItem x:Uid="AgentEventsPage_ToggleButton_38" Text="Error" Tag="error"/>
62-
<SelectorBarItem x:Uid="AgentEventsPage_ToggleButton_39" Text="Lifecycle" Tag="lifecycle"/>
63-
<SelectorBarItem x:Uid="AgentEventsPage_ToggleButton_40" Text="Plan" Tag="plan"/>
64-
<SelectorBarItem x:Uid="AgentEventsPage_ToggleButton_41" Text="Approval" Tag="approval"/>
65-
<SelectorBarItem x:Uid="AgentEventsPage_ToggleButton_42" Text="Thinking" Tag="thinking"/>
66-
<SelectorBarItem x:Uid="AgentEventsPage_ToggleButton_43" Text="Patch" Tag="patch"/>
67-
</SelectorBar>
68-
</ScrollViewer>
60+
<!-- Filter bar — removed; agent dropdown + live badge provide enough context -->
6961

7062
<ListView x:Name="EventsList" Grid.Row="3"
7163
SelectionMode="None"
@@ -142,16 +134,14 @@
142134
</ListView.ItemTemplate>
143135
</ListView>
144136

145-
<StackPanel x:Name="EmptyState" Grid.Row="3"
146-
VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="12">
147-
<FontIcon Glyph="{x:Bind helpers:FluentIconCatalog.AgentEvents, Mode=OneTime}"
148-
FontSize="48" IsTextScaleFactorEnabled="False"
149-
Foreground="{ThemeResource TextFillColorTertiaryBrush}"
150-
HorizontalAlignment="Center"/>
151-
<TextBlock x:Uid="AgentEventsPage_TextBlock_96" Text="No agent events yet"
137+
<!-- Empty state -->
138+
<StackPanel x:Name="EmptyState" Grid.Row="2"
139+
VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="8">
140+
<TextBlock Text="🤖" FontSize="48" HorizontalAlignment="Center"/>
141+
<TextBlock x:Uid="AgentEventsPage_TextBlock_96" Text="No events in this session"
152142
Style="{StaticResource SubtitleTextBlockStyle}"
153143
HorizontalAlignment="Center"/>
154-
<TextBlock x:Uid="AgentEventsPage_TextBlock_99" Text="Real-time agent events (tool calls, responses, errors) will appear here as agents run."
144+
<TextBlock x:Uid="AgentEventsPage_TextBlock_99" Text="Events stream here in real-time as agents run. History clears when the app restarts."
155145
Style="{StaticResource CaptionTextBlockStyle}"
156146
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
157147
HorizontalAlignment="Center" TextWrapping="Wrap" MaxWidth="320"/>

src/OpenClaw.Tray.WinUI/Pages/AgentEventsPage.xaml.cs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ public sealed partial class AgentEventsPage : Page
1313
{
1414
private const int MaxEvents = 400;
1515
private readonly List<AgentEventInfo> _allEvents = new();
16-
private string _activeFilter = "all";
1716
private string? _agentIdFilter;
1817
private bool _filterDirty;
1918
private AppState? _appState;
@@ -84,6 +83,35 @@ public void Initialize(HubWindow hub)
8483
_appState.AgentEventAdded += OnAgentEventAdded;
8584
_appState.PropertyChanged += OnAppStateChanged;
8685
PopulateAgentFilter(hub);
86+
UpdateLiveBadge();
87+
}
88+
89+
private void UpdateLiveBadge()
90+
{
91+
var connected = _appState?.Status == ConnectionStatus.Connected;
92+
DispatcherQueue?.TryEnqueue(() =>
93+
{
94+
if (connected)
95+
{
96+
LiveDot.Fill = new Microsoft.UI.Xaml.Media.SolidColorBrush(
97+
Microsoft.UI.ColorHelper.FromArgb(255, 255, 68, 68));
98+
LiveText.Text = "Live";
99+
LiveText.Foreground = new Microsoft.UI.Xaml.Media.SolidColorBrush(
100+
Microsoft.UI.ColorHelper.FromArgb(255, 255, 68, 68));
101+
LiveBadge.Background = new Microsoft.UI.Xaml.Media.SolidColorBrush(
102+
Microsoft.UI.ColorHelper.FromArgb(32, 255, 68, 68));
103+
}
104+
else
105+
{
106+
LiveDot.Fill = new Microsoft.UI.Xaml.Media.SolidColorBrush(
107+
Microsoft.UI.ColorHelper.FromArgb(255, 128, 128, 128));
108+
LiveText.Text = "Offline";
109+
LiveText.Foreground = new Microsoft.UI.Xaml.Media.SolidColorBrush(
110+
Microsoft.UI.ColorHelper.FromArgb(255, 128, 128, 128));
111+
LiveBadge.Background = new Microsoft.UI.Xaml.Media.SolidColorBrush(
112+
Microsoft.UI.ColorHelper.FromArgb(32, 128, 128, 128));
113+
}
114+
});
87115
}
88116

89117
private void OnAppStateChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
@@ -93,6 +121,10 @@ private void OnAppStateChanged(object? sender, System.ComponentModel.PropertyCha
93121
_allEvents.Clear();
94122
ApplyFilter();
95123
}
124+
else if (e.PropertyName == nameof(AppState.Status))
125+
{
126+
UpdateLiveBadge();
127+
}
96128
}
97129

98130
private void OnAgentEventAdded(AgentEventInfo evt)
@@ -131,12 +163,6 @@ public void AddEvent(AgentEventInfo evt)
131163
}
132164
}
133165

134-
private void OnFilterSelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)
135-
{
136-
var tag = sender.SelectedItem?.Tag as string;
137-
_activeFilter = string.IsNullOrEmpty(tag) ? "all" : tag;
138-
ApplyFilter();
139-
}
140166

141167
private void ApplyFilter()
142168
{
@@ -147,10 +173,6 @@ private void ApplyFilter()
147173
filtered = filtered.Where(e => e.SessionKey != null &&
148174
e.SessionKey.StartsWith($"agent:{_agentIdFilter}:", StringComparison.OrdinalIgnoreCase));
149175

150-
// Filter by stream type (use ResolvedStream so "item" events with kind:"tool" match the Tool filter)
151-
if (_activeFilter != "all")
152-
filtered = filtered.Where(e => e.ResolvedStream.Equals(_activeFilter, StringComparison.OrdinalIgnoreCase));
153-
154176
var list = filtered.ToList();
155177
EventsList.ItemsSource = list;
156178
EventsList.Visibility = list.Count > 0 ? Visibility.Visible : Visibility.Collapsed;

src/OpenClaw.Tray.WinUI/Pages/UsagePage.xaml.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void Initialize()
7373
// Only apply cached cost data when its period matches the current
7474
// selection — otherwise the daily list briefly shows e.g. 30-day
7575
// data while the selector reads "7 Days".
76-
if (_appState?.UsageCost != null && _appState.UsageCost.Days == _currentPeriodDays)
76+
if (_appState?.UsageCost != null && ShouldApplyUsageCost(_appState.UsageCost))
7777
{
7878
UpdateUsageCost(_appState.UsageCost);
7979
_dailyCostLoading.BeginRefresh();
@@ -200,6 +200,9 @@ public void UpdateUsageCost(GatewayCostUsageInfo cost)
200200
if (cost.UpdatedAt < _lastAppliedUsageCostUpdatedAtUtc)
201201
return;
202202

203+
if (!ShouldApplyUsageCost(cost))
204+
return;
205+
203206
// The Windows tray fires usage.cost twice per refresh: once via
204207
// RequestUsageAsync() (always days=30) and once directly via the
205208
// selector (currently 7 or 30). If the gateway ignores the `days`
@@ -227,6 +230,21 @@ public void UpdateUsageCost(GatewayCostUsageInfo cost)
227230
UpdateDailyCostLoadingVisuals();
228231
}
229232

233+
private bool ShouldApplyUsageCost(GatewayCostUsageInfo cost)
234+
{
235+
if (cost.Days <= 0)
236+
return true;
237+
238+
// The gateway can compute the requested range inclusively (e.g. 8
239+
// for a 7-day request). Allow ±1 so valid responses are not dropped.
240+
if (Math.Abs(cost.Days - _currentPeriodDays) <= 1)
241+
return true;
242+
243+
// If nothing has ever loaded, accept a mismatched period rather than
244+
// leaving the page spinning forever when an older gateway ignores days.
245+
return !_dailyCostLoading.HasLoaded;
246+
}
247+
230248
private void SyncSelectorToServerDays(int days)
231249
{
232250
// Only the two SelectorBar items are valid targets; ignore anything

src/OpenClaw.Tray.WinUI/Strings/en-us/Resources.resw

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,7 +1546,7 @@ On your gateway host (Mac/Linux), run:
15461546
<value>Dashboard → openclaw://dashboard</value>
15471547
</data>
15481548
<data name="AgentEventsPage_TextBlock_18.Text" xml:space="preserve">
1549-
<value>Agent Events</value>
1549+
<value>Event Stream</value>
15501550
</data>
15511551
<data name="AgentFilterCombo.Header" xml:space="preserve">
15521552
<value>Agent</value>
@@ -1585,10 +1585,10 @@ On your gateway host (Mac/Linux), run:
15851585
<value>Patch</value>
15861586
</data>
15871587
<data name="AgentEventsPage_TextBlock_96.Text" xml:space="preserve">
1588-
<value>No agent events yet</value>
1588+
<value>No events in this session</value>
15891589
</data>
15901590
<data name="AgentEventsPage_TextBlock_99.Text" xml:space="preserve">
1591-
<value>Real-time agent events (tool calls, responses, errors) will appear here as agents run.</value>
1591+
<value>Events stream here in real-time as agents run. History clears when the app restarts.</value>
15921592
</data>
15931593
<data name="ClearButton.Content" xml:space="preserve">
15941594
<value>Clear</value>
@@ -2242,7 +2242,7 @@ On your gateway host (Mac/Linux), run:
22422242
<value>Conversations</value>
22432243
</data>
22442244
<data name="HubWindow_NavigationViewItem_94.Content" xml:space="preserve">
2245-
<value>Agent Events</value>
2245+
<value>Event Stream</value>
22462246
</data>
22472247
<data name="HubWindow_NavigationViewItem_97.Content" xml:space="preserve">
22482248
<value>Skills</value>

src/OpenClaw.Tray.WinUI/Windows/HubWindow.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@
179179
<NavigationViewItem x:Uid="HubWindow_Advanced" x:Name="NavAdvanced" Content="Advanced" SelectsOnInvoked="False">
180180
<NavigationViewItem.Icon><ImageIcon Source="{StaticResource Advanced_Icon}"/></NavigationViewItem.Icon>
181181
<NavigationViewItem.MenuItems>
182-
<NavigationViewItem x:Uid="HubWindow_NavigationViewItem_94" Tag="agentevents" Content="Agent Events">
182+
<NavigationViewItem x:Uid="HubWindow_NavigationViewItem_94" Tag="agentevents" Content="Event Stream">
183183
<NavigationViewItem.Icon><ImageIcon Source="{StaticResource AgentEvents_Icon}"/></NavigationViewItem.Icon>
184184
</NavigationViewItem>
185185
<NavigationViewItem x:Uid="AgentsNavItem" x:Name="AgentsNavItem" Content="Agents" SelectsOnInvoked="False" IsExpanded="True">

tests/OpenClaw.Tray.Tests/AsyncListLoadingPageWiringTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ public void UsagePage_GuardsStalePeriodResponses()
5050
{
5151
var source = ReadSource("src", "OpenClaw.Tray.WinUI", "Pages", "UsagePage.xaml.cs");
5252

53-
Assert.Contains("cost.Days != _currentPeriodDays", source);
53+
Assert.Contains("ShouldApplyUsageCost", source);
54+
Assert.Contains("Math.Abs(cost.Days - _currentPeriodDays) <= 1", source);
55+
Assert.Contains("return !_dailyCostLoading.HasLoaded", source);
5456
Assert.Contains("cost.UpdatedAt < _lastAppliedUsageCostUpdatedAtUtc", source);
5557
Assert.Contains("_dailyCostLoading.BeginInitialRefresh()", source);
5658
}

0 commit comments

Comments
 (0)