diff --git a/KitX Clients/KitX Core/KitX.Core.BluePrint.Test/Program.cs b/KitX Clients/KitX Core/KitX.Core.BluePrint.Test/Program.cs index 19766eb4..6e36cbbc 100644 --- a/KitX Clients/KitX Core/KitX.Core.BluePrint.Test/Program.cs +++ b/KitX Clients/KitX Core/KitX.Core.BluePrint.Test/Program.cs @@ -5,11 +5,13 @@ using Microsoft.Extensions.DependencyInjection; using KitX.Core.DI; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Blueprint; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Contract; +using KitX.Workflow.Contract.Models; +using KitX.Workflow.Conversion; -using KitX.Core.Workflow.Conversion; namespace KitX.Core.BluePrint.Test; public class Program diff --git a/KitX Clients/KitX Core/KitX.Core/DI/CoreServiceCollectionExtensions.cs b/KitX Clients/KitX Core/KitX.Core/DI/CoreServiceCollectionExtensions.cs index cf406e26..a9d0df73 100644 --- a/KitX Clients/KitX Core/KitX.Core/DI/CoreServiceCollectionExtensions.cs +++ b/KitX Clients/KitX Core/KitX.Core/DI/CoreServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using KitX.Core.Contract.Activity; using KitX.Core.Contract.Announcement; using KitX.Core.Contract.Configuration; @@ -21,13 +21,10 @@ using KitX.Core.Security; using KitX.Core.Statistics; using KitX.Core.Tasks; -using KitX.Core.Workflow; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; using KitX.Core.Event; +using KitX.Workflow.Hosting; using Serilog; -using KitX.Core.Workflow.Conversion; namespace KitX.Core.DI; /// @@ -60,21 +57,6 @@ public static IServiceCollection AddCoreServices(this IServiceCollection service Log.Information("Registering IPluginService..."); services.AddSingleton(); - // Workflow Services - Log.Information("Registering workflow services..."); - // Individual service implementations (WorkflowScriptService facade used for backward compatibility) - // IBlockScriptService is created via factory to inject RealPluginManager from DI - services.AddSingleton(provider => - { - var state = WorkflowScriptService.RuntimeState; - var rpm = provider.GetRequiredService(); - var service = new BlockScriptServiceImpl(state, rpm); - Log.Information("[DI] IBlockScriptService created with RealPluginManager. HashCode: {HashCode}", rpm.GetHashCode()); - return service; - }); - services.AddSingleton(sp => WorkflowScriptService.PluginServiceInstance); - services.AddSingleton(sp => WorkflowScriptService.ManagementServiceInstance); - // Activity Services Log.Information("Registering IActivityService..."); services.AddSingleton(); @@ -116,106 +98,15 @@ public static IServiceCollection AddCoreServices(this IServiceCollection service Log.Information("Registering IDeviceHttpClient..."); services.AddSingleton(); - // RealPluginManager must be registered as singleton so that PluginsServer and WorkflowScriptService - // use the same instance. This ensures plugin connection events are properly received. - Log.Information("Registering RealPluginManager..."); - services.AddSingleton(provider => - { - var pluginServer = provider.GetRequiredService(); - var eventService = provider.GetRequiredService(); - var deviceDiscoveryService = provider.GetRequiredService(); - var deviceServer = provider.GetRequiredService(); - return new RealPluginManager(pluginServer, eventService, deviceDiscoveryService, deviceServer, provider.GetRequiredService()); - }); - - // RealPluginManager is pre-resolved by the caller after BuildServiceProvider(). - // Phase 5: Announcement Service Log.Information("Registering IAnnouncementService..."); services.AddSingleton(); - // KCS File Services - Log.Information("Registering IKcsFileService..."); - services.AddSingleton(); - - // Block Script Services - Log.Information("Registering IBlockScriptParser..."); - services.AddSingleton(provider => - { - var funcRegistry = provider.GetService(); - var service = new KitX.Core.Workflow.BlockScripting.BlockScriptParser(funcRegistry); - return service; - }); - - Log.Information("Registering IBlockScriptExecutor..."); - services.AddSingleton(provider => - { - var service = new KitX.Core.Workflow.BlockScripting.BlockScriptExecutor(); - // Resolve RealPluginManager from DI to ensure same instance - try - { - var pluginManager = provider.GetRequiredService(); - service.SetPluginManager(pluginManager); - Log.Information("[DI] IBlockScriptExecutor: RealPluginManager HashCode = {HashCode}", pluginManager.GetHashCode()); - } - catch (Exception ex) - { - Log.Error(ex, "[DI] Could not initialize BlockScriptExecutor with RealPluginManager from DI container"); - } - return service; - }); - - Log.Information("Registering IBlockScopeManager..."); - services.AddSingleton(); - - // Blueprint Sub-services (must be registered before IBlueprintService) - Log.Information("Registering Blueprint sub-services..."); - - // Discover and register all IBuiltinFunctionDefinition implementations - var functionRegistry = BuiltinFunctionRegistry.Discover(typeof(BuiltinFunctionRegistry).Assembly); - services.AddSingleton(functionRegistry); - - // NodeRegistry with function registry for dynamic node creation - services.AddSingleton(provider => - { - var reg = provider.GetRequiredService(); - return new NodeRegistry(reg); - }); - - services.AddSingleton(); - services.AddSingleton(); - - // Blueprint Converters - Log.Information("Registering IBlockScriptToBlueprintConverter..."); - services.AddSingleton(provider => - { - var parser = provider.GetRequiredService(); - var nodeRegistry = provider.GetRequiredService(); - var layoutService = provider.GetRequiredService(); - var funcRegistry = provider.GetService(); - return new BlockScriptToBlueprintConverter(parser, nodeRegistry, layoutService, funcRegistry!); - }); - Log.Information("Registering IBlueprintToBlockScriptConverter..."); - services.AddSingleton(); - - // Blueprint Export Strategies — all auto-registered from IBuiltinFunctionDefinition implementations - Log.Information("Registering auto-discovered builtin function export strategies..."); - foreach (var def in functionRegistry.AllDefinitions) - { - services.AddSingleton(new BuiltinFunctionExportStrategyAdapter(def)); - } - - // Blueprint Services - Log.Information("Registering IBlueprintService..."); - services.AddSingleton(); - - // Workflow Storage Service - Log.Information("Registering IWorkflowStorageService..."); - services.AddSingleton(); - - // Trigger Manager - Log.Information("Registering TriggerManager..."); - services.AddSingleton(); + // Workflow Services — full graph registered by the KitX.Workflow library. + // This includes RealPluginManager (registered as a singleton so PluginsServer and + // WorkflowScriptService share the same instance and receive plugin connection events; + // the caller pre-resolves it after BuildServiceProvider()). + services.AddKitXWorkflow(); // IMPORTANT: Do NOT call BuildServiceProvider() here. // The caller is responsible for building the single IServiceProvider and passing it diff --git a/KitX Clients/KitX Core/KitX.Core/Device/DeviceHttpClient.cs b/KitX Clients/KitX Core/KitX.Core/Device/DeviceHttpClient.cs index 23e0801e..91f25b7c 100644 --- a/KitX Clients/KitX Core/KitX.Core/Device/DeviceHttpClient.cs +++ b/KitX Clients/KitX Core/KitX.Core/Device/DeviceHttpClient.cs @@ -1,37 +1,18 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using KitX.Core.Contract.Device; using KitX.Shared.CSharp.Device; using KitX.Shared.CSharp.WebCommand; using Serilog; namespace KitX.Core.Device; -/// -/// Interface for device HTTP client — sends requests to remote DevicesServer instances. -/// Used for cross-device plugin invocation via the /Api/V1/Plugin/Invoke endpoint. -/// -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, - Request request, - CancellationToken ct = default); -} - /// /// Device HTTP client implementation. /// Sends plugin invoke requests to remote DevicesServer over HTTP. /// Protocol compatible with legacy PluginControllerExtensions.RemoteInvoke. +/// Implements the contract now defined in KitX.Core.Contract. /// public class DeviceHttpClient : IDeviceHttpClient { diff --git a/KitX Clients/KitX Core/KitX.Core/KitX.Core.csproj b/KitX Clients/KitX Core/KitX.Core/KitX.Core.csproj index 4abf2fc4..4d5e15b9 100644 --- a/KitX Clients/KitX Core/KitX.Core/KitX.Core.csproj +++ b/KitX Clients/KitX Core/KitX.Core/KitX.Core.csproj @@ -29,6 +29,7 @@ + diff --git a/KitX Clients/KitX Dashboard b/KitX Clients/KitX Dashboard index 5514abad..cf980d08 160000 --- a/KitX Clients/KitX Dashboard +++ b/KitX Clients/KitX Dashboard @@ -1 +1 @@ -Subproject commit 5514abad213e046f385d6248f3d5d79455ca5e30 +Subproject commit cf980d0889925900824839d4afe7c032336f4150 diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScriptServiceImpl.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScriptServiceImpl.cs similarity index 94% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScriptServiceImpl.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScriptServiceImpl.cs index aad46814..3b48190c 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScriptServiceImpl.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScriptServiceImpl.cs @@ -1,14 +1,17 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Contract; using Serilog; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// BlockScript parsing and execution service. -/// Implements IBlockScriptService. +/// Implements both the public IBlockScriptService (Dashboard-facing, source-string +/// based methods) and the internal IBlockScriptPipelineService (parsed-model based +/// methods consumed only by the workflow pipeline). /// -internal class BlockScriptServiceImpl : IBlockScriptService +internal class BlockScriptServiceImpl : IBlockScriptService, IBlockScriptPipelineService { private readonly WorkflowRuntimeState _state; private RealPluginManager? _realPluginManager; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScopeManager.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScopeManager.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScopeManager.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScopeManager.cs index 82a0ba59..ec47f037 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScopeManager.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScopeManager.cs @@ -1,6 +1,6 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Block scope manager implementation - manages variable scoping for block scripts diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptExecutionGlobals.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptExecutionGlobals.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptExecutionGlobals.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptExecutionGlobals.cs index b54bd4d2..ea8a46f4 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptExecutionGlobals.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptExecutionGlobals.cs @@ -1,6 +1,6 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Script globals for block script execution — 仅保留核心手脚架。 diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptExecutor.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptExecutor.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptExecutor.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptExecutor.cs index 95389970..16f58211 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptExecutor.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptExecutor.cs @@ -1,10 +1,10 @@ -using System.Diagnostics; +using System.Diagnostics; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.CFG; +using KitX.Workflow.CFG; -using KitX.Core.Workflow.Conversion; -namespace KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +namespace KitX.Workflow.BlockScripting; /// /// Block script executor using full-script assembly compilation. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptParser.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptParser.cs similarity index 99% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptParser.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptParser.cs index 8e0e5f35..679ec825 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptParser.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptParser.cs @@ -1,7 +1,7 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using Serilog; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Block script parser implementation. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptWellKnown.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptWellKnown.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptWellKnown.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptWellKnown.cs index f506b014..58934b25 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptWellKnown.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockScriptWellKnown.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Well-known string constants for the BlockScript/Blueprint pipeline. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockStatementExtractor.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockStatementExtractor.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockStatementExtractor.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockStatementExtractor.cs index bb916afd..45cca35d 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockStatementExtractor.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockStatementExtractor.cs @@ -1,13 +1,13 @@ -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; -using KitX.Core.Workflow.Conversion; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; +using KitX.Workflow.Conversion; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Extracts statements and variable declarations from validated syntax trees. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockStructureRecognizer.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockStructureRecognizer.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockStructureRecognizer.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockStructureRecognizer.cs index e47fa20a..d4e04170 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockStructureRecognizer.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockStructureRecognizer.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.Text; using KitX.Core.Contract.Workflow; using Serilog; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Recognizes block structure using source text scanning. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockSyntaxValidator.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockSyntaxValidator.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockSyntaxValidator.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockSyntaxValidator.cs index 8a4b604b..4be34923 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockSyntaxValidator.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlockSyntaxValidator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Validates pure C# code within recognized blocks using Roslyn. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlueprintDebugger.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlueprintDebugger.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlueprintDebugger.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlueprintDebugger.cs index 67ba71bb..27f43930 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlueprintDebugger.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BlueprintDebugger.cs @@ -1,8 +1,8 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using KitX.Core.Contract.Workflow; using Serilog; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; public class BlueprintDebugger : IBlueprintDebugController { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BuiltinFunctionRegistry.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BuiltinFunctionRegistry.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BuiltinFunctionRegistry.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BuiltinFunctionRegistry.cs index 8f2d3014..b9c3cf9a 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BuiltinFunctionRegistry.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/BuiltinFunctionRegistry.cs @@ -1,7 +1,7 @@ -using System.Reflection; +using System.Reflection; using Serilog; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// 内置函数定义的中央注册中心。通过反射自动发现所有 diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CSCompiler.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CSCompiler.cs similarity index 96% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CSCompiler.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CSCompiler.cs index 4ba13a9f..f1dbf315 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CSCompiler.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CSCompiler.cs @@ -1,9 +1,9 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Compiles an entire into a .NET assembly using Roslyn @@ -104,7 +104,7 @@ public CSCompiler() // Phase 4: Load into collectible ALContext and instantiate var alc = new CollectibleAssemblyLoadContext(hash); var loadedAssembly = alc.LoadFromStream(assembly); - var typeName = $"KitX.Core.Workflow.BlockScripting.Generated.CompiledScript_{hash}"; + var typeName = $"KitX.Workflow.BlockScripting.Generated.CompiledScript_{hash}"; var scriptType = loadedAssembly.GetType(typeName); if (scriptType == null) { @@ -180,7 +180,7 @@ public CSCompiler() var alc = new CollectibleAssemblyLoadContext(hash); var loadedAssembly = alc.LoadFromStream(assembly); - var typeName = $"KitX.Core.Workflow.BlockScripting.Generated.CompiledScript_{hash}"; + var typeName = $"KitX.Workflow.BlockScripting.Generated.CompiledScript_{hash}"; var scriptType = loadedAssembly.GetType(typeName); if (scriptType == null) { alc.Unload(); return null; } diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CSEmitContext.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CSEmitContext.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CSEmitContext.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CSEmitContext.cs index 18505b8a..eb40551a 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CSEmitContext.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CSEmitContext.cs @@ -1,10 +1,10 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.Conversion; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Context passed to during diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CompiledScriptEntry.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CompiledScriptEntry.cs similarity index 96% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CompiledScriptEntry.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CompiledScriptEntry.cs index 703accb8..4e98fd92 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CompiledScriptEntry.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CompiledScriptEntry.cs @@ -1,7 +1,7 @@ -using System.Runtime.Loader; +using System.Runtime.Loader; using Serilog; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Wraps a compiled script instance with its diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CompiledScriptMeta.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CompiledScriptMeta.cs similarity index 87% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CompiledScriptMeta.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CompiledScriptMeta.cs index 49ce95d5..ce783c4a 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/CompiledScriptMeta.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/CompiledScriptMeta.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Metadata for a persisted compiled script assembly on disk. @@ -24,7 +24,7 @@ internal class CompiledScriptMeta /// /// Full type name of the compiled script class in the assembly, - /// e.g. "KitX.Core.Workflow.BlockScripting.Generated.CompiledScript_1a2b3c4d". + /// e.g. "KitX.Workflow.BlockScripting.Generated.CompiledScript_1a2b3c4d". /// public string TypeName { get; set; } = string.Empty; } \ No newline at end of file diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/HelperFunctionCodeGenerator.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/HelperFunctionCodeGenerator.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/HelperFunctionCodeGenerator.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/HelperFunctionCodeGenerator.cs index 70f44e24..e98578e5 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/HelperFunctionCodeGenerator.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/HelperFunctionCodeGenerator.cs @@ -1,7 +1,7 @@ -using System.Text; +using System.Text; using KitX.Core.Contract.Workflow; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Generates C# source code from HelperFunction definitions. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/IBuiltinFunctionDefinition.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/IBuiltinFunctionDefinition.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/IBuiltinFunctionDefinition.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/IBuiltinFunctionDefinition.cs index e9d47b36..61e627ab 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/IBuiltinFunctionDefinition.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/IBuiltinFunctionDefinition.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// 自描述的内置函数定义接口。实现此接口的类会被 diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ICompiledBlockScript.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ICompiledBlockScript.cs similarity index 92% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ICompiledBlockScript.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ICompiledBlockScript.cs index d399f7e0..e50ea607 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ICompiledBlockScript.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ICompiledBlockScript.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Represents a BlockScript compiled into a .NET assembly via Roslyn CSharpCompilation. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ScriptCompilationBackend.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ScriptCompilationBackend.cs similarity index 95% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ScriptCompilationBackend.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ScriptCompilationBackend.cs index 400e68e6..f97778a8 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ScriptCompilationBackend.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ScriptCompilationBackend.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.Loader; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -6,7 +6,7 @@ using KitX.Core.Contract.Workflow; using Serilog; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Roslyn compilation backend — compiles @@ -75,9 +75,9 @@ internal static List GetCompilationReferences() var seedAssemblies = new Assembly[] { typeof(BlockScriptExecutionGlobals).Assembly, - typeof(KitX.Core.Contract.Workflow.BlockScript).Assembly, + typeof(KitX.Workflow.Contract.Models.BlockScript).Assembly, typeof(ICompiledBlockScript).Assembly, - typeof(KitX.Core.Contract.Workflow.PluginCallInfo).Assembly, + typeof(KitX.Workflow.Contract.Models.PluginCallInfo).Assembly, typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly, typeof(object).Assembly, typeof(System.Collections.Generic.List<>).Assembly, diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ScriptPersistenceManager.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ScriptPersistenceManager.cs similarity index 99% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ScriptPersistenceManager.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ScriptPersistenceManager.cs index 1f312967..a5e9ad19 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/ScriptPersistenceManager.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BlockScripting/ScriptPersistenceManager.cs @@ -1,7 +1,7 @@ -using System.Text.Json; +using System.Text.Json; using Serilog; -namespace KitX.Core.Workflow.BlockScripting; +namespace KitX.Workflow.BlockScripting; /// /// Manages disk persistence of compiled script assemblies. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/BlueprintRenderDataService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/BlueprintRenderDataService.cs similarity index 87% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/BlueprintRenderDataService.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/BlueprintRenderDataService.cs index 05cdffa4..102ea758 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/BlueprintRenderDataService.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/BlueprintRenderDataService.cs @@ -1,7 +1,7 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using Serilog; -namespace KitX.Core.Workflow.Blueprint; +namespace KitX.Workflow.Blueprint; /// /// Classifies blueprint connections into Exec (execution flow) and Data (data flow) @@ -10,7 +10,7 @@ namespace KitX.Core.Workflow.Blueprint; public class BlueprintRenderDataService : IBlueprintRenderDataService { /// - public BlueprintRenderData GetRenderData(Contract.Workflow.Blueprint blueprint) + public BlueprintRenderData GetRenderData(KitX.Core.Contract.Workflow.Blueprint blueprint) { var exec = new List(); var data = new List(); diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/BlueprintService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/BlueprintService.cs similarity index 85% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/BlueprintService.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/BlueprintService.cs index f129dccf..9308f93f 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/BlueprintService.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/BlueprintService.cs @@ -1,8 +1,8 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -namespace KitX.Core.Workflow.Blueprint; +using KitX.Workflow.Conversion; +namespace KitX.Workflow.Blueprint; /// /// Blueprint service implementation @@ -23,10 +23,10 @@ public BlueprintService( _executor = executor; } - public Contract.Workflow.Blueprint CreateBlueprint() + public KitX.Core.Contract.Workflow.Blueprint CreateBlueprint() { Log.Information("Creating new Blueprint"); - return new Contract.Workflow.Blueprint + return new KitX.Core.Contract.Workflow.Blueprint { Name = "Untitled", CreatedAt = DateTime.Now, @@ -34,7 +34,7 @@ public Contract.Workflow.Blueprint CreateBlueprint() }; } - public Contract.Workflow.Blueprint? ImportFromBlockScript(string sourceCode, List? helperFunctions = null) + public KitX.Core.Contract.Workflow.Blueprint? ImportFromBlockScript(string sourceCode, List? helperFunctions = null) { try { @@ -50,7 +50,7 @@ public Contract.Workflow.Blueprint CreateBlueprint() } } - public string ExportToBlockScript(Contract.Workflow.Blueprint blueprint) + public string ExportToBlockScript(KitX.Core.Contract.Workflow.Blueprint blueprint) { try { @@ -64,7 +64,7 @@ public string ExportToBlockScript(Contract.Workflow.Blueprint blueprint) } } - public async Task ExecuteBlueprintAsync(Contract.Workflow.Blueprint blueprint) + public async Task ExecuteBlueprintAsync(KitX.Core.Contract.Workflow.Blueprint blueprint) { try { @@ -101,7 +101,7 @@ public async Task ExecuteBlueprintAsync(Contract.Wor } } - public Dictionary GetDebugNodeMapping(Contract.Workflow.Blueprint blueprint) + public Dictionary GetDebugNodeMapping(KitX.Core.Contract.Workflow.Blueprint blueprint) { try { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/LayoutService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/LayoutService.cs similarity index 96% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/LayoutService.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/LayoutService.cs index a2520a81..28c47ac2 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/LayoutService.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/LayoutService.cs @@ -1,7 +1,7 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using Serilog; -namespace KitX.Core.Workflow.Blueprint; +namespace KitX.Workflow.Blueprint; /// /// Recursive subgraph layout engine. @@ -28,7 +28,7 @@ public class LayoutService : ILayoutService private const double DataNodeVSpacing = 150; /// - public void LayoutNodes(Contract.Workflow.Blueprint blueprint) + public void LayoutNodes(KitX.Core.Contract.Workflow.Blueprint blueprint) { if (blueprint.Nodes.Count == 0) return; @@ -76,7 +76,7 @@ public void LayoutNodes(Contract.Workflow.Blueprint blueprint) /// direction assignment matches physical pin layout. /// private Dictionary> BuildExecAdjacencyMap( - Contract.Workflow.Blueprint blueprint) + KitX.Core.Contract.Workflow.Blueprint blueprint) { var map = new Dictionary>(); @@ -110,7 +110,7 @@ public void LayoutNodes(Contract.Workflow.Blueprint blueprint) private LayoutRegion? BuildRegionTree( string nodeId, Dictionary> execMap, - Contract.Workflow.Blueprint blueprint, + KitX.Core.Contract.Workflow.Blueprint blueprint, HashSet visited, HashSet placed) { @@ -183,7 +183,7 @@ public void LayoutNodes(Contract.Workflow.Blueprint blueprint) /// /// Places data-only nodes (Const, Variable) in a left sidebar column. /// - private void PlaceDataNodes(Contract.Workflow.Blueprint blueprint, HashSet placed) + private void PlaceDataNodes(KitX.Core.Contract.Workflow.Blueprint blueprint, HashSet placed) { var dataNodes = blueprint.Nodes.Where(n => !placed.Contains(n.Id)).ToList(); if (dataNodes.Count == 0) return; @@ -249,7 +249,7 @@ private abstract class LayoutRegion public double MeasuredWidth { get; protected set; } public double MeasuredHeight { get; protected set; } public abstract void Measure(double availableWidth = MaxRowWidth); - public abstract void Arrange(double x, double y, Contract.Workflow.Blueprint bp); + public abstract void Arrange(double x, double y, KitX.Core.Contract.Workflow.Blueprint bp); } /// @@ -317,7 +317,7 @@ public override void Measure(double availableWidth = MaxRowWidth) } } - public override void Arrange(double x, double y, Contract.Workflow.Blueprint bp) + public override void Arrange(double x, double y, KitX.Core.Contract.Workflow.Blueprint bp) { double currentY = y; @@ -436,7 +436,7 @@ public override void Measure(double availableWidth = MaxRowWidth) + lowerBranchHeight; } - public override void Arrange(double x, double y, Contract.Workflow.Blueprint bp) + public override void Arrange(double x, double y, KitX.Core.Contract.Workflow.Blueprint bp) { // Read the fork node's actual position (placed by parent LinearRegion) var forkNode = bp.GetNodeById(ForkNodeId); diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/NodeExportHelper.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/NodeExportHelper.cs similarity index 92% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/NodeExportHelper.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/NodeExportHelper.cs index 0a9bdcde..06b50d6c 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/NodeExportHelper.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/NodeExportHelper.cs @@ -1,8 +1,8 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Pins; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.Conversion; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Pins; -namespace KitX.Core.Workflow.Blueprint; +namespace KitX.Workflow.Blueprint; /// /// Implements INodeExportHelper — resolves input values for export strategies @@ -12,10 +12,10 @@ namespace KitX.Core.Workflow.Blueprint; internal class NodeExportHelper : INodeExportHelper { /// - public Contract.Workflow.Blueprint Blueprint { get; private set; } = null!; + public KitX.Core.Contract.Workflow.Blueprint Blueprint { get; private set; } = null!; /// Sets the current blueprint and context for resolution - public void SetContext(Contract.Workflow.Blueprint blueprint, ConversionContext? ctx) + public void SetContext(KitX.Core.Contract.Workflow.Blueprint blueprint, ConversionContext? ctx) { Blueprint = blueprint; _currentCtx = ctx; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/NodeRegistry.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/NodeRegistry.cs similarity index 96% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/NodeRegistry.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/NodeRegistry.cs index 6ddab745..d60363c5 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/NodeRegistry.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Blueprint/NodeRegistry.cs @@ -1,8 +1,8 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.BlockScripting; using Serilog; -namespace KitX.Core.Workflow.Blueprint; +namespace KitX.Workflow.Blueprint; /// /// Unified registry for node type creation and metadata. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/BranchFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/BranchFunction.cs similarity index 94% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/BranchFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/BranchFunction.cs index 094373c7..d8fa3160 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/BranchFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/BranchFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// Branch 内置函数 — 条件分支控制流。 @@ -96,7 +96,7 @@ private static string GetStringLiteral(ExpressionSyntax expr) => } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/BreakFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/BreakFunction.cs similarity index 87% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/BreakFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/BreakFunction.cs index 1a323548..97963aa0 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/BreakFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/BreakFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions; +namespace KitX.Workflow.BuiltinFunctions; /// /// Break 内置函数 — 退出当前循环。 diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/CreateWorkflowFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/CreateWorkflowFunction.cs similarity index 89% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/CreateWorkflowFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/CreateWorkflowFunction.cs index 44ece492..e1bbe466 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/CreateWorkflowFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/CreateWorkflowFunction.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class CreateWorkflowFunction : IBuiltinFunctionDefinition { @@ -53,17 +53,17 @@ public BlueprintNode ConfigureNode(BlueprintNode node, CFGStatement stmt) } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public string CreateWorkflow(string name, string blockScriptSource) { if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(blockScriptSource)) return ""; - if (!DI.ServiceHost.IsInitialized) return ""; + if (!ServiceLocator.IsInitialized) return ""; try { - var storage = DI.ServiceHost.GetRequiredService(); + var storage = ServiceLocator.GetRequiredService(); var workflowId = Guid.NewGuid().ToString(); var kcsData = new KcsFileFormat { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/FlipFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/FlipFunction.cs similarity index 95% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/FlipFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/FlipFunction.cs index 0d0f1690..a69a5d53 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/FlipFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/FlipFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// Flip 内置函数 — 交替路由控制流。每次执行时交替选择两个输出分支之一。 @@ -96,7 +96,7 @@ private static string GetStringLiteral(ExpressionSyntax expr) => } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { // ────────────────────────────────────────────── // Partial class — Flip 的运行时方法和状态 diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/GetFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/GetFunction.cs similarity index 94% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/GetFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/GetFunction.cs index 3d585e06..7f612b95 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/GetFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/GetFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions; +namespace KitX.Workflow.BuiltinFunctions; /// /// Get builtin function — reads a variable value from global scope. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/GetPluginInfoByNameFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/GetPluginInfoByNameFunction.cs similarity index 90% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/GetPluginInfoByNameFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/GetPluginInfoByNameFunction.cs index e4411ef9..a3f51953 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/GetPluginInfoByNameFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/GetPluginInfoByNameFunction.cs @@ -1,13 +1,13 @@ -using System.Text.Json; +using System.Text.Json; using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Plugin; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class GetPluginInfoByNameFunction : IBuiltinFunctionDefinition { @@ -63,17 +63,17 @@ private static string StripQuotes(string s) } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public string GetPluginInfoByName(string pluginName) { if (string.IsNullOrEmpty(pluginName)) return "{}"; - if (!DI.ServiceHost.IsInitialized) return "{}"; + if (!ServiceLocator.IsInitialized) return "{}"; try { - var pluginService = DI.ServiceHost.GetRequiredService(); + var pluginService = ServiceLocator.GetRequiredService(); var plugin = pluginService.GetInstalledPlugins() .FirstOrDefault(p => p.PluginInfo?.Name == pluginName); if (plugin?.PluginInfo == null) return "{}"; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/InstallPluginFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/InstallPluginFunction.cs similarity index 84% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/InstallPluginFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/InstallPluginFunction.cs index d2c3d0b8..61d9efec 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/InstallPluginFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/InstallPluginFunction.cs @@ -1,12 +1,12 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Plugin; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class InstallPluginFunction : IBuiltinFunctionDefinition { @@ -47,17 +47,17 @@ public class InstallPluginFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public bool InstallPlugin(string kxpPath) { if (string.IsNullOrEmpty(kxpPath)) return false; - if (!DI.ServiceHost.IsInitialized) return false; + if (!ServiceLocator.IsInitialized) return false; try { - var pluginService = DI.ServiceHost.GetRequiredService(); + var pluginService = ServiceLocator.GetRequiredService(); return pluginService.ImportPluginAsync(kxpPath).GetAwaiter().GetResult(); } catch (Exception ex) diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/JsonGetFieldFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/JsonGetFieldFunction.cs similarity index 95% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/JsonGetFieldFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/JsonGetFieldFunction.cs index 57214d64..35b187e8 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/JsonGetFieldFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/JsonGetFieldFunction.cs @@ -1,12 +1,12 @@ -using System.Text.Json; +using System.Text.Json; using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class JsonGetFieldFunction : IBuiltinFunctionDefinition { @@ -64,7 +64,7 @@ private static string StripQuotes(string s) } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ListPluginNamesFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ListPluginNamesFunction.cs similarity index 85% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ListPluginNamesFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ListPluginNamesFunction.cs index 2038c5f4..74dd5297 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ListPluginNamesFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ListPluginNamesFunction.cs @@ -1,13 +1,13 @@ -using System.Text.Json; +using System.Text.Json; using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Plugin; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class ListPluginNamesFunction : IBuiltinFunctionDefinition { @@ -46,20 +46,20 @@ public class ListPluginNamesFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public string ListPluginNames() { - if (!DI.ServiceHost.IsInitialized) + if (!ServiceLocator.IsInitialized) { - Log.Warning("[BlockScriptGlobals] ListPluginNames: ServiceHost not initialized"); + Log.Warning("[BlockScriptGlobals] ListPluginNames: ServiceLocator not initialized"); return "[]"; } try { - var pluginService = DI.ServiceHost.GetRequiredService(); + var pluginService = ServiceLocator.GetRequiredService(); var plugins = pluginService.GetInstalledPlugins(); var names = plugins .Where(p => p.PluginInfo != null) diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ListWorkflowsFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ListWorkflowsFunction.cs similarity index 86% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ListWorkflowsFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ListWorkflowsFunction.cs index 4bb1bba0..012ed872 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ListWorkflowsFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ListWorkflowsFunction.cs @@ -1,12 +1,12 @@ -using System.Text.Json; +using System.Text.Json; using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class ListWorkflowsFunction : IBuiltinFunctionDefinition { @@ -45,20 +45,20 @@ public class ListWorkflowsFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public string ListWorkflows() { - if (!DI.ServiceHost.IsInitialized) + if (!ServiceLocator.IsInitialized) { - Log.Warning("[BlockScriptGlobals] ListWorkflows: ServiceHost not initialized"); + Log.Warning("[BlockScriptGlobals] ListWorkflows: ServiceLocator not initialized"); return "[]"; } try { - var storage = DI.ServiceHost.GetRequiredService(); + var storage = ServiceLocator.GetRequiredService(); var workflows = storage.DiscoverWorkflowsAsync().GetAwaiter().GetResult(); var info = workflows.Select(w => new { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/LoopFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/LoopFunction.cs similarity index 94% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/LoopFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/LoopFunction.cs index fb9c1ecc..cbe8497f 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/LoopFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/LoopFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// Loop 内置函数 — 循环控制流。 @@ -100,7 +100,7 @@ private static string GetStringLiteral(ExpressionSyntax expr) => } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PauseFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PauseFunction.cs similarity index 89% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PauseFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PauseFunction.cs index 0cc9cceb..8f2b961f 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PauseFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PauseFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// Pause 内置函数 — 暂停执行指定毫秒数。 @@ -53,7 +53,7 @@ public List EmitStatements(CFGStatement stmt, CSEmitContext ctx } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PluginCallFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PluginCallFunction.cs similarity index 92% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PluginCallFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PluginCallFunction.cs index 6d664987..a0b74035 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PluginCallFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PluginCallFunction.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// PluginCall 内置函数 — 调用本机插件函数。 @@ -44,7 +44,7 @@ public List EmitStatements(CFGStatement stmt, CSEmitContext ctx } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PluginCallWithTargetFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PluginCallWithTargetFunction.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PluginCallWithTargetFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PluginCallWithTargetFunction.cs index 0d3fa9f1..caedfd1c 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PluginCallWithTargetFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PluginCallWithTargetFunction.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// PluginCallWithTarget 内置函数 — 调用远程设备上的插件。 @@ -181,7 +181,7 @@ private static string StripQuotes(string s) } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PrintFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PrintFunction.cs similarity index 89% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PrintFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PrintFunction.cs index 1fd63332..6a095b93 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/PrintFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/PrintFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// Print 内置函数 — 输出值到控制台。 @@ -53,7 +53,7 @@ public List EmitStatements(CFGStatement stmt, CSEmitContext ctx } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ReadTextFileFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ReadTextFileFunction.cs similarity index 89% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ReadTextFileFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ReadTextFileFunction.cs index 32595888..5348877a 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ReadTextFileFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ReadTextFileFunction.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class ReadTextFileFunction : IBuiltinFunctionDefinition { @@ -46,7 +46,7 @@ public class ReadTextFileFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/RunWorkflowFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/RunWorkflowFunction.cs similarity index 84% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/RunWorkflowFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/RunWorkflowFunction.cs index 45820e97..c53ba4f7 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/RunWorkflowFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/RunWorkflowFunction.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class RunWorkflowFunction : IBuiltinFunctionDefinition { @@ -46,17 +46,17 @@ public class RunWorkflowFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public bool RunWorkflow(string workflowId) { if (string.IsNullOrEmpty(workflowId)) return false; - if (!DI.ServiceHost.IsInitialized) return false; + if (!ServiceLocator.IsInitialized) return false; try { - var wfService = DI.ServiceHost.GetRequiredService(); + var wfService = ServiceLocator.GetRequiredService(); return wfService.RunWorkflowAsync(workflowId).GetAwaiter().GetResult(); } catch (Exception ex) diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/SetFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/SetFunction.cs similarity index 93% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/SetFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/SetFunction.cs index b6b294ed..14ab179f 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/SetFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/SetFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// Set builtin function — writes a value to a global variable. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StartPluginFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StartPluginFunction.cs similarity index 86% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StartPluginFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StartPluginFunction.cs index adef6ea3..5cfa963b 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StartPluginFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StartPluginFunction.cs @@ -1,12 +1,12 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Plugin; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class StartPluginFunction : IBuiltinFunctionDefinition { @@ -47,17 +47,17 @@ public class StartPluginFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public bool StartPlugin(string pluginName) { if (string.IsNullOrEmpty(pluginName)) return false; - if (!DI.ServiceHost.IsInitialized) return false; + if (!ServiceLocator.IsInitialized) return false; try { - var pluginService = DI.ServiceHost.GetRequiredService(); + var pluginService = ServiceLocator.GetRequiredService(); var plugin = pluginService.GetInstalledPlugins() .FirstOrDefault(p => p.PluginInfo?.Name == pluginName); if (plugin == null) return false; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StopPluginFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StopPluginFunction.cs similarity index 86% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StopPluginFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StopPluginFunction.cs index 8c3cb271..c0c5ad17 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StopPluginFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StopPluginFunction.cs @@ -1,12 +1,12 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Plugin; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class StopPluginFunction : IBuiltinFunctionDefinition { @@ -47,17 +47,17 @@ public class StopPluginFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public bool StopPlugin(string pluginName) { if (string.IsNullOrEmpty(pluginName)) return false; - if (!DI.ServiceHost.IsInitialized) return false; + if (!ServiceLocator.IsInitialized) return false; try { - var pluginService = DI.ServiceHost.GetRequiredService(); + var pluginService = ServiceLocator.GetRequiredService(); var plugin = pluginService.GetInstalledPlugins() .FirstOrDefault(p => p.PluginInfo?.Name == pluginName); if (plugin == null) return false; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StopWorkflowFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StopWorkflowFunction.cs similarity index 84% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StopWorkflowFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StopWorkflowFunction.cs index fc1af6cc..89da297b 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/StopWorkflowFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/StopWorkflowFunction.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class StopWorkflowFunction : IBuiltinFunctionDefinition { @@ -46,17 +46,17 @@ public class StopWorkflowFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { public bool StopWorkflow(string workflowId) { if (string.IsNullOrEmpty(workflowId)) return false; - if (!DI.ServiceHost.IsInitialized) return false; + if (!ServiceLocator.IsInitialized) return false; try { - var wfService = DI.ServiceHost.GetRequiredService(); + var wfService = ServiceLocator.GetRequiredService(); return wfService.StopWorkflowAsync(workflowId).GetAwaiter().GetResult(); } catch (Exception ex) diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ToLoopCondFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ToLoopCondFunction.cs similarity index 95% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ToLoopCondFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ToLoopCondFunction.cs index 749493e7..9a8d749f 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/ToLoopCondFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/ToLoopCondFunction.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// ToLoopCond 内置函数 — 标记循环体的结尾并返回循环条件块。 @@ -113,7 +113,7 @@ private static string GetStringLiteral(ExpressionSyntax expr) => } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { // ────────────────────────────────────────────── // Partial class — ToLoopCond 的运行时方法 diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/TryGetDeviceFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/TryGetDeviceFunction.cs similarity index 92% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/TryGetDeviceFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/TryGetDeviceFunction.cs index 4fd538c6..0d09d824 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/TryGetDeviceFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/TryGetDeviceFunction.cs @@ -1,13 +1,13 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using KitX.Core.Contract.Device; using KitX.Shared.CSharp.Device; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { /// /// TryGetDevice 内置函数 — 根据设备名称查找已连接设备。 @@ -111,7 +111,7 @@ private static string StripQuotes(string s) } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { @@ -129,14 +129,14 @@ public partial class BlockScriptExecutionGlobals try { - if (!DI.ServiceHost.IsInitialized) + if (!ServiceLocator.IsInitialized) { - Log.Warning("[BlockScriptGlobals] TryGetDevice: ServiceHost not initialized"); + Log.Warning("[BlockScriptGlobals] TryGetDevice: ServiceLocator not initialized"); return null; } - var deviceServer = DI.ServiceHost.GetRequiredService(); - var discoveryService = DI.ServiceHost.GetRequiredService(); + var deviceServer = ServiceLocator.GetRequiredService(); + var discoveryService = ServiceLocator.GetRequiredService(); var signedInDevices = deviceServer.GetSignedInDevices(); diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/WriteTextFileFunction.cs b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/WriteTextFileFunction.cs similarity index 90% rename from KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/WriteTextFileFunction.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/WriteTextFileFunction.cs index 6ee0db8a..cb6e6fd4 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/BuiltinFunctions/WriteTextFileFunction.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/BuiltinFunctions/WriteTextFileFunction.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.Conversion; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; -namespace KitX.Core.Workflow.BuiltinFunctions +namespace KitX.Workflow.BuiltinFunctions { public class WriteTextFileFunction : IBuiltinFunctionDefinition { @@ -47,7 +47,7 @@ public class WriteTextFileFunction : IBuiltinFunctionDefinition } } -namespace KitX.Core.Workflow.BlockScripting +namespace KitX.Workflow.BlockScripting { public partial class BlockScriptExecutionGlobals { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/BlueprintDebugContext.cs b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/BlueprintDebugContext.cs similarity index 75% rename from KitX Clients/KitX Core/KitX.Core/Workflow/CFG/BlueprintDebugContext.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/CFG/BlueprintDebugContext.cs index b4d1bbd7..aea104ae 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/BlueprintDebugContext.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/BlueprintDebugContext.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.CFG; +namespace KitX.Workflow.CFG; public class BlueprintDebugContext { diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGBlock.cs b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGBlock.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGBlock.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGBlock.cs index c530b7bf..b9e243f0 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGBlock.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGBlock.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.CFG; +namespace KitX.Workflow.CFG; /// /// Type of a CFG block, indicating its structural role in the control flow. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGEdge.cs b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGEdge.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGEdge.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGEdge.cs index defa55e3..f3462421 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGEdge.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGEdge.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.CFG; +namespace KitX.Workflow.CFG; /// /// Type of a control flow edge between blocks. Making edge semantics diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGStatement.cs b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGStatement.cs similarity index 99% rename from KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGStatement.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGStatement.cs index 249e1c79..989e20b4 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/CFGStatement.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/CFGStatement.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.CFG; +namespace KitX.Workflow.CFG; /// /// Kinds of statements in the CFG. Unified statement kind replacing the former Pipeline.FormattedStatementKind. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/ConstDeclaration.cs b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/ConstDeclaration.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/CFG/ConstDeclaration.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/CFG/ConstDeclaration.cs index 374767d3..9e6446fa 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/ConstDeclaration.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/ConstDeclaration.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.CFG; +namespace KitX.Workflow.CFG; /// /// A constant declaration from #ConstBlock. Preserves both the raw source diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/ControlFlowGraph.cs b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/ControlFlowGraph.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/CFG/ControlFlowGraph.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/CFG/ControlFlowGraph.cs index 9e4ee88a..af96a512 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/CFG/ControlFlowGraph.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/CFG/ControlFlowGraph.cs @@ -1,7 +1,7 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using System.Text; -namespace KitX.Core.Workflow.CFG; +namespace KitX.Workflow.CFG; /// /// The Control Flow Graph — canonical intermediate representation for diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/ConstantValueRewriter.cs b/KitX Clients/KitX Workflow/KitX.Workflow/ConstantValueRewriter.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/ConstantValueRewriter.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/ConstantValueRewriter.cs index 3757a612..fffa8730 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/ConstantValueRewriter.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/ConstantValueRewriter.cs @@ -1,8 +1,8 @@ -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// Rewriter for injecting constant values into variable declarations using CSharpSyntaxRewriter diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptExecutor.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptExecutor.cs new file mode 100644 index 00000000..e1cb8925 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptExecutor.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.Contract.Models; + +namespace KitX.Workflow.Contract; + +/// +/// Block script executor interface - executes parsed block scripts. +/// +/// Moved to the workflow library's internal Contract surface: its methods operate on +/// the parsed BlockScript model (also internal), and the Dashboard no longer +/// invokes executor methods directly (it routes execution through IBlockScriptService / +/// IBlueprintService, which take source strings). +/// +public interface IBlockScriptExecutor +{ + /// + /// Executes a block script + /// + /// The parsed block script + /// Input parameters + /// Cancellation token + /// Execution result + Task ExecuteAsync( + BlockScript script, + Dictionary? parameters = null, + CancellationToken cancellationToken = default); + + /// + /// Validates a block script + /// + BlockScriptValidationResult Validate(BlockScript script); + + /// + /// Sets an optional debug controller for interactive execution (breakpoints, step, slow). + /// Pass null to disable debug mode. + /// + void SetDebugger(IBlueprintDebugController? debugger); +} diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptPipeline.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptPipeline.cs new file mode 100644 index 00000000..7bac2364 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptPipeline.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using KitX.Core.Contract.Workflow; + +namespace KitX.Workflow.Contract; + +/// +/// Block script parser interface - parses C# scripts with block attributes. +/// +/// Internal to the workflow pipeline (only BlockScriptExecutor / DI use it); +/// moved out of the public Contract surface. +/// +public interface IBlockScriptParser +{ + /// + /// Parses a block-based script from source code + /// + /// The C# source code with block attributes + /// Parsed block script result + BlockScriptParseResult Parse(string sourceCode); + + /// + /// Parses a block-based script from source code asynchronously + /// + Task ParseAsync(string sourceCode); + + /// + /// Validates block script syntax and structure + /// + BlockScriptValidationResult Validate(string sourceCode); +} + +/// +/// Block scope manager interface - manages variable scoping. +/// Internal to the workflow pipeline. +/// +public interface IBlockScopeManager +{ + /// + /// Gets the global (ConstBlock) scope + /// + IBlockScope GlobalScope { get; } + + /// + /// Resolves a variable name to its value (searches local then global) + /// + object? ResolveVariable(string name); + + /// + /// Sets a variable value in the appropriate scope + /// + void SetVariable(string name, object? value, bool global = false); + + /// + /// Checks if a variable exists in any scope + /// + bool HasVariable(string name); + + /// + /// Clears all local scopes (called between executions) + /// + void ClearLocalScopes(); +} + +/// +/// Variable scope interface. +/// Internal to the workflow pipeline. +/// +public interface IBlockScope +{ + /// + /// Name of the block this scope belongs to + /// + string BlockName { get; } + + /// + /// Whether this is the global scope + /// + bool IsGlobal { get; } + + /// + /// Gets a variable value + /// + object? GetVariable(string name); + + /// + /// Sets a variable value + /// + void SetVariable(string name, object? value); + + /// + /// Checks if a variable exists in this scope + /// + bool HasVariable(string name); + + /// + /// Gets all variables in this scope + /// + Dictionary GetAllVariables(); +} diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptPipelineService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptPipelineService.cs new file mode 100644 index 00000000..13d92353 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlockScriptPipelineService.cs @@ -0,0 +1,45 @@ +using System.Threading; +using System.Threading.Tasks; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.Contract.Models; + +namespace KitX.Workflow.Contract; + +/// +/// Internal pipeline extension of . +/// +/// Carries the BlockScript methods that operate on the parsed BlockScript / +/// BlockScriptParseResult models — these are pipeline-internal and not consumed +/// by the Dashboard, so they are split out of the public Contract interface together +/// with the model types they reference (which also live in this namespace). +/// Implemented by the same BlockScriptServiceImpl that implements +/// IBlockScriptService. +/// +public interface IBlockScriptPipelineService +{ + /// + /// Parses a block script from source code. + /// + BlockScriptParseResult ParseBlockScript(string sourceCode); + + /// + /// Parses a block script from source code asynchronously. + /// + Task ParseBlockScriptAsync(string sourceCode); + + /// + /// Executes an already-parsed block script. + /// + Task ExecuteBlockScriptAsync( + BlockScript script, + System.Collections.Generic.Dictionary? parameters = null, + CancellationToken cancellationToken = default); + + /// + /// Compiles a parsed BlockScript and persists the compiled assembly to disk. + /// + /// The parsed BlockScript to compile. + /// The workflow ID for assembly naming. + /// True if compilation and persistence succeeded. + Task CompileAndPersistAsync(BlockScript script, string workflowId); +} diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlueprintConverters.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlueprintConverters.cs new file mode 100644 index 00000000..9cea76cd --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IBlueprintConverters.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; + +namespace KitX.Workflow.Contract; + +/// +/// Interface for converting BlockScript to Blueprint. +/// Internal to the workflow pipeline (consumed by BlueprintService). +/// +public interface IBlockScriptToBlueprintConverter +{ + /// + /// Convert BlockScript source code to Blueprint + /// + /// BlockScript source code + /// Helper functions available + /// Converted Blueprint + KitX.Core.Contract.Workflow.Blueprint Convert(string sourceCode, List? helperFunctions = null); + + /// + /// Convert parsed BlockScript to Blueprint + /// + /// Parsed BlockScript + /// Converted Blueprint + KitX.Core.Contract.Workflow.Blueprint Convert(KitX.Workflow.Contract.Models.BlockScript script); +} + +/// +/// Interface for converting Blueprint to BlockScript. +/// Internal to the workflow pipeline (consumed by BlueprintService). +/// +public interface IBlueprintToBlockScriptConverter +{ + /// + /// Convert Blueprint to BlockScript source code + /// + /// Blueprint to convert + /// BlockScript source code + string Convert(KitX.Core.Contract.Workflow.Blueprint blueprint); + + /// + /// Convert Blueprint to parsed BlockScript + /// + /// Blueprint to convert + /// Parsed BlockScript + KitX.Workflow.Contract.Models.BlockScript ConvertToBlockScript(KitX.Core.Contract.Workflow.Blueprint blueprint); +} diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/ILayoutService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/ILayoutService.cs new file mode 100644 index 00000000..18ac67dc --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/ILayoutService.cs @@ -0,0 +1,10 @@ +namespace KitX.Workflow.Contract; + +/// +/// Interface for layout service. +/// Internal to the workflow pipeline (consumed by BlockScriptToBlueprintConverter). +/// +public interface ILayoutService +{ + void LayoutNodes(KitX.Core.Contract.Workflow.Blueprint blueprint); +} diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/INodeExportStrategy.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/INodeExportStrategy.cs new file mode 100644 index 00000000..f074311f --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/INodeExportStrategy.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; + +namespace KitX.Workflow.Contract; + +using ContractWorkflow = KitX.Core.Contract.Workflow; + +/// +/// Helper service providing data resolution utilities for node export strategies. +/// Implemented by BlueprintToBlockScriptConverter. +/// Internal to the workflow pipeline. +/// +public interface INodeExportHelper +{ + /// + /// Resolves the input value for a pin by tracing data connections. + /// Returns ConstName for const references, PubVarName for pubvar references, + /// or the pin's default value. + /// + string GetInputValue(ContractWorkflow.BlueprintNode node, string pinName); + + /// + /// Resolves all non-Exec input arguments for a node, returning them as a comma-separated string. + /// + string GetInputArgs(ContractWorkflow.BlueprintNode node); + + /// + /// The blueprint being converted. + /// + ContractWorkflow.Blueprint Blueprint { get; } + + /// + /// Returns the PubVar name assigned to the given output pin, or null if no data connection exists. + /// + string? GetOutputPubVar(ContractWorkflow.BlueprintNode node, string pinName); + + /// + /// Returns true if the given output pin is consumed by at least one data connection. + /// + bool IsOutputConsumed(ContractWorkflow.BlueprintNode node, string pinName); +} + +/// +/// Strategy for converting a specific node type to a BlockScript statement. +/// Each node type that participates in reverse conversion provides an implementation, +/// eliminating the need for switch-based dispatch in the converter. +/// Internal to the workflow pipeline. +/// +public interface INodeExportStrategy +{ + /// + /// The node type this strategy handles. + /// + ContractWorkflow.BlueprintNodeType NodeType { get; } + + /// + /// Whether this node type represents a control flow construct (Branch, Loop, etc.). + /// Used by the converter to determine main flow termination and sub-graph processing. + /// + bool IsControlFlow { get; } + + /// + /// Converts the node to a BlockScript statement, or null if the node should be skipped. + /// + KitX.Workflow.Contract.Models.BlockStatement? ToStatement(ContractWorkflow.BlueprintNode node, INodeExportHelper helper); + + /// + /// For control flow nodes: returns the output arm configuration. + /// Each arm defines an output pin name and whether it represents a loopback. + /// Non-control-flow strategies return an empty collection. + /// + IEnumerable GetOutputArms(ContractWorkflow.BlueprintNode node); +} + +/// +/// Describes a single output arm of a control flow node (e.g., Branch's True/False, Loop's LoopBody/LoopEnd). +/// Internal to the workflow pipeline. +/// +public struct OutputArmDescriptor +{ + /// + /// The output pin name (e.g., Pins.True, Pins.False, Pins.LoopBody, Pins.LoopEnd) + /// + public string PinName { get; set; } + + /// + /// Whether this arm loops back to a parent node (LoopBody loops back to the Loop node) + /// + public bool IsLoopback { get; set; } +} diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IPluginManager.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IPluginManager.cs new file mode 100644 index 00000000..69fd9451 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/IPluginManager.cs @@ -0,0 +1,41 @@ +using KitX.Core.Contract.Workflow; + +namespace KitX.Workflow.Contract; + +/// +/// 插件管理器接口 - BlockScripting 使用此接口调用插件方法。 +/// Copy of Kscript.CSharp.Parser.Core.IPluginManager for BlockScripting use +/// without depending on the KCS parser assembly. +/// 实际实现由 RealPluginManager 提供。 +/// +public interface IPluginManager +{ + /// + /// 调用插件方法 + /// + /// 返回值类型 + /// 调用信息 + /// 插件方法的返回值 + T Call(PluginCallInfo callInfo); + + /// + /// 调用插件方法(无返回值) + /// + /// 调用信息 + void Call(PluginCallInfo callInfo); + + /// + /// 检查插件是否存在 + /// + /// 插件名称 + /// 插件是否存在 + bool IsPluginExists(string pluginName); + + /// + /// 检查插件方法是否存在 + /// + /// 插件名称 + /// 方法名称 + /// 方法是否存在 + bool IsMethodExists(string pluginName, string methodName); +} diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockDefinition.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockDefinition.cs new file mode 100644 index 00000000..f29a04d5 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockDefinition.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; + +namespace KitX.Workflow.Contract.Models; + +/// +/// Represents a single block definition in the script +/// +public class BlockDefinition +{ + /// + /// Block type + /// + public BlockType Type { get; set; } + + /// + /// Block name (for NamedBlock) + /// + public string Name { get; set; } = string.Empty; + + /// + /// Variable declarations in this block + /// + public List Variables { get; set; } = []; + + /// + /// Statements in this block (excluding Loop statements, which are separated) + /// + public List Statements { get; set; } = []; + + /// + /// Line number in source where this block starts + /// + public int LineNumber { get; set; } + + /// + /// Name of the next block to execute when this block ends naturally + /// (i.e., not ended by Branch/Loop/ToLoopCond) + /// + public string? NextBlockName { get; set; } + + /// + /// For LoopBlock: the block name containing this loop (i.e., the parent block) + /// + public string? ParentBlockName { get; set; } +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockScript.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockScript.cs new file mode 100644 index 00000000..2ae2d2af --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockScript.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; + +using KitX.Core.Contract.Workflow; +namespace KitX.Workflow.Contract.Models; + +/// +/// Parsed block script container +/// +public class BlockScript +{ + /// + /// Global constants block (ConstBlock) + /// + public BlockDefinition? ConstBlock { get; set; } + + /// + /// Public variables block (PubVarBlock) - optional + /// + public BlockDefinition? PubVarBlock { get; set; } + + /// + /// Main entry block (MainBlock) + /// + public BlockDefinition? MainBlock { get; set; } + + /// + /// Named blocks dictionary by name + /// + public Dictionary NamedBlocks { get; set; } = []; + + /// + /// All blocks in order of appearance + /// + public List AllBlocks { get; set; } = []; + + /// + /// Loop blocks dictionary by parent block name + /// (e.g., "MainBlock" -> LoopBlock for MainBlock's Loop statement) + /// + public Dictionary LoopBlocks { get; set; } = []; + + /// + /// Raw source code (parsed input, may not include helper functions) + /// + public string SourceCode { get; set; } = string.Empty; + + /// + /// Full source code including merged helper functions (for execution) + /// + public string FullSourceCode { get; set; } = string.Empty; + + /// + /// Debug mapping from CFG statement IDs to Blueprint node IDs. + /// Populated during BP→BS conversion for use by the debug execution pipeline. + /// + public Dictionary? DebugNodeMapping { get; set; } + + /// + /// Helper functions to be made available in script execution context + /// + public List HelperFunctions { get; set; } = []; + + + /// + /// Gets a block by name (checks LoopBlocks first by block name, then NamedBlocks, then standard blocks) + /// IMPORTANT: LoopBlocks are checked FIRST because LoopBlock names (like "LoopBody") should NOT be + /// shadowed by user-defined NamedBlocks with the same name. + /// + public BlockDefinition? GetBlockByName(string name) + { + // First check LoopBlocks by the block's own name (not parent block name) + // This is critical because LoopBlocks are created for "NextBlock = Loop(...)" statements + // and their names (like "LoopBody") should take precedence over user-defined blocks + foreach (var kvp in LoopBlocks) + { + if (kvp.Value.Name == name) + return kvp.Value; + } + + // Then check NamedBlocks (user-defined blocks) + if (NamedBlocks.TryGetValue(name, out var namedBlock)) + return namedBlock; + + // Then check the standard blocks by name match + if (MainBlock?.Name == name) + return MainBlock; + if (ConstBlock?.Name == name) + return ConstBlock; + if (PubVarBlock?.Name == name) + return PubVarBlock; + + return null; + } +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockScriptModels.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockScriptModels.cs new file mode 100644 index 00000000..551f7a34 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/BlockScriptModels.cs @@ -0,0 +1,32 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Block type enumeration +/// +public enum BlockType +{ + /// + /// Constants block - variables are globally scoped and read-only + /// + ConstBlock, + + /// + /// Main block - entry point, local scope + /// + MainBlock, + + /// + /// Named block - local scope, can be called by name + /// + NamedBlock, + + /// + /// Public variable block - globally scoped and writable, but not exposed in UI editor + /// + PubVarBlock, + + /// + /// Loop block - auto-generated block containing a Loop statement + /// + LoopBlock +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/FlowControlType.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/FlowControlType.cs new file mode 100644 index 00000000..88a6bc32 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/FlowControlType.cs @@ -0,0 +1,32 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Flow control statement types +/// +public enum FlowControlType +{ + /// + /// Branch to another block based on condition + /// + Branch, + + /// + /// Loop while condition is true (Loop has three args: condition, trueBlock, falseBlock) + /// + Loop, + + /// + /// Return from script execution + /// + Return, + + /// + /// Break from current loop + /// + Break, + + /// + /// To loop condition - marks the end of a loop body and returns to loop condition + /// + ToLoopCond +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/PluginCallInfo.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/PluginCallInfo.cs new file mode 100644 index 00000000..29e5427c --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/PluginCallInfo.cs @@ -0,0 +1,59 @@ +using System; + +namespace KitX.Workflow.Contract.Models; + +/// +/// 插件调用信息,用于传递给 IPluginManager.Call 的参数。 +/// Copy of Kscript.CSharp.Parser.Models.PluginCallInfo for BlockScripting use +/// without depending on the KCS parser assembly. +/// +public class PluginCallInfo +{ + /// + /// 插件名称 + /// + public string PluginName { get; set; } = string.Empty; + + /// + /// 方法名称 + /// + public string MethodName { get; set; } = string.Empty; + + /// + /// 方法参数值数组 + /// + public object[] Parameters { get; set; } = Array.Empty(); + + /// + /// 参数类型数组 + /// + public Type[] ParameterTypes { get; set; } = Array.Empty(); + + /// + /// 参数名称数组 + /// + public string[] ParameterNames { get; set; } = Array.Empty(); + + /// + /// 目标设备名称(远程调用时使用)。如果为空或 null,则为本地调用。 + /// + public string? TargetDevice { get; set; } + + public PluginCallInfo() + { + } + + public PluginCallInfo(string pluginName, string methodName, object[] parameters, Type[] parameterTypes, string[] parameterNames) + { + PluginName = pluginName; + MethodName = methodName; + Parameters = parameters; + ParameterTypes = parameterTypes; + ParameterNames = parameterNames; + } + + public override string ToString() + { + return $"{PluginName}.{MethodName}({string.Join(", ", Parameters)})"; + } +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Results/BlockExecutionResult.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Results/BlockExecutionResult.cs new file mode 100644 index 00000000..99885ddb --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Results/BlockExecutionResult.cs @@ -0,0 +1,48 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Result of executing a block - used by state machine for flow control +/// +public class BlockExecutionResult +{ + /// + /// Whether execution should continue to next block + /// + public bool ShouldContinue { get; set; } = true; + + /// + /// Name of the next block to execute (null means end of script) + /// + public string? NextBlockName { get; set; } + + /// + /// Whether this is a return (end of entire script) + /// + public bool IsReturn { get; set; } + + /// + /// Return value if IsReturn is true + /// + public object? ReturnValue { get; set; } + + /// + /// Create a result for continuing to next block + /// + public static BlockExecutionResult ContinueTo(string? nextBlockName) => new() + { + ShouldContinue = true, + NextBlockName = nextBlockName, + IsReturn = false + }; + + /// + /// Create a result for end of script + /// + public static BlockExecutionResult Return(object? value = null) => new() + { + ShouldContinue = false, + NextBlockName = null, + IsReturn = true, + ReturnValue = value + }; +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Results/BlockScriptParseResult.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Results/BlockScriptParseResult.cs new file mode 100644 index 00000000..de063295 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Results/BlockScriptParseResult.cs @@ -0,0 +1,27 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Result of parsing operation +/// +public class BlockScriptParseResult +{ + /// + /// Whether parsing was successful + /// + public bool IsSuccess { get; set; } + + /// + /// Error message if parsing failed + /// + public string? ErrorMessage { get; set; } + + /// + /// Line number where error occurred + /// + public int ErrorLine { get; set; } + + /// + /// The parsed script if successful + /// + public BlockScript? Script { get; set; } +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/BlockStatement.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/BlockStatement.cs new file mode 100644 index 00000000..8eed3ccc --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/BlockStatement.cs @@ -0,0 +1,24 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Base class for statements within a block +/// +public abstract class BlockStatement +{ + /// + /// Debug statement ID — preserved through BP⇄BS round-trip. + /// Set by CFG→BS conversion; consumed by BS→CFG conversion. + /// Empty means "unset; generate a new ID". + /// + public string StatementId { get; set; } = string.Empty; + + /// + /// Line number in source + /// + public int LineNumber { get; set; } + + /// + /// Original source code for this statement + /// + public string SourceCode { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/ExpressionStatement.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/ExpressionStatement.cs new file mode 100644 index 00000000..b2356df4 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/ExpressionStatement.cs @@ -0,0 +1,12 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Expression statement +/// +public class ExpressionStatement : BlockStatement +{ + /// + /// The expression to execute + /// + public string Expression { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/FlowControlStatement.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/FlowControlStatement.cs new file mode 100644 index 00000000..45d6e354 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/FlowControlStatement.cs @@ -0,0 +1,51 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Flow control statement +/// +public class FlowControlStatement : BlockStatement +{ + /// + /// Type of flow control + /// + public FlowControlType ControlType { get; set; } + + /// + /// Condition expression (for Branch/Loop) + /// + public string ConditionExpression { get; set; } = string.Empty; + + /// + /// Target block name when condition is true (for Branch/Loop) + /// + public string TrueBlockName { get; set; } = string.Empty; + + /// + /// Target block name when condition is false (for Branch/Loop) + /// For Loop: this is the loop exit block + /// + public string FalseBlockName { get; set; } = string.Empty; + + /// + /// For ToLoopCond: the block name containing the Loop statement to return to + /// + public string? ToLoopCondReturnTo { get; set; } + + /// + /// Regenerates SourceCode from current field values. + /// Call after updating TrueBlockName/FalseBlockName/etc. to keep SourceCode in sync. + /// + public void RegenerateSourceCode() + { + SourceCode = ControlType switch + { + FlowControlType.Branch => $"NextBlock = Branch({ConditionExpression}, \"{TrueBlockName}\", \"{FalseBlockName}\");", + FlowControlType.Loop => $"NextBlock = Loop({ConditionExpression}, \"{TrueBlockName}\", \"{FalseBlockName}\");", + FlowControlType.ToLoopCond => ToLoopCondReturnTo != null + ? $"NextBlock = ToLoopCond(\"{ToLoopCondReturnTo}\");" + : "ToLoopCond();", + FlowControlType.Break => "Break();", + _ => SourceCode + }; + } +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/VariableDeclarationStatement.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/VariableDeclarationStatement.cs new file mode 100644 index 00000000..16ac10b7 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/Statements/VariableDeclarationStatement.cs @@ -0,0 +1,12 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Variable declaration statement +/// +public class VariableDeclarationStatement : BlockStatement +{ + /// + /// The variable declaration + /// + public VariableDeclaration Declaration { get; set; } = new(); +} \ No newline at end of file diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/VariableDeclaration.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/VariableDeclaration.cs new file mode 100644 index 00000000..99368a34 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Contract/Models/VariableDeclaration.cs @@ -0,0 +1,27 @@ +namespace KitX.Workflow.Contract.Models; + +/// +/// Variable declaration +/// +public class VariableDeclaration +{ + /// + /// Variable name + /// + public string Name { get; set; } = string.Empty; + + /// + /// Variable type as string + /// + public string Type { get; set; } = "object"; + + /// + /// Initial value expression as string (for evaluation at parse time or execution time) + /// + public string? InitialValueExpression { get; set; } + + /// + /// Default value (pre-evaluated for const block) + /// + public object? DefaultValue { get; set; } +} \ No newline at end of file diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BP2CFGConverter.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BP2CFGConverter.cs similarity index 96% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BP2CFGConverter.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BP2CFGConverter.cs index 93f0ef9d..141bf1a7 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BP2CFGConverter.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BP2CFGConverter.cs @@ -1,20 +1,20 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.Blueprint; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.Blueprint; using Microsoft.CodeAnalysis.CSharp.Syntax; using Serilog; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Pins; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Pins; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; +namespace KitX.Workflow.Conversion; /// /// Builds a from a . /// This is the unified BP→BS algorithm. /// -/// Whether is present or not, +/// Whether is present or not, /// this single algorithm produces a CFG. When BlockScopes are available, they guide /// block membership; when absent, blocks are derived from topology alone. /// @@ -38,7 +38,7 @@ public BP2CFGConverter( /// Builds a ControlFlowGraph from a Blueprint. /// Single entry point that unifies the BlockScopes-based and topology-based paths. /// - public ControlFlowGraph Build(Contract.Workflow.Blueprint blueprint) + public ControlFlowGraph Build(KitX.Core.Contract.Workflow.Blueprint blueprint) { var cfg = new ControlFlowGraph { @@ -149,7 +149,7 @@ public ControlFlowGraph Build(Contract.Workflow.Blueprint blueprint) // ════════════════════════════════════════════════════════════════════ private void AnalyzeConnections( - Contract.Workflow.Blueprint blueprint, + KitX.Core.Contract.Workflow.Blueprint blueprint, Dictionary nodeById, List execConns, List dataConns, @@ -249,7 +249,7 @@ or BlueprintNodeType.CallHelper // ════════════════════════════════════════════════════════════════════ private static HashSet FindReachableNodeIds( - Contract.Workflow.Blueprint blueprint, + KitX.Core.Contract.Workflow.Blueprint blueprint, Dictionary nodeById, List execConns) { @@ -285,7 +285,7 @@ private static HashSet FindReachableNodeIds( // ════════════════════════════════════════════════════════════════════ private void BuildBlocksFromScopes( - Contract.Workflow.Blueprint blueprint, + KitX.Core.Contract.Workflow.Blueprint blueprint, ControlFlowGraph cfg, Dictionary nodeById, HashSet reachableNodeIds, @@ -319,7 +319,7 @@ private void BuildBlocksFromScopes( // ════════════════════════════════════════════════════════════════════ private void BuildBlocksFromTopology( - Contract.Workflow.Blueprint blueprint, + KitX.Core.Contract.Workflow.Blueprint blueprint, ControlFlowGraph cfg, Dictionary nodeById, HashSet reachableNodeIds, @@ -351,7 +351,7 @@ private void BuildBlocksFromTopology( private void WalkNode( BlueprintNode node, CFGBlock currentBlock, ControlFlowGraph cfg, Dictionary nodeById, HashSet reachableNodeIds, - List execConns, Contract.Workflow.Blueprint blueprint, + List execConns, KitX.Core.Contract.Workflow.Blueprint blueprint, HashSet visited, List pendingControlFlowNodes, Dictionary loopNodes, Dictionary loopOwnerBlockNames, @@ -432,7 +432,7 @@ private void WalkNode( private void ProcessSubGraphs( ControlFlowGraph cfg, Dictionary nodeById, HashSet reachableNodeIds, List execConns, - Contract.Workflow.Blueprint blueprint, + KitX.Core.Contract.Workflow.Blueprint blueprint, List pendingControlFlowNodes, Dictionary loopNodes, Dictionary loopOwnerBlockNames, @@ -459,7 +459,7 @@ private void ProcessSubGraphs( private void ProcessControlFlowSubGraph( BlueprintNode cfNode, ControlFlowGraph cfg, Dictionary nodeById, HashSet reachableNodeIds, - List execConns, Contract.Workflow.Blueprint blueprint, + List execConns, KitX.Core.Contract.Workflow.Blueprint blueprint, Dictionary loopNodes, Dictionary loopOwnerBlockNames, ref int blockCounter) { @@ -529,7 +529,7 @@ private void ProcessControlFlowSubGraph( // ════════════════════════════════════════════════════════════════════ private void BuildEdgesFromTopology( - ControlFlowGraph cfg, Contract.Workflow.Blueprint blueprint, + ControlFlowGraph cfg, KitX.Core.Contract.Workflow.Blueprint blueprint, Dictionary nodeById, List execConns) { foreach (var block in cfg.Blocks) @@ -635,7 +635,7 @@ private void BuildEdgesFromTopology( /// This replaces the ad-hoc NextBlockName fallback logic. /// private static void ResolveMissingNextBlockNames( - ControlFlowGraph cfg, Contract.Workflow.Blueprint blueprint, + ControlFlowGraph cfg, KitX.Core.Contract.Workflow.Blueprint blueprint, Dictionary nodeById, List execConns) { foreach (var block in cfg.Blocks) @@ -754,7 +754,7 @@ private static void SetParentLoopReferences(ControlFlowGraph cfg) private CFGStatement? GenerateStatement( BlueprintNode node, Dictionary nodeById, - List execConns, Contract.Workflow.Blueprint blueprint) + List execConns, KitX.Core.Contract.Workflow.Blueprint blueprint) { // Delegate to existing strategy-based generation, then convert to CFGStatement var blockStmt = GenerateBlockStatement(node, nodeById, execConns, blueprint); @@ -769,7 +769,7 @@ private static void SetParentLoopReferences(ControlFlowGraph cfg) /// private BlockStatement? GenerateBlockStatement( BlueprintNode node, Dictionary nodeById, - List execConns, Contract.Workflow.Blueprint blueprint) + List execConns, KitX.Core.Contract.Workflow.Blueprint blueprint) { switch (node.NodeType) { @@ -872,7 +872,7 @@ private void PostProcessCallReturn(BlueprintNode node, BlockStatement stmt) /// Sets the context for PubVar resolution during statement generation. /// Called before Build() when BlockScopes path is used. /// - public void SetContext(Contract.Workflow.Blueprint blueprint, ConversionContext? ctx) + public void SetContext(KitX.Core.Contract.Workflow.Blueprint blueprint, ConversionContext? ctx) { _exportHelper.SetContext(blueprint, ctx); _currentCtx = ctx; @@ -999,7 +999,7 @@ private static CFGStatement CreateToLoopCondStatement(string? returnTo) /// private static void ResolveControlFlowTargets( ControlFlowGraph cfg, - Contract.Workflow.Blueprint blueprint, + KitX.Core.Contract.Workflow.Blueprint blueprint, Dictionary nodeById, List execConns) { @@ -1022,7 +1022,7 @@ private static void ResolveControlFlowTargets( private static void ResolveControlFlowTargetsForNode( CFGStatement stmt, BlueprintNode cfNode, - ControlFlowGraph cfg, Contract.Workflow.Blueprint blueprint, + ControlFlowGraph cfg, KitX.Core.Contract.Workflow.Blueprint blueprint, List execConns) { foreach (var pin in cfNode.OutputPins.Where(p => p.Type == PinType.Execution)) @@ -1072,7 +1072,7 @@ private static void ResolveControlFlowTargetsForNode( } private static string? FindBlockContainingNode(ControlFlowGraph cfg, string targetNodeId, - Contract.Workflow.Blueprint blueprint) + KitX.Core.Contract.Workflow.Blueprint blueprint) { // Find which BlockScope contains the target node foreach (var scope in blueprint.BlockScopes) diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BS2CFGConverter.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BS2CFGConverter.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BS2CFGConverter.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BS2CFGConverter.cs index bbac769e..ed48fe03 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BS2CFGConverter.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BS2CFGConverter.cs @@ -1,13 +1,13 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.BlockScripting; using Serilog; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Functions; -using KitX.Core.Workflow.CFG; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Functions; +using KitX.Workflow.CFG; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Phase 2: Takes a parsed BlockScript AST and produces a ControlFlowGraph diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlockScriptSerializer.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlockScriptSerializer.cs similarity index 94% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlockScriptSerializer.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlockScriptSerializer.cs index 2a35abf0..416be0c9 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlockScriptSerializer.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlockScriptSerializer.cs @@ -1,11 +1,11 @@ -using System.Text; +using System.Text; using KitX.Core.Contract.Workflow; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Serializes a to source code string. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlockScriptToBlueprintConverter.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlockScriptToBlueprintConverter.cs similarity index 95% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlockScriptToBlueprintConverter.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlockScriptToBlueprintConverter.cs index 5961d865..cfe4adb7 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlockScriptToBlueprintConverter.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlockScriptToBlueprintConverter.cs @@ -1,10 +1,10 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.CFG; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.CFG; using Serilog; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Converts BlockScript to Blueprint via a clean 6-phase pipeline. @@ -41,7 +41,7 @@ public BlockScriptToBlueprintConverter( _functionRegistry = functionRegistry; } - public Contract.Workflow.Blueprint Convert(string sourceCode, List? helperFunctions = null) + public KitX.Core.Contract.Workflow.Blueprint Convert(string sourceCode, List? helperFunctions = null) { var result = _parser.Parse(sourceCode); if (!result.IsSuccess || result.Script == null) @@ -53,7 +53,7 @@ public Contract.Workflow.Blueprint Convert(string sourceCode, List(); diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlueprintToBlockScriptConverter.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlueprintToBlockScriptConverter.cs similarity index 87% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlueprintToBlockScriptConverter.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlueprintToBlockScriptConverter.cs index aa92c037..eda83141 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BlueprintToBlockScriptConverter.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BlueprintToBlockScriptConverter.cs @@ -1,10 +1,10 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.CFG; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.CFG; using Serilog; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Converts Blueprint back to a fully-expanded BlockScript source code. @@ -44,12 +44,12 @@ public BlueprintToBlockScriptConverter(IEnumerable strategi internal ControlFlowGraph? LastCFG { get; private set; } - public Contract.Workflow.Blueprint Blueprint { get; private set; } = null!; + public KitX.Core.Contract.Workflow.Blueprint Blueprint { get; private set; } = null!; - public string Convert(Contract.Workflow.Blueprint blueprint) + public string Convert(KitX.Core.Contract.Workflow.Blueprint blueprint) => ConvertToBlockScript(blueprint).SourceCode; - public BlockScript ConvertToBlockScript(Contract.Workflow.Blueprint blueprint) + public BlockScript ConvertToBlockScript(KitX.Core.Contract.Workflow.Blueprint blueprint) { Blueprint = blueprint; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BuiltinFunctionExportStrategyAdapter.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BuiltinFunctionExportStrategyAdapter.cs similarity index 88% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BuiltinFunctionExportStrategyAdapter.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BuiltinFunctionExportStrategyAdapter.cs index efdc5f42..78f3aaa4 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/BuiltinFunctionExportStrategyAdapter.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/BuiltinFunctionExportStrategyAdapter.cs @@ -1,9 +1,9 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.CFG; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.CFG; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// 将 适配为 , diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2BPConverter.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2BPConverter.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2BPConverter.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2BPConverter.cs index 2a4285c9..b7dc62fb 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2BPConverter.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2BPConverter.cs @@ -1,12 +1,12 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.BlockScripting; using Serilog; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Pins; -using KitX.Core.Workflow.CFG; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Pins; +using KitX.Workflow.CFG; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Phase 3: Creates all Blueprint nodes and exec flow edges from ControlFlowGraph. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2BSConverter.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2BSConverter.cs similarity index 95% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2BSConverter.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2BSConverter.cs index 01f7dbae..25457039 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2BSConverter.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2BSConverter.cs @@ -1,10 +1,10 @@ -using KitX.Core.Contract.Workflow; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; +using KitX.Core.Contract.Workflow; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Blocks; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Generates a from a . diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2CSGenerator.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2CSGenerator.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2CSGenerator.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2CSGenerator.cs index 49dfd3a2..baf6a16a 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFG2CSGenerator.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFG2CSGenerator.cs @@ -1,15 +1,15 @@ -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using KitX.Core.Contract.Workflow; using Serilog; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using KitX.Core.Workflow.CFG; +using KitX.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Generates Roslyn from a . @@ -112,7 +112,7 @@ internal static Dictionary InferPubVarTypes( /// Generates the complete for the compiled script. /// Structure: /// - /// namespace KitX.Core.Workflow.BlockScripting.Generated { + /// namespace KitX.Workflow.BlockScripting.Generated { /// public class CompiledScript_<hash> : ICompiledBlockScript { /// public static T ConvertTo<T>(object? value) { ... } /// // Helper functions as static methods (typed, NO wrappers) @@ -145,7 +145,7 @@ internal static CompilationUnitSyntax GenerateCompilationUnit( classDecl = classDecl.AddMembers(runMethod); var nsDecl = NamespaceDeclaration( - ParseName("KitX.Core.Workflow.BlockScripting.Generated")) + ParseName("KitX.Workflow.BlockScripting.Generated")) .AddMembers(classDecl); var usings = new List @@ -154,7 +154,7 @@ internal static CompilationUnitSyntax GenerateCompilationUnit( UsingDirective(ParseName("System.Threading")), UsingDirective(ParseName("System.Threading.Tasks")), UsingDirective(ParseName("KitX.Core.Contract.Workflow")), - UsingDirective(ParseName("KitX.Core.Workflow.BlockScripting")) + UsingDirective(ParseName("KitX.Workflow.BlockScripting")) }; return CompilationUnit() diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFGConditionDuplicator.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFGConditionDuplicator.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFGConditionDuplicator.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFGConditionDuplicator.cs index 6e96a4b7..9bc545e7 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFGConditionDuplicator.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFGConditionDuplicator.cs @@ -1,4 +1,4 @@ -namespace KitX.Core.Workflow.CFG; +namespace KitX.Workflow.CFG; /// /// Duplicates Loop condition evaluation statements before each ToLoopCond diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFGPipeline.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFGPipeline.cs similarity index 93% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFGPipeline.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFGPipeline.cs index d95660f3..f71c2d8e 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/CFGPipeline.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/CFGPipeline.cs @@ -1,9 +1,9 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; -using KitX.Core.Workflow.CFG; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.CFG; +namespace KitX.Workflow.Conversion; /// /// Canonical CFG pipeline: five sub-path functions that compose into four main paths. @@ -53,7 +53,7 @@ internal static ControlFlowGraph BS2CFG( /// Equivalent to BP2CFGConverter.Build(). /// internal static ControlFlowGraph BP2CFG( - Contract.Workflow.Blueprint blueprint, + KitX.Core.Contract.Workflow.Blueprint blueprint, Dictionary strategyMap, Dictionary builtinMap, NodeExportHelper exportHelper, diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/ConversionContext.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/ConversionContext.cs similarity index 89% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/ConversionContext.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/ConversionContext.cs index 5f50b107..6a5229ad 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/ConversionContext.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/ConversionContext.cs @@ -1,9 +1,9 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Accumulated state for Blueprint → BlockScript conversion. @@ -11,7 +11,7 @@ namespace KitX.Core.Workflow.Conversion; /// internal class ConversionContext { - public required Contract.Workflow.Blueprint Blueprint { get; set; } + public required KitX.Core.Contract.Workflow.Blueprint Blueprint { get; set; } public required BlockScript Script { get; set; } // Phase 1: Connection analysis diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/DataEdgeBuilder.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/DataEdgeBuilder.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/DataEdgeBuilder.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/DataEdgeBuilder.cs index dd4bc999..1c779fa1 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/DataEdgeBuilder.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/DataEdgeBuilder.cs @@ -1,12 +1,12 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.BlockScripting; -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Pins; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Pins; using Serilog; -using KitX.Core.Workflow.CFG; +using KitX.Workflow.CFG; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Phase 4+5: Creates data edges from ControlFlowGraph argument analysis. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/ExprUtils.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/ExprUtils.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/ExprUtils.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/ExprUtils.cs index 5598b07d..a8679f4f 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/ExprUtils.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/ExprUtils.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Shared expression-parsing utilities used across pipeline phases. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/PipelineAssembler.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/PipelineAssembler.cs similarity index 95% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/PipelineAssembler.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/PipelineAssembler.cs index cde52f1c..e691ea41 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/PipelineAssembler.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/PipelineAssembler.cs @@ -1,10 +1,10 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using Serilog; -using KitX.Core.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.CFG; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Phase 6: Assembles the final Blueprint from all pipeline outputs. @@ -15,11 +15,11 @@ public class PipelineAssembler private PipelineContext _ctx = null!; private Dictionary _nodeById = new(); - public Contract.Workflow.Blueprint Assemble(PipelineContext context) + public KitX.Core.Contract.Workflow.Blueprint Assemble(PipelineContext context) { _ctx = context; - var bp = new Contract.Workflow.Blueprint + var bp = new KitX.Core.Contract.Workflow.Blueprint { Name = "Imported from BlockScript", PubVarNames = new List(context.PubVarNames), @@ -172,7 +172,7 @@ public Contract.Workflow.Blueprint Assemble(PipelineContext context) // Block Scope Construction // ────────────────────────────────────────────── - private void BuildBlockScopes(Contract.Workflow.Blueprint bp, PipelineContext ctx) + private void BuildBlockScopes(KitX.Core.Contract.Workflow.Blueprint bp, PipelineContext ctx) { var mainBlockName = ctx.FormattedScript.MainBlockName; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/PipelineContext.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/PipelineContext.cs similarity index 96% rename from KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/PipelineContext.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/Conversion/PipelineContext.cs index b9b83e69..27f9ba9c 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/Conversion/PipelineContext.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Conversion/PipelineContext.cs @@ -1,10 +1,10 @@ -using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Pins; +using static KitX.Workflow.BlockScripting.BlockScriptWellKnown.Pins; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.CFG; +using KitX.Workflow.CFG; -using KitX.Core.Workflow.BlockScripting; -using KitX.Core.Workflow.Blueprint; -namespace KitX.Core.Workflow.Conversion; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +namespace KitX.Workflow.Conversion; /// /// Accumulated state flowing through all 6 conversion phases. diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/GlobalUsings.cs b/KitX Clients/KitX Workflow/KitX.Workflow/GlobalUsings.cs new file mode 100644 index 00000000..0aab36f1 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/GlobalUsings.cs @@ -0,0 +1,8 @@ +// Global usings for the KitX.Workflow library. +// These are shared across all source files so that the migrated code (which originally +// relied on file-level usings under KitX.Core.Workflow) resolves common namespaces +// without each file having to repeat them. + +global using KitX.Workflow.Hosting; +global using KitX.Workflow.Contract; +global using KitX.Workflow.Contract.Models; diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Hosting/ServiceCollectionExtensions.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Hosting/ServiceCollectionExtensions.cs new file mode 100644 index 00000000..0f364ad6 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Hosting/ServiceCollectionExtensions.cs @@ -0,0 +1,138 @@ +using Microsoft.Extensions.DependencyInjection; +using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Plugin; +using KitX.Core.Contract.Device; +using KitX.Core.Contract.Event; +using KitX.Workflow; +using KitX.Workflow.BlockScripting; +using KitX.Workflow.Blueprint; +using KitX.Workflow.Conversion; +using Serilog; + +namespace KitX.Workflow.Hosting; + +/// +/// DI registration extensions for the KitX.Workflow library. +/// Host applications (KitX.Core) call to register +/// the full workflow service graph: BlockScript parsing/execution, blueprint +/// conversion pipeline, builtin-function registry, and the plugin/trigger bridges. +/// +public static class ServiceCollectionExtensions +{ + /// + /// Registers all KitX.Workflow services in the dependency injection container. + /// The host must have already registered the shared Core services that workflow + /// depends on (IPluginServer, IDeviceServer, IEventService, IDeviceHttpClient, + /// IDeviceDiscoveryService) before calling this. + /// + /// The service collection to add services to. + /// The service collection for chaining. + public static IServiceCollection AddKitXWorkflow(this IServiceCollection services) + { + Log.Information("[AddKitXWorkflow] Registering workflow services..."); + + // IBlockScriptService is created via factory to inject RealPluginManager from DI. + // WorkflowScriptService facade is kept as the backward-compat singleton graph. + services.AddSingleton(provider => + { + var state = WorkflowScriptService.RuntimeState; + var rpm = provider.GetRequiredService(); + var service = new BlockScriptServiceImpl(state, rpm); + Log.Information("[DI] IBlockScriptService created with RealPluginManager. HashCode: {HashCode}", rpm.GetHashCode()); + return service; + }); + // IBlockScriptPipelineService shares the same BlockScriptServiceImpl instance + // (it carries the parsed-model methods split out of the public IBlockScriptService). + services.AddSingleton(sp => (IBlockScriptPipelineService)sp.GetRequiredService()); + services.AddSingleton(sp => WorkflowScriptService.PluginServiceInstance); + services.AddSingleton(sp => WorkflowScriptService.ManagementServiceInstance); + + // RealPluginManager — singleton so PluginsServer and WorkflowScriptService share + // the same instance, ensuring plugin connection events are properly received. + services.AddSingleton(provider => + { + var pluginServer = provider.GetRequiredService(); + var eventService = provider.GetRequiredService(); + var deviceDiscoveryService = provider.GetRequiredService(); + var deviceServer = provider.GetRequiredService(); + return new RealPluginManager(pluginServer, eventService, deviceDiscoveryService, deviceServer, provider.GetRequiredService()); + }); + // Expose the same RealPluginManager instance under the bridge contract so the + // host (Dashboard) can pre-resolve it to force eager singleton construction. + services.AddSingleton(sp => sp.GetRequiredService()); + + // KCS File Service + services.AddSingleton(); + + // Block Script Services + services.AddSingleton(provider => + { + var funcRegistry = provider.GetService(); + return new BlockScriptParser(funcRegistry); + }); + + services.AddSingleton(provider => + { + var service = new BlockScriptExecutor(); + try + { + var pluginManager = provider.GetRequiredService(); + service.SetPluginManager(pluginManager); + Log.Information("[DI] IBlockScriptExecutor: RealPluginManager HashCode = {HashCode}", pluginManager.GetHashCode()); + } + catch (Exception ex) + { + Log.Error(ex, "[DI] Could not initialize BlockScriptExecutor with RealPluginManager from DI container"); + } + return service; + }); + + services.AddSingleton(); + + // Blueprint sub-services (must be registered before IBlueprintService) + // Discover and register all IBuiltinFunctionDefinition implementations + var functionRegistry = BuiltinFunctionRegistry.Discover(typeof(BuiltinFunctionRegistry).Assembly); + services.AddSingleton(functionRegistry); + + // NodeRegistry with function registry for dynamic node creation + services.AddSingleton(provider => + { + var reg = provider.GetRequiredService(); + return new NodeRegistry(reg); + }); + + services.AddSingleton(); + services.AddSingleton(); + + // Blueprint Converters + services.AddSingleton(provider => + { + var parser = provider.GetRequiredService(); + var nodeRegistry = provider.GetRequiredService(); + var layoutService = provider.GetRequiredService(); + var funcRegistry = provider.GetService(); + return new BlockScriptToBlueprintConverter(parser, nodeRegistry, layoutService, funcRegistry!); + }); + services.AddSingleton(); + + // Blueprint Export Strategies — all auto-registered from IBuiltinFunctionDefinition implementations + foreach (var def in functionRegistry.AllDefinitions) + { + services.AddSingleton(new BuiltinFunctionExportStrategyAdapter(def)); + } + + // Blueprint Services + services.AddSingleton(); + + // Workflow Storage Service + services.AddSingleton(); + + // Trigger Manager (constructor takes IPluginServer) + services.AddSingleton(); + // Expose TriggerManager under the ITriggerManager contract too + services.AddSingleton(sp => sp.GetRequiredService()); + + Log.Information("[AddKitXWorkflow] Workflow services registered."); + return services; + } +} diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/Hosting/ServiceLocator.cs b/KitX Clients/KitX Workflow/KitX.Workflow/Hosting/ServiceLocator.cs new file mode 100644 index 00000000..06b66ce5 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/Hosting/ServiceLocator.cs @@ -0,0 +1,72 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace KitX.Workflow.Hosting; + +/// +/// Centralized service locator for the KitX.Workflow library. +/// +/// This is the workflow library's own counterpart of KitX.Core's ServiceLocator. +/// The host application (KitX.Core) must call with the +/// single shared after building it, so that workflow +/// code created outside of DI (e.g. builtin-function runtime methods, lazy singletons) +/// can resolve shared services (IPluginService, IDeviceServer, workflow services, ...) +/// through the same container, without taking a compile-time dependency on KitX.Core. +/// +public static class ServiceLocator +{ + private static IServiceProvider? _serviceProvider; + private static bool _isInitialized; + + /// + /// Gets the single IServiceProvider for the workflow library. + /// Throws if accessed before initialization. + /// + public static IServiceProvider ServiceProvider + { + get + { + if (_serviceProvider is null) + throw new InvalidOperationException( + "ServiceLocator has not been initialized. " + + "Call ServiceLocator.Initialize() first."); + + return _serviceProvider; + } + } + + /// Gets whether the locator has been initialized. + public static bool IsInitialized => _isInitialized; + + /// + /// Initializes the locator with the single shared IServiceProvider. + /// Should be called exactly ONCE during application startup, + /// after building the service provider. + /// + public static void Initialize(IServiceProvider serviceProvider) + { + if (_isInitialized) + { + Serilog.Log.Warning("[ServiceLocator] Initialize called more than once. Ignoring."); + return; + } + + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _isInitialized = true; + + Serilog.Log.Information("[ServiceLocator] Initialized. ServiceProvider HashCode: {HashCode}", + serviceProvider.GetHashCode()); + } + + /// + /// Gets a required service from the DI container. + /// Throws InvalidOperationException if the service is not registered. + /// + public static T GetRequiredService() where T : notnull + => ServiceProvider.GetRequiredService(); + + /// + /// Gets a service from the DI container, or null if not registered. + /// + public static T? GetService() where T : class + => ServiceProvider.GetService(); +} diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/KcsFileService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/KcsFileService.cs similarity index 98% rename from KitX Clients/KitX Core/KitX.Core/Workflow/KcsFileService.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/KcsFileService.cs index d59794bb..ea0ac209 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/KcsFileService.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/KcsFileService.cs @@ -1,11 +1,11 @@ -using System.Text.Json; +using System.Text.Json; using KitX.Core.Contract.Workflow; using Serilog; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// KCS文件服务实现 - 仅负责KCS文件的读写 diff --git a/KitX Clients/KitX Workflow/KitX.Workflow/KitX.Workflow.csproj b/KitX Clients/KitX Workflow/KitX.Workflow/KitX.Workflow.csproj new file mode 100644 index 00000000..889d6be8 --- /dev/null +++ b/KitX Clients/KitX Workflow/KitX.Workflow/KitX.Workflow.csproj @@ -0,0 +1,47 @@ + + + + net10.0 + enable + enable + KitX.Workflow + + + + $(Version) + $(Version) + 24.10.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2024-02-07"))).TotalDays).$([System.Math]::Floor($([System.DateTime]::UtcNow.TimeOfDay.TotalMinutes))) + + + + + + <_Parameter1>KitX.Core.DI.Tests + + + <_Parameter1>KitX.Core.BluePrint.Test + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/RealPluginManager.cs b/KitX Clients/KitX Workflow/KitX.Workflow/RealPluginManager.cs similarity index 94% rename from KitX Clients/KitX Core/KitX.Core/Workflow/RealPluginManager.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/RealPluginManager.cs index da5e4522..af131df5 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/RealPluginManager.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/RealPluginManager.cs @@ -1,28 +1,26 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Text; using System.Text.Json; using KitX.Core.Contract.Workflow; using KitX.Core.Contract.Plugin; using KitX.Core.Contract.Device; using KitX.Core.Contract.Event; -using KitX.Core.Device; using KitX.Core.Contract.Plugin.Events; -using KitX.Core.Event; -using KitX.Core.DI; +using KitX.Workflow.Hosting; using KitX.Shared.CSharp.Device; using KitX.Shared.CSharp.Plugin; using KitX.Shared.CSharp.WebCommand; using KitX.Shared.CSharp.WebCommand.Infos; using Serilog; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// 真实的插件管理器实现,通过 WebSocket 与插件通信。 /// Implements both Contract.IPluginManager (primary, for BlockScripting) and /// KCS IPluginManager (legacy, for KCS pipeline compatibility). /// -public class RealPluginManager : IPluginManager +public class RealPluginManager : IPluginManager, IRealPluginManagerBridge { private readonly IPluginServer _pluginServer; private readonly IDeviceServer _deviceServer; @@ -42,38 +40,15 @@ public class RealPluginManager : IPluginManager private readonly ConcurrentDictionary> _pendingResponses = new(); /// - /// 构造函数(仅需 IPluginServer,其他依赖从 ServiceHost 解析) + /// 构造函数(仅需 IPluginServer,其他依赖从 ServiceLocator 解析) /// /// 插件服务器实例 public RealPluginManager(IPluginServer pluginServer) : this(pluginServer, - ServiceHost.IsInitialized ? ServiceHost.GetRequiredService() : new KitX.Core.Event.EventService(), - ServiceHost.IsInitialized ? ServiceHost.GetRequiredService() : null!, - ServiceHost.IsInitialized ? ServiceHost.GetRequiredService() : null!, - new DeviceHttpClient()) - { - } - - /// - /// 构造函数 - /// - /// 插件服务器实例 - /// 事件服务实例 - /// 设备发现服务实例 - public RealPluginManager(IPluginServer pluginServer, IEventService eventService, IDeviceDiscoveryService deviceDiscoveryService) - : this(pluginServer, eventService, deviceDiscoveryService, null!, new DeviceHttpClient()) - { - } - - /// - /// 构造函数 - /// - /// 插件服务器实例 - /// 事件服务实例 - /// 设备发现服务实例 - /// HTTP 客户端,用于跨设备调用 - public RealPluginManager(IPluginServer pluginServer, IEventService eventService, IDeviceDiscoveryService deviceDiscoveryService, IDeviceHttpClient deviceHttpClient) - : this(pluginServer, eventService, deviceDiscoveryService, null!, deviceHttpClient) + ServiceLocator.GetRequiredService(), + ServiceLocator.GetRequiredService(), + ServiceLocator.GetRequiredService(), + ServiceLocator.GetRequiredService()) { } @@ -91,7 +66,7 @@ public RealPluginManager(IPluginServer pluginServer, IEventService eventService, _eventService = eventService ?? throw new ArgumentNullException(nameof(eventService)); _deviceDiscoveryService = deviceDiscoveryService ?? throw new ArgumentNullException(nameof(deviceDiscoveryService)); _deviceServer = deviceServer; - _deviceHttpClient = deviceHttpClient ?? new DeviceHttpClient(); + _deviceHttpClient = deviceHttpClient ?? throw new ArgumentNullException(nameof(deviceHttpClient)); Log.Information("[RealPluginManager] Constructor. This HashCode: {ThisHashCode}, PluginServer HashCode: {PluginServerHashCode}", GetHashCode(), _pluginServer.GetHashCode()); @@ -100,7 +75,7 @@ public RealPluginManager(IPluginServer pluginServer, IEventService eventService, _pluginServer.PluginMessageReceived += OnPluginMessageReceived; // 订阅插件响应事件(当插件返回带RequestId的响应时触发) - _eventService.Subscribe(EventNames.PluginResponse, (sender, args) => OnPluginResponse(this, args)); + _eventService.Subscribe(WorkflowEventNames.PluginResponse, (sender, args) => OnPluginResponse(this, args)); } /// diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/TriggerManager.cs b/KitX Clients/KitX Workflow/KitX.Workflow/TriggerManager.cs similarity index 87% rename from KitX Clients/KitX Core/KitX.Core/Workflow/TriggerManager.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/TriggerManager.cs index e3b482a6..d4a2e362 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/TriggerManager.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/TriggerManager.cs @@ -1,21 +1,20 @@ -using System.Text.Json; +using System.Text.Json; using KitX.Core.Contract.Workflow; using KitX.Core.Contract.Event; using KitX.Core.Contract.Plugin; using KitX.Shared.CSharp.WebCommand; using KitX.Shared.CSharp.WebCommand.Infos; using Serilog; -using KitX.Core.DI; - +using KitX.Workflow.Hosting; using PluginMessageReceivedEventArgs = KitX.Core.Contract.Plugin.Events.PluginMessageReceivedEventArgs; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// 管理触发器路由:从插件接收触发信号,路由到匹配的工作流并执行。 /// 触发器是纯信号(等同于"运行"按钮),不携带业务数据。 /// -public class TriggerManager +public class TriggerManager : ITriggerManager { private readonly IPluginServer _pluginServer; private readonly JsonSerializerOptions _serializerOptions = new() @@ -36,13 +35,12 @@ public class TriggerManager private readonly Dictionary _workflowTriggers = new(); /// - /// Creates a new trigger manager + /// Creates a new trigger manager bound to the given plugin server. /// - public TriggerManager() + /// Plugin server used to receive TriggerFired messages. + public TriggerManager(IPluginServer pluginServer) { - _pluginServer = ServiceHost.IsInitialized - ? ServiceHost.GetRequiredService() - : new KitX.Core.Device.PluginsServer(new KitX.Core.Event.EventService()); + _pluginServer = pluginServer ?? throw new ArgumentNullException(nameof(pluginServer)); _pluginServer.PluginMessageReceived += OnPluginMessageReceived; Log.Information("[TriggerManager] Initialized and subscribed to PluginMessageReceived"); } @@ -88,13 +86,13 @@ public async void InitializeFromPersistedWorkflows() { try { - if (!ServiceHost.IsInitialized) + if (!ServiceLocator.IsInitialized) { - Log.Error("[TriggerManager] Cannot initialize from persisted workflows: ServiceHost not initialized"); + Log.Error("[TriggerManager] Cannot initialize from persisted workflows: ServiceLocator not initialized"); return; } - var storageService = ServiceHost.GetRequiredService(); + var storageService = ServiceLocator.GetRequiredService(); var workflows = await storageService.DiscoverWorkflowsAsync(); foreach (var workflow in workflows) @@ -181,10 +179,10 @@ private void OnPluginMessageReceived(object? sender, PluginMessageReceivedEventA Log.Information("[TriggerManager] Triggering workflow: {WorkflowId}", workflowId); _ = System.Threading.Tasks.Task.Run(async () => { - bool success = await ServiceHost.GetRequiredService().RunWorkflowAsync(workflowId); - ServiceHost.GetRequiredService().Publish( - KitX.Core.Event.EventNames.WorkflowExecutionResult, - new KitX.Core.Contract.Event.WorkflowExecutionResultEventArgs( + bool success = await ServiceLocator.GetRequiredService().RunWorkflowAsync(workflowId); + ServiceLocator.GetRequiredService().Publish( + WorkflowEventNames.WorkflowExecutionResult, + new WorkflowExecutionResultEventArgs( workflowId, success, success ? null : "Workflow execution failed")); }); diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowCase.cs b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowCase.cs similarity index 91% rename from KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowCase.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/WorkflowCase.cs index 2d567ec1..b7bb2eda 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowCase.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowCase.cs @@ -1,6 +1,6 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// Workflow case implementation diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowManagementService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowManagementService.cs similarity index 95% rename from KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowManagementService.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/WorkflowManagementService.cs index c1a09926..41ee3ebb 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowManagementService.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowManagementService.cs @@ -1,7 +1,7 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using Serilog; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// Workflow lifecycle management service. @@ -10,14 +10,16 @@ namespace KitX.Core.Workflow; internal class WorkflowManagementService : IWorkflowManagementService { private readonly WorkflowRuntimeState _state; - private readonly IBlockScriptService _blockScriptService; + // Holds the concrete impl so both the public IBlockScriptService (source-string methods) + // and the internal IBlockScriptPipelineService (parsed-model methods) are reachable. + private readonly BlockScriptServiceImpl _blockScriptService; /// /// Initializes a new instance of WorkflowManagementService. /// /// Shared runtime state. /// Block script execution service. - internal WorkflowManagementService(WorkflowRuntimeState state, IBlockScriptService blockScriptService) + internal WorkflowManagementService(WorkflowRuntimeState state, BlockScriptServiceImpl blockScriptService) { _state = state; _blockScriptService = blockScriptService; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowOutput.cs b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowOutput.cs similarity index 94% rename from KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowOutput.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/WorkflowOutput.cs index b8ecc238..7a52e097 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowOutput.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowOutput.cs @@ -1,7 +1,7 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Text; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// 工作流脚本输出辅助类 diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowPluginService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowPluginService.cs similarity index 93% rename from KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowPluginService.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/WorkflowPluginService.cs index f0797b1f..e8ff5ed6 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowPluginService.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowPluginService.cs @@ -1,11 +1,11 @@ -using KitX.Core.Contract.Workflow; +using KitX.Core.Contract.Workflow; using KitX.Core.Contract.Plugin; -using KitX.Core.DI; +using KitX.Workflow.Hosting; using KitX.Shared.CSharp.Plugin; using Microsoft.CodeAnalysis.CSharp; using Serilog; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// Plugin coordination service for workflow script processing. @@ -31,9 +31,13 @@ public void InitializePluginManager() try { - var pluginServer = ServiceHost.IsInitialized - ? ServiceHost.GetRequiredService() - : new KitX.Core.Device.PluginsServer(new KitX.Core.Event.EventService()); + if (!ServiceLocator.IsInitialized) + { + Log.Error("[WorkflowPluginService] Cannot initialize plugin manager: ServiceLocator not initialized"); + return; + } + + var pluginServer = ServiceLocator.GetRequiredService(); var realPluginManager = new RealPluginManager(pluginServer); _state.IsParserInitialized = true; diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowRuntimeState.cs b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowRuntimeState.cs similarity index 92% rename from KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowRuntimeState.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/WorkflowRuntimeState.cs index 41f89f6f..32da92a7 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowRuntimeState.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowRuntimeState.cs @@ -1,9 +1,9 @@ -using Csharpell.Core; +using Csharpell.Core; using KitX.Core.Contract.Workflow; -using KitX.Core.Workflow.BlockScripting; +using KitX.Workflow.BlockScripting; using KitX.Shared.CSharp.Plugin; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// Shared state container for workflow runtime services. diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowScriptService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowScriptService.cs similarity index 88% rename from KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowScriptService.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/WorkflowScriptService.cs index cf1f48c5..f62d1786 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowScriptService.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowScriptService.cs @@ -1,22 +1,25 @@ -using KitX.Core.Contract.Workflow; -using KitX.Core.DI; +using KitX.Core.Contract.Workflow; +using KitX.Workflow.Contract; +using KitX.Workflow.Hosting; using KitX.Shared.CSharp.Plugin; using Serilog; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// Facade service that delegates to specialized workflow services. -/// Exposes all four workflow interfaces for backward compatibility. +/// Exposes the public workflow interfaces (IWorkflowManagementService, +/// IWorkflowPluginService, IBlockScriptService) plus the internal +/// IBlockScriptPipelineService for backward compatibility. /// public class WorkflowScriptService : IWorkflowManagementService, - IWorkflowPluginService, IBlockScriptService + IWorkflowPluginService, IBlockScriptService, IBlockScriptPipelineService { /// /// Gets the singleton facade instance. /// WorkflowScriptService is a facade that delegates to its static service graph, /// so it's not resolved from DI (IBlockScriptService is registered as BlockScriptServiceImpl). - /// Use ServiceHost.GetRequiredService<IWorkflowManagementService>() etc. for individual interfaces. + /// Use ServiceLocator.GetRequiredService<IWorkflowManagementService>() etc. for individual interfaces. /// public static WorkflowScriptService Instance { get; } = new(); @@ -27,8 +30,10 @@ public class WorkflowScriptService : IWorkflowManagementService, /// /// Service graph — built once at singleton instantiation. + /// Held as the concrete impl so both IBlockScriptService (public) and + /// IBlockScriptPipelineService (internal) methods are reachable. /// - private static IBlockScriptService? _blockScriptService; + private static BlockScriptServiceImpl? _blockScriptService; private static IWorkflowManagementService? _managementService; private static readonly IWorkflowPluginService PluginService; @@ -52,7 +57,7 @@ static WorkflowScriptService() /// Gets the BlockScriptService, creating it lazily once RealPluginManager is available. /// This ensures the BlockScriptService always has a valid RealPluginManager. /// - private static IBlockScriptService BlockScriptService + private static BlockScriptServiceImpl BlockScriptService { get { @@ -61,7 +66,7 @@ private static IBlockScriptService BlockScriptService RealPluginManager? rpm = null; try { - rpm = ServiceHost.GetRequiredService(); + rpm = ServiceLocator.GetRequiredService(); if (rpm != null) { SharedState.IsParserInitialized = true; @@ -142,13 +147,7 @@ public string ApplyConstantsToCode(string code, List constants public string MergeHelperFunctions(string mainCode, List helperFunctions) => PluginService.MergeHelperFunctions(mainCode, helperFunctions); - // --- IBlockScriptService --- - - public BlockScriptParseResult ParseBlockScript(string sourceCode) => - BlockScriptService.ParseBlockScript(sourceCode); - - public Task ParseBlockScriptAsync(string sourceCode) => - BlockScriptService.ParseBlockScriptAsync(sourceCode); + // --- IBlockScriptService (public: source-string based) --- public BlockScriptValidationResult ValidateBlockScript(string sourceCode) => BlockScriptService.ValidateBlockScript(sourceCode); @@ -156,12 +155,6 @@ public BlockScriptValidationResult ValidateBlockScript(string sourceCode) => public List ParseConstantsFromBlockScript(string sourceCode) => BlockScriptService.ParseConstantsFromBlockScript(sourceCode); - public Task ExecuteBlockScriptAsync( - BlockScript script, - Dictionary? parameters = null, - CancellationToken cancellationToken = default) => - BlockScriptService.ExecuteBlockScriptAsync(script, parameters, cancellationToken); - public Task ExecuteBlockScriptAsync( string sourceCode, Dictionary? parameters = null, @@ -181,9 +174,24 @@ public Task ExecuteBlockScriptAsync( CancellationToken cancellationToken = default) => BlockScriptService.ExecuteBlockScriptAsync(sourceCode, helperFunctions, constantOverrides, cancellationToken); - public Task CompileAndPersistAsync(BlockScript script, string workflowId) => - BlockScriptService.CompileAndPersistAsync(script, workflowId); - public int PreloadCompiledScripts(string workflowId) => BlockScriptService.PreloadCompiledScripts(workflowId); + + // --- IBlockScriptPipelineService (internal: parsed-model based) --- + + public BlockScriptParseResult ParseBlockScript(string sourceCode) => + BlockScriptService.ParseBlockScript(sourceCode); + + public Task ParseBlockScriptAsync(string sourceCode) => + BlockScriptService.ParseBlockScriptAsync(sourceCode); + + public Task ExecuteBlockScriptAsync( + BlockScript script, + Dictionary? parameters = null, + CancellationToken cancellationToken = default) => + BlockScriptService.ExecuteBlockScriptAsync(script, parameters, cancellationToken); + + public Task CompileAndPersistAsync(BlockScript script, string workflowId) => + BlockScriptService.CompileAndPersistAsync(script, workflowId); } + diff --git a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowStorageService.cs b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowStorageService.cs similarity index 97% rename from KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowStorageService.cs rename to KitX Clients/KitX Workflow/KitX.Workflow/WorkflowStorageService.cs index ac7752b8..df75bb1f 100644 --- a/KitX Clients/KitX Core/KitX.Core/Workflow/WorkflowStorageService.cs +++ b/KitX Clients/KitX Workflow/KitX.Workflow/WorkflowStorageService.cs @@ -1,9 +1,9 @@ -using System.Text.Json; +using System.Text.Json; using KitX.Core.Contract.Workflow; -using KitX.Core.DI; +using KitX.Workflow.Hosting; using Serilog; -namespace KitX.Core.Workflow; +namespace KitX.Workflow; /// /// Workflow storage service implementation - manages workflow file persistence @@ -11,17 +11,17 @@ namespace KitX.Core.Workflow; public class WorkflowStorageService : IWorkflowStorageService { /// - /// Gets the singleton instance (resolves from ServiceHost when available). + /// Gets the singleton instance (resolves from ServiceLocator when available). /// Internal code should use constructor injection instead. /// public static WorkflowStorageService Instance { get { - if (ServiceHost.IsInitialized) - return (WorkflowStorageService)ServiceHost.GetRequiredService(); - Log.Error("[WorkflowStorageService] Instance: ServiceHost not initialized! Returning orphan instance — " + - "this indicates a DI initialization order bug. Use ServiceHost/constructor injection instead."); + if (ServiceLocator.IsInitialized) + return (WorkflowStorageService)ServiceLocator.GetRequiredService(); + Log.Error("[WorkflowStorageService] Instance: ServiceLocator not initialized! Returning orphan instance — " + + "this indicates a DI initialization order bug. Use ServiceLocator/constructor injection instead."); return new WorkflowStorageService(); } } diff --git a/KitX Standard b/KitX Standard index 51da1348..6d12db26 160000 --- a/KitX Standard +++ b/KitX Standard @@ -1 +1 @@ -Subproject commit 51da1348a5cc9455adb94dd38a684ba41bdf63e2 +Subproject commit 6d12db2687a6c2d07728dbe44702fd12cfec39ee diff --git a/KitX.sln b/KitX.sln index 5480b224..d6ae8786 100644 --- a/KitX.sln +++ b/KitX.sln @@ -157,6 +157,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KitX.Core.DI.Tests", "KitX EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KitX.Core.BluePrint.Test", "KitX Clients\KitX Core\KitX.Core.BluePrint.Test\KitX.Core.BluePrint.Test.csproj", "{3C461B17-B9A4-97E1-9A62-79BC972F7A13}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KitX Workflow", "KitX Workflow", "{5B220184-3539-443A-A12B-4381F4817D13}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KitX.Workflow", "KitX Clients\KitX Workflow\KitX.Workflow\KitX.Workflow.csproj", "{E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -931,6 +935,26 @@ Global {3C461B17-B9A4-97E1-9A62-79BC972F7A13}.Release|x64.Build.0 = Release|Any CPU {3C461B17-B9A4-97E1-9A62-79BC972F7A13}.Release|x86.ActiveCfg = Release|Any CPU {3C461B17-B9A4-97E1-9A62-79BC972F7A13}.Release|x86.Build.0 = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|ARM.ActiveCfg = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|ARM.Build.0 = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|ARM64.Build.0 = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|x64.ActiveCfg = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|x64.Build.0 = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|x86.ActiveCfg = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Debug|x86.Build.0 = Debug|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|Any CPU.Build.0 = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|ARM.ActiveCfg = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|ARM.Build.0 = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|ARM64.ActiveCfg = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|ARM64.Build.0 = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|x64.ActiveCfg = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|x64.Build.0 = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|x86.ActiveCfg = Release|Any CPU + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -985,6 +1009,8 @@ Global {641562BA-D2B5-4799-8712-11C23912A79B} = {C4C2D1CC-294B-4C93-8A64-34D5212AD74E} {9D8CEB24-748C-0392-629C-45342937C32A} = {C4C2D1CC-294B-4C93-8A64-34D5212AD74E} {3C461B17-B9A4-97E1-9A62-79BC972F7A13} = {C4C2D1CC-294B-4C93-8A64-34D5212AD74E} + {5B220184-3539-443A-A12B-4381F4817D13} = {673CF32C-65BF-4EB3-83D3-47FEC77B47A0} + {E4438FD7-74FB-417C-B4F1-FC5C6040F5FC} = {5B220184-3539-443A-A12B-4381F4817D13} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {09BBC227-F41B-4D10-9E38-0EEE07ED17BC}