Skip to content

Commit 1c1a844

Browse files
committed
Enhance AgentHubService with caching and error handling; add cache management in UI
1 parent 4ece56d commit 1c1a844

17 files changed

+1262
-73
lines changed

Directory.Packages.props

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22
<PropertyGroup>
33
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4-
<Version>0.1.7.0</Version>
4+
<Version>0.1.8.0</Version>
55
<AssemblyVersion>$(Version)</AssemblyVersion>
66
<FileVersion>$(Version)</FileVersion>
77
<InformationalVersion>$(Version)</InformationalVersion>
@@ -18,7 +18,6 @@
1818
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.3" />
1919
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.3" />
2020
<PackageVersion Include="Avalonia.Desktop" Version="11.3.3" />
21-
<PackageVersion Include="Avalonia.Browser" Version="11.3.3" />
2221
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.3" />
2322
<PackageVersion Include="FluentAvaloniaUI" Version="2.4.0" />
2423
</ItemGroup>

SemanticCode.Desktop/SemanticCode.Desktop.csproj

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<OutputType>WinExe</OutputType>
4-
<!--If you are willing to use Windows/MacOS native APIs you will need to create 3 projects.
5-
One for Windows with net9.0-windows TFM, one for MacOS with net9.0-macos and one with net9.0 TFM for Linux.-->
64
<TargetFramework>net10.0</TargetFramework>
75
<Nullable>enable</Nullable>
86
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
7+
<AssemblyTitle>Semantic Code</AssemblyTitle>
8+
<Product>Semantic Code</Product>
9+
<AssemblyProduct>Semantic Code</AssemblyProduct>
910
</PropertyGroup>
1011

1112
<PropertyGroup>
@@ -18,17 +19,22 @@
1819

1920
<PropertyGroup>
2021
<ApplicationManifest>app.manifest</ApplicationManifest>
22+
<ApplicationIcon>favicon.ico</ApplicationIcon>
2123
</PropertyGroup>
24+
25+
<ItemGroup>
26+
<Content Include="favicon.ico" />
27+
</ItemGroup>
2228

2329
<ItemGroup>
24-
<PackageReference Include="Avalonia.Desktop"/>
30+
<PackageReference Include="Avalonia.Desktop" />
2531
<PackageReference Include="Avalonia.Diagnostics">
2632
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
2733
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
2834
</PackageReference>
2935
</ItemGroup>
3036

3137
<ItemGroup>
32-
<ProjectReference Include="..\SemanticCode\SemanticCode.csproj"/>
38+
<ProjectReference Include="..\SemanticCode\SemanticCode.csproj" />
3339
</ItemGroup>
3440
</Project>

SemanticCode.Desktop/favicon.ico

37.9 KB
Binary file not shown.

SemanticCode.sln

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,47 @@ EndProject
1717
Global
1818
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1919
Debug|Any CPU = Debug|Any CPU
20+
Debug|ARM64 = Debug|ARM64
21+
Debug|x64 = Debug|x64
22+
Debug|x86 = Debug|x86
2023
Release|Any CPU = Release|Any CPU
24+
Release|ARM64 = Release|ARM64
25+
Release|x64 = Release|x64
26+
Release|x86 = Release|x86
2127
EndGlobalSection
2228
GlobalSection(ProjectConfigurationPlatforms) = postSolution
2329
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
2430
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|Any CPU.Build.0 = Debug|Any CPU
31+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|ARM64.ActiveCfg = Debug|Any CPU
32+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|ARM64.Build.0 = Debug|Any CPU
33+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|x64.ActiveCfg = Debug|Any CPU
34+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|x64.Build.0 = Debug|Any CPU
35+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|x86.ActiveCfg = Debug|Any CPU
36+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|x86.Build.0 = Debug|Any CPU
2537
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|Any CPU.ActiveCfg = Release|Any CPU
2638
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|Any CPU.Build.0 = Release|Any CPU
39+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|ARM64.ActiveCfg = Release|Any CPU
40+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|ARM64.Build.0 = Release|Any CPU
41+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|x64.ActiveCfg = Release|Any CPU
42+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|x64.Build.0 = Release|Any CPU
43+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|x86.ActiveCfg = Release|Any CPU
44+
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|x86.Build.0 = Release|Any CPU
2745
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
2846
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|Any CPU.Build.0 = Debug|Any CPU
47+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
48+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|ARM64.Build.0 = Debug|Any CPU
49+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|x64.ActiveCfg = Debug|Any CPU
50+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|x64.Build.0 = Debug|Any CPU
51+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|x86.ActiveCfg = Debug|Any CPU
52+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|x86.Build.0 = Debug|Any CPU
2953
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|Any CPU.ActiveCfg = Release|Any CPU
3054
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|Any CPU.Build.0 = Release|Any CPU
55+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|ARM64.ActiveCfg = Release|Any CPU
56+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|ARM64.Build.0 = Release|Any CPU
57+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|x64.ActiveCfg = Release|Any CPU
58+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|x64.Build.0 = Release|Any CPU
59+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|x86.ActiveCfg = Release|Any CPU
60+
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|x86.Build.0 = Release|Any CPU
3161
EndGlobalSection
3262
GlobalSection(SolutionProperties) = preSolution
3363
HideSolutionNode = FALSE

SemanticCode.sln.DotSettings.user

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,10 @@
88
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASymbol_002Ecs_002Fl_003AC_0021_003FUsers_003Ftoken_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F860d38664572484ebf4032dba43bddb7341a00_003F85_003Fc6ba96c4_003FSymbol_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
99
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASynchronizationContextTaskScheduler_002Ecs_002Fl_003AC_0021_003FUsers_003Ftoken_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F96cdc0cbcc484f48a653f0bd0ba43069f04918_003F54_003Faace4664_003FSynchronizationContextTaskScheduler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
1010
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATask_00601_002Ecs_002Fl_003AC_0021_003FUsers_003Ftoken_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F96cdc0cbcc484f48a653f0bd0ba43069f04918_003F88_003Faa4b39a0_003FTask_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
11+
12+
13+
14+
15+
16+
1117
</wpf:ResourceDictionary>

SemanticCode/App.axaml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
<Application xmlns="https://github.com/avaloniaui"
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:local="using:SemanticCode"
4+
xmlns:vm="using:SemanticCode.ViewModels"
45
xmlns:styling="clr-namespace:FluentAvalonia.Styling;assembly=FluentAvalonia"
56
x:Class="SemanticCode.App"
6-
RequestedThemeVariant="Default">
7-
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
7+
RequestedThemeVariant="Default"
8+
Name="Semantic Code">
89

910
<Application.DataTemplates>
1011
<local:ViewLocator />
1112
</Application.DataTemplates>
1213

13-
<Application.Resources>
14-
<ResourceDictionary>
15-
<ResourceDictionary.MergedDictionaries>
16-
</ResourceDictionary.MergedDictionaries>
17-
</ResourceDictionary>
18-
</Application.Resources>
19-
2014
<Application.Styles>
2115
<FluentTheme />
2216
<!-- As of preview5, these properties now default to false -->

SemanticCode/App.axaml.cs

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.IO;
4+
using System.Linq;
15
using Avalonia;
6+
using Avalonia.Controls;
27
using Avalonia.Controls.ApplicationLifetimes;
38
using Avalonia.Markup.Xaml;
9+
using Avalonia.Platform;
410
using SemanticCode.ViewModels;
511
using SemanticCode.Views;
612

713
namespace SemanticCode;
814

