Skip to content

feat(server-utils): Add pi-ai integration - #25869

Closed
mydea wants to merge 13 commits into
developfrom
feat/pi-ai-integration
Closed

mydea wants to merge 13 commits into
developfrom
feat/pi-ai-integration

Conversation

@mydea

@mydea mydea commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Why: pi-ai had no instrumentation of its own: only Flue and pi-durable traced its requests, each with its own chat spans (turn observations and a models proxy). Instrumenting pi-ai itself covers direct users too, and lets both frameworks drop their chat-span code (~1.1k lines) so there is a single source of gen_ai.chat spans. The version range starts at 0.80 because Flue 2.0–2.2 depend on pi-ai 0.83–0.87; >=1 would have dropped their chat spans.

How to review: Start with integrations/pi-ai.ts and orchestrion/config/pi-ai.ts. complete* awaits stream*, and compat.stream hands some models to a Models of its own, so nested synchronous calls are deduped with a depth counter and only the outermost call gets a span. ai/pi-ai/chat.ts is the old pi-durable models.ts, moved. Flue now passes the conversation to the pi-ai span through the scope.

On Cloudflare, @sentry/cloudflare/vite now splices the @flue/runtime import into the Cloudflare SDK's baseSdk module instead of @sentry/server-utils's Flue integration. Every orchestrion-instrumented module imports @sentry/server-utils, so with pi-ai instrumented the old location closed an import cycle that ran Flue's module-level createModels() before pi-ai's ModelsImpl existed, and the worker failed at startup.

Unsure about:

  • Chat spans change origin from auto.ai.flue / auto.ai.pi_durable to auto.ai.pi_ai.
  • Flue's chat spans now require the runtime hook or bundler plugin; a manual-only instrument(createFlueInstrumentation()) keeps agent/tool spans but loses chat spans. Setups following our docs (--import on Node, the Vite plugin on Cloudflare, the Bun plugin) are unaffected, and Flue now warns once on its first model call when pi-ai was not instrumented. pi-durable is unaffected: it was only ever instrumented through the hook or plugin.
  • flue.turn.purpose (compaction vs. agent turn) is dropped, since pi-ai cannot see it. Could be carried through the scope if we want it.
  • The Flue / pi-durable e2e apps need an OpenRouter key, so their updated assertions were not run locally. The Cloudflare Flue worker was run locally with wrangler dev and a fake key: it starts, and records invoke_agent > chat (auto.ai.pi_ai) > the provider HTTP span.

Release note:

  • feat(server-utils): Add pi-ai integration

    The new piAiIntegration traces requests sent with pi-ai (@earendil-works/pi-ai >= 0.80) as gen_ai.chat spans, through createModels() or the standalone stream/complete functions. It is enabled by default and needs the Sentry runtime hook or bundler plugin.

    Once pi-ai has sent a request, the openai, @anthropic-ai/sdk, @google/genai and Workers AI integrations stop recording requests for the rest of the process, because pi-ai sends its requests through those clients. An app that also calls those SDKs directly no longer gets spans for those calls.

    Flue and pi-durable send their model calls through pi-ai, so their gen_ai.chat spans now come from this integration:

    • Their origin changes from auto.ai.flue / auto.ai.pi_durable to auto.ai.pi_ai. Agent and tool spans keep their origin.
    • Flue apps that only call instrument(Sentry.createFlueInstrumentation()) need the runtime hook (--import) or bundler plugin for gen_ai.chat spans. Without it, the SDK logs a warning on the first model call.
    • The flue.turn.purpose attribute is no longer set.
    • pi-durable records model calls only for a models object created with pi-ai's createModels().

🤖 Generated with Claude Code

via Francesco Gringl-Novy.

--

View Junior Session [Sentry]

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Compared: 8cc0b63 (PR test merge using develop at 2c5b8f8)

Against: 2c5b8f8 (develop) · base run #64128

✅ Baseline matches: this diff contains only this PR's changes.

