Codeunit 4300 Agent Task Impl.

App
System Application
Namespace
System.Agents
Versions
25-28

Procedures, 41

Versions171819202122232425262728

Source2526272829

Source in 29

src/System Application/App/Agent/Interaction/Internal/AgentTaskImpl.Codeunit.al324 lines, Copyright (c) Microsoft Corporation. MIT

// ------------------------------------------------------------------------------------------------
// 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.Agents.TaskPane;
using System.Agents.Troubleshooting;
using System.Environment;
using System.Integration;

codeunit 4300 "Agent Task Impl."
{
    Access = Internal;
    InherentEntitlements = X;
    InherentPermissions = X;

    procedure GetStepsDoneCount(AgentTaskID: BigInteger): Integer
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.Get(AgentTaskID);
        exit(GetStepsDoneCount(AgentTask));
    end;

    procedure GetStepsDoneCount(var AgentTask: Record "Agent Task"): Integer
    var
        AgentTaskLogEntry: Record "Agent Task Log Entry";
    begin
        AgentTaskLogEntry.SetRange("Task ID", AgentTask."ID");
        AgentTaskLogEntry.ReadIsolation := IsolationLevel::ReadCommitted;
        exit(AgentTaskLogEntry.Count());
    end;

    procedure GetDetailsForAgentTaskLogEntry(var AgentTaskLogEntry: Record "Agent Task Log Entry"): Text
    var
        ContentInStream: InStream;
        ContentText: Text;
    begin
        AgentTaskLogEntry.CalcFields(Details);
        AgentTaskLogEntry.Details.CreateInStream(ContentInStream, GetDefaultEncoding());
        ContentInStream.Read(ContentText);
        exit(ContentText);
    end;

    procedure ShowTaskLogEntries(AgentTaskID: BigInteger)
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.Get(AgentTaskID);
        ShowTaskLogEntries(AgentTask);
    end;

    procedure ShowTaskLogEntries(var AgentTask: Record "Agent Task")
    var
        AgentTaskLogEntry: Record "Agent Task Log Entry";
    begin
        AgentTaskLogEntry.SetRange("Task ID", AgentTask.ID);
        Page.Run(Page::"Agent Task Log Entry List", AgentTaskLogEntry);
    end;

    procedure ShowTask(var AgentTask: Record "Agent Task")
    var
        TaskPane: Codeunit "Task Pane";
    begin
        // Route archived agents' tasks to the task log entries card, which keeps it reachable for auditing.
        if AgentTask."Agent Substate" = AgentTask."Agent Substate"::Archived then begin
            ShowTaskLogEntries(AgentTask);
            exit;
        end;

        TaskPane.ShowTask(AgentTask);
    end;

    procedure CreateTask(AgentUserSecurityID: Guid; TaskTitle: Text[150]; ExternalID: Text[2048]; BillingContext: Enum "Agent Task Billing Context"; ModelId: Code[30]; var NewAgentTask: Record "Agent Task")
    begin
        NewAgentTask."Agent User Security ID" := AgentUserSecurityID;
        NewAgentTask."Created By" := UserSecurityId();
        NewAgentTask.Title := TaskTitle;
        NewAgentTask."Needs Attention" := false;
        NewAgentTask.Status := NewAgentTask.Status::Paused;
        NewAgentTask."External ID" := ExternalID;
        NewAgentTask."Model ID" := ModelId;
        NewAgentTask."Billing Context" := BillingContext;
        NewAgentTask.Insert();
    end;

    procedure AddMessage(From: Text[250]; MessageText: Text; ExternalMessageId: Text[2048]; var CurrentAgentTask: Record "Agent Task"; RequiresReview: Boolean): Record "Agent Task Message"
    var
        AgentTaskMessage: Record "Agent Task Message";
        AgentMessageImpl: Codeunit "Agent Message Impl.";
    begin
        if MessageText = '' then
            Error(MessageTextMustBeProvidedErr);

        AgentTaskMessage."Task ID" := CurrentAgentTask.ID;
        AgentTaskMessage."Type" := AgentTaskMessage."Type"::Input;
        AgentTaskMessage."External ID" := ExternalMessageId;
        AgentTaskMessage.From := From;
        AgentTaskMessage."Requires Review" := RequiresReview;
        AgentTaskMessage.Insert();

        AgentMessageImpl.UpdateText(AgentTaskMessage, MessageText);
        exit(AgentTaskMessage);
    end;

    procedure StopTask(AgentTaskID: BigInteger; AgentTaskStatus: enum "Agent Task Status"; UserConfirm: Boolean)
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.ID := AgentTaskID;
        StopTask(AgentTask, AgentTaskStatus, UserConfirm);
    end;

    procedure StopTask(var AgentTask: Record "Agent Task"; AgentTaskStatus: enum "Agent Task Status"; UserConfirm: Boolean)
    var
        AgentTaskToModify: Record "Agent Task";
    begin
        AgentTaskToModify.Get(AgentTask.ID);
        if ((AgentTaskToModify.Status = AgentTaskStatus) and (AgentTaskToModify."Needs Attention" = false)) then
            exit; // Task is already stopped and does not need attention.

        if UserConfirm then
            if not Confirm(AreYouSureThatYouWantToStopTheTaskQst) then
                exit;

        AgentTaskToModify.Status := AgentTaskStatus;
        AgentTaskToModify."Needs Attention" := false;
        AgentTaskToModify.Modify(true);

        AgentTask.Status := AgentTaskToModify.Status;
        AgentTask."Needs Attention" := AgentTaskToModify."Needs Attention";
    end;

    procedure RestartTask(AgentTaskID: BigInteger; UserConfirm: Boolean)
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.ID := AgentTaskID;
        RestartTask(AgentTask, UserConfirm);
    end;

    procedure RestartTask(var AgentTask: Record "Agent Task"; UserConfirm: Boolean)
    var
        AgentTaskToModify: Record "Agent Task";
    begin
        if UserConfirm then
            if not Confirm(AreYouSureThatYouWantToRestartTheTaskQst) then
                exit;

        AgentTaskToModify.Get(AgentTask.ID);
        AgentTaskToModify."Needs Attention" := false;
        AgentTaskToModify.Status := AgentTaskToModify.Status::Ready;
        AgentTaskToModify.Modify(true);

        AgentTask."Needs Attention" := AgentTaskToModify."Needs Attention";
        AgentTask.Status := AgentTaskToModify.Status;
    end;

    procedure TaskExists(AgentUserSecurityID: Guid; ConversationId: Text): Boolean
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.SetRange("Agent User Security ID", AgentUserSecurityID);
        AgentTask.ReadIsolation(IsolationLevel::ReadCommitted);
        AgentTask.SetRange("External ID", ConversationId);
        exit(not AgentTask.IsEmpty());
    end;

    procedure GetDefaultEncoding(): TextEncoding
    begin
        exit(TextEncoding::UTF8);
    end;

    procedure SetTaskStatusToReadyIfPossible(AgentTaskID: BigInteger)
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.ID := AgentTaskID;
        SetTaskStatusToReadyIfPossible(AgentTask);
    end;

    procedure SetTaskStatusToReadyIfPossible(var AgentTask: Record "Agent Task")
    var
        AgentTaskToModify: Record "Agent Task";
    begin
        // Only change the status if the task is in a status where it can be started again.
        // If the task is running, we should not change the state, as platform will pickup a new message automatically.
        if CanAgentTaskBeSetToReady(AgentTask) then begin
            AgentTaskToModify.Get(AgentTask.ID);
            AgentTaskToModify.Status := AgentTaskToModify.Status::Ready;
            AgentTaskToModify.Modify(true);
            AgentTask.Status := AgentTaskToModify.Status;
        end;
    end;

    procedure CanAgentTaskBeSetToReady(AgentTaskID: BigInteger): Boolean
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.Get(AgentTaskID);
        exit(CanAgentTaskBeSetToReady(AgentTask));
    end;

    procedure CanAgentTaskBeSetToReady(var AgentTask: Record "Agent Task"): Boolean
    begin
        exit((AgentTask.Status = AgentTask.Status::Paused) or (AgentTask.Status = AgentTask.Status::Completed));
    end;

    procedure IsTaskRunning(AgentTaskID: BigInteger): Boolean
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.Get(AgentTaskID);
        exit(IsTaskRunning(AgentTask));
    end;

    procedure IsTaskRunning(var AgentTask: Record "Agent Task"): Boolean
    begin
        exit(AgentTask.Status = AgentTask.Status::Running);
    end;

    procedure IsTaskCompleted(AgentTaskID: BigInteger): Boolean
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.Get(AgentTaskID);
        exit(IsTaskCompleted(AgentTask));
    end;

    procedure IsTaskCompleted(var AgentTask: Record "Agent Task"): Boolean
    begin
        exit(AgentTask.Status = AgentTask.Status::Completed);
    end;

    procedure IsTaskStopped(AgentTaskID: BigInteger): Boolean
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.Get(AgentTaskID);
        exit(IsTaskStopped(AgentTask));
    end;

    procedure IsTaskStopped(var AgentTask: Record "Agent Task"): Boolean
    begin
        exit((AgentTask.Status = AgentTask.Status::"Stopped by User") or (AgentTask.Status = AgentTask.Status::"Stopped by System"));
    end;

    procedure ArchiveTask(AgentTaskID: BigInteger; UserConfirm: Boolean)
    var
        AgentTask: Record "Agent Task";
    begin
        AgentTask.Get(AgentTaskID);
        if AgentTask.Archived = true then
            exit; // Task is already archived.

        if UserConfirm then
            if not Confirm(AreYouSureThatYouWantToArchiveTheTaskQst) then
                exit;

        AgentTask.Archived := true;
        AgentTask.Modify(true);
    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;

    procedure GetModelId(TaskId: BigInteger): Code[30]
    var
        AgentTaskRecord: Record "Agent Task";
    begin
        AgentTaskRecord.Get(TaskId);
        exit(AgentTaskRecord."Model ID")
    end;

    procedure GetModelName(TaskId: BigInteger): Text[70]
    var
        AgentTaskRecord: Record "Agent Task";
    begin
        AgentTaskRecord.Get(TaskId);
        AgentTaskRecord.CalcFields("Model Name");
        exit(AgentTaskRecord."Model Name");
    end;

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"System Action Triggers", GetAgentTaskMessagePageId, '', true, true)]
    local procedure OnGetAgentTaskMessagePageId(var PageId: Integer)
    begin
        PageId := Page::"Agent Task Message Card";
    end;

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"System Action Triggers", GetPageSummary, '', true, true)]
    local procedure OnGetGetPageSummary(PageId: Integer; Bookmark: Text; var Summary: Text)
    var
        TempPageSummaryParameters: Record "Page Summary Parameters";
        PageSummaryProvider: Codeunit "Page Summary Provider";
    begin
        if PageId = 0 then begin
            Summary := '';
            exit;
        end;

        TempPageSummaryParameters."Page ID" := PageId;
#pragma warning disable AA0139
        TempPageSummaryParameters.Bookmark := Bookmark;
#pragma warning restore AA0139
        TempPageSummaryParameters."Include Binary Data" := false;
        Summary := PageSummaryProvider.GetPageSummary(TempPageSummaryParameters);
    end;

    var
        MessageTextMustBeProvidedErr: Label 'You must provide a message text.';
        AreYouSureThatYouWantToRestartTheTaskQst: Label 'Are you sure that you want to restart the task?';
        AreYouSureThatYouWantToStopTheTaskQst: Label 'Are you sure that you want to stop the task?';
        AreYouSureThatYouWantToArchiveTheTaskQst: Label 'Are you sure that you want to archive the task?';
}