diff --git a/packages/cli/package.json b/packages/cli/package.json index ba3e9e9d1..1573155c3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -101,10 +101,9 @@ "@hono/node-server": "^2.0.10", "@mastra/client-js": "^1.38.0", "@sentry/api": "catalog:", - "@sentry/core": "10.63.0", + "@sentry/core": "catalog:", "@sentry/mcp-server": "workspace:*", - "@sentry/node": "10.65.0", - "@sentry/node-core": "10.63.0", + "@sentry/node": "catalog:", "@sentry/sqlish": "^1.0.1", "@sentry/symbolic": "13.7.0", "@sentry/toolkit-core": "workspace:*", diff --git a/packages/cli/patches/@sentry%2Fcore@10.63.0.patch b/packages/cli/patches/@sentry%2Fcore@10.63.0.patch deleted file mode 100644 index db315f63d..000000000 --- a/packages/cli/patches/@sentry%2Fcore@10.63.0.patch +++ /dev/null @@ -1,309 +0,0 @@ -diff --git a/build/cjs/index.js b/build/cjs/index.js -index e05216a98e34459736b64fa1d360878a42b8375d..124e25c91f683feb101f1373d468f030d689f4ed 100644 ---- a/build/cjs/index.js -+++ b/build/cjs/index.js -@@ -2,7 +2,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); - - const errors = require('./tracing/errors.js'); - const utils$2 = require('./tracing/utils.js'); --const idleSpan = require('./tracing/idleSpan.js'); - const sentrySpan = require('./tracing/sentrySpan.js'); - const sentryNonRecordingSpan = require('./tracing/sentryNonRecordingSpan.js'); - const spanstatus = require('./tracing/spanstatus.js'); -@@ -31,7 +30,6 @@ const base = require('./transports/base.js'); - const offline = require('./transports/offline.js'); - const multiplexed = require('./transports/multiplexed.js'); - const integration = require('./integration.js'); --const providerSkip = require('./utils/ai/providerSkip.js'); - const filterKeyValueData = require('./utils/data-collection/filterKeyValueData.js'); - const filterCookies = require('./utils/data-collection/filterCookies.js'); - const filterQueryParams = require('./utils/data-collection/filterQueryParams.js'); -@@ -63,21 +61,8 @@ const breadcrumbs = require('./breadcrumbs.js'); - const functiontostring = require('./integrations/functiontostring.js'); - const eventFilters = require('./integrations/eventFilters.js'); - const linkederrors = require('./integrations/linkederrors.js'); --const moduleMetadata = require('./integrations/moduleMetadata.js'); - const requestdata = require('./integrations/requestdata.js'); --const captureconsole = require('./integrations/captureconsole.js'); --const dedupe = require('./integrations/dedupe.js'); --const extraerrordata = require('./integrations/extraerrordata.js'); --const rewriteframes = require('./integrations/rewriteframes.js'); --const supabase = require('./integrations/supabase.js'); --const zoderrors = require('./integrations/zoderrors.js'); --const thirdPartyErrorsFilter = require('./integrations/third-party-errors-filter.js'); - const console$1 = require('./integrations/console.js'); --const featureFlagsIntegration = require('./integrations/featureFlags/featureFlagsIntegration.js'); --const growthbook = require('./integrations/featureFlags/growthbook.js'); --const conversationId = require('./integrations/conversationId.js'); --const profiling = require('./profiling.js'); --const fetch = require('./fetch.js'); - const feedback = require('./feedback.js'); - const internal = require('./logs/internal.js'); - const publicApi = require('./logs/public-api.js'); -@@ -85,26 +70,10 @@ const consoleIntegration = require('./logs/console-integration.js'); - const internal$1 = require('./metrics/internal.js'); - const publicApi$1 = require('./metrics/public-api.js'); - const consola = require('./integrations/consola.js'); --const index = require('./tracing/vercel-ai/index.js'); - const utils$3 = require('./tracing/ai/utils.js'); - const genAiAttributes = require('./tracing/ai/gen-ai-attributes.js'); --const utils = require('./tracing/vercel-ai/utils.js'); --const constants$7 = require('./tracing/vercel-ai/constants.js'); --const index$7 = require('./tracing/openai/index.js'); --const constants$6 = require('./tracing/openai/constants.js'); --const index$4 = require('./tracing/anthropic-ai/index.js'); --const constants = require('./tracing/anthropic-ai/constants.js'); --const index$6 = require('./tracing/google-genai/index.js'); --const constants$2 = require('./tracing/google-genai/constants.js'); --const index$1 = require('./tracing/langchain/index.js'); - const utils$1 = require('./tracing/langchain/utils.js'); --const constants$4 = require('./tracing/langchain/constants.js'); --const index$5 = require('./tracing/langgraph/index.js'); --const constants$5 = require('./tracing/langgraph/constants.js'); --const spanBuffer = require('./tracing/spans/spanBuffer.js'); --const hasSpanStreamingEnabled = require('./tracing/spans/hasSpanStreamingEnabled.js'); - const spanStreaming = require('./integrations/spanStreaming.js'); --const featureFlags = require('./utils/featureFlags.js'); - const aggregateErrors = require('./utils/aggregate-errors.js'); - const breadcrumbLogLevel = require('./utils/breadcrumb-log-level.js'); - const dsn = require('./utils/dsn.js'); -@@ -147,16 +116,12 @@ const metadata = require('./metadata.js'); - const escapeStringForRegex = require('./vendor/escapeStringForRegex.js'); - const randomSafeContext = require('./utils/randomSafeContext.js'); - const serverRuntimeClient = require('./server-runtime-client.js'); --const trpc = require('./trpc.js'); --const index$8 = require('./integrations/mcp-server/index.js'); - const node = require('./utils/node.js'); - const nodeStackTrace = require('./utils/node-stack-trace.js'); - const vercelWaitUntil = require('./utils/vercelWaitUntil.js'); - const flushIfServerless = require('./utils/flushIfServerless.js'); - const anr = require('./utils/anr.js'); - const timer = require('./utils/timer.js'); --const index$2 = require('./integrations/express/index.js'); --const postgresjs = require('./integrations/postgresjs.js'); - const sql = require('./utils/sql.js'); - const clientPatch = require('./integrations/http/client-patch.js'); - const clientSubscriptions = require('./integrations/http/client-subscriptions.js'); -@@ -166,7 +131,6 @@ const addOutgoingRequestBreadcrumb = require('./integrations/http/add-outgoing-r - const getRequestUrl = require('./integrations/http/get-request-url.js'); - const constants$3 = require('./integrations/http/constants.js'); - const browser = require('./utils/browser.js'); --const embeddings = require('./tracing/langchain/embeddings.js'); - - - -@@ -175,8 +139,6 @@ exports.getCapturedScopesOnSpan = utils$2.getCapturedScopesOnSpan; - exports.markSpanForOtelSourceInference = utils$2.markSpanForOtelSourceInference; - exports.setCapturedScopesOnSpan = utils$2.setCapturedScopesOnSpan; - exports.spanShouldInferOtelSource = utils$2.spanShouldInferOtelSource; --exports.TRACING_DEFAULTS = idleSpan.TRACING_DEFAULTS; --exports.startIdleSpan = idleSpan.startIdleSpan; - exports.SentrySpan = sentrySpan.SentrySpan; - exports.SentryNonRecordingSpan = sentryNonRecordingSpan.SentryNonRecordingSpan; - exports.SPAN_STATUS_ERROR = spanstatus.SPAN_STATUS_ERROR; -@@ -299,9 +261,6 @@ exports.defineIntegration = integration.defineIntegration; - exports.extendIntegration = integration.extendIntegration; - exports.getIntegrationsToSetup = integration.getIntegrationsToSetup; - exports.installedIntegrations = integration.installedIntegrations; --exports._INTERNAL_clearAiProviderSkips = providerSkip._INTERNAL_clearAiProviderSkips; --exports._INTERNAL_shouldSkipAiProviderWrapping = providerSkip._INTERNAL_shouldSkipAiProviderWrapping; --exports._INTERNAL_skipAiProviderWrapping = providerSkip._INTERNAL_skipAiProviderWrapping; - exports._INTERNAL_filterKeyValueData = filterKeyValueData.filterKeyValueData; - exports._INTERNAL_filterCookies = filterCookies.filterCookies; - exports._INTERNAL_filterQueryParams = filterQueryParams.filterQueryParams; -@@ -313,7 +272,6 @@ exports.prepareEvent = prepareEvent.prepareEvent; - exports.createCheckInEnvelope = checkin.createCheckInEnvelope; - exports.hasSpansEnabled = hasSpansEnabled.hasSpansEnabled; - exports.isStreamedBeforeSendSpanCallback = beforeSendSpan.isStreamedBeforeSendSpanCallback; --exports.withStreamedSpan = beforeSendSpan.withStreamedSpan; - exports.isSentryRequestUrl = isSentryRequestUrl.isSentryRequestUrl; - exports.handleCallbackErrors = handleCallbackErrors.handleCallbackErrors; - exports.fmt = parameterize.fmt; -@@ -363,23 +321,8 @@ exports.functionToStringIntegration = functiontostring.functionToStringIntegrati - exports.eventFiltersIntegration = eventFilters.eventFiltersIntegration; - exports.inboundFiltersIntegration = eventFilters.inboundFiltersIntegration; - exports.linkedErrorsIntegration = linkederrors.linkedErrorsIntegration; --exports.moduleMetadataIntegration = moduleMetadata.moduleMetadataIntegration; - exports.requestDataIntegration = requestdata.requestDataIntegration; --exports.captureConsoleIntegration = captureconsole.captureConsoleIntegration; --exports.dedupeIntegration = dedupe.dedupeIntegration; --exports.extraErrorDataIntegration = extraerrordata.extraErrorDataIntegration; --exports.rewriteFramesIntegration = rewriteframes.rewriteFramesIntegration; --exports.instrumentSupabaseClient = supabase.instrumentSupabaseClient; --exports.supabaseIntegration = supabase.supabaseIntegration; --exports.zodErrorsIntegration = zoderrors.zodErrorsIntegration; --exports.thirdPartyErrorFilterIntegration = thirdPartyErrorsFilter.thirdPartyErrorFilterIntegration; - exports.consoleIntegration = console$1.consoleIntegration; --exports.featureFlagsIntegration = featureFlagsIntegration.featureFlagsIntegration; --exports.growthbookIntegration = growthbook.growthbookIntegration; --exports.conversationIdIntegration = conversationId.conversationIdIntegration; --exports.profiler = profiling.profiler; --exports._INTERNAL_getTracingHeadersForFetchRequest = fetch._INTERNAL_getTracingHeadersForFetchRequest; --exports.instrumentFetchRequest = fetch.instrumentFetchRequest; - exports.captureFeedback = feedback.captureFeedback; - exports._INTERNAL_captureLog = internal._INTERNAL_captureLog; - exports._INTERNAL_captureSerializedLog = internal._INTERNAL_captureSerializedLog; -@@ -391,36 +334,12 @@ exports._INTERNAL_captureSerializedMetric = internal$1._INTERNAL_captureSerializ - exports._INTERNAL_flushMetricsBuffer = internal$1._INTERNAL_flushMetricsBuffer; - exports.metrics = publicApi$1; - exports.createConsolaReporter = consola.createConsolaReporter; --exports.addVercelAiProcessors = index.addVercelAiProcessors; --exports.getProviderMetadataAttributes = index.getProviderMetadataAttributes; - exports.getTruncatedJsonString = utils$3.getTruncatedJsonString; - exports.shouldEnableTruncation = utils$3.shouldEnableTruncation; - exports.GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE = genAiAttributes.GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE; - exports.GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE = genAiAttributes.GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE; --exports._INTERNAL_cleanupToolCallSpanContext = utils._INTERNAL_cleanupToolCallSpanContext; --exports._INTERNAL_getSpanContextForToolCallId = utils._INTERNAL_getSpanContextForToolCallId; --exports._INTERNAL_toolCallSpanContextMap = constants$7.toolCallSpanContextMap; --exports.instrumentOpenAiClient = index$7.instrumentOpenAiClient; --exports.OPENAI_INTEGRATION_NAME = constants$6.OPENAI_INTEGRATION_NAME; --exports.instrumentAnthropicAiClient = index$4.instrumentAnthropicAiClient; --exports.ANTHROPIC_AI_INTEGRATION_NAME = constants.ANTHROPIC_AI_INTEGRATION_NAME; --exports.instrumentGoogleGenAIClient = index$6.instrumentGoogleGenAIClient; --exports.GOOGLE_GENAI_INTEGRATION_NAME = constants$2.GOOGLE_GENAI_INTEGRATION_NAME; --exports.createLangChainCallbackHandler = index$1.createLangChainCallbackHandler; - exports._INTERNAL_mergeLangChainCallbackHandler = utils$1._INTERNAL_mergeLangChainCallbackHandler; --exports.LANGCHAIN_INTEGRATION_NAME = constants$4.LANGCHAIN_INTEGRATION_NAME; --exports.instrumentCreateReactAgent = index$5.instrumentCreateReactAgent; --exports.instrumentLangGraph = index$5.instrumentLangGraph; --exports.instrumentStateGraphCompile = index$5.instrumentStateGraphCompile; --exports.LANGGRAPH_INTEGRATION_NAME = constants$5.LANGGRAPH_INTEGRATION_NAME; --exports.SpanBuffer = spanBuffer.SpanBuffer; --exports.hasSpanStreamingEnabled = hasSpanStreamingEnabled.hasSpanStreamingEnabled; - exports.spanStreamingIntegration = spanStreaming.spanStreamingIntegration; --exports._INTERNAL_FLAG_BUFFER_SIZE = featureFlags._INTERNAL_FLAG_BUFFER_SIZE; --exports._INTERNAL_MAX_FLAGS_PER_SPAN = featureFlags._INTERNAL_MAX_FLAGS_PER_SPAN; --exports._INTERNAL_addFeatureFlagToActiveSpan = featureFlags._INTERNAL_addFeatureFlagToActiveSpan; --exports._INTERNAL_copyFlagsFromScopeToEvent = featureFlags._INTERNAL_copyFlagsFromScopeToEvent; --exports._INTERNAL_insertFlagToScope = featureFlags._INTERNAL_insertFlagToScope; - exports.applyAggregateErrorsToEvent = aggregateErrors.applyAggregateErrorsToEvent; - exports.getBreadcrumbLogLevelFromHttpStatusCode = breadcrumbLogLevel.getBreadcrumbLogLevelFromHttpStatusCode; - exports.dsnFromString = dsn.dsnFromString; -@@ -575,8 +494,6 @@ exports._INTERNAL_safeDateNow = randomSafeContext.safeDateNow; - exports._INTERNAL_safeMathRandom = randomSafeContext.safeMathRandom; - exports._INTERNAL_withRandomSafeContext = randomSafeContext.withRandomSafeContext; - exports.ServerRuntimeClient = serverRuntimeClient.ServerRuntimeClient; --exports.trpcMiddleware = trpc.trpcMiddleware; --exports.wrapMcpServerWithSentry = index$8.wrapMcpServerWithSentry; - exports.isNodeEnv = node.isNodeEnv; - exports.loadModule = node.loadModule; - exports.filenameIsInApp = nodeStackTrace.filenameIsInApp; -@@ -587,11 +504,6 @@ exports.flushIfServerless = flushIfServerless.flushIfServerless; - exports.callFrameToStackFrame = anr.callFrameToStackFrame; - exports.watchdogTimer = anr.watchdogTimer; - exports._INTERNAL_safeUnref = timer.safeUnref; --exports.expressErrorHandler = index$2.expressErrorHandler; --exports.patchExpressModule = index$2.patchExpressModule; --exports.setupExpressErrorHandler = index$2.setupExpressErrorHandler; --exports._INTERNAL_sanitizeSqlQuery = postgresjs._sanitizeSqlQuery; --exports.instrumentPostgresJsSql = postgresjs.instrumentPostgresJsSql; - exports._INTERNAL_getSqlQuerySummary = sql.getSqlQuerySummary; - exports.patchHttpModuleClient = clientPatch.patchHttpModuleClient; - exports.getHttpClientSubscriptions = clientSubscriptions.getHttpClientSubscriptions; -@@ -608,5 +520,4 @@ exports.HTTP_ON_SERVER_REQUEST = constants$3.HTTP_ON_SERVER_REQUEST; - exports.getComponentName = browser.getComponentName; - exports.getLocationHref = browser.getLocationHref; - exports.htmlTreeAsString = browser.htmlTreeAsString; --exports.instrumentLangChainEmbeddings = embeddings.instrumentLangChainEmbeddings; - //# sourceMappingURL=index.js.map -diff --git a/build/esm/index.js b/build/esm/index.js -index a90984714e9c91f844c0daa488caadbe20ceb493..dbca96e14eb70c535cd467a240f6990f6c6b0575 100644 ---- a/build/esm/index.js -+++ b/build/esm/index.js -@@ -1,6 +1,5 @@ - export { registerSpanErrorInstrumentation } from './tracing/errors.js'; - export { getCapturedScopesOnSpan, markSpanForOtelSourceInference, setCapturedScopesOnSpan, spanShouldInferOtelSource } from './tracing/utils.js'; --export { TRACING_DEFAULTS, startIdleSpan } from './tracing/idleSpan.js'; - export { SentrySpan } from './tracing/sentrySpan.js'; - export { SentryNonRecordingSpan } from './tracing/sentryNonRecordingSpan.js'; - export { SPAN_STATUS_ERROR, SPAN_STATUS_OK, SPAN_STATUS_UNSET, getSpanStatusFromHttpCode, setHttpStatus } from './tracing/spanstatus.js'; -@@ -29,7 +28,6 @@ export { createTransport } from './transports/base.js'; - export { makeOfflineTransport } from './transports/offline.js'; - export { MULTIPLEXED_TRANSPORT_EXTRA_KEY, makeMultiplexedTransport } from './transports/multiplexed.js'; - export { addIntegration, defineIntegration, extendIntegration, getIntegrationsToSetup, installedIntegrations } from './integration.js'; --export { _INTERNAL_clearAiProviderSkips, _INTERNAL_shouldSkipAiProviderWrapping, _INTERNAL_skipAiProviderWrapping } from './utils/ai/providerSkip.js'; - export { filterKeyValueData as _INTERNAL_filterKeyValueData } from './utils/data-collection/filterKeyValueData.js'; - export { filterCookies as _INTERNAL_filterCookies } from './utils/data-collection/filterCookies.js'; - export { filterQueryParams as _INTERNAL_filterQueryParams } from './utils/data-collection/filterQueryParams.js'; -@@ -38,7 +36,7 @@ export { applyScopeDataToEvent, getCombinedScopeData, mergeScopeData } from './u - export { prepareEvent } from './utils/prepareEvent.js'; - export { createCheckInEnvelope } from './checkin.js'; - export { hasSpansEnabled } from './utils/hasSpansEnabled.js'; --export { isStreamedBeforeSendSpanCallback, withStreamedSpan } from './tracing/spans/beforeSendSpan.js'; -+export { isStreamedBeforeSendSpanCallback } from './tracing/spans/beforeSendSpan.js'; - export { isSentryRequestUrl } from './utils/isSentryRequestUrl.js'; - export { handleCallbackErrors } from './utils/handleCallbackErrors.js'; - export { fmt, parameterize } from './utils/parameterize.js'; -@@ -61,21 +59,8 @@ export { addBreadcrumb } from './breadcrumbs.js'; - export { functionToStringIntegration } from './integrations/functiontostring.js'; - export { eventFiltersIntegration, inboundFiltersIntegration } from './integrations/eventFilters.js'; - export { linkedErrorsIntegration } from './integrations/linkederrors.js'; --export { moduleMetadataIntegration } from './integrations/moduleMetadata.js'; - export { requestDataIntegration } from './integrations/requestdata.js'; --export { captureConsoleIntegration } from './integrations/captureconsole.js'; --export { dedupeIntegration } from './integrations/dedupe.js'; --export { extraErrorDataIntegration } from './integrations/extraerrordata.js'; --export { rewriteFramesIntegration } from './integrations/rewriteframes.js'; --export { instrumentSupabaseClient, supabaseIntegration } from './integrations/supabase.js'; --export { zodErrorsIntegration } from './integrations/zoderrors.js'; --export { thirdPartyErrorFilterIntegration } from './integrations/third-party-errors-filter.js'; - export { consoleIntegration } from './integrations/console.js'; --export { featureFlagsIntegration } from './integrations/featureFlags/featureFlagsIntegration.js'; --export { growthbookIntegration } from './integrations/featureFlags/growthbook.js'; --export { conversationIdIntegration } from './integrations/conversationId.js'; --export { profiler } from './profiling.js'; --export { _INTERNAL_getTracingHeadersForFetchRequest, instrumentFetchRequest } from './fetch.js'; - export { captureFeedback } from './feedback.js'; - export { _INTERNAL_captureLog, _INTERNAL_captureSerializedLog, _INTERNAL_flushLogsBuffer } from './logs/internal.js'; - import * as publicApi from './logs/public-api.js'; -@@ -85,26 +70,10 @@ export { _INTERNAL_captureMetric, _INTERNAL_captureSerializedMetric, _INTERNAL_f - import * as publicApi$1 from './metrics/public-api.js'; - export { publicApi$1 as metrics }; - export { createConsolaReporter } from './integrations/consola.js'; --export { addVercelAiProcessors, getProviderMetadataAttributes } from './tracing/vercel-ai/index.js'; - export { getTruncatedJsonString, shouldEnableTruncation } from './tracing/ai/utils.js'; - export { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE } from './tracing/ai/gen-ai-attributes.js'; --export { _INTERNAL_cleanupToolCallSpanContext, _INTERNAL_getSpanContextForToolCallId } from './tracing/vercel-ai/utils.js'; --export { toolCallSpanContextMap as _INTERNAL_toolCallSpanContextMap } from './tracing/vercel-ai/constants.js'; --export { instrumentOpenAiClient } from './tracing/openai/index.js'; --export { OPENAI_INTEGRATION_NAME } from './tracing/openai/constants.js'; --export { instrumentAnthropicAiClient } from './tracing/anthropic-ai/index.js'; --export { ANTHROPIC_AI_INTEGRATION_NAME } from './tracing/anthropic-ai/constants.js'; --export { instrumentGoogleGenAIClient } from './tracing/google-genai/index.js'; --export { GOOGLE_GENAI_INTEGRATION_NAME } from './tracing/google-genai/constants.js'; --export { createLangChainCallbackHandler } from './tracing/langchain/index.js'; - export { _INTERNAL_mergeLangChainCallbackHandler } from './tracing/langchain/utils.js'; --export { LANGCHAIN_INTEGRATION_NAME } from './tracing/langchain/constants.js'; --export { instrumentCreateReactAgent, instrumentLangGraph, instrumentStateGraphCompile } from './tracing/langgraph/index.js'; --export { LANGGRAPH_INTEGRATION_NAME } from './tracing/langgraph/constants.js'; --export { SpanBuffer } from './tracing/spans/spanBuffer.js'; --export { hasSpanStreamingEnabled } from './tracing/spans/hasSpanStreamingEnabled.js'; - export { spanStreamingIntegration } from './integrations/spanStreaming.js'; --export { _INTERNAL_FLAG_BUFFER_SIZE, _INTERNAL_MAX_FLAGS_PER_SPAN, _INTERNAL_addFeatureFlagToActiveSpan, _INTERNAL_copyFlagsFromScopeToEvent, _INTERNAL_insertFlagToScope } from './utils/featureFlags.js'; - export { applyAggregateErrorsToEvent } from './utils/aggregate-errors.js'; - export { getBreadcrumbLogLevelFromHttpStatusCode } from './utils/breadcrumb-log-level.js'; - export { dsnFromString, dsnToString, makeDsn } from './utils/dsn.js'; -@@ -147,16 +116,12 @@ export { getFilenameToMetadataMap } from './metadata.js'; - export { escapeStringForRegex } from './vendor/escapeStringForRegex.js'; - export { safeDateNow as _INTERNAL_safeDateNow, safeMathRandom as _INTERNAL_safeMathRandom, withRandomSafeContext as _INTERNAL_withRandomSafeContext } from './utils/randomSafeContext.js'; - export { ServerRuntimeClient } from './server-runtime-client.js'; --export { trpcMiddleware } from './trpc.js'; --export { wrapMcpServerWithSentry } from './integrations/mcp-server/index.js'; - export { isNodeEnv, loadModule } from './utils/node.js'; - export { filenameIsInApp, node, nodeStackLineParser } from './utils/node-stack-trace.js'; - export { vercelWaitUntil } from './utils/vercelWaitUntil.js'; - export { flushIfServerless } from './utils/flushIfServerless.js'; - export { callFrameToStackFrame, watchdogTimer } from './utils/anr.js'; - export { safeUnref as _INTERNAL_safeUnref } from './utils/timer.js'; --export { expressErrorHandler, patchExpressModule, setupExpressErrorHandler } from './integrations/express/index.js'; --export { _sanitizeSqlQuery as _INTERNAL_sanitizeSqlQuery, instrumentPostgresJsSql } from './integrations/postgresjs.js'; - export { getSqlQuerySummary as _INTERNAL_getSqlQuerySummary } from './utils/sql.js'; - export { patchHttpModuleClient } from './integrations/http/client-patch.js'; - export { getHttpClientSubscriptions } from './integrations/http/client-subscriptions.js'; -@@ -166,5 +131,4 @@ export { addOutgoingRequestBreadcrumb } from './integrations/http/add-outgoing-r - export { getRequestOptions, getRequestUrl, getRequestUrlFromClientRequest, getRequestUrlObject } from './integrations/http/get-request-url.js'; - export { HTTP_ON_CLIENT_REQUEST, HTTP_ON_SERVER_REQUEST } from './integrations/http/constants.js'; - export { getComponentName, getLocationHref, htmlTreeAsString } from './utils/browser.js'; --export { instrumentLangChainEmbeddings } from './tracing/langchain/embeddings.js'; - //# sourceMappingURL=index.js.map diff --git a/packages/cli/patches/@sentry%2Fnode-core@10.63.0.patch b/packages/cli/patches/@sentry%2Fnode-core@10.63.0.patch deleted file mode 100644 index 88bc631e2..000000000 --- a/packages/cli/patches/@sentry%2Fnode-core@10.63.0.patch +++ /dev/null @@ -1,77 +0,0 @@ -diff --git a/build/cjs/light/index.js b/build/cjs/light/index.js -index 8fb4980846f783f7e352e7abd056bb95b8d86ea6..5514ac17921b832eb31c114e9bdf8999389e7060 100644 ---- a/build/cjs/light/index.js -+++ b/build/cjs/light/index.js -@@ -75,7 +75,6 @@ exports.addEventProcessor = core.addEventProcessor; - exports.addIntegration = core.addIntegration; - exports.bindScopeToEmitter = core.bindScopeToEmitter; - exports.captureCheckIn = core.captureCheckIn; --exports.captureConsoleIntegration = core.captureConsoleIntegration; - exports.captureEvent = core.captureEvent; - exports.captureException = core.captureException; - exports.captureFeedback = core.captureFeedback; -@@ -86,12 +85,9 @@ exports.consoleLoggingIntegration = core.consoleLoggingIntegration; - exports.continueTrace = core.continueTrace; - exports.createConsolaReporter = core.createConsolaReporter; - exports.createTransport = core.createTransport; --exports.dedupeIntegration = core.dedupeIntegration; - exports.endSession = core.endSession; - exports.envToBool = core.envToBool; - exports.eventFiltersIntegration = core.eventFiltersIntegration; --exports.extraErrorDataIntegration = core.extraErrorDataIntegration; --exports.featureFlagsIntegration = core.featureFlagsIntegration; - exports.flush = core.flush; - exports.functionToStringIntegration = core.functionToStringIntegration; - exports.getActiveSpan = core.getActiveSpan; -@@ -105,16 +101,13 @@ exports.getSpanDescendants = core.getSpanDescendants; - exports.getSpanStatusFromHttpCode = core.getSpanStatusFromHttpCode; - exports.getTraceData = core.getTraceData; - exports.getTraceMetaTags = core.getTraceMetaTags; --exports.instrumentSupabaseClient = core.instrumentSupabaseClient; - exports.isEnabled = core.isEnabled; - exports.isInitialized = core.isInitialized; - exports.lastEventId = core.lastEventId; - exports.linkedErrorsIntegration = core.linkedErrorsIntegration; - exports.metrics = core.metrics; - exports.parameterize = core.parameterize; --exports.profiler = core.profiler; - exports.requestDataIntegration = core.requestDataIntegration; --exports.rewriteFramesIntegration = core.rewriteFramesIntegration; - exports.setAttribute = core.setAttribute; - exports.setAttributes = core.setAttributes; - exports.setContext = core.setContext; -@@ -126,7 +119,6 @@ exports.setMeasurement = core.setMeasurement; - exports.setTag = core.setTag; - exports.setTags = core.setTags; - exports.setUser = core.setUser; --exports.spanStreamingIntegration = core.spanStreamingIntegration; - exports.spanToBaggageHeader = core.spanToBaggageHeader; - exports.spanToJSON = core.spanToJSON; - exports.spanToTraceHeader = core.spanToTraceHeader; -@@ -135,15 +127,10 @@ exports.startNewTrace = core.startNewTrace; - exports.startSession = core.startSession; - exports.startSpan = core.startSpan; - exports.startSpanManual = core.startSpanManual; --exports.supabaseIntegration = core.supabaseIntegration; - exports.suppressTracing = core.suppressTracing; --exports.trpcMiddleware = core.trpcMiddleware; - exports.updateSpanName = core.updateSpanName; - exports.withActiveSpan = core.withActiveSpan; - exports.withIsolationScope = core.withIsolationScope; - exports.withMonitor = core.withMonitor; - exports.withScope = core.withScope; --exports.withStreamedSpan = core.withStreamedSpan; --exports.wrapMcpServerWithSentry = core.wrapMcpServerWithSentry; --exports.zodErrorsIntegration = core.zodErrorsIntegration; - //# sourceMappingURL=index.js.map -diff --git a/build/esm/light/index.js b/build/esm/light/index.js -index f9e2a0818600f096bb980db7330338829256416d..a58d0aba64f228b9ced5291797507e8b1dadc111 100644 ---- a/build/esm/light/index.js -+++ b/build/esm/light/index.js -@@ -27,5 +27,5 @@ export { createMissingInstrumentationContext } from '../utils/createMissingInstr - export { makeNodeTransport } from '../transports/http.js'; - export { cron } from '../cron/index.js'; - export { NODE_VERSION } from '../nodeVersion.js'; --export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createConsolaReporter, createTransport, dedupeIntegration, endSession, envToBool, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRequestUrl, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, metrics, parameterize, profiler, requestDataIntegration, rewriteFramesIntegration, setAttribute, setAttributes, setContext, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, trpcMiddleware, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope, withStreamedSpan, wrapMcpServerWithSentry, zodErrorsIntegration } from '@sentry/core'; -+export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureCheckIn, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createConsolaReporter, createTransport, endSession, envToBool, eventFiltersIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRequestUrl, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, metrics, parameterize, requestDataIntegration, setAttribute, setAttributes, setContext, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, suppressTracing, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope } from '@sentry/core'; - //# sourceMappingURL=index.js.map diff --git a/packages/cli/script/bench.ts b/packages/cli/script/bench.ts index f17ff5708..e745c4890 100644 --- a/packages/cli/script/bench.ts +++ b/packages/cli/script/bench.ts @@ -320,7 +320,7 @@ type OpEntry = { async function buildOps(): Promise { // Lazy-import production code so unit tests can import the helpers/fixtures - // without loading all of @sentry/node-core. + // without loading all of @sentry/node. const { detectDsn, detectAllDsns } = await import("../src/lib/dsn/detector.js"); const { findProjectRoot } = await import("../src/lib/dsn/project-root.js"); diff --git a/packages/cli/script/build.ts b/packages/cli/script/build.ts index 918bf82f4..091544820 100644 --- a/packages/cli/script/build.ts +++ b/packages/cli/script/build.ts @@ -154,6 +154,9 @@ async function bundleJs(): Promise { SENTRY_CLIENT_ID_BUILD: JSON.stringify(SENTRY_CLIENT_ID), "process.env.NODE_ENV": JSON.stringify("production"), __SENTRY_DEBUG_ID__: JSON.stringify(PLACEHOLDER_DEBUG_ID), + // Tree-shakes the SDK's runtime module hooks, which can't instrument a + // bundle and would hook the host app in library mode. + __SENTRY_CHANNEL_INJECTION__: "false", }, plugins: [ textImportPlugin, diff --git a/packages/cli/script/bundle.ts b/packages/cli/script/bundle.ts index ad744b31f..86d71dbac 100644 --- a/packages/cli/script/bundle.ts +++ b/packages/cli/script/bundle.ts @@ -311,6 +311,9 @@ const commonDefine: Record = { SENTRY_CLIENT_ID_BUILD: JSON.stringify(SENTRY_CLIENT_ID), "process.env.NODE_ENV": JSON.stringify("production"), __SENTRY_DEBUG_ID__: JSON.stringify(PLACEHOLDER_DEBUG_ID), + // Tree-shakes the SDK's runtime module hooks, which can't instrument a + // bundle and would hook the host app in library mode. + __SENTRY_CHANNEL_INJECTION__: "false", }; // In an ESM bundle, `require`, `__dirname`, and `__filename` don't exist, but diff --git a/packages/cli/script/check-patches.ts b/packages/cli/script/check-patches.ts index 627148c57..c263c0ba0 100644 --- a/packages/cli/script/check-patches.ts +++ b/packages/cli/script/check-patches.ts @@ -225,15 +225,6 @@ for (const [key, patchPath] of Object.entries(patches)) { * `-v`=version alias in `runApplication` so `-v` stays the Sentry CLI's * `--verbose` alias at every position; `--version` remains the version flag. * The stale marker is the original `inputs[0] === "-v"` version check. - * - * @sentry/core and @sentry/node-core: these are tree-shaking patches that strip - * unused re-exports (AI/integration modules) from the build barrels so esbuild - * excludes them from the bundle. They edit bundler-generated barrels and are - * therefore especially prone to silent context drift on a version bump. Each - * marker is a re-export the patch removes (present in the pristine package, - * absent once patched); its presence means the strip did NOT apply and the - * bundle will re-bloat with the AI integrations — re-introducing the dangling - * re-export class the patch guards against. */ const CONTENT_ASSERTIONS: ReadonlyArray<{ /** Installed file to inspect, relative to the resolved node_modules dir. */ @@ -308,30 +299,6 @@ const CONTENT_ASSERTIONS: ReadonlyArray<{ description: "@stricli/core CJS: pluggable `renderHelp` hook missing (`sentry --help --json` will fall back to text help instead of structured JSON)", }, - { - file: "@sentry/core/build/cjs/index.js", - staleMarker: "exports.instrumentOpenAiClient", - description: - "@sentry/core CJS: tree-shaking strip not applied (AI integrations re-bundled)", - }, - { - file: "@sentry/core/build/esm/index.js", - staleMarker: "from './tracing/openai/index.js'", - description: - "@sentry/core ESM: tree-shaking strip not applied (AI integrations re-bundled)", - }, - { - file: "@sentry/node-core/build/cjs/light/index.js", - staleMarker: "exports.dedupeIntegration", - description: - "@sentry/node-core CJS light: integration re-export strip not applied", - }, - { - file: "@sentry/node-core/build/esm/light/index.js", - staleMarker: "dedupeIntegration", - description: - "@sentry/node-core ESM light: integration re-export strip not applied", - }, ]; for (const assertion of CONTENT_ASSERTIONS) { diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 941da517e..937b355da 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -2,7 +2,7 @@ * CLI runner with fast-path dispatch. * * Shell completion (`__complete`) is dispatched before any heavy imports - * to avoid loading `@sentry/node-core` (~280ms). All other commands go through + * to avoid loading `@sentry/node` (~100ms). All other commands go through * the full CLI with telemetry, middleware, and error recovery. * * Extracted from `bin.ts` so the logic is testable and reusable without @@ -26,7 +26,7 @@ async function preloadProjectContext(cwd: string): Promise { // Snapshot env-token host BEFORE anything mutates env.SENTRY_HOST/URL // (the .sentryclirc shim or the default-URL fallback below). Pins the // env-token's trust scope to the user's shell, not a repo-local file. - // Dynamic import: env-token-host chains into db/auth → telemetry → @sentry/node-core + // Dynamic import: env-token-host chains into db/auth → telemetry → @sentry/node const { captureEnvTokenHost } = await import("./lib/env-token-host.js"); captureEnvTokenHost(); @@ -70,12 +70,12 @@ async function preloadProjectContext(cwd: string): Promise { /** * Fast-path: shell completion. * - * Dispatched before importing the full CLI to avoid loading @sentry/node-core, + * Dispatched before importing the full CLI to avoid loading @sentry/node, * @stricli/core, and other heavy dependencies. Only loads the lightweight * completion engine and SQLite cache modules. */ export async function runCompletion(completionArgs: string[]): Promise { - // Disable telemetry so db/index.ts skips the @sentry/node-core lazy-require (~280ms) + // Disable telemetry so db/index.ts skips the @sentry/node lazy-require (~100ms) getEnv().SENTRY_CLI_NO_TELEMETRY = "1"; const { handleComplete } = await import("./lib/complete.js"); handleComplete(completionArgs); @@ -624,7 +624,7 @@ export async function runCli(cliArgs: string[]): Promise { * fuzzy matches and extracts org/project context from the raw argv. */ async function reportUnknownCommand(argv: string[]): Promise { - const Sentry = await import("@sentry/node-core/light"); + const Sentry = await import("@sentry/node"); const { resolveCommandPath } = await import("./lib/introspect.js"); const { routes } = await import("./app.js"); const { getDefaultOrganization } = await import("./lib/db/defaults.js"); @@ -665,7 +665,9 @@ export async function runCli(cliArgs: string[]): Promise { // Fixed message string so all unknown commands group into one Sentry // issue. The per-event detail (which token, suggestions) lives in the // structured context above and is queryable via Discover. - Sentry.captureMessage("unknown_command", "info"); + // captureEvent, not captureMessage: with `attachStacktrace` on, + // captureMessage adds a synthetic exception that marks the session errored. + Sentry.captureEvent({ message: "unknown_command", level: "info" }); } /** Build the command executor by composing error-recovery middlewares. */ diff --git a/packages/cli/src/commands/api.ts b/packages/cli/src/commands/api.ts index b00846361..aec7b19a6 100644 --- a/packages/cli/src/commands/api.ts +++ b/packages/cli/src/commands/api.ts @@ -7,7 +7,7 @@ import { access, readFile } from "node:fs/promises"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import type { SentryContext } from "../context.js"; import { appendSearchParams, rawApiRequest } from "../lib/api-client.js"; import { buildCommand } from "../lib/command.js"; diff --git a/packages/cli/src/commands/cli/feedback.ts b/packages/cli/src/commands/cli/feedback.ts index 2d73780a2..da547149a 100644 --- a/packages/cli/src/commands/cli/feedback.ts +++ b/packages/cli/src/commands/cli/feedback.ts @@ -10,7 +10,7 @@ import { isatty } from "node:tty"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import type { SentryContext } from "../../context.js"; import { buildCommand } from "../../lib/command.js"; import { ConfigError, ValidationError } from "../../lib/errors.js"; diff --git a/packages/cli/src/commands/cli/setup.ts b/packages/cli/src/commands/cli/setup.ts index ca334b96a..879a4b8bd 100644 --- a/packages/cli/src/commands/cli/setup.ts +++ b/packages/cli/src/commands/cli/setup.ts @@ -10,7 +10,7 @@ import { existsSync, unlinkSync } from "node:fs"; import { chmod, copyFile, mkdir, rename, unlink } from "node:fs/promises"; import { dirname, join } from "node:path"; import { isatty } from "node:tty"; -import { captureException } from "@sentry/node-core/light"; +import { captureException } from "@sentry/node"; import type { SentryContext } from "../../context.js"; import { installAgentSkills } from "../../lib/agent-skills.js"; import { assertAutoLoginHostTrusted } from "../../lib/auto-auth.js"; diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 02b2a4fda..0b78f105c 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -18,7 +18,7 @@ */ import path from "node:path"; -import { setTag } from "@sentry/node-core/light"; +import { setTag } from "@sentry/node"; import type { SentryContext } from "../context.js"; import { looksLikePath, parseOrgProjectArg } from "../lib/arg-parsing.js"; import { buildCommand } from "../lib/command.js"; diff --git a/packages/cli/src/commands/log/list.ts b/packages/cli/src/commands/log/list.ts index 1735e7e81..0c5f6a5d6 100644 --- a/packages/cli/src/commands/log/list.ts +++ b/packages/cli/src/commands/log/list.ts @@ -7,7 +7,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import type { SentryContext } from "../../context.js"; import { type LogSortDirection, diff --git a/packages/cli/src/lib/agent-skills.ts b/packages/cli/src/lib/agent-skills.ts index 27f585ed3..63d968fc8 100644 --- a/packages/cli/src/lib/agent-skills.ts +++ b/packages/cli/src/lib/agent-skills.ts @@ -12,7 +12,7 @@ import { accessSync, constants, existsSync, mkdirSync } from "node:fs"; import { rename, rm, writeFile } from "node:fs/promises"; import { basename, dirname, join } from "node:path"; -import { captureException } from "@sentry/node-core/light"; +import { captureException } from "@sentry/node"; import { SKILL_FILES } from "../generated/skill-content.js"; /** Where skills are installed */ diff --git a/packages/cli/src/lib/api/dashboards.ts b/packages/cli/src/lib/api/dashboards.ts index 5e115434a..09ba5532f 100644 --- a/packages/cli/src/lib/api/dashboards.ts +++ b/packages/cli/src/lib/api/dashboards.ts @@ -12,7 +12,7 @@ import { updateOrganizationDashboard, } from "@sentry/api"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { resolveEventsSort } from "@sentry/toolkit-core/events-sort"; import { array, safeParse } from "valibot"; diff --git a/packages/cli/src/lib/api/infrastructure.ts b/packages/cli/src/lib/api/infrastructure.ts index d3f122d13..c3573193d 100644 --- a/packages/cli/src/lib/api/infrastructure.ts +++ b/packages/cli/src/lib/api/infrastructure.ts @@ -21,7 +21,7 @@ import { paginate as paginateFrom, } from "@sentry/toolkit-core/pagination"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { type GenericSchema, safeParse } from "valibot"; import { extractRequiredScopes } from "../api-scope.js"; diff --git a/packages/cli/src/lib/api/logs.ts b/packages/cli/src/lib/api/logs.ts index 2d192387e..e14e0d631 100644 --- a/packages/cli/src/lib/api/logs.ts +++ b/packages/cli/src/lib/api/logs.ts @@ -7,7 +7,7 @@ import { listOrganizationEvents } from "@sentry/api"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { type GenericSchema, safeParse } from "valibot"; import { diff --git a/packages/cli/src/lib/api/teams.ts b/packages/cli/src/lib/api/teams.ts index 0c761f7b8..9f888176d 100644 --- a/packages/cli/src/lib/api/teams.ts +++ b/packages/cli/src/lib/api/teams.ts @@ -11,7 +11,7 @@ import { listProjectTeams as sdkListProjectTeams, } from "@sentry/api"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import type { SentryTeam } from "../../types/index.js"; diff --git a/packages/cli/src/lib/auth-hint.ts b/packages/cli/src/lib/auth-hint.ts index 87ca85afd..b1ce75df6 100644 --- a/packages/cli/src/lib/auth-hint.ts +++ b/packages/cli/src/lib/auth-hint.ts @@ -24,7 +24,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { getActiveEnvVarName, getRawEnvToken, diff --git a/packages/cli/src/lib/db/index.ts b/packages/cli/src/lib/db/index.ts index be549fb1c..db8dcbe87 100644 --- a/packages/cli/src/lib/db/index.ts +++ b/packages/cli/src/lib/db/index.ts @@ -224,7 +224,7 @@ export function getDatabase(): Database { } // Wrap with tracing proxy for automatic query instrumentation. - // Lazy-require telemetry to avoid top-level import of @sentry/node-core (~85ms). + // Lazy-require telemetry to avoid top-level import of @sentry/node (~100ms). // Shell completions set SENTRY_CLI_NO_TELEMETRY=1 to skip this entirely. if (getEnv().SENTRY_CLI_NO_TELEMETRY === "1") { db = rawDb; diff --git a/packages/cli/src/lib/delta-upgrade.ts b/packages/cli/src/lib/delta-upgrade.ts index d2586325d..7ac8fbe0c 100644 --- a/packages/cli/src/lib/delta-upgrade.ts +++ b/packages/cli/src/lib/delta-upgrade.ts @@ -2,7 +2,7 @@ import { join } from "node:path"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { applyPatchChainInMemory, extractStableChain as binpatchExtractStableChain, diff --git a/packages/cli/src/lib/dsn/fs-utils.ts b/packages/cli/src/lib/dsn/fs-utils.ts index d41eeec87..9d568be99 100644 --- a/packages/cli/src/lib/dsn/fs-utils.ts +++ b/packages/cli/src/lib/dsn/fs-utils.ts @@ -6,7 +6,7 @@ import { stat } from "node:fs/promises"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; /** * Check if an error is an expected file system error that should be silently ignored. diff --git a/packages/cli/src/lib/error-reporting.ts b/packages/cli/src/lib/error-reporting.ts index fc8be2699..5bf15ca82 100644 --- a/packages/cli/src/lib/error-reporting.ts +++ b/packages/cli/src/lib/error-reporting.ts @@ -26,7 +26,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { AliasNotFoundError, ArgumentParseError, @@ -491,7 +491,10 @@ function argumentErrorClassName(error: unknown): string { */ export function reportArgumentError(error: unknown, message: string): void { const errorClass = argumentErrorClassName(error); - Sentry.captureMessage("invalid_argument", { + // captureEvent, not captureMessage: with `attachStacktrace` on, + // captureMessage adds a synthetic exception that marks the session errored. + Sentry.captureEvent({ + message: "invalid_argument", level: "info", tags: { "argument_error.class": errorClass }, contexts: { diff --git a/packages/cli/src/lib/formatters/human.ts b/packages/cli/src/lib/formatters/human.ts index 565594723..7f55c8cef 100644 --- a/packages/cli/src/lib/formatters/human.ts +++ b/packages/cli/src/lib/formatters/human.ts @@ -8,7 +8,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import prettyMs from "pretty-ms"; import type { DashboardDetail, diff --git a/packages/cli/src/lib/hex-id-recovery.ts b/packages/cli/src/lib/hex-id-recovery.ts index 3f78448d4..e6d7dadfe 100644 --- a/packages/cli/src/lib/hex-id-recovery.ts +++ b/packages/cli/src/lib/hex-id-recovery.ts @@ -24,7 +24,7 @@ * module only owns the recovery-specific control flow. */ -import { addBreadcrumb } from "@sentry/node-core/light"; +import { addBreadcrumb } from "@sentry/node"; import type { SpanListItem } from "../types/index.js"; import { listLogs, listSpans, queryEvents } from "./api-client.js"; diff --git a/packages/cli/src/lib/init/interactive.ts b/packages/cli/src/lib/init/interactive.ts index 1d3cad659..6c040de37 100644 --- a/packages/cli/src/lib/init/interactive.ts +++ b/packages/cli/src/lib/init/interactive.ts @@ -10,7 +10,7 @@ * `LoggingUI` (CI / npm fallback). */ -import { setTag } from "@sentry/node-core/light"; +import { setTag } from "@sentry/node"; import { WizardError } from "../errors.js"; import { abortIfCancelled, diff --git a/packages/cli/src/lib/init/tools/create-sentry-project.ts b/packages/cli/src/lib/init/tools/create-sentry-project.ts index acd0f6591..af78a27ce 100644 --- a/packages/cli/src/lib/init/tools/create-sentry-project.ts +++ b/packages/cli/src/lib/init/tools/create-sentry-project.ts @@ -7,7 +7,7 @@ * that auto-creates a personal team for eligible members. */ -import { captureException } from "@sentry/node-core/light"; +import { captureException } from "@sentry/node"; import { createProjectWithAutoTeam, createProjectWithDsn, diff --git a/packages/cli/src/lib/init/tools/run-commands.ts b/packages/cli/src/lib/init/tools/run-commands.ts index 64a688375..19d414579 100644 --- a/packages/cli/src/lib/init/tools/run-commands.ts +++ b/packages/cli/src/lib/init/tools/run-commands.ts @@ -1,5 +1,5 @@ import { spawn } from "node:child_process"; -import { addBreadcrumb } from "@sentry/node-core/light"; +import { addBreadcrumb } from "@sentry/node"; import { whichSync } from "../../which.js"; import { DEFAULT_COMMAND_TIMEOUT_MS } from "../constants.js"; import type { RunCommandsPayload, ToolResult } from "../types.js"; diff --git a/packages/cli/src/lib/init/ui/ink-ui.ts b/packages/cli/src/lib/init/ui/ink-ui.ts index 369041f83..62b14f778 100644 --- a/packages/cli/src/lib/init/ui/ink-ui.ts +++ b/packages/cli/src/lib/init/ui/ink-ui.ts @@ -54,7 +54,7 @@ import { ReadStream } from "node:tty"; const _require = createRequire(import.meta.url); -import { addBreadcrumb, setTag } from "@sentry/node-core/light"; +import { addBreadcrumb, setTag } from "@sentry/node"; import { FULL_BANNER_LINES } from "../../banner.js"; import { openBrowser } from "../../browser.js"; import { CLI_VERSION } from "../../constants.js"; diff --git a/packages/cli/src/lib/init/verify-setup.ts b/packages/cli/src/lib/init/verify-setup.ts index e77a4bd22..aad64bded 100644 --- a/packages/cli/src/lib/init/verify-setup.ts +++ b/packages/cli/src/lib/init/verify-setup.ts @@ -14,11 +14,7 @@ import { type ChildProcess, spawn, spawnSync } from "node:child_process"; import { resolve } from "node:path"; -import { - addBreadcrumb, - captureException, - setTag, -} from "@sentry/node-core/light"; +import { addBreadcrumb, captureException, setTag } from "@sentry/node"; import { createSpotlightBuffer } from "@spotlightjs/spotlight/sdk"; import { BUFFER_SIZE, shutdownServer } from "../../commands/local/run.js"; import { buildApp, tryListen } from "../../commands/local/server.js"; diff --git a/packages/cli/src/lib/init/wizard-runner.ts b/packages/cli/src/lib/init/wizard-runner.ts index 8ee7b9de2..bc162d794 100644 --- a/packages/cli/src/lib/init/wizard-runner.ts +++ b/packages/cli/src/lib/init/wizard-runner.ts @@ -19,7 +19,7 @@ import { captureException, getTraceData, setTag, -} from "@sentry/node-core/light"; +} from "@sentry/node"; import { formatAuthHeader } from "../auth-header.js"; import { formatBanner } from "../banner.js"; import { CLI_VERSION } from "../constants.js"; diff --git a/packages/cli/src/lib/interactive-login.ts b/packages/cli/src/lib/interactive-login.ts index cc5d0abb8..948f27000 100644 --- a/packages/cli/src/lib/interactive-login.ts +++ b/packages/cli/src/lib/interactive-login.ts @@ -6,7 +6,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { openBrowser } from "./browser.js"; import { setupCopyKeyListener } from "./clipboard.js"; import { getAccountRow } from "./db/accounts.js"; diff --git a/packages/cli/src/lib/logger.ts b/packages/cli/src/lib/logger.ts index f9f8f409f..569b56c7b 100644 --- a/packages/cli/src/lib/logger.ts +++ b/packages/cli/src/lib/logger.ts @@ -10,8 +10,8 @@ * renders in corrected local time — consola's default renders UTC in the SEA * binaries this CLI ships. * 2. **Sentry.createConsolaReporter()** — auto-forwards all log messages to Sentry - * structured logs via `_INTERNAL_captureLog`. Requires `enableLogs: true` in - * `Sentry.init()` (already enabled in telemetry.ts). + * structured logs via `_INTERNAL_captureLog`. Library mode drops these logs + * in `beforeSendLog` (see telemetry.ts). * * ## Log levels * @@ -59,12 +59,10 @@ * @module */ -import { createRequire } from "node:module"; +import { createConsolaReporter } from "@sentry/node"; import type { ConsolaInstance } from "consola"; import { createConsola } from "consola"; -const _require = createRequire(import.meta.url); - import { getEnv } from "./env.js"; import { formatLogTime } from "./timezone.js"; @@ -277,22 +275,10 @@ export function attachSentryReporter(): void { return; } - // oxlint-disable-next-line sentry-cli/no-silent-catch -- grandfathered silent catch — see #1531; drain by adding log.debug()/log.warn() or re-throwing. - try { - // Dynamic import to avoid pulling in Sentry at module load time. - // The reporter is exported from @sentry/node-core/light (via @sentry/node → @sentry/core). - const Sentry = _require("@sentry/node-core/light") as { - createConsolaReporter: (options?: Record) => { - log: (logObj: unknown) => void; - }; - }; - - const sentryReporter = Sentry.createConsolaReporter(); - logger.addReporter(sentryReporter); - sentryReporterAttached = true; - } catch { - // Sentry not available (e.g., telemetry disabled) — continue without reporter - } + // Imported statically: the bundler leaves a runtime `require()` unresolved, + // which would either fail or load a host application's `@sentry/node`. + logger.addReporter(createConsolaReporter()); + sentryReporterAttached = true; } /** diff --git a/packages/cli/src/lib/oauth.ts b/packages/cli/src/lib/oauth.ts index 5e1373a81..4fa143a3e 100644 --- a/packages/cli/src/lib/oauth.ts +++ b/packages/cli/src/lib/oauth.ts @@ -37,7 +37,6 @@ import { } from "./errors.js"; import { logger } from "./logger.js"; import { normalizeHttpOrigin } from "./sentry-urls.js"; -import { withHttpSpan } from "./telemetry.js"; import { getActiveTokenHost } from "./token-host.js"; /** @@ -272,105 +271,101 @@ function assertRefreshHostTrusted(refreshUrl: string): string { * @param scope - Space-joined scope string to request. Defaults to the full * {@link SCOPES} set. Use {@link resolveOAuthScopeString} to build it. */ -function requestDeviceCode(scope: string = SCOPES) { +async function requestDeviceCode(scope: string = SCOPES) { const clientId = getClientId(); - return withHttpSpan("POST", "/oauth/device/code/", async () => { - const response = await fetchWithConnectionError( - `${getSentryUrl()}/oauth/device/code/`, - { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: deviceCodeRequestBody(clientId, scope), - }, - ); + const response = await fetchWithConnectionError( + `${getSentryUrl()}/oauth/device/code/`, + { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: deviceCodeRequestBody(clientId, scope), + }, + ); - if (!response.ok) { - const errorText = await response.text(); - throw new ApiError( - "Failed to initiate device flow", - response.status, - errorText, - "/oauth/device/code/", - ); - } + if (!response.ok) { + const errorText = await response.text(); + throw new ApiError( + "Failed to initiate device flow", + response.status, + errorText, + "/oauth/device/code/", + ); + } - let data: unknown; - try { - data = await response.json(); - } catch (parseError) { - logger.debug("Non-JSON response from device code endpoint", parseError); - throw new ApiError( - "Invalid response from device authorization endpoint", - response.status, - "The server returned a non-JSON response body.", - "/oauth/device/code/", - ); - } + let data: unknown; + try { + data = await response.json(); + } catch (parseError) { + logger.debug("Non-JSON response from device code endpoint", parseError); + throw new ApiError( + "Invalid response from device authorization endpoint", + response.status, + "The server returned a non-JSON response body.", + "/oauth/device/code/", + ); + } - const result = safeParse(DeviceCodeResponseSchema, data); - if (!result.success) { - throw new ApiError( - "Invalid response from device authorization endpoint", - response.status, - result.issues.map((i) => i.message).join(", "), - "/oauth/device/code/", - ); - } + const result = safeParse(DeviceCodeResponseSchema, data); + if (!result.success) { + throw new ApiError( + "Invalid response from device authorization endpoint", + response.status, + result.issues.map((i) => i.message).join(", "), + "/oauth/device/code/", + ); + } - return result.output; - }); + return result.output; } /** * Poll Sentry's token endpoint for the access token */ -function pollForToken(deviceCode: string): Promise { - return withHttpSpan("POST", "/oauth/token/", async () => { - const response = await fetchWithConnectionError( - `${getSentryUrl()}/oauth/token/`, - { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: deviceTokenRequestBody(getClientId(), deviceCode), - }, - ); - - let data: unknown; - try { - data = await response.json(); - } catch (parseError) { - logger.debug("Non-JSON response from token endpoint", parseError); - throw new ApiError( - "Unexpected response from token endpoint", - response.status, - "The server returned a non-JSON response body (possible proxy or CDN issue).", - "/oauth/token/", - ); - } - - // Try to parse as success response first - const tokenResult = safeParse(TokenResponseSchema, data); - if (tokenResult.success) { - return tokenResult.output; - } - - // Try to parse as error response - const errorResult = safeParse(TokenErrorResponseSchema, data); - if (errorResult.success) { - throw new DeviceFlowError( - errorResult.output.error, - errorResult.output.error_description, - ); - } +async function pollForToken(deviceCode: string): Promise { + const response = await fetchWithConnectionError( + `${getSentryUrl()}/oauth/token/`, + { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: deviceTokenRequestBody(getClientId(), deviceCode), + }, + ); - // If neither schema matches, throw a generic error + let data: unknown; + try { + data = await response.json(); + } catch (parseError) { + logger.debug("Non-JSON response from token endpoint", parseError); throw new ApiError( "Unexpected response from token endpoint", response.status, - JSON.stringify(data), + "The server returned a non-JSON response body (possible proxy or CDN issue).", "/oauth/token/", ); - }); + } + + // Try to parse as success response first + const tokenResult = safeParse(TokenResponseSchema, data); + if (tokenResult.success) { + return tokenResult.output; + } + + // Try to parse as error response + const errorResult = safeParse(TokenErrorResponseSchema, data); + if (errorResult.success) { + throw new DeviceFlowError( + errorResult.output.error, + errorResult.output.error_description, + ); + } + + // If neither schema matches, throw a generic error + throw new ApiError( + "Unexpected response from token endpoint", + response.status, + JSON.stringify(data), + "/oauth/token/", + ); } type PollResult = @@ -541,80 +536,78 @@ export async function setApiToken( } /** Refresh an access token using a refresh token. */ -export function refreshAccessToken( +export async function refreshAccessToken( refreshToken: string, options: { credentialHost: string }, ): Promise { const clientId = getClientId(); const credentialHost = assertRefreshHostTrusted(options.credentialHost); - return withHttpSpan("POST", "/oauth/token/", async () => { - const response = await fetchWithConnectionError( - `${credentialHost}/oauth/token/`, - { - method: "POST", - // Never replay a refresh credential to a server-selected destination. - redirect: "error", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: new URLSearchParams({ - client_id: clientId, - grant_type: "refresh_token", - refresh_token: refreshToken, - }), - }, - true, - ); + const response = await fetchWithConnectionError( + `${credentialHost}/oauth/token/`, + { + method: "POST", + // Never replay a refresh credential to a server-selected destination. + redirect: "error", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: new URLSearchParams({ + client_id: clientId, + grant_type: "refresh_token", + refresh_token: refreshToken, + }), + }, + true, + ); - if (!response.ok) { - let rejected = false; - try { - const errorResult = safeParse( - TokenErrorResponseSchema, - await response.json(), - ); - rejected = - errorResult.success && errorResult.output.error === "invalid_grant"; - } catch (error) { - logger.debug("Failed to parse token refresh error response", error); - } - if (rejected) { - throw new AuthError( - "expired", - "Session expired because the refresh credential was rejected. Run 'sentry auth login' to re-authenticate.", - ); - } - throw new ApiError( - "Token refresh failed", - response.status, - "The refresh endpoint returned an unexpected failure.", - "/oauth/token/", + if (!response.ok) { + let rejected = false; + try { + const errorResult = safeParse( + TokenErrorResponseSchema, + await response.json(), ); + rejected = + errorResult.success && errorResult.output.error === "invalid_grant"; + } catch (error) { + logger.debug("Failed to parse token refresh error response", error); } - - let data: unknown; - try { - data = await response.json(); - } catch (parseError) { - logger.debug("Non-JSON response from token refresh endpoint", parseError); - throw new ApiError( - "Unexpected response from token refresh endpoint", - response.status, - "The server returned a non-JSON response body (possible proxy or CDN issue).", - "/oauth/token/", + if (rejected) { + throw new AuthError( + "expired", + "Session expired because the refresh credential was rejected. Run 'sentry auth login' to re-authenticate.", ); } + throw new ApiError( + "Token refresh failed", + response.status, + "The refresh endpoint returned an unexpected failure.", + "/oauth/token/", + ); + } + + let data: unknown; + try { + data = await response.json(); + } catch (parseError) { + logger.debug("Non-JSON response from token refresh endpoint", parseError); + throw new ApiError( + "Unexpected response from token refresh endpoint", + response.status, + "The server returned a non-JSON response body (possible proxy or CDN issue).", + "/oauth/token/", + ); + } - const result = safeParse(TokenResponseSchema, data); + const result = safeParse(TokenResponseSchema, data); - if (!result.success) { - throw new ApiError( - "Invalid response from token refresh endpoint", - response.status, - result.issues.map((i) => i.message).join(", "), - "/oauth/token/", - ); - } + if (!result.success) { + throw new ApiError( + "Invalid response from token refresh endpoint", + response.status, + result.issues.map((i) => i.message).join(", "), + "/oauth/token/", + ); + } - return result.output; - }); + return result.output; } diff --git a/packages/cli/src/lib/sdk-invoke.ts b/packages/cli/src/lib/sdk-invoke.ts index 898b6ec01..27354f065 100644 --- a/packages/cli/src/lib/sdk-invoke.ts +++ b/packages/cli/src/lib/sdk-invoke.ts @@ -204,7 +204,7 @@ const ANSI_RE = /\x1b\[[0-9;]*m/g; async function flushTelemetry(): Promise { // oxlint-disable-next-line sentry-cli/no-silent-catch -- grandfathered silent catch — see #1531; drain by adding log.debug()/log.warn() or re-throwing. try { - const Sentry = await import("@sentry/node-core/light"); + const Sentry = await import("@sentry/node"); const client = Sentry.getClient(); if (client) { await client.flush(3000); diff --git a/packages/cli/src/lib/sentry-client.ts b/packages/cli/src/lib/sentry-client.ts index 9c6dd26c3..e3543441a 100644 --- a/packages/cli/src/lib/sentry-client.ts +++ b/packages/cli/src/lib/sentry-client.ts @@ -10,7 +10,7 @@ import { setTimeout as sleepMs } from "node:timers/promises"; import type { SentryClient } from "@sentry/api"; -import { getTraceData } from "@sentry/node-core/light"; +import { getTraceData } from "@sentry/node"; import { computeInvalidationPrefixes } from "@sentry/toolkit-core/response-cache"; import { formatAuthHeader, @@ -59,7 +59,7 @@ import { isRetryableMethod, } from "./retry-policy.js"; import { normalizeHttpOrigin, normalizeOrigin } from "./sentry-urls.js"; -import { withTracingSpan } from "./telemetry.js"; +import { isManualHttpTracing, withTracingSpan } from "./telemetry.js"; import { parseSntrysClaim } from "./token-claims.js"; import { isHostTrustedForClaim, @@ -227,16 +227,14 @@ function prepareHeaders( headers.set("User-Agent", getUserAgent()); } - // Inject distributed tracing headers to connect CLI spans to backend traces. - // Manual injection is required because Bun's fetch doesn't fire undici - // diagnostics channels, so the SDK's nativeNodeFetchIntegration cannot work. - // When telemetry is disabled, getTraceData() returns {} — no headers injected. - const traceData = getTraceData(); - if (traceData["sentry-trace"]) { - headers.set("sentry-trace", traceData["sentry-trace"]); - } - if (traceData.baggage) { - headers.set("baggage", traceData.baggage); + if (isManualHttpTracing()) { + const traceData = getTraceData(); + if (traceData["sentry-trace"]) { + headers.set("sentry-trace", traceData["sentry-trace"]); + } + if (traceData.baggage) { + headers.set("baggage", traceData.baggage); + } } // Inject user-configured custom headers for self-hosted proxies (IAP, @@ -519,7 +517,7 @@ function handleFetchError( return { action: "retry", delayMs: backoffDelayMs(attempt, MAX_BACKOFF_MS) }; } -/** Extract the URL pathname for span naming */ +/** Extract the URL pathname for logging and cache keys */ function extractUrlPath(input: Request | string | URL): string { const raw = extractInputUrl(input); // oxlint-disable-next-line sentry-cli/no-silent-catch -- grandfathered silent catch — see #1531; drain by adding log.debug()/log.warn() or re-throwing. @@ -772,7 +770,6 @@ async function fetchWithRetry({ * - 401 handling: force-refreshes the token and retries once (any method) * - Jittered exponential backoff between retries * - User-Agent header for API analytics - * - Automatic HTTP span tracing for every request * * Cache is checked first — on a hit, auth refresh, timeout, and retry logic are * all skipped. On a miss or for non-GET methods, the full authenticated flow runs @@ -796,7 +793,7 @@ type AuthenticatedFetchOptions = { function createAuthenticatedFetch( options: AuthenticatedFetchOptions = {}, ): (input: Request | string | URL, init?: RequestInit) => Promise { - return function authenticatedFetch( + return async function authenticatedFetch( input: Request | string | URL, init?: RequestInit, ): Promise { @@ -815,82 +812,83 @@ function createAuthenticatedFetch( init?.method ?? (input instanceof Request ? input.method : "GET"); const urlPath = extractUrlPath(input); - return withTracingSpan( - `${method} ${urlPath}`, - "http.client", - async (span) => { - const fullUrl = extractInputUrl(input); - const startTime = performance.now(); - - // Check cache before auth/retry for GET requests. - // Uses current token (no refresh) so lookups are fast but Vary-correct. - const credential = options.credential ?? getCredentialContext(); - if (!credential) { - await refreshToken(); - throw new Error( - "Authentication state was not available after refresh", - ); - } - // A synthetic HTTP cache response has no validated final-origin or - // credential provenance. Discovery must obtain both from the network. - const lookup = options.validatedRedirects - ? undefined - : await tryCacheLookup( - method, - fullUrl, - authHeaders(credential.token), - credential.identity, - ); - if (lookup?.kind === "hit") { - span.setAttribute( - "http.response.status_code", - lookup.response.status, + const request = async (): Promise => { + const fullUrl = extractInputUrl(input); + const startTime = performance.now(); + + // Check cache before auth/retry for GET requests. + // Uses current token (no refresh) so lookups are fast but Vary-correct. + const credential = options.credential ?? getCredentialContext(); + if (!credential) { + await refreshToken(); + throw new Error("Authentication state was not available after refresh"); + } + // A synthetic HTTP cache response has no validated final-origin or + // credential provenance. Discovery must obtain both from the network. + const lookup = options.validatedRedirects + ? undefined + : await tryCacheLookup( + method, + fullUrl, + authHeaders(credential.token), + credential.identity, ); + if (lookup?.kind === "hit") { + log.debug( + `${method} ${urlPath} → ${lookup.response.status} (cache hit, ${(performance.now() - startTime).toFixed(0)}ms)`, + ); + return lookup.response; + } + + const retryContext: RetryContext = { + input, + init, + method, + fullUrl, + credential, + validatedRedirects: options.validatedRedirects === true, + idempotent: options.idempotent === true, + responseBodyMode: + method.toUpperCase() !== "GET" + ? "stream" + : ((input instanceof Request + ? sdkResponseBodyModes.get(input) + : undefined) ?? + (options.bufferResponseBody ? "buffer" : "stream")), + }; + let response = await fetchWithRetry({ + ...retryContext, + conditionalHeaders: lookup?.conditionalHeaders, + }); + if (lookup?.kind === "stale" && response.status === 304) { + const revalidated = await lookup.revalidate(response); + if (revalidated) { log.debug( - `${method} ${urlPath} → ${lookup.response.status} (cache hit, ${(performance.now() - startTime).toFixed(0)}ms)`, + `${method} ${urlPath} → 304 (revalidated cache entry, ${(performance.now() - startTime).toFixed(0)}ms)`, ); - return lookup.response; + return revalidated; } + // A 304 the entry cannot use has no body; fetch it unconditionally. + response = await fetchWithRetry(retryContext); + } + log.debug( + `${method} ${urlPath} → ${response.status} (${(performance.now() - startTime).toFixed(0)}ms)`, + ); + return response; + }; - const retryContext: RetryContext = { - input, - init, - method, - fullUrl, - credential, - validatedRedirects: options.validatedRedirects === true, - idempotent: options.idempotent === true, - responseBodyMode: - method.toUpperCase() !== "GET" - ? "stream" - : ((input instanceof Request - ? sdkResponseBodyModes.get(input) - : undefined) ?? - (options.bufferResponseBody ? "buffer" : "stream")), - }; - let response = await fetchWithRetry({ - ...retryContext, - conditionalHeaders: lookup?.conditionalHeaders, - }); - if (lookup?.kind === "stale" && response.status === 304) { - const revalidated = await lookup.revalidate(response); - if (revalidated) { - span.setAttribute("http.response.status_code", revalidated.status); - log.debug( - `${method} ${urlPath} → 304 (revalidated cache entry, ${(performance.now() - startTime).toFixed(0)}ms)`, - ); - return revalidated; - } - // A 304 the entry cannot use has no body; fetch it unconditionally. - response = await fetchWithRetry(retryContext); - } + if (!isManualHttpTracing()) { + return await request(); + } + return await withTracingSpan( + `${method} ${urlPath}`, + "http.client", + async (span) => { + const response = await request(); span.setAttribute("http.response.status_code", response.status); if (!response.ok) { span.setStatus({ code: 2, message: `${response.status}` }); } - log.debug( - `${method} ${urlPath} → ${response.status} (${(performance.now() - startTime).toFixed(0)}ms)`, - ); return response; }, { "http.request.method": method, "url.path": urlPath }, diff --git a/packages/cli/src/lib/telemetry.ts b/packages/cli/src/lib/telemetry.ts index fa1ec7fe9..b3ddc694a 100644 --- a/packages/cli/src/lib/telemetry.ts +++ b/packages/cli/src/lib/telemetry.ts @@ -12,7 +12,7 @@ import { chmodSync, statSync } from "node:fs"; import { createRequire } from "node:module"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; const _require = createRequire(import.meta.url); @@ -271,9 +271,7 @@ export async function withTelemetry( * * @internal Exported for testing */ -export function createBeforeExitHandler( - client: Sentry.LightNodeClient, -): () => void { +export function createBeforeExitHandler(client: Sentry.NodeClient): () => void { let isFlushing = false; return () => { if (isFlushing) { @@ -425,7 +423,14 @@ const LIBRARY_EXCLUDED_INTEGRATIONS = new Set([ "NodeFetch", // diagnostics_channel + trace headers "FunctionToString", // wraps Function.prototype.toString "ChildProcess", // monitors child processes + "WorkerThreads", // diagnostics_channel on the host's worker threads "NodeRuntimeMetrics", // runtime metrics timer would keep host event loop alive + // Framework error handlers subscribe to the host's framework channels + "Express", + "Fastify", + "Hapi", + "Hono", + "Koa", ]); /** @@ -450,6 +455,18 @@ const hasGetSystemErrorMap = (() => { /** Current beforeExit handler, tracked so it can be replaced on re-init */ let currentBeforeExitHandler: (() => void) | null = null; +let manualHttpTracing = false; + +/** + * Whether API requests need CLI-made `http.client` spans and trace headers. + * Library mode excludes the SDK's Http/NodeFetch integrations because they + * would also trace the host's requests, and Bun's fetch doesn't fire the + * undici diagnostics channels they listen on. + */ +export function isManualHttpTracing(): boolean { + return manualHttpTracing; +} + /** Match all SaaS regional URLs (us.sentry.io, de.sentry.io, o1234.ingest.us.sentry.io, etc.) */ const SENTRY_SAAS_SUBDOMAIN_RE = /^https:\/\/[^/]*\.sentry\.io(\/|$)/; @@ -524,9 +541,11 @@ function setAgentTags(info: AgentInfo): void { export function initSentry( enabled: boolean, options?: { libraryMode?: boolean }, -): Sentry.LightNodeClient | undefined { +): Sentry.NodeClient | undefined { const libraryMode = options?.libraryMode ?? false; const environment = getCliEnvironment(); + manualHttpTracing = + libraryMode || typeof process.versions.bun !== "undefined"; /** * Ensure frame paths are absolute so Sentry's symbolicator can match them. @@ -591,6 +610,18 @@ export function initSentry( const client = Sentry.init({ dsn: SENTRY_CLI_DSN, enabled, + // The tracing integrations instrument database, framework, and AI + // libraries through diagnostics channels, which in library mode belong + // to the host application. + ...(libraryMode && { + defaultIntegrations: Sentry.getDefaultIntegrationsWithoutPerformance(), + }), + // Keep v10's transaction model: dashboards and alerts rely on scope tags + // on transactions, and beforeSendTransaction scrubs server_name. + traceLifecycle: "static", + // Shipped bundles strip these hooks via the `__SENTRY_CHANNEL_INJECTION__` + // build define; this keeps unbundled runs (dev, tests) consistent. + enableRuntimeChannelInjection: false, // Compress outgoing envelopes with zstd (level 3) instead of gzip — // smaller payloads, faster compress/decompress on both sides. // Automatic gzip fallback when running on Node < 22.15, where @@ -608,8 +639,7 @@ export function initSentry( // The zstd-transport reads `caCerts` and passes it as `ca:` to // `http.request()`, and the SDK's fallback `makeNodeTransport` does the same. transportOptions: { caCerts: getCustomCaCerts() }, - // Keep default integrations but filter out ones that add overhead without benefit. - // Important: Don't use defaultIntegrations: false as it may break debug ID support. + // Filter out default integrations that add overhead without benefit. // NodeSystemError is excluded on runtimes missing util.getSystemErrorMap (Bun) — CLI-K1. // Library mode uses the extended exclusion set to avoid polluting the host process. integrations: (defaults) => { @@ -643,10 +673,9 @@ export function initSentry( return filtered; }, environment, - // Enable Sentry structured logs for non-exception telemetry (e.g., unexpected input warnings). - // Disabled when telemetry is off or in library mode — the SDK registers - // beforeExit handlers for log flushing that keep the event loop alive. - enableLogs: enabled && !libraryMode, + // v11 removed `enableLogs` and always captures `Sentry.logger.*` calls. + // Library mode never sent logs in v10, so keep dropping them there. + ...(libraryMode && { beforeSendLog: () => null }), // Disable client reports when telemetry is off or in library mode — the SDK // registers a setInterval + beforeExit handler that keep the event loop alive. ...((libraryMode || !enabled) && { sendClientReports: false }), @@ -694,6 +723,14 @@ export function initSentry( }, }); + // v11 attaches the client to the current scope before switching to the + // AsyncLocalStorage context strategy. When init runs inside a still-pending + // pre-init span (as in the CLI's middleware chain), that scope is lost in + // the switch and every later capture finds no client. + if (client) { + Sentry.setCurrentClient(client); + } + // Always remove our own previous handler on re-init. if (currentBeforeExitHandler) { process.removeListener("beforeExit", currentBeforeExitHandler); @@ -704,15 +741,15 @@ export function initSentry( const isBun = typeof process.versions.bun !== "undefined"; const runtime = isBun ? "bun" : "node"; - // LightNodeClient hardcodes runtime to { name: 'node' }. Override it so - // events carry the correct runtime when running as a compiled Bun binary. + // NodeClient defaults runtime to { name: 'node' }. Override it so + // events carry the correct runtime when the npm package runs under Bun. const opts = client.getOptions(); opts.runtime = { name: runtime, version: isBun ? process.versions.bun : process.version, }; - // Tag whether running as bun binary or node (npm package). + // Tag whether running under Bun or Node. // Kept alongside the SDK's promoted 'runtime' tag for explicit signaling // and backward compatibility with existing dashboards/alerts. Sentry.setTag("cli.runtime", runtime); @@ -1009,7 +1046,7 @@ export function createWizardPromptTelemetry(): WizardPromptTelemetry { * to OK on success or Error on failure. * * Use this generic helper for custom operations, or use the specialized - * helpers (withHttpSpan, withDbSpan, withFsSpan, withSerializeSpan) for + * helpers (withDbSpan, withFsSpan, withSerializeSpan) for * common operation types. * * @param name - Span name (e.g., "scanDirectory", "findProjectRoot") @@ -1100,28 +1137,6 @@ export function withTracingSpan( ); } -/** - * Wrap an HTTP request with a span for tracing. - * - * Creates a child span under the current active span to track - * HTTP request duration and status. - * - * @param method - HTTP method (GET, POST, etc.) - * @param url - Request URL or path - * @param fn - The async function that performs the HTTP request - * @returns The result of the function - */ -export function withHttpSpan( - method: string, - url: string, - fn: () => Promise, -): Promise { - return withTracing(`${method} ${url}`, "http.client", fn, { - "http.request.method": method, - "url.path": url, - }); -} - /** * Wrap a database operation with a span for tracing. * diff --git a/packages/cli/src/lib/telemetry/zstd-transport.ts b/packages/cli/src/lib/telemetry/zstd-transport.ts index f78cb5ebd..9452b937c 100644 --- a/packages/cli/src/lib/telemetry/zstd-transport.ts +++ b/packages/cli/src/lib/telemetry/zstd-transport.ts @@ -12,7 +12,7 @@ * when the transport is created, every envelope uses zstd; otherwise * every envelope uses gzip. * - * This mirrors `@sentry/node-core/transports/http.js` `makeNodeTransport` + * This mirrors `@sentry/node/transports/http.js` `makeNodeTransport` * — URL parsing, `no_proxy` handling, proxy agent, CA certs, keepAlive, * IPv6 hostname unwrapping, rate-limit response header normalization — * but swaps out the gzip-via-stream-pipe for an async one-shot compress @@ -45,10 +45,10 @@ import { type TransportRequest, type TransportRequestExecutor, } from "@sentry/core"; -import { - makeNodeTransport, - type NodeTransportOptions, -} from "@sentry/node-core/light"; +import { makeNodeTransport } from "@sentry/node"; + +/** `@sentry/node` v11 no longer re-exports this type from its entry point. */ +type NodeTransportOptions = Parameters[0]; /** Codec actually applied to a given envelope. */ type AppliedEncoding = "zstd" | "gzip" | "none"; @@ -155,7 +155,7 @@ export function makeCompressedTransport( * no_proxy. When true, the caller falls back to the SDK's default * transport (which handles CONNECT tunneling). * - * Mirrors `@sentry/node-core/transports/http.js` `applyNoProxyOption`'s + * Mirrors `@sentry/node/transports/http.js` `applyNoProxyOption`'s * proxy-resolution priority: * - http → `options.proxy` | `http_proxy` * - https → `options.proxy` | `https_proxy` | `http_proxy` diff --git a/packages/cli/src/lib/version-check.ts b/packages/cli/src/lib/version-check.ts index f574380ce..d3dd708d4 100644 --- a/packages/cli/src/lib/version-check.ts +++ b/packages/cli/src/lib/version-check.ts @@ -8,7 +8,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- Sentry SDK recommends namespace import -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { compare as semverCompare } from "semver"; import type { UpgradeSource } from "./binary.js"; import { CLI_VERSION } from "./constants.js"; diff --git a/packages/cli/test/commands/api.test.ts b/packages/cli/test/commands/api.test.ts index 80f8c8649..6f90ee7a7 100644 --- a/packages/cli/test/commands/api.test.ts +++ b/packages/cli/test/commands/api.test.ts @@ -8,7 +8,7 @@ import { writeFile } from "node:fs/promises"; import { Readable } from "node:stream"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; import { apiCommand, diff --git a/packages/cli/test/commands/event/view.test.ts b/packages/cli/test/commands/event/view.test.ts index ae41ad7d5..f64dbd4c2 100644 --- a/packages/cli/test/commands/event/view.test.ts +++ b/packages/cli/test/commands/event/view.test.ts @@ -6,7 +6,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; import { collectEventIds, diff --git a/packages/cli/test/e2e/completion.test.ts b/packages/cli/test/e2e/completion.test.ts index 68e51d6c3..8c67485dc 100644 --- a/packages/cli/test/e2e/completion.test.ts +++ b/packages/cli/test/e2e/completion.test.ts @@ -2,7 +2,7 @@ * Completion Latency E2E Tests * * Spawns the actual CLI binary with `__complete` args and measures - * wall-clock latency. The completion fast-path skips @sentry/node-core, + * wall-clock latency. The completion fast-path skips @sentry/node, * Stricli, and middleware — these tests catch regressions that would * re-introduce heavy imports into the completion path. * diff --git a/packages/cli/test/e2e/local.test.ts b/packages/cli/test/e2e/local.test.ts index f28042ec6..baa9dc7fb 100644 --- a/packages/cli/test/e2e/local.test.ts +++ b/packages/cli/test/e2e/local.test.ts @@ -747,7 +747,7 @@ describe("Local daemon E2E", () => { "--input-type=module", "-e", `import * as Sentry from '@sentry/node'; - Sentry.init({enableLogs: true, tracesSampleRate: 1}); + Sentry.init({tracesSampleRate: 1}); const id = Sentry.captureException(new Error('Local real SDK event')); console.error('SDK_EVENT:' + id); await Sentry.flush(2000); diff --git a/packages/cli/test/fixtures/bench/helpers.ts b/packages/cli/test/fixtures/bench/helpers.ts index cd9f486de..6ddbcf9d9 100644 --- a/packages/cli/test/fixtures/bench/helpers.ts +++ b/packages/cli/test/fixtures/bench/helpers.ts @@ -149,7 +149,7 @@ export async function withBenchDb( fn: (configDir: string) => Promise, ): Promise { // Import lazily — importing `src/lib/db/index.js` has non-trivial side - // effects (loads bun:sqlite, @sentry/node-core via createTracedDatabase). + // effects (loads bun:sqlite, @sentry/node via createTracedDatabase). const { closeDatabase } = await import("../../../src/lib/db/index.js"); const saved = process.env.SENTRY_CONFIG_DIR; diff --git a/packages/cli/test/fixtures/local-agent-server.ts b/packages/cli/test/fixtures/local-agent-server.ts index 0970c5dd2..4cb6724b1 100644 --- a/packages/cli/test/fixtures/local-agent-server.ts +++ b/packages/cli/test/fixtures/local-agent-server.ts @@ -105,7 +105,6 @@ export function createLocalAgentServer() { function startServer(): void { init({ dsn: process.env.SENTRY_DSN, - enableLogs: true, tracesSampleRate: 1, }); diff --git a/packages/cli/test/lib/api-client.coverage.test.ts b/packages/cli/test/lib/api-client.coverage.test.ts index a37b63eaf..feecfebdc 100644 --- a/packages/cli/test/lib/api-client.coverage.test.ts +++ b/packages/cli/test/lib/api-client.coverage.test.ts @@ -7,7 +7,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { number, object, string } from "valibot"; import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; import { resolveEventInOrg } from "../../src/lib/api/events.js"; diff --git a/packages/cli/test/lib/api-client.multiregion.test.ts b/packages/cli/test/lib/api-client.multiregion.test.ts index 959df45be..85487c8d1 100644 --- a/packages/cli/test/lib/api-client.multiregion.test.ts +++ b/packages/cli/test/lib/api-client.multiregion.test.ts @@ -6,7 +6,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; import { findProjectByDsnKey, diff --git a/packages/cli/test/lib/api/projects.test.ts b/packages/cli/test/lib/api/projects.test.ts index 4d33f57a2..92da3bec3 100644 --- a/packages/cli/test/lib/api/projects.test.ts +++ b/packages/cli/test/lib/api/projects.test.ts @@ -8,7 +8,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; import { createProjectWithDsn, diff --git a/packages/cli/test/lib/command.test.ts b/packages/cli/test/lib/command.test.ts index 7283321fb..d85cb039d 100644 --- a/packages/cli/test/lib/command.test.ts +++ b/packages/cli/test/lib/command.test.ts @@ -8,7 +8,7 @@ import { setTimeout as sleep } from "node:timers/promises"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { buildApplication, type CommandContext, diff --git a/packages/cli/test/lib/dsn/fs-utils.test.ts b/packages/cli/test/lib/dsn/fs-utils.test.ts index 03043662b..2f886c535 100644 --- a/packages/cli/test/lib/dsn/fs-utils.test.ts +++ b/packages/cli/test/lib/dsn/fs-utils.test.ts @@ -11,7 +11,7 @@ const { captureException } = vi.hoisted(() => ({ captureException: vi.fn(), })); -vi.mock("@sentry/node-core/light", () => ({ +vi.mock("@sentry/node", () => ({ captureException, startSpan: (_opts: unknown, fn: () => unknown) => fn(), })); diff --git a/packages/cli/test/lib/dsn/project-root.test.ts b/packages/cli/test/lib/dsn/project-root.test.ts index 26c1e6faf..dbcdc4ad2 100644 --- a/packages/cli/test/lib/dsn/project-root.test.ts +++ b/packages/cli/test/lib/dsn/project-root.test.ts @@ -20,7 +20,7 @@ const { noopSpan } = vi.hoisted(() => ({ }, })); -vi.mock("@sentry/node-core/light", () => ({ +vi.mock("@sentry/node", () => ({ startSpan: (_opts: unknown, fn: (span: unknown) => unknown) => fn(noopSpan), captureException: vi.fn(), })); diff --git a/packages/cli/test/lib/error-reporting.test.ts b/packages/cli/test/lib/error-reporting.test.ts index a673192e7..d4d2c5a86 100644 --- a/packages/cli/test/lib/error-reporting.test.ts +++ b/packages/cli/test/lib/error-reporting.test.ts @@ -9,7 +9,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { ArgumentParseError, FlagNotFoundError } from "@stricli/core"; import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; import { formatAuthHeader } from "../../src/lib/auth-header.js"; @@ -834,7 +834,7 @@ describe("reportArgumentError", () => { let messageSpy: ReturnType; beforeEach(() => { - messageSpy = vi.spyOn(Sentry, "captureMessage"); + messageSpy = vi.spyOn(Sentry, "captureEvent"); }); afterEach(() => { @@ -848,7 +848,8 @@ describe("reportArgumentError", () => { new ValidationError("Invalid period 'bogus'", "period"), ); reportArgumentError(error, 'Failed to parse "bogus" for period'); - expect(messageSpy).toHaveBeenCalledWith("invalid_argument", { + expect(messageSpy).toHaveBeenCalledWith({ + message: "invalid_argument", level: "info", tags: { "argument_error.class": "ArgumentParseError" }, contexts: { @@ -867,8 +868,8 @@ describe("reportArgumentError", () => { "No flag registered for --nope", ); expect(messageSpy).toHaveBeenCalledWith( - "invalid_argument", expect.objectContaining({ + message: "invalid_argument", contexts: { invalid_argument: expect.objectContaining({ error_class: "FlagNotFoundError", diff --git a/packages/cli/test/lib/init/interactive.test.ts b/packages/cli/test/lib/init/interactive.test.ts index 3fce6e21d..6c1608649 100644 --- a/packages/cli/test/lib/init/interactive.test.ts +++ b/packages/cli/test/lib/init/interactive.test.ts @@ -8,7 +8,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterEach, describe, expect, test, vi } from "vitest"; import { WizardError } from "../../../src/lib/errors.js"; import { handleInteractive } from "../../../src/lib/init/interactive.js"; diff --git a/packages/cli/test/lib/init/tools/run-commands-spawn.mocked.test.ts b/packages/cli/test/lib/init/tools/run-commands-spawn.mocked.test.ts index b4b021bdf..a99cf3714 100644 --- a/packages/cli/test/lib/init/tools/run-commands-spawn.mocked.test.ts +++ b/packages/cli/test/lib/init/tools/run-commands-spawn.mocked.test.ts @@ -47,7 +47,7 @@ vi.mock("node:child_process", async () => { }; }); -vi.mock("@sentry/node-core/light", () => ({ +vi.mock("@sentry/node", () => ({ addBreadcrumb: vi.fn(), })); diff --git a/packages/cli/test/lib/init/ui/ink-ui-telemetry.test.ts b/packages/cli/test/lib/init/ui/ink-ui-telemetry.test.ts index b0df7ede3..3ae550c96 100644 --- a/packages/cli/test/lib/init/ui/ink-ui-telemetry.test.ts +++ b/packages/cli/test/lib/init/ui/ink-ui-telemetry.test.ts @@ -1,5 +1,5 @@ // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterEach, describe, expect, test, vi } from "vitest"; import { InkUI } from "../../../../src/lib/init/ui/ink-ui.js"; import { diff --git a/packages/cli/test/lib/init/verify-setup-windows.mocked.test.ts b/packages/cli/test/lib/init/verify-setup-windows.mocked.test.ts index 7c333270c..cc181fecb 100644 --- a/packages/cli/test/lib/init/verify-setup-windows.mocked.test.ts +++ b/packages/cli/test/lib/init/verify-setup-windows.mocked.test.ts @@ -69,7 +69,7 @@ vi.mock("node:child_process", async (importOriginal) => { }; }); -vi.mock("@sentry/node-core/light", () => ({ +vi.mock("@sentry/node", () => ({ addBreadcrumb: vi.fn(), captureException: vi.fn(), setTag: vi.fn(), diff --git a/packages/cli/test/lib/init/verify-setup.test.ts b/packages/cli/test/lib/init/verify-setup.test.ts index a4d76b7bc..8dc0d200e 100644 --- a/packages/cli/test/lib/init/verify-setup.test.ts +++ b/packages/cli/test/lib/init/verify-setup.test.ts @@ -11,7 +11,7 @@ const sentryMocks = vi.hoisted(() => ({ setTag: vi.fn(), })); -vi.mock("@sentry/node-core/light", () => sentryMocks); +vi.mock("@sentry/node", () => sentryMocks); type FixtureProcesses = { shellPid: number; diff --git a/packages/cli/test/lib/init/wizard-runner.test.ts b/packages/cli/test/lib/init/wizard-runner.test.ts index 1ae9fff1d..57c0ca784 100644 --- a/packages/cli/test/lib/init/wizard-runner.test.ts +++ b/packages/cli/test/lib/init/wizard-runner.test.ts @@ -1,6 +1,6 @@ import { MastraClient } from "@mastra/client-js"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- spyOn requires object reference -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterEach, beforeEach, diff --git a/packages/cli/test/lib/run-commands.mocked.test.ts b/packages/cli/test/lib/run-commands.mocked.test.ts index bc17c5411..5d025e682 100644 --- a/packages/cli/test/lib/run-commands.mocked.test.ts +++ b/packages/cli/test/lib/run-commands.mocked.test.ts @@ -1,7 +1,7 @@ /** * Unit tests for the run-commands tool. * - * Kept as a mocked sibling file because vi.mock() on @sentry/node-core/light + * Kept as a mocked sibling file because vi.mock() on @sentry/node * must precede all module imports to take effect. */ @@ -22,7 +22,7 @@ const { breadcrumbs } = vi.hoisted(() => ({ breadcrumbs: [] as Breadcrumb[], })); -vi.mock("@sentry/node-core/light", () => ({ +vi.mock("@sentry/node", () => ({ addBreadcrumb: (crumb: Breadcrumb) => breadcrumbs.push(crumb), })); diff --git a/packages/cli/test/lib/scanner-flags.integration.test.ts b/packages/cli/test/lib/scanner-flags.integration.test.ts index 885ad9c64..54cee7bb9 100644 --- a/packages/cli/test/lib/scanner-flags.integration.test.ts +++ b/packages/cli/test/lib/scanner-flags.integration.test.ts @@ -21,7 +21,7 @@ import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { ExitCode, run } from "@stricli/core"; import { describe, expect, test, vi } from "vitest"; import { app } from "../../src/app.js"; @@ -336,12 +336,12 @@ describe("arguments that fail to parse", () => { }); test("is reported to Sentry for UX research", async () => { - const messageSpy = vi.spyOn(Sentry, "captureMessage"); + const messageSpy = vi.spyOn(Sentry, "captureEvent"); try { await runApp(["issue", "list", "--period", "bogus"]); expect(messageSpy).toHaveBeenCalledWith( - "invalid_argument", expect.objectContaining({ + message: "invalid_argument", contexts: { invalid_argument: expect.objectContaining({ cause_class: "ValidationError", diff --git a/packages/cli/test/lib/sdk-invoke-isolation.focused.test.ts b/packages/cli/test/lib/sdk-invoke-isolation.focused.test.ts index 744c1a73c..5e9a1ae6e 100644 --- a/packages/cli/test/lib/sdk-invoke-isolation.focused.test.ts +++ b/packages/cli/test/lib/sdk-invoke-isolation.focused.test.ts @@ -42,7 +42,7 @@ vi.mock("../../src/lib/telemetry.js", () => ({ callback: (span: undefined) => Promise, ): Promise => await callback(undefined), })); -vi.mock("@sentry/node-core/light", () => ({ getClient: () => null })); +vi.mock("@sentry/node", () => ({ getClient: () => null })); import { getCustomHeaders } from "../../src/lib/custom-headers.js"; import { getEnv } from "../../src/lib/env.js"; diff --git a/packages/cli/test/lib/sentry-client.test.ts b/packages/cli/test/lib/sentry-client.test.ts index 3b20cfca0..12fe0e291 100644 --- a/packages/cli/test/lib/sentry-client.test.ts +++ b/packages/cli/test/lib/sentry-client.test.ts @@ -3,6 +3,12 @@ * regression coverage. */ +import { + getActiveSpan, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + spanToJSON, + startSpan, +} from "@sentry/node"; import { afterEach, beforeEach, describe, expect, test } from "vitest"; import { setAuthToken } from "../../src/lib/db/auth.js"; import { RateLimitError, TimeoutError } from "../../src/lib/errors.js"; @@ -12,6 +18,7 @@ import { getSdkConfig, resetAuthenticatedFetch, } from "../../src/lib/sentry-client.js"; +import { initSentry } from "../../src/lib/telemetry.js"; import { mockFetch, useTestConfigDir } from "../helpers.js"; useTestConfigDir("sentry-client-"); @@ -619,6 +626,49 @@ describe("user abort passthrough", () => { }); }); +describe("API request tracing", () => { + afterEach(() => { + initSentry(false); + }); + + async function tracedRequest(): Promise<{ + headers: Headers; + activeSpanOp: string | undefined; + }> { + let headers = new Headers(); + let activeSpanOp: string | undefined; + globalThis.fetch = mockFetch(async (input, init) => { + headers = new Headers( + init?.headers ?? (input instanceof Request ? input.headers : undefined), + ); + const span = getActiveSpan(); + activeSpanOp = span + ? spanToJSON(span).attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] + : undefined; + return jsonResponse({ ok: true }); + }); + await startSpan({ name: "host", op: "test" }, () => + getAuthenticatedFetch()(`${REGION_URL}/api/0/organizations/`), + ); + return { headers, activeSpanOp }; + } + + test("adds its own http.client span and trace headers in library mode", async () => { + initSentry(true, { libraryMode: true }); + const { headers, activeSpanOp } = await tracedRequest(); + expect(headers.get("sentry-trace")).toBeTruthy(); + expect(headers.get("baggage")).toBeTruthy(); + expect(activeSpanOp).toBe("http.client"); + }); + + test("leaves HTTP spans and headers to the SDK integrations in CLI mode", async () => { + initSentry(true); + const { headers, activeSpanOp } = await tracedRequest(); + expect(headers.get("sentry-trace")).toBeNull(); + expect(activeSpanOp).toBe("test"); + }); +}); + describe("resolveTimeoutMs", () => { test("returns 120 000 ms for Seer /autofix/ POST paths", () => { expect( diff --git a/packages/cli/test/lib/telemetry-credentials.test.ts b/packages/cli/test/lib/telemetry-credentials.test.ts index 1c69dc872..21d4082aa 100644 --- a/packages/cli/test/lib/telemetry-credentials.test.ts +++ b/packages/cli/test/lib/telemetry-credentials.test.ts @@ -13,7 +13,7 @@ import { setContext, startSpan, withScope, -} from "@sentry/node-core/light"; +} from "@sentry/node"; import { afterEach, describe, expect, test, vi } from "vitest"; import { extractMessagePrefix } from "../../src/lib/error-reporting.js"; import { redactTelemetryEnvelope } from "../../src/lib/telemetry/credential-redaction.js"; @@ -39,7 +39,8 @@ function captureTelemetry() { } // Enable capture only after every delivery route is intercepted. client.getOptions().enabled = true; - client.getOptions().enableLogs = true; + // Library mode drops logs; lift that so log scrubbing is exercised too. + client.getOptions().beforeSendLog = undefined; client.init(); function serializedEnvelope(type: string): string { const envelope = send.mock.calls.find(([entry]) => @@ -55,8 +56,10 @@ function captureTelemetry() { afterEach(async () => { await client?.close(0); - getCurrentScope().clear(); - getIsolationScope().clear(); + // v11 removed Scope.clear(); reset only the state these tests set. + for (const scope of [getCurrentScope(), getIsolationScope()]) { + scope.setContext("synthetic", null).clearBreadcrumbs(); + } vi.restoreAllMocks(); }); diff --git a/packages/cli/test/lib/telemetry-init-scope.test.ts b/packages/cli/test/lib/telemetry-init-scope.test.ts new file mode 100644 index 000000000..ca7599f5c --- /dev/null +++ b/packages/cli/test/lib/telemetry-init-scope.test.ts @@ -0,0 +1,24 @@ +/** + * Runs in its own file so the SDK starts on its default stack-based context + * strategy, which is what the CLI sees before the first `initSentry()`. + */ + +// oxlint-disable-next-line sentry-cli/no-namespace-import -- inspect the SDK's active client +import * as Sentry from "@sentry/node"; +import { afterEach, expect, test } from "vitest"; +import { initSentry } from "../../src/lib/telemetry.js"; + +afterEach(async () => { + await Sentry.getClient()?.close(0); +}); + +test("binds the client when init runs inside a pending pre-init span", async () => { + let client: ReturnType; + await Sentry.startSpan({ name: "pre-init" }, async () => { + await Promise.resolve(); + client = initSentry(true, { libraryMode: true }); + }); + + expect(client).toBeDefined(); + expect(Sentry.getClient()).toBe(client); +}); diff --git a/packages/cli/test/lib/telemetry-session.test.ts b/packages/cli/test/lib/telemetry-session.test.ts index 36f146586..536d7dd1d 100644 --- a/packages/cli/test/lib/telemetry-session.test.ts +++ b/packages/cli/test/lib/telemetry-session.test.ts @@ -12,7 +12,7 @@ */ // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterEach, describe, expect, test, vi } from "vitest"; import { createBeforeExitHandler, @@ -21,13 +21,13 @@ import { describe("createBeforeExitHandler", () => { /** - * Create a minimal mock LightNodeClient for testing the beforeExit handler. + * Create a minimal mock NodeClient for testing the beforeExit handler. * Only needs flush() since that's all the handler uses from the client. */ - function createMockClient(): Sentry.LightNodeClient { + function createMockClient(): Sentry.NodeClient { return { flush: () => Promise.resolve(true), - } as unknown as Sentry.LightNodeClient; + } as unknown as Sentry.NodeClient; } test("ends OK session on beforeExit", () => { diff --git a/packages/cli/test/lib/telemetry.test.ts b/packages/cli/test/lib/telemetry.test.ts index e0873dc39..113c91066 100644 --- a/packages/cli/test/lib/telemetry.test.ts +++ b/packages/cli/test/lib/telemetry.test.ts @@ -7,7 +7,7 @@ import { chmodSync, mkdirSync, rmSync } from "node:fs"; import { setTimeout as sleep } from "node:timers/promises"; // oxlint-disable-next-line sentry-cli/no-namespace-import -- needed for spyOn mocking -import * as Sentry from "@sentry/node-core/light"; +import * as Sentry from "@sentry/node"; import { afterAll, afterEach, @@ -41,7 +41,6 @@ import { setOrgProjectContext, withDbSpan, withFsSpan, - withHttpSpan, withSerializeSpan, withTelemetry, withTracing, @@ -107,6 +106,23 @@ describe("initSentry", () => { const client = initSentry(true); expect(client?.getOptions().release).toBe("0.0.0-dev"); }); + + test("library mode leaves the host's process hooks and channels alone", () => { + const client = initSentry(true, { libraryMode: true }); + const names = client?.getOptions().integrations.map((i) => i.name) ?? []; + for (const hostHook of [ + "OnUncaughtException", + "OnUnhandledRejection", + "Http", + "NodeFetch", + "WorkerThreads", + "Express", + "Postgres", + "OpenAI", + ]) { + expect(names).not.toContain(hostHook); + } + }); }); describe("withTelemetry", () => { @@ -834,21 +850,6 @@ describe("setArgsContext", () => { }); }); -describe("withHttpSpan", () => { - test("executes function and returns result", async () => { - const result = await withHttpSpan("GET", "/test", async () => "success"); - expect(result).toBe("success"); - }); - - test("propagates errors", async () => { - await expect( - withHttpSpan("POST", "/test", async () => { - throw new Error("http error"); - }), - ).rejects.toThrow("http error"); - }); -}); - describe("withDbSpan", () => { test("executes function and returns result", () => { const result = withDbSpan("testOp", () => 42); diff --git a/packages/cli/test/lib/wizard-runner-handle-final-result.mocked.test.ts b/packages/cli/test/lib/wizard-runner-handle-final-result.mocked.test.ts index 4580f166c..02fb89059 100644 --- a/packages/cli/test/lib/wizard-runner-handle-final-result.mocked.test.ts +++ b/packages/cli/test/lib/wizard-runner-handle-final-result.mocked.test.ts @@ -1,7 +1,7 @@ /** * Unit tests for handleFinalResult in wizard-runner.ts. * - * Kept as a mocked sibling file because vi.mock() on @sentry/node-core/light + * Kept as a mocked sibling file because vi.mock() on @sentry/node * would pollute the module graph for other wizard-runner tests that may not * want Sentry calls mocked. */ @@ -20,7 +20,7 @@ const { tags } = vi.hoisted(() => ({ tags: {} as Record, })); -vi.mock("@sentry/node-core/light", () => ({ +vi.mock("@sentry/node", () => ({ addBreadcrumb: () => null, captureException: () => null, getTraceData: () => ({}), diff --git a/packages/cli/vitest.config.ts b/packages/cli/vitest.config.ts index e68d88448..0462145d1 100644 --- a/packages/cli/vitest.config.ts +++ b/packages/cli/vitest.config.ts @@ -96,7 +96,7 @@ export default defineConfig({ // vi.spyOn. Without inlining, ESM namespace objects are frozen // and spyOn throws "Cannot redefine property". inline: [ - "@sentry/node-core", + "@sentry/node", "@sentry/core", "@clack/prompts", "node:child_process", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 135443c29..e0cc31f2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -203,8 +203,6 @@ packageExtensionsChecksum: sha256-PIoL2jn0sFpFHgcMKW97dNeqBXVNxH6qFIzsWIBFOMY= patchedDependencies: '@ai-sdk/provider-utils@2.2.8': 4649a74595006c4a262d453549e091db331ade06b4f4320957af1b2c659b8ee3 '@cloudflare/workers-oauth-provider@0.10.3': 34910b67929c1888b1492384c514d6baeedc4a439f66e21375dee5af404834f8 - '@sentry/core@10.63.0': e663994979ff877a26ab6d4dea5968fbaee4ccdfdeb85623983535a572678940 - '@sentry/node-core@10.63.0': 0a5f08471bd72cb833a2b36220c96001d966e5c390d71aaf598fdef75b552640 '@stricli/core@1.2.8': cbf047581d38be04108d3921321c14a778272c24004da8110d4498d4f2a6b2e1 importers: @@ -418,7 +416,7 @@ importers: devDependencies: '@spotlightjs/spotlight': specifier: ^4.11.7 - version: 4.11.8(@cfworker/json-schema@4.1.1)(hono-rate-limiter@0.4.2(hono@4.13.8)) + version: 4.11.8(@cfworker/json-schema@4.1.1)(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1))(hono-rate-limiter@0.4.2(hono@4.13.8)) '@testing-library/react': specifier: ^16.3.2 version: 16.3.3(@testing-library/dom@10.4.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -471,17 +469,14 @@ importers: specifier: 'catalog:' version: 0.400.0(valibot@1.4.2(typescript@5.9.3))(zod@4.6.7) '@sentry/core': - specifier: 10.63.0 - version: 10.63.0(patch_hash=e663994979ff877a26ab6d4dea5968fbaee4ccdfdeb85623983535a572678940) + specifier: 'catalog:' + version: 11.6.0 '@sentry/mcp-server': specifier: workspace:* version: link:../mcp-server '@sentry/node': - specifier: 10.65.0 - version: 10.65.0(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1)) - '@sentry/node-core': - specifier: 10.63.0 - version: 10.63.0(patch_hash=0a5f08471bd72cb833a2b36220c96001d966e5c390d71aaf598fdef75b552640)(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.220.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.11.0(@opentelemetry/api@1.9.1)) + specifier: 'catalog:' + version: 11.6.0(@babel/core@7.28.0)(rollup@4.62.4) '@sentry/sqlish': specifier: ^1.0.1 version: 1.0.1(react@19.2.8) @@ -4516,10 +4511,6 @@ packages: wrangler: optional: true - '@sentry/conventions@0.12.0': - resolution: {integrity: sha512-z1JQrl/1SLY+8wpzvork6vl+fpsg/oCCxM7HWWhUnI/R+OGNyoIzieQuggX3uUMY7NBtp8UWCQx6FeFazzOF9g==} - engines: {node: '>=14'} - '@sentry/conventions@0.15.1': resolution: {integrity: sha512-ZLP8bRdMON3prWE2tJyImuYscCxdcJeIPIhrOs/rgyFm3C1nCh1B6gdvPj3AZ5zW08oSFFCsq7T+tYEW3h8MNA==} engines: {node: '>=14'} @@ -4564,27 +4555,6 @@ packages: resolution: {integrity: sha512-V52/+SkMcPdlldExPC9TWS2sZ+CC+8BSzvVbRtkQxvy+jTOXFAJfInaVLPAAVt8W4WbPw9iAxVMzwHGaZ2muBw==} engines: {node: '>=20.19.0 <22.0.0 || >=22.12.0 <23.0.0 || >=23.2.0'} - '@sentry/node-core@10.63.0': - resolution: {integrity: sha512-TaNtkGDRNxH3SjOea2PDtaebkNjMbAH8ZFsEcwlqmadpS7nqSR7z6slZy/iu7y1nLiUdbmcM5JmXwxksy52WRQ==} - engines: {node: '>=18'} - peerDependencies: - '@opentelemetry/api': ^1.9.0 - '@opentelemetry/core': ^1.30.1 || ^2.1.0 - '@opentelemetry/exporter-trace-otlp-http': '>=0.57.0 <1' - '@opentelemetry/instrumentation': '>=0.57.1 <1' - '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@opentelemetry/core': - optional: true - '@opentelemetry/exporter-trace-otlp-http': - optional: true - '@opentelemetry/instrumentation': - optional: true - '@opentelemetry/sdk-trace-base': - optional: true - '@sentry/node-core@10.65.0': resolution: {integrity: sha512-U01X9mPT+jZnsLPmPWfBU67Ka+t/Sdd9RGAuvGoKdrI6N47a/9PDkM9oCW+kj0fmZwogZHTgSnzJU5oi3pImgA==} engines: {node: '>=18'} @@ -4664,14 +4634,6 @@ packages: resolution: {integrity: sha512-5uHdUSACyodmtar+LxhFl4/MdICJ1/38mrp5lrMpDKfWSV/7tu/KRmr5gD2J9Nm47I/xxbghSz+oinJ4EtJatQ==} engines: {node: '>=20.19.0 <22.0.0 || >=22.12.0 <23.0.0 || >=23.2.0'} - '@sentry/opentelemetry@10.63.0': - resolution: {integrity: sha512-8yqi8+Ej/anmMn82blXA0BNMeAMs4av6nx0DzhxDrFya28ZaYOn19PChd3erMidfU0HnLLFNqWiFlYxBKq+/KA==} - engines: {node: '>=18'} - peerDependencies: - '@opentelemetry/api': ^1.9.0 - '@opentelemetry/core': ^1.30.1 || ^2.1.0 - '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 - '@sentry/opentelemetry@10.65.0': resolution: {integrity: sha512-8C6FPvm3XBvUrkM52dX3Gz0p2H0Ij8t4sahUA+GTiCz0WM0fnyPeQPGC/b6I4jamV9UXyCZRnE1UEEGCoD+c7A==} engines: {node: '>=18'} @@ -12751,15 +12713,13 @@ snapshots: '@cloudflare/workers-types': 4.20260405.1 wrangler: 4.151.3(@cloudflare/workers-types@4.20260405.1)(@types/node@24.13.5) - '@sentry/conventions@0.12.0': {} - '@sentry/conventions@0.15.1': {} '@sentry/conventions@0.16.0': {} '@sentry/conventions@0.26.0': {} - '@sentry/core@10.63.0(patch_hash=e663994979ff877a26ab6d4dea5968fbaee4ccdfdeb85623983535a572678940)': {} + '@sentry/core@10.63.0': {} '@sentry/core@10.65.0': dependencies: @@ -12787,18 +12747,6 @@ snapshots: dependencies: '@sentry/core': 11.6.0 - '@sentry/node-core@10.63.0(patch_hash=0a5f08471bd72cb833a2b36220c96001d966e5c390d71aaf598fdef75b552640)(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.220.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.11.0(@opentelemetry/api@1.9.1))': - dependencies: - '@sentry/conventions': 0.12.0 - '@sentry/core': 10.63.0(patch_hash=e663994979ff877a26ab6d4dea5968fbaee4ccdfdeb85623983535a572678940) - '@sentry/opentelemetry': 10.63.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.11.0(@opentelemetry/api@1.9.1)) - import-in-the-middle: 3.5.1 - optionalDependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.11.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.220.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.11.0(@opentelemetry/api@1.9.1) - '@sentry/node-core@10.65.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.220.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.11.0(@opentelemetry/api@1.9.1))': dependencies: '@sentry/conventions': 0.15.1 @@ -12897,14 +12845,6 @@ snapshots: - rollup - webpack - '@sentry/opentelemetry@10.63.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.11.0(@opentelemetry/api@1.9.1))': - dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.11.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.11.0(@opentelemetry/api@1.9.1) - '@sentry/conventions': 0.12.0 - '@sentry/core': 10.63.0(patch_hash=e663994979ff877a26ab6d4dea5968fbaee4ccdfdeb85623983535a572678940) - '@sentry/opentelemetry@10.65.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.11.0(@opentelemetry/api@1.9.1))': dependencies: '@opentelemetry/api': 1.9.1 @@ -13140,7 +13080,7 @@ snapshots: '@hono/node-server': 1.19.17(hono@4.13.8) '@jridgewell/trace-mapping': 0.3.31 '@modelcontextprotocol/sdk': 1.32.0(@cfworker/json-schema@4.1.1)(zod@4.6.5) - '@sentry/core': 10.63.0(patch_hash=e663994979ff877a26ab6d4dea5968fbaee4ccdfdeb85623983535a572678940) + '@sentry/core': 10.63.0 '@sentry/node': 10.65.0(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1)) anser: 2.3.5 chalk: 5.6.2 @@ -13161,13 +13101,13 @@ snapshots: - hono-rate-limiter - supports-color - '@spotlightjs/spotlight@4.11.8(@cfworker/json-schema@4.1.1)(hono-rate-limiter@0.4.2(hono@4.13.8))': + '@spotlightjs/spotlight@4.11.8(@cfworker/json-schema@4.1.1)(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1))(hono-rate-limiter@0.4.2(hono@4.13.8))': dependencies: '@hono/mcp': 0.2.5(@modelcontextprotocol/sdk@1.32.0(@cfworker/json-schema@4.1.1)(zod@4.6.5))(hono-rate-limiter@0.4.2(hono@4.13.8))(hono@4.13.8)(zod@4.6.5) '@hono/node-server': 1.19.17(hono@4.13.8) '@jridgewell/trace-mapping': 0.3.31 '@modelcontextprotocol/sdk': 1.32.0(@cfworker/json-schema@4.1.1)(zod@4.6.5) - '@sentry/core': 10.63.0(patch_hash=e663994979ff877a26ab6d4dea5968fbaee4ccdfdeb85623983535a572678940) + '@sentry/core': 10.63.0 '@sentry/node': 10.65.0(@opentelemetry/core@2.11.0(@opentelemetry/api@1.9.1)) anser: 2.3.5 chalk: 5.6.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index df8e40413..7f8f8dd0a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,8 +5,6 @@ packages: patchedDependencies: "@ai-sdk/provider-utils@2.2.8": patches/@ai-sdk__provider-utils@2.2.8.patch "@cloudflare/workers-oauth-provider@0.10.3": patches/@cloudflare__workers-oauth-provider@0.10.3.patch - "@sentry/core@10.63.0": packages/cli/patches/@sentry%2Fcore@10.63.0.patch - "@sentry/node-core@10.63.0": packages/cli/patches/@sentry%2Fnode-core@10.63.0.patch "@stricli/core@1.2.8": packages/cli/patches/@stricli%2Fcore@1.2.8.patch packageExtensions: