Repository navigation
Commit 561dee1
fix(ai-sdk): log AI SDK v7 inline file data as attachments (#2752)
build off of
#2751
fixes
#2750
> π€ **This text was AI-generated.**
## Problem
With AI SDK v7, file parts carry their bytes in a tagged wrapper
(`SharedV4FileData`):
```ts
{ type: "file", mediaType: "image/png", data: { type: "data", data: Uint8Array } }
```
The AI SDK plugin only turned bare bytes into attachments, so it copied
this wrapper into the span as is. `deepCopyEvent` then turned the
`Uint8Array` into an object with one key per byte. 1 MB of image became
about 120 MB of heap on every model call
(#2750).
The plugin fix in #2751 had only a unit test. No e2e scenario sent a v7
tagged file part, so the real `streamText` path was never tested.
## Solution
The plugin now converts the inner bytes to an attachment and keeps the
v7 wrapper around it. The logged span has the same shape as the v7 input
and matches how decision images are already logged:
```text
before: data: { type: "data", data: { "0": 137, "1": 80, ... } }
after: data: { type: "data", data: <braintrust_attachment image/png> }
```
The `ai-sdk-instrumentation` scenario gets a new
`ai-sdk-stream-image-file-operation`. It streams a real 32x32 red PNG to
OpenAI and checks that the top-level call span and the model call span
each log one PNG attachment and no raw bytes. v7 sends the tagged form;
v5 and v6 send plain bytes. The test fails without the fix.
Other changes in this commit:
- Remove the plugin unit test and two live-API image tests in
`ai-sdk.test.ts`, which the new e2e test covers. Delete their unused
`test-image.png` fixture.
- Replace `gpt-4.1-nano` (deprecated) and `gpt-4o-mini` with
`gpt-5.4-nano-2026-03-17`. AI SDK v3 stays on `gpt-4o-mini` because its
OpenAI provider sends `max_tokens`, which GPT-5 models reject.
- Send `providerOptions: { openai: { store: false } }` on multi-step
tool
calls for AI SDK v5+. This sends earlier tool calls in full instead of
by ID, so recording also works for OpenAI orgs with Zero Data Retention.
- Re-record all scenario cassettes and snapshots.
---------
Co-authored-by: Paulo Martins <paulo.martins@nectir.io>1 parent 43d5223 commit 561dee1
62 files changed
Lines changed: 57017 additions & 32447 deletions
File tree
- .changeset
- e2e/scenarios/ai-sdk-instrumentation
- __cassettes__
- ai-sdk-v5-latest.cassette.blobs
- ai-sdk-v5.cassette.blobs
- ai-sdk-v6-latest.cassette.blobs
- ai-sdk-v6.cassette.blobs
- ai-sdk-v7-latest.cassette.blobs
- ai-sdk-v7.cassette.blobs
- __snapshots__
- js/src
- instrumentation/plugins
- wrappers/ai-sdk
- fixtures
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments