Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions KitX Clients/KitX Core/KitX.Core.BluePrint.Test/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
123 changes: 7 additions & 116 deletions KitX Clients/KitX Core/KitX.Core/DI/CoreServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

/// <summary>
Expand Down Expand Up @@ -60,21 +57,6 @@ public static IServiceCollection AddCoreServices(this IServiceCollection service
Log.Information("Registering IPluginService...");
services.AddSingleton<IPluginService, PluginsManager>();

// 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<IBlockScriptService>(provider =>
{
var state = WorkflowScriptService.RuntimeState;
var rpm = provider.GetRequiredService<RealPluginManager>();
var service = new BlockScriptServiceImpl(state, rpm);
Log.Information("[DI] IBlockScriptService created with RealPluginManager. HashCode: {HashCode}", rpm.GetHashCode());
return service;
});
services.AddSingleton<IWorkflowPluginService>(sp => WorkflowScriptService.PluginServiceInstance);
services.AddSingleton<IWorkflowManagementService>(sp => WorkflowScriptService.ManagementServiceInstance);

// Activity Services
Log.Information("Registering IActivityService...");
services.AddSingleton<IActivityService, ActivityManager>();
Expand Down Expand Up @@ -116,106 +98,15 @@ public static IServiceCollection AddCoreServices(this IServiceCollection service
Log.Information("Registering IDeviceHttpClient...");
services.AddSingleton<IDeviceHttpClient, DeviceHttpClient>();

// 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<RealPluginManager>(provider =>
{
var pluginServer = provider.GetRequiredService<IPluginServer>();
var eventService = provider.GetRequiredService<IEventService>();
var deviceDiscoveryService = provider.GetRequiredService<IDeviceDiscoveryService>();
var deviceServer = provider.GetRequiredService<IDeviceServer>();
return new RealPluginManager(pluginServer, eventService, deviceDiscoveryService, deviceServer, provider.GetRequiredService<IDeviceHttpClient>());
});

// RealPluginManager is pre-resolved by the caller after BuildServiceProvider().

// Phase 5: Announcement Service
Log.Information("Registering IAnnouncementService...");
services.AddSingleton<IAnnouncementService, AnnouncementManager>();

// KCS File Services
Log.Information("Registering IKcsFileService...");
services.AddSingleton<IKcsFileService, KcsFileService>();

// Block Script Services
Log.Information("Registering IBlockScriptParser...");
services.AddSingleton<IBlockScriptParser, KitX.Core.Workflow.BlockScripting.BlockScriptParser>(provider =>
{
var funcRegistry = provider.GetService<BuiltinFunctionRegistry>();
var service = new KitX.Core.Workflow.BlockScripting.BlockScriptParser(funcRegistry);
return service;
});

Log.Information("Registering IBlockScriptExecutor...");
services.AddSingleton<IBlockScriptExecutor, KitX.Core.Workflow.BlockScripting.BlockScriptExecutor>(provider =>
{
var service = new KitX.Core.Workflow.BlockScripting.BlockScriptExecutor();
// Resolve RealPluginManager from DI to ensure same instance
try
{
var pluginManager = provider.GetRequiredService<RealPluginManager>();
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<IBlockScopeManager, KitX.Core.Workflow.BlockScripting.BlockScopeManager>();

// 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<INodeRegistry>(provider =>
{
var reg = provider.GetRequiredService<BuiltinFunctionRegistry>();
return new NodeRegistry(reg);
});

services.AddSingleton<ILayoutService, LayoutService>();
services.AddSingleton<IBlueprintRenderDataService, BlueprintRenderDataService>();

// Blueprint Converters
Log.Information("Registering IBlockScriptToBlueprintConverter...");
services.AddSingleton<IBlockScriptToBlueprintConverter>(provider =>
{
var parser = provider.GetRequiredService<IBlockScriptParser>();
var nodeRegistry = provider.GetRequiredService<INodeRegistry>();
var layoutService = provider.GetRequiredService<ILayoutService>();
var funcRegistry = provider.GetService<BuiltinFunctionRegistry>();
return new BlockScriptToBlueprintConverter(parser, nodeRegistry, layoutService, funcRegistry!);
});
Log.Information("Registering IBlueprintToBlockScriptConverter...");
services.AddSingleton<IBlueprintToBlockScriptConverter, BlueprintToBlockScriptConverter>();

// 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<INodeExportStrategy>(new BuiltinFunctionExportStrategyAdapter(def));
}

// Blueprint Services
Log.Information("Registering IBlueprintService...");
services.AddSingleton<IBlueprintService, BlueprintService>();

// Workflow Storage Service
Log.Information("Registering IWorkflowStorageService...");
services.AddSingleton<IWorkflowStorageService, WorkflowStorageService>();

// Trigger Manager
Log.Information("Registering TriggerManager...");
services.AddSingleton<TriggerManager>();
// 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
Expand Down
23 changes: 2 additions & 21 deletions KitX Clients/KitX Core/KitX.Core/Device/DeviceHttpClient.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Interface for device HTTP client — sends requests to remote DevicesServer instances.
/// Used for cross-device plugin invocation via the /Api/V1/Plugin/Invoke endpoint.
/// </summary>
public interface IDeviceHttpClient
{
/// <summary>
/// Invokes a plugin method on a remote device via HTTP POST to /Api/V1/Plugin/Invoke.
/// </summary>
/// <param name="targetDevice">Target device info (contains IPv4 and DevicesServerPort)</param>
/// <param name="token">Valid session token for the target device</param>
/// <param name="request">The Request object to send</param>
/// <param name="ct">Cancellation token</param>
/// <returns>HTTP response from remote device, or null on network error</returns>
Task<HttpResponseMessage?> InvokePluginAsync(
DeviceInfo targetDevice,
string token,
Request request,
CancellationToken ct = default);
}

/// <summary>
/// Device HTTP client implementation.
/// Sends plugin invoke requests to remote DevicesServer over HTTP.
/// Protocol compatible with legacy PluginControllerExtensions.RemoteInvoke.
/// Implements the <see cref="IDeviceHttpClient"/> contract now defined in KitX.Core.Contract.
/// </summary>
public class DeviceHttpClient : IDeviceHttpClient
{
Expand Down
1 change: 1 addition & 0 deletions KitX Clients/KitX Core/KitX.Core/KitX.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<ProjectReference Include="..\..\..\KitX Standard\KitX Script\Kscript.CSharp.Parser\Kscript.CSharp.Parser.csproj" Condition="false" />
<ProjectReference Include="..\..\..\KitX Standard\KitX Shared\KitX.Shared.CSharp\KitX.Shared.CSharp.csproj" />
<ProjectReference Include="..\..\..\KitX Standard\KitX Contracts\KitX.Contract.CSharp\KitX.Contract.CSharp.csproj" />
<ProjectReference Include="..\..\KitX Workflow\KitX.Workflow\KitX.Workflow.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// BlockScript parsing and execution service.
/// Implements IBlockScriptService.
/// Implements both the public <c>IBlockScriptService</c> (Dashboard-facing, source-string
/// based methods) and the internal <c>IBlockScriptPipelineService</c> (parsed-model based
/// methods consumed only by the workflow pipeline).
/// </summary>
internal class BlockScriptServiceImpl : IBlockScriptService
internal class BlockScriptServiceImpl : IBlockScriptService, IBlockScriptPipelineService
{
private readonly WorkflowRuntimeState _state;
private RealPluginManager? _realPluginManager;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using KitX.Core.Contract.Workflow;
using KitX.Core.Contract.Workflow;

namespace KitX.Core.Workflow.BlockScripting;
namespace KitX.Workflow.BlockScripting;

/// <summary>
/// Block scope manager implementation - manages variable scoping for block scripts
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using KitX.Core.Contract.Workflow;
using KitX.Core.Contract.Workflow;

namespace KitX.Core.Workflow.BlockScripting;
namespace KitX.Workflow.BlockScripting;

/// <summary>
/// Script globals for block script execution — 仅保留核心手脚架。
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Block script executor using full-script assembly compilation.
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Block script parser implementation.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace KitX.Core.Workflow.BlockScripting;
namespace KitX.Workflow.BlockScripting;

/// <summary>
/// Well-known string constants for the BlockScript/Blueprint pipeline.
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Extracts statements and variable declarations from validated syntax trees.
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Recognizes block structure using source text scanning.
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Validates pure C# code within recognized blocks using Roslyn.
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Reflection;
using System.Reflection;
using Serilog;

namespace KitX.Core.Workflow.BlockScripting;
namespace KitX.Workflow.BlockScripting;

/// <summary>
/// 内置函数定义的中央注册中心。通过反射自动发现所有 <see cref="IBuiltinFunctionDefinition"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Compiles an entire <see cref="BlockScript"/> into a .NET assembly using Roslyn
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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; }

Expand Down
Loading
Loading