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);