diff --git a/src/System Application/App/Agent/Interaction/Internal/AgentTaskLogEntryList.Page.al b/src/System Application/App/Agent/Interaction/Internal/AgentTaskLogEntryList.Page.al
index 501895ecd0..5ddb43e88a 100644
--- a/src/System Application/App/Agent/Interaction/Internal/AgentTaskLogEntryList.Page.al
+++ b/src/System Application/App/Agent/Interaction/Internal/AgentTaskLogEntryList.Page.al
@@ -58,12 +58,22 @@ page 4303 "Agent Task Log Entry List"
field("User Full Name"; Rec."User Full Name")
{
Caption = 'User Full Name';
- Tooltip = 'Specifies the full name of the user that was involved in performing the step..';
+ Tooltip = 'Specifies the full name of the user that was involved in performing the step.';
}
field(Description; Rec.Description)
{
Caption = 'Description';
}
+ field(Reason; Rec.Reason)
+ {
+ ApplicationArea = All;
+ Caption = 'Reason';
+
+ trigger OnDrillDown()
+ begin
+ Message(Rec.Reason);
+ end;
+ }
field(Details; DetailsTxt)
{
Caption = 'Details';
@@ -75,6 +85,28 @@ page 4303 "Agent Task Log Entry List"
end;
}
}
+ fixed(DisclaimerGroup)
+ {
+ group(Left)
+ {
+ ShowCaption = false;
+ label(Empty)
+ {
+ ApplicationArea = All;
+ Caption = '', Locked = true;
+ }
+ }
+ group(Right)
+ {
+ ShowCaption = false;
+ label(Disclaimer)
+ {
+ ApplicationArea = All;
+ Caption = 'AI-generated content may be incorrect.';
+ Style = Subordinate;
+ }
+ }
+ }
}
}
@@ -85,6 +117,9 @@ page 4303 "Agent Task Log Entry List"
actionref(Refresh_Promoted; Refresh)
{
}
+ actionref(Feedback_Promoted; Feedback)
+ {
+ }
}
area(Creation)
{
@@ -99,6 +134,19 @@ page 4303 "Agent Task Log Entry List"
CurrPage.Update(false);
end;
}
+ action(Feedback)
+ {
+ ApplicationArea = All;
+ Caption = 'Give Feedback';
+ ToolTip = 'Tell us what you think about the agent and suggest new features or improvements.';
+ Image = Comment;
+ Scope = Repeater;
+
+ trigger OnAction()
+ begin
+ RequestFeedback();
+ end;
+ }
}
}
@@ -119,14 +167,23 @@ page 4303 "Agent Task Log Entry List"
DetailsTxt := AgentTaskImpl.GetDetailsForAgentTaskLogEntry(Rec);
case Rec.Level of
Rec.Level::Error:
- TypeStyle := 'Unfavorable';
+ TypeStyle := Format(PageStyle::Unfavorable);
Rec.Level::Warning:
- TypeStyle := 'Ambiguous';
+ TypeStyle := Format(PageStyle::Ambiguous);
else
- TypeStyle := 'Standard';
+ TypeStyle := Format(PageStyle::Standard);
end;
end;
+ local procedure RequestFeedback()
+ var
+ AgentUserFeedback: Codeunit "Agent User Feedback";
+ ContextProperties: Dictionary of [Text, Text];
+ begin
+ ContextProperties := AgentUserFeedback.InitializeAgentTaskContext(Rec."Task ID");
+ AgentUserFeedback.RequestFeedback(ContextProperties);
+ end;
+
var
DetailsTxt: Text;
TypeStyle: Text;
diff --git a/src/System Application/App/Agent/Interaction/Internal/AgentUserFeedback.Codeunit.al b/src/System Application/App/Agent/Interaction/Internal/AgentUserFeedback.Codeunit.al
new file mode 100644
index 0000000000..268da52788
--- /dev/null
+++ b/src/System Application/App/Agent/Interaction/Internal/AgentUserFeedback.Codeunit.al
@@ -0,0 +1,132 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.Agents;
+
+using System.Feedback;
+
+codeunit 4329 "Agent User Feedback"
+{
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ var
+ AgentMetadataProviderTok: Label 'Copilot.Agents.AgentTypeId', Locked = true;
+ AgentUserSecurityIdTok: Label 'Copilot.Agents.AgentId', Locked = true;
+ AgentTaskIdTok: Label 'Copilot.Agents.TaskId', Locked = true;
+ AgentTaskLogEntryIdTok: Label 'Copilot.Agents.TaskLogEntryId', Locked = true;
+ AgentTaskLogEntryTypeTok: Label 'Copilot.Agents.TaskLogEntryType', Locked = true;
+ CopilotThumbsUpFeedbackTok: Label 'Copilot.ThumbsUp', Locked = true;
+ CopilotThumbsDownFeedbackTok: Label 'Copilot.ThumbsDown', Locked = true;
+ AgentFeatureNameTok: Label 'Agents', Locked = true;
+ AgentFeatureAreaTok: Label 'Agents', Locked = true;
+ AgentFeatureAreaDisplayNameLbl: Label 'Agents';
+
+ procedure InitializeAgentContext(AgentMetadataProvider: Enum "Agent Metadata Provider"; AgentUserSecurityID: Guid) Context: Dictionary of [Text, Text]
+ begin
+ Context.Add(AgentMetadataProviderTok, Format(AgentMetadataProvider.AsInteger()));
+ Context.Add(AgentUserSecurityIdTok, Format(AgentUserSecurityID));
+ end;
+
+ procedure InitializeAgentTaskContext(TaskId: BigInteger) Context: Dictionary of [Text, Text]
+ var
+ Agent: Record Agent;
+ begin
+ if not (TryFindRelatedAgentToTask(TaskId, Agent)) then
+ exit;
+
+ Context := InitializeAgentContext(Agent."Agent Metadata Provider", Agent."User Security ID");
+ Context.Add(AgentTaskIdTok, Format(TaskId));
+ end;
+
+ procedure InitializeAgentTaskLogEntryContext(AgentTaskLogEntry: Record "Agent Task Log Entry") Context: Dictionary of [Text, Text]
+ var
+ Agent: Record Agent;
+ begin
+ if not (TryFindRelatedAgentToTask(AgentTaskLogEntry."Task ID", Agent)) then
+ exit;
+
+ Context := InitializeAgentContext(Agent."Agent Metadata Provider", Agent."User Security ID");
+ Context.Add(AgentTaskIdTok, Format(AgentTaskLogEntry."Task ID"));
+ Context.Add(AgentTaskLogEntryIdTok, Format(AgentTaskLogEntry.ID));
+ Context.Add(AgentTaskLogEntryTypeTok, Format(AgentTaskLogEntry.Type));
+ end;
+
+ procedure RequestFeedback(ContextProperties: Dictionary of [Text, Text])
+ var
+ MicrosoftUserFeedback: Codeunit "Microsoft User Feedback";
+ EmptyContextFiles: Dictionary of [Text, Text];
+ begin
+ MicrosoftUserFeedback.SetIsAIFeedback(true);
+ MicrosoftUserFeedback.RequestFeedback(AgentFeatureNameTok, AgentFeatureAreaTok, AgentFeatureAreaDisplayNameLbl, EmptyContextFiles, ContextProperties);
+ end;
+
+ #region Property Tokens
+
+ procedure GetAgentMetadataProviderTok(): Text
+ begin
+ exit(AgentMetadataProviderTok);
+ end;
+
+ procedure GetAgentUserSecurityIdTok(): Text
+ begin
+ exit(AgentUserSecurityIdTok);
+ end;
+
+ procedure GetAgentTaskIdTok(): Text
+ begin
+ exit(AgentTaskIdTok);
+ end;
+
+ procedure GetAgentTaskLogEntryIdTok(): Text
+ begin
+ exit(AgentTaskLogEntryIdTok);
+ end;
+
+ procedure GetAgentTaskLogEntryTypeTok(): Text
+ begin
+ exit(AgentTaskLogEntryTypeTok);
+ end;
+
+ procedure GetCopilotThumbsUpFeedbackTok(): Text
+ begin
+ exit(CopilotThumbsUpFeedbackTok);
+ end;
+
+ procedure GetCopilotThumbsDownFeedbackTok(): Text
+ begin
+ exit(CopilotThumbsDownFeedbackTok);
+ end;
+
+ #endregion
+
+ procedure IsAgentTaskFeedback(Context: Dictionary of [Text, Text]): Boolean
+ begin
+ exit(Context.ContainsKey(AgentMetadataProviderTok)
+ and Context.ContainsKey(AgentUserSecurityIdTok)
+ and Context.ContainsKey(AgentTaskIdTok));
+ end;
+
+ procedure IsAgentTaskMetadataProvider(AgentMetadataProvider: Enum "Agent Metadata Provider"; Context: Dictionary of [Text, Text]): Boolean
+ begin
+ if not Context.ContainsKey(AgentMetadataProviderTok) then
+ exit(false);
+
+ exit(Context.Get(AgentMetadataProviderTok) = Format(AgentMetadataProvider.AsInteger()));
+ end;
+
+ local procedure TryFindRelatedAgentToTask(TaskId: Integer; var Agent: Record Agent): Boolean
+ var
+ Tasks: Record "Agent Task";
+ begin
+ if not Tasks.Get(TaskId) then
+ exit(false);
+
+ if not Agent.Get(Tasks."Agent User Security ID") then
+ exit(false);
+
+ exit(true);
+ end;
+}
\ No newline at end of file
diff --git a/src/System Application/App/Extension Management/src/ExtensionManagement.Codeunit.al b/src/System Application/App/Extension Management/src/ExtensionManagement.Codeunit.al
index ada09c3bfc..e76da6a5cf 100644
--- a/src/System Application/App/Extension Management/src/ExtensionManagement.Codeunit.al
+++ b/src/System Application/App/Extension Management/src/ExtensionManagement.Codeunit.al
@@ -263,6 +263,16 @@ codeunit 2504 "Extension Management"
exit(ExtensionOperationImpl.GetAppName(AppId))
end;
+ ///
+ /// Returns the Publisher of the app given the App Id.
+ ///
+ /// The unique identifier of the app.
+ /// The publisher of the app.
+ procedure GetAppPublisher(AppId: Guid): Text
+ begin
+ exit(ExtensionOperationImpl.GetAppPublisher(AppId))
+ end;
+
///
/// Returns the detailed message from a deployment operation.
///
diff --git a/src/System Application/App/Extension Management/src/ExtensionOperationImpl.Codeunit.al b/src/System Application/App/Extension Management/src/ExtensionOperationImpl.Codeunit.al
index aaeacf6d75..5d5514f5f3 100644
--- a/src/System Application/App/Extension Management/src/ExtensionOperationImpl.Codeunit.al
+++ b/src/System Application/App/Extension Management/src/ExtensionOperationImpl.Codeunit.al
@@ -436,6 +436,19 @@ codeunit 2503 "Extension Operation Impl"
end;
end;
+ procedure GetAppPublisher(AppId: Guid) AppPublisher: Text
+ var
+ PublishedApplication: Record "Published Application";
+ begin
+ if PublishedApplication.ReadPermission then begin
+ PublishedApplication.SetRange(ID, AppId);
+ PublishedApplication.SetRange("Tenant Visible", true);
+
+ if PublishedApplication.FindFirst() then
+ AppPublisher := PublishedApplication.Publisher;
+ end;
+ end;
+
internal procedure GetAppName(AppId: Guid; OperationId: Guid) AppName: Text
begin
AppName := GetAppName(AppId);