@openclaw/discord 2026.6.8-beta.2 → 2026.6.9-beta.1

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 (110) hide show
  1. package/dist/action-runtime-api.js +1 -1
  2. package/dist/api.js +13 -13
  3. package/dist/{approval-handler.runtime-B3gyUd-L.js → approval-handler.runtime-BprBDUQG.js} +3 -3
  4. package/dist/{audit-BlfewK04.js → audit-DuZUxGjM.js} +3 -3
  5. package/dist/{channel-b0hY1EJw.js → channel--3YhTUOb.js} +27 -19
  6. package/dist/{channel-actions-BnPHwCZ_.js → channel-actions-CoudAyAB.js} +12 -6
  7. package/dist/{channel-actions.runtime-DX5iW6ut.js → channel-actions.runtime-DdOfD3fi.js} +5 -5
  8. package/dist/channel-plugin-api.js +1 -1
  9. package/dist/{channel.setup-By5cfELZ.js → channel.setup-C-y6Jifd.js} +2 -2
  10. package/dist/{components-D-CYw0-b.js → components-CUmrNvv-.js} +1 -1
  11. package/dist/{conversation-identity-CKzQAqFF.js → conversation-identity-CN-HPn11.js} +2 -2
  12. package/dist/{directory-config-Bu7FYOsl.js → directory-config-BCt5KxcX.js} +1 -1
  13. package/dist/directory-contract-api.js +1 -1
  14. package/dist/{directory-live-LjENjK6L.js → directory-live-CE7IDmwo.js} +1 -1
  15. package/dist/{handle-action.guild-admin-BS2qnhXF.js → handle-action.guild-admin-B7SnVS0m.js} +14 -9
  16. package/dist/index.js +1 -1
  17. package/dist/{manager.runtime-BU1vkOeO.js → manager.runtime-zMVwNPAT.js} +12 -4
  18. package/dist/{message-handler-CQVkXHMN.js → message-handler-DE413Oj4.js} +6 -6
  19. package/dist/{message-handler.preflight-DAnLOeDA.js → message-handler.preflight-BuF-DsE2.js} +10 -10
  20. package/dist/{message-handler.process-Dp5NQT05.js → message-handler.process-BX8HsMfV.js} +37 -23
  21. package/dist/{message-utils-Bx993JLN.js → message-utils-s_8KDqAQ.js} +1 -1
  22. package/dist/{outbound-adapter-CmN7ao1t.js → outbound-adapter-CNievjXH.js} +6 -6
  23. package/dist/{pluralkit-SYmlmerw.js → pluralkit-BXkU9XmC.js} +1 -1
  24. package/dist/{provider-DrScDA1p.js → provider-ByZ6xxgi.js} +85 -56
  25. package/dist/{provider-session.runtime-DXTzSYOJ.js → provider-session.runtime-DMfaQ9Z6.js} +3 -3
  26. package/dist/provider.runtime-EW-G8l_U.js +2 -0
  27. package/dist/{resolve-channels-Rautpk8n.js → resolve-channels-t1URw0Qz.js} +1 -1
  28. package/dist/{resolve-users-Bw7vvtsi.js → resolve-users-Bapkb237.js} +1 -1
  29. package/dist/{runtime-C80YEJ7Z.js → runtime-C6jV3hf4.js} +24 -10
  30. package/dist/runtime-api.actions.js +2 -2
  31. package/dist/runtime-api.js +19 -19
  32. package/dist/runtime-api.lookup.js +4 -4
  33. package/dist/runtime-api.monitor-5BSxmucu.js +6 -0
  34. package/dist/runtime-api.monitor.js +4 -4
  35. package/dist/runtime-api.send.js +5 -5
  36. package/dist/runtime-api.threads.js +3 -3
  37. package/dist/{send-zGsXF-up.js → send-o-Y1DiAT.js} +3 -3
  38. package/dist/{send.components-ktzrUTkt.js → send.components-B4_oNcOh.js} +4 -4
  39. package/dist/{send.outbound-C8oC51um.js → send.outbound-DhiXV3UJ.js} +53 -10
  40. package/dist/{send.receipt-DsQWEQ2O.js → send.receipt-HXIwVvXy.js} +2 -1
  41. package/dist/{send.shared-Dvo2ZCVG.js → send.shared-DYdjs_Zh.js} +13 -5
  42. package/dist/session-binding-contract-api.js +1 -1
  43. package/dist/setup-plugin-api.js +1 -1
  44. package/dist/{subagent-hooks-kjrWDeDg.js → subagent-hooks-CbF_Z5F0.js} +2 -2
  45. package/dist/subagent-hooks-api.js +1 -1
  46. package/dist/{system-events-CvU3Aduf.js → system-events-BxTHlBbM.js} +1 -1
  47. package/dist/{target-resolver-DMPTzuo7.js → target-resolver-DpC8iueE.js} +2 -2
  48. package/dist/targets-BEIgHBHc.js +3 -0
  49. package/dist/{thread-bindings-DO32M2kW.js → thread-bindings-CEVvN75T.js} +4 -4
  50. package/dist/{thread-bindings.discord-api-304M1PMr.js → thread-bindings.discord-api-B8NfbxEB.js} +4 -4
  51. package/dist/{thread-bindings.manager-C9YT7wF2.js → thread-bindings.manager-BKfUaXGt.js} +3 -3
  52. package/dist/{transcripts-source-Chy2OrO_.js → transcripts-source-W6n_8J8g.js} +1 -1
  53. package/dist/transcripts-source-api.js +1 -1
  54. package/dist/{typing-BaivbXIG.js → typing-0-pUmlY9.js} +1 -1
  55. package/node_modules/undici/README.md +59 -18
  56. package/node_modules/undici/docs/docs/GettingStarted.md +278 -0
  57. package/node_modules/undici/docs/docs/api/Agent.md +3 -0
  58. package/node_modules/undici/docs/docs/api/BalancedPool.md +1 -1
  59. package/node_modules/undici/docs/docs/api/Client.md +44 -5
  60. package/node_modules/undici/docs/docs/api/Connector.md +1 -0
  61. package/node_modules/undici/docs/docs/api/Cookies.md +28 -1
  62. package/node_modules/undici/docs/docs/api/Dispatcher.md +22 -5
  63. package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +6 -9
  64. package/node_modules/undici/docs/docs/api/Errors.md +12 -0
  65. package/node_modules/undici/docs/docs/api/EventSource.md +50 -3
  66. package/node_modules/undici/docs/docs/api/Fetch.md +5 -3
  67. package/node_modules/undici/docs/docs/api/H2CClient.md +3 -3
  68. package/node_modules/undici/docs/docs/api/MockAgent.md +1 -1
  69. package/node_modules/undici/docs/docs/api/MockCallHistory.md +1 -1
  70. package/node_modules/undici/docs/docs/api/Pool.md +4 -1
  71. package/node_modules/undici/docs/docs/api/RedirectHandler.md +4 -1
  72. package/node_modules/undici/docs/docs/api/RetryAgent.md +3 -3
  73. package/node_modules/undici/docs/docs/api/RetryHandler.md +6 -6
  74. package/node_modules/undici/docs/docs/api/RoundRobinPool.md +1 -1
  75. package/node_modules/undici/docs/docs/api/SnapshotAgent.md +3 -3
  76. package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +1 -0
  77. package/node_modules/undici/docs/docs/api/api-lifecycle.md +4 -4
  78. package/node_modules/undici/lib/core/connect.js +29 -4
  79. package/node_modules/undici/lib/core/util.js +8 -6
  80. package/node_modules/undici/lib/dispatcher/client-h1.js +69 -2
  81. package/node_modules/undici/lib/dispatcher/client-h2.js +160 -37
  82. package/node_modules/undici/lib/dispatcher/client.js +36 -7
  83. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +1 -0
  84. package/node_modules/undici/lib/dispatcher/proxy-agent.js +2 -1
  85. package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +4 -2
  86. package/node_modules/undici/lib/handler/redirect-handler.js +36 -11
  87. package/node_modules/undici/lib/interceptor/dns.js +4 -0
  88. package/node_modules/undici/lib/interceptor/redirect.js +3 -3
  89. package/node_modules/undici/lib/mock/mock-call-history.js +1 -1
  90. package/node_modules/undici/lib/mock/snapshot-agent.js +9 -1
  91. package/node_modules/undici/lib/util/cache.js +8 -2
  92. package/node_modules/undici/lib/web/cookies/parse.js +17 -25
  93. package/node_modules/undici/lib/web/eventsource/eventsource.js +7 -18
  94. package/node_modules/undici/lib/web/eventsource/util.js +32 -1
  95. package/node_modules/undici/lib/web/fetch/body.js +43 -0
  96. package/node_modules/undici/lib/web/fetch/index.js +17 -3
  97. package/node_modules/undici/lib/web/fetch/request.js +33 -3
  98. package/node_modules/undici/lib/web/websocket/receiver.js +20 -3
  99. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -1
  100. package/node_modules/undici/lib/web/websocket/websocket.js +3 -1
  101. package/node_modules/undici/package.json +1 -1
  102. package/node_modules/undici/types/client.d.ts +5 -0
  103. package/node_modules/undici/types/connector.d.ts +1 -0
  104. package/node_modules/undici/types/fetch.d.ts +5 -1
  105. package/node_modules/undici/types/interceptors.d.ts +1 -1
  106. package/npm-shrinkwrap.json +7 -7
  107. package/package.json +5 -5
  108. package/dist/provider.runtime-nb-6cRoy.js +0 -2
  109. package/dist/runtime-api.monitor-D8KNDAd5.js +0 -6
  110. package/dist/targets-CKaNidbk.js +0 -3
