Skip to content

Add FileUpload overload to Agent Task Message Builder#8687

Open
krupybalu wants to merge 4 commits into
mainfrom
private/bkrupinszki/632807
Open

Add FileUpload overload to Agent Task Message Builder#8687
krupybalu wants to merge 4 commits into
mainfrom
private/bkrupinszki/632807

Conversation

@krupybalu

@krupybalu krupybalu commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an AddAttachment(File: FileUpload) overload to the Agent Task Message
Builder SDK (codeunits 4316 / 4311). This lets callers add attachments
straight from a fileuploadaction, which is what enables multi-file
attachment upload in the Agent Designer (see the companion platform PR).

MIME type is derived from the file name; content is read with MS-DOS
encoding to keep binary attachments byte-safe (matches the Email SDK).

Testing

Added SDK unit tests covering the MIME-type derivation helper and chained
multi-attachment adds.

Work item: AB#632807

What & why

Linked work

Fixes #

How I validated this

  • I read the full diff and it contains only changes I intended.
  • I built the affected app(s) locally with no new analyzer warnings.
  • I ran the change in Business Central and confirmed it behaves as expected.
  • I added or updated tests for the new behavior, or explained below why none are needed.

What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)

Risk & compatibility

Balázs Krupinszki and others added 4 commits June 16, 2026 15:34
Adds AddAttachment(File: FileUpload) on codeunit 4316 (and matching impl
on 4311) so pages can use a fileuploadaction with multi-select to attach
several files in one browser dialog instead of calling UploadAttachment()
once per file.

The FileUpload stream is read with TextEncoding::MSDos so that binary
attachments (PDF, PNG, XLSX, ...) round-trip byte-for-byte, matching the
Email module's UploadAttachment(_, SingleFile: FileUpload) precedent. An
EncodeType-parameterized overload is also exposed for known text uploads.

The existing single-file UploadAttachment() (which wraps File.UploadIntoStream
and is the root cause of the Agent Designer attachments dialog only allowing
one file at a time) is left in place for compatibility.

Tests:
- ContentTypeFromFilenameForKnownExtensions, ContentTypeFromFilename-
  IsCaseInsensitive, ContentTypeFromFilenameForUnknownExtensionReturnsEmpty
  cover the MIME derivation the FileUpload overload uses.
- AddAttachmentChainedMultipleTimesAddsAllFiles covers the
  foreach-over-List-of-FileUpload chained-add path.

Refs 632807

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Option D refinement: keep only the single-arg AddAttachment(File: FileUpload)
overload (MS-DOS encoding inline). The EncodeType-parameterized overload had no
concrete consumer and was unrequested surface; attachments always want byte-safe
MS-DOS encoding, and callers needing a different encoding can use the existing
InStream overload.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@krupybalu krupybalu requested review from a team June 19, 2026 11:47
@github-actions github-actions Bot added this to the Version 29.0 milestone Jun 19, 2026
/// </remarks>
/// <param name="File">The file to attach, as supplied by a fileuploadaction trigger.</param>
/// <returns>This instance of the Agent Task Message Builder.</returns>
procedure AddAttachment(File: FileUpload): codeunit "Agent Task Message Builder"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

FileUpload overload cannot mark attachment as ignored

All other AddAttachment overloads expose an Ignored: Boolean parameter (and optionally IgnoredReason) so callers can flag attachments for non-processing. The new FileUpload overload unconditionally attaches the file as non-ignored, preventing callers that receive a FileUpload from a page trigger from ever marking it as ignored without first converting it to an InStream manually.

Recommendation:

  • Add a second AddAttachment(File: FileUpload; Ignored: Boolean) overload (and optionally one with IgnoredReason) that delegates to the internal impl with the appropriate flag, consistent with the API surface of the other overloads.
Suggested change
procedure AddAttachment(File: FileUpload): codeunit "Agent Task Message Builder"
procedure AddAttachment(File: FileUpload; Ignored: Boolean): codeunit "Agent Task Message Builder"
begin
FeatureAccessManagement.AgentManagementAllowed(true);
AgentTaskMsgBuilderImpl.AddAttachment(File, Ignored);
exit(this);
end;

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

// to support multi-file selection from the browser file picker. MS-DOS encoding keeps
// binary attachments (PDF, PNG, XLSX, ...) byte-safe, matching the Email SDK precedent.
FileName := File.FileName;
if FileName = '' then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

Silent discard of empty-filename FileUpload

When File.FileName is empty the method silently returns this with no log, trace, or error. In a fluent chain a caller cannot distinguish between a successful attach and a silently dropped file, making production issues (e.g. a FileUpload object that loses its name) invisible.

Recommendation:

  • Add a telemetry or session log entry before the early exit so that empty-name uploads appear in diagnostic traces. If an empty filename always indicates a programming error rather than a valid edge case, consider raising an error instead.
Suggested change
if FileName = '' then
FileName := File.FileName;
if FileName = '' then begin
Session.LogMessage('0000XXX', 'FileUpload AddAttachment skipped: empty file name.', Verbosity::Warning, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', 'Agent');
exit(this);
end;

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

exit(this);
File.CreateInStream(FileInStream, TextEncoding::MSDos);
AddAttachment(
CopyStr(FileName, 1, 250),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

Silent filename truncation loses trailing extension

CopyStr(FileName, 1, 250) silently truncates file names longer than 250 characters before storing them. If the extension falls beyond character 250 the stored name has no extension, which means GetContentTypeFromFilename would return an empty MIME type when that same name is later inspected, and MIME-type detection on the full name (line 192) diverges from what is actually stored.

Recommendation:

  • Either validate that the filename does not exceed 250 characters and surface an error to the caller, or at least ensure the extension is preserved after truncation. A simple guard would be to raise an error with a descriptive message when the filename is too long.
Suggested change
CopyStr(FileName, 1, 250),
if StrLen(FileName) > 250 then
Error('File name ''%1'' exceeds the maximum allowed length of 250 characters.', FileName);
AddAttachment(
CopyStr(FileName, 1, 250),
CopyStr(GetContentTypeFromFilename(FileName), 1, 100),
FileInStream);

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

AgentTaskMessageBuilder
.Initialize('Sender', 'Two files attached')
.SetAgentTask(AgentTaskRecord)
.AddAttachment('first.txt', 'text/plain', InStream1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

Test uses wrong overload for FileUpload scenario

The test AddAttachmentChainedMultipleTimesAddsAllFiles is described as verifying the behaviour of repeated calls "as a fileuploadaction trigger would issue, looping over List of [FileUpload]" but actually invokes the string-based InStream overload (AddAttachment('first.txt', 'text/plain', InStream1)). The new AddAttachment(File: FileUpload) overload introduced in this PR has zero unit-test coverage.

Recommendation:

  • Replace the two AddAttachment(name, mime, stream) calls with a mock or stub FileUpload value (or use an integration-test approach that supplies a real FileUpload). At a minimum, add a separate test that exercises the new overload end-to-end so that encoding, MIME-type derivation, and the silent-skip-on-empty-name branch are all covered.
Suggested change
.AddAttachment('first.txt', 'text/plain', InStream1)
// Replace lines 1427-1428 with calls that use the FileUpload overload,
// e.g. via a helper that populates a FileUpload from a TempBlob,
// or rename this test and add a separate test for FileUpload.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant