dd-trace 6.20.1 → 6.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/ci/diagnose.js +9 -14
  2. package/ci/init.js +1 -2
  3. package/ci/test-optimization-validation/ci-discovery.js +9 -4
  4. package/ci/test-optimization-validation/executable.js +1 -5
  5. package/ci/test-optimization-validation/framework-adapters/cypress.js +1 -4
  6. package/ci/test-optimization-validation/framework-adapters/vitest.js +1 -1
  7. package/ci/test-optimization-validation/generated-files.js +6 -4
  8. package/ci/test-optimization-validation/generated-test-contract.js +7 -3
  9. package/ci/test-optimization-validation/manifest-scaffold.js +7 -2
  10. package/ci/test-optimization-validation/manifest-schema.js +6 -7
  11. package/ci/test-optimization-validation/report-writer.js +6 -2
  12. package/ci/test-optimization-validation/runner-command.js +2 -4
  13. package/ci/test-optimization-validation/runner-contract.js +1 -2
  14. package/ci/test-optimization-validation/scenarios/auto-test-retries.js +1 -15
  15. package/ci/vitest-no-worker-init-setup.mjs +10 -7
  16. package/index.d.ts +116 -17
  17. package/initialize.mjs +1 -3
  18. package/openfeature/rules-based.d.ts +11 -0
  19. package/openfeature/rules-based.js +7 -0
  20. package/package.json +13 -11
  21. package/packages/datadog-core/src/storage.js +16 -0
  22. package/packages/datadog-esbuild/index.js +18 -12
  23. package/packages/datadog-instrumentations/src/aerospike.js +3 -3
  24. package/packages/datadog-instrumentations/src/ai.js +3 -3
  25. package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +0 -6
  26. package/packages/datadog-instrumentations/src/aws-sdk.js +21 -13
  27. package/packages/datadog-instrumentations/src/cassandra-driver.js +25 -20
  28. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +9 -23
  29. package/packages/datadog-instrumentations/src/cucumber.js +48 -33
  30. package/packages/datadog-instrumentations/src/elasticsearch.js +1 -5
  31. package/packages/datadog-instrumentations/src/electron.js +6 -6
  32. package/packages/datadog-instrumentations/src/fastify.js +13 -4
  33. package/packages/datadog-instrumentations/src/fs.js +2 -2
  34. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +9 -5
  35. package/packages/datadog-instrumentations/src/grpc/client.js +2 -0
  36. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +2 -2
  37. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +1 -2
  38. package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
  39. package/packages/datadog-instrumentations/src/helpers/register.js +36 -1
  40. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -0
  41. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +87 -6
  42. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +5 -6
  43. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +48 -31
  44. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +64 -11
  45. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
  46. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +42 -4
  47. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +7 -10
  48. package/packages/datadog-instrumentations/src/ioredis.js +7 -5
  49. package/packages/datadog-instrumentations/src/iovalkey.js +7 -5
  50. package/packages/datadog-instrumentations/src/jest.js +122 -11
  51. package/packages/datadog-instrumentations/src/knex.js +9 -5
  52. package/packages/datadog-instrumentations/src/mariadb-bundle.js +3 -3
  53. package/packages/datadog-instrumentations/src/mocha/common.js +20 -8
  54. package/packages/datadog-instrumentations/src/mocha/main.js +140 -43
  55. package/packages/datadog-instrumentations/src/mocha/utils.js +127 -38
  56. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +61 -34
  57. package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
  58. package/packages/datadog-instrumentations/src/mongodb-core.js +3 -3
  59. package/packages/datadog-instrumentations/src/mongoose.js +3 -3
  60. package/packages/datadog-instrumentations/src/nova-sonic/audio.js +173 -0
  61. package/packages/datadog-instrumentations/src/nova-sonic/index.js +209 -0
  62. package/packages/datadog-instrumentations/src/nova-sonic/session.js +483 -0
  63. package/packages/datadog-instrumentations/src/openai-realtime/index.js +18 -6
  64. package/packages/datadog-instrumentations/src/openai-realtime/session.js +1 -1
  65. package/packages/datadog-instrumentations/src/openai.js +7 -0
  66. package/packages/datadog-instrumentations/src/pino.js +5 -6
  67. package/packages/datadog-instrumentations/src/playwright.js +3 -0
  68. package/packages/datadog-instrumentations/src/redis.js +27 -13
  69. package/packages/datadog-instrumentations/src/router.js +30 -0
  70. package/packages/datadog-instrumentations/src/rum-browser-scripts.js +2 -6
  71. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +7 -5
  72. package/packages/datadog-instrumentations/src/vitest-main.js +9 -17
  73. package/packages/datadog-instrumentations/src/vitest-util.js +2 -2
  74. package/packages/datadog-instrumentations/src/vitest-worker.js +1 -2
  75. package/packages/datadog-instrumentations/src/vitest.js +2 -2
  76. package/packages/datadog-instrumentations/src/webdriverio.js +118 -21
  77. package/packages/datadog-instrumentations/src/ws.js +1 -4
  78. package/packages/datadog-plugin-amqplib/src/client.js +1 -2
  79. package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -5
  80. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/handler.js +1 -2
  81. package/packages/datadog-plugin-aws-sdk/src/base.js +5 -8
  82. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +18 -0
  83. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/sonic.js +45 -0
  84. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -3
  85. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -5
  86. package/packages/datadog-plugin-azure-durable-functions/src/index.js +5 -4
  87. package/packages/datadog-plugin-azure-functions/src/index.js +5 -3
  88. package/packages/datadog-plugin-claude-agent-sdk/src/index.js +0 -2
  89. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +18 -5
  90. package/packages/datadog-plugin-cypress/src/index.js +6 -6
  91. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -2
  92. package/packages/datadog-plugin-cypress/src/support.js +1 -4
  93. package/packages/datadog-plugin-express/src/code_origin.js +1 -2
  94. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
  95. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
  96. package/packages/datadog-plugin-graphql/src/execute.js +5 -5
  97. package/packages/datadog-plugin-grpc/src/util.js +1 -2
  98. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -2
  99. package/packages/datadog-plugin-mocha/src/index.js +223 -39
  100. package/packages/datadog-plugin-mocha/src/webdriverio-video.js +453 -0
  101. package/packages/datadog-plugin-mongodb-core/src/query.js +8 -5
  102. package/packages/datadog-plugin-next/src/index.js +1 -2
  103. package/packages/datadog-plugin-openai/src/tracing.js +5 -2
  104. package/packages/datadog-plugin-openai-agents/src/integration.js +6 -2
  105. package/packages/datadog-plugin-openai-agents/src/processor.js +2 -4
  106. package/packages/datadog-plugin-postgres/src/index.js +24 -0
  107. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -5
  108. package/packages/datadog-plugin-rhea/src/consumer.js +1 -4
  109. package/packages/datadog-plugin-vitest/src/index.js +5 -2
  110. package/packages/datadog-shimmer/src/shimmer.js +5 -4
  111. package/packages/datadog-webpack/index.js +55 -43
  112. package/packages/datadog-webpack/src/loader.js +56 -8
  113. package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -4
  114. package/packages/dd-trace/src/aiguard/messages/utils.js +1 -2
  115. package/packages/dd-trace/src/aiguard/redaction.js +8 -2
  116. package/packages/dd-trace/src/appsec/api_security/normalized-route.js +3 -2
  117. package/packages/dd-trace/src/appsec/api_security/sampler.js +2 -6
  118. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -9
  119. package/packages/dd-trace/src/appsec/handlers/http-request.js +3 -9
  120. package/packages/dd-trace/src/appsec/handlers/http-response.js +7 -2
  121. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -3
  122. package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +1 -4
  123. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +7 -1
  124. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -3
  125. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -3
  126. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +1 -6
  127. package/packages/dd-trace/src/appsec/lambda.js +1 -3
  128. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +37 -27
  129. package/packages/dd-trace/src/appsec/rasp/lfi.js +9 -5
  130. package/packages/dd-trace/src/appsec/reporter.js +21 -1
  131. package/packages/dd-trace/src/appsec/stack_trace.js +1 -2
  132. package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +3 -6
  133. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +1 -1
  134. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +13 -7
  135. package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +1 -2
  136. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +2 -8
  137. package/packages/dd-trace/src/ci-visibility/resolve-runfile-path.js +54 -0
  138. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +5 -8
  139. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +2 -53
  140. package/packages/dd-trace/src/config/config-types.d.ts +2 -2
  141. package/packages/dd-trace/src/config/defaults.js +5 -5
  142. package/packages/dd-trace/src/config/generated-config-types.d.ts +8 -0
  143. package/packages/dd-trace/src/config/helper.js +34 -3
  144. package/packages/dd-trace/src/config/index.js +10 -9
  145. package/packages/dd-trace/src/config/normalize-service.js +1 -1
  146. package/packages/dd-trace/src/config/parsers.js +2 -2
  147. package/packages/dd-trace/src/config/supported-configurations.json +35 -0
  148. package/packages/dd-trace/src/datastreams/processor.js +3 -2
  149. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -4
  150. package/packages/dd-trace/src/debugger/constants.js +1 -0
  151. package/packages/dd-trace/src/debugger/devtools_client/index.js +5 -3
  152. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +17 -12
  153. package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -2
  154. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -0
  155. package/packages/dd-trace/src/debugger/devtools_client/worker-error.js +21 -0
  156. package/packages/dd-trace/src/debugger/guardrail-metrics.js +2 -2
  157. package/packages/dd-trace/src/debugger/index.js +24 -2
  158. package/packages/dd-trace/src/debugger/probe_sampler.js +108 -11
  159. package/packages/dd-trace/src/dogstatsd.js +1 -1
  160. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  161. package/packages/dd-trace/src/exporters/common/request.js +2 -5
  162. package/packages/dd-trace/src/exporters/common/url.js +1 -1
  163. package/packages/dd-trace/src/id.js +15 -5
  164. package/packages/dd-trace/src/lambda/handler.js +179 -19
  165. package/packages/dd-trace/src/lambda/index.js +15 -1
  166. package/packages/dd-trace/src/lambda/runtime/patch.js +34 -7
  167. package/packages/dd-trace/src/llmobs/agent-manifest.js +296 -0
  168. package/packages/dd-trace/src/llmobs/audio-utils.js +3 -2
  169. package/packages/dd-trace/src/llmobs/constants/tags.js +13 -0
  170. package/packages/dd-trace/src/llmobs/experiments/experiment.js +1 -1
  171. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +15 -0
  172. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +1 -2
  173. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -3
  174. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
  175. package/packages/dd-trace/src/llmobs/plugins/nova-sonic.js +92 -0
  176. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +56 -2
  177. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +38 -0
  178. package/packages/dd-trace/src/llmobs/prompts/manager.js +5 -7
  179. package/packages/dd-trace/src/llmobs/prompts/prompt.js +1 -1
  180. package/packages/dd-trace/src/llmobs/sdk.js +23 -6
  181. package/packages/dd-trace/src/llmobs/span_processor.js +18 -8
  182. package/packages/dd-trace/src/llmobs/tagger.js +56 -3
  183. package/packages/dd-trace/src/llmobs/util.js +1 -2
  184. package/packages/dd-trace/src/llmobs/writers/base.js +7 -6
  185. package/packages/dd-trace/src/llmobs/writers/util.js +3 -1
  186. package/packages/dd-trace/src/log/log.js +1 -5
  187. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +30 -1
  188. package/packages/dd-trace/src/openfeature/configuration_source.js +17 -2
  189. package/packages/dd-trace/src/openfeature/debug-logging-hook.js +25 -0
  190. package/packages/dd-trace/src/openfeature/evaluation-telemetry-opt-out-hook.js +51 -0
  191. package/packages/dd-trace/src/openfeature/flagging_provider.js +59 -3
  192. package/packages/dd-trace/src/openfeature/remote_config.js +9 -0
  193. package/packages/dd-trace/src/openfeature/writers/util.js +43 -4
  194. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +1 -1
  195. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  196. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -2
  197. package/packages/dd-trace/src/opentelemetry/otlp/common.proto +1 -1
  198. package/packages/dd-trace/src/opentelemetry/resource-attributes.js +1 -1
  199. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +6 -23
  200. package/packages/dd-trace/src/opentracing/propagation/text_map.js +53 -13
  201. package/packages/dd-trace/src/otel-sampling.js +4 -5
  202. package/packages/dd-trace/src/otel-thread-ctx.js +81 -15
  203. package/packages/dd-trace/src/plugins/database.js +7 -16
  204. package/packages/dd-trace/src/plugins/util/git.js +9 -25
  205. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -5
  206. package/packages/dd-trace/src/plugins/util/test.js +48 -4
  207. package/packages/dd-trace/src/priority_sampler.js +1 -2
  208. package/packages/dd-trace/src/profiling/profiler.js +4 -6
  209. package/packages/dd-trace/src/profiling/profilers/wall.js +4 -10
  210. package/packages/dd-trace/src/proxy.js +3 -2
  211. package/packages/dd-trace/src/ritm.js +4 -2
  212. package/packages/dd-trace/src/serverless.js +10 -0
  213. package/packages/dd-trace/src/span_processor.js +13 -17
  214. package/packages/dd-trace/src/storage-channels.js +112 -46
  215. package/packages/dd-trace/src/telemetry/endpoints.js +1 -3
  216. package/packages/dd-trace/src/util.js +29 -0
  217. package/packages/dd-trace/src/web-tags-cache.js +6 -2
  218. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
  219. package/vendor/dist/@datadog/openfeature-node-server/rules-based/LICENSE +201 -0
  220. package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.d.ts +925 -0
  221. package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.js +1 -0
  222. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  223. package/vendor/dist/protobufjs/index.js +1 -1
  224. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  225. package/vendor/dist/shell-quote/index.js +1 -1
@@ -72,11 +72,7 @@ function createWrapRequest (name) {
72
72
 
73
73
  return function wrapRequest (request) {
74
74
  return function (params, options, cb) {
75
- if (!startCh.hasSubscribers) {
76
- return request.apply(this, arguments)
77
- }
78
-
79
- if (!params) return request.apply(this, arguments)
75
+ if (!startCh.hasSubscribers || !params) return request.apply(this, arguments)
80
76
 
81
77
  const ctx = { params }
82
78
  return startCh.runStores(ctx, () => {
@@ -83,10 +83,10 @@ function createWrapAddListener (ch, mappings) {
83
83
  }
84
84
  }
85
85
 
86
- function createWrapRemoveListener (mappings) {
86
+ function createWrapRemoveListener () {
87
87
  return function wrapRemoveListener (removeListener) {
88
88
  return function (channel, listener) {
89
- const mapping = mappings[channel]
89
+ const mapping = listeners[channel]
90
90
 
91
91
  if (mapping) {
92
92
  const wrapper = mapping.get(listener)
@@ -212,10 +212,10 @@ addHook({ name: 'electron', versions: ['>=37.0.0'] }, electron => {
212
212
  wrap(ipcRenderer, 'sendToHost', createWrapSend(rendererSendCh))
213
213
 
214
214
  wrap(ipcRenderer, 'addListener', createWrapAddListener(rendererReceiveCh, listeners))
215
- wrap(ipcRenderer, 'off', createWrapRemoveListener(listeners))
215
+ wrap(ipcRenderer, 'off', createWrapRemoveListener())
216
216
  wrap(ipcRenderer, 'on', createWrapAddListener(rendererReceiveCh, listeners))
217
217
  wrap(ipcRenderer, 'once', createWrapAddListener(rendererReceiveCh, listeners))
218
- wrap(ipcRenderer, 'removeListener', createWrapRemoveListener(listeners))
218
+ wrap(ipcRenderer, 'removeListener', createWrapRemoveListener())
219
219
  wrap(ipcRenderer, 'removeAllListeners', createWrapRemoveAllListeners(listeners))
220
220
 
221
221
  ipcRenderer.send('datadog:apm:renderer:patched')
@@ -223,12 +223,12 @@ addHook({ name: 'electron', versions: ['>=37.0.0'] }, electron => {
223
223
  wrap(ipcMain, 'addListener', createWrapAddListener(mainReceiveCh, listeners))
224
224
  wrap(ipcMain, 'handle', createWrapAddListener(mainHandleCh, handlers))
225
225
  wrap(ipcMain, 'handleOnce', createWrapAddListener(mainHandleCh, handlers))
226
- wrap(ipcMain, 'off', createWrapRemoveListener(listeners))
226
+ wrap(ipcMain, 'off', createWrapRemoveListener())
227
227
  wrap(ipcMain, 'on', createWrapAddListener(mainReceiveCh, listeners))
228
228
  wrap(ipcMain, 'once', createWrapAddListener(mainReceiveCh, listeners))
229
229
  wrap(ipcMain, 'removeAllListeners', createWrapRemoveAllListeners(listeners))
230
230
  wrap(ipcMain, 'removeHandler', createWrapRemoveAllListeners(handlers))
231
- wrap(ipcMain, 'removeListener', createWrapRemoveListener(listeners))
231
+ wrap(ipcMain, 'removeListener', createWrapRemoveListener())
232
232
 
233
233
  ipcMain.once('datadog:apm:renderer:patched', event => rendererPatchedCh.publish(event))
234
234
 
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const shimmer = require('../../datadog-shimmer')
4
+ const { isEmpty } = require('../../dd-trace/src/util')
4
5
  const { addHook, channel, createErrorPublisher } = require('./helpers/instrument')
5
6
 
6
7
  const errorChannel = channel('apm:fastify:middleware:error')
@@ -186,6 +187,17 @@ function onRequest (request, reply, done) {
186
187
  return done()
187
188
  }
188
189
 
190
+ /**
191
+ * Publishing an empty body would set a WAF address for nothing, so only non-empty bodies are published.
192
+ * Strings, arrays and binary bodies are checked by length to avoid enumerating one key per character or element.
193
+ *
194
+ * @param {unknown} body
195
+ */
196
+ function hasBody (body) {
197
+ if (typeof body === 'string') return body.length > 0
198
+ return typeof body === 'object' && body !== null && !isEmpty(body)
199
+ }
200
+
189
201
  function preHandler (request, reply, done) {
190
202
  if (typeof done !== 'function') return
191
203
  if (!reply || typeof reply.send !== 'function') return done()
@@ -194,11 +206,8 @@ function preHandler (request, reply, done) {
194
206
  const res = getRes(reply)
195
207
  const ctx = { req, res }
196
208
 
197
- // eslint-disable-next-line no-restricted-syntax -- arbitrary body keys; publishing {} sets a WAF address
198
- const hasBody = request.body && Object.keys(request.body).length > 0
199
-
200
209
  // For multipart/form-data, the body is not available until after preValidation hook
201
- if (bodyParserReadCh.hasSubscribers && hasBody && !bodyPublished.has(req)) {
210
+ if (bodyParserReadCh.hasSubscribers && !bodyPublished.has(req) && hasBody(request.body)) {
202
211
  ctx.abortController = new AbortController()
203
212
  ctx.body = request.body
204
213
  bodyParserReadCh.publish(ctx)
@@ -232,9 +232,9 @@ function getMethodParamsRelationByPrefix (prefix) {
232
232
  return paramsByMethod
233
233
  }
234
234
 
235
- function createWatchWrapFunction (override = '') {
235
+ function createWatchWrapFunction () {
236
236
  return function wrapFunction (original) {
237
- const name = override || original.name
237
+ const name = original.name
238
238
  const method = name
239
239
  const operation = name
240
240
  return function (...args) {
@@ -126,10 +126,14 @@ function wrapMethod (method) {
126
126
  }
127
127
  }
128
128
 
129
- function massWrap (obj, methods, wrapper) {
129
+ /**
130
+ * @param {Record<string, Function>} obj
131
+ * @param {string[]} methods
132
+ */
133
+ function massWrap (obj, methods) {
130
134
  for (const method of methods) {
131
135
  if (typeof obj[method] === 'function') {
132
- shimmer.wrap(obj, method, wrapper)
136
+ shimmer.wrap(obj, method, wrapMethod)
133
137
  }
134
138
  }
135
139
  }
@@ -274,11 +278,11 @@ addHook({ name: '@google-cloud/pubsub', versions: ['>=1.2'] }, (obj) => {
274
278
  addHook({ name: '@google-cloud/pubsub', versions: ['>=1.2'] }, (obj) => {
275
279
  const { PublisherClient, SchemaServiceClient, SubscriberClient } = obj.v1
276
280
 
277
- massWrap(PublisherClient.prototype, publisherMethods, wrapMethod)
278
- massWrap(SubscriberClient.prototype, subscriberMethods, wrapMethod)
281
+ massWrap(PublisherClient.prototype, publisherMethods)
282
+ massWrap(SubscriberClient.prototype, subscriberMethods)
279
283
 
280
284
  if (SchemaServiceClient) {
281
- massWrap(SchemaServiceClient.prototype, schemaServiceMethods, wrapMethod)
285
+ massWrap(SchemaServiceClient.prototype, schemaServiceMethods)
282
286
  }
283
287
 
284
288
  return obj
@@ -246,6 +246,8 @@ function patch (hasPeer = false) {
246
246
  return function patch (grpc) {
247
247
  const proto = grpc.Client.prototype
248
248
 
249
+ if (instances.has(proto)) return grpc
250
+
249
251
  instances.set(proto, grpc)
250
252
 
251
253
  shimmer.wrap(proto, 'makeBidiStreamRequest', createWrapMakeRequest(types.bidi, hasPeer))
@@ -4,7 +4,7 @@ const Module = require('module')
4
4
  const dc = require('dc-polyfill')
5
5
 
6
6
  const log = require('../../../dd-trace/src/log')
7
- const { loadChannel } = require('./register.js')
7
+ const { activate, loadChannel } = require('./register.js')
8
8
  const {
9
9
  filename,
10
10
  getDisabledInstrumentations,
@@ -96,7 +96,7 @@ dc.subscribe(CHANNEL, (message) => {
96
96
  if (disabledInstrumentations.has(name)) return
97
97
 
98
98
  if (payload.activate && isRewriteActivationEnabled(name)) {
99
- loadChannel.publish({ name })
99
+ activate(name, payload.version)
100
100
  return
101
101
  }
102
102
 
@@ -132,8 +132,7 @@ module.exports.checkForPotentialConflicts = function () {
132
132
 
133
133
  for (const pathToModule of Object.keys(require.cache)) {
134
134
  const { pkg } = extractPackageAndModulePath(pathToModule)
135
- if (naughties.has(pkg)) continue
136
- if (!potentialConflicts.has(pkg)) continue
135
+ if (naughties.has(pkg) || !potentialConflicts.has(pkg)) continue
137
136
 
138
137
  warnings.push(() => `Warning: Package '${pkg}' may cause conflicts with dd-trace.`)
139
138
 
@@ -88,7 +88,7 @@ exports.getHooks = function getHooks (names) {
88
88
  for (const { module } of rewriterInstrumentations) {
89
89
  if (!requested.has(module.name)) continue
90
90
  // Fresh objects, including the versions array: callers may adjust a hook
91
- // for their own registration (the ai, claude-agent-sdk and
91
+ // for their own registration (the ai and
92
92
  // aws-durable-execution-sdk-js plugins set `hook.file = null`), which must
93
93
  // not leak into any other call.
94
94
  const hook = { name: module.name, versions: [module.versionRange], file: module.filePath }
@@ -14,6 +14,7 @@ const {
14
14
  matchesInstrumentation,
15
15
  } = require('./instrumentation-utils')
16
16
  const rewriter = require('./rewriter')
17
+ const { getActivationSetup } = require('./rewriter/instrumentation-registry')
17
18
 
18
19
  const DD_TRACE_DEBUG = getValueFromEnvSources('DD_TRACE_DEBUG')
19
20
 
@@ -58,6 +59,39 @@ const instrumentedIntegrationsSuccess = new Map()
58
59
  const alreadyLoggedIncompatibleIntegrations = new Set()
59
60
  /** @type {Set<string>} */
60
61
  const compatibleOrchestrionTargets = new Set()
62
+ /** @type {Set<(activation: import('./rewriter/instrumentation-registry').Activation) => void>} */
63
+ const blockedActivationSetups = new Set()
64
+
65
+ /**
66
+ * @param {string} moduleName
67
+ * @param {string} [version]
68
+ */
69
+ function activate (moduleName, version) {
70
+ const setup = getActivationSetup(moduleName)
71
+ if (setup) {
72
+ if (blockedActivationSetups.has(setup)) return
73
+ // Block re-entrant activation until setup completes, and never retry a failed setup.
74
+ blockedActivationSetups.add(setup)
75
+ try {
76
+ setup({ moduleName, version })
77
+ blockedActivationSetups.delete(setup)
78
+ } catch (error) {
79
+ const message = String(error?.message ?? error)
80
+ log.error('Error during activation setup of %s: %s', moduleName, message, error)
81
+ telemetry('error', [
82
+ `error_type:${error?.constructor?.name ?? typeof error}`,
83
+ `integration:${moduleName}`,
84
+ `integration_version:${version ?? 'unknown'}`,
85
+ ], {
86
+ result: 'error',
87
+ result_class: 'internal_error',
88
+ result_reason: `Error during activation of ${moduleName}: ${message}`,
89
+ })
90
+ return
91
+ }
92
+ }
93
+ loadChannel.publish({ name: moduleName })
94
+ }
61
95
 
62
96
  orchestrionLoadChannel.subscribe(({ moduleName, version, result }) => {
63
97
  const nameVersion = `${moduleName}@${version}`
@@ -72,7 +106,7 @@ orchestrionLoadChannel.subscribe(({ moduleName, version, result }) => {
72
106
  if (result === 'matched' || result === 'rewritten') {
73
107
  compatibleOrchestrionTargets.add(nameVersion)
74
108
  instrumentedIntegrationsSuccess.set(nameVersion, true)
75
- if (result === 'rewritten') loadChannel.publish({ name: moduleName })
109
+ if (result === 'rewritten') activate(moduleName, version)
76
110
  }
77
111
  })
78
112
 
@@ -176,6 +210,7 @@ function logAbortedIntegrations () {
176
210
  }
177
211
 
178
212
  module.exports = {
213
+ activate,
179
214
  filename,
180
215
  pathSepExpr,
181
216
  loadChannel,
@@ -188,6 +188,7 @@ function createMatcher (dcModule) {
188
188
  waitForAsyncEnd,
189
189
  } = require('./transforms')
190
190
  const {
191
+ postgresQueryAcquire,
191
192
  postgresQueryHandlers,
192
193
  postgresQueryLifecycle,
193
194
  postgresQueryPreparation,
@@ -204,6 +205,7 @@ function createMatcher (dcModule) {
204
205
  matcher.addTransform('configureGraphqlJitRuntime', configureGraphqlJitRuntime)
205
206
  matcher.addTransform('configureMercuriusRequest', configureMercuriusRequest)
206
207
  matcher.addTransform('publishDurableOrchestrationFailure', publishDurableOrchestrationFailure)
208
+ matcher.addTransform('postgresQueryAcquire', postgresQueryAcquire)
207
209
  matcher.addTransform('postgresQueryHandlers', postgresQueryHandlers)
208
210
  matcher.addTransform('postgresQueryLifecycle', postgresQueryLifecycle)
209
211
  matcher.addTransform('postgresQueryPreparation', postgresQueryPreparation)
@@ -1,14 +1,35 @@
1
1
  'use strict'
2
2
 
3
3
  // Activated rewrites publish their module name to the plugin manager after evaluation.
4
- // Only pure Orchestrion integrations that need this activation set activate: true.
4
+ // Integrations can also provide synchronous runtime setup before plugin activation.
5
+ // Setup must not load rewrite targets: re-entrant activations of the same group are dropped.
6
+ // activate: true covers every rewrite target in the entry; activate.modules narrows it to the packages
7
+ // that should trigger activation, leaving the rest of the entry rewrite-only.
5
8
  // Other entries use hooks or another activation path, or do not need activation from a rewrite.
9
+ /**
10
+ * @typedef {object} Activation
11
+ * @property {string} moduleName
12
+ * @property {string} [version]
13
+ *
14
+ * @typedef {object} ActivationConfig
15
+ * @property {string[]} [modules]
16
+ * @property {((activation: Activation) => void)} [setup]
17
+ *
18
+ * @typedef {object} InstrumentationRegistryEntry
19
+ * @property {true|ActivationConfig} [activate]
20
+ * @property {Array<{ module: { name: string } }>} instrumentations
21
+ */
22
+
23
+ /** @satisfies {InstrumentationRegistryEntry[]} */
6
24
  const registry = [
7
25
  { instrumentations: require('./instrumentations/ai') },
8
26
  { activate: true, instrumentations: require('./instrumentations/azure-cosmos') },
9
27
  { instrumentations: require('./instrumentations/azure-durable-functions') },
10
28
  { activate: true, instrumentations: require('./instrumentations/bullmq') },
11
- { instrumentations: require('./instrumentations/claude-agent-sdk') },
29
+ {
30
+ activate: { setup: () => require('../../claude-agent-sdk') },
31
+ instrumentations: require('./instrumentations/claude-agent-sdk'),
32
+ },
12
33
  { instrumentations: require('./instrumentations/graphql') },
13
34
  { instrumentations: require('./instrumentations/graphql-jit') },
14
35
  { activate: true, instrumentations: require('./instrumentations/langchain') },
@@ -19,14 +40,66 @@ const registry = [
19
40
  { instrumentations: require('./instrumentations/playwright') },
20
41
  { activate: true, instrumentations: require('./instrumentations/postgres') },
21
42
  { instrumentations: require('./instrumentations/webdriverio') },
22
- { instrumentations: require('./instrumentations/aws-durable-execution-sdk-js') },
43
+ {
44
+ activate: { setup: () => require('../../aws-durable-execution-sdk-js') },
45
+ instrumentations: require('./instrumentations/aws-durable-execution-sdk-js'),
46
+ },
23
47
  { activate: true, instrumentations: require('./instrumentations/supabase') },
24
48
  ]
25
49
 
26
50
  const activatedModules = new Set()
51
+ /** @type {Map<string, (activation: Activation) => void>} */
52
+ const activationSetups = new Map()
27
53
  for (const { activate, instrumentations } of registry) {
28
- if (!activate) continue
29
- for (const { module } of instrumentations) activatedModules.add(module.name)
54
+ if (activate === undefined) continue
55
+ if (activate !== true && (typeof activate !== 'object' || activate === null || Array.isArray(activate))) {
56
+ throw new TypeError('Instrumentation registry activate must be true or an activation config object')
57
+ }
58
+ const config = activate === true ? undefined : activate
59
+ const setup = config?.setup
60
+ if (setup !== undefined && typeof setup !== 'function') {
61
+ throw new TypeError('Instrumentation registry activate.setup must be a function')
62
+ }
63
+
64
+ const rewriteModules = new Set(instrumentations.map(({ module }) => module.name))
65
+ for (const moduleName of resolveActivationModules(config?.modules, rewriteModules)) {
66
+ if (activatedModules.has(moduleName) && activationSetups.get(moduleName) !== setup) {
67
+ throw new TypeError(`Instrumentation registry activation module "${moduleName}" has conflicting setup functions`)
68
+ }
69
+ activatedModules.add(moduleName)
70
+ if (setup) activationSetups.set(moduleName, setup)
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Activation covers every rewrite target in the entry unless it names the packages to activate. An explicit
76
+ * list keeps helper packages that share the entry rewrite-only.
77
+ * @param {string[]|undefined} modules
78
+ * @param {Set<string>} rewriteModules
79
+ * @returns {Set<string>}
80
+ */
81
+ function resolveActivationModules (modules, rewriteModules) {
82
+ if (modules === undefined) return rewriteModules
83
+ if (!Array.isArray(modules) || modules.length === 0) {
84
+ throw new TypeError('Instrumentation registry activate.modules must be a non-empty array')
85
+ }
86
+
87
+ const entryModules = new Set()
88
+ for (const moduleName of modules) {
89
+ if (typeof moduleName !== 'string' || moduleName.length === 0) {
90
+ throw new TypeError('Instrumentation registry activate.modules must contain non-empty strings')
91
+ }
92
+ if (!rewriteModules.has(moduleName)) {
93
+ throw new TypeError(
94
+ `Instrumentation registry activation module "${moduleName}" is not a rewrite target in its entry`
95
+ )
96
+ }
97
+ if (entryModules.has(moduleName)) {
98
+ throw new TypeError(`Instrumentation registry activation module "${moduleName}" is duplicated in its entry`)
99
+ }
100
+ entryModules.add(moduleName)
101
+ }
102
+ return entryModules
30
103
  }
31
104
 
32
105
  const instrumentations = registry.flatMap(entry => entry.instrumentations)
@@ -38,4 +111,12 @@ function isRewriteActivationEnabled (moduleName) {
38
111
  return activatedModules.has(moduleName)
39
112
  }
40
113
 
41
- module.exports = { isRewriteActivationEnabled, instrumentations, registry }
114
+ /**
115
+ * @param {string} moduleName
116
+ * @returns {((activation: Activation) => void)|undefined}
117
+ */
118
+ function getActivationSetup (moduleName) {
119
+ return activationSetups.get(moduleName)
120
+ }
121
+
122
+ module.exports = { getActivationSetup, isRewriteActivationEnabled, instrumentations, registry }
@@ -26,11 +26,10 @@ const COMPILE_DEFERRED_FIELD = 'FunctionDeclaration[id.name="compileDeferredFiel
26
26
  */
27
27
 
28
28
  /**
29
- * @param {GraphqlJitInstrumentation[]} instrumentations
30
29
  * @param {string} versionRange
31
30
  * @param {string} filePath
32
31
  */
33
- function addInstrumentations (instrumentations, versionRange, filePath) {
32
+ function addInstrumentations (versionRange, filePath) {
34
33
  const moduleDefinition = { name: 'graphql-jit', versionRange, filePath }
35
34
  instrumentations.push(
36
35
  {
@@ -75,9 +74,9 @@ function addInstrumentations (instrumentations, versionRange, filePath) {
75
74
  const instrumentations = []
76
75
  // graphql-jit 0.7 and 0.8.0 use this layout and remain compatible with GraphQL 15 and 16.
77
76
  // GraphQL 17 compatibility starts at 0.8.1.
78
- addInstrumentations(instrumentations, '>=0.7.0 <0.8.5 || >=0.8.7 <0.9.0', 'dist/execution.js')
79
- addInstrumentations(instrumentations, '>=0.8.5 <0.8.7', 'dist/cjs/execution.js')
80
- addInstrumentations(instrumentations, '>=0.8.5 <0.8.7', 'dist/esm/execution.js')
81
- addInstrumentations(instrumentations, '>=0.8.7 <0.9.0', 'dist/execution.mjs')
77
+ addInstrumentations('>=0.7.0 <0.8.5 || >=0.8.7 <0.9.0', 'dist/execution.js')
78
+ addInstrumentations('>=0.8.5 <0.8.7', 'dist/cjs/execution.js')
79
+ addInstrumentations('>=0.8.5 <0.8.7', 'dist/esm/execution.js')
80
+ addInstrumentations('>=0.8.7 <0.9.0', 'dist/execution.mjs')
82
81
 
83
82
  module.exports = instrumentations
@@ -1,36 +1,53 @@
1
1
  'use strict'
2
2
 
3
- const handlers = ['src/index.js', 'cjs/src/index.js'].map(filePath => ({
4
- module: {
5
- name: 'postgres',
6
- versionRange: '>=3.0.0',
7
- filePath,
8
- },
9
- astQuery: 'Program',
10
- transform: 'postgresQueryHandlers',
11
- channelName: 'query',
12
- }))
3
+ const instrumentations = []
13
4
 
14
- const preparations = ['src/connection.js', 'cjs/src/connection.js'].map(filePath => ({
15
- module: {
16
- name: 'postgres',
17
- versionRange: '>=3.0.0',
18
- filePath,
19
- },
20
- astQuery: 'Program',
21
- transform: 'postgresQueryPreparation',
22
- channelName: 'query:prepare',
23
- }))
5
+ for (const filePath of ['src/index.js', 'cjs/src/index.js']) {
6
+ instrumentations.push({
7
+ module: {
8
+ name: 'postgres',
9
+ versionRange: '>=3.0.0',
10
+ filePath,
11
+ },
12
+ astQuery: 'Program',
13
+ transform: 'postgresQueryHandlers',
14
+ channelName: 'query',
15
+ })
16
+ }
24
17
 
25
- const lifecycles = ['src/query.js', 'cjs/src/query.js'].map(filePath => ({
26
- module: {
27
- name: 'postgres',
28
- versionRange: '>=3.0.0',
29
- filePath,
30
- },
31
- astQuery: 'Program',
32
- transform: 'postgresQueryLifecycle',
33
- channelName: 'query',
34
- }))
18
+ for (const filePath of ['src/connection.js', 'cjs/src/connection.js']) {
19
+ instrumentations.push({
20
+ module: {
21
+ name: 'postgres',
22
+ versionRange: '>=3.0.0',
23
+ filePath,
24
+ },
25
+ astQuery: 'Program',
26
+ transform: 'postgresQueryAcquire',
27
+ channelName: 'query:acquire',
28
+ }, {
29
+ module: {
30
+ name: 'postgres',
31
+ versionRange: '>=3.0.0',
32
+ filePath,
33
+ },
34
+ astQuery: 'Program',
35
+ transform: 'postgresQueryPreparation',
36
+ channelName: 'query:prepare',
37
+ })
38
+ }
35
39
 
36
- module.exports = [...handlers, ...preparations, ...lifecycles]
40
+ for (const filePath of ['src/query.js', 'cjs/src/query.js']) {
41
+ instrumentations.push({
42
+ module: {
43
+ name: 'postgres',
44
+ versionRange: '>=3.0.0',
45
+ filePath,
46
+ },
47
+ astQuery: 'Program',
48
+ transform: 'postgresQueryLifecycle',
49
+ channelName: 'query',
50
+ })
51
+ }
52
+
53
+ module.exports = instrumentations
@@ -80,6 +80,19 @@ module.exports = [
80
80
  },
81
81
  channelName: 'Runner_run',
82
82
  },
83
+ {
84
+ module: {
85
+ name: '@wdio/runner',
86
+ versionRange: '>=9.0.0',
87
+ filePath: 'build/index.js',
88
+ },
89
+ functionQuery: {
90
+ className: 'Runner',
91
+ methodName: '_startSession',
92
+ kind: 'Async',
93
+ },
94
+ channelName: 'Runner_startSession',
95
+ },
83
96
  {
84
97
  module: {
85
98
  name: '@wdio/runner',
@@ -130,6 +143,33 @@ module.exports = [
130
143
  channelName: 'BaseReporter_waitForSync',
131
144
  transform: 'waitForAsyncEnd',
132
145
  },
146
+ {
147
+ module: {
148
+ name: '@wdio/mocha-framework',
149
+ versionRange: '>=9.0.0',
150
+ filePath: 'build/index.js',
151
+ },
152
+ functionQuery: {
153
+ className: 'MochaAdapter',
154
+ methodName: 'init',
155
+ kind: 'Async',
156
+ },
157
+ channelName: 'MochaAdapter_init',
158
+ },
159
+ {
160
+ module: {
161
+ name: '@wdio/mocha-framework',
162
+ versionRange: '>=9.0.0',
163
+ filePath: 'build/index.js',
164
+ },
165
+ astQuery: 'VariableDeclarator[id.name="MochaAdapter"] > ClassExpression > ClassBody > ' +
166
+ 'MethodDefinition[key.name="init"] ReturnStatement > ' +
167
+ 'CallExpression[callee.object.name="promise"][callee.property.name="then"], ' +
168
+ 'ClassDeclaration[id.name="MochaAdapter"] > ClassBody > MethodDefinition[key.name="init"] ReturnStatement > ' +
169
+ 'CallExpression[callee.object.name="promise"][callee.property.name="then"]',
170
+ channelName: 'MochaAdapter_init',
171
+ transform: 'waitForAsyncEnd',
172
+ },
133
173
  {
134
174
  module: {
135
175
  name: '@wdio/jasmine-framework',
@@ -466,9 +506,8 @@ module.exports = [
466
506
  versionRange: '>=9.0.0',
467
507
  filePath: 'build/index.js',
468
508
  },
469
- astQuery: 'TryStatement:has(CatchClause IfStatement[test.operator=">"]' +
470
- '[test.left.object.name="retries"][test.left.property.name="limit"]' +
471
- '[test.right.object.name="retries"][test.right.property.name="attempts"]) > BlockStatement',
509
+ astQuery: 'FunctionDeclaration[id.name="executeAsync"] TryStatement:has(CatchClause ' +
510
+ 'CallExpression[callee.object.name="executeAsync"][callee.property.name="call"]) > BlockStatement',
472
511
  channelName: 'executeAsync',
473
512
  transform: 'awaitContextCallback',
474
513
  transformOptions: {
@@ -481,10 +520,8 @@ module.exports = [
481
520
  versionRange: '>=9.0.0',
482
521
  filePath: 'build/index.js',
483
522
  },
484
- astQuery: 'FunctionDeclaration[id.name="executeAsync"] CatchClause ' +
485
- 'IfStatement[test.operator=">"][test.left.object.name="retries"]' +
486
- '[test.left.property.name="limit"][test.right.object.name="retries"]' +
487
- '[test.right.property.name="attempts"]',
523
+ astQuery: 'FunctionDeclaration[id.name="executeAsync"] CatchClause > BlockStatement > ' +
524
+ 'IfStatement:has(CallExpression[callee.object.name="executeAsync"][callee.property.name="call"])',
488
525
  channelName: 'executeAsync',
489
526
  transform: 'awaitContextCallback',
490
527
  transformOptions: {
@@ -495,12 +532,15 @@ module.exports = [
495
532
  {
496
533
  module: {
497
534
  name: 'jasmine-core',
498
- versionRange: '>=5.0.0 <6.0.0',
535
+ versionRange: '>=5.0.0 <7.0.0',
499
536
  filePath: 'lib/jasmine-core/jasmine.js',
500
537
  },
501
538
  astQuery: 'AssignmentExpression[left.object.object.name="Spec"]' +
502
539
  '[left.object.property.name="prototype"][left.property.name="execute"] > FunctionExpression',
540
+ // A method name keeps the original function expression, so the start context
541
+ // carries `self` (the legacy Spec) that the WebdriverIO Jasmine lifecycle reads.
503
542
  functionQuery: {
543
+ methodName: 'execute',
504
544
  kind: 'Sync',
505
545
  },
506
546
  channelName: 'Spec_execute',
@@ -508,7 +548,7 @@ module.exports = [
508
548
  {
509
549
  module: {
510
550
  name: 'jasmine-core',
511
- versionRange: '>=5.0.0 <6.0.0',
551
+ versionRange: '>=5.0.0 <7.0.0',
512
552
  filePath: 'lib/jasmine-core/jasmine.js',
513
553
  },
514
554
  astQuery: 'AssignmentExpression[left.object.object.name="Spec"]' +
@@ -521,7 +561,20 @@ module.exports = [
521
561
  {
522
562
  module: {
523
563
  name: 'jasmine-core',
524
- versionRange: '>=5.0.0 <6.0.0',
564
+ versionRange: '>=5.0.0 <7.0.0',
565
+ filePath: 'lib/jasmine-core/jasmine.js',
566
+ },
567
+ functionQuery: {
568
+ className: 'Spec',
569
+ methodName: 'status',
570
+ kind: 'Sync',
571
+ },
572
+ channelName: 'Spec_attemptDone',
573
+ },
574
+ {
575
+ module: {
576
+ name: 'jasmine-core',
577
+ versionRange: '>=5.0.0 <7.0.0',
525
578
  filePath: 'lib/jasmine-core/jasmine.js',
526
579
  },
527
580
  functionQuery: {
@@ -534,7 +587,7 @@ module.exports = [
534
587
  {
535
588
  module: {
536
589
  name: 'jasmine-core',
537
- versionRange: '>=5.0.0 <6.0.0',
590
+ versionRange: '>=5.0.0 <7.0.0',
538
591
  filePath: 'lib/jasmine-core/jasmine.js',
539
592
  },
540
593
  functionQuery: {
@@ -45,6 +45,7 @@
45
45
  "@wdio/config/build/node/index.js": "@wdio/config",
46
46
  "@wdio/jasmine-framework/build/index.js": "@wdio/jasmine-framework",
47
47
  "@wdio/local-runner/build/index.js": "@wdio/local-runner",
48
+ "@wdio/mocha-framework/build/index.js": "@wdio/mocha-framework",
48
49
  "@wdio/runner/build/index.js": "@wdio/runner",
49
50
  "@wdio/utils/build/index.js": "@wdio/utils",
50
51
  "ai/dist/index.js": "ai",