915
public partial class App : Application
1016
{
17+
private TrayIcon? _trayIcon;
18+
1119
public override void Initialize()
1220
{
1321
AvaloniaXamlLoader.Load(this);
@@ -17,10 +25,13 @@ public override void OnFrameworkInitializationCompleted()
1725
{
1826
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
1927
{
20-
desktop.MainWindow = new MainWindow
28+
var mainWindow = new MainWindow
2129
{
2230
DataContext = new MainViewModel()
2331
};
32+
desktop.MainWindow = mainWindow;
33+
34+
CreateTrayIcon();
2435
}
2536
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
2637
{
@@ -32,4 +43,107 @@ public override void OnFrameworkInitializationCompleted()
3243

3344
base.OnFrameworkInitializationCompleted();
3445
}
46+
47+
private void CreateTrayIcon()
48+
{
49+
try
50+
{
51+
var menu = new NativeMenu();
52+
53+
var showMenuItem = new NativeMenuItem("显示主窗口");
54+
showMenuItem.Click += ShowMainWindow;
55+
menu.Add(showMenuItem);
56+
57+
var openClaudeMenuItem = new NativeMenuItem("打开 .claude 文件夹");
58+
openClaudeMenuItem.Click += OpenClaudeFolder;
59+
menu.Add(openClaudeMenuItem);
60+
61+
menu.Add(new NativeMenuItemSeparator());
62+
63+
var exitMenuItem = new NativeMenuItem("退出");
64+
exitMenuItem.Click += ExitApplication;
65+
menu.Add(exitMenuItem);
66+
67+
_trayIcon = new TrayIcon
68+
{
69+
Icon = new WindowIcon(AssetLoader.Open(new Uri("avares://SemanticCode/Assets/favicon.ico"))),
70+
ToolTipText = "SemanticCode",
71+
Menu = menu
72+
};
73+
74+
_trayIcon.Clicked += ShowMainWindow;
75+
TrayIcon.SetIcons(this, [_trayIcon]);
76+
}
77+
catch (Exception ex)
78+
{
79+
Debug.WriteLine($"Failed to create tray icon: {ex.Message}");
80+
}
81+
}
82+
83+
private void OpenClaudeFolder(object? sender, EventArgs eventArgs)
84+
{
85+
try
86+
{
87+
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
88+
var claudeFolder = Path.Combine(userProfile, ".claude");
89+
90+
if (!Directory.Exists(claudeFolder))
91+
{
92+
Directory.CreateDirectory(claudeFolder);
93+
}
94+
95+
if (OperatingSystem.IsWindows())
96+
{
97+
Process.Start(new ProcessStartInfo
98+
{
99+
FileName = "explorer.exe",
100+
Arguments = claudeFolder,
101+
UseShellExecute = true
102+
});
103+
}
104+
else if (OperatingSystem.IsMacOS())
105+
{
106+
Process.Start(new ProcessStartInfo
107+
{
108+
FileName = "open",
109+
Arguments = claudeFolder,
110+
UseShellExecute = true
111+
});
112+
}
113+
else if (OperatingSystem.IsLinux())
114+
{
115+
Process.Start(new ProcessStartInfo
116+
{
117+
FileName = "xdg-open",
118+
Arguments = claudeFolder,
119+
UseShellExecute = true
120+
});
121+
}
122+
}
123+
catch (Exception ex)
124+
{
125+
// Log error or show message
126+
Debug.WriteLine($"Failed to open .claude folder: {ex.Message}");
127+
}
128+
}
129+
130+
private void ExitApplication(object? sender, EventArgs eventArgs)
131+
{
132+
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
133+
{
134+
desktop.Shutdown();
135+
}
136+
}
137+
private void ShowMainWindow(object? sender, EventArgs e)
138+
{
139+
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
140+
{
141+
if (desktop.MainWindow != null)
142+
{
143+
desktop.MainWindow.Show();
144+
desktop.MainWindow.WindowState = WindowState.Normal;
145+
desktop.MainWindow.Activate();
146+
}
147+
}
148+
}
35149
}

SemanticCode/Pages/AgentHubView.axaml

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,12 @@
1212
<vm:AgentHubViewModel />
1313
</Design.DataContext>
1414

15-
<Grid>
16-
<Grid.RowDefinitions>
17-
<RowDefinition Height="Auto"/>
18-
<RowDefinition Height="*"/>
19-
</Grid.RowDefinitions>
20-
15+
<Grid RowDefinitions="Auto,*">
16+
2117
<!-- Header -->
2218
<StackPanel Grid.Row="0" Margin="24,24,24,16" Spacing="8">
23-
<Grid>
24-
<Grid.ColumnDefinitions>
25-
<ColumnDefinition Width="*"/>
26-
<ColumnDefinition Width="Auto"/>
27-
</Grid.ColumnDefinitions>
28-
19+
<Grid ColumnDefinitions="*,Auto">
20+
2921
<StackPanel Grid.Column="0" Spacing="4">
3022
<TextBlock Text="{Binding HubData.Title}"
3123
FontSize="24"
@@ -50,13 +42,38 @@
5042
<Run Text="安装目录: "/>
5143
<Run Text="{Binding AgentsDirectory}"/>
5244
</TextBlock>
45+
<TextBlock FontSize="12"
46+
Foreground="{DynamicResource AccentFillColorDefaultBrush}"
47+
Text="{Binding CacheStatus}"
48+
IsVisible="{Binding CacheStatus, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
5349
</StackPanel>
5450
</StackPanel>
5551

56-
<Button Grid.Column="1"
57-
Content="刷新"
58-
Command="{Binding RefreshCommand}"
59-
IsEnabled="{Binding !IsLoading}"/>
52+
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
53+
<Button Content="清除缓存"
54+
Command="{Binding ClearCacheCommand}"
55+
IsEnabled="{Binding !IsLoading}"/>
56+
<Button Content="刷新"
57+
Command="{Binding RefreshCommand}"
58+
IsEnabled="{Binding !IsLoading}"
59+
Classes="accent"/>
60+
</StackPanel>
61+
</Grid>
62+
63+
<!-- Search and Count -->
64+
<Grid ColumnDefinitions="*,Auto"
65+
Margin="0,8,0,0"
66+
IsVisible="{Binding HasData}">
67+
<TextBox Grid.Column="0"
68+
Text="{Binding SearchText}"
69+
Watermark="搜索Agent名称或描述..."
70+
MaxWidth="400"
71+
HorizontalAlignment="Left"/>
72+
<TextBlock Grid.Column="1"
73+
Text="{Binding CountDisplay}"
74+
FontSize="12"
75+
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
76+
VerticalAlignment="Center"/>
6077
</Grid>
6178
</StackPanel>
6279

@@ -106,7 +123,7 @@
106123
<ScrollViewer VerticalScrollBarVisibility="Auto"
107124
HorizontalScrollBarVisibility="Disabled"
108125
IsVisible="{Binding HasData}">
109-
<ItemsControl ItemsSource="{Binding HubData.Agents}">
126+
<ItemsControl ItemsSource="{Binding FilteredAgents}">
110127
<ItemsControl.ItemsPanel>
111128
<ItemsPanelTemplate>
112129
<UniformGrid Columns="2"

0 commit comments

Comments
 (0)