diff --git a/KitX Contracts/KitX.Contract.CSharp/TriggerHelper.cs b/KitX Contracts/KitX.Contract.CSharp/TriggerHelper.cs
new file mode 100644
index 0000000..7854215
--- /dev/null
+++ b/KitX Contracts/KitX.Contract.CSharp/TriggerHelper.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using KitX.Shared.CSharp.WebCommand;
+using KitX.Shared.CSharp.WebCommand.Infos;
+
+namespace KitX.Contract.CSharp;
+
+///
+/// 插件触发器辅助工具。插件通过此类发送触发信号到 Dashboard。
+/// 触发器是纯信号,不携带业务数据。工作流被触发后通过调用插件函数获取数据。
+///
+public static class TriggerHelper
+{
+ private static readonly JsonSerializerOptions _options = new()
+ {
+ WriteIndented = false,
+ IncludeFields = true,
+ PropertyNameCaseInsensitive = true,
+ };
+
+ ///
+ /// 触发一个信号事件
+ ///
+ /// SetSendCommandAction 提供的发送回调
+ /// 触发器名称
+ public static void FireTrigger(Action? sendAction, string triggerName)
+ {
+ if (sendAction is null) return;
+
+ var request = new Request
+ {
+ Type = RequestTypes.Command,
+ Version = RequestVersions.V1,
+ Content = JsonSerializer.Serialize(new Command
+ {
+ Request = CommandRequestInfo.TriggerFired,
+ Tags = new Dictionary { { "TriggerName", triggerName } }
+ }, _options)
+ };
+
+ sendAction.Invoke(request);
+ }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Activity/IActivityService.cs b/KitX Core Contracts/KitX.Core.Contract/Activity/IActivityService.cs
new file mode 100644
index 0000000..fae97e4
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Activity/IActivityService.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Threading.Tasks;
+
+namespace KitX.Core.Contract.Activity;
+
+///
+/// Activity management service interface
+///
+public interface IActivityService
+{
+ ///
+ /// Records app start event
+ ///
+ void RecordAppStart();
+
+ ///
+ /// Records app exit event
+ ///
+ void RecordAppExit();
+
+ ///
+ /// Records an activity
+ ///
+ /// The activity type
+ /// Optional details
+ void RecordActivity(string type, Dictionary? details = null);
+
+ ///
+ /// Gets activities
+ ///
+ /// Optional start date
+ /// Optional end date
+ /// Maximum number of activities to return
+ /// List of activities
+ IList GetActivities(DateTime? startDate = null, DateTime? endDate = null, int limit = 100);
+
+ ///
+ /// Gets activity statistics
+ ///
+ /// Start date
+ /// End date
+ /// Activity statistics
+ IActivityStatistics GetStatistics(DateTime startDate, DateTime endDate);
+
+ ///
+ /// Event raised when activities are updated
+ ///
+ event EventHandler? ActivitiesUpdated;
+}
+
+///
+/// Activity interface
+///
+public interface IActivity
+{
+ ///
+ /// Gets the activity ID
+ ///
+ string Id { get; }
+
+ ///
+ /// Gets the activity type
+ ///
+ string Type { get; }
+
+ ///
+ /// Gets the timestamp
+ ///
+ DateTime Timestamp { get; }
+
+ ///
+ /// Gets the details
+ ///
+ Dictionary Details { get; }
+}
+
+///
+/// Activity statistics interface
+///
+public interface IActivityStatistics
+{
+ ///
+ /// Gets the total number of activities
+ ///
+ int TotalActivities { get; }
+
+ ///
+ /// Gets the activities grouped by type
+ ///
+ Dictionary ActivitiesByType { get; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Announcement/IAnnouncementService.cs b/KitX Core Contracts/KitX.Core.Contract/Announcement/IAnnouncementService.cs
new file mode 100644
index 0000000..676f850
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Announcement/IAnnouncementService.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using KitX.Core.Contract.Configuration;
+
+namespace KitX.Core.Contract.Announcement;
+
+///
+/// Announcement service interface
+///
+public interface IAnnouncementService
+{
+ ///
+ /// Gets the announcement configuration
+ ///
+ IAnnouncementConf AnnouncementConfig { get; }
+
+ ///
+ /// Checks for new announcements
+ ///
+ /// List of new announcements
+ Task> CheckNewAnnouncementsAsync();
+
+ ///
+ /// Marks an announcement as read
+ ///
+ /// The announcement ID
+ void MarkAsRead(string announcementId);
+
+ ///
+ /// Gets all read announcement IDs
+ ///
+ /// List of read announcement IDs
+ IReadOnlyList GetReadAnnouncementIds();
+
+ ///
+ /// Saves the announcement configuration
+ ///
+ void SaveAnnouncementConfig();
+
+ ///
+ /// Event raised when new announcements are available
+ ///
+ event EventHandler? NewAnnouncementsAvailable;
+}
+
+///
+/// Announcement interface
+///
+public interface IAnnouncement
+{
+ ///
+ /// Gets the announcement ID
+ ///
+ string Id { get; }
+
+ ///
+ /// Gets the announcement title
+ ///
+ string Title { get; }
+
+ ///
+ /// Gets the announcement content
+ ///
+ string Content { get; }
+
+ ///
+ /// Gets the publish date
+ ///
+ DateTime PublishDate { get; }
+
+ ///
+ /// Gets the version
+ ///
+ string Version { get; }
+}
+
+///
+/// New announcements event arguments
+///
+public class NewAnnouncementsEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the announcements
+ ///
+ public IReadOnlyList Announcements { get; set; } = Array.Empty();
+
+ ///
+ /// Gets or sets announcements as dictionary (date -> content)
+ ///
+ public Dictionary? AnnouncementsDict { get; set; }
+}
+
+///
+/// Announcement error event arguments
+///
+public class AnnouncementErrorEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the error message
+ ///
+ public string ErrorMessage { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the stack trace
+ ///
+ public string StackTrace { get; set; } = string.Empty;
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/ConfigChangedEventArgs.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/ConfigChangedEventArgs.cs
new file mode 100644
index 0000000..9e05817
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/ConfigChangedEventArgs.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Configuration changed event arguments
+///
+public class ConfigChangedEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the configuration type (e.g., "App", "Plugins", "Security")
+ ///
+ public string ConfigType { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the property name that changed
+ ///
+ public string PropertyName { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the old value
+ ///
+ public object? OldValue { get; set; }
+
+ ///
+ /// Gets or sets the new value
+ ///
+ public object? NewValue { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IActivityConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IActivityConf.cs
new file mode 100644
index 0000000..8c15a61
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IActivityConf.cs
@@ -0,0 +1,9 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Activity configuration section
+///
+public interface IActivityConf
+{
+ int TotalRecorded { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IAnnouncementConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IAnnouncementConf.cs
new file mode 100644
index 0000000..b407a00
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IAnnouncementConf.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+
+namespace KitX.Core.Contract.Configuration;
+
+public interface IAnnouncementConf
+{
+ ///
+ /// Gets or sets the list of accepted announcement IDs
+ ///
+ List Accepted { get; set; }
+
+ ///
+ /// Gets or sets the config file location
+ ///
+ string? ConfigFileLocation { get; set; }
+}
+
+///
+/// Backward-compatible alias of .
+/// Deprecated: use instead.
+///
+[Obsolete("Use IAnnouncementConf instead.")]
+public interface IAnnouncementConfig : IAnnouncementConf
+{
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IAppConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IAppConf.cs
new file mode 100644
index 0000000..02cfff6
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IAppConf.cs
@@ -0,0 +1,84 @@
+using System.Collections.Generic;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Application configuration interface (complete structure)
+///
+/// Aggregate root of the configuration sections. Retains the *Config name
+/// because the *Conf equivalent (, the App section)
+/// is already taken; all section interfaces are unified under the *Conf
+/// naming convention.
+///
+///
+public interface IAppConfig
+{
+ ///
+ /// Gets or sets the application configuration
+ ///
+ IAppConf App { get; set; }
+
+ ///
+ /// Gets or sets the windows configuration
+ ///
+ IWindowsConf Windows { get; set; }
+
+ ///
+ /// Gets or sets the pages configuration
+ ///
+ IPagesConf Pages { get; set; }
+
+ ///
+ /// Gets or sets the web configuration
+ ///
+ IWebConf Web { get; set; }
+
+ ///
+ /// Gets or sets the log configuration
+ ///
+ ILogConf Log { get; set; }
+
+ ///
+ /// Gets or sets the IO configuration
+ ///
+ IIOConf IO { get; set; }
+
+ ///
+ /// Gets or sets the activity configuration
+ ///
+ IActivityConf Activity { get; set; }
+
+ ///
+ /// Gets or sets the loaders configuration
+ ///
+ ILoadersConf Loaders { get; set; }
+}
+
+///
+/// Application configuration section
+///
+public interface IAppConf
+{
+ string IconFileName { get; set; }
+ string CoverIconFileName { get; set; }
+ string AppLanguage { get; set; }
+ string Theme { get; set; }
+ string ThemeColor { get; set; }
+ Dictionary SurpportLanguages { get; set; }
+ string LocalPluginsFileFolder { get; set; }
+ string LocalPluginsDataFolder { get; set; }
+ bool DeveloperSetting { get; set; }
+ bool ShowAnnouncementWhenStart { get; set; }
+ ulong RanTime { get; set; }
+ int LastBreakAfterExit { get; set; }
+
+ ///
+ /// Default expand mode for blueprint nested (Block) nodes.
+ /// Values: "Embedded" (Picture-in-Picture inner editor, default) or
+ /// "SubEditor" (modal overlay with breadcrumb navigation).
+ /// Consumed by BlueprintEditorViewModel.InitializeBlockScopes when
+ /// creating BlueprintBlockNodeVM instances. Unknown values fall back
+ /// to "Embedded".
+ ///
+ string BlueprintNestedNodeExpandMode { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigLoader.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigLoader.cs
new file mode 100644
index 0000000..68fea69
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigLoader.cs
@@ -0,0 +1,21 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Loads configuration from files
+///
+public interface IConfigLoader
+{
+ ///
+ /// Loads a config file from the specified location
+ ///
+ /// Config type
+ /// Directory path
+ /// File name
+ /// The loaded config or default
+ T Load(string location, string fileName) where T : class, new();
+
+ ///
+ /// Loads SecurityConfig with special handling
+ ///
+ ISecurityConf LoadSecurityConfig(string location);
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigSaver.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigSaver.cs
new file mode 100644
index 0000000..e6b8df7
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigSaver.cs
@@ -0,0 +1,16 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Saves configuration to files
+///
+public interface IConfigSaver
+{
+ ///
+ /// Saves a config to the specified location
+ ///
+ /// Config type
+ /// Config to save
+ /// Directory path
+ /// File name
+ void Save(T config, string location, string fileName) where T : class;
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigService.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigService.cs
new file mode 100644
index 0000000..e06ae3c
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigService.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Configuration management service interface
+///
+public interface IConfigService
+{
+ ///
+ /// Gets the application configuration
+ ///
+ IAppConfig AppConfig { get; }
+
+ ///
+ /// Gets the plugins configuration
+ ///
+ IPluginsConf PluginsConfig { get; }
+
+ ///
+ /// Gets the security configuration
+ ///
+ ISecurityConf SecurityConfig { get; }
+
+ ///
+ /// Loads all configurations from files
+ ///
+ void Load();
+
+ ///
+ /// Saves all configurations to files
+ ///
+ void SaveAll();
+
+ ///
+ /// Reloads all configurations from files
+ ///
+ void Reload();
+
+ ///
+ /// Event raised when configuration changes
+ ///
+ event EventHandler? ConfigChanged;
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigWithMetadata.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigWithMetadata.cs
new file mode 100644
index 0000000..b43f4f3
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IConfigWithMetadata.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Interface for configurations with metadata fields
+///
+public interface IConfigWithMetadata
+{
+ ///
+ /// Gets or sets the configuration file location
+ ///
+ string? ConfigFileLocation { get; set; }
+
+ ///
+ /// Gets or sets the configuration file watcher name
+ ///
+ string? ConfigFileWatcherName { get; set; }
+
+ ///
+ /// Gets or sets the configuration generated time
+ ///
+ DateTime? ConfigGeneratedTime { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IIOConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IIOConf.cs
new file mode 100644
index 0000000..bf766f8
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IIOConf.cs
@@ -0,0 +1,10 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// IO configuration section
+///
+public interface IIOConf
+{
+ int UpdatingCheckPerThreadFilesCount { get; set; }
+ int OperatingSystemVersionUpdateInterval { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/ILoadersConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/ILoadersConf.cs
new file mode 100644
index 0000000..c1ba09b
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/ILoadersConf.cs
@@ -0,0 +1,9 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Loaders configuration section
+///
+public interface ILoadersConf
+{
+ string InstallPath { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/ILogConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/ILogConf.cs
new file mode 100644
index 0000000..9c59c63
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/ILogConf.cs
@@ -0,0 +1,14 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Log configuration section
+///
+public interface ILogConf
+{
+ long LogFileSingleMaxSize { get; set; }
+ string LogFilePath { get; set; }
+ string LogTemplate { get; set; }
+ int LogFileMaxCount { get; set; }
+ int LogFileFlushInterval { get; set; }
+ LogLevel LogLevel { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IPagesConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IPagesConf.cs
new file mode 100644
index 0000000..89d7898
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IPagesConf.cs
@@ -0,0 +1,56 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Pages configuration section
+///
+public interface IPagesConf
+{
+ IHomePageConf Home { get; set; }
+ IDevicePageConf Device { get; set; }
+ IMarketPageConf Market { get; set; }
+ ISettingsPageConf Settings { get; set; }
+}
+
+///
+/// Device page configuration
+///
+public interface IDevicePageConf
+{
+}
+
+///
+/// Market page configuration
+///
+public interface IMarketPageConf
+{
+}
+
+///
+/// Home page configuration
+///
+public interface IHomePageConf
+{
+ NavigationViewPaneDisplayMode NavigationViewPaneDisplayMode { get; set; }
+ string SelectedViewName { get; set; }
+ bool IsNavigationViewPaneOpened { get; set; }
+ bool UseAreaExpanded { get; set; }
+}
+
+///
+/// Settings page configuration
+///
+public interface ISettingsPageConf
+{
+ NavigationViewPaneDisplayMode NavigationViewPaneDisplayMode { get; set; }
+ string SelectedViewName { get; set; }
+ bool PaletteAreaExpanded { get; set; }
+ bool WebRelatedAreaExpanded { get; set; }
+ bool WebRelatedAreaOfNetworkInterfacesExpanded { get; set; }
+ bool LogRelatedAreaExpanded { get; set; }
+ bool UpdateRelatedAreaExpanded { get; set; }
+ bool AboutAreaExpanded { get; set; }
+ bool AuthorsAreaExpanded { get; set; }
+ bool LinksAreaExpanded { get; set; }
+ bool ThirdPartyLicensesAreaExpanded { get; set; }
+ bool IsNavigationViewPaneOpened { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IPluginsConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IPluginsConf.cs
new file mode 100644
index 0000000..513fee5
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IPluginsConf.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using KitX.Shared.CSharp.Device;
+using KitX.Shared.CSharp.Loader;
+using KitX.Shared.CSharp.Plugin;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Plugins configuration interface
+///
+public interface IPluginsConf
+{
+ ///
+ /// Gets or sets the list of plugin installations
+ ///
+ IList Plugins { get; set; }
+}
+
+///
+/// Backward-compatible alias of .
+/// Deprecated: use instead.
+///
+[Obsolete("Use IPluginsConf instead.")]
+public interface IPluginsConfig : IPluginsConf
+{
+}
+
+///
+/// Plugin installation interface
+///
+public interface IPluginInstallation
+{
+ ///
+ /// Gets the unique identifier for this plugin installation
+ ///
+ Guid Id { get; }
+
+ ///
+ /// Gets the installation path
+ ///
+ string? InstallPath { get; }
+
+ ///
+ /// Gets or sets the plugin information
+ ///
+ PluginInfo? PluginInfo { get; set; }
+
+ ///
+ /// Gets or sets the loader information
+ ///
+ LoaderInfo? LoaderInfo { get; set; }
+
+ ///
+ /// Gets or sets the list of installed devices
+ ///
+ IList InstalledDevices { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/ISecurityConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/ISecurityConf.cs
new file mode 100644
index 0000000..af7f3ae
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/ISecurityConf.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using KitX.Shared.CSharp.Device;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Security configuration interface
+///
+public interface ISecurityConf
+{
+ ///
+ /// Gets or sets the device keys list
+ ///
+ IList DeviceKeys { get; set; }
+}
+
+///
+/// Backward-compatible alias of .
+/// Deprecated: use instead.
+///
+[Obsolete("Use ISecurityConf instead.")]
+public interface ISecurityConfig : ISecurityConf
+{
+}
+
+///
+/// Device key interface
+///
+public interface IDeviceKey
+{
+ ///
+ /// Gets the device locator
+ ///
+ DeviceLocator Device { get; }
+
+ ///
+ /// Gets the RSA public key in PEM format
+ ///
+ string? RsaPublicKeyPem { get; }
+
+ ///
+ /// Gets the MAC address
+ ///
+ string MacAddress { get; }
+
+ ///
+ /// Gets the device name
+ ///
+ string DeviceName { get; }
+
+ ///
+ /// Gets the public key
+ ///
+ string PublicKey { get; }
+
+ ///
+ /// Gets the time when the key was added
+ ///
+ DateTime AddedAt { get; }
+}
\ No newline at end of file
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IWebConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IWebConf.cs
new file mode 100644
index 0000000..01b4503
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IWebConf.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Web configuration section
+///
+public interface IWebConf
+{
+ double DelayStartSeconds { get; set; }
+ string ApiServer { get; set; }
+ string ApiPath { get; set; }
+ int DevicesViewRefreshDelay { get; set; }
+ List? AcceptedNetworkInterfaces { get; set; }
+ int? UserSpecifiedDevicesServerPort { get; set; }
+ int? UserSpecifiedPluginsServerPort { get; set; }
+ int UdpPortSend { get; set; }
+ int UdpPortReceive { get; set; }
+ int UdpSendFrequency { get; set; }
+ string UdpBroadcastAddress { get; set; }
+ string IPFilter { get; set; }
+ int SocketBufferSize { get; set; }
+ int DeviceInfoTTLSeconds { get; set; }
+ bool DisableRemovingOfflineDeviceCard { get; set; }
+ string UpdateServer { get; set; }
+ string UpdatePath { get; set; }
+ string UpdateDownloadPath { get; set; }
+ string UpdateChannel { get; set; }
+ string UpdateSource { get; set; }
+}
+
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/IWindowsConf.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/IWindowsConf.cs
new file mode 100644
index 0000000..7374a8b
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/IWindowsConf.cs
@@ -0,0 +1,41 @@
+using System.Collections.Generic;
+using Common.BasicHelper.Graphics.Screen;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Windows configuration section
+///
+public interface IWindowsConf
+{
+ IMainWindowConf MainWindow { get; set; }
+ IAnnouncementWindowConf AnnouncementWindow { get; set; }
+}
+
+///
+/// Main window configuration
+///
+public interface IMainWindowConf
+{
+ Resolution Size { get; set; }
+ Distances Location { get; set; }
+ WindowState WindowState { get; set; }
+ bool IsHidden { get; set; }
+ Dictionary Tags { get; set; }
+ int GreetingTextCount_Morning { get; set; }
+ int GreetingTextCount_Noon { get; set; }
+ int GreetingTextCount_AfterNoon { get; set; }
+ int GreetingTextCount_Evening { get; set; }
+ int GreetingTextCount_Night { get; set; }
+ int GreetingUpdateInterval { get; set; }
+}
+
+///
+/// Announcement window configuration
+///
+public interface IAnnouncementWindowConf
+{
+ Resolution Size { get; set; }
+ Distances Location { get; set; }
+}
+
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/LogLevel.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/LogLevel.cs
new file mode 100644
index 0000000..5196aee
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/LogLevel.cs
@@ -0,0 +1,33 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Logging level for the KitX logger.
+///
+/// This is the contract-level logging level used by .
+/// It intentionally mirrors the numeric values of Serilog's
+/// Serilog.Events.LogEventLevel (Verbose=0 … Fatal=5) so that pre-existing
+/// config files containing the old integer values keep deserializing unchanged.
+/// Implementations may map this enum onto their actual logging framework
+/// (e.g., Serilog) without requiring a contract-level dependency on it.
+///
+///
+public enum LogLevel
+{
+ /// Verbose level (most detailed, e.g. tracing)
+ Verbose = 0,
+
+ /// Debug level
+ Debug = 1,
+
+ /// Information level (default)
+ Information = 2,
+
+ /// Warning level
+ Warning = 3,
+
+ /// Error level
+ Error = 4,
+
+ /// Fatal level (least detailed)
+ Fatal = 5
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/NavigationViewPaneDisplayMode.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/NavigationViewPaneDisplayMode.cs
new file mode 100644
index 0000000..9732e4d
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/NavigationViewPaneDisplayMode.cs
@@ -0,0 +1,19 @@
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Navigation view pane display mode enum.
+///
+/// This is a UI-layer mapping enum: it mirrors the UI framework's navigation-view
+/// pane display mode so the UI layer (KitX Dashboard) can serialize/deserialize
+/// pane mode without leaking a UI framework reference into the contract layer.
+/// KitX Dashboard has converters depending on this type — do not delete.
+///
+///
+public enum NavigationViewPaneDisplayMode
+{
+ Auto = 0,
+ Left = 1,
+ Top = 2,
+ LeftCompact = 3,
+ LeftMinimal = 4
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Configuration/WindowState.cs b/KitX Core Contracts/KitX.Core.Contract/Configuration/WindowState.cs
new file mode 100644
index 0000000..35cdca8
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Configuration/WindowState.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace KitX.Core.Contract.Configuration;
+
+///
+/// Window state enumeration (mirrors Avalonia.WindowState).
+///
+/// This is a UI-layer mapping enum: it mirrors the Avalonia UI framework's
+/// Avalonia.Controls.WindowState so the UI layer (KitX Dashboard) can
+/// serialize/deserialize window state without leaking a UI framework reference
+/// into the contract layer. KitX Dashboard has converters depending on this type
+/// — do not delete.
+///
+///
+public enum WindowState
+{
+ Normal,
+ Minimized,
+ Maximized,
+ FullScreen,
+ NonInteractive
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Device/IDeviceService.cs b/KitX Core Contracts/KitX.Core.Contract/Device/IDeviceService.cs
new file mode 100644
index 0000000..c1c6685
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Device/IDeviceService.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using KitX.Shared.CSharp.Device;
+
+namespace KitX.Core.Contract.Device;
+
+///
+/// Device discovery service interface
+///
+public interface IDeviceDiscoveryService
+{
+ ///
+ /// Gets the default device information
+ ///
+ DeviceInfo DefaultDeviceInfo { get; }
+
+ ///
+ /// Gets the port the discovery service is running on
+ ///
+ int? Port { get; }
+
+ ///
+ /// Starts the device discovery service
+ ///
+ /// The service instance
+ IDeviceDiscoveryService Run();
+
+ ///
+ /// Stops the device discovery service
+ ///
+ void Stop();
+
+ ///
+ /// Event raised when a device is discovered
+ ///
+ event EventHandler? DeviceDiscovered;
+
+ ///
+ /// Event raised when a device goes offline
+ ///
+ event EventHandler? DeviceOffline;
+}
+
+///
+/// Device server interface for HTTP API
+///
+public interface IDeviceServer
+{
+ ///
+ /// Gets the port the server is running on
+ ///
+ int? Port { get; }
+
+ ///
+ /// Starts the device server
+ ///
+ /// The server instance
+ IDeviceServer Run();
+
+ ///
+ /// Stops the device server
+ ///
+ void Stop();
+
+ ///
+ /// Checks if a device is signed in
+ ///
+ /// The device locator
+ /// True if the device is signed in
+ bool IsDeviceSignedIn(DeviceLocator locator);
+
+ ///
+ /// Gets the signed device token for a device locator
+ ///
+ /// The device locator
+ /// The token or null if not found
+ string? GetDeviceToken(DeviceLocator locator);
+
+ ///
+ /// Gets all signed-in device locators
+ ///
+ /// Read-only list of signed-in device locators
+ IReadOnlyList GetSignedInDevices();
+}
+
+///
+/// Devices organizer interface
+///
+public interface IDevicesOrganizer
+{
+ ///
+ /// Event raised when a device is discovered
+ ///
+ event EventHandler? DeviceDiscovered;
+
+ ///
+ /// Event raised when a device goes offline
+ ///
+ event EventHandler? DeviceOffline;
+}
+
+///
+/// Device case interface
+///
+public interface IDeviceCase
+{
+ ///
+ /// Gets or sets the device information
+ ///
+ DeviceInfo DeviceInfo { get; set; }
+
+ ///
+ /// Gets a value indicating whether the device is authorized
+ ///
+ bool IsAuthorized { get; }
+
+ ///
+ /// Gets a value indicating whether this is the main device
+ ///
+ bool IsMainDevice { get; }
+
+ ///
+ /// Gets a value indicating whether the device is online
+ ///
+ bool IsOnline { get; }
+
+ ///
+ /// Gets the last seen time
+ ///
+ DateTime LastSeen { get; }
+}
+
+///
+/// Device discovered event arguments
+///
+public class DeviceDiscoveredEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the device information
+ ///
+ public DeviceInfo? DeviceInfo { get; set; }
+}
+
+///
+/// Device offline event arguments
+///
+public class DeviceOfflineEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the device ID
+ ///
+ public string DeviceId { get; set; } = string.Empty;
+}
+
+///
+/// Device HTTP client interface — sends requests to remote DevicesServer instances.
+/// Used for cross-device plugin invocation via the /Api/V1/Plugin/Invoke endpoint.
+/// (Moved to Contract so the Workflow library can depend on the abstraction without
+/// referencing KitX.Core.)
+///
+public interface IDeviceHttpClient
+{
+ ///
+ /// Invokes a plugin method on a remote device via HTTP POST to /Api/V1/Plugin/Invoke.
+ ///
+ /// Target device info (contains IPv4 and DevicesServerPort)
+ /// Valid session token for the target device
+ /// The Request object to send
+ /// Cancellation token
+ /// HTTP response from remote device, or null on network error
+ Task InvokePluginAsync(
+ DeviceInfo targetDevice,
+ string token,
+ KitX.Shared.CSharp.WebCommand.Request request,
+ CancellationToken ct = default);
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Device/INetworkService.cs b/KitX Core Contracts/KitX.Core.Contract/Device/INetworkService.cs
new file mode 100644
index 0000000..acb04e4
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Device/INetworkService.cs
@@ -0,0 +1,30 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace KitX.Core.Contract.Device;
+
+///
+/// Unified orchestrator for the device network stack (discovery UDP server,
+/// device HTTP server, plugin WebSocket server). Owns startup ordering, port
+/// configuration and shutdown. Implemented in KitX.Core.
+///
+public interface INetworkService
+{
+ /// Starts all network servers asynchronously (honors DelayStartSeconds and SkipNetworkSystemOnStartup).
+ Task StartAsync(CancellationToken ct = default);
+
+ /// Stops all running network servers.
+ Task StopAsync(CancellationToken ct = default);
+
+ ///
+ /// Stops and restarts the device discovery + device HTTP servers only
+ /// (plugin server untouched). Waits for UDP sockets to settle before restarting.
+ ///
+ Task RestartDevicesServersAsync(CancellationToken ct = default);
+
+ /// Stops the device discovery + device HTTP servers only (plugin server untouched).
+ Task StopDevicesServersAsync(CancellationToken ct = default);
+
+ /// True when at least one server is running.
+ bool IsRunning { get; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Device/ServerStatus.cs b/KitX Core Contracts/KitX.Core.Contract/Device/ServerStatus.cs
new file mode 100644
index 0000000..c41bda0
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Device/ServerStatus.cs
@@ -0,0 +1,13 @@
+namespace KitX.Core.Contract.Device;
+
+///
+/// Server status enumeration
+///
+public enum ServerStatus
+{
+ Pending,
+ Starting,
+ Running,
+ Stopping,
+ Errored
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Event/EventArgs.cs b/KitX Core Contracts/KitX.Core.Contract/Event/EventArgs.cs
new file mode 100644
index 0000000..50f6efd
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Event/EventArgs.cs
@@ -0,0 +1,89 @@
+using System;
+using KitX.Shared.CSharp.Device;
+using KitX.Shared.CSharp.Plugin;
+
+namespace KitX.Core.Contract.Event;
+
+///
+/// Event args for port changed events
+///
+public class PortChangedEventArgs : EventArgs
+{
+ ///
+ /// The new port number
+ ///
+ public int Port { get; set; }
+}
+
+///
+/// Event args for device key events
+///
+public class DeviceKeyEventArgs : EventArgs
+{
+ ///
+ /// The device key
+ ///
+ public string Key { get; set; } = string.Empty;
+}
+
+///
+/// Event args for device info events
+///
+public class DeviceInfoEventArgs : EventArgs
+{
+ ///
+ /// The device information
+ ///
+ public DeviceInfo? DeviceInfo { get; set; }
+}
+
+///
+/// Event args for plugin events
+///
+[Obsolete("Use KitX.Core.Contract.Plugin.Events.PluginRegisteredEventArgs or PluginUnregisteredEventArgs instead.")]
+public class PluginEventArgs : EventArgs
+{
+ ///
+ /// The plugin information
+ ///
+ public PluginInfo? PluginInfo { get; set; }
+}
+
+///
+/// Event args for plugin connection events
+///
+public class PluginConnectionEventArgs : EventArgs
+{
+ ///
+ /// The connection ID
+ ///
+ public string ConnectionId { get; set; } = string.Empty;
+
+ ///
+ /// The plugin information
+ ///
+ public PluginInfo? PluginInfo { get; set; }
+}
+
+///
+/// Event args for exchange device key request events.
+/// Published when a key exchange request is received, requiring user confirmation.
+///
+public class ExchangeDeviceKeyEventArgs : EventArgs
+{
+ ///
+ /// The verification code displayed to the user for confirmation.
+ /// This code must match between the two devices for the exchange to proceed.
+ ///
+ public string VerificationCode { get; set; } = string.Empty;
+
+ ///
+ /// The address of the requesting device
+ ///
+ public string RequestingDeviceAddress { get; set; } = string.Empty;
+
+ ///
+ /// The encrypted device key from the request (for informational purposes only, not for UI display)
+ ///
+ public string? EncryptedDeviceKey { get; set; }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Event/EventNames.cs b/KitX Core Contracts/KitX.Core.Contract/Event/EventNames.cs
new file mode 100644
index 0000000..d921005
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Event/EventNames.cs
@@ -0,0 +1,163 @@
+namespace KitX.Core.Contract.Event;
+
+///
+/// Event names for the event bus
+///
+public static class EventNames
+{
+ ///
+ /// Language changed event
+ ///
+ public const string LanguageChanged = "LanguageChanged";
+
+ ///
+ /// Greeting text interval updated event
+ ///
+ public const string GreetingTextIntervalUpdated = "GreetingTextIntervalUpdated";
+
+ ///
+ /// App config changed event
+ ///
+ public const string AppConfigChanged = "AppConfigChanged";
+
+ ///
+ /// Plugins config changed event
+ ///
+ public const string PluginsConfigChanged = "PluginsConfigChanged";
+
+ ///
+ /// Mica opacity changed event
+ ///
+ public const string MicaOpacityChanged = "MicaOpacityChanged";
+
+ ///
+ /// Develop settings changed event
+ ///
+ public const string DevelopSettingsChanged = "DevelopSettingsChanged";
+
+ ///
+ /// Log config updated event
+ ///
+ public const string LogConfigUpdated = "LogConfigUpdated";
+
+ ///
+ /// Theme config changed event
+ ///
+ public const string ThemeConfigChanged = "ThemeConfigChanged";
+
+ ///
+ /// Use statistics changed event
+ ///
+ public const string UseStatisticsChanged = "UseStatisticsChanged";
+
+ ///
+ /// Devices server port changed event
+ ///
+ public const string DevicesServerPortChanged = "DevicesServerPortChanged";
+
+ ///
+ /// Plugins server port changed event
+ ///
+ public const string PluginsServerPortChanged = "PluginsServerPortChanged";
+
+ ///
+ /// Activities updated event
+ ///
+ public const string OnActivitiesUpdated = "OnActivitiesUpdated";
+
+ ///
+ /// Receive cancel exchanging device key event
+ ///
+ public const string OnReceiveCancelExchangingDeviceKey = "OnReceiveCancelExchangingDeviceKey";
+
+ ///
+ /// Exiting event
+ ///
+ public const string OnExiting = "OnExiting";
+
+ ///
+ /// Receiving device info event
+ ///
+ public const string OnReceivingDeviceInfo = "OnReceivingDeviceInfo";
+
+ ///
+ /// Config hot reloaded event
+ ///
+ public const string OnConfigHotReloaded = "OnConfigHotReloaded";
+
+ ///
+ /// Accepting device key event
+ ///
+ public const string OnAcceptingDeviceKey = "OnAcceptingDeviceKey";
+
+ ///
+ /// Receive exchange device key request event.
+ /// Published when a key exchange request is received, requiring user confirmation.
+ ///
+ public const string OnReceiveExchangeDeviceKey = "OnReceiveExchangeDeviceKey";
+
+ ///
+ /// Plugin connected event
+ ///
+ public const string PluginConnected = "PluginConnected";
+
+ ///
+ /// Plugin disconnected event
+ ///
+ public const string PluginDisconnected = "PluginDisconnected";
+
+ ///
+ /// Plugin registered event
+ ///
+ public const string PluginRegistered = "PluginRegistered";
+
+ ///
+ /// Plugin unregistered event
+ ///
+ public const string PluginUnregistered = "PluginUnregistered";
+
+ ///
+ /// Plugin message received event
+ ///
+ public const string PluginMessageReceived = "PluginMessageReceived";
+
+ ///
+ /// Plugin response event (has RequestId)
+ ///
+ public const string PluginResponse = "PluginResponse";
+
+ ///
+ /// Workflow created event
+ ///
+ public const string WorkflowCreated = "WorkflowCreated";
+
+ ///
+ /// Workflow deleted event
+ ///
+ public const string WorkflowDeleted = "WorkflowDeleted";
+
+ ///
+ /// Workflow renamed event
+ ///
+ public const string WorkflowRenamed = "WorkflowRenamed";
+
+ ///
+ /// Workflow data saved event
+ ///
+ public const string WorkflowDataSaved = "WorkflowDataSaved";
+
+ ///
+ /// Trigger fired event
+ ///
+ public const string TriggerFired = "TriggerFired";
+
+ ///
+ /// Workflow triggered event (a workflow was started by a trigger)
+ ///
+ public const string WorkflowTriggered = "WorkflowTriggered";
+
+ ///
+ /// Workflow execution result event (success or failure)
+ ///
+ public const string WorkflowExecutionResult = "WorkflowExecutionResult";
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Event/IEventService.cs b/KitX Core Contracts/KitX.Core.Contract/Event/IEventService.cs
new file mode 100644
index 0000000..843b86a
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Event/IEventService.cs
@@ -0,0 +1,58 @@
+using System;
+using System.ComponentModel;
+
+namespace KitX.Core.Contract.Event;
+
+///
+/// Event service interface for global event bus
+///
+public interface IEventService
+{
+ ///
+ /// Subscribes to an event
+ ///
+ /// The event name
+ /// The event handler
+ void Subscribe(string eventName, EventHandler handler);
+
+ ///
+ /// Unsubscribes from an event
+ ///
+ /// The event name
+ /// The event handler
+ void Unsubscribe(string eventName, EventHandler handler);
+
+ ///
+ /// Publishes an event
+ ///
+ /// The event name
+ /// The event arguments
+ void Publish(string eventName, EventArgs args);
+
+ ///
+ /// Subscribes to a typed event
+ ///
+ /// The event args type
+ /// The event name
+ /// The event handler
+ void Subscribe(string eventName, EventHandler handler)
+ where TEventArgs : EventArgs;
+
+ ///
+ /// Unsubscribes from a typed event
+ ///
+ /// The event args type
+ /// The event name
+ /// The event handler
+ void Unsubscribe(string eventName, EventHandler handler)
+ where TEventArgs : EventArgs;
+
+ ///
+ /// Publishes a typed event
+ ///
+ /// The event args type
+ /// The event name
+ /// The event arguments
+ void Publish(string eventName, TEventArgs args)
+ where TEventArgs : EventArgs;
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Event/WorkflowEventArgs.cs b/KitX Core Contracts/KitX.Core.Contract/Event/WorkflowEventArgs.cs
new file mode 100644
index 0000000..cda2807
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Event/WorkflowEventArgs.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+
+namespace KitX.Core.Contract.Event;
+
+///
+/// Event arguments for workflow rename events
+///
+public class WorkflowRenamedEventArgs : EventArgs
+{
+ ///
+ /// The workflow ID that was renamed
+ ///
+ public string WorkflowId { get; }
+
+ ///
+ /// The new name of the workflow
+ ///
+ public string NewName { get; }
+
+ public WorkflowRenamedEventArgs(string workflowId, string newName)
+ {
+ WorkflowId = workflowId;
+ NewName = newName;
+ }
+}
+
+///
+/// Event arguments for workflow data saved events
+///
+public class WorkflowSavedEventArgs : EventArgs
+{
+ ///
+ /// The workflow ID that was saved
+ ///
+ public string WorkflowId { get; }
+
+ ///
+ /// The workflow name at time of save
+ ///
+ public string WorkflowName { get; }
+
+ ///
+ /// The workflow description at time of save
+ ///
+ public string Description { get; }
+
+ ///
+ /// The workflow author at time of save
+ ///
+ public string Author { get; }
+
+ public WorkflowSavedEventArgs(string workflowId, string workflowName,
+ string description = "", string author = "")
+ {
+ WorkflowId = workflowId;
+ WorkflowName = workflowName;
+ Description = description;
+ Author = author;
+ }
+}
+
+///
+/// Event arguments for workflow execution result events
+///
+public class WorkflowExecutionResultEventArgs : EventArgs
+{
+ ///
+ /// The workflow ID that was executed
+ ///
+ public string WorkflowId { get; }
+
+ ///
+ /// Whether the execution succeeded
+ ///
+ public bool IsSuccess { get; }
+
+ ///
+ /// Error message if execution failed
+ ///
+ public string? ErrorMessage { get; }
+
+ ///
+ /// Lines of Print() output produced during execution (null if not captured).
+ /// Surfaced to the Debug activity log so users can see what the workflow printed
+ /// without opening the editor's output panel.
+ ///
+ public IReadOnlyList? Output { get; }
+
+ public WorkflowExecutionResultEventArgs(string workflowId, bool isSuccess,
+ string? errorMessage = null, IReadOnlyList? output = null)
+ {
+ WorkflowId = workflowId;
+ IsSuccess = isSuccess;
+ ErrorMessage = errorMessage;
+ Output = output;
+ }
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/FileWatcher/IFileWatcherService.cs b/KitX Core Contracts/KitX.Core.Contract/FileWatcher/IFileWatcherService.cs
new file mode 100644
index 0000000..037bc27
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/FileWatcher/IFileWatcherService.cs
@@ -0,0 +1,28 @@
+using System.IO;
+using System.ComponentModel;
+
+namespace KitX.Core.Contract.FileWatcher;
+
+///
+/// File watcher service interface
+///
+public interface IFileWatcherService
+{
+ ///
+ /// Registers a file watcher
+ ///
+ /// The file path to watch
+ /// The callback when file changes
+ void RegisterWatcher(string filePath, FileSystemEventHandler onChanged);
+
+ ///
+ /// Unregisters a file watcher
+ ///
+ /// The file path to stop watching
+ void UnregisterWatcher(string filePath);
+
+ ///
+ /// Clears all file watchers
+ ///
+ void Clear();
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Hotkey/IKeyHookService.cs b/KitX Core Contracts/KitX.Core.Contract/Hotkey/IKeyHookService.cs
new file mode 100644
index 0000000..9e1dddb
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Hotkey/IKeyHookService.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace KitX.Core.Contract.Hotkey;
+
+///
+/// Key hook service interface for global hotkeys
+///
+public interface IKeyHookService
+{
+ ///
+ /// Starts the key hook
+ ///
+ void StartHook();
+
+ ///
+ /// Stops the key hook
+ ///
+ void StopHook();
+
+ ///
+ /// Registers a hotkey handler
+ ///
+ /// The keys sequence
+ /// The handler
+ void RegisterHotKeyHandler(string keysSequence, Action handler);
+
+ ///
+ /// Unregisters a hotkey handler
+ ///
+ /// The keys sequence
+ void UnregisterHotKeyHandler(string keysSequence);
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/KitX-Background-ani.png b/KitX Core Contracts/KitX.Core.Contract/KitX-Background-ani.png
new file mode 100644
index 0000000..7abdbc3
Binary files /dev/null and b/KitX Core Contracts/KitX.Core.Contract/KitX-Background-ani.png differ
diff --git a/KitX Core Contracts/KitX.Core.Contract/KitX.Core.Contract.csproj b/KitX Core Contracts/KitX.Core.Contract/KitX.Core.Contract.csproj
new file mode 100644
index 0000000..a621f46
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/KitX.Core.Contract.csproj
@@ -0,0 +1,48 @@
+
+
+
+ net10.0
+ enable
+ True
+
+
+
+ $(Version)
+ $(Version)
+ 24.10.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2024-02-07"))).TotalDays).$([System.Math]::Floor($([System.DateTime]::UtcNow.TimeOfDay.TotalMinutes)))
+
+
+
+ KitX.Core.Contract.CSharp
+ Dynesshely
+ Crequency
+ Core service contracts for KitX Dashboard written in C#
+ AGPL-3.0-only
+ True
+ KitX-Background-ani.png
+ README.md
+ https://github.com/Crequency/KitX/
+ https://github.com/Crequency/KitX-Standard/
+
+
+
+
+ True
+ \
+
+
+ True
+ \
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/KitX Core Contracts/KitX.Core.Contract/Plugin/Events/PluginEventArgs.cs b/KitX Core Contracts/KitX.Core.Contract/Plugin/Events/PluginEventArgs.cs
new file mode 100644
index 0000000..068086b
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Plugin/Events/PluginEventArgs.cs
@@ -0,0 +1,122 @@
+using System;
+using KitX.Shared.CSharp.Plugin;
+
+namespace KitX.Core.Contract.Plugin.Events;
+
+///
+/// Plugin status changed event arguments
+///
+public class PluginStatusChangedEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the plugin ID
+ ///
+ public Guid PluginId { get; set; }
+
+ ///
+ /// Gets or sets the plugin name
+ ///
+ public string PluginName { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the old status
+ ///
+ public PluginStatus OldStatus { get; set; }
+
+ ///
+ /// Gets or sets the new status
+ ///
+ public PluginStatus NewStatus { get; set; }
+}
+
+///
+/// Plugin response event arguments
+///
+public class PluginResponseEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the request ID
+ ///
+ public string RequestId { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the response content
+ ///
+ public string Content { get; set; } = string.Empty;
+}
+
+///
+/// Plugin status report event arguments
+///
+public class PluginStatusReportEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the connection ID
+ ///
+ public string ConnectionId { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the status message
+ ///
+ public string Status { get; set; } = string.Empty;
+}
+
+///
+/// Plugin registered event arguments
+///
+public class PluginRegisteredEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the plugin info
+ ///
+ public PluginInfo? PluginInfo { get; set; }
+}
+
+///
+/// Plugin unregistered event arguments
+///
+public class PluginUnregisteredEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the plugin info
+ ///
+ public PluginInfo? PluginInfo { get; set; }
+}
+
+///
+/// Plugin connected event arguments
+///
+public class PluginConnectedEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the connection ID
+ ///
+ public string? ConnectionId { get; set; }
+}
+
+///
+/// Plugin disconnected event arguments
+///
+public class PluginDisconnectedEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the connection ID
+ ///
+ public string? ConnectionId { get; set; }
+}
+
+///
+/// Plugin message received event arguments
+///
+public class PluginMessageReceivedEventArgs : EventArgs
+{
+ ///
+ /// Gets or sets the connection ID
+ ///
+ public string? ConnectionId { get; set; }
+
+ ///
+ /// Gets or sets the message
+ ///
+ public string? Message { get; set; }
+}
\ No newline at end of file
diff --git a/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginConnection.cs b/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginConnection.cs
new file mode 100644
index 0000000..d343993
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginConnection.cs
@@ -0,0 +1,48 @@
+using System;
+using KitX.Shared.CSharp.Plugin;
+using KitX.Core.Contract.Device;
+using CTask = System.Threading.Tasks.Task;
+
+namespace KitX.Core.Contract.Plugin;
+
+///
+/// Plugin connection interface
+///
+public interface IPluginConnection : IPluginConnector
+{
+ ///
+ /// Gets or sets the plugin info
+ ///
+ new PluginInfo? PluginInfo { get; set; }
+
+ ///
+ /// Gets the connection status
+ ///
+ ServerStatus Status { get; }
+
+ ///
+ /// Event raised when a message is received
+ ///
+ event EventHandler? MessageReceived;
+
+ ///
+ /// Event raised when connection is closed
+ ///
+ event EventHandler? Closed;
+
+ ///
+ /// Initializes the connection
+ ///
+ void Initialize();
+
+ ///
+ /// Sends a message
+ ///
+ /// The message to send
+ void Send(string message);
+
+ ///
+ /// Closes the connection
+ ///
+ CTask CloseAsync();
+}
diff --git a/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginConnector.cs b/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginConnector.cs
new file mode 100644
index 0000000..5f63eff
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginConnector.cs
@@ -0,0 +1,37 @@
+using System;
+using KitX.Shared.CSharp.Plugin;
+using KitX.Core.Contract.Plugin.Events;
+
+namespace KitX.Core.Contract.Plugin;
+
+///
+/// Plugin connector interface for managing individual plugin connections
+///
+public interface IPluginConnector
+{
+ ///
+ /// Gets the connection ID
+ ///
+ string? ConnectionId { get; }
+
+ ///
+ /// Gets the plugin info
+ ///
+ PluginInfo? PluginInfo { get; }
+
+ ///
+ /// Sends a request to the plugin
+ ///
+ /// The request to send
+ void Request(object request);
+
+ ///
+ /// Event raised when a plugin response is received
+ ///
+ event EventHandler? PluginResponse;
+
+ ///
+ /// Event raised when plugin reports status
+ ///
+ event EventHandler? StatusReport;
+}
\ No newline at end of file
diff --git a/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginServer.cs b/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginServer.cs
new file mode 100644
index 0000000..871277a
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginServer.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using KitX.Shared.CSharp.Plugin;
+using KitX.Core.Contract.Plugin.Events;
+
+namespace KitX.Core.Contract.Plugin;
+
+///
+/// Plugin server interface for managing plugin connections
+///
+public interface IPluginServer
+{
+ ///
+ /// Gets the port the server is running on
+ ///
+ int? Port { get; }
+
+ ///
+ /// Gets the list of currently connected plugins
+ ///
+ IReadOnlyList Connections { get; }
+
+ ///
+ /// Starts the plugin server
+ ///
+ /// The server instance
+ IPluginServer Run();
+
+ ///
+ /// Stops the plugin server
+ ///
+ void Stop();
+
+ ///
+ /// Finds a connector for a specific plugin
+ ///
+ /// The plugin info
+ /// The plugin connector or null if not found
+ IPluginConnector? FindConnector(PluginInfo pluginInfo);
+
+ ///
+ /// Finds a connection by connection ID
+ ///
+ /// The connection ID
+ /// The plugin connection or null if not found
+ IPluginConnection? FindConnection(string connectionId);
+
+ ///
+ /// Event raised when server port changes
+ ///
+ event EventHandler? PortChanged;
+
+ ///
+ /// Event raised when a plugin connects
+ ///
+ event EventHandler? PluginConnected;
+
+ ///
+ /// Event raised when a plugin disconnects
+ ///
+ event EventHandler? PluginDisconnected;
+
+ ///
+ /// Event raised when a plugin message is received
+ ///
+ event EventHandler? PluginMessageReceived;
+
+ ///
+ /// Event raised when a plugin registers with the server
+ ///
+ event EventHandler? PluginRegistered;
+
+ ///
+ /// Event raised when a plugin unregisters/disconnects from the server
+ ///
+ event EventHandler? PluginUnregistered;
+
+ ///
+ /// Event raised when a plugin sends a response (has RequestId)
+ ///
+ event EventHandler? PluginResponse;
+}
\ No newline at end of file
diff --git a/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginService.cs b/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginService.cs
new file mode 100644
index 0000000..495e5a2
--- /dev/null
+++ b/KitX Core Contracts/KitX.Core.Contract/Plugin/IPluginService.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using KitX.Core.Contract.Configuration;
+using KitX.Shared.CSharp.Plugin;
+using KitX.Core.Contract.Plugin.Events;
+
+namespace KitX.Core.Contract.Plugin;
+
+///
+/// Plugin management service interface
+///
+public interface IPluginService
+{
+ ///
+ /// Gets all installed plugins
+ ///
+ IReadOnlyList GetInstalledPlugins();
+
+ ///
+ /// Gets a plugin by its ID
+ ///
+ /// The plugin ID
+ /// The plugin installation or null if not found
+ IPluginInstallation? GetPlugin(Guid pluginId);
+
+ ///
+ /// Imports a plugin package (.kxp file)
+ ///
+ /// Path to the .kxp file
+ /// True if import was successful
+ Task ImportPluginAsync(string kxpFilePath);
+
+ ///
+ /// Removes a plugin
+ ///
+ /// The plugin ID
+ /// True if removal was successful
+ Task RemovePluginAsync(Guid pluginId);
+
+ ///
+ /// Starts a plugin
+ ///
+ /// The plugin ID
+ /// True if start was successful
+ Task StartPluginAsync(Guid pluginId);
+
+ ///
+ /// Stops a plugin
+ ///
+ /// The plugin ID
+ /// True if stop was successful
+ Task StopPluginAsync(Guid pluginId);
+
+ ///
+ /// Calls a plugin function
+ ///
+ /// The plugin ID
+ /// The function name
+ /// Optional parameters
+ /// The function result
+ Task