public async Task SendAsync(KernelCommand kernelCommand, CancellationToken cancellationToken)
        {
            // FIX: remove this one as this is for backward compatibility
            await _sender.SendAsync("submitCommand", KernelCommandEnvelope.Serialize(KernelCommandEnvelope.Create(kernelCommand)), cancellationToken : cancellationToken);

            await _sender.SendAsync("kernelCommandFromServer", KernelCommandEnvelope.Serialize(KernelCommandEnvelope.Create(kernelCommand)), cancellationToken : cancellationToken);
        }
        public void When_command_type_registered_then_kernel_registers_envelope_type_for_serialization(bool withHandler)
        {
            KernelCommandEnvelope.RegisterDefaults();

            using var kernel = new FakeKernel();

            if (withHandler)
            {
                kernel.RegisterCommandHandler <CustomCommandTypes.FirstSubmission.MyCommand>(
                    (_, _) => Task.CompletedTask);
            }
            else
            {
                kernel.RegisterCommandType <CustomCommandTypes.FirstSubmission.MyCommand>();
            }

            var    originalCommand             = new CustomCommandTypes.FirstSubmission.MyCommand("xyzzy");
            string envelopeJson                = KernelCommandEnvelope.Serialize(originalCommand);
            var    roundTrippedCommandEnvelope = KernelCommandEnvelope.Deserialize(envelopeJson);

            roundTrippedCommandEnvelope
            .Command
            .Should()
            .BeOfType <CustomCommandTypes.FirstSubmission.MyCommand>()
            .Which
            .Info
            .Should()
            .Be(originalCommand.Info);
        }
Esempio n. 3
0
        public async Task SendAsync(KernelCommand kernelCommand, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            _sender.WriteMessage(KernelCommandEnvelope.Serialize(KernelCommandEnvelope.Create(kernelCommand)));

            await _sender.FlushAsync(cancellationToken);
        }
Esempio n. 4
0
        public static void RegisterEventsAndCommands()
        {
            // register commands and event with serialization

            var commandTypes = typeof(CSharpProjectKernel).Assembly.ExportedTypes
                               .Where(t => !t.IsAbstract && !t.IsInterface)
                               .Where(t => typeof(KernelCommand).IsAssignableFrom(t))
                               .OrderBy(t => t.Name)
                               .ToList();
            var eventTypes = typeof(CSharpProjectKernel).Assembly.ExportedTypes
                             .Where(t => !t.IsAbstract && !t.IsInterface)
                             .Where(t => typeof(KernelEvent).IsAssignableFrom(t))
                             .OrderBy(t => t.Name)
                             .ToList();

            foreach (var commandType in commandTypes)
            {
                KernelCommandEnvelope.RegisterCommand(commandType);
            }

            foreach (var eventType in eventTypes)
            {
                KernelEventEnvelope.RegisterEvent(eventType);
            }
        }
Esempio n. 5
0
 public void Dispose()
 {
     KernelCommandEnvelope.ResetToDefaults();
     KernelEventEnvelope.ResetToDefaults();
     _host.Value.Dispose();
     _host = null;
 }
Esempio n. 6
0
 public static TKernel UseVSCodeCommands <TKernel>(this TKernel kernel) where TKernel : Kernel
 {
     kernel.RegisterCommandType <GetInput>();
     KernelCommandEnvelope.RegisterCommand <GetInput>();
     KernelEventEnvelope.RegisterEvent <InputProduced>();
     return(kernel);
 }
        public CommandLineParserTests(ITestOutputHelper output)
        {
            KernelCommandEnvelope.ResetToDefaults();
            KernelEventEnvelope.ResetToDefaults();

            _output            = output;
            _serviceCollection = new ServiceCollection();
            _parser            = CommandLineParser.Create(
                _serviceCollection,
                startServer: (options, invocationContext) =>
            {
                _startOptions = options;
            },
                jupyter: (startupOptions, console, startServer, context) =>
            {
                _startOptions = startupOptions;
                return(Task.FromResult(1));
            },
                startStdIO: (startupOptions, kernel, console) =>
            {
                _startOptions = startupOptions;
                return(Task.FromResult(1));
            },
                startHttp: (startupOptions, console, startServer, context) =>
            {
                _startOptions = startupOptions;
                return(Task.FromResult(1));
            },
                telemetry: new FakeTelemetry(),
                firstTimeUseNoticeSentinel: new NopFirstTimeUseNoticeSentinel());

            _connectionFile        = new FileInfo(Path.GetTempFileName());
            _kernelSpecInstallPath = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()));
        }
        public void Create_creates_envelope_of_the_correct_type()
        {
            IKernelCommand command = new SubmitCode("display(123)");

            var envelope = KernelCommandEnvelope.Create(command);

            envelope.Should().BeOfType<KernelCommandEnvelope<SubmitCode>>();
        }
        public void Create_creates_envelope_with_reference_to_original_command()
        {
            IKernelCommand command = new SubmitCode("display(123)");

            var envelope = KernelCommandEnvelope.Create(command);

            envelope.Command.Should().BeSameAs(command);
        }
Esempio n. 10
0
 public static T UseQuitCommand <T>(this T kernel, IDisposable disposeOnQuit, CancellationToken cancellationToken)
     where T : Kernel
 {
     Quit.DisposeOnQuit = disposeOnQuit;
     KernelCommandEnvelope.RegisterCommandType <Quit>(nameof(Quit));
     cancellationToken.Register(async() => { await kernel.SendAsync(new Quit()); });
     return(kernel);
 }
        public async Task stdio_command_extends_the_protocol_with_quit_command()
        {
            await _parser.InvokeAsync("stdio");

            var envelope = KernelCommandEnvelope.Deserialize(@"{ commandType: ""Quit"", command : { } }");

            envelope.Command.Should()
            .BeOfType <Quit>();
        }
Esempio n. 12
0
        public async Task HandleAsync(SubmitCode command, KernelInvocationContext context)
        {
            var envelope = KernelCommandEnvelope.Create(command);

            _clientStream.WriteMessage(KernelCommandEnvelope.Serialize(envelope));
            await _clientStream.FlushAsync();

            await PollEvents(envelope.Token);
        }
        public static Task WriteAsync(
            this StandardIOKernelServer server,
            KernelCommand command)
        {
            var json = KernelCommandEnvelope.Serialize(
                KernelCommandEnvelope.Create(command));

            return(server.WriteAsync(json));
        }
    static CSharpProjectKernel()
    {
        // register commands and event with serialization
        KernelCommandEnvelope.RegisterCommand <OpenProject>();
        KernelCommandEnvelope.RegisterCommand <OpenDocument>();
        KernelCommandEnvelope.RegisterCommand <CompileProject>();

        KernelEventEnvelope.RegisterEvent <DocumentOpened>();
        KernelEventEnvelope.RegisterEvent <AssemblyProduced>();
    }
Esempio n. 15
0
        internal async Task ExecuteEnvelope(string token)
        {
            var envelope = EnvelopeHelper.GetAndDeleteEnvelope(token);

            if (envelope != null)
            {
                TrackEvents(token);
                var serialized = KernelCommandEnvelope.Serialize(envelope);
                await DotNetInteractiveProcess.StandardInput.WriteLineAsync(serialized);
            }
        }
Esempio n. 16
0
        public void Command_contract_has_not_been_broken(KernelCommand command)
        {
            var _configuration = new Configuration()
                                 .UsingExtension($"{command.GetType().Name}.json")
                                 .SetInteractive(Debugger.IsAttached);

            command.SetToken("the-token");

            var json = KernelCommandEnvelope.Serialize(command);

            this.Assent(json, _configuration);
        }
Esempio n. 17
0
        public async Task when_a_KernelCommandEnvelope_is_received_it_reads_the_command()
        {
            var kernelCommand = new SubmitCode("x=1");
            var message       = KernelCommandEnvelope.Serialize(KernelCommandEnvelope.Create(kernelCommand));

            using var stringReader = new StringReader(message);
            var receiver = new KernelCommandAndEventTextReceiver(stringReader);

            var d = await receiver.CommandsAndEventsAsync(CancellationToken.None).FirstAsync();

            d.Command.Should().BeEquivalentTo(kernelCommand);
        }
Esempio n. 18
0
        public async Task when_a_KernelCommand_is_sent_it_writes_a_KernelCommandEnvelope()
        {
            var kernelCommand = new SubmitCode("x=1");
            var buffer        = new StringBuilder();

            var sender = new KernelCommandAndEventTextStreamSender(new StringWriter(buffer));
            await sender.SendAsync(kernelCommand, CancellationToken.None);

            var envelopeMessage = buffer.ToString();

            envelopeMessage.Should()
            .BeEquivalentTo(KernelCommandEnvelope.Serialize(KernelCommandEnvelope.Create(kernelCommand)) + KernelCommandAndEventTextStreamSender.Delimiter);
        }
        public SerializationTests(ITestOutputHelper output)
        {
            _output = output;

            KernelCommandEnvelope.RegisterCommand <OpenProject>();
            KernelCommandEnvelope.RegisterCommand <OpenDocument>();
            KernelCommandEnvelope.RegisterCommand <CompileProject>();
            KernelEventEnvelope.RegisterEvent <DocumentOpened>();
            KernelEventEnvelope.RegisterEvent <AssemblyProduced>();

            KernelCommandEnvelope.RegisterCommand <GetInput>();
            KernelEventEnvelope.RegisterEvent <InputProduced>();
        }
        public async Task kernel_server_honors_log_path()
        {
            using var logPath        = DisposableDirectory.Create();
            using var outputReceived = new ManualResetEvent(false);
            var errorLines = new List <string>();

            // start as external process
            var dotnet = new Dotnet(logPath.Directory);

            using var kernelServerProcess = dotnet.StartProcess(
                      args: $@"""{typeof(Program).Assembly.Location}"" kernel-server --log-path ""{logPath.Directory.FullName}""",
                      output: _line => { outputReceived.Set(); },
                      error: errorLines.Add);

            // wait for log file to be created
            var logFile = await logPath.Directory.WaitForFile(
                timeout : TimeSpan.FromSeconds(2),
                predicate : _file => true); // any matching file is the one we want

            errorLines.Should().BeEmpty();
            logFile.Should().NotBeNull("unable to find created log file");

            // submit code
            var submission     = new SubmitCode("1+1");
            var submissionJson = KernelCommandEnvelope.Serialize(KernelCommandEnvelope.Create(submission));
            await kernelServerProcess.StandardInput.WriteLineAsync(submissionJson);

            await kernelServerProcess.StandardInput.FlushAsync();

            // wait for output to proceed
            var gotOutput = outputReceived.WaitOne(timeout: TimeSpan.FromSeconds(2));

            gotOutput.Should().BeTrue("expected to receive on stdout");

            // kill
            kernelServerProcess.StandardInput.Close(); // simulate Ctrl+C
            await Task.Delay(TimeSpan.FromSeconds(2)); // allow logs to be flushed

            kernelServerProcess.Kill();
            kernelServerProcess.WaitForExit(2000).Should().BeTrue();
            errorLines.Should().BeEmpty();

            // check log file for expected contents
            (await logFile.WaitForFileCondition(
                 timeout: TimeSpan.FromSeconds(2),
                 predicate: file => file.Length > 0))
            .Should().BeTrue("expected non-empty log file");
            var logFileContents = File.ReadAllText(logFile.FullName);

            logFileContents.Should().Contain("โ„น OnAssemblyLoad: ");
        }
