wrapAISDK copies AI SDK v7 file bytes one key per byte instead of turning them into attachments

Aberta
#2,750 0 comentários 0 reações 1 responsável Ver no GitHub

Mantenedores costumam responder em até 1 dia

@AbhiPrasad já está trabalhando nisso.

Desde 6/11/2026.

  • #2751 de @pmartinsdev — fechado sem integrar
  • #2752 de @AbhiPrasad — aberto

Avaliação

Esta issue ainda não foi avaliada.

Descrição

typescript

What happens

With ai 7.0.145 and braintrust 3.32.0, file parts reach the doStream model span as { type: 'file', mediaType, data: { type: 'data', data: Uint8Array } }, the AI SDK 7 shape (SharedV4FileData). processContentPart passes part.data, the wrapper object, to convertDataToAttachment, which only handles a string, Uint8Array, Buffer or Blob, so no attachment is made. deepCopyEvent then runs JSON.stringify and JSON.parse on the raw Uint8Array, which becomes an object with one key per byte.

https://github.com/braintrustdata/braintrust-sdk-javascript/blob/braintrust%403.32.0/js/src/instrumentation/plugins/ai-sdk-plugin.ts#L1297-L1301

The same code is in 3.43.0 and on main as of e0b7107dc7.

Impact

1 MB of image bytes becomes 1,000,000 keys and about 120 MB of heap on every model call. We call Claude through Vertex, which takes no image URLs, so the AI SDK downloads every image in the conversation and each call carries all of them. A chat with 25 MB of images pushed the heap to about 3.1 GB, and our 4 GB serverless instances were killed for memory.

On a single 38-image call (24.5 MB of images), the heap peaked at 2,651 MB with wrapAISDK and at 117 MB without it, and deepCopyEvent alone allocated 5.4 GB.

Reproduction

processContentPart leaves this shape untouched, so the model span event is copied like this.

import { deepCopyEvent } from 'braintrust';

const copy = deepCopyEvent({
  input: [{ type: 'file', mediaType: 'image/png', data: { type: 'data', data: new Uint8Array(1_000_000) } }],
});
// copy.input[0].data.data is a plain object with 1,000,000 keys, about 11 MB of JSON

Workaround we use

A one-line change in processContentPart, applied with pnpm patch to every build in dist, fixes it for us.

       const fileAttachment = convertDataToAttachment(
-        part.data,
+        part.data.type === "data" ? part.data.data : part.data,
         part.mimeType || part.mediaType,
         part.name || part.filename
       );

With it, the same 38-image call peaked at 130 MB of heap with tracing on. A complete fix could also handle { type: 'url' } and the other SharedV4FileData variants in convertDataToAttachment.

Environment

  • braintrust 3.32.0, also seen at runtime on 3.42.0 and in the source of 3.43.0
  • ai 7.0.145 with @ai-sdk/google-vertex 5.0.117 (Anthropic on Vertex)
  • Node 22
Linguagem predominante
TypeScript
Estrelas
29
Forks
22
Merge médio
1d 25min
PRs com merge (30d)
80

Preparar o ambiente

  • Inclui um Dockerfile ou arquivo Docker Compose
  • Sem modelo de pull request
  • Sem guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de braintrustdata/braintrust-sdk-javascript

Todas as issues de braintrustdata/braintrust-sdk-javascript

Issues semelhantes

Mais issues de TypeScript

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.