Path Size % Change Change
@sentry/browser 30.43 kB - -
@sentry/browser - with treeshaking flags 28.53 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 28.44 kB - -
@sentry/browser (incl. Tracing) 52.69 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 52.7 kB - -
@sentry/browser (incl. Tracing, Profiling) 55.62 kB - -
@sentry/browser (incl. Tracing, Replay) 92.95 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 81.55 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 97.69 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 110.66 kB - -
@sentry/browser (incl. Feedback) 47.98 kB - -
@sentry/browser (incl. sendFeedback) 35.51 kB - -
@sentry/browser (incl. FeedbackAsync) 40.61 kB - -
@sentry/browser (incl. Metrics) 31.43 kB - -
@sentry/browser (incl. Logs) 31.71 kB - -
@sentry/browser (incl. Metrics & Logs) 32.39 kB - -
@sentry/react 32.22 kB - -
@sentry/react (incl. Tracing) 54.95 kB - -
@sentry/vue 38.71 kB - -
@sentry/vue (incl. Tracing) 55.57 kB - -
@sentry/svelte 30.45 kB - -
@sentry/remix (Remix 3 client bundle) 57.73 kB - -
CDN Bundle 32.15 kB - -
CDN Bundle (incl. Tracing) 53.19 kB - -
CDN Bundle (incl. Logs, Metrics) 34.37 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 55.12 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 75.81 kB - -
CDN Bundle (incl. Tracing, Replay) 91.35 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 93.31 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 97.46 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 99.48 kB - -
CDN Bundle - uncompressed 94.59 kB - -
CDN Bundle (incl. Tracing) - uncompressed 157.58 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 101.14 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 163.55 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 232.7 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 279.26 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 285.22 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 292.97 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 298.91 kB - -
@sentry/nextjs (client) 57.82 kB - -
@sentry/sveltekit (client) 53.14 kB - -
@sentry/core/server 44.34 kB - -
@sentry/core/browser 13.95 kB - -
@sentry/node 155.27 kB +0.1% +141 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 81.81 kB +0.19% +148 B 🔺
@sentry/node - without tracing 96.02 kB +0.17% +154 B 🔺
@sentry/node - without channel injection 135.88 kB +0.09% +115 B 🔺
@sentry/aws-serverless 104.2 kB +0.17% +168 B 🔺
@sentry/cloudflare (withSentry) - minified 198.04 kB - -
@sentry/cloudflare (withSentry) 491.9 kB - -
@sentry/nextjs/cloudflare (withSentry) - minified 218.62 kB - -

View base workflow run

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Optional E2E tests

Some optional checks were not successful. They do not block the merge. 1 not successful, 56 successful. See the run.

Check Status
❌ CI: Optional E2E Tests / E2E node-anthropic-send-to-sentry (latest) Test (optional) Failing after 3m Details
Successful checks
Check Status
✅ CI: Optional E2E Tests / E2E astro-7-static Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E supabase-nextjs Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E gen-ai-libraries (cloudflare) Test (optional) Successful in 29s Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react-sourcemaps Test (optional) Successful in 23s Details
✅ CI: Optional E2E Tests / E2E cloudflare-think Test (optional) Successful in 37s Details
✅ CI: Optional E2E Tests / E2E cloudflare-pi-durable (latest) Test (optional) Successful in 25s Details
✅ CI: Optional E2E Tests / E2E cloudflare-pi-durable Test (optional) Successful in 31s Details
✅ CI: Optional E2E Tests / E2E react-router-7-framework-instrumentation Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E cloudflare-flue-send-to-sentry Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-openai-send-to-sentry Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E cloudflare-mastra Test (optional) Successful in 29s Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (cloudflare, latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E debug-id-sourcemaps Test (optional) Successful in 37s Details
✅ CI: Optional E2E Tests / E2E solidstart-2 Test (optional) Successful in 38s Details
✅ CI: Optional E2E Tests / E2E vue-3 (no Options API) Test (optional) Successful in 53s Details
✅ CI: Optional E2E Tests / E2E cloudflare-agent Test (optional) Successful in 27s Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react (latest) Test (optional) Successful in 57s Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps (static / nuxt generate) Test (optional) Successful in 21s Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps Test (optional) Successful in 21s Details
✅ CI: Optional E2E Tests / E2E deno (latest) Test (optional) Successful in 44s Details
✅ CI: Optional E2E Tests / E2E cloudflare-think (ai v6) Test (optional) Successful in 35s Details
✅ CI: Optional E2E Tests / E2E astro-7 Test (optional) Successful in 57s Details
✅ CI: Optional E2E Tests / E2E react-send-to-sentry Test (optional) Successful in 3m Details
✅ CI: Optional E2E Tests / E2E nextjs-orpc Test (optional) Successful in 54s Details
✅ CI: Optional E2E Tests / E2E node-express-mcp-v2 Test (optional) Successful in 13s Details
✅ CI: Optional E2E Tests / E2E nextjs-16-tunnel (cloudflare) Test (optional) Successful in 38s Details
✅ CI: Optional E2E Tests / E2E node-express-send-to-sentry-static Test (optional) Successful in 42s Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react-cloudflare Test (optional) Successful in 26s Details
✅ CI: Optional E2E Tests / E2E nuxt-5 Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nextjs-15 (latest) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E node-eve Test (optional) Successful in 37s Details
✅ CI: Optional E2E Tests / E2E gen-ai-libraries Test (optional) Successful in 30s Details
✅ CI: Optional E2E Tests / E2E node-flue (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-express-mcp-v1 Test (optional) Successful in 14s Details
✅ CI: Optional E2E Tests / E2E nextjs-15 (turbo) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E node-eve (orchestrion) Test (optional) Successful in 36s Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (vinext) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (vinext, bun) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nestjs-12 (latest) Test (optional) Successful in 28s Details
✅ CI: Optional E2E Tests / E2E node-pi-durable (latest) Test (optional) Successful in 22s Details
✅ CI: Optional E2E Tests / E2E node-mastra (latest) Test (optional) Successful in 41s Details
✅ CI: Optional E2E Tests / E2E nextjs-14 (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-eve (latest) Test (optional) Successful in 47s Details
✅ CI: Optional E2E Tests / E2E node-fastify-6 (tracer provider) Test (optional) Successful in 19s Details
✅ CI: Optional E2E Tests / E2E node-express-send-to-sentry Test (optional) Successful in 46s Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (deno) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E node-openai-decisions Test (optional) Successful in 17s Details
✅ CI: Optional E2E Tests / E2E node-openai-decisions (latest) Test (optional) Successful in 16s Details
✅ CI: Optional E2E Tests / E2E node-pi-durable Test (optional) Successful in 25s Details
✅ CI: Optional E2E Tests / E2E node-mastra Test (optional) Successful in 49s Details
✅ CI: Optional E2E Tests / E2E node-openai-send-to-sentry (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-flue Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-fastify-6 Test (optional) Successful in 21s Details
✅ CI: Optional E2E Tests / E2E cloudflare-workers-send-to-sentry Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps (client source maps kept) Test (optional) Successful in 22s Details
✅ CI: Optional E2E Tests / E2E node-anthropic-send-to-sentry Test (optional) Successful in 1m Details

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread pnpm-lock.yaml
jsdom-worker:
specifier: ^0.3.0
version: 0.3.0(node-fetch@2.7.0(encoding@0.1.13))
version: 0.3.0(node-fetch@3.3.2)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Lockfile pins jsdom-worker to node-fetch 3

Medium Severity

Adding @earendil-works/pi-ai pulled node-fetch@3 into the workspace, and pnpm now satisfies jsdom-worker's node-fetch: * peer with that ESM-only release instead of node-fetch@2. jsdom-worker loads the peer with require(), which fails on v3, so @sentry/replay unit tests that import it are likely to break.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 94cc573. Configure here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

this seems fine, as long as tests pass this should be ok.

Comment on lines +65 to +73
...(model.provider ? { [GEN_AI_PROVIDER_NAME]: model.provider } : {}),
...(model.id ? { [GEN_AI_REQUEST_MODEL]: model.id } : {}),
...(conversationId ? { [GEN_AI_CONVERSATION_ID]: conversationId } : {}),
...getServerAttributes(model),
...(streaming ? { [GEN_AI_RESPONSE_STREAMING]: true } : {}),
...(callOptions?.temperature !== undefined ? { [GEN_AI_REQUEST_TEMPERATURE]: callOptions.temperature } : {}),
...(callOptions?.maxTokens !== undefined ? { [GEN_AI_REQUEST_MAX_TOKENS]: callOptions.maxTokens } : {}),
...(callOptions?.reasoning ? { [GEN_AI_REQUEST_REASONING_LEVEL]: callOptions.reasoning } : {}),
...(recordInputs && context ? getRequestContentAttributes(context) : {}),

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

all of this seems redundant, we can just define undefined values without spreading everywhere, this has the same effect.

}

/**
* Diagnostics-channel-based integration for pi-ai (`@earendil-works/pi-ai` >= 0.80.0 < 2, whose API

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

the comment is too implementation specific, it should explain what it does for a consumer of the integration.

@sentry-junior sentry-junior Bot left a comment

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.

The core approach holds up. I checked pi-ai 0.80.1, 0.85.1 and 1.4.0: complete* and fetchDeferred call their stream* counterpart synchronously before the first await, and compat hands off to compatModels.stream synchronously too. So the depth counter does dedupe the nested calls, and node-flue and the pi-durable e2e apps pass in CI. A few things before this lands:

  • Cloudflare + Flue workers fail at startup. cloudflare-flue-send-to-sentry fails at deploy validation with Uncaught ReferenceError: Cannot access 'ModelsImpl' before initialization ... in createModels (job). It's the same error on all three runs of this branch, and it isn't caused by the missing OpenRouter key. My guess, which I haven't verified locally: this is an import cycle that pi-ai's new transform creates. The snippet injected into dist/models.js/dist/compat.js imports @sentry/server-utils. That package's flue integration module has the @flue/runtime import added by the Vite provided-module plugin. @flue/runtime then reaches createModels() at module top level (via pi-ai's compat), while models.js is still waiting on its own imports. cloudflare-pi-durable, which has no provided-module import, passes, which fits. Please break the cycle at the snippet/plugin layer rather than with a lazy import, and keep this e2e as the regression check.
  • CI. Check lockfile fails on 94cc5731 ("Run pnpm dedupe to apply the changes above"), and the branch now conflicts with develop, so the head commit 5939453f has no Build & Test run.
  • Release note. skipPiAiProviderIntegrations() now runs on the first request through any pi-ai app, not just Flue/pi-durable ones. An app that calls pi-ai directly and also uses openai/@anthropic-ai/sdk/@google/genai itself loses those integrations' spans for the whole process. The JSDoc covers this, but it should also go in the release note next to the origin change.

mydea and others added 8 commits October 29, 2026 13:57
Traces every `@earendil-works/pi-ai` request as a `gen_ai.chat` span, from
the `Models` methods and the standalone `compat` functions. Flue and
pi-durable send their model calls through pi-ai, so they no longer open
chat spans of their own and rely on this integration instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`compat` loads pi-ai's model catalog with a JSON import, and Deno 2.8 drops
import attributes once a module hook is registered, compiling the JSON as
JavaScript. The `Models` test still runs on Deno.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…i suites

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Flue's model calls are now traced by the pi-ai integration, which needs the
module hook or bundler plugin, while `instrument()` does not. Without them a
Flue app silently lost its `gen_ai.chat` spans; it now gets a warning on its
first model call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The deferred calls pass a handle where the others pass the request, which
the request mapping already reads as empty, so they share the `stream` and
`complete` channels. Also drops comments and fields that still described the
removed Flue turn spans, test cases already covered by the pi-ai helper
tests, and corrects the engines comments of the pi suites: pnpm installs
packages whose `engines` exclude the running Node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mydea
mydea force-pushed the feat/pi-ai-integration branch from 5939453 to ec04022 Compare October 29, 2026 12:59

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ec04022. Configure here.

sentry-junior Bot and others added 5 commits October 29, 2026 13:11
…ead of `@sentry/server-utils`

Every orchestrion-instrumented module imports `@sentry/server-utils`, so the
`@flue/runtime` import spliced into its Flue integration closed a cycle through
pi-ai, now that pi-ai is instrumented: an entry that loads pi-ai first ran
Flue's module-level `createModels()` before pi-ai's `ModelsImpl` was
initialized, and the worker failed at startup.

Co-Authored-By: Francesco Gringl-Novy <francesco.novy@sentry.io>
Sets the optional span attributes directly, as span attributes drop
`undefined` values, and describes `piAiIntegration` for its users.

Co-Authored-By: Francesco Gringl-Novy <francesco.novy@sentry.io>
Co-Authored-By: Francesco Gringl-Novy <francesco.novy@sentry.io>
valibot 1.1.0 is affected by GHSA-vqpr-j7v3-hqw9, which fails dependency review.

Co-Authored-By: Francesco Gringl-Novy <francesco.novy@sentry.io>
…tions

Co-Authored-By: Francesco Gringl-Novy <francesco.novy@sentry.io>
dcramer added a commit to getsentry/junior that referenced this pull request Oct 29, 2026
Upgrade `@sentry/node` and `@sentry/nitro` to 11.10.0. Library
instrumentation now uses build-time orchestrion instead of a runtime
`--import` hook.

Closes #2334

## Build-time instrumentation

- `juniorNitro()` adds the orchestrion Rollup plugin from
`@sentry/server-utils/orchestrion/rollup`. Every Junior app gets library
spans with no config change. `@sentry/nitro` adds only source maps and
the Nitro request channel.
- Remove `instrument.mjs`, `cross-env`, and `NODE_OPTIONS=--import` from
`apps/example` and the `junior init` scaffold. `server.ts` already calls
`initSentry()` first.
- Remove the `import-in-the-middle` bundling workaround. v11 does not
use it.
- `nitro dev` does not bundle `node_modules`, so dev gets no library
spans. Under v11 the old `--import` did not give them either.

## SDK options

- `sendDefaultPii` → `dataCollection`. Collect only incoming request
bodies, because outgoing calls carry prompts that the payload filter
does not see. Set `databaseQueryData: false`.
- Remove `traceLifecycle`, `registerEsmLoaderHooks`, `streamGenAiSpans`,
`enableLogs`, `withStreamedSpan`, and the transaction scrubber.
`SENTRY_ENABLE_LOGS=false` still drops logs.
- Filter the AI provider integrations (Anthropic, OpenAI, Google,
Mistral, Groq, Together, Vercel AI). pi-ai parses provider streams
itself, so their spans duplicate Junior's `gen_ai` spans without usage
or cost. Remove the filter after getsentry/sentry-javascript#25869.
- The web search `generateText` call had no manual span and relied on
the Vercel AI integration. It now has its own `gen_ai.chat` span with
usage.
- Remove `@opentelemetry/api` and `@opentelemetry/core` from Junior, the
example app, and the scaffold. Nothing imports them, and v11 does not
need them as peers. Remove the `@sentry/cli` build allowance, because
v11 no longer installs it.

## Manual instrumentation

- Delete `db/tracing.ts`. Sentry's `pg` and Neon spans replace it. Query
text is the same and neither records parameter values. The automatic
spans add connect spans but lose the PostgreSQL error code,
`db.operation.name`, `db.collection.name`, and `app.db.driver`.
- Remove the `http.server.request` webhook span and the `GET
files.slack.com` span. Sentry's `http.server` and fetch spans replace
them.
- Automatic fetch spans and breadcrumbs record the request URL. The
payload filter now keeps only the `https://files.slack.com` host for
private Slack file URLs, because the path names the workspace and file.
It also drops `url.fragment`, like `url.query`.
- `withSpan` keeps an `error.type` that the callback set. Before, it
replaced values such as `rate_limited` with the error name. Remove
`setSpanStatus("error")` calls before a `throw`, because Sentry sets the
error status.

## Verification

- `pnpm typecheck`, `pnpm lint`, `pnpm release:check`, and `pnpm test`
pass.
- The example Vercel build passes `check-vercel-output.mjs`.
- With `SENTRY_DEBUG=1`, a `node_server` build of the example logs
`Bundler plugin ran, injected libraries=[@anthropic-ai/sdk, h3, openai,
@google/genai, @mistralai/mistralai, @neondatabase/serverless,
@redis/client, hono, ai, pg, pg-pool]`, and spans reach the DSN.
- Not checked: a Vercel preview deploy against a real Sentry project.

## Review notes

- 11.10.0 is younger than `minimumReleaseAge`, so its seven packages are
in `minimumReleaseAgeExclude` with exact versions. Remove them later.

## Follow up work

* Once getsentry/sentry-javascript#25869 ships,
update the SDKs and remove the manual ai spans

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: David Cramer <david@sentry.io>
@mydea

mydea commented Oct 30, 2026

Copy link
Copy Markdown
Member Author

This got a bit complex, I'll split this into some smaller PRs...

@mydea mydea closed this Oct 30, 2026
mydea added a commit that referenced this pull request Oct 30, 2026
…dependencies (#25933)

**Why:** The Flue and pi-durable suites installed their packages through
`additionalDependencies`: an unlocked `npm install` into a fresh tmp dir
for every `createEsmAndCjsTests` call. That is 3 installs for Flue and 9
for pi-durable, per run and Node version. Measured locally for Flue:
~16s cold / ~3s warm and 210 MB each time. The unpinned `^` ranges also
let upstream releases reach CI without review. As root devDependencies
they are installed once and pinned by the lockfile. They were kept out
because their `engines.node >= 22.19` broke `yarn install` on Node 20.
Under pnpm, without `engine-strict`, that is only a warning. Both suites
still skip below Node 22.

Additionally, we used to use `createEsmAndCjsTests` and then skip for
the cjs case. Instead, we can just use `createEsmTests` here.

This prepares the split of the pi-ai integration (#25869).

**How to review:** Best viewed with whitespace hidden. Dropping the
trailing options argument made the formatter re-indent both suites, and
switching to `createEsmTests` removed the hand-written CJS skips. No
assertions change. The `allowBuilds` entries are for `@google/genai` and
`protobufjs`, which the pi packages pull in.

**Unsure about:** `pnpm dedupe` (enforced in CI) moves the root
`@google/genai` from 1.20.0 to 1.52.0 and bumps some
`@aws-sdk`/`@smithy` packages, since pi-ai depends on newer versions.
The google-genai and aws-serverless suites pass locally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant