From 283ab4b1dc0391599b4455f4fc74653b0e42f5b8 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 2 Jun 2025 15:48:05 -0400 Subject: [PATCH 1/4] feat(node): Add vercel ai input/outputs if `sendDefaultPii` is `true` --- dev-packages/node-integration-tests/package.json | 2 +- .../src/integrations/tracing/vercelai/constants.ts | 1 + .../node/src/integrations/tracing/vercelai/index.ts | 3 +-- .../integrations/tracing/vercelai/instrumentation.ts | 11 ++++++++--- 4 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 packages/node/src/integrations/tracing/vercelai/constants.ts diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json index d7fd85737942..09ae6c121e5b 100644 --- a/dev-packages/node-integration-tests/package.json +++ b/dev-packages/node-integration-tests/package.json @@ -36,7 +36,7 @@ "@types/mongodb": "^3.6.20", "@types/mysql": "^2.15.21", "@types/pg": "^8.6.5", - "ai": "^4.0.6", + "ai": "^4.3.16", "amqplib": "^0.10.7", "apollo-server": "^3.11.1", "body-parser": "^1.20.3", diff --git a/packages/node/src/integrations/tracing/vercelai/constants.ts b/packages/node/src/integrations/tracing/vercelai/constants.ts new file mode 100644 index 000000000000..fd4473c4c084 --- /dev/null +++ b/packages/node/src/integrations/tracing/vercelai/constants.ts @@ -0,0 +1 @@ +export const INTEGRATION_NAME = 'VercelAI'; diff --git a/packages/node/src/integrations/tracing/vercelai/index.ts b/packages/node/src/integrations/tracing/vercelai/index.ts index f68b95f0f815..a8e6756ff590 100644 --- a/packages/node/src/integrations/tracing/vercelai/index.ts +++ b/packages/node/src/integrations/tracing/vercelai/index.ts @@ -3,10 +3,9 @@ import type { IntegrationFn } from '@sentry/core'; import { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, spanToJSON } from '@sentry/core'; import { generateInstrumentOnce } from '../../../otel/instrument'; import { addOriginToSpan } from '../../../utils/addOriginToSpan'; +import { INTEGRATION_NAME } from './constants'; import { SentryVercelAiInstrumentation } from './instrumentation'; -const INTEGRATION_NAME = 'VercelAI'; - export const instrumentVercelAi = generateInstrumentOnce(INTEGRATION_NAME, () => new SentryVercelAiInstrumentation({})); const _vercelAIIntegration = (() => { diff --git a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts index e4f8a5ba25ae..51b5a788e862 100644 --- a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts +++ b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts @@ -1,6 +1,7 @@ import type { InstrumentationConfig, InstrumentationModuleDefinition } from '@opentelemetry/instrumentation'; import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation'; -import { SDK_VERSION } from '@sentry/core'; +import { getCurrentScope, SDK_VERSION } from '@sentry/core'; +import { INTEGRATION_NAME } from './constants'; import type { TelemetrySettings } from './types'; // List of patched methods @@ -70,14 +71,18 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase { return (...args: MethodArgs) => { const existingExperimentalTelemetry = args[0].experimental_telemetry || {}; const isEnabled = existingExperimentalTelemetry.isEnabled; + const client = getCurrentScope().getClient(); + const shouldRecordImportAndExports = client?.getIntegrationByName(INTEGRATION_NAME) + ? client.getOptions().sendDefaultPii + : false; // if `isEnabled` is not explicitly set to `true` or `false`, enable telemetry // but disable capturing inputs and outputs by default if (isEnabled === undefined) { args[0].experimental_telemetry = { isEnabled: true, - recordInputs: false, - recordOutputs: false, + recordInputs: shouldRecordImportAndExports, + recordOutputs: shouldRecordImportAndExports, ...existingExperimentalTelemetry, }; } From 4e76f0475dff41045c6d5cf429d81ace2fd97b3c Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 2 Jun 2025 22:34:39 -0400 Subject: [PATCH 2/4] Add tests --- .../tracing/vercelai/instrument-with-pii.mjs | 11 ++ .../tracing/{ai => vercelai}/instrument.mjs | 1 + .../tracing/{ai => vercelai}/scenario.mjs | 0 .../suites/tracing/{ai => vercelai}/test.ts | 100 ++++++++++-------- .../tracing/vercelai/instrumentation.ts | 27 +++-- 5 files changed, 83 insertions(+), 56 deletions(-) create mode 100644 dev-packages/node-integration-tests/suites/tracing/vercelai/instrument-with-pii.mjs rename dev-packages/node-integration-tests/suites/tracing/{ai => vercelai}/instrument.mjs (84%) rename dev-packages/node-integration-tests/suites/tracing/{ai => vercelai}/scenario.mjs (100%) rename dev-packages/node-integration-tests/suites/tracing/{ai => vercelai}/test.ts (67%) diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/instrument-with-pii.mjs b/dev-packages/node-integration-tests/suites/tracing/vercelai/instrument-with-pii.mjs new file mode 100644 index 000000000000..b798e21228f5 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/instrument-with-pii.mjs @@ -0,0 +1,11 @@ +import * as Sentry from '@sentry/node'; +import { loggingTransport } from '@sentry-internal/node-integration-tests'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + sendDefaultPii: true, + transport: loggingTransport, + integrations: [Sentry.vercelAIIntegration()], +}); diff --git a/dev-packages/node-integration-tests/suites/tracing/ai/instrument.mjs b/dev-packages/node-integration-tests/suites/tracing/vercelai/instrument.mjs similarity index 84% rename from dev-packages/node-integration-tests/suites/tracing/ai/instrument.mjs rename to dev-packages/node-integration-tests/suites/tracing/vercelai/instrument.mjs index 46a27dd03b74..5e898ee1949d 100644 --- a/dev-packages/node-integration-tests/suites/tracing/ai/instrument.mjs +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/instrument.mjs @@ -6,4 +6,5 @@ Sentry.init({ release: '1.0', tracesSampleRate: 1.0, transport: loggingTransport, + integrations: [Sentry.vercelAIIntegration()], }); diff --git a/dev-packages/node-integration-tests/suites/tracing/ai/scenario.mjs b/dev-packages/node-integration-tests/suites/tracing/vercelai/scenario.mjs similarity index 100% rename from dev-packages/node-integration-tests/suites/tracing/ai/scenario.mjs rename to dev-packages/node-integration-tests/suites/tracing/vercelai/scenario.mjs diff --git a/dev-packages/node-integration-tests/suites/tracing/ai/test.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts similarity index 67% rename from dev-packages/node-integration-tests/suites/tracing/ai/test.ts rename to dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts index c0a3ccb4a78a..06464ae82f10 100644 --- a/dev-packages/node-integration-tests/suites/tracing/ai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts @@ -2,14 +2,15 @@ import { afterAll, describe, expect } from 'vitest'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../utils/runner'; // `ai` SDK only support Node 18+ -describe('ai', () => { +describe('Vercel AI integration', () => { afterAll(() => { cleanupChildProcesses(); }); - const EXPECTED_TRANSACTION = { + const EXPECTED_TRANSACTION_DEFAULT_PII_FALSE = { transaction: 'main', spans: expect.arrayContaining([ + // First span - no telemetry config, should enable telemetry but not record inputs/outputs when sendDefaultPii: false expect.objectContaining({ data: expect.objectContaining({ 'ai.completion_tokens.used': 20, @@ -35,48 +36,51 @@ describe('ai', () => { origin: 'auto.vercelai.otel', status: 'ok', }), + // Second span - explicitly enabled telemetry but recordInputs/recordOutputs not set, should not record when sendDefaultPii: false expect.objectContaining({ data: expect.objectContaining({ - 'sentry.origin': 'auto.vercelai.otel', - 'sentry.op': 'ai.run.doGenerate', - 'operation.name': 'ai.generateText.doGenerate', - 'ai.operationId': 'ai.generateText.doGenerate', - 'ai.model.provider': 'mock-provider', + 'ai.completion_tokens.used': 20, 'ai.model.id': 'mock-model-id', - 'ai.settings.maxRetries': 2, - 'gen_ai.system': 'mock-provider', - 'gen_ai.request.model': 'mock-model-id', - 'ai.pipeline.name': 'generateText.doGenerate', + 'ai.model.provider': 'mock-provider', 'ai.model_id': 'mock-model-id', - 'ai.streaming': false, - 'ai.response.finishReason': 'stop', - 'ai.response.model': 'mock-model-id', - 'ai.usage.promptTokens': 10, - 'ai.usage.completionTokens': 20, - 'gen_ai.response.finish_reasons': ['stop'], - 'gen_ai.usage.input_tokens': 10, - 'gen_ai.usage.output_tokens': 20, - 'ai.completion_tokens.used': 20, + 'ai.operationId': 'ai.generateText', + 'ai.pipeline.name': 'generateText', 'ai.prompt_tokens.used': 10, + 'ai.response.finishReason': 'stop', + 'ai.settings.maxRetries': 2, + 'ai.settings.maxSteps': 1, + 'ai.streaming': false, 'ai.total_tokens.used': 30, + 'ai.usage.completionTokens': 20, + 'ai.usage.promptTokens': 10, + 'operation.name': 'ai.generateText', + 'sentry.op': 'ai.pipeline.generateText', + 'sentry.origin': 'auto.vercelai.otel', }), - description: 'generateText.doGenerate', - op: 'ai.run.doGenerate', + description: 'generateText', + op: 'ai.pipeline.generateText', origin: 'auto.vercelai.otel', status: 'ok', }), + ]), + }; + + const EXPECTED_TRANSACTION_DEFAULT_PII_TRUE = { + transaction: 'main', + spans: expect.arrayContaining([ + // First span - no telemetry config, should enable telemetry AND record inputs/outputs when sendDefaultPii: true expect.objectContaining({ data: expect.objectContaining({ 'ai.completion_tokens.used': 20, 'ai.model.id': 'mock-model-id', 'ai.model.provider': 'mock-provider', 'ai.model_id': 'mock-model-id', - 'ai.prompt': '{"prompt":"Where is the second span?"}', + 'ai.prompt': '{"prompt":"Where is the first span?"}', 'ai.operationId': 'ai.generateText', 'ai.pipeline.name': 'generateText', 'ai.prompt_tokens.used': 10, 'ai.response.finishReason': 'stop', - 'ai.input_messages': '{"prompt":"Where is the second span?"}', + 'ai.input_messages': '{"prompt":"Where is the first span?"}', 'ai.settings.maxRetries': 2, 'ai.settings.maxSteps': 1, 'ai.streaming': false, @@ -92,33 +96,31 @@ describe('ai', () => { origin: 'auto.vercelai.otel', status: 'ok', }), + // Second span - explicitly enabled telemetry, should record inputs/outputs regardless of sendDefaultPii expect.objectContaining({ data: expect.objectContaining({ - 'sentry.origin': 'auto.vercelai.otel', - 'sentry.op': 'ai.run.doGenerate', - 'operation.name': 'ai.generateText.doGenerate', - 'ai.operationId': 'ai.generateText.doGenerate', - 'ai.model.provider': 'mock-provider', + 'ai.completion_tokens.used': 20, 'ai.model.id': 'mock-model-id', - 'ai.settings.maxRetries': 2, - 'gen_ai.system': 'mock-provider', - 'gen_ai.request.model': 'mock-model-id', - 'ai.pipeline.name': 'generateText.doGenerate', + 'ai.model.provider': 'mock-provider', 'ai.model_id': 'mock-model-id', - 'ai.streaming': false, - 'ai.response.finishReason': 'stop', - 'ai.response.model': 'mock-model-id', - 'ai.usage.promptTokens': 10, - 'ai.usage.completionTokens': 20, - 'gen_ai.response.finish_reasons': ['stop'], - 'gen_ai.usage.input_tokens': 10, - 'gen_ai.usage.output_tokens': 20, - 'ai.completion_tokens.used': 20, + 'ai.prompt': '{"prompt":"Where is the second span?"}', + 'ai.operationId': 'ai.generateText', + 'ai.pipeline.name': 'generateText', 'ai.prompt_tokens.used': 10, + 'ai.response.finishReason': 'stop', + 'ai.input_messages': '{"prompt":"Where is the second span?"}', + 'ai.settings.maxRetries': 2, + 'ai.settings.maxSteps': 1, + 'ai.streaming': false, 'ai.total_tokens.used': 30, + 'ai.usage.completionTokens': 20, + 'ai.usage.promptTokens': 10, + 'operation.name': 'ai.generateText', + 'sentry.op': 'ai.pipeline.generateText', + 'sentry.origin': 'auto.vercelai.otel', }), - description: 'generateText.doGenerate', - op: 'ai.run.doGenerate', + description: 'generateText', + op: 'ai.pipeline.generateText', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -126,8 +128,14 @@ describe('ai', () => { }; createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { - test('creates ai related spans ', async () => { - await createRunner().expect({ transaction: EXPECTED_TRANSACTION }).start().completed(); + test('creates ai related spans with sendDefaultPii: false', async () => { + await createRunner().expect({ transaction: EXPECTED_TRANSACTION_DEFAULT_PII_FALSE }).start().completed(); + }); + }); + + createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument-with-pii.mjs', (createRunner, test) => { + test('creates ai related spans with sendDefaultPii: true', async () => { + await createRunner().expect({ transaction: EXPECTED_TRANSACTION_DEFAULT_PII_TRUE }).start().completed(); }); }); }); diff --git a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts index 51b5a788e862..4044af563877 100644 --- a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts +++ b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts @@ -71,21 +71,28 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase { return (...args: MethodArgs) => { const existingExperimentalTelemetry = args[0].experimental_telemetry || {}; const isEnabled = existingExperimentalTelemetry.isEnabled; + const client = getCurrentScope().getClient(); const shouldRecordImportAndExports = client?.getIntegrationByName(INTEGRATION_NAME) ? client.getOptions().sendDefaultPii : false; - // if `isEnabled` is not explicitly set to `true` or `false`, enable telemetry - // but disable capturing inputs and outputs by default - if (isEnabled === undefined) { - args[0].experimental_telemetry = { - isEnabled: true, - recordInputs: shouldRecordImportAndExports, - recordOutputs: shouldRecordImportAndExports, - ...existingExperimentalTelemetry, - }; - } + // Set recordInputs and recordOutputs based on sendDefaultPii if not explicitly set + const recordInputs = + existingExperimentalTelemetry.recordInputs !== undefined + ? existingExperimentalTelemetry.recordInputs + : shouldRecordImportAndExports; + const recordOutputs = + existingExperimentalTelemetry.recordOutputs !== undefined + ? existingExperimentalTelemetry.recordOutputs + : shouldRecordImportAndExports; + + args[0].experimental_telemetry = { + ...existingExperimentalTelemetry, + isEnabled: isEnabled !== undefined ? isEnabled : true, + recordInputs, + recordOutputs, + }; // @ts-expect-error we know that the method exists return originalMethod.apply(this, args); From 71e754607f8d4e66f229c8ad57b48901bb4d1d9b Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 3 Jun 2025 12:21:58 -0400 Subject: [PATCH 3/4] rename shouldRecordInputsAndOutputs --- .../src/integrations/tracing/vercelai/instrumentation.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts index 4044af563877..dc2a627904a5 100644 --- a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts +++ b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts @@ -73,7 +73,7 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase { const isEnabled = existingExperimentalTelemetry.isEnabled; const client = getCurrentScope().getClient(); - const shouldRecordImportAndExports = client?.getIntegrationByName(INTEGRATION_NAME) + const shouldRecordInputsAndOutputs = client?.getIntegrationByName(INTEGRATION_NAME) ? client.getOptions().sendDefaultPii : false; @@ -81,11 +81,11 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase { const recordInputs = existingExperimentalTelemetry.recordInputs !== undefined ? existingExperimentalTelemetry.recordInputs - : shouldRecordImportAndExports; + : shouldRecordInputsAndOutputs; const recordOutputs = existingExperimentalTelemetry.recordOutputs !== undefined ? existingExperimentalTelemetry.recordOutputs - : shouldRecordImportAndExports; + : shouldRecordInputsAndOutputs; args[0].experimental_telemetry = { ...existingExperimentalTelemetry, From 379de2c238749328f26d50a95b719ce5287deb60 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 4 Jun 2025 23:24:31 -0400 Subject: [PATCH 4/4] add integration option --- .../suites/tracing/vercelai/test.ts | 131 ++++++++-- .../integrations/tracing/vercelai/index.ts | 4 +- .../tracing/vercelai/instrumentation.ts | 66 ++++- .../integrations/tracing/vercelai/types.ts | 19 ++ .../tracing/vercelai/instrumentation.test.ts | 214 ++++++++++++++++ yarn.lock | 241 +++--------------- 6 files changed, 439 insertions(+), 236 deletions(-) create mode 100644 packages/node/test/integrations/tracing/vercelai/instrumentation.test.ts diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts index f675a0d0d73e..7876dbccb440 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts @@ -12,7 +12,7 @@ describe('Vercel AI integration', () => { spans: expect.arrayContaining([ // First span - no telemetry config, should enable telemetry but not record inputs/outputs when sendDefaultPii: false expect.objectContaining({ - data: expect.objectContaining({ + data: { 'ai.model.id': 'mock-model-id', 'ai.model.provider': 'mock-provider', 'ai.operationId': 'ai.generateText', @@ -28,7 +28,7 @@ describe('Vercel AI integration', () => { 'operation.name': 'ai.generateText', 'sentry.op': 'ai.pipeline.generateText', 'sentry.origin': 'auto.vercelai.otel', - }), + }, description: 'generateText', op: 'ai.pipeline.generateText', origin: 'auto.vercelai.otel', @@ -36,7 +36,7 @@ describe('Vercel AI integration', () => { }), // Second span - explicitly enabled telemetry but recordInputs/recordOutputs not set, should not record when sendDefaultPii: false expect.objectContaining({ - data: expect.objectContaining({ + data: { 'sentry.origin': 'auto.vercelai.otel', 'sentry.op': 'ai.run.doGenerate', 'operation.name': 'ai.generateText.doGenerate', @@ -58,12 +58,72 @@ describe('Vercel AI integration', () => { 'gen_ai.response.id': expect.any(String), 'gen_ai.response.model': 'mock-model-id', 'gen_ai.usage.total_tokens': 30, - }), + }, + description: 'generateText.doGenerate', + op: 'ai.run.doGenerate', + origin: 'auto.vercelai.otel', + status: 'ok', + }), + // Third span - explicit telemetry enabled, should record inputs/outputs regardless of sendDefaultPii + expect.objectContaining({ + data: { + 'ai.model.id': 'mock-model-id', + 'ai.model.provider': 'mock-provider', + 'ai.operationId': 'ai.generateText', + 'ai.pipeline.name': 'generateText', + 'ai.prompt': '{"prompt":"Where is the second span?"}', + 'ai.response.finishReason': 'stop', + 'ai.response.text': expect.any(String), + 'ai.settings.maxRetries': 2, + 'ai.settings.maxSteps': 1, + 'ai.streaming': false, + 'gen_ai.prompt': '{"prompt":"Where is the second span?"}', + 'gen_ai.response.model': 'mock-model-id', + 'gen_ai.usage.input_tokens': 10, + 'gen_ai.usage.output_tokens': 20, + 'gen_ai.usage.total_tokens': 30, + 'operation.name': 'ai.generateText', + 'sentry.op': 'ai.pipeline.generateText', + 'sentry.origin': 'auto.vercelai.otel', + }, description: 'generateText', op: 'ai.pipeline.generateText', origin: 'auto.vercelai.otel', status: 'ok', }), + // Fourth span - doGenerate for explicit telemetry enabled call + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.vercelai.otel', + 'sentry.op': 'ai.run.doGenerate', + 'operation.name': 'ai.generateText.doGenerate', + 'ai.operationId': 'ai.generateText.doGenerate', + 'ai.model.provider': 'mock-provider', + 'ai.model.id': 'mock-model-id', + 'ai.settings.maxRetries': 2, + 'gen_ai.system': 'mock-provider', + 'gen_ai.request.model': 'mock-model-id', + 'ai.pipeline.name': 'generateText.doGenerate', + 'ai.streaming': false, + 'ai.response.finishReason': 'stop', + 'ai.response.model': 'mock-model-id', + 'ai.response.id': expect.any(String), + 'ai.response.text': expect.any(String), + 'ai.response.timestamp': expect.any(String), + 'ai.prompt.format': expect.any(String), + 'ai.prompt.messages': expect.any(String), + 'gen_ai.response.finish_reasons': ['stop'], + 'gen_ai.usage.input_tokens': 10, + 'gen_ai.usage.output_tokens': 20, + 'gen_ai.response.id': expect.any(String), + 'gen_ai.response.model': 'mock-model-id', + 'gen_ai.usage.total_tokens': 30, + }, + description: 'generateText.doGenerate', + op: 'ai.run.doGenerate', + origin: 'auto.vercelai.otel', + status: 'ok', + }), ]), }; @@ -72,35 +132,67 @@ describe('Vercel AI integration', () => { spans: expect.arrayContaining([ // First span - no telemetry config, should enable telemetry AND record inputs/outputs when sendDefaultPii: true expect.objectContaining({ - data: expect.objectContaining({ - 'ai.completion_tokens.used': 20, + data: { 'ai.model.id': 'mock-model-id', 'ai.model.provider': 'mock-provider', - 'ai.model_id': 'mock-model-id', - 'ai.prompt': '{"prompt":"Where is the first span?"}', 'ai.operationId': 'ai.generateText', 'ai.pipeline.name': 'generateText', - 'ai.prompt_tokens.used': 10, + 'ai.prompt': '{"prompt":"Where is the first span?"}', 'ai.response.finishReason': 'stop', - 'ai.input_messages': '{"prompt":"Where is the first span?"}', + 'ai.response.text': 'First span here!', 'ai.settings.maxRetries': 2, 'ai.settings.maxSteps': 1, 'ai.streaming': false, - 'ai.total_tokens.used': 30, - 'ai.usage.completionTokens': 20, - 'ai.usage.promptTokens': 10, + 'gen_ai.prompt': '{"prompt":"Where is the first span?"}', + 'gen_ai.response.model': 'mock-model-id', + 'gen_ai.usage.input_tokens': 10, + 'gen_ai.usage.output_tokens': 20, + 'gen_ai.usage.total_tokens': 30, 'operation.name': 'ai.generateText', 'sentry.op': 'ai.pipeline.generateText', 'sentry.origin': 'auto.vercelai.otel', - }), + }, description: 'generateText', op: 'ai.pipeline.generateText', origin: 'auto.vercelai.otel', status: 'ok', }), - // Second span - explicitly enabled telemetry, should record inputs/outputs regardless of sendDefaultPii + // Second span - doGenerate for first call, should also include input/output fields when sendDefaultPii: true + expect.objectContaining({ + data: { + 'ai.model.id': 'mock-model-id', + 'ai.model.provider': 'mock-provider', + 'ai.operationId': 'ai.generateText.doGenerate', + 'ai.pipeline.name': 'generateText.doGenerate', + 'ai.prompt.format': 'prompt', + 'ai.prompt.messages': '[{"role":"user","content":[{"type":"text","text":"Where is the first span?"}]}]', + 'ai.response.finishReason': 'stop', + 'ai.response.id': expect.any(String), + 'ai.response.model': 'mock-model-id', + 'ai.response.text': 'First span here!', + 'ai.response.timestamp': expect.any(String), + 'ai.settings.maxRetries': 2, + 'ai.streaming': false, + 'gen_ai.request.model': 'mock-model-id', + 'gen_ai.response.finish_reasons': ['stop'], + 'gen_ai.response.id': expect.any(String), + 'gen_ai.response.model': 'mock-model-id', + 'gen_ai.system': 'mock-provider', + 'gen_ai.usage.input_tokens': 10, + 'gen_ai.usage.output_tokens': 20, + 'gen_ai.usage.total_tokens': 30, + 'operation.name': 'ai.generateText.doGenerate', + 'sentry.op': 'ai.run.doGenerate', + 'sentry.origin': 'auto.vercelai.otel', + }, + description: 'generateText.doGenerate', + op: 'ai.run.doGenerate', + origin: 'auto.vercelai.otel', + status: 'ok', + }), + // Third span - explicitly enabled telemetry, should record inputs/outputs regardless of sendDefaultPii expect.objectContaining({ - data: expect.objectContaining({ + data: { 'ai.model.id': 'mock-model-id', 'ai.model.provider': 'mock-provider', 'ai.operationId': 'ai.generateText', @@ -119,14 +211,15 @@ describe('Vercel AI integration', () => { 'operation.name': 'ai.generateText', 'sentry.op': 'ai.pipeline.generateText', 'sentry.origin': 'auto.vercelai.otel', - }), + }, description: 'generateText', op: 'ai.pipeline.generateText', origin: 'auto.vercelai.otel', status: 'ok', }), + // Fourth span - doGenerate for explicitly enabled telemetry call expect.objectContaining({ - data: expect.objectContaining({ + data: { 'sentry.origin': 'auto.vercelai.otel', 'sentry.op': 'ai.run.doGenerate', 'operation.name': 'ai.generateText.doGenerate', @@ -151,7 +244,7 @@ describe('Vercel AI integration', () => { 'gen_ai.response.id': expect.any(String), 'gen_ai.response.model': 'mock-model-id', 'gen_ai.usage.total_tokens': 30, - }), + }, description: 'generateText.doGenerate', op: 'ai.run.doGenerate', origin: 'auto.vercelai.otel', diff --git a/packages/node/src/integrations/tracing/vercelai/index.ts b/packages/node/src/integrations/tracing/vercelai/index.ts index 6c96a9c279a7..44bc2dca915f 100644 --- a/packages/node/src/integrations/tracing/vercelai/index.ts +++ b/packages/node/src/integrations/tracing/vercelai/index.ts @@ -15,14 +15,16 @@ import { } from './attributes'; import { INTEGRATION_NAME } from './constants'; import { SentryVercelAiInstrumentation } from './instrumentation'; +import type { VercelAiOptions } from './types'; export const instrumentVercelAi = generateInstrumentOnce(INTEGRATION_NAME, () => new SentryVercelAiInstrumentation({})); -const _vercelAIIntegration = (() => { +const _vercelAIIntegration = ((options: VercelAiOptions = {}) => { let instrumentation: undefined | SentryVercelAiInstrumentation; return { name: INTEGRATION_NAME, + options, setupOnce() { instrumentation = instrumentVercelAi(); }, diff --git a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts index dc2a627904a5..4b823670793a 100644 --- a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts +++ b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts @@ -2,7 +2,7 @@ import type { InstrumentationConfig, InstrumentationModuleDefinition } from '@op import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation'; import { getCurrentScope, SDK_VERSION } from '@sentry/core'; import { INTEGRATION_NAME } from './constants'; -import type { TelemetrySettings } from './types'; +import type { TelemetrySettings, VercelAiIntegration } from './types'; // List of patched methods // From: https://sdk.vercel.ai/docs/ai-sdk-core/telemetry#collected-data @@ -24,6 +24,47 @@ type MethodArgs = [MethodFirstArg, ...unknown[]]; type PatchedModuleExports = Record<(typeof INSTRUMENTED_METHODS)[number], (...args: MethodArgs) => unknown> & Record; +interface RecordingOptions { + recordInputs?: boolean; + recordOutputs?: boolean; +} + +/** + * Determines whether to record inputs and outputs for Vercel AI telemetry based on the configuration hierarchy. + * + * The order of precedence is: + * 1. The vercel ai integration options + * 2. The experimental_telemetry options in the vercel ai method calls + * 3. When telemetry is explicitly enabled (isEnabled: true), default to recording + * 4. Otherwise, use the sendDefaultPii option from client options + */ +export function determineRecordingSettings( + integrationRecordingOptions: RecordingOptions | undefined, + methodTelemetryOptions: RecordingOptions, + telemetryExplicitlyEnabled: boolean | undefined, + defaultRecordingEnabled: boolean, +): { recordInputs: boolean; recordOutputs: boolean } { + const recordInputs = + integrationRecordingOptions?.recordInputs !== undefined + ? integrationRecordingOptions.recordInputs + : methodTelemetryOptions.recordInputs !== undefined + ? methodTelemetryOptions.recordInputs + : telemetryExplicitlyEnabled === true + ? true // When telemetry is explicitly enabled, default to recording inputs + : defaultRecordingEnabled; + + const recordOutputs = + integrationRecordingOptions?.recordOutputs !== undefined + ? integrationRecordingOptions.recordOutputs + : methodTelemetryOptions.recordOutputs !== undefined + ? methodTelemetryOptions.recordOutputs + : telemetryExplicitlyEnabled === true + ? true // When telemetry is explicitly enabled, default to recording inputs + : defaultRecordingEnabled; + + return { recordInputs, recordOutputs }; +} + /** * This detects is added by the Sentry Vercel AI Integration to detect if the integration should * be enabled. @@ -73,19 +114,16 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase { const isEnabled = existingExperimentalTelemetry.isEnabled; const client = getCurrentScope().getClient(); - const shouldRecordInputsAndOutputs = client?.getIntegrationByName(INTEGRATION_NAME) - ? client.getOptions().sendDefaultPii - : false; - - // Set recordInputs and recordOutputs based on sendDefaultPii if not explicitly set - const recordInputs = - existingExperimentalTelemetry.recordInputs !== undefined - ? existingExperimentalTelemetry.recordInputs - : shouldRecordInputsAndOutputs; - const recordOutputs = - existingExperimentalTelemetry.recordOutputs !== undefined - ? existingExperimentalTelemetry.recordOutputs - : shouldRecordInputsAndOutputs; + const integration = client?.getIntegrationByName(INTEGRATION_NAME); + const integrationOptions = integration?.options; + const shouldRecordInputsAndOutputs = integration ? Boolean(client?.getOptions().sendDefaultPii) : false; + + const { recordInputs, recordOutputs } = determineRecordingSettings( + integrationOptions, + existingExperimentalTelemetry, + isEnabled, + shouldRecordInputsAndOutputs, + ); args[0].experimental_telemetry = { ...existingExperimentalTelemetry, diff --git a/packages/node/src/integrations/tracing/vercelai/types.ts b/packages/node/src/integrations/tracing/vercelai/types.ts index 8773f84d52c6..50434b70604f 100644 --- a/packages/node/src/integrations/tracing/vercelai/types.ts +++ b/packages/node/src/integrations/tracing/vercelai/types.ts @@ -1,3 +1,5 @@ +import type { Integration } from '@sentry/core'; + /** * Telemetry configuration. */ @@ -42,3 +44,20 @@ export declare type AttributeValue = | Array | Array | Array; + +export interface VercelAiOptions { + /** + * Enable or disable input recording. Enabled if `sendDefaultPii` is `true` + * or if you set `isEnabled` to `true` in your ai SDK method telemetry settings + */ + recordInputs?: boolean; + /** + * Enable or disable output recording. Enabled if `sendDefaultPii` is `true` + * or if you set `isEnabled` to `true` in your ai SDK method telemetry settings + */ + recordOutputs?: boolean; +} + +export interface VercelAiIntegration extends Integration { + options: VercelAiOptions; +} diff --git a/packages/node/test/integrations/tracing/vercelai/instrumentation.test.ts b/packages/node/test/integrations/tracing/vercelai/instrumentation.test.ts new file mode 100644 index 000000000000..9a9d8cc50f0a --- /dev/null +++ b/packages/node/test/integrations/tracing/vercelai/instrumentation.test.ts @@ -0,0 +1,214 @@ +import { describe, expect, test } from 'vitest'; +import { determineRecordingSettings } from '../../../../src/integrations/tracing/vercelai/instrumentation'; + +describe('determineRecordingSettings', () => { + test('should use integration recording options when provided (recordInputs: true, recordOutputs: false)', () => { + const result = determineRecordingSettings( + { recordInputs: true, recordOutputs: false }, // integrationRecordingOptions + {}, // methodTelemetryOptions + undefined, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: true, + recordOutputs: false, + }); + }); + + test('should use integration recording options when provided (recordInputs: false, recordOutputs: true)', () => { + const result = determineRecordingSettings( + { recordInputs: false, recordOutputs: true }, // integrationRecordingOptions + {}, // methodTelemetryOptions + true, // telemetryExplicitlyEnabled + true, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: false, + recordOutputs: true, + }); + }); + + test('should fall back to method telemetry options when integration options not provided', () => { + const result = determineRecordingSettings( + {}, // integrationRecordingOptions + { recordInputs: true, recordOutputs: false }, // methodTelemetryOptions + undefined, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: true, + recordOutputs: false, + }); + }); + + test('should prefer integration recording options over method telemetry options', () => { + const result = determineRecordingSettings( + { recordInputs: false, recordOutputs: false }, // integrationRecordingOptions + { recordInputs: true, recordOutputs: true }, // methodTelemetryOptions + undefined, // telemetryExplicitlyEnabled + true, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: false, + recordOutputs: false, + }); + }); + + test('should default to recording when telemetry is explicitly enabled', () => { + const result = determineRecordingSettings( + {}, // integrationRecordingOptions + {}, // methodTelemetryOptions + true, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: true, + recordOutputs: true, + }); + }); + + test('should use default recording setting when telemetry is explicitly disabled', () => { + const result = determineRecordingSettings( + {}, // integrationRecordingOptions + {}, // methodTelemetryOptions + false, // telemetryExplicitlyEnabled + true, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: true, + recordOutputs: true, + }); + }); + + test('should use default recording setting when telemetry enablement is undefined', () => { + const result = determineRecordingSettings( + {}, // integrationRecordingOptions + {}, // methodTelemetryOptions + undefined, // telemetryExplicitlyEnabled + true, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: true, + recordOutputs: true, + }); + }); + + test('should not record when default recording is disabled and no explicit configuration', () => { + const result = determineRecordingSettings( + {}, // integrationRecordingOptions + {}, // methodTelemetryOptions + undefined, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: false, + recordOutputs: false, + }); + }); + + test('should handle partial integration recording options (only recordInputs)', () => { + const result = determineRecordingSettings( + { recordInputs: true }, // integrationRecordingOptions + {}, // methodTelemetryOptions + false, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: true, + recordOutputs: false, // falls back to defaultRecordingEnabled + }); + }); + + test('should handle partial integration recording options (only recordOutputs)', () => { + const result = determineRecordingSettings( + { recordOutputs: true }, // integrationRecordingOptions + {}, // methodTelemetryOptions + false, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: false, // falls back to defaultRecordingEnabled + recordOutputs: true, + }); + }); + + test('should handle partial method telemetry options (only recordInputs)', () => { + const result = determineRecordingSettings( + {}, // integrationRecordingOptions + { recordInputs: true }, // methodTelemetryOptions + false, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: true, + recordOutputs: false, // falls back to defaultRecordingEnabled + }); + }); + + test('should handle partial method telemetry options (only recordOutputs)', () => { + const result = determineRecordingSettings( + {}, // integrationRecordingOptions + { recordOutputs: true }, // methodTelemetryOptions + false, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: false, // falls back to defaultRecordingEnabled + recordOutputs: true, + }); + }); + + test('should prefer integration recording options over method telemetry for partial configs', () => { + const result = determineRecordingSettings( + { recordInputs: false }, // integrationRecordingOptions + { recordInputs: true, recordOutputs: true }, // methodTelemetryOptions + false, // telemetryExplicitlyEnabled + true, // defaultRecordingEnabled + ); + + expect(result).toEqual({ + recordInputs: false, // from integration recording options + recordOutputs: true, // from method telemetry options + }); + }); + + test('complex scenario: sendDefaultPii enabled, telemetry enablement undefined, mixed options', () => { + const result = determineRecordingSettings( + { recordOutputs: false }, // integrationRecordingOptions + { recordInputs: false }, // methodTelemetryOptions + undefined, // telemetryExplicitlyEnabled + true, // defaultRecordingEnabled (sendDefaultPii: true) + ); + + expect(result).toEqual({ + recordInputs: false, // from method telemetry options + recordOutputs: false, // from integration recording options + }); + }); + + test('complex scenario: explicit telemetry enabled overrides sendDefaultPii disabled', () => { + const result = determineRecordingSettings( + {}, // integrationRecordingOptions + {}, // methodTelemetryOptions + true, // telemetryExplicitlyEnabled + false, // defaultRecordingEnabled (sendDefaultPii: false) + ); + + expect(result).toEqual({ + recordInputs: true, + recordOutputs: true, + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index a547a6d053a5..f8ee2a1e749b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -80,41 +80,40 @@ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.2.tgz#c836b1bd81e6d62cd6cdf3ee4948bcdce8ea79c8" integrity sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A== -"@ai-sdk/provider-utils@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-2.0.2.tgz#ea9d510be442b38bd40ae50dbf5b64ffc396952b" - integrity sha512-IAvhKhdlXqiSmvx/D4uNlFYCl8dWT+M9K+IuEcSgnE2Aj27GWu8sDIpAf4r4Voc+wOUkOECVKQhFo8g9pozdjA== +"@ai-sdk/provider-utils@2.2.8": + version "2.2.8" + resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz#ad11b92d5a1763ab34ba7b5fc42494bfe08b76d1" + integrity sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA== dependencies: - "@ai-sdk/provider" "1.0.1" - eventsource-parser "^3.0.0" - nanoid "^3.3.7" + "@ai-sdk/provider" "1.1.3" + nanoid "^3.3.8" secure-json-parse "^2.7.0" -"@ai-sdk/provider@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-1.0.1.tgz#8172a3cbbfa61bb40b88512165f70fe3c186cb60" - integrity sha512-mV+3iNDkzUsZ0pR2jG0sVzU6xtQY5DtSCBy3JFycLp6PwjyLw/iodfL3MwdmMCRJWgs3dadcHejRnMvF9nGTBg== +"@ai-sdk/provider@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-1.1.3.tgz#ebdda8077b8d2b3f290dcba32c45ad19b2704681" + integrity sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg== dependencies: json-schema "^0.4.0" -"@ai-sdk/react@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-1.0.3.tgz#b9bc24e20bdc5768cbb0d9c65471fb60ab2675ec" - integrity sha512-Mak7qIRlbgtP4I7EFoNKRIQTlABJHhgwrN8SV2WKKdmsfWK2RwcubQWz1hp88cQ0bpF6KxxjSY1UUnS/S9oR5g== +"@ai-sdk/react@1.2.12": + version "1.2.12" + resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-1.2.12.tgz#f4250b6df566b170af98a71d5708b52108dd0ce1" + integrity sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g== dependencies: - "@ai-sdk/provider-utils" "2.0.2" - "@ai-sdk/ui-utils" "1.0.2" + "@ai-sdk/provider-utils" "2.2.8" + "@ai-sdk/ui-utils" "1.2.11" swr "^2.2.5" throttleit "2.1.0" -"@ai-sdk/ui-utils@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@ai-sdk/ui-utils/-/ui-utils-1.0.2.tgz#2b5ad527f821b055663ddc60f2c45a82956091a0" - integrity sha512-hHrUdeThGHu/rsGZBWQ9PjrAU9Htxgbo9MFyR5B/aWoNbBeXn1HLMY1+uMEnXL5pRPlmyVRjgIavWg7UgeNDOw== +"@ai-sdk/ui-utils@1.2.11": + version "1.2.11" + resolved "https://registry.yarnpkg.com/@ai-sdk/ui-utils/-/ui-utils-1.2.11.tgz#4f815589d08d8fef7292ade54ee5db5d09652603" + integrity sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w== dependencies: - "@ai-sdk/provider" "1.0.1" - "@ai-sdk/provider-utils" "2.0.2" - zod-to-json-schema "^3.23.5" + "@ai-sdk/provider" "1.1.3" + "@ai-sdk/provider-utils" "2.2.8" + zod-to-json-schema "^3.24.1" "@ampproject/remapping@2.2.0": version "2.2.0" @@ -2965,11 +2964,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz#51299374de171dbd80bb7d838e1cfce9af36f353" integrity sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ== -"@esbuild/aix-ppc64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461" - integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA== - "@esbuild/aix-ppc64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" @@ -3010,11 +3004,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz#58565291a1fe548638adb9c584237449e5e14018" integrity sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw== -"@esbuild/android-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894" - integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg== - "@esbuild/android-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" @@ -3060,11 +3049,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz#5eb8c652d4c82a2421e3395b808e6d9c42c862ee" integrity sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ== -"@esbuild/android-arm@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3" - integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== - "@esbuild/android-arm@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" @@ -3105,11 +3089,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz#ae19d665d2f06f0f48a6ac9a224b3f672e65d517" integrity sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg== -"@esbuild/android-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb" - integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw== - "@esbuild/android-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" @@ -3150,11 +3129,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz#05b17f91a87e557b468a9c75e9d85ab10c121b16" integrity sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q== -"@esbuild/darwin-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936" - integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA== - "@esbuild/darwin-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz#49d8bf8b1df95f759ac81eb1d0736018006d7e34" @@ -3195,11 +3169,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz#c58353b982f4e04f0d022284b8ba2733f5ff0931" integrity sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw== -"@esbuild/darwin-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9" - integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA== - "@esbuild/darwin-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" @@ -3240,11 +3209,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz#f9220dc65f80f03635e1ef96cfad5da1f446f3bc" integrity sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA== -"@esbuild/freebsd-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00" - integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg== - "@esbuild/freebsd-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" @@ -3285,11 +3249,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz#69bd8511fa013b59f0226d1609ac43f7ce489730" integrity sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g== -"@esbuild/freebsd-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f" - integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q== - "@esbuild/freebsd-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" @@ -3330,11 +3289,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz#8050af6d51ddb388c75653ef9871f5ccd8f12383" integrity sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g== -"@esbuild/linux-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43" - integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg== - "@esbuild/linux-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" @@ -3375,11 +3329,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz#ecaabd1c23b701070484990db9a82f382f99e771" integrity sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ== -"@esbuild/linux-arm@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736" - integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== - "@esbuild/linux-arm@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" @@ -3420,11 +3369,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz#3ed2273214178109741c09bd0687098a0243b333" integrity sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ== -"@esbuild/linux-ia32@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5" - integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw== - "@esbuild/linux-ia32@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" @@ -3475,11 +3419,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz#a0fdf440b5485c81b0fbb316b08933d217f5d3ac" integrity sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw== -"@esbuild/linux-loong64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc" - integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ== - "@esbuild/linux-loong64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" @@ -3520,11 +3459,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz#e11a2806346db8375b18f5e104c5a9d4e81807f6" integrity sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q== -"@esbuild/linux-mips64el@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb" - integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw== - "@esbuild/linux-mips64el@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" @@ -3565,11 +3499,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz#06a2744c5eaf562b1a90937855b4d6cf7c75ec96" integrity sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw== -"@esbuild/linux-ppc64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412" - integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw== - "@esbuild/linux-ppc64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" @@ -3610,11 +3539,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz#65b46a2892fc0d1af4ba342af3fe0fa4a8fe08e7" integrity sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA== -"@esbuild/linux-riscv64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694" - integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q== - "@esbuild/linux-riscv64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" @@ -3655,11 +3579,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz#e71ea18c70c3f604e241d16e4e5ab193a9785d6f" integrity sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw== -"@esbuild/linux-s390x@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577" - integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw== - "@esbuild/linux-s390x@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" @@ -3700,21 +3619,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz#d47f97391e80690d4dfe811a2e7d6927ad9eed24" integrity sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ== -"@esbuild/linux-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f" - integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q== - "@esbuild/linux-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== -"@esbuild/netbsd-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6" - integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw== - "@esbuild/netbsd-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" @@ -3755,11 +3664,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz#44e743c9778d57a8ace4b72f3c6b839a3b74a653" integrity sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA== -"@esbuild/netbsd-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40" - integrity sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw== - "@esbuild/netbsd-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" @@ -3770,11 +3674,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz#05c5a1faf67b9881834758c69f3e51b7dee015d7" integrity sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q== -"@esbuild/openbsd-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f" - integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A== - "@esbuild/openbsd-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" @@ -3815,11 +3714,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz#2e58ae511bacf67d19f9f2dcd9e8c5a93f00c273" integrity sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA== -"@esbuild/openbsd-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205" - integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA== - "@esbuild/openbsd-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" @@ -3860,11 +3754,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz#adb022b959d18d3389ac70769cef5a03d3abd403" integrity sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA== -"@esbuild/sunos-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6" - integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig== - "@esbuild/sunos-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" @@ -3905,11 +3794,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz#84906f50c212b72ec360f48461d43202f4c8b9a2" integrity sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A== -"@esbuild/win32-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85" - integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ== - "@esbuild/win32-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" @@ -3950,11 +3834,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz#5e3eacc515820ff729e90d0cb463183128e82fac" integrity sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ== -"@esbuild/win32-ia32@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2" - integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA== - "@esbuild/win32-ia32@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" @@ -3995,11 +3874,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz#81fd50d11e2c32b2d6241470e3185b70c7b30699" integrity sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg== -"@esbuild/win32-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b" - integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg== - "@esbuild/win32-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" @@ -9648,18 +9522,17 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ai@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ai/-/ai-4.0.6.tgz#94ef793df8525c01043e15a60030ce88d7b5c7d5" - integrity sha512-TD7fH0LymjIYWmdQViB5SoBb1iuuDPOZ7RMU3W9r4SeUf68RzWyixz118QHQTENNqPiGA6vs5NDVAmZOnhzqYA== +ai@^4.3.16: + version "4.3.16" + resolved "https://registry.yarnpkg.com/ai/-/ai-4.3.16.tgz#c9446da1024cdc1dfe2913d151b70c91d40f2378" + integrity sha512-KUDwlThJ5tr2Vw0A1ZkbDKNME3wzWhuVfAOwIvFUzl1TPVDFAXDFTXio3p+jaKneB+dKNCvFFlolYmmgHttG1g== dependencies: - "@ai-sdk/provider" "1.0.1" - "@ai-sdk/provider-utils" "2.0.2" - "@ai-sdk/react" "1.0.3" - "@ai-sdk/ui-utils" "1.0.2" + "@ai-sdk/provider" "1.1.3" + "@ai-sdk/provider-utils" "2.2.8" + "@ai-sdk/react" "1.2.12" + "@ai-sdk/ui-utils" "1.2.11" "@opentelemetry/api" "1.9.0" jsondiffpatch "0.6.0" - zod-to-json-schema "^3.23.5" ajv-formats@2.1.1, ajv-formats@^2.1.1: version "2.1.1" @@ -15091,37 +14964,6 @@ esbuild@^0.23.0, esbuild@^0.23.1: "@esbuild/win32-ia32" "0.23.1" "@esbuild/win32-x64" "0.23.1" -esbuild@^0.24.2: - version "0.24.2" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.2.tgz#b5b55bee7de017bff5fb8a4e3e44f2ebe2c3567d" - integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA== - optionalDependencies: - "@esbuild/aix-ppc64" "0.24.2" - "@esbuild/android-arm" "0.24.2" - "@esbuild/android-arm64" "0.24.2" - "@esbuild/android-x64" "0.24.2" - "@esbuild/darwin-arm64" "0.24.2" - "@esbuild/darwin-x64" "0.24.2" - "@esbuild/freebsd-arm64" "0.24.2" - "@esbuild/freebsd-x64" "0.24.2" - "@esbuild/linux-arm" "0.24.2" - "@esbuild/linux-arm64" "0.24.2" - "@esbuild/linux-ia32" "0.24.2" - "@esbuild/linux-loong64" "0.24.2" - "@esbuild/linux-mips64el" "0.24.2" - "@esbuild/linux-ppc64" "0.24.2" - "@esbuild/linux-riscv64" "0.24.2" - "@esbuild/linux-s390x" "0.24.2" - "@esbuild/linux-x64" "0.24.2" - "@esbuild/netbsd-arm64" "0.24.2" - "@esbuild/netbsd-x64" "0.24.2" - "@esbuild/openbsd-arm64" "0.24.2" - "@esbuild/openbsd-x64" "0.24.2" - "@esbuild/sunos-x64" "0.24.2" - "@esbuild/win32-arm64" "0.24.2" - "@esbuild/win32-ia32" "0.24.2" - "@esbuild/win32-x64" "0.24.2" - esbuild@^0.25.0: version "0.25.5" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.5.tgz#71075054993fdfae76c66586f9b9c1f8d7edd430" @@ -15537,11 +15379,6 @@ events@^3.0.0, events@^3.2.0, events@^3.3.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -eventsource-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.0.tgz#9303e303ef807d279ee210a17ce80f16300d9f57" - integrity sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA== - exec-sh@^0.3.2, exec-sh@^0.3.4: version "0.3.6" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" @@ -15940,7 +15777,7 @@ fbjs@^0.8.0: setimmediate "^1.0.5" ua-parser-js "^0.7.18" -fdir@^6.2.0, fdir@^6.3.0, fdir@^6.4.2, fdir@^6.4.4: +fdir@^6.2.0, fdir@^6.3.0, fdir@^6.4.4: version "6.4.5" resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.5.tgz#328e280f3a23699362f95f2e82acf978a0c0cb49" integrity sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw== @@ -21553,7 +21390,7 @@ named-placeholders@^1.1.3: dependencies: lru-cache "^7.14.1" -nanoid@^3.3.11, nanoid@^3.3.3, nanoid@^3.3.4, nanoid@^3.3.6, nanoid@^3.3.7, nanoid@^3.3.8: +nanoid@^3.3.11, nanoid@^3.3.3, nanoid@^3.3.4, nanoid@^3.3.6, nanoid@^3.3.8: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== @@ -24192,7 +24029,7 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.1.10, postcss@^8.2.14, postcss@^8.2.15, postcss@^8.3.7, postcss@^8.4.23, postcss@^8.4.27, postcss@^8.4.39, postcss@^8.4.43, postcss@^8.4.47, postcss@^8.4.7, postcss@^8.4.8, postcss@^8.5.2, postcss@^8.5.3: +postcss@^8.1.10, postcss@^8.2.14, postcss@^8.2.15, postcss@^8.3.7, postcss@^8.4.23, postcss@^8.4.27, postcss@^8.4.39, postcss@^8.4.43, postcss@^8.4.47, postcss@^8.4.7, postcss@^8.4.8, postcss@^8.5.3: version "8.5.4" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.4.tgz#d61014ac00e11d5f58458ed7247d899bd65f99c0" integrity sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w== @@ -25782,7 +25619,7 @@ rollup@^3.27.1, rollup@^3.28.1: optionalDependencies: fsevents "~2.3.2" -rollup@^4.18.0, rollup@^4.20.0, rollup@^4.30.1, rollup@^4.34.9, rollup@^4.35.0: +rollup@^4.18.0, rollup@^4.20.0, rollup@^4.34.9, rollup@^4.35.0: version "4.41.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.41.1.tgz#46ddc1b33cf1b0baa99320d3b0b4973dc2253b6a" integrity sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw== @@ -30253,10 +30090,10 @@ zip-stream@^6.0.1: compress-commons "^6.0.2" readable-stream "^4.0.0" -zod-to-json-schema@^3.23.5: - version "3.23.5" - resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.23.5.tgz#ec23def47dcafe3a4d640eba6a346b34f9a693a5" - integrity sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA== +zod-to-json-schema@^3.24.1: + version "3.24.5" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" + integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g== zod@^3.22.3, zod@^3.22.4, zod@^3.24.1: version "3.24.1"