@@ -15,7 +15,7 @@ same implementation. Use the built-in global `FormData` with the built-in
15
15
  global `fetch()`, and use `undici`'s `FormData` with `undici.fetch()`.
16
16
 
17
17
  If you want the installed `undici` package to provide the globals, call
18
- [`install()`](/docs/api/GlobalInstallation.md) so `fetch`, `Headers`,
18
+ [`install()`](/docs/docs/api/GlobalInstallation.md) so `fetch`, `Headers`,
19
19
  `Response`, `Request`, and `FormData` are installed together as a matching set.
20
20
 
21
21
  ## Response
@@ -26,7 +26,7 @@ This API is implemented as per the standard, you can find documentation on [MDN]
26
26
 
27
27
  This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Request)
28
28
 
29
- ## Header
29
+ ## Headers
30
30
 
31
31
  This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
32
32
 
@@ -41,7 +41,9 @@ This API is implemented as per the standard, you can find documentation on [MDN]
41
41
  - [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json)
42
42
  - [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text)
43
43
 
44
- There is an ongoing discussion regarding `.formData()` and its usefulness and performance in server environments. It is recommended to use a dedicated library for parsing `multipart/form-data` bodies, such as [Busboy](https://www.npmjs.com/package/busboy) or [@fastify/busboy](https://www.npmjs.com/package/@fastify/busboy).
44
+ There is an ongoing discussion regarding `body.formData()` and its usefulness, performance, and security in server environments. Calling `body.formData()` causes undici to buffer and parse the entire body. Because multipart parsing has inherent security risks, `body.formData()` must only be called on responses from trusted servers.
45
+
46
+ For responses from untrusted or user-controlled servers, use a dedicated streaming library for parsing `multipart/form-data` bodies, such as [Busboy](https://www.npmjs.com/package/busboy) or [@fastify/busboy](https://www.npmjs.com/package/@fastify/busboy), and apply application-specific limits.
45
47
 
46
48
  These libraries can be interfaced with fetch with the following example code:
47
49
 
@@ -17,7 +17,7 @@ const server = createServer((req, res) => {
17
17
  })
18
18
 
19
19
  server.listen()
20
- once(server, 'listening').then(() => {
20
+ once(server, 'listening').then(async () => {
21
21
  const client = new H2CClient(`http://localhost:${server.address().port}/`)
22
22
 
23
23
  const response = await client.request({ path: '/', method: 'GET' })
@@ -46,8 +46,8 @@ Returns: `H2CClient`
46
46
  - **keepAliveTimeoutThreshold** `number | null` (optional) - Default: `2e3` - A number of milliseconds subtracted from server _keep-alive_ hints when overriding `keepAliveTimeout` to account for timing inaccuracies caused by e.g. transport latency. Defaults to 2 seconds.
47
47
  - **maxHeaderSize** `number | null` (optional) - Default: `--max-http-header-size` or `16384` - The maximum length of request headers in bytes. Defaults to Node.js' --max-http-header-size or 16KiB.
48
48
  - **maxResponseSize** `number | null` (optional) - Default: `-1` - The maximum length of response body in bytes. Set to `-1` to disable.
49
- - **maxConcurrentStreams**: `number` - Default: `100`. Dictates the maximum number of concurrent streams for a single H2 session. It can be overridden by a SETTINGS remote frame.
50
- - **pipelining** `number | null` (optional) - Default to `maxConcurrentStreams` - The amount of concurrent requests sent over a single HTTP/2 session in accordance with [RFC-7540](https://httpwg.org/specs/rfc7540.html#StreamsLayer) Stream specification. Streams can be closed up by remote server at any time.
49
+ - **maxConcurrentStreams**: `number` - Default: `100`. The maximum number of concurrent HTTP/2 streams per session also advertised to the server as `peerMaxConcurrentStreams` (the cap on streams the server may push back). The initial value is replaced by the server's `SETTINGS_MAX_CONCURRENT_STREAMS` whenever the server sends one, so a user-supplied value acts as a pre-`SETTINGS` default rather than a hard cap.
50
+ - **pipelining** `number | null` (optional) - Default to `maxConcurrentStreams` - The amount of concurrent requests sent over a single HTTP/2 session in accordance with [RFC-7540](https://httpwg.org/specs/rfc7540.html#StreamsLayer) Stream specification. Streams can be closed up by remote server at any time. Unlike on a regular [`Client`](/docs/docs/api/Client.md), `H2CClient` aliases `pipelining` to `maxConcurrentStreams` at construction time, so the two move together.
51
51
  - **pingInterval**: `number` - Default: `60e3`. The time interval in milliseconds between PING frames sent to the server. Set to `0` to disable PING frames. This is only applicable for HTTP/2 connections.
52
52
  - **connect** `ConnectOptions | null` (optional) - Default: `null`.
53
53
  - **strictContentLength** `Boolean` (optional) - Default: `true` - Whether to treat request content length mismatches as errors. If true, an error is thrown when the request content-length header doesn't match the length of the request body. **Security Warning:** Disabling this option can expose your application to HTTP Request Smuggling attacks, where mismatched content-length headers cause servers and proxies to interpret request boundaries differently. This can lead to cache poisoning, credential hijacking, and bypassing security controls. Only disable this in controlled environments where you fully trust the request source.
@@ -580,7 +580,7 @@ mockAgent.getCallHistory()?.firstCall()
580
580
  ```js
581
581
  const mockAgent = new MockAgent()
582
582
 
583
- mockAgent.clearAllCallHistory()
583
+ mockAgent.clearCallHistory()
584
584
  ```
585
585
 
586
586
  #### Example - call history instance class method
@@ -165,7 +165,7 @@ Parameters :
165
165
 
166
166
  - criteria : the first parameter. a function, regexp or object.
167
167
  - function : filter MockCallHistoryLog when the function returns false
168
- - regexp : filter MockCallHistoryLog when the regexp does not match on MockCallHistoryLog.toString() ([see](./MockCallHistoryLog.md#to-string))
168
+ - regexp : filter MockCallHistoryLog when the regexp does not match on MockCallHistoryLog.toString() ([see](/docs/docs/api/MockCallHistoryLog.md#to-string))
169
169
  - object : an object with MockCallHistoryLog properties as keys to apply multiple filters. each values are a [filter parameter](/docs/docs/api/MockCallHistory.md#filter-parameter)
170
170
  - options : the second parameter. an object.
171
171
  - options.operator : `'AND'` or `'OR'` (default `'OR'`). Used only if criteria is an object. see below
@@ -21,6 +21,9 @@ Extends: [`ClientOptions`](/docs/docs/api/Client.md#parameter-clientoptions)
21
21
  * **connections** `number | null` (optional) - Default: `null` - The number of `Client` instances to create. When set to `null`, the `Pool` instance will create an unlimited amount of `Client` instances.
22
22
  * **clientTtl** `number | null` (optional) - Default: `null` - The amount of time before a `Client` instance is removed from the `Pool` and closed. When set to `null`, `Client` instances will not be removed or closed based on age.
23
23
 
24
+ > [!NOTE]
25
+ > `Pool` inherits all [`ClientOptions`](/docs/docs/api/Client.md#parameter-clientoptions), including `allowH2` (default `true`) and `maxConcurrentStreams` (default `100`). With the unlimited default of `connections`, `Pool` will open a new `Client` — and therefore a new TCP/TLS socket — per concurrent dispatch, which defeats HTTP/2 multiplexing on a shared session. To benefit from h2 multiplexing on a single session, cap `connections` (e.g. `connections: 1`) so that concurrent requests share a session up to `maxConcurrentStreams`.
26
+
24
27
  ## Instance Properties
25
28
 
26
29
  ### `Pool.closed`
@@ -33,7 +36,7 @@ Implements [Client.destroyed](/docs/docs/api/Client.md#clientdestroyed)
33
36
 
34
37
  ### `Pool.stats`
35
38
 
36
- Returns [`PoolStats`](PoolStats.md) instance for this pool.
39
+ Returns [`PoolStats`](/docs/docs/api/PoolStats.md) instance for this pool.
37
40
 
38
41
  ## Instance Methods
39
42
 
@@ -8,7 +8,7 @@ Arguments:
8
8
 
9
9
  - **dispatch** `function` - The dispatch function to be called after every retry.
10
10
  - **maxRedirections** `number` - Maximum number of redirections allowed.
11
- - **opts** `object` - Options for handling redirection.
11
+ - **opts** `object` - Options for handling redirection. Supports `throwOnMaxRedirect`, `stripHeadersOnRedirect`, and `stripHeadersOnCrossOriginRedirect`.
12
12
  - **handler** `object` - An object containing handlers for different stages of the request lifecycle.
13
13
 
14
14
  Returns: `RedirectHandler`
@@ -18,6 +18,9 @@ Returns: `RedirectHandler`
18
18
  - **dispatch** `(options: Dispatch.DispatchOptions, handlers: Dispatch.DispatchHandler) => Promise<Dispatch.DispatchResponse>` (required) - Dispatch function to be called after every redirection.
19
19
  - **maxRedirections** `number` (required) - Maximum number of redirections allowed.
20
20
  - **opts** `object` (required) - Options for handling redirection.
21
+ - **throwOnMaxRedirect** `boolean` - Throw when the maximum number of redirections is reached.
22
+ - **stripHeadersOnRedirect** `string[]` - Header names to remove from all redirected requests.
23
+ - **stripHeadersOnCrossOriginRedirect** `string[]` - Header names to remove from cross-origin redirected requests.
21
24
  - **handler** `object` (required) - Handlers for different stages of the request lifecycle.
22
25
 
23
26
  ### Properties
@@ -12,7 +12,7 @@ Arguments:
12
12
  * **dispatcher** `undici.Dispatcher` (required) - the dispatcher to wrap
13
13
  * **options** `RetryHandlerOptions` (optional) - the options
14
14
 
15
- Returns: `ProxyAgent`
15
+ Returns: `RetryAgent`
16
16
 
17
17
  ### Parameter: `RetryHandlerOptions`
18
18
 
@@ -23,9 +23,9 @@ Returns: `ProxyAgent`
23
23
  - **minTimeout** `number` (optional) - Minimum number of milliseconds to wait before retrying. Default: `500` (half a second)
24
24
  - **timeoutFactor** `number` (optional) - Factor to multiply the timeout by for each retry attempt. Default: `2`
25
25
  - **retryAfter** `boolean` (optional) - It enables automatic retry after the `Retry-After` header is received. Default: `true`
26
- - **methods** `string[]` (optional) - Array of HTTP methods to retry. Default: `['GET', 'PUT', 'HEAD', 'OPTIONS', 'DELETE']`
26
+ - **methods** `string[]` (optional) - Array of HTTP methods to retry. Default: `['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE']`
27
27
  - **statusCodes** `number[]` (optional) - Array of HTTP status codes to retry. Default: `[429, 500, 502, 503, 504]`
28
- - **errorCodes** `string[]` (optional) - Array of Error codes to retry. Default: `['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ENETDOWN','ENETUNREACH', 'EHOSTDOWN', 'UND_ERR_SOCKET']`
28
+ - **errorCodes** `string[]` (optional) - Array of Error codes to retry. Default: `['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ENETDOWN', 'ENETUNREACH', 'EHOSTDOWN', 'EHOSTUNREACH', 'EPIPE', 'UND_ERR_SOCKET']`
29
29
 
30
30
  **`RetryContext`**
31
31
 
@@ -4,12 +4,12 @@ Extends: `undici.DispatcherHandlers`
4
4
 
5
5
  A handler class that implements the retry logic for a request.
6
6
 
7
- ## `new RetryHandler(dispatchOptions, retryHandlers, [retryOptions])`
7
+ ## `new RetryHandler(opts, { dispatch, handler })`
8
8
 
9
9
  Arguments:
10
10
 
11
- - **options** `Dispatch.DispatchOptions & RetryOptions` (required) - It is an intersection of `Dispatcher.DispatchOptions` and `RetryOptions`.
12
- - **retryHandlers** `RetryHandlers` (required) - Object containing the `dispatch` to be used on every retry, and `handler` for handling the `dispatch` lifecycle.
11
+ - **opts** `Dispatch.DispatchOptions & { retryOptions?: RetryOptions }` (required) - An intersection of `Dispatcher.DispatchOptions` and an optional `RetryOptions` object.
12
+ - **{ dispatch, handler }** `RetryHandlers` (required) - Object containing the `dispatch` to be used on every retry, and `handler` for handling the `dispatch` lifecycle.
13
13
 
14
14
  Returns: `retryHandler`
15
15
 
@@ -20,15 +20,15 @@ Extends: [`Dispatch.DispatchOptions`](/docs/docs/api/Dispatcher.md#parameter-dis
20
20
  #### `RetryOptions`
21
21
 
22
22
  - **throwOnError** `boolean` (optional) - Disable to prevent throwing error on last retry attept, useful if you need the body on errors from server or if you have custom error handler.
23
- - **retry** `(err: Error, context: RetryContext, callback: (err?: Error | null) => void) => number | null` (optional) - Function to be called after every retry. It should pass error if no more retries should be performed.
23
+ - **retry** `(err: Error, context: RetryContext, callback: (err?: Error | null) => void) => void` (optional) - Function to be called after every retry. It should pass error if no more retries should be performed.
24
24
  - **maxRetries** `number` (optional) - Maximum number of retries. Default: `5`
25
25
  - **maxTimeout** `number` (optional) - Maximum number of milliseconds to wait before retrying. Default: `30000` (30 seconds)
26
26
  - **minTimeout** `number` (optional) - Minimum number of milliseconds to wait before retrying. Default: `500` (half a second)
27
27
  - **timeoutFactor** `number` (optional) - Factor to multiply the timeout by for each retry attempt. Default: `2`
28
28
  - **retryAfter** `boolean` (optional) - It enables automatic retry after the `Retry-After` header is received. Default: `true`
29
- - **methods** `string[]` (optional) - Array of HTTP methods to retry. Default: `['GET', 'PUT', 'HEAD', 'OPTIONS', 'DELETE']`
29
+ - **methods** `string[]` (optional) - Array of HTTP methods to retry. Default: `['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE']`
30
30
  - **statusCodes** `number[]` (optional) - Array of HTTP status codes to retry. Default: `[429, 500, 502, 503, 504]`
31
- - **errorCodes** `string[]` (optional) - Array of Error codes to retry. Default: `['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ENETDOWN','ENETUNREACH', 'EHOSTDOWN', 'UND_ERR_SOCKET']`
31
+ - **errorCodes** `string[]` (optional) - Array of Error codes to retry. Default: `['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ENETDOWN', 'ENETUNREACH', 'EHOSTDOWN', 'EHOSTUNREACH', 'EPIPE', 'UND_ERR_SOCKET']`
32
32
 
33
33
  **`RetryContext`**
34
34
 
@@ -66,7 +66,7 @@ Implements [Client.destroyed](/docs/docs/api/Client.md#clientdestroyed)
66
66
 
67
67
  ### `RoundRobinPool.stats`
68
68
 
69
- Returns [`PoolStats`](PoolStats.md) instance for this pool.
69
+ Returns [`PoolStats`](/docs/docs/api/PoolStats.md) instance for this pool.
70
70
 
71
71
  ## Instance Methods
72
72
 
@@ -634,6 +634,6 @@ SnapshotAgent provides similar functionality to nock but is specifically designe
634
634
 
635
635
  ## See Also
636
636
 
637
- - [MockAgent](./MockAgent.md) - Manual mocking for more control
638
- - [MockCallHistory](./MockCallHistory.md) - Inspecting request history
639
- - [Testing Best Practices](../best-practices/writing-tests.md) - General testing guidance
637
+ - [MockAgent](/docs/docs/api/MockAgent.md) - Manual mocking for more control
638
+ - [MockCallHistory](/docs/docs/api/MockCallHistory.md) - Inspecting request history
639
+ - [Testing Best Practices](/docs/docs/best-practices/writing-tests.md) - General testing guidance
@@ -22,6 +22,7 @@ Extends: [`PoolOptions`](/docs/docs/api/Pool.md#parameter-pooloptions)
22
22
  * **password** `string` (optional) - SOCKS5 proxy password for authentication. Can also be provided in the proxy URL.
23
23
  * **connect** `Function` (optional) - Custom connector function for the proxy connection.
24
24
  * **proxyTls** `BuildOptions` (optional) - TLS options for the proxy connection (when using SOCKS5 over TLS).
25
+ * **requestTls** `BuildOptions` (optional) - TLS options applied to the HTTPS connection to the target server through the SOCKS5 tunnel. Use this to configure `ca`, `cert`, `key`, `rejectUnauthorized`, `servername`, etc. for the target HTTPS endpoint.
25
26
 
26
27
  Examples:
27
28
 
@@ -58,9 +58,9 @@ stateDiagram-v2
58
58
 
59
59
  ### idle
60
60
 
61
- The **idle** state is the initial state of a `Client` instance. While an `origin` is required for instantiating a `Client` instance, the underlying socket connection will not be established until a request is queued using [`Client.dispatch()`](/docs/docs/api/Client.md#clientdispatchoptions-handlers). By calling `Client.dispatch()` directly or using one of the multiple implementations ([`Client.connect()`](Client.md#clientconnectoptions-callback), [`Client.pipeline()`](Client.md#clientpipelineoptions-handler), [`Client.request()`](Client.md#clientrequestoptions-callback), [`Client.stream()`](Client.md#clientstreamoptions-factory-callback), and [`Client.upgrade()`](/docs/docs/api/Client.md#clientupgradeoptions-callback)), the `Client` instance will transition from **idle** to [**pending**](/docs/docs/api/Client.md#pending) and then most likely directly to [**processing**](/docs/docs/api/Client.md#processing).
61
+ The **idle** state is the initial state of a `Client` instance. While an `origin` is required for instantiating a `Client` instance, the underlying socket connection will not be established until a request is queued using [`Client.dispatch()`](/docs/docs/api/Client.md#clientdispatchoptions-handlers). By calling `Client.dispatch()` directly or using one of the multiple implementations ([`Client.connect()`](/docs/docs/api/Client.md#clientconnectoptions-callback), [`Client.pipeline()`](/docs/docs/api/Client.md#clientpipelineoptions-handler), [`Client.request()`](/docs/docs/api/Client.md#clientrequestoptions-callback), [`Client.stream()`](/docs/docs/api/Client.md#clientstreamoptions-factory-callback), and [`Client.upgrade()`](/docs/docs/api/Client.md#clientupgradeoptions-callback)), the `Client` instance will transition from **idle** to [**pending**](/docs/docs/api/Client.md#pending) and then most likely directly to [**processing**](/docs/docs/api/Client.md#processing).
62
62
 
63
- Calling [`Client.close()`](/docs/docs/api/Client.md#clientclosecallback) or [`Client.destroy()`](Client.md#clientdestroyerror-callback) transitions directly to the [**destroyed**](/docs/docs/api/Client.md#destroyed) state since the `Client` instance will have no queued requests in this state.
63
+ Calling [`Client.close()`](/docs/docs/api/Client.md#clientclosecallback) or [`Client.destroy()`](/docs/docs/api/Client.md#clientdestroyerror-callback) transitions directly to the [**destroyed**](/docs/docs/api/Client.md#destroyed) state since the `Client` instance will have no queued requests in this state.
64
64
 
65
65
  ### pending
66
66
 
@@ -72,11 +72,11 @@ Calling [`Client.destroy()`](/docs/docs/api/Client.md#clientdestroyerror-callbac
72
72
 
73
73
  ### processing
74
74
 
75
- The **processing** state is a state machine within itself. It initializes to the [**processing.running**](/docs/docs/api/Client.md#running) state. The [`Client.dispatch()`](/docs/docs/api/Client.md#clientdispatchoptions-handlers), [`Client.close()`](Client.md#clientclosecallback), and [`Client.destroy()`](Client.md#clientdestroyerror-callback) can be called at any time while the `Client` is in this state. `Client.dispatch()` will add more requests to the queue while existing requests continue to be processed. `Client.close()` will transition to the [**processing.closing**](/docs/docs/api/Client.md#closing) state. And `Client.destroy()` will transition to [**destroyed**](/docs/docs/api/Client.md#destroyed).
75
+ The **processing** state is a state machine within itself. It initializes to the [**processing.running**](/docs/docs/api/Client.md#running) state. The [`Client.dispatch()`](/docs/docs/api/Client.md#clientdispatchoptions-handlers), [`Client.close()`](/docs/docs/api/Client.md#clientclosecallback), and [`Client.destroy()`](/docs/docs/api/Client.md#clientdestroyerror-callback) can be called at any time while the `Client` is in this state. `Client.dispatch()` will add more requests to the queue while existing requests continue to be processed. `Client.close()` will transition to the [**processing.closing**](/docs/docs/api/Client.md#closing) state. And `Client.destroy()` will transition to [**destroyed**](/docs/docs/api/Client.md#destroyed).
76
76
 
77
77
  #### running
78
78
 
79
- In the **processing.running** sub-state, queued requests are being processed in a FIFO order. If a request body requires draining, the *needDrain* event transitions to the [**processing.busy**](/docs/docs/api/Client.md#busy) sub-state. The *close* event transitions the Client to the [**process.closing**](/docs/docs/api/Client.md#closing) sub-state. If all queued requests are processed and neither [`Client.close()`](/docs/docs/api/Client.md#clientclosecallback) nor [`Client.destroy()`](Client.md#clientdestroyerror-callback) are called, then the [**processing**](/docs/docs/api/Client.md#processing) machine will trigger a *keepalive* event transitioning the `Client` back to the [**pending**](/docs/docs/api/Client.md#pending) state. During this time, the `Client` is waiting for the socket connection to timeout, and once it does, it triggers the *timeout* event and transitions to the [**idle**](/docs/docs/api/Client.md#idle) state.
79
+ In the **processing.running** sub-state, queued requests are being processed in a FIFO order. If a request body requires draining, the *needDrain* event transitions to the [**processing.busy**](/docs/docs/api/Client.md#busy) sub-state. The *close* event transitions the Client to the [**process.closing**](/docs/docs/api/Client.md#closing) sub-state. If all queued requests are processed and neither [`Client.close()`](/docs/docs/api/Client.md#clientclosecallback) nor [`Client.destroy()`](/docs/docs/api/Client.md#clientdestroyerror-callback) are called, then the [**processing**](/docs/docs/api/Client.md#processing) machine will trigger a *keepalive* event transitioning the `Client` back to the [**pending**](/docs/docs/api/Client.md#pending) state. During this time, the `Client` is waiting for the socket connection to timeout, and once it does, it triggers the *timeout* event and transitions to the [**idle**](/docs/docs/api/Client.md#idle) state.
80
80
 
81
81
  #### busy
82
82
 
@@ -3,7 +3,7 @@
3
3
  const net = require('node:net')
4
4
  const assert = require('node:assert')
5
5
  const util = require('./util')
6
- const { InvalidArgumentError } = require('./errors')
6
+ const { InvalidArgumentError, ConnectTimeoutError } = require('./errors')
7
7
 
8
8
  let tls // include tls conditionally since it is not always available
9
9
 
@@ -59,7 +59,7 @@ const SessionCache = class WeakSessionCache {
59
59
  }
60
60
  }
61
61
 
62
- function buildConnector ({ allowH2, useH2c, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) {
62
+ function buildConnector ({ allowH2, preferH2, useH2c, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) {
63
63
  if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) {
64
64
  throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero')
65
65
  }
@@ -89,7 +89,7 @@ function buildConnector ({ allowH2, useH2c, maxCachedSessions, socketPath, timeo
89
89
  servername,
90
90
  session,
91
91
  localAddress,
92
- ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'],
92
+ ALPNProtocols: allowH2 ? (preferH2 ? ['h2', 'http/1.1'] : ['http/1.1', 'h2']) : ['http/1.1'],
93
93
  socket: httpSocket, // upgrade socket connection
94
94
  port,
95
95
  host: hostname
@@ -142,7 +142,7 @@ function buildConnector ({ allowH2, useH2c, maxCachedSessions, socketPath, timeo
142
142
  if (callback) {
143
143
  const cb = callback
144
144
  callback = null
145
- cb(err)
145
+ cb(maybeNormalizeConnectError(err, this, { timeout, hostname, port }))
146
146
  }
147
147
  })
148
148
 
@@ -150,4 +150,29 @@ function buildConnector ({ allowH2, useH2c, maxCachedSessions, socketPath, timeo
150
150
  }
151
151
  }
152
152
 
153
+ // `net.connect` with `autoSelectFamily` raises an `AggregateError` when every
154
+ // attempted address fails. If any of those failures is a timeout, surface the
155
+ // error as a `ConnectTimeoutError` so callers see the same error regardless of
156
+ // which timer (Node's internal one or undici's `connectTimeout`) wins the race.
157
+ // The original `AggregateError` is preserved on `.cause`.
158
+ function maybeNormalizeConnectError (err, socket, opts) {
159
+ if (
160
+ err instanceof AggregateError &&
161
+ (err.code === 'ETIMEDOUT' || err.errors.some((e) => e != null && e.code === 'ETIMEDOUT'))
162
+ ) {
163
+ let message = 'Connect Timeout Error'
164
+ if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) {
165
+ message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(', ')},`
166
+ } else {
167
+ message += ` (attempted address: ${opts.hostname}:${opts.port},`
168
+ }
169
+ message += ` timeout: ${opts.timeout}ms)`
170
+
171
+ const wrapped = new ConnectTimeoutError(message)
172
+ wrapped.cause = err
173
+ return wrapped
174
+ }
175
+ return err
176
+ }
177
+
153
178
  module.exports = buildConnector
@@ -698,9 +698,8 @@ function isFormDataLike (object) {
698
698
  }
699
699
 
700
700
  function addAbortListener (signal, listener) {
701
- if (signal instanceof AbortSignal) {
702
- const disposable = addAbortListenerNative(signal, listener)
703
- return () => disposable[Symbol.dispose]()
701
+ if (!signal || 'aborted' in signal) {
702
+ return addAbortListenerNative(signal, listener)[Symbol.dispose]
704
703
  }
705
704
 
706
705
  if (typeof signal.addEventListener === 'function') {
@@ -793,8 +792,9 @@ const rangeHeaderRegex = /^bytes (\d+)-(\d+)\/(\d+|\*)?$/
793
792
  */
794
793
  function parseRangeHeader (range) {
795
794
  if (range == null || range === '') return { start: 0, end: null, size: null }
795
+ if (!range) return null
796
796
 
797
- const m = range ? range.match(rangeHeaderRegex) : null
797
+ const m = rangeHeaderRegex.exec(range)
798
798
  return m
799
799
  ? {
800
800
  start: parseInt(m[1]),
@@ -943,8 +943,10 @@ function getProtocolFromUrlString (urlString) {
943
943
  return urlString.slice(0, urlString.indexOf(':') + 1)
944
944
  }
945
945
 
946
- const kEnumerableProperty = Object.create(null)
947
- kEnumerableProperty.enumerable = true
946
+ const kEnumerableProperty = {
947
+ __proto__: null,
948
+ enumerable: true
949
+ }
948
950
 
949
951
  const normalizedMethodRecordsBase = {
950
952
  delete: 'DELETE',
@@ -57,6 +57,9 @@ const constants = require('../llhttp/constants.js')
57
57
  const EMPTY_BUF = Buffer.alloc(0)
58
58
  const FastBuffer = Buffer[Symbol.species]
59
59
  const removeAllListeners = util.removeAllListeners
60
+ const kIdleSocketValidation = Symbol('kIdleSocketValidation')
61
+ const kIdleSocketValidationTimeout = Symbol('kIdleSocketValidationTimeout')
62
+ const kSocketUsed = Symbol('kSocketUsed')
60
63
 
61
64
  let extractBody
62
65
 
@@ -371,7 +374,6 @@ class Parser {
371
374
  finish () {
372
375
  assert(currentParser === null)
373
376
  assert(this.ptr != null)
374
- assert(!this.paused)
375
377
 
376
378
  const { llhttp } = this
377
379
 
@@ -450,6 +452,11 @@ class Parser {
450
452
  return -1
451
453
  }
452
454
 
455
+ if (client[kRunning] === 0) {
456
+ util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket)))
457
+ return -1
458
+ }
459
+
453
460
  const request = client[kQueue][client[kRunningIdx]]
454
461
  if (!request) {
455
462
  return -1
@@ -585,6 +592,11 @@ class Parser {
585
592
  return -1
586
593
  }
587
594
 
595
+ if (client[kRunning] === 0) {
596
+ util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket)))
597
+ return -1
598
+ }
599
+
588
600
  const request = client[kQueue][client[kRunningIdx]]
589
601
 
590
602
  if (!request) {
@@ -763,6 +775,7 @@ class Parser {
763
775
  request.onResponseEnd(headers)
764
776
 
765
777
  client[kQueue][client[kRunningIdx]++] = null
778
+ socket[kSocketUsed] = client[kPending] === 0
766
779
 
767
780
  if (socket[kWriting]) {
768
781
  assert(client[kRunning] === 0)
@@ -839,6 +852,9 @@ function connectH1 (client, socket) {
839
852
  socket[kWriting] = false
840
853
  socket[kReset] = false
841
854
  socket[kBlocking] = false
855
+ socket[kIdleSocketValidation] = 0
856
+ socket[kIdleSocketValidationTimeout] = null
857
+ socket[kSocketUsed] = false
842
858
  socket[kParser] = new Parser(client, socket, llhttpInstance)
843
859
 
844
860
  util.addListener(socket, 'error', onHttpSocketError)
@@ -881,7 +897,7 @@ function connectH1 (client, socket) {
881
897
  * @returns {boolean}
882
898
  */
883
899
  busy (request) {
884
- if (socket[kWriting] || socket[kReset] || socket[kBlocking]) {
900
+ if (socket[kWriting] || socket[kReset] || socket[kBlocking] || socket[kIdleSocketValidation] === 1) {
885
901
  return true
886
902
  }
887
903
 
@@ -961,6 +977,8 @@ function onHttpSocketEnd () {
961
977
  function onHttpSocketClose () {
962
978
  const parser = this[kParser]
963
979
 
980
+ clearIdleSocketValidation(this)
981
+
964
982
  if (parser) {
965
983
  if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) {
966
984
  this[kError] = parser.finish() || this[kError]
@@ -1007,6 +1025,28 @@ function onSocketClose () {
1007
1025
  this[kClosed] = true
1008
1026
  }
1009
1027
 
1028
+ function clearIdleSocketValidation (socket) {
1029
+ if (socket[kIdleSocketValidationTimeout]) {
1030
+ clearTimeout(socket[kIdleSocketValidationTimeout])
1031
+ socket[kIdleSocketValidationTimeout] = null
1032
+ }
1033
+
1034
+ socket[kIdleSocketValidation] = 0
1035
+ }
1036
+
1037
+ function scheduleIdleSocketValidation (client, socket) {
1038
+ socket[kIdleSocketValidation] = 1
1039
+ socket[kIdleSocketValidationTimeout] = setTimeout(() => {
1040
+ socket[kIdleSocketValidationTimeout] = null
1041
+ socket[kIdleSocketValidation] = 2
1042
+
1043
+ if (client[kSocket] === socket && !socket.destroyed) {
1044
+ client[kResume]()
1045
+ }
1046
+ }, 0)
1047
+ socket[kIdleSocketValidationTimeout].unref?.()
1048
+ }
1049
+
1010
1050
  /**
1011
1051
  * @param {import('./client.js')} client
1012
1052
  */
@@ -1024,6 +1064,32 @@ function resumeH1 (client) {
1024
1064
  socket[kNoRef] = false
1025
1065
  }
1026
1066
 
1067
+ if (client[kRunning] === 0 && client[kPending] > 0 && socket[kSocketUsed]) {
1068
+ if (socket[kIdleSocketValidation] === 0) {
1069
+ scheduleIdleSocketValidation(client, socket)
1070
+ socket[kParser].readMore()
1071
+ if (socket.destroyed) {
1072
+ return
1073
+ }
1074
+ return
1075
+ }
1076
+
1077
+ if (socket[kIdleSocketValidation] === 1) {
1078
+ socket[kParser].readMore()
1079
+ if (socket.destroyed) {
1080
+ return
1081
+ }
1082
+ return
1083
+ }
1084
+ }
1085
+
1086
+ if (client[kRunning] === 0) {
1087
+ socket[kParser].readMore()
1088
+ if (socket.destroyed) {
1089
+ return
1090
+ }
1091
+ }
1092
+
1027
1093
  if (client[kSize] === 0) {
1028
1094
  if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) {
1029
1095
  socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE)
@@ -1122,6 +1188,7 @@ function writeH1 (client, request) {
1122
1188
  }
1123
1189
 
1124
1190
  const socket = client[kSocket]
1191
+ clearIdleSocketValidation(socket)
1125
1192
 
1126
1193
  /**
1127
1194
  * @param {Error} [err]