Add FileUpload overload to Agent Task Message Builder#8687
Conversation
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>
…te/bkrupinszki/632807
| /// </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" |
There was a problem hiding this comment.
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 withIgnoredReason) that delegates to the internal impl with the appropriate flag, consistent with the API surface of the other overloads.
| 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 |
There was a problem hiding this comment.
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.
| 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), |
There was a problem hiding this comment.
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.
| 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) |
There was a problem hiding this comment.
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 stubFileUploadvalue (or use an integration-test approach that supplies a realFileUpload). 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.
| .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
Summary
Adds an
AddAttachment(File: FileUpload)overload to the Agent Task MessageBuilder SDK (codeunits 4316 / 4311). This lets callers add attachments
straight from a
fileuploadaction, which is what enables multi-fileattachment 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
What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)
Risk & compatibility