diff --git a/dev-packages/bun-integration-tests/node-suites/excludes.ts b/dev-packages/bun-integration-tests/node-suites/excludes.ts index c2b32342e3f0..e43e5cc23347 100644 --- a/dev-packages/bun-integration-tests/node-suites/excludes.ts +++ b/dev-packages/bun-integration-tests/node-suites/excludes.ts @@ -92,6 +92,7 @@ export const NO_AUTO_INSTRUMENTATION = [ 'suites/tracing/mastra/test.ts', 'suites/tracing/mcp-handler-exact-once/test.ts', 'suites/tracing/mcp-server/**', + 'suites/tracing/mistral-v2/test.ts', 'suites/tracing/mistral/test.ts', 'suites/tracing/mongodb-v4/test.ts', 'suites/tracing/mongodb-v5/test.ts', @@ -210,6 +211,10 @@ const BUN_BUILD_EAGER_SUBSCRIPTION = ['suites/tracing/orchestrion-lazy-registrat // `http.server.request.start`. const BUN_BUILD_NO_HTTP_SERVER_INTEGRATION = ['suites/express/multiple-init/test.ts']; +// `@mistralai/mistralai` v3 statically imports its optional peer `@livekit/rtc-node`, so Bun cannot +// bundle the scenarios. `mistral-v2` still covers Mistral here. +const BUN_BUILD_UNBUNDLEABLE_DEPENDENCY = ['suites/tracing/mistral/test.ts']; + // Some or all tests fail with the bundled scenarios. The cause is not investigated yet. In // `express/tracing` only the request data tests fail: they set `httpIntegration` options, and with // `@sentry/bun` the request body comes from `bunHttpServerIntegration`. @@ -247,5 +252,6 @@ export const BUN_BUILD_EXCLUDE = [ '**/node_modules/**', ...BUN_BUILD_EAGER_SUBSCRIPTION, ...BUN_BUILD_NO_HTTP_SERVER_INTEGRATION, + ...BUN_BUILD_UNBUNDLEABLE_DEPENDENCY, ...BUN_BUILD_NOT_TRIAGED, ]; diff --git a/dev-packages/deno-integration-tests/node-suites/excludes.ts b/dev-packages/deno-integration-tests/node-suites/excludes.ts index b93a8ff63a65..bed8f796a588 100644 --- a/dev-packages/deno-integration-tests/node-suites/excludes.ts +++ b/dev-packages/deno-integration-tests/node-suites/excludes.ts @@ -62,6 +62,7 @@ const NOT_TRIAGED = [ 'suites/tracing/koa/test.ts', 'suites/tracing/langchain/test.ts', 'suites/tracing/langgraph/test.ts', + 'suites/tracing/mistral-v2/test.ts', 'suites/tracing/mistral/test.ts', 'suites/tracing/mongodb/test.ts', 'suites/tracing/mongoose-v5/test.ts', diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json index 33358dd59fc2..d10a8c09c085 100644 --- a/dev-packages/node-integration-tests/package.json +++ b/dev-packages/node-integration-tests/package.json @@ -44,7 +44,7 @@ "@langchain/core": "^0.3.80", "@langchain/langgraph": "^0.2.32", "@langchain/openai": "^0.5.0", - "@mistralai/mistralai": "2.6.4", + "@mistralai/mistralai": "3.3.0", "@modelcontextprotocol/client": "^2.0.0", "@modelcontextprotocol/server": "^2.0.0", "@nestjs/common": "^11", diff --git a/dev-packages/node-integration-tests/suites/tracing/mistral-v2/test.ts b/dev-packages/node-integration-tests/suites/tracing/mistral-v2/test.ts new file mode 100644 index 000000000000..5cd698bda1a2 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/mistral-v2/test.ts @@ -0,0 +1,75 @@ +import { + GEN_AI_OPERATION_NAME, + GEN_AI_RESPONSE_ID, + GEN_AI_RESPONSE_STREAMING, + GEN_AI_USAGE_TOTAL_TOKENS, + SENTRY_ORIGIN, +} from '@sentry/conventions/attributes'; +import { afterAll, describe, expect } from 'vitest'; +import { cleanupChildProcesses, createEsmTests } from '../../../utils/runner'; + +const ORIGIN = 'auto.ai.mistralai'; +const MISTRAL_V2 = { additionalDependencies: { '@mistralai/mistralai': '2.6.4' } }; + +// The `mistral` suite runs on the latest major; this keeps the still-supported v2 covered. The +// scenarios are shared, since the request and response shapes we read are the same across majors. +describe('Mistral integration (v2)', () => { + afterAll(() => { + cleanupChildProcesses(); + }); + + createEsmTests( + __dirname, + '../mistral/scenario-chat.mjs', + '../mistral/instrument.mjs', + (createRunner, test) => { + test('creates chat and streamed chat spans on @mistralai/mistralai v2', async () => { + await createRunner() + .expect({ + span: container => { + const chatSpan = container.items.find( + s => s.attributes[GEN_AI_RESPONSE_ID]?.value === 'chatcmpl-mock123', + ); + expect(chatSpan).toBeDefined(); + expect(chatSpan!.attributes[GEN_AI_OPERATION_NAME]?.value).toBe('chat'); + expect(chatSpan!.attributes[SENTRY_ORIGIN]?.value).toBe(ORIGIN); + expect(chatSpan!.attributes[GEN_AI_USAGE_TOTAL_TOKENS]?.value).toBe(25); + + const streamSpan = container.items.find( + s => s.attributes[GEN_AI_RESPONSE_ID]?.value === 'chatcmpl-stream-123', + ); + expect(streamSpan).toBeDefined(); + expect(streamSpan!.attributes[GEN_AI_RESPONSE_STREAMING]?.value).toBe(true); + expect(streamSpan!.attributes[GEN_AI_USAGE_TOTAL_TOKENS]?.value).toBe(30); + }, + }) + .start() + .completed(); + }); + }, + MISTRAL_V2, + ); + + createEsmTests( + __dirname, + '../mistral/scenario-embeddings.mjs', + '../mistral/instrument.mjs', + (createRunner, test) => { + test('creates embeddings spans on @mistralai/mistralai v2', async () => { + await createRunner() + .expect({ + span: container => { + const embeddingsSpan = container.items.find( + s => s.attributes[GEN_AI_OPERATION_NAME]?.value === 'embeddings', + ); + expect(embeddingsSpan).toBeDefined(); + expect(embeddingsSpan!.attributes[SENTRY_ORIGIN]?.value).toBe(ORIGIN); + }, + }) + .start() + .completed(); + }); + }, + MISTRAL_V2, + ); +}); diff --git a/dev-packages/node-integration-tests/suites/tracing/mistral/test.ts b/dev-packages/node-integration-tests/suites/tracing/mistral/test.ts index 1b1e91310beb..8b5373b22921 100644 --- a/dev-packages/node-integration-tests/suites/tracing/mistral/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/mistral/test.ts @@ -30,7 +30,7 @@ const ORIGIN = 'auto.ai.mistralai'; // Not exported from `@sentry/conventions` yet; the SDK defines it in `ai/core/gen-ai-attributes`. const GEN_AI_REQUEST_STREAM = 'gen_ai.request.stream'; -// ESM-only: `@mistralai/mistralai` v2 ships no CJS build, so CJS consumers load it via `require(esm)`, +// ESM-only: `@mistralai/mistralai` v2+ ships no CJS build, so CJS consumers load it via `require(esm)`, // whose auto-instrumentation is inconsistent across Node versions. The SDK's native mode is ESM, so we // only run the suite there. describe('Mistral integration', () => { diff --git a/packages/server-utils/src/orchestrion/config/mistral.ts b/packages/server-utils/src/orchestrion/config/mistral.ts index 01dd2b7320ff..aefaafb01c1d 100644 --- a/packages/server-utils/src/orchestrion/config/mistral.ts +++ b/packages/server-utils/src/orchestrion/config/mistral.ts @@ -2,10 +2,10 @@ import type { InstrumentationConfig } from '../apmTypes'; import { getModuleNames } from './module-names'; -// `@mistralai/mistralai` v2 is ESM-only, so there is a single built file per resource (no dual CJS/ESM +// `@mistralai/mistralai` v2+ is ESM-only, so there is a single built file per resource (no dual CJS/ESM // variants). Each SDK resource class exposes async methods that return a thenable, so `kind: 'Auto'` // resolves to `wrapPromise`; the `.stream` methods resolve to an async-iterable `EventStream`. -const MODULE = { name: '@mistralai/mistralai', versionRange: '>=2.0.0 <3' } as const; +const MODULE = { name: '@mistralai/mistralai', versionRange: '>=2.0.0 <4' } as const; const CHAT_FILE = { ...MODULE, filePath: 'esm/sdk/chat.js' } as const; const AGENTS_FILE = { ...MODULE, filePath: 'esm/sdk/agents.js' } as const; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1fb1417361a2..e9b9231b6d54 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -453,7 +453,7 @@ importers: version: 0.133.0(zod@4.6.7) '@google/genai': specifier: ^1.20.0 - version: 1.20.0(encoding@0.1.13)(supports-color@10.0.0) + version: 1.20.0(@modelcontextprotocol/sdk@1.32.2(@cfworker/json-schema@4.1.1)(supports-color@10.0.0)(zod@4.6.7))(encoding@0.1.13)(supports-color@10.0.0) '@langchain/core': specifier: ^1.2.17 version: 1.2.17(@opentelemetry/api@1.10.0)(openai@5.18.1(ws@8.21.3)(zod@4.6.7))(ws@8.21.3) @@ -606,7 +606,7 @@ importers: version: 3.1068.0 '@google/genai': specifier: ^1.20.0 - version: 1.20.0(encoding@0.1.13)(supports-color@10.0.0) + version: 1.20.0(@modelcontextprotocol/sdk@1.32.2(@cfworker/json-schema@4.1.1)(supports-color@10.0.0)(zod@4.6.7))(encoding@0.1.13)(supports-color@10.0.0) '@growthbook/growthbook': specifier: ^1.6.5 version: 1.6.5 @@ -632,8 +632,8 @@ importers: specifier: ^0.5.0 version: 0.5.18(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@5.18.1(ws@8.21.3)(zod@4.6.7)))(ws@8.21.3) '@mistralai/mistralai': - specifier: 2.6.4 - version: 2.6.4(@opentelemetry/api@1.9.0) + specifier: 3.3.0 + version: 3.3.0(@aws-sdk/client-s3@3.1068.0)(@azure/storage-blob@12.31.0(supports-color@10.0.0))(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.0)(supports-color@10.0.0) '@modelcontextprotocol/client': specifier: ^2.0.0 version: 2.0.0 @@ -6083,14 +6083,36 @@ packages: engines: {node: '>=18'} hasBin: true - '@mistralai/mistralai@2.6.4': - resolution: {integrity: sha512-PPt4GyJqs2hEsWrYCJZK5f0ORmT+L2MSm75LVGD7kBLf6ZKsoDpld/FRBQXr8xG6iFCBOFJFYzvGYhUb+UCkbw==} + '@mistralai/mistralai@3.3.0': + resolution: {integrity: sha512-b5NSkQ8lFBxwZfA4Vj5oHxs7Jw7VrZRI2E9g95sigQiTi3NsQ//o6y3nDXjKUPWjksfagjH3STEFCYBg19SMvg==} peerDependencies: + '@aws-sdk/client-s3': ^3.300.0 + '@azure/identity': ^4.0.0 + '@azure/storage-blob': ^12.24.0 + '@google-cloud/storage': ^7.0.0 || ^8.0.0 + '@hpcc-js/wasm-zstd': ^1.16.0 + '@livekit/rtc-node': ^0.13.28 + '@msgpack/msgpack': ^3.0.0 '@opentelemetry/api': ^1.9.0 '@opentelemetry/exporter-trace-otlp-http': ^0.220.0 '@opentelemetry/resources': ^2.9.0 '@opentelemetry/sdk-trace-base': ^2.9.0 + livekit-client: ^2.19.0 peerDependenciesMeta: + '@aws-sdk/client-s3': + optional: true + '@azure/identity': + optional: true + '@azure/storage-blob': + optional: true + '@google-cloud/storage': + optional: true + '@hpcc-js/wasm-zstd': + optional: true + '@livekit/rtc-node': + optional: true + '@msgpack/msgpack': + optional: true '@opentelemetry/api': optional: true '@opentelemetry/exporter-trace-otlp-http': @@ -6099,6 +6121,8 @@ packages: optional: true '@opentelemetry/sdk-trace-base': optional: true + livekit-client: + optional: true '@mjackson/node-fetch-server@0.2.0': resolution: {integrity: sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==} @@ -6111,6 +6135,16 @@ packages: resolution: {integrity: sha512-pJCEwGG7Lfr/+PQp9ZTwKXNeO5wzbfKL7H3MYpCorM4oFBoQrdjnBgEoqG+RjhsvS1FKrDbKux+M1HhlnGWqcA==} engines: {node: '>=20'} + '@modelcontextprotocol/sdk@1.32.2': + resolution: {integrity: sha512-SWsVtH/0vULSQStoZ6xxH2K09Li8fXYTMC64ZeogCdpZ3XSi1eCPOByV1OpuJxuI3OcmHhosDWYyii07tpPsLw==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + '@modelcontextprotocol/server@2.0.0': resolution: {integrity: sha512-YhHWdHfpFMQfd0prsEnxKeS3Qz3ytIGmsS0sth4KDjnacIT7hxk6hXHkJ9KysxlkvTM+WZAtQbbcUhdoP4Hvtw==} engines: {node: '>=20'} @@ -12164,6 +12198,12 @@ packages: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} + express-rate-limit@8.7.1: + resolution: {integrity: sha512-2FXbqkygil3mZiXzEtM0IjE/UBmBNot0J1GEVrJT4JbrvwOSoEtqtO+wHbiMQELWe1eNvHoYRg2dkjOid+6JkA==} + engines: {node: '>= 16'} + peerDependencies: + express: '>= 4.11' + express@4.22.1: resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} engines: {node: '>= 0.10.0'} @@ -13658,6 +13698,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} @@ -23424,10 +23467,12 @@ snapshots: '@google-cloud/promisify@2.0.3': {} - '@google/genai@1.20.0(encoding@0.1.13)(supports-color@10.0.0)': + '@google/genai@1.20.0(@modelcontextprotocol/sdk@1.32.2(@cfworker/json-schema@4.1.1)(supports-color@10.0.0)(zod@4.6.7))(encoding@0.1.13)(supports-color@10.0.0)': dependencies: google-auth-library: 9.15.1(encoding@0.1.13)(supports-color@10.0.0) ws: 8.21.3 + optionalDependencies: + '@modelcontextprotocol/sdk': 1.32.2(@cfworker/json-schema@4.1.1)(supports-color@10.0.0)(zod@4.6.7) transitivePeerDependencies: - bufferutil - encoding @@ -24179,16 +24224,21 @@ snapshots: - encoding - supports-color - '@mistralai/mistralai@2.6.4(@opentelemetry/api@1.9.0)': + '@mistralai/mistralai@3.3.0(@aws-sdk/client-s3@3.1068.0)(@azure/storage-blob@12.31.0(supports-color@10.0.0))(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.0)(supports-color@10.0.0)': dependencies: + '@modelcontextprotocol/sdk': 1.32.2(@cfworker/json-schema@4.1.1)(supports-color@10.0.0)(zod@4.6.7) '@opentelemetry/semantic-conventions': 1.43.0 ws: 8.21.3 zod: 4.6.7 zod-to-json-schema: 3.25.2(zod@4.6.7) optionalDependencies: + '@aws-sdk/client-s3': 3.1068.0 + '@azure/storage-blob': 12.31.0(supports-color@10.0.0) '@opentelemetry/api': 1.9.0 transitivePeerDependencies: + - '@cfworker/json-schema' - bufferutil + - supports-color - utf-8-validate '@mjackson/node-fetch-server@0.2.0': {} @@ -24207,6 +24257,30 @@ snapshots: dependencies: zod: 4.6.7 + '@modelcontextprotocol/sdk@1.32.2(@cfworker/json-schema@4.1.1)(supports-color@10.0.0)(zod@4.6.7)': + dependencies: + '@hono/node-server': 2.0.10(hono@4.13.11) + ajv: 8.20.0 + ajv-formats: 3.0.1 + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.1 + express: 5.2.1(supports-color@10.0.0) + express-rate-limit: 8.7.1(express@5.2.1(supports-color@10.0.0))(supports-color@10.0.0) + hono: 4.13.11 + jose: 6.2.10 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 4.6.7 + zod-to-json-schema: 3.25.2(zod@4.6.7) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 + transitivePeerDependencies: + - supports-color + '@modelcontextprotocol/server@2.0.0': dependencies: '@modelcontextprotocol/core': 2.0.0 @@ -31108,6 +31182,14 @@ snapshots: expect-type@1.4.0: {} + express-rate-limit@8.7.1(express@5.2.1(supports-color@10.0.0))(supports-color@10.0.0): + dependencies: + debug: 4.4.3(supports-color@10.0.0) + express: 5.2.1(supports-color@10.0.0) + ip-address: 10.7.2 + transitivePeerDependencies: + - supports-color + express@4.22.1(supports-color@10.0.0): dependencies: accepts: 1.3.8 @@ -33078,6 +33160,8 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema-typed@8.0.2: {} + json-schema@0.4.0: {} json-stable-stringify-without-jsonify@1.0.1: {}