Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.Logging;

namespace Microsoft.Agents.AI.Workflows.Declarative.Interpreter;

Expand All @@ -27,6 +28,7 @@ internal static class Steps
public static string Restart(string actionId) => $"{actionId}_{nameof(Restart)}";
}

private readonly ILogger _logger;
private readonly Executor _rootAction;
private readonly WorkflowModel<Func<object?, bool>> _workflowModel;
private readonly DeclarativeWorkflowOptions _workflowOptions;
Expand All @@ -37,6 +39,7 @@ public WorkflowActionVisitor(
WorkflowFormulaState state,
DeclarativeWorkflowOptions options)
{
this._logger = options.LoggerFactory.CreateLogger<WorkflowActionVisitor>();
this._rootAction = rootAction;
this._workflowModel = new WorkflowModel<Func<object?, bool>>((IModeledAction)rootAction);
this._workflowOptions = options;
Expand Down Expand Up @@ -645,6 +648,7 @@ private static string GetParentId(BotElement item) =>
private void NotSupported(DialogAction item)
{
Debug.WriteLine($"> UNKNOWN: {new string('\t', this._workflowModel.GetDepth(item.GetParentId()))}{FormatItem(item)} => {FormatParent(item)}");
this._logger.LogWarning("Unsupported action skipped: {ActionType} ({ActionId}).", item.GetType().Name, item.GetId());
this.HasUnsupportedActions = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit.Sdk;

Expand Down Expand Up @@ -246,6 +247,36 @@ public void UnsupportedAction(Type type)
Assert.True(visitor.HasUnsupportedActions);
}

[Fact]
public void UnsupportedActionLogsWarning()
{
SearchKnowledgeSources.Builder unsupportedAction = new() { Id = "action_bad" };
AdaptiveDialog.Builder dialogBuilder =
new()
{
BeginDialog =
new OnActivity.Builder()
{
Id = "anything",
Actions = [unsupportedAction]
}
};
AdaptiveDialog dialog = dialogBuilder.Build();

WorkflowFormulaState state = new(RecalcEngineFactory.Create());
Mock<ResponseAgentProvider> mockAgentProvider = CreateMockProvider("1");
CapturingLoggerFactory loggerFactory = new();
DeclarativeWorkflowOptions options = new(mockAgentProvider.Object) { LoggerFactory = loggerFactory };
WorkflowActionVisitor visitor = new(new DeclarativeWorkflowExecutor<string>(WorkflowActionVisitor.Steps.Root("anything"), options, state, (message) => DeclarativeWorkflowBuilder.DefaultTransform(message)), state, options);
WorkflowElementWalker walker = new(visitor);
walker.Visit(dialog);

Assert.True(visitor.HasUnsupportedActions);
(LogLevel Level, string Message) warning = Assert.Single(loggerFactory.Entries, entry => entry.Level == LogLevel.Warning);
Assert.Contains(nameof(SearchKnowledgeSources), warning.Message, StringComparison.Ordinal);
Assert.Contains("action_bad", warning.Message, StringComparison.Ordinal);
}

[Theory]
[InlineData("CaseInsensitive.yaml", "end_when_match")]
[InlineData("ClearAllVariables.yaml", "clear_all")]
Expand Down Expand Up @@ -405,4 +436,29 @@ private static Mock<IHttpRequestHandler> CreateMockHttpRequestHandler()
}));
return mockHandler;
}

private sealed class CapturingLoggerFactory : ILoggerFactory
{
public List<(LogLevel Level, string Message)> Entries { get; } = [];

public void AddProvider(ILoggerProvider provider)
{
}

public ILogger CreateLogger(string categoryName) => new CapturingLogger(this.Entries);

public void Dispose()
{
}

private sealed class CapturingLogger(List<(LogLevel Level, string Message)> entries) : ILogger
{
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;

public bool IsEnabled(LogLevel logLevel) => true;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
=> entries.Add((logLevel, formatter(state, exception)));
}
}
}
Loading