@openclaw/discord 2026.6.33 → 2026.6.35

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 (179) hide show
  1. package/dist/action-runtime-api.js +1 -1
  2. package/dist/{api-CjnGBhM3.js → api-1GXlSrYP.js} +42 -21
  3. package/dist/api.js +14 -14
  4. package/dist/{approval-handler.runtime-BWPQrzpP.js → approval-handler.runtime-Dv4p7REU.js} +3 -3
  5. package/dist/{audit-BwJ_2OjL.js → audit-DEVi9nIs.js} +3 -3
  6. package/dist/{channel-Ddnonoy4.js → channel-CQIRiosn.js} +15 -15
  7. package/dist/{channel-actions-CwmIqnYN.js → channel-actions-JziPEcBU.js} +2 -2
  8. package/dist/{channel-actions.runtime-DvpTfaJ4.js → channel-actions.runtime-D7L47LY3.js} +5 -5
  9. package/dist/channel-plugin-api.js +1 -1
  10. package/dist/{channel.setup-glZ5Y98a.js → channel.setup-oMeR19Cc.js} +2 -2
  11. package/dist/{components-j6lTZBsT.js → components-_s5UPJqU.js} +1 -1
  12. package/dist/{conversation-identity-36FFBwm5.js → conversation-identity-B0k94-bz.js} +2 -2
  13. package/dist/{directory-config-BYMFzL29.js → directory-config-CD1svkyN.js} +1 -1
  14. package/dist/directory-contract-api.js +1 -1
  15. package/dist/{directory-live-9JtJCiu8.js → directory-live-DBTsSRxl.js} +5 -5
  16. package/dist/{handle-action.guild-admin-xxGYrp-I.js → handle-action.guild-admin-CYIFMxh-.js} +2 -2
  17. package/dist/index.js +1 -1
  18. package/dist/{manager.runtime-BK6cf2Zu.js → manager.runtime-BZVdGX2d.js} +17 -9
  19. package/dist/{message-handler-BqpJIavO.js → message-handler-DZd9Bpq8.js} +7 -6
  20. package/dist/{message-handler.preflight-C90MxCcv.js → message-handler.preflight-Axv9J9EO.js} +12 -11
  21. package/dist/{message-handler.process-CeQ7Bd_3.js → message-handler.process-CG0zFS-Z.js} +10 -10
  22. package/dist/{message-utils-CJeAoISH.js → message-utils-Dbuw27gd.js} +1 -1
  23. package/dist/{outbound-adapter-Dxs6iKEq.js → outbound-adapter-CKC_kmUN.js} +6 -6
  24. package/dist/pluralkit-CfTReLl3.js +40 -0
  25. package/dist/{probe-esE_Oqdm.js → probe-DcgZIpyF.js} +3 -2
  26. package/dist/{probe.runtime-C3Atgpvr.js → probe.runtime-CVwM9L5E.js} +1 -1
  27. package/dist/{provider-C7376XFH.js → provider-CwwSXIIj.js} +102 -37
  28. package/dist/{provider-session.runtime-CCdqogGf.js → provider-session.runtime-reBWkqHZ.js} +3 -3
  29. package/dist/provider.runtime-BsmTLYS_.js +2 -0
  30. package/dist/{resolve-allowlist-common-3gB2Gpmm.js → resolve-allowlist-common-D7bZqAw3.js} +3 -3
  31. package/dist/{resolve-channels-B3gQf8QL.js → resolve-channels--oE-RnO6.js} +6 -6
  32. package/dist/{resolve-users-BO10y5fJ.js → resolve-users-QXo8CXBU.js} +5 -5
  33. package/dist/{runtime-CFlR3L9X.js → runtime-CF7ramAs.js} +7 -7
  34. package/dist/runtime-api.actions.js +2 -2
  35. package/dist/runtime-api.js +19 -19
  36. package/dist/runtime-api.lookup.js +5 -5
  37. package/dist/runtime-api.monitor-CzF8MUl_.js +6 -0
  38. package/dist/runtime-api.monitor.js +5 -5
  39. package/dist/runtime-api.send.js +5 -5
  40. package/dist/runtime-api.threads.js +3 -3
  41. package/dist/{send-JHxfT4Pk.js → send-Bb295iHT.js} +5 -5
  42. package/dist/{send.components-CN35E2Ck.js → send.components-COkDUO3B.js} +4 -4
  43. package/dist/{send.outbound-B-cA1Esv.js → send.outbound-B_sk0hNe.js} +3 -3
  44. package/dist/{send.receipt-CGecJDin.js → send.receipt-Cli6_9Sn.js} +19 -7
  45. package/dist/{send.shared-vcbfThdy.js → send.shared-BCG7MWnP.js} +2 -2
  46. package/dist/session-binding-contract-api.js +1 -1
  47. package/dist/setup-plugin-api.js +1 -1
  48. package/dist/{subagent-hooks-20wXhVzZ.js → subagent-hooks-CtqoWK4x.js} +2 -2
  49. package/dist/subagent-hooks-api.js +1 -1
  50. package/dist/{system-events-DR27TE7p.js → system-events-BxGNk_wE.js} +1 -1
  51. package/dist/{target-resolver-CDi1gI90.js → target-resolver-BcoK6b0g.js} +2 -2
  52. package/dist/targets-Q-ZoP7K4.js +3 -0
  53. package/dist/{thread-bindings-DU4T6nDo.js → thread-bindings-DJ_HT6GJ.js} +4 -4
  54. package/dist/{thread-bindings.discord-api-CYkr-3Gj.js → thread-bindings.discord-api-OPyjvgyz.js} +4 -4
  55. package/dist/{thread-bindings.manager-BqWs1UE2.js → thread-bindings.manager-Cd2HAVw_.js} +3 -3
  56. package/dist/{transcripts-source-D-lBI5ZD.js → transcripts-source-CPf5gURy.js} +1 -1
  57. package/dist/transcripts-source-api.js +1 -1
  58. package/dist/{typing-xr05bL-r.js → typing-DY0cwLdg.js} +1 -1
  59. package/node_modules/undici/README.md +8 -2
  60. package/node_modules/undici/docs/docs/api/Agent.md +248 -44
  61. package/node_modules/undici/docs/docs/api/BalancedPool.md +246 -48
  62. package/node_modules/undici/docs/docs/api/CacheStorage.md +171 -13
  63. package/node_modules/undici/docs/docs/api/CacheStore.md +294 -98
  64. package/node_modules/undici/docs/docs/api/Client.md +386 -179
  65. package/node_modules/undici/docs/docs/api/ClientStats.md +80 -14
  66. package/node_modules/undici/docs/docs/api/Connector.md +118 -36
  67. package/node_modules/undici/docs/docs/api/ContentType.md +65 -25
  68. package/node_modules/undici/docs/docs/api/Cookies.md +122 -71
  69. package/node_modules/undici/docs/docs/api/Debug.md +34 -18
  70. package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +364 -164
  71. package/node_modules/undici/docs/docs/api/Dispatcher.md +485 -1102
  72. package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +102 -87
  73. package/node_modules/undici/docs/docs/api/Errors.md +503 -40
  74. package/node_modules/undici/docs/docs/api/EventSource.md +298 -32
  75. package/node_modules/undici/docs/docs/api/Fetch.md +680 -31
  76. package/node_modules/undici/docs/docs/api/GlobalInstallation.md +78 -98
  77. package/node_modules/undici/docs/docs/api/H2CClient.md +298 -176
  78. package/node_modules/undici/docs/docs/api/Interceptors.md +418 -0
  79. package/node_modules/undici/docs/docs/api/MockAgent.md +333 -314
  80. package/node_modules/undici/docs/docs/api/MockCallHistory.md +272 -98
  81. package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +189 -26
  82. package/node_modules/undici/docs/docs/api/MockClient.md +151 -33
  83. package/node_modules/undici/docs/docs/api/MockErrors.md +56 -5
  84. package/node_modules/undici/docs/docs/api/MockPool.md +321 -258
  85. package/node_modules/undici/docs/docs/api/Pool.md +235 -43
  86. package/node_modules/undici/docs/docs/api/PoolStats.md +119 -13
  87. package/node_modules/undici/docs/docs/api/ProxyAgent.md +179 -160
  88. package/node_modules/undici/docs/docs/api/RedirectHandler.md +238 -63
  89. package/node_modules/undici/docs/docs/api/RetryAgent.md +113 -26
  90. package/node_modules/undici/docs/docs/api/RetryHandler.md +161 -77
  91. package/node_modules/undici/docs/docs/api/RoundRobinPool.md +166 -72
  92. package/node_modules/undici/docs/docs/api/SnapshotAgent.md +264 -542
  93. package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +177 -196
  94. package/node_modules/undici/docs/docs/api/Util.md +68 -11
  95. package/node_modules/undici/docs/docs/api/WebSocket.md +475 -80
  96. package/node_modules/undici/docs/docs/api/api-lifecycle.md +100 -32
  97. package/node_modules/undici/docs/docs/best-practices/client-certificate.md +2 -0
  98. package/node_modules/undici/docs/docs/best-practices/crawling.md +3 -1
  99. package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +6 -4
  100. package/node_modules/undici/docs/docs/best-practices/mocking-request.md +9 -7
  101. package/node_modules/undici/docs/docs/best-practices/proxy.md +3 -1
  102. package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +10 -8
  103. package/node_modules/undici/docs/docs/best-practices/writing-tests.md +2 -0
  104. package/node_modules/undici/docs/docs/{GettingStarted.md → getting-started.md} +22 -19
  105. package/node_modules/undici/docs/docs/index.md +784 -0
  106. package/node_modules/undici/docs/docs/site.json +125 -0
  107. package/node_modules/undici/docs/docs/type-map.json +79 -0
  108. package/node_modules/undici/lib/api/api-request.js +7 -1
  109. package/node_modules/undici/lib/api/readable.js +42 -7
  110. package/node_modules/undici/lib/cache/memory-cache-store.js +56 -11
  111. package/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
  112. package/node_modules/undici/lib/core/connect.js +16 -2
  113. package/node_modules/undici/lib/core/errors.js +20 -0
  114. package/node_modules/undici/lib/core/request.js +14 -3
  115. package/node_modules/undici/lib/core/symbols.js +3 -0
  116. package/node_modules/undici/lib/core/util.js +30 -2
  117. package/node_modules/undici/lib/dispatcher/agent.js +10 -5
  118. package/node_modules/undici/lib/dispatcher/balanced-pool.js +7 -4
  119. package/node_modules/undici/lib/dispatcher/client-h1.js +74 -9
  120. package/node_modules/undici/lib/dispatcher/client-h2.js +483 -151
  121. package/node_modules/undici/lib/dispatcher/client.js +76 -30
  122. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +13 -1
  123. package/node_modules/undici/lib/dispatcher/dispatcher.js +15 -1
  124. package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +3 -0
  125. package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +37 -8
  126. package/node_modules/undici/lib/dispatcher/proxy-agent.js +58 -7
  127. package/node_modules/undici/lib/dispatcher/retry-agent.js +3 -0
  128. package/node_modules/undici/lib/dispatcher/round-robin-pool.js +1 -1
  129. package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +106 -22
  130. package/node_modules/undici/lib/global.js +36 -16
  131. package/node_modules/undici/lib/handler/cache-handler.js +297 -65
  132. package/node_modules/undici/lib/handler/cache-revalidation-handler.js +13 -3
  133. package/node_modules/undici/lib/handler/decorator-handler.js +7 -1
  134. package/node_modules/undici/lib/handler/deduplication-handler.js +12 -6
  135. package/node_modules/undici/lib/handler/redirect-handler.js +26 -5
  136. package/node_modules/undici/lib/handler/retry-handler.js +238 -51
  137. package/node_modules/undici/lib/interceptor/cache.js +221 -58
  138. package/node_modules/undici/lib/interceptor/decompress.js +124 -15
  139. package/node_modules/undici/lib/interceptor/deduplicate.js +5 -4
  140. package/node_modules/undici/lib/interceptor/dns.js +7 -0
  141. package/node_modules/undici/lib/interceptor/dump.js +10 -23
  142. package/node_modules/undici/lib/mock/mock-agent.js +13 -1
  143. package/node_modules/undici/lib/mock/mock-interceptor.js +25 -7
  144. package/node_modules/undici/lib/mock/mock-utils.js +246 -27
  145. package/node_modules/undici/lib/util/cache.js +415 -71
  146. package/node_modules/undici/lib/util/date.js +23 -6
  147. package/node_modules/undici/lib/web/cookies/parse.js +150 -146
  148. package/node_modules/undici/lib/web/cookies/util.js +79 -9
  149. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +28 -1
  150. package/node_modules/undici/lib/web/eventsource/eventsource.js +13 -3
  151. package/node_modules/undici/lib/web/eventsource/util.js +1 -1
  152. package/node_modules/undici/lib/web/fetch/body.js +2 -1
  153. package/node_modules/undici/lib/web/fetch/constants.js +1 -1
  154. package/node_modules/undici/lib/web/fetch/index.js +17 -2
  155. package/node_modules/undici/lib/web/fetch/request.js +2 -3
  156. package/node_modules/undici/lib/web/fetch/response.js +1 -3
  157. package/node_modules/undici/lib/web/fetch/util.js +10 -2
  158. package/node_modules/undici/lib/web/webidl/index.js +3 -3
  159. package/node_modules/undici/lib/web/websocket/connection.js +1 -1
  160. package/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
  161. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -10
  162. package/node_modules/undici/lib/web/websocket/websocket.js +22 -0
  163. package/node_modules/undici/package.json +4 -4
  164. package/node_modules/undici/types/client.d.ts +53 -3
  165. package/node_modules/undici/types/cookies.d.ts +1 -1
  166. package/node_modules/undici/types/dispatcher.d.ts +3 -3
  167. package/node_modules/undici/types/errors.d.ts +10 -0
  168. package/node_modules/undici/types/handlers.d.ts +2 -0
  169. package/node_modules/undici/types/interceptors.d.ts +2 -0
  170. package/node_modules/undici/types/mock-agent.d.ts +11 -10
  171. package/node_modules/undici/types/mock-interceptor.d.ts +5 -1
  172. package/node_modules/undici/types/proxy-agent.d.ts +7 -0
  173. package/node_modules/undici/types/socks5-proxy-agent.d.ts +2 -0
  174. package/npm-shrinkwrap.json +7 -7
  175. package/package.json +6 -5
  176. package/dist/pluralkit-DI6RYaVj.js +0 -24
  177. package/dist/provider.runtime-D1m66kDS.js +0 -2
  178. package/dist/runtime-api.monitor-4oc58TSk.js +0 -6
  179. package/dist/targets-C6yd3y8R.js +0 -3
@@ -53,10 +53,8 @@ const {
53
53
  kHTTPContext,
54
54
  kMaxConcurrentStreams,
55
55
  kHostAuthority,
56
- kHTTP2InitialWindowSize,
57
- kHTTP2ConnectionWindowSize,
58
56
  kResume,
59
- kPingInterval
57
+ kHTTP2Options
60
58
  } = require('../core/symbols.js')
61
59
  const connectH1 = require('./client-h1.js')
62
60
  const connectH2 = require('./client-h2.js')
@@ -76,6 +74,16 @@ function getPipelining (client) {
76
74
  return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1
77
75
  }
78
76
 
77
+ let h2NamespaceOptsWarning = false
78
+ function emitH2OptionsNamespaceWarning (optName) {
79
+ if (h2NamespaceOptsWarning === true) return
80
+
81
+ process.emitWarning(`Use h2Options.${optName} instead. ${optName} for H2 will be deprecated in future major.`, {
82
+ code: 'UNDICI-H2-OPTIONS'
83
+ })
84
+ h2NamespaceOptsWarning = true
85
+ }
86
+
79
87
  // Protocol-aware dispatch ceiling. h1 RFC7230 pipelining is unrelated to h2
80
88
  // stream multiplexing — over h2 the ceiling is the (server-confirmed)
81
89
  // maxConcurrentStreams. Before a context is attached we use the h1
@@ -128,7 +136,9 @@ class Client extends DispatcherBase {
128
136
  initialWindowSize,
129
137
  connectionWindowSize,
130
138
  pingInterval,
131
- webSocket
139
+ webSocket,
140
+ h2Options,
141
+ eventSource
132
142
  } = {}) {
133
143
  if (keepAlive !== undefined) {
134
144
  throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead')
@@ -216,35 +226,66 @@ class Client extends DispatcherBase {
216
226
  throw new InvalidArgumentError('allowH2 must be a valid boolean value')
217
227
  }
218
228
 
219
- if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) {
220
- throw new InvalidArgumentError('maxConcurrentStreams must be a positive integer, greater than 0')
221
- }
229
+ // We validate only if allowH2 is enabled or null (enabled by default)
230
+ if (allowH2 !== false) {
231
+ // Prioritise new h2Options object, otherwise fallback to prior configuration options
232
+ if (h2Options != null) {
233
+ if (h2Options.useH2c != null && typeof h2Options.useH2c !== 'boolean') {
234
+ throw new InvalidArgumentError('h2Options.useH2c must be a valid boolean value')
235
+ }
222
236
 
223
- if (useH2c != null && typeof useH2c !== 'boolean') {
224
- throw new InvalidArgumentError('useH2c must be a valid boolean value')
225
- }
237
+ if (h2Options.settings?.initialWindowSize != null && (!Number.isInteger(h2Options.settings.initialWindowSize) || h2Options.settings.initialWindowSize < 1)) {
238
+ throw new InvalidArgumentError('h2Options.settings.initialWindowSize must be a positive integer, greater than 0')
239
+ }
226
240
 
227
- if (initialWindowSize != null && (!Number.isInteger(initialWindowSize) || initialWindowSize < 1)) {
228
- throw new InvalidArgumentError('initialWindowSize must be a positive integer, greater than 0')
229
- }
241
+ if (h2Options.maxConcurrentStreams != null && (!Number.isInteger(h2Options.connectionWindowSize) || h2Options.maxConcurrentStreams < 1)) {
242
+ throw new InvalidArgumentError('h2Options.maxConcurrentStreams must be a positive integer, greater than 0')
243
+ }
230
244
 
231
- if (connectionWindowSize != null && (!Number.isInteger(connectionWindowSize) || connectionWindowSize < 1)) {
232
- throw new InvalidArgumentError('connectionWindowSize must be a positive integer, greater than 0')
233
- }
245
+ if (h2Options.connectionWindowSize != null && (!Number.isInteger(h2Options.connectionWindowSize) || h2Options.connectionWindowSize < 1)) {
246
+ throw new InvalidArgumentError('h2Options.connectionWindowSize must be a positive integer, greater than 0')
247
+ }
248
+
249
+ if (h2Options.pingInterval != null && (typeof h2Options.pingInterval !== 'number' || !Number.isInteger(h2Options.pingInterval) || h2Options.pingInterval < 0)) {
250
+ throw new InvalidArgumentError('h2Options.pingInterval must be a positive integer, greater or equal to 0')
251
+ }
252
+ } else {
253
+ if (useH2c != null && typeof useH2c !== 'boolean') {
254
+ emitH2OptionsNamespaceWarning('useH2c')
255
+ throw new InvalidArgumentError('useH2c must be a valid boolean value')
256
+ }
257
+
258
+ if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) {
259
+ emitH2OptionsNamespaceWarning('maxConcurrentStreams')
260
+ throw new InvalidArgumentError('maxConcurrentStreams must be a positive integer, greater than 0')
261
+ }
234
262
 
235
- if (pingInterval != null && (typeof pingInterval !== 'number' || !Number.isInteger(pingInterval) || pingInterval < 0)) {
236
- throw new InvalidArgumentError('pingInterval must be a positive integer, greater or equal to 0')
263
+ if (initialWindowSize != null && (!Number.isInteger(initialWindowSize) || initialWindowSize < 1)) {
264
+ emitH2OptionsNamespaceWarning('initialWindowSize')
265
+ throw new InvalidArgumentError('initialWindowSize must be a positive integer, greater than 0')
266
+ }
267
+
268
+ if (connectionWindowSize != null && (!Number.isInteger(connectionWindowSize) || connectionWindowSize < 1)) {
269
+ emitH2OptionsNamespaceWarning('connectionWindowSize')
270
+ throw new InvalidArgumentError('connectionWindowSize must be a positive integer, greater than 0')
271
+ }
272
+
273
+ if (pingInterval != null && (typeof pingInterval !== 'number' || !Number.isInteger(pingInterval) || pingInterval < 0)) {
274
+ emitH2OptionsNamespaceWarning('pingInterval')
275
+ throw new InvalidArgumentError('pingInterval must be a positive integer, greater or equal to 0')
276
+ }
277
+ }
237
278
  }
238
279
 
239
- super({ webSocket })
280
+ super({ webSocket, eventSource })
240
281
 
241
282
  if (typeof connect !== 'function') {
242
283
  connect = buildConnector({
243
284
  ...tls,
244
285
  maxCachedSessions,
245
286
  allowH2,
246
- useH2c,
247
287
  socketPath,
288
+ useH2c: h2Options?.useH2c ?? useH2c,
248
289
  timeout: connectTimeout,
249
290
  ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
250
291
  ...connect
@@ -280,16 +321,20 @@ class Client extends DispatcherBase {
280
321
  this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1
281
322
  this[kHTTPContext] = null
282
323
  // h2
283
- this[kMaxConcurrentStreams] = maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server
284
- // HTTP/2 window sizes are set to higher defaults than Node.js core for better performance:
285
- // - initialWindowSize: 262144 (256KB) vs Node.js default 65535 (64KB - 1)
286
- // Allows more data to be sent before requiring acknowledgment, improving throughput
287
- // especially on high-latency networks. This matches common production HTTP/2 servers.
288
- // - connectionWindowSize: 524288 (512KB) vs Node.js default (none set)
289
- // Provides better flow control for the entire connection across multiple streams.
290
- this[kHTTP2InitialWindowSize] = initialWindowSize != null ? initialWindowSize : 262144
291
- this[kHTTP2ConnectionWindowSize] = connectionWindowSize != null ? connectionWindowSize : 524288
292
- this[kPingInterval] = pingInterval != null ? pingInterval : 60e3 // Default ping interval for h2 - 1 minute
324
+ this[kHTTP2Options] = {
325
+ pingInterval: h2Options?.pingInterval ?? pingInterval ?? 60e3,
326
+ connectionWindowSize: h2Options?.connectionWindowSize ?? connectionWindowSize ?? 524288,
327
+ maxConcurrentStreams: h2Options?.maxConcurrentStreams ?? maxConcurrentStreams ?? 100, // Max peerConcurrentStreams for a Node h2 server
328
+ sessionOptions: {
329
+ // HTTP/2 window sizes are set to higher defaults than Node.js core for better performance:
330
+ // - initialWindowSize: 262144 (256KB) vs Node.js default 65535 (64KB - 1)
331
+ // Allows more data to be sent before requiring acknowledgment, improving throughput
332
+ // especially on high-latency networks. This matches common production HTTP/2 servers.
333
+ // - connectionWindowSize: 524288 (512KB) vs Node.js default (none set)
334
+ // Provides better flow control for the entire connection across multiple streams.
335
+ initialWindowSize: h2Options?.initialWindowSize ?? initialWindowSize ?? 262144
336
+ }
337
+ }
293
338
 
294
339
  // kQueue is built up of 3 sections separated by
295
340
  // the kRunningIdx and kPendingIdx indices.
@@ -672,6 +717,7 @@ function _resume (client, sync) {
672
717
  }
673
718
 
674
719
  if (!client[kHTTPContext]) {
720
+ client[kServerName] = request.servername
675
721
  connect(client)
676
722
  return
677
723
  }
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const buffer = require('node:buffer')
3
4
  const Dispatcher = require('./dispatcher')
4
5
  const {
5
6
  ClientDestroyedError,
@@ -11,6 +12,7 @@ const { kDestroy, kClose, kClosed, kDestroyed, kDispatch } = require('../core/sy
11
12
  const kOnDestroyed = Symbol('onDestroyed')
12
13
  const kOnClosed = Symbol('onClosed')
13
14
  const kWebSocketOptions = Symbol('webSocketOptions')
15
+ const kEventSourceOptions = Symbol('eventSourceOptions')
14
16
 
15
17
  class DispatcherBase extends Dispatcher {
16
18
  /** @type {boolean} */
@@ -31,10 +33,11 @@ class DispatcherBase extends Dispatcher {
31
33
  constructor (opts) {
32
34
  super()
33
35
  this[kWebSocketOptions] = opts?.webSocket ?? {}
36
+ this[kEventSourceOptions] = opts?.eventSource ?? {}
34
37
  }
35
38
 
36
39
  /**
37
- * @returns {import('../../types/dispatcher').WebSocketOptions}
40
+ * @returns {import('../../types/client').Client.WebSocketOptions}
38
41
  */
39
42
  get webSocketOptions () {
40
43
  return {
@@ -43,6 +46,15 @@ class DispatcherBase extends Dispatcher {
43
46
  }
44
47
  }
45
48
 
49
+ /**
50
+ * @returns {import('../../types/client').Client.EventSourceOptions}
51
+ */
52
+ get eventSourceOptions () {
53
+ return {
54
+ maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength
55
+ }
56
+ }
57
+
46
58
  /** @returns {boolean} */
47
59
  get destroyed () {
48
60
  return this[kDestroyed]
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
  const EventEmitter = require('node:events')
3
+ const { kOriginless, kUrl } = require('../core/symbols')
3
4
 
4
5
  class Dispatcher extends EventEmitter {
5
6
  dispatch () {
@@ -17,6 +18,10 @@ class Dispatcher extends EventEmitter {
17
18
  compose (...args) {
18
19
  // So we handle [interceptor1, interceptor2] or interceptor1, interceptor2, ...
19
20
  const interceptors = Array.isArray(args[0]) ? args[0] : args
21
+ // null disables origin-dependent interceptors; undefined uses opts.origin.
22
+ const interceptorOrigin = this[kOriginless] === true
23
+ ? null
24
+ : this[kUrl]?.origin
20
25
  let dispatch = this.dispatch.bind(this)
21
26
 
22
27
  for (const interceptor of interceptors) {
@@ -28,13 +33,22 @@ class Dispatcher extends EventEmitter {
28
33
  throw new TypeError(`invalid interceptor, expected function received ${typeof interceptor}`)
29
34
  }
30
35
 
31
- dispatch = interceptor(dispatch)
36
+ dispatch = interceptor(dispatch, interceptorOrigin)
32
37
 
33
38
  if (dispatch == null || typeof dispatch !== 'function' || dispatch.length !== 2) {
34
39
  throw new TypeError('invalid interceptor')
35
40
  }
36
41
  }
37
42
 
43
+ const originalDispatch = dispatch
44
+ const self = this
45
+ dispatch = function (opts, handler) {
46
+ if (opts && typeof opts === 'object' && !opts.origin && self[kUrl]) {
47
+ opts = Object.assign({}, opts, { origin: self[kUrl].origin })
48
+ }
49
+ return originalDispatch(opts, handler)
50
+ }
51
+
38
52
  return new Proxy(this, {
39
53
  get: (target, key) => key === 'dispatch' ? dispatch : target[key]
40
54
  })
@@ -3,6 +3,7 @@
3
3
  const Dispatcher = require('./dispatcher')
4
4
  const { InvalidArgumentError } = require('../core/errors')
5
5
  const { toRawHeaders } = require('../core/util')
6
+ const { kOriginless, kUrl } = require('../core/symbols')
6
7
 
7
8
  class LegacyHandlerWrapper {
8
9
  #handler
@@ -71,6 +72,8 @@ class Dispatcher1Wrapper extends Dispatcher {
71
72
  }
72
73
 
73
74
  this.#dispatcher = dispatcher
75
+ this[kUrl] = dispatcher[kUrl]
76
+ this[kOriginless] = dispatcher[kOriginless]
74
77
  }
75
78
 
76
79
  static wrapHandler (handler) {
@@ -16,7 +16,7 @@ class EnvHttpProxyAgent extends DispatcherBase {
16
16
  #opts = null
17
17
 
18
18
  constructor (opts = {}) {
19
- super()
19
+ super(opts)
20
20
  this.#opts = opts
21
21
 
22
22
  const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts
@@ -65,9 +65,17 @@ class EnvHttpProxyAgent extends DispatcherBase {
65
65
  #getProxyAgentForUrl (url) {
66
66
  let { protocol, host: hostname, port } = url
67
67
 
68
- // Stripping ports in this way instead of using parsedUrl.hostname to make
69
- // sure that the brackets around IPv6 addresses are kept.
70
- hostname = hostname.replace(/:\d*$/, '').toLowerCase()
68
+ // Remove the port suffix (e.g. ":8080") and then strip surrounding
69
+ // brackets from IPv6 literals (e.g. "[::1]" -> "::1") so that the
70
+ // result matches the unbracketed form stored by #parseNoProxy.
71
+ hostname = hostname.replace(/:\d*$/, '').replace(/^\[(.+)\]$/, '$1').toLowerCase()
72
+ // Drop a trailing dot: it only marks the fully qualified form of a domain
73
+ // name ("example.com." and "example.com" are the same name, RFC 1034 root
74
+ // label). This runs on every dispatch, so it is a charCode check rather
75
+ // than a third regex. `length > 1` leaves the degenerate host "." alone.
76
+ if (hostname.length > 1 && hostname.charCodeAt(hostname.length - 1) === 46) {
77
+ hostname = hostname.slice(0, -1)
78
+ }
71
79
  port = Number.parseInt(port, 10) || DEFAULT_PORTS[protocol] || 0
72
80
  if (!this.#shouldProxy(hostname, port)) {
73
81
  return this[kNoProxyAgent]
@@ -119,11 +127,32 @@ class EnvHttpProxyAgent extends DispatcherBase {
119
127
  if (!entry) {
120
128
  continue
121
129
  }
122
- const parsed = entry.match(/^(.+):(\d+)$/)
130
+
131
+ // An IPv6 entry with a port must be bracketed: [::1]:443.
132
+ // A bare IPv6 address like ::1 contains colons that must not be
133
+ // confused with a host:port separator, so we handle it separately.
134
+ let hostname, port
135
+ const ipv6WithPort = entry.match(/^\[(.+)\]:(\d+)$/)
136
+ if (ipv6WithPort) {
137
+ hostname = ipv6WithPort[1]
138
+ port = Number.parseInt(ipv6WithPort[2], 10)
139
+ } else {
140
+ // Bracketed IPv6 without port, or plain hostname[:port], or bare IPv6.
141
+ // Strip optional brackets first.
142
+ const unbracketed = entry.replace(/^\[(.+)\]$/, '$1')
143
+ // A bare IPv6 address contains multiple colons; a hostname:port entry
144
+ // has exactly one colon followed by digits. Only attempt host:port
145
+ // splitting when that is unambiguously the case.
146
+ const colonCount = (unbracketed.match(/:/g) || []).length
147
+ const parsed = colonCount === 1 && unbracketed.match(/^(.+):(\d+)$/)
148
+ hostname = parsed ? parsed[1] : unbracketed
149
+ port = parsed ? Number.parseInt(parsed[2], 10) : 0
150
+ }
151
+
123
152
  noProxyEntries.push({
124
- // strip leading dot or asterisk with dot
125
- hostname: (parsed ? parsed[1] : entry).replace(/^\*?\./, '').toLowerCase(),
126
- port: parsed ? Number.parseInt(parsed[2], 10) : 0
153
+ // strip leading dot or asterisk with dot, and any trailing dot
154
+ hostname: hostname.replace(/^\*?\./, '').replace(/^(.+)\.$/, '$1').toLowerCase(),
155
+ port
127
156
  })
128
157
  }
129
158
 
@@ -4,11 +4,12 @@ const { kProxy, kClose, kDestroy, kDispatch } = require('../core/symbols')
4
4
  const Agent = require('./agent')
5
5
  const Pool = require('./pool')
6
6
  const DispatcherBase = require('./dispatcher-base')
7
- const { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = require('../core/errors')
7
+ const { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError, ProxyConnectionError } = require('../core/errors')
8
8
  const buildConnector = require('../core/connect')
9
9
  const Client = require('./client')
10
10
  const { channels } = require('../core/diagnostics')
11
11
  const Socks5ProxyAgent = require('./socks5-proxy-agent')
12
+ const { hasSafeIterator } = require('../core/util')
12
13
 
13
14
  const kAgent = Symbol('proxy agent')
14
15
  const kClient = Symbol('proxy client')
@@ -37,10 +38,15 @@ function defaultAgentFactory (origin, opts) {
37
38
  return new Pool(origin, opts)
38
39
  }
39
40
 
41
+ function shouldProxyTunnel (requestProtocol, proxyTunnel) {
42
+ return proxyTunnel === true || requestProtocol !== 'http:'
43
+ }
44
+
40
45
  class Http1ProxyWrapper extends DispatcherBase {
41
46
  #client
47
+ #proxyServername
42
48
 
43
- constructor (proxyUrl, { headers = {}, connect, factory }) {
49
+ constructor (proxyUrl, { headers = {}, connect, factory, proxyServername }) {
44
50
  if (!proxyUrl) {
45
51
  throw new InvalidArgumentError('Proxy URL is mandatory')
46
52
  }
@@ -48,6 +54,7 @@ class Http1ProxyWrapper extends DispatcherBase {
48
54
  super()
49
55
 
50
56
  this[kProxyHeaders] = headers
57
+ this.#proxyServername = proxyServername
51
58
  if (factory) {
52
59
  this.#client = factory(proxyUrl, { connect })
53
60
  } else {
@@ -82,6 +89,13 @@ class Http1ProxyWrapper extends DispatcherBase {
82
89
  }
83
90
  opts.headers = { ...this[kProxyHeaders], ...headers }
84
91
 
92
+ // Pin the SNI/cert hostname to the proxy. Without this the underlying
93
+ // Client would derive it from the (rewritten) Host header, which points
94
+ // at the target — wrong for the TLS handshake to the proxy itself.
95
+ if (this.#proxyServername != null) {
96
+ opts.servername = this.#proxyServername
97
+ }
98
+
85
99
  return this.#client[kDispatch](opts, handler)
86
100
  }
87
101
 
@@ -105,9 +119,9 @@ class ProxyAgent extends DispatcherBase {
105
119
  throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.')
106
120
  }
107
121
 
108
- const { proxyTunnel = true, connectTimeout } = opts
122
+ const { proxyTunnel, connectTimeout } = opts
109
123
 
110
- super()
124
+ super(opts)
111
125
 
112
126
  const url = this.#getUrl(opts)
113
127
  const { href, origin, port, protocol, username, password, hostname: proxyHostname } = url
@@ -132,6 +146,7 @@ class ProxyAgent extends DispatcherBase {
132
146
  }
133
147
 
134
148
  const connect = buildConnector({ timeout: connectTimeout, ...opts.proxyTls })
149
+ const connectHTTP1 = buildConnector({ timeout: connectTimeout, ...opts.proxyTls, allowH2: false })
135
150
  this[kConnectEndpoint] = buildConnector({ timeout: connectTimeout, ...opts.requestTls })
136
151
  this[kConnectEndpointHTTP1] = buildConnector({ timeout: connectTimeout, ...opts.requestTls, allowH2: false })
137
152
 
@@ -147,16 +162,29 @@ class ProxyAgent extends DispatcherBase {
147
162
  factory: agentFactory,
148
163
  username: opts.username || username,
149
164
  password: opts.password || password,
165
+ connectTimeout,
150
166
  proxyTls: opts.proxyTls,
151
167
  requestTls: opts.requestTls
152
168
  })
153
169
  }
154
170
 
155
- if (!this[kTunnelProxy] && protocol === 'http:' && this[kProxy].protocol === 'http:') {
171
+ if (!shouldProxyTunnel(protocol, this[kTunnelProxy])) {
172
+ const forwardConnect = this[kProxy].protocol === 'https:'
173
+ ? (opts, cb) => connectHTTP1(opts, (err, socket) => {
174
+ if (err && err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
175
+ cb(new SecureProxyConnectionError(err))
176
+ } else {
177
+ cb(err, socket)
178
+ }
179
+ })
180
+ : connectHTTP1
156
181
  return new Http1ProxyWrapper(this[kProxy].uri, {
157
182
  headers: this[kProxyHeaders],
158
- connect,
159
- factory: agentFactory
183
+ connect: forwardConnect,
184
+ factory: agentFactory,
185
+ proxyServername: this[kProxy].protocol === 'https:'
186
+ ? (this[kProxyTls]?.servername || proxyHostname)
187
+ : undefined
160
188
  })
161
189
  }
162
190
  return agentFactory(origin, options)
@@ -231,6 +259,14 @@ class ProxyAgent extends DispatcherBase {
231
259
  if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
232
260
  // Throw a custom error to avoid loop in client.js#connect
233
261
  callback(new SecureProxyConnectionError(err))
262
+ } else if (err.code === 'UND_ERR_SOCKET') {
263
+ // A socket failure while establishing the tunnel means the CONNECT
264
+ // never completed, so there is nothing to recover - the proxy just
265
+ // tore down the connection. client.js#onError treats UND_ERR_SOCKET
266
+ // as a recoverable error on an established connection and leaves the
267
+ // request queued, which makes connect() retry forever. Surface it as
268
+ // a non-recoverable proxy error so the request fails instead. (#3897)
269
+ callback(new ProxyConnectionError(err))
234
270
  } else {
235
271
  callback(err)
236
272
  }
@@ -310,6 +346,21 @@ function buildHeaders (headers) {
310
346
  return headersPair
311
347
  }
312
348
 
349
+ // Materialize iterable header containers (e.g. Map, Headers) into a record so
350
+ // that throwIfProxyAuthIsSent() can inspect their entries. Object.keys and
351
+ // for...in see nothing on a Map/Headers instance, so without this the
352
+ // Proxy-Authorization guard is bypassed and proxy credentials can reach the
353
+ // origin server (GHSA-6cv7-626c-qhqw).
354
+ if (headers && typeof headers === 'object' && hasSafeIterator(headers)) {
355
+ const headersPair = {}
356
+
357
+ for (const [key, value] of headers) {
358
+ headersPair[key] = value
359
+ }
360
+
361
+ return headersPair
362
+ }
363
+
313
364
  return headers
314
365
  }
315
366
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  const Dispatcher = require('./dispatcher')
4
4
  const RetryHandler = require('../handler/retry-handler')
5
+ const { kOriginless, kUrl } = require('../core/symbols')
5
6
 
6
7
  class RetryAgent extends Dispatcher {
7
8
  #agent = null
@@ -10,6 +11,8 @@ class RetryAgent extends Dispatcher {
10
11
  super(options)
11
12
  this.#agent = agent
12
13
  this.#options = options
14
+ this[kUrl] = agent[kUrl]
15
+ this[kOriginless] = agent[kOriginless]
13
16
  }
14
17
 
15
18
  dispatch (opts, handler) {
@@ -65,7 +65,7 @@ class RoundRobinPool extends PoolBase {
65
65
  })
66
66
  }
67
67
 
68
- super()
68
+ super(options)
69
69
 
70
70
  this[kConnections] = connections || null
71
71
  this[kUrl] = util.parseOrigin(origin)