diff --git a/build/ci.yml b/build/ci.yml index 54fb79c335..b22a3f0af4 100644 --- a/build/ci.yml +++ b/build/ci.yml @@ -4,7 +4,7 @@ trigger: variables: Build.Major: 0 - Build.Minor: 11 + Build.Minor: 12 Drops.Dir: $(Build.ArtifactStagingDirectory)/drops IQSharp.Hosting.Env: 'build-agent-iqsharp' diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 872d3a96af..6bfdb7f9ac 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -34,9 +34,9 @@ - - - + + + diff --git a/src/Kernel/IQSharpEngine.cs b/src/Kernel/IQSharpEngine.cs index 88122f5271..a79b3d1894 100644 --- a/src/Kernel/IQSharpEngine.cs +++ b/src/Kernel/IQSharpEngine.cs @@ -17,6 +17,8 @@ using Microsoft.Jupyter.Core.Protocol; using Newtonsoft.Json; using System.Threading.Tasks; +using System.Collections.Immutable; +using Microsoft.Quantum.IQSharp.AzureClient; namespace Microsoft.Quantum.IQSharp.Kernel { @@ -41,7 +43,8 @@ public IQSharpEngine( PerformanceMonitor performanceMonitor, IShellRouter shellRouter, IEventService eventService, - IMagicSymbolResolver magicSymbolResolver + IMagicSymbolResolver magicSymbolResolver, + IReferences references ) : base(shell, shellRouter, context, logger, services) { this.performanceMonitor = performanceMonitor; @@ -69,6 +72,8 @@ IMagicSymbolResolver magicSymbolResolver RegisterSymbolResolver(this.SymbolsResolver); RegisterSymbolResolver(this.MagicResolver); + RegisterPackageLoadedEvent(services, logger, references); + // Handle new shell messages. shellRouter.RegisterHandlers(); @@ -79,9 +84,72 @@ IMagicSymbolResolver magicSymbolResolver Process.GetCurrentProcess().Id ); + eventService?.TriggerServiceInitialized(this); } + /// + /// Registers an event handler that searches newly loaded packages + /// for extensions to this engine (in particular, for result encoders). + /// + private void RegisterPackageLoadedEvent(IServiceProvider services, ILogger logger, IReferences references) + { + var knownAssemblies = references + .Assemblies + .Select(asm => asm.Assembly.GetName()) + .ToImmutableHashSet() + // Except assemblies known at compile-time as well. + .Add(typeof(StateVectorToHtmlResultEncoder).Assembly.GetName()) + .Add(typeof(AzureClientErrorToHtmlEncoder).Assembly.GetName()); + foreach (var knownAssembly in knownAssemblies) System.Console.WriteLine($"{knownAssembly.FullName}"); + + // Register new display encoders when packages load. + references.PackageLoaded += (sender, args) => + { + logger.LogDebug("Scanning for display encoders after loading {Package}.", args.PackageId); + foreach (var assembly in references.Assemblies + .Select(asm => asm.Assembly) + .Where(asm => !knownAssemblies.Contains(asm.GetName())) + ) + { + // Look for display encoders in the new assembly. + logger.LogDebug("Found new assembly {Name}, looking for display encoders.", assembly.FullName); + var relevantTypes = assembly + .GetTypes() + .Where(type => + !type.IsAbstract && + !type.IsInterface && + typeof(IResultEncoder).IsAssignableFrom(type) + ); + + foreach (var type in relevantTypes) + { + logger.LogDebug( + "Found display encoder {TypeName} in {AssemblyName}; registering.", + type.FullName, + assembly.FullName + ); + + // Try and instantiate the new result encoder, but if it fails, that is likely + // a non-critical failure that should result in a warning. + try + { + RegisterDisplayEncoder(ActivatorUtilities.CreateInstance(services, type) as IResultEncoder); + } + catch (Exception ex) + { + logger.LogWarning( + ex, + "Encountered exception loading result encoder {TypeName} from {AssemblyName}.", + type.FullName, assembly.FullName + ); + } + } + knownAssemblies = knownAssemblies.Add(assembly.GetName()); + } + }; + } + internal ISnippets Snippets { get; } internal ISymbolResolver SymbolsResolver { get; } diff --git a/src/Tool/appsettings.json b/src/Tool/appsettings.json index d5cbc6ab1e..f6951ce8db 100644 --- a/src/Tool/appsettings.json +++ b/src/Tool/appsettings.json @@ -6,25 +6,26 @@ }, "AllowedHosts": "*", "DefaultPackageVersions": [ - "Microsoft.Quantum.Compiler::0.11.2006.1615-beta", + "Microsoft.Quantum.Compiler::0.12.20062505-beta", - "Microsoft.Quantum.CsharpGeneration::0.11.2006.1615-beta", - "Microsoft.Quantum.Development.Kit::0.11.2006.1615-beta", - "Microsoft.Quantum.Simulators::0.11.2006.1615-beta", - "Microsoft.Quantum.Xunit::0.11.2006.1615-beta", + "Microsoft.Quantum.CsharpGeneration::0.12.20062505-beta", + "Microsoft.Quantum.Development.Kit::0.12.20062505-beta", + "Microsoft.Quantum.Simulators::0.12.20062505-beta", + "Microsoft.Quantum.Xunit::0.12.20062505-beta", - "Microsoft.Quantum.Standard::0.11.2006.1615-beta", - "Microsoft.Quantum.Chemistry::0.11.2006.1615-beta", - "Microsoft.Quantum.Chemistry.Jupyter::0.11.2006.1615-beta", - "Microsoft.Quantum.MachineLearning::0.11.2006.1615-beta", - "Microsoft.Quantum.Numerics::0.11.2006.1615-beta", + "Microsoft.Quantum.Standard::0.12.20062505-beta", + "Microsoft.Quantum.Chemistry::0.12.20062505-beta", + "Microsoft.Quantum.Chemistry.Jupyter::0.12.20062505-beta", + "Microsoft.Quantum.MachineLearning::0.12.20062505-beta", + "Microsoft.Quantum.Numerics::0.12.20062505-beta", - "Microsoft.Quantum.Katas::0.11.2006.1615-beta", + "Microsoft.Quantum.Katas::0.12.20062505-beta", - "Microsoft.Quantum.Research::0.11.2006.1615-beta", + "Microsoft.Quantum.Research::0.12.20062505-beta", + - "Microsoft.Quantum.Providers.IonQ::0.11.2006.1615-beta", - "Microsoft.Quantum.Providers.Honeywell::0.11.2006.1615-beta", - "Microsoft.Quantum.Providers.QCI::0.11.2006.1615-beta", + "Microsoft.Quantum.Providers.IonQ::0.12.20062505-beta", + "Microsoft.Quantum.Providers.Honeywell::0.12.20062505-beta", + "Microsoft.Quantum.Providers.QCI::0.12.20062505-beta" ] }