Esempio n. 21
0
        public void All_command_types_are_round_trip_serializable(IKernelCommand command)
        {
            var originalEnvelope = KernelCommandEnvelope.Create(command);

            var json = KernelCommandEnvelope.Serialize(originalEnvelope);

            _output.WriteLine(json);

            var deserializedEnvelope = KernelCommandEnvelope.Deserialize(json);

            deserializedEnvelope
            .Should()
            .BeEquivalentTo(originalEnvelope);
        }
Esempio n. 22
0
        public Task OnLoadAsync(Kernel kernel)
        {
            if (kernel is CompositeKernel compositeKernel)
            {
                var outputOption = new Option <FileInfo>(
                    new [] { "-o", "--output" },
                    description: "The name of the file to write the transcript to");

                var record = new Command(
                    "#!record",
                    "Records a replayable transcript of code submissions.")
                {
                    outputOption
                };

                record.Handler = CommandHandler.Create((InvocationContext ctx) =>
                {
                    var outputFile = ctx.ParseResult.GetValueForOption(outputOption);

                    compositeKernel.AddMiddleware(async(command, context, next) =>
                    {
                        var json = KernelCommandEnvelope.Serialize(command);

                        await File.AppendAllLinesAsync(
                            outputFile.FullName,
                            new[]
                        {
                            json
                        });

                        await next(command, context);
                    });

                    return(Task.CompletedTask);
                });

                compositeKernel.AddDirective(record);
            }

            KernelInvocationContext.Current?.Display(
                new HtmlString(@"<details><summary>Use the <code>#!record</code> magic command to keep a transcript of the code you run.</summary>
    <p>Once you enable transcripts using <code>#!record</code>, each code submission (including re-running cells) is recorded in the specified file. The JSON format used is the same format recognized by the .NET Interactive <code>stdio</code> and <code>http</code> APIs and can be used to replay an interactive session via automation.</p>
    <img src=""https://user-images.githubusercontent.com/547415/109562409-343b1300-7a93-11eb-8ebf-79bb6af028cf.png"" width=""75%"" />
    </details>"),
                "text/html");

            return(Task.CompletedTask);
        }
Esempio n. 23
0
        public void All_command_types_are_round_trip_serializable(KernelCommand command)
        {
            var originalEnvelope = KernelCommandEnvelope.Create(command);

            var json = KernelCommandEnvelope.Serialize(originalEnvelope);

            _output.WriteLine(json);

            var deserializedEnvelope = KernelCommandEnvelope.Deserialize(json);

            deserializedEnvelope
            .Should()
            .BeEquivalentTo(originalEnvelope,
                            o => o.Excluding(e => e.Command.Properties)
                            .Excluding(e => e.Command.Handler));
        }
Esempio n. 24
0
        public async IAsyncEnumerable <CommandOrEvent> CommandsOrEventsAsync([EnumeratorCancellation] CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                KernelCommand kernelCommand = null;
                KernelEvent   kernelEvent   = null;

                var message = await ReadMessageAsync(cancellationToken);

                if (string.IsNullOrWhiteSpace(message))
                {
                    continue;
                }

                var isParseError = false;
                try
                {
                    var jsonObject = JsonDocument.Parse(message).RootElement;
                    if (IsEventEnvelope(jsonObject))
                    {
                        var kernelEventEnvelope = KernelEventEnvelope.Deserialize(jsonObject);
                        kernelEvent = kernelEventEnvelope.Event;
                    }
                    else if (IsCommandEnvelope(jsonObject))
                    {
                        var kernelCommandEnvelope = KernelCommandEnvelope.Deserialize(jsonObject);
                        kernelCommand = kernelCommandEnvelope.Command;
                    }
                    else
                    {
                        kernelEvent = new DiagnosticLogEntryProduced(
                            $"Expected {nameof(KernelCommandEnvelope)} or {nameof(KernelEventEnvelope)} but received: \n{message}", KernelCommand.None);
                        isParseError = true;
                    }
                }
                catch (Exception ex)
                {
                    kernelEvent = new DiagnosticLogEntryProduced(
                        $"Error while parsing Envelope: {message} \n{ex.Message}", KernelCommand.None);
                    isParseError = true;
                }

                yield return(kernelCommand is null ? new CommandOrEvent(kernelEvent, isParseError) : new CommandOrEvent(kernelCommand));
            }
        }
Esempio n. 25
0
        protected override async Task <CommandOrEvent> ReadCommandOrEventAsync(CancellationToken cancellationToken)
        {
            KernelCommand kernelCommand = null;
            KernelEvent   kernelEvent   = null;

            var message = await ReadMessageAsync(cancellationToken);

            if (string.IsNullOrWhiteSpace(message))
            {
                return(null);
            }

            var isParseError = false;

            try
            {
                var jsonObject = JsonDocument.Parse(message).RootElement;
                if (IsEventEnvelope(jsonObject))
                {
                    var kernelEventEnvelope = KernelEventEnvelope.Deserialize(jsonObject);
                    kernelEvent = kernelEventEnvelope.Event;
                }
                else if (IsCommandEnvelope(jsonObject))
                {
                    var kernelCommandEnvelope = KernelCommandEnvelope.Deserialize(jsonObject);
                    kernelCommand = kernelCommandEnvelope.Command;
                }
                else
                {
                    kernelEvent = new DiagnosticLogEntryProduced(
                        $"Expected {nameof(KernelCommandEnvelope)} or {nameof(KernelEventEnvelope)} but received: \n{message}", KernelCommand.None);
                    isParseError = true;
                }
            }
            catch (Exception ex)
            {
                kernelEvent = new DiagnosticLogEntryProduced(
                    $"Error while parsing Envelope: {message} \n{ex.Message}", KernelCommand.None);
                isParseError = true;
            }

            return(kernelCommand is null ? new CommandOrEvent(kernelEvent, isParseError) : new CommandOrEvent(kernelCommand));
        }
        public void When_command_type_reregistered_with_changed_type_command_then_kernel_registers_updated_envelope_type_for_serialization(bool withHandler)
        {
            // Notebook authors should be able to develop their custom commands experimentally and progressively,
            // so we don't want any "you have to restart your kernel now" situations just because you already
            // called RegisterCommandHandler once for a particular command type.
            KernelCommandEnvelope.RegisterDefaults();

            using var kernel = new FakeKernel();

            if (withHandler)
            {
                kernel.RegisterCommandHandler <CustomCommandTypes.FirstSubmission.MyCommand>(
                    (_, _) => Task.CompletedTask);
                kernel.RegisterCommandHandler <CustomCommandTypes.SecondSubmission.MyCommand>(
                    (_, _) => Task.CompletedTask);
            }
            else
            {
                kernel.RegisterCommandType <CustomCommandTypes.FirstSubmission.MyCommand>();
                kernel.RegisterCommandType <CustomCommandTypes.SecondSubmission.MyCommand>();
            }

            var    originalCommand             = new CustomCommandTypes.SecondSubmission.MyCommand("xyzzy", 42);
            string envelopeJson                = KernelCommandEnvelope.Serialize(originalCommand);
            var    roundTrippedCommandEnvelope = KernelCommandEnvelope.Deserialize(envelopeJson);

            roundTrippedCommandEnvelope
            .Command
            .Should()
            .BeOfType <CustomCommandTypes.SecondSubmission.MyCommand>()
            .Which
            .Info
            .Should()
            .Be(originalCommand.Info);
            roundTrippedCommandEnvelope
            .Command
            .As <CustomCommandTypes.SecondSubmission.MyCommand>()
            .AdditionalProperty
            .Should()
            .Be(originalCommand.AdditionalProperty);
        }
        public Task OnLoadAsync(IKernel kernel)
        {
            if (kernel is CompositeKernel kernelBase)
            {
                var record = new Command(
                    "#!record",
                    "Records a replayable transcript of code submissions.")
                {
                    new Option <FileInfo>(
                        new [] { "-o", "--output" },
                        description: "The name of the file to write the transcript to")
                };

                record.Handler = CommandHandler.Create <FileInfo>(output =>
                {
                    kernelBase.AddMiddleware(async(command, context, next) =>
                    {
                        var json = KernelCommandEnvelope.Serialize(command);

                        await File.AppendAllLinesAsync(
                            output.FullName,
                            new[]
                        {
                            json
                        });

                        await next(command, context);
                    });

                    return(Task.CompletedTask);
                });

                kernelBase.AddDirective(record);
            }

            return(Task.CompletedTask);
        }
Esempio n. 28
0
 public async Task SubmitCommand(string kernelCommandEnvelope)
 {
     var envelope = KernelCommandEnvelope.Deserialize(kernelCommandEnvelope);
     var command  = envelope.Command;
     await _connection.Kernel.SendAsync(command);
 }
Esempio n. 29
0
 public Task SendAsync(KernelCommand kernelCommand, CancellationToken cancellationToken)
 {
     _onSendAsync?.Invoke(new CommandOrEvent(KernelCommandEnvelope.Deserialize(KernelCommandEnvelope.Serialize(kernelCommand)).Command));
     return(Task.CompletedTask);
 }
Esempio n. 30
0
#pragma warning disable CS1998
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext,
                                                             CancellationToken cancellationToken)
        {
            var value       = turnContext.Activity;
            var attachments = turnContext.Activity.Attachments;

            if (turnContext.Activity.Value == null) // someone typed in something, it isn't a card
            {
                var content = turnContext.Activity.Text;
                var code    = CheckForCode(content);

                var conversationReference = turnContext.Activity.GetConversationReference();
                var mention = new Mention
                {
                    Mentioned = turnContext.Activity.From,
                    Text      = $"<at>{turnContext.Activity.From.Name}</at>",
                };

                if (!string.IsNullOrEmpty(code))
                {
                    if (DotNetInteractiveProcessRunner.Instance.CanExecuteCode)
                    {
                        var submissionToken = Guid.NewGuid().ToString("N");
                        var messageText     = string.Empty;
                        var user            = UserGame.GetOrCreateUser(mention, turnContext.Activity.From);
                        if (UserGame.CurrentChatUser?.Id != user.Id)
                        {
                            UserGame.CurrentChatUser = user;
                            messageText = $"Hey {mention.Text} It looks like you're typing some code. Let me run it for you! ๐Ÿ˜Š";
                        }
                        else
                        {
                            messageText = UserGame.GetMessageForUser(mention);
                        }

                        await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async (context, token) =>
                        {
                            var message = MessageFactory.Text(messageText);
                            if (messageText.Contains(mention.Text))
                            {
                                message.Entities.Add(mention);
                            }
                            await context.SendActivityAsync(message, token);
                        }, cancellationToken);

                        // build the envelope
                        var submitCode = new SubmitCode(code);
                        submitCode.SetToken(submissionToken);
                        var envelope = KernelCommandEnvelope.Create(submitCode);
                        var channel  = ContentSubjectHelper.GetOrCreateChannel(submissionToken);
                        EnvelopeHelper.StoreEnvelope(submissionToken, envelope);
                        var cardSent = false;
                        channel
                        .Timeout(DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(1)))
                        .Buffer(TimeSpan.FromSeconds(1))
                        .Subscribe(
                            onNext: async formattedValues =>
                        {
                            turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference,
                                                                          (context, token) =>
                            {
                                if (formattedValues.Count > 0)
                                {
                                    var hasHtml = formattedValues.Any(f => f.MimeType == HtmlFormatter.MimeType);

                                    if (hasHtml)
                                    {
                                        if (!cardSent)
                                        {
                                            cardSent = true;
                                            var card = new HeroCard
                                            {
                                                Title    = "Your output is too awesome ๐Ÿ˜Ž",
                                                Subtitle = "Use the viewer to see it.",
                                                Buttons  = new List <CardAction>
                                                {
                                                    new TaskModuleAction("Open Viewer",
                                                                         new { data = submissionToken })
                                                },
                                            }.ToAttachment();
                                            var message = MessageFactory.Attachment(card);
                                            context.SendActivityAsync(message, token).Wait();
                                        }
                                    }
                                    else
                                    {
                                        var content = string.Join("\n", formattedValues.Select(f => f.Value));
                                        var message = MessageFactory.Text($"```\n{content.HtmlEncode()}");
                                        context.SendActivityAsync(message, token).Wait();
                                    }
                                }

                                return(Task.CompletedTask);
                            }, cancellationToken).Wait();
                        }, onCompleted: async() =>
                        {
                            await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async(context, token) =>
                            {
                                await Task.Delay(1000);
                                var message = MessageFactory.Text($"{mention.Text} all done here ๐Ÿ‘");
                                message.Entities.Add(mention);
                                await context.SendActivityAsync(message, token);
                            }, cancellationToken);
                        },
                            onError: async error =>
                        {
                            await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async(context, token) =>
                            {
                                await Task.Delay(1000);
                                var message = MessageFactory.Text($@"{mention.Text} there were some issues ๐Ÿ‘Ž :\n {error.Message}");
                                message.Entities.Add(mention);
                                await context.SendActivityAsync(message, token);
                            }, cancellationToken);
                        });

                        user.IncrementCodeSubmissionCount();
                        await DotNetInteractiveProcessRunner.Instance.ExecuteEnvelope(submissionToken);
                    }
                    else
                    {
                        await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async (context, token) =>
                        {
                            var message = MessageFactory.Text($"Sorry {mention.Text} cannot execute your code now. ๐Ÿ˜“");
                            message.Entities.Add(mention);
                            await context.SendActivityAsync(message, token);
                        }, cancellationToken);
                    }
                }
                else if (string.IsNullOrWhiteSpace(DotNetInteractiveProcessRunner.Instance.SessionLanguage))
                {
                    var card   = CardUtilities.CreateAdaptiveCardAttachment(CardJsonFiles.SelectLanguage);
                    var attach = MessageFactory.Attachment(card);
                    await turnContext.SendActivityAsync(attach, cancellationToken);
                }
                else if (content.Contains("๐Ÿ‘Š"))
                {
                    var mentioned = turnContext.Activity.GetMentions()?.FirstOrDefault(m => m.Mentioned.Id.EndsWith(_botId));
                    if (mentioned != null)
                    {
                        await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference,
                                                                            async (context, token) =>
                        {
                            var message = MessageFactory.Text($"{mention.Text} back at you my friend! ๐Ÿ‘Š");
                            message.Entities.Add(mention);
                            await context.SendActivityAsync(message, token);
                        }, cancellationToken);
                    }
                }
            }
            else
            {
                var userAction = turnContext.Activity.Value;

                if (((JObject)userAction).Value <string>("userAction").Equals("SelectLanguage"))
                {
                    if (string.IsNullOrWhiteSpace(DotNetInteractiveProcessRunner.Instance.SessionLanguage))
                    {
                        var language = ((JObject)userAction).Value <string>("language");
                        DotNetInteractiveProcessRunner.Instance.SessionLanguage = language;
                        var languageLabel = ((JObject)userAction).Value <string>("languageLabel");
                        var message       = MessageFactory.Text($"All set. Let's write some {DotNetInteractiveProcessRunner.Instance.SessionLanguage} code together! ๐Ÿค˜๐Ÿป");
                        await turnContext.SendActivityAsync(message, cancellationToken);
                    }
                }
            }
        }