@@ -523,46 +523,31 @@ registry/direct-handler test. There is no HTTP fallback.
523523
524524### File Output Pattern (Downloads)
525525
526- For tools that return files, use ` FileToolProcessor ` to store files and return ` UserFile ` objects.
527-
528- #### In Tool transformResponse
529-
530- ``` typescript
531- import { FileToolProcessor } from ' @/executor/utils/file-tool-processor'
532-
533- transformResponse : async (response , context ) => {
534- const data = await response .json ()
535-
536- // Process file outputs to UserFile objects
537- const fileProcessor = new FileToolProcessor (context )
538- const file = await fileProcessor .processFileData ({
539- data: data .content , // base64 or buffer
540- mimeType: data .mimeType ,
541- filename: data .filename ,
542- })
543-
544- return {
545- success: true ,
546- output: { file },
547- }
548- }
549- ```
550-
551- #### In the operation handler (for complex file handling)
552-
553- ``` typescript
554- // Return file data that FileToolProcessor can handle. No API route is involved.
555- return Response .json ({
556- success: true ,
557- output: {
558- file: {
559- data: base64Content ,
560- mimeType: ' application/pdf' ,
561- filename: ' document.pdf' ,
562- },
563- },
564- })
565- ```
526+ Declare downloads as ` file ` / ` file[] ` outputs and return canonical ` UserFile ` objects.
527+ Internal operation responses are capped at 10 MiB ** before** ` transformResponse ` and
528+ ` FileToolProcessor ` run. Inline base64 expands the bytes by roughly one third, so it
529+ cannot carry a download near that limit. Persist downloads in the server operation
530+ ** before ` Response.json ` ** , not in a response transform.
531+
532+ Follow ` executeQuickBooksDownloadDocument ` or ` executeAgiloftRetrieveAttachment ` :
533+
534+ - Derive storage scope only from trusted ` request.context ` , never tool parameters.
535+ Use ` uploadExecutionFile ` for a complete workspace/workflow/execution scope;
536+ otherwise use ` uploadCopilotFile ` with the trusted user identity. Reject missing
537+ storage authority before downloading. Do not fabricate an ` ExecutionContext ` .
538+ - Keep provider authentication, DNS-pinned downloads, byte caps and cancellation.
539+ Normalize image metadata with ` resolveStoredFileMetadata ` before uploading.
540+ - Return the stored file unchanged through the response schema and transform; use
541+ ` userFileSchema ` / ` UserFile ` rather than rebuilding a base64-only shape.
542+ ` FileToolProcessor ` passes stored files through; the executor records them for
543+ execution consumers. Do not call its private ` processFileData ` method.
544+ - Surface storage failures instead of falling back to an oversized inline payload.
545+ Storage helpers do not promise rollback when later execution steps fail.
546+
547+ Test provider bytes larger than the inline JSON budget through the actual handler,
548+ bounded response reader, transform and file processor, mocking provider/storage
549+ boundaries only. Preserve explicit legacy base64 outputs when they are a separate
550+ versioned contract; do not silently convert those outputs or raise the global cap.
566551
567552### Key Helpers Reference
568553
0 commit comments