Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,17 @@ codeunit 4300 "Agent Task Impl."
exit((AgentTask.Status = AgentTask.Status::"Stopped by User") or (AgentTask.Status = AgentTask.Status::"Stopped by System"));
end;

internal procedure TryGetAgentRecordFromTaskId(TaskId: Integer; var Agent: Record Agent): Boolean
var
AgentTask: Record "Agent Task";
begin
if AgentTask.Get(TaskId) then
if Agent.Get(AgentTask."Agent User Security ID") then
exit(true);

exit(false);
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"System Action Triggers", GetAgentTaskMessagePageId, '', true, true)]
local procedure OnGetAgentTaskMessagePageId(var PageId: Integer)
begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ page 4303 "Agent Task Log Entry List"
field(Description; Rec.Description)
{
Caption = 'Description';

trigger OnDrillDown()
begin
Message(Rec.Description);
end;
}
field(Reason; Rec.Reason)
{
Caption = 'Reason';

trigger OnDrillDown()
begin
Message(Rec.Reason);
end;
}
field(Details; DetailsTxt)
{
Expand All @@ -75,6 +89,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;
}
}
}
}

area(FactBoxes)
Expand All @@ -97,6 +133,9 @@ page 4303 "Agent Task Log Entry List"
actionref(Refresh_Promoted; Refresh)
{
}
actionref(Feedback_Promoted; Feedback)
{
}
}
area(Creation)
{
Expand All @@ -111,6 +150,24 @@ 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;
Enabled = IsFeedbackActionEnabled;
Visible = IsFeedbackActionEnabled;

trigger OnAction()
var
AgentUserFeedback: Codeunit "Agent User Feedback";
ContextProperties: Dictionary of [Text, Text];
begin
ContextProperties := AgentUserFeedback.InitializeAgentTaskContext(Rec."Task ID");
AgentUserFeedback.RequestFeedback('Agent Task Log Entries', ContextProperties);
end;
}
}
}

Expand All @@ -126,20 +183,27 @@ page 4303 "Agent Task Log Entry List"

local procedure UpdateControls()
var
Agent: Record Agent;
AgentTaskImpl: Codeunit "Agent Task Impl.";
begin
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;

if AgentTaskImpl.TryGetAgentRecordFromTaskId(Rec."Task ID", Agent) then
IsFeedbackActionEnabled := Agent."Publisher Type" <> Agent."Publisher Type"::"Third Party"
else
IsFeedbackActionEnabled := false
end;

var
IsFeedbackActionEnabled: Boolean;
DetailsTxt: Text;
TypeStyle: Text;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// ------------------------------------------------------------------------------------------------
// 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"
{
Access = Internal;
InherentEntitlements = X;
InherentPermissions = X;

// The values below align with the existing feature and context properties from the timeline.
var
AgentUserSecurityIdTok: Label 'Copilot.Agents.AgentId', Locked = true;
AgentMetadataProviderTok: Label 'Copilot.Agents.AgentTypeId', Locked = true;
AgentTaskIdTok: Label 'Copilot.Agents.TaskId', Locked = true;
AgentFeatureAreaTok: Label 'Copilot', Locked = true;
AgentFeatureDisplayNameTok: Label 'Copilot', Locked = true;

// The values below are not used by the timeline.
var
AgentTaskLogEntryIdTok: Label 'Copilot.Agents.TaskLogEntryId', Locked = true;
AgentTaskLogEntryTypeTok: Label 'Copilot.Agents.TaskLogEntryType', Locked = true;


[Scope('OnPrem')]
procedure GetAgentMetadataProviderTok(): Text
begin
exit(AgentMetadataProviderTok);
end;

[Scope('OnPrem')]
procedure GetAgentUserSecurityIdTok(): Text
begin
exit(AgentUserSecurityIdTok);
end;

[Scope('OnPrem')]
procedure GetAgentTaskIdTok(): Text
begin
exit(AgentTaskIdTok);
end;

[Scope('OnPrem')]
procedure GetAgentTaskLogEntryIdTok(): Text
begin
exit(AgentTaskLogEntryIdTok);
end;

[Scope('OnPrem')]
procedure GetAgentTaskLogEntryTypeTok(): Text
begin
exit(AgentTaskLogEntryTypeTok);
end;

[Scope('OnPrem')]
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;

[Scope('OnPrem')]
procedure InitializeAgentTaskContext(TaskId: BigInteger) Context: Dictionary of [Text, Text]
var
Agent: Record Agent;
AgentTaskImpl: Codeunit "Agent Task Impl.";
begin
if not (AgentTaskImpl.TryGetAgentRecordFromTaskId(TaskId, Agent)) then
exit;

Context := InitializeAgentContext(Agent."Agent Metadata Provider", Agent."User Security ID");
Context.Add(AgentTaskIdTok, Format(TaskId));
end;

[Scope('OnPrem')]
procedure RequestFeedback(FeatureName: Text; Context: Dictionary of [Text, Text])
var
MicrosoftUserFeedback: Codeunit "Microsoft User Feedback";
EmptyContextFiles: Dictionary of [Text, Text];
FeedbackType: Text;
CopilotThumbsUpTok: Label 'Copilot.ThumbsUp', Locked = true;
CopilotThumbsDownTok: Label 'Copilot.ThumbsDown', Locked = true;
FeedbackTypeTok: Label 'Feedback.Type', Locked = true;
begin
MicrosoftUserFeedback.SetIsAIFeedback(true);

if Context.ContainsKey(FeedbackTypeTok) then
FeedbackType := Context.Get(FeedbackTypeTok);

case FeedbackType of
CopilotThumbsUpTok:
MicrosoftUserFeedback.RequestLikeFeedback(FeatureName, AgentFeatureAreaTok, AgentFeatureDisplayNameTok, EmptyContextFiles, Context);
CopilotThumbsDownTok:
MicrosoftUserFeedback.RequestDislikeFeedback(FeatureName, AgentFeatureAreaTok, AgentFeatureDisplayNameTok, EmptyContextFiles, Context);
else
MicrosoftUserFeedback.RequestFeedback(FeatureName, AgentFeatureAreaTok, AgentFeatureDisplayNameTok, EmptyContextFiles, Context);
end;
end;
}
6 changes: 6 additions & 0 deletions src/System Application/App/Agent/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@
"name": "Data Compression",
"publisher": "Microsoft",
"version": "27.4.0.0"
},
{
"id": "f7964d32-7685-400f-8297-4bc17d0aab0e",
"name": "Microsoft User Feedback",
"publisher": "Microsoft",
"version": "27.4.0.0"
}
],
"propagateDependencies": true,
Expand Down
Loading