/// <inhericdoc /> public List <PredictiveSuggestion> GetSuggestion(PredictionContext context, CancellationToken cancellationToken) { var localCancellationToken = Settings.ContinueOnTimeout ? CancellationToken.None : cancellationToken; IEnumerable <ValueTuple <string, string, PredictionSource> > suggestions = Enumerable.Empty <ValueTuple <string, string, PredictionSource> >(); string maskedUserInput = string.Empty; // This is the list of records of the source suggestion and the prediction source. var telemetryData = new List <ValueTuple <string, PredictionSource> >(); try { maskedUserInput = AzPredictor.MaskCommandLine(context.InputAst.FindAll((ast) => ast is CommandAst, true).LastOrDefault() as CommandAst); suggestions = _service.GetSuggestion(context.InputAst, _settings.SuggestionCount.Value, _settings.MaxAllowedCommandDuplicate.Value, localCancellationToken); localCancellationToken.ThrowIfCancellationRequested(); var userAcceptedAndSuggestion = new Dictionary <string, string>(); foreach (var s in suggestions) { telemetryData.Add(ValueTuple.Create(s.Item2, s.Item3)); userAcceptedAndSuggestion[s.Item1] = s.Item2; } lock (_userAcceptedAndSuggestion) { foreach (var u in userAcceptedAndSuggestion) { _userAcceptedAndSuggestion[u.Key] = u.Value; } } localCancellationToken.ThrowIfCancellationRequested(); var returnedValue = suggestions.Select((r, index) => { return(new PredictiveSuggestion(r.Item1)); }) .ToList(); _telemetryClient.OnGetSuggestion(maskedUserInput, telemetryData, cancellationToken.IsCancellationRequested); return(returnedValue); } catch (Exception e) when(!(e is OperationCanceledException)) { this._telemetryClient.OnGetSuggestionError(e); } return(new List <PredictiveSuggestion>()); }
/// <inhericdoc /> public void StartEarlyProcessing(IReadOnlyList <string> history) { // The context only changes when the user executes the corresponding command. this._azContext?.UpdateContext(); lock (_userAcceptedAndSuggestion) { _userAcceptedAndSuggestion.Clear(); } if (history.Count > 0) { if (_lastTwoMaskedCommands.Any()) { _lastTwoMaskedCommands.Dequeue(); } else { // This is the first time we populate our record. Push the second to last command in history to the // queue. If there is only one command in history, push the command placeholder. if (history.Count() > 1) { string secondToLastLine = history.TakeLast(AzPredictorConstants.CommandHistoryCountToProcess).First(); var secondToLastCommand = GetAstAndMaskedCommandLine(secondToLastLine); _lastTwoMaskedCommands.Enqueue(secondToLastCommand.Item2); _service.RecordHistory(secondToLastCommand.Item1); } else { _lastTwoMaskedCommands.Enqueue(AzPredictorConstants.CommandPlaceholder); // We only extract parameter values from the command line in _service.RecordHistory. // So we don't need to do that for a placeholder. } } string lastLine = history.Last(); var lastCommand = GetAstAndMaskedCommandLine(lastLine); _lastTwoMaskedCommands.Enqueue(lastCommand.Item2); if ((lastCommand.Item2 != null) && !string.Equals(AzPredictorConstants.CommandPlaceholder, lastCommand.Item2, StringComparison.Ordinal)) { _service.RecordHistory(lastCommand.Item1); } _telemetryClient.OnHistory(lastCommand.Item2); _service.RequestPredictions(_lastTwoMaskedCommands); } ValueTuple <CommandAst, string> GetAstAndMaskedCommandLine(string commandLine) { var asts = Parser.ParseInput(commandLine, out _, out _); var allNestedAsts = asts?.FindAll((ast) => ast is CommandAst, true); var commandAst = allNestedAsts?.LastOrDefault() as CommandAst; string maskedCommandLine = null; var commandName = commandAst?.CommandElements?.FirstOrDefault().ToString(); if (_service.IsSupportedCommand(commandName)) { maskedCommandLine = AzPredictor.MaskCommandLine(commandAst); } else { maskedCommandLine = AzPredictorConstants.CommandPlaceholder; } return(ValueTuple.Create(commandAst, maskedCommandLine)); } }