@openclaw/proxyline 0.2.0 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.3.0 - 2026-05-15
4
+
5
+ - Added branded Proxyline dispatcher detection, reusable active-runtime installs, scoped dynamic bypass registration, first-class undici dispatcher tuning options, and a side-effect-light dispatcher detection subpath.
6
+ - Fixed async scoped bypass lifetimes, ambient runtime reuse compatibility checks, WebSocket surface matching, and zero-valued undici timeout handling.
7
+ - Moved `undici` to a peer dependency so host applications share one global dispatcher runtime with Proxyline.
4
8
 
5
9
  ## 0.2.0 - 2026-05-14
6
10
 
package/LICENSE CHANGED
@@ -1,5 +1,6 @@
1
1
  MIT License
2
2
 
3
+ Copyright (c) 2026 OpenClaw Foundation
3
4
  Copyright (c) 2026 Jesse Merhi
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Proxyline
1
+ # 🌐 Proxyline
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/%40openclaw%2Fproxyline.svg)](https://www.npmjs.com/package/@openclaw/proxyline)
4
4
  [![node](https://img.shields.io/node/v/%40openclaw%2Fproxyline.svg)](https://nodejs.org/)
@@ -17,9 +17,11 @@ Website: [proxyline.dev](https://proxyline.dev)
17
17
  - **Two modes.** `managed` forces traffic through a configured proxy and fails closed on bad config. `ambient` reads `HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY` / `NO_PROXY` for tooling that needs environment compatibility.
18
18
  - **Covers the surfaces that matter.** `http.request`, `http.get`, `https.request`, `https.get`, both global agents, the undici global dispatcher, and helpers for WebSocket agents and HTTP CONNECT sockets.
19
19
  - **Replaces caller agents.** In managed mode and active ambient mode, a per-request `http.Agent` passed by a library does not bypass the proxy. TLS options on the caller agent (`ca`, `cert`, `key`, `rejectUnauthorized`, …) are preserved so destination TLS still validates.
20
+ - **Intentional bypasses only.** Managed mode can accept a `bypassPolicy` callback or scoped `registerBypass()` / `withBypass()` calls for trusted loopback or control-plane traffic that must stay direct; every bypass is visible through `explain()`.
21
+ - **Embeddable runtime controls.** `ifActive` handles process singleton reuse/replacement, `undici` options tune dispatcher defaults, and `isProxylineDispatcher()` identifies Proxyline-owned dispatchers without constructor-name checks.
20
22
  - **Scoped proxy CA trust.** `proxyTls.ca` / `proxyTls.caFile` trust a private CA for the proxy endpoint only — no `NODE_EXTRA_CA_CERTS` and no `NODE_TLS_REJECT_UNAUTHORIZED=0`.
21
23
  - **Observable.** `proxy.explain(url)` returns a structured decision (`proxied` / `direct` with a `reason`), and an `onEvent` callback receives `runtime.installed`, `runtime.stopped`, and per-decision events. Proxy URLs are credential-redacted.
22
- - **Restoreable.** `proxy.stop()` restores the captured Node HTTP(S) methods, global agents, undici dispatcher, and fetch globals. The runtime is a process-wide singleton a second install throws `RUNTIME_ALREADY_ACTIVE`.
24
+ - **Restoreable.** `proxy.stop()` restores the captured Node HTTP(S) methods, global agents, undici dispatcher, and fetch globals. The runtime is a process-wide singleton; by default a second active install throws `RUNTIME_ALREADY_ACTIVE`, while `ifActive` can reuse or replace intentionally.
23
25
 
24
26
  ## Install
25
27
 
@@ -29,7 +31,7 @@ pnpm add @openclaw/proxyline
29
31
  npm install @openclaw/proxyline
30
32
  ```
31
33
 
32
- Requires Node 20.18.1+.
34
+ Requires Node 20.18.1+ and a host `undici` dependency compatible with `>=7.25.0 <9`.
33
35
 
34
36
  ## Quick start
35
37
 
@@ -0,0 +1,3 @@
1
+ export declare const PROXYLINE_DISPATCHER_BRAND: unique symbol;
2
+ export declare function isProxylineDispatcher(dispatcher: unknown): boolean;
3
+ //# sourceMappingURL=dispatcher-brand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher-brand.d.ts","sourceRoot":"","sources":["../src/dispatcher-brand.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,0BAA0B,eAA+C,CAAC;AAMvF,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAIlE"}
@@ -0,0 +1,6 @@
1
+ export const PROXYLINE_DISPATCHER_BRAND = Symbol.for("@openclaw/proxyline.dispatcher");
2
+ export function isProxylineDispatcher(dispatcher) {
3
+ return typeof dispatcher === "object" &&
4
+ dispatcher !== null &&
5
+ dispatcher[PROXYLINE_DISPATCHER_BRAND] === true;
6
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { openProxyConnectTunnel, type OpenProxyConnectTunnelOptions } from "./connect.js";
2
2
  export { createAmbientNodeProxyAgent, hasAmbientNodeProxyConfigured, type AmbientNodeProxyAgentOptions, } from "./node-http.js";
3
3
  export { installGlobalProxy, installProxyline } from "./runtime.js";
4
+ export { isProxylineDispatcher, PROXYLINE_DISPATCHER_BRAND } from "./dispatcher-brand.js";
4
5
  export { ProxylineError, redactProxyUrl, resolveProxyTlsCa, type ProxylineTlsOptions, } from "./shared.js";
5
- export type { ExplainOptions, ProxylineBypassPolicy, ProxylineBypassRequest, ProxylineDecision, ProxylineEvent, ProxylineHandle, ProxylineMode, ProxylineOptions, ProxylineSurface, } from "./types.js";
6
+ export type { ExplainOptions, ProxylineBypassRegistration, ProxylineBypassPolicy, ProxylineBypassRequest, ProxylineDecision, ProxylineEvent, ProxylineHandle, ProxylineMode, ProxylineOptions, ProxylineSurface, ProxylineUndiciOptions, } from "./types.js";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,KAAK,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,KAAK,4BAA4B,GAClC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EACL,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,KAAK,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,KAAK,4BAA4B,GAClC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EACL,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { openProxyConnectTunnel } from "./connect.js";
2
2
  export { createAmbientNodeProxyAgent, hasAmbientNodeProxyConfigured, } from "./node-http.js";
3
3
  export { installGlobalProxy, installProxyline } from "./runtime.js";
4
+ export { isProxylineDispatcher, PROXYLINE_DISPATCHER_BRAND } from "./dispatcher-brand.js";
4
5
  export { ProxylineError, redactProxyUrl, resolveProxyTlsCa, } from "./shared.js";
@@ -2,7 +2,7 @@ import http from "node:http";
2
2
  import https from "node:https";
3
3
  import { type ProxyEnvSnapshot } from "./env.js";
4
4
  import { type ProxylineTlsOptions } from "./shared.js";
5
- import type { ProxyResolver } from "./types.js";
5
+ import type { ProxylineSurface, ProxyResolver } from "./types.js";
6
6
  export type NodeHttpRequestOptions = http.RequestOptions & https.RequestOptions & {
7
7
  agent?: http.Agent | false;
8
8
  };
@@ -14,7 +14,7 @@ type NodeAgentRequestOptions = http.RequestOptions & https.RequestOptions & {
14
14
  };
15
15
  type NodeProxyAgentOptions = NodeAgentOptions & {
16
16
  defaultProtocol?: "http" | "https";
17
- getProxyForUrl: (url: string, request?: http.ClientRequest) => string;
17
+ getProxyForUrl: (url: string, surface?: ProxylineSurface, request?: http.ClientRequest) => string;
18
18
  proxyTls?: ProxylineTlsOptions;
19
19
  };
20
20
  export declare const CALLER_AGENT_TLS_OPTION_KEYS: readonly ["ca", "cert", "ciphers", "clientCertEngine", "crl", "dhparam", "ecdhCurve", "honorCipherOrder", "key", "maxVersion", "minVersion", "passphrase", "pfx", "rejectUnauthorized", "secureOptions", "secureProtocol", "sessionIdContext"];
@@ -1 +1 @@
1
- {"version":3,"file":"node-http.d.ts","sourceRoot":"","sources":["../src/node-http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node-http.d.ts","sourceRoot":"","sources":["../src/node-http.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,MAAM,YAAY,CAAC;AAI/B,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAqC,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,GAAG;IAChF,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;CAC5B,CAAC;AAEF,KAAK,cAAc,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC;AAC1C,KAAK,gBAAgB,GAAG,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,CAAC,KAAK,CAAC;AACxE,KAAK,gBAAgB,GAAG,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;AAC/D,KAAK,uBAAuB,GAAG,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,GAAG;IAC1E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAYF,KAAK,qBAAqB,GAAG,gBAAgB,GAAG;IAC9C,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,cAAc,EAAE,CACd,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,EAC1B,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,KACzB,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAChC,CAAC;AAOF,eAAO,MAAM,4BAA4B,gPAkB/B,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IACjC,OAAO,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC;IACzB,eAAe,EAAE,OAAO,IAAI,CAAC,WAAW,CAAC;IACzC,YAAY,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACnC,QAAQ,EAAE,OAAO,KAAK,CAAC,GAAG,CAAC;IAC3B,gBAAgB,EAAE,OAAO,KAAK,CAAC,WAAW,CAAC;CAC5C,CAAC;AA6DF,wBAAgB,kBAAkB,CAAC,OAAO,SAAS,cAAc,EAC/D,cAAc,EAAE,OAAO,EACvB,WAAW,EAAE,gBAAgB,GAC5B,OAAO,CAsCT;AAiiBD,qBAAa,uBAAwB,SAAQ,IAAI,CAAC,KAAK;;IACrD,SAAgB,OAAO,EAAE,gBAAgB,CAAC;gBAYvB,OAAO,EAAE,qBAAqB;IAcjD,IAAW,WAAW,IAAI,MAAM,CAI/B;IAED,IAAW,WAAW,CAAC,KAAK,EAAE,MAAM,EAEnC;IAED,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,QAAQ,CAAC,MAAM,EAAE,MAAM,EAEjC;IAEM,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,GAAG,MAAM;IAsCjE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,EAAE,uBAAuB,GAAG,IAAI;IA6BlE,OAAO,IAAI,IAAI;CAShC;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,aAAa,EACvB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,eAAe,GAAE,MAAM,GAAG,OAAgB,GACzC,uBAAuB,CAMzB;AAED,wBAAgB,qBAAqB,IAAI,uBAAuB,CAI/D;AAED,MAAM,MAAM,4BAA4B,GAAG;IACzC,GAAG,CAAC,EAAE,gBAAgB,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAChC,CAAC;AAMF,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAIT;AAED,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,4BAAiC,GACzC,uBAAuB,GAAG,SAAS,CAWrC"}
package/dist/node-http.js CHANGED
@@ -227,6 +227,12 @@ function isSecureEndpoint(options, stackProtocol) {
227
227
  function shouldTunnelRequest(req, options, stackProtocol) {
228
228
  return isSecureEndpoint(options, stackProtocol) || isWebSocketRequest(req);
229
229
  }
230
+ function requestSurface(req, options, stackProtocol) {
231
+ if (isWebSocketRequest(req)) {
232
+ return "websocket";
233
+ }
234
+ return isSecureEndpoint(options, stackProtocol) ? "node-https" : "node-http";
235
+ }
230
236
  function splitHostPort(value) {
231
237
  const bracketed = value.match(/^\[([^\]]+)\](?::(\d+))?$/);
232
238
  if (bracketed) {
@@ -595,7 +601,7 @@ export class ProxylineNodeProxyAgent extends http.Agent {
595
601
  // Node's http.Agent constructor assigns this, but this wrapper is dual-use.
596
602
  }
597
603
  getProxyForUrl(url, request) {
598
- return this.#getProxyForUrl(url, request);
604
+ return this.#getProxyForUrl(url, undefined, request);
599
605
  }
600
606
  #callStackProtocol() {
601
607
  const originalStackTraceLimit = Error.stackTraceLimit;
@@ -638,7 +644,8 @@ export class ProxylineNodeProxyAgent extends http.Agent {
638
644
  ? { ...options, secureEndpoint: true }
639
645
  : options;
640
646
  const url = requestDestinationUrl(req, agentOptions, stackProtocol);
641
- const proxy = this.#getProxyForUrl(url, req);
647
+ const surface = requestSurface(req, agentOptions, stackProtocol);
648
+ const proxy = this.#getProxyForUrl(url, surface, req);
642
649
  if (!proxy) {
643
650
  (isSecureEndpoint(agentOptions, stackProtocol) ? this.#httpsAgent : this.#httpAgent)
644
651
  .addRequest(req, agentOptions);
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAGV,eAAe,EACf,gBAAgB,EAGjB,MAAM,YAAY,CAAC;AA6kBpB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAqF3E;AAED,eAAO,MAAM,kBAAkB,yBAAmB,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAIV,eAAe,EACf,gBAAgB,EAIjB,MAAM,YAAY,CAAC;AA4sBpB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAyI3E;AAED,eAAO,MAAM,kBAAkB,yBAAmB,CAAC"}
package/dist/runtime.js CHANGED
@@ -4,7 +4,9 @@ import { Agent as UndiciAgent, Dispatcher, FormData as UndiciFormData, Headers a
4
4
  import { createAmbientProxyResolver, EMPTY_PROXY_ENV, resolveAmbientProxyForUrl, readProxyEnv, } from "./env.js";
5
5
  import { bindNodeHttpMethod, createDirectNodeAgent, createNodeProxyAgent, } from "./node-http.js";
6
6
  import { formatUrl, ProxylineError, redactProxyUrl, resolveProxyTlsCa, } from "./shared.js";
7
+ import { PROXYLINE_DISPATCHER_BRAND } from "./dispatcher-brand.js";
7
8
  let activeRuntime;
9
+ let activeHandle;
8
10
  // Node's global fetch types come from bundled undici-types, while the runtime
9
11
  // implementation intentionally delegates to this package's undici dependency.
10
12
  const proxylineHeaders = UndiciHeaders;
@@ -140,13 +142,47 @@ function isProxyableUrlProtocol(protocol) {
140
142
  protocol === "ws:" ||
141
143
  protocol === "wss:";
142
144
  }
143
- function shouldBypassManagedProxy(bypassPolicy, url, surface) {
145
+ function shouldBypassManagedProxy(bypassPolicy, bypasses, url, surface) {
146
+ if (bypasses.has(url, surface)) {
147
+ return true;
148
+ }
144
149
  if (bypassPolicy === undefined) {
145
150
  return false;
146
151
  }
147
152
  return bypassPolicy({ surface, url: formatUrl(url) });
148
153
  }
149
- function createManagedProxyResolver(proxyUrl, bypassPolicy) {
154
+ function bypassKey(url, surface) {
155
+ return `${surface ?? "*"}\n${formatUrl(url)}`;
156
+ }
157
+ function createDynamicBypassRegistry() {
158
+ const counts = new Map();
159
+ return {
160
+ add: (registration) => {
161
+ const key = bypassKey(registration.url, registration.surface);
162
+ counts.set(key, (counts.get(key) ?? 0) + 1);
163
+ let stopped = false;
164
+ return () => {
165
+ if (stopped) {
166
+ return;
167
+ }
168
+ stopped = true;
169
+ const next = (counts.get(key) ?? 1) - 1;
170
+ if (next <= 0) {
171
+ counts.delete(key);
172
+ }
173
+ else {
174
+ counts.set(key, next);
175
+ }
176
+ };
177
+ },
178
+ has: (url, surface) => (counts.get(bypassKey(url, surface)) ?? 0) > 0 ||
179
+ (counts.get(bypassKey(url, undefined)) ?? 0) > 0,
180
+ };
181
+ }
182
+ function proxyEnvSnapshotKey(env) {
183
+ return JSON.stringify(env ?? EMPTY_PROXY_ENV);
184
+ }
185
+ function createManagedProxyResolver(proxyUrl, bypassPolicy, bypasses) {
150
186
  const redactedProxyUrl = redactProxyUrl(proxyUrl);
151
187
  return {
152
188
  active: true,
@@ -161,7 +197,7 @@ function createManagedProxyResolver(proxyUrl, bypassPolicy) {
161
197
  url: formattedUrl,
162
198
  };
163
199
  }
164
- if (shouldBypassManagedProxy(bypassPolicy, url, surface)) {
200
+ if (shouldBypassManagedProxy(bypassPolicy, bypasses, url, surface)) {
165
201
  return {
166
202
  kind: "direct",
167
203
  reason: "managed-proxy-bypass-policy",
@@ -177,34 +213,79 @@ function createManagedProxyResolver(proxyUrl, bypassPolicy) {
177
213
  proxyUrl: redactedProxyUrl,
178
214
  };
179
215
  },
180
- getProxyForUrl: (url) => {
216
+ getProxyForUrl: (url, surface = "unknown") => {
181
217
  const protocol = new URL(url).protocol;
182
218
  return isProxyableUrlProtocol(protocol) &&
183
- !shouldBypassManagedProxy(bypassPolicy, url, "unknown")
219
+ !shouldBypassManagedProxy(bypassPolicy, bypasses, url, surface)
184
220
  ? proxyUrl.href
185
221
  : "";
186
222
  },
187
223
  };
188
224
  }
189
- function createUndiciProxyDispatcher(options, proxyCa) {
225
+ function finiteNonNegativeInteger(value) {
226
+ return typeof value === "number" && Number.isFinite(value) && value >= 0
227
+ ? Math.floor(value)
228
+ : undefined;
229
+ }
230
+ function finitePositiveInteger(value) {
231
+ return typeof value === "number" && Number.isFinite(value) && value > 0
232
+ ? Math.floor(value)
233
+ : undefined;
234
+ }
235
+ function resolveUndiciBaseOptions(options) {
236
+ const bodyTimeout = finiteNonNegativeInteger(options?.bodyTimeout);
237
+ const headersTimeout = finiteNonNegativeInteger(options?.headersTimeout);
238
+ return {
239
+ ...(options?.allowH2 !== undefined ? { allowH2: options.allowH2 } : {}),
240
+ ...(bodyTimeout !== undefined ? { bodyTimeout } : {}),
241
+ ...(headersTimeout !== undefined ? { headersTimeout } : {}),
242
+ ...(options?.connect !== undefined
243
+ ? {
244
+ connect: {
245
+ ...(options.connect.autoSelectFamily !== undefined
246
+ ? { autoSelectFamily: options.connect.autoSelectFamily }
247
+ : {}),
248
+ ...(finitePositiveInteger(options.connect.autoSelectFamilyAttemptTimeout) !== undefined
249
+ ? {
250
+ autoSelectFamilyAttemptTimeout: finitePositiveInteger(options.connect.autoSelectFamilyAttemptTimeout),
251
+ }
252
+ : {}),
253
+ },
254
+ }
255
+ : {}),
256
+ };
257
+ }
258
+ function createUndiciAgent(options) {
259
+ return new UndiciAgent(resolveUndiciBaseOptions(options));
260
+ }
261
+ function createUndiciProxyAgent(proxyUrl, options) {
262
+ return new UndiciProxyAgent({
263
+ ...resolveUndiciBaseOptions(options.undici),
264
+ uri: proxyUrl,
265
+ ...(options.proxyCa !== undefined ? { proxyTls: { ca: options.proxyCa } } : {}),
266
+ });
267
+ }
268
+ function createUndiciProxyDispatcher(options, dispatcherOptions) {
190
269
  if (options.mode === "ambient") {
191
270
  if (!options.active) {
192
- return new UndiciAgent();
271
+ return createUndiciAgent(dispatcherOptions.undici);
193
272
  }
194
- return new AmbientUndiciDispatcher(options.env, proxyCa);
273
+ return new AmbientUndiciDispatcher(options.env, dispatcherOptions);
195
274
  }
196
- return new ManagedUndiciDispatcher(options.resolver, proxyCa);
275
+ return new ManagedUndiciDispatcher(options.resolver, dispatcherOptions);
197
276
  }
198
277
  class ManagedUndiciDispatcher extends Dispatcher {
199
- #directDispatcher = new UndiciAgent();
200
- #proxyCa;
278
+ [PROXYLINE_DISPATCHER_BRAND] = true;
279
+ #directDispatcher;
280
+ #dispatcherOptions;
201
281
  #proxyDispatchers = new Map();
202
282
  #resolver;
203
283
  #closedError;
204
- constructor(resolver, proxyCa) {
284
+ constructor(resolver, dispatcherOptions) {
205
285
  super();
206
286
  this.#resolver = resolver;
207
- this.#proxyCa = proxyCa;
287
+ this.#dispatcherOptions = dispatcherOptions;
288
+ this.#directDispatcher = createUndiciAgent(dispatcherOptions.undici);
208
289
  }
209
290
  dispatch(options, handler) {
210
291
  if (this.#closedError !== undefined) {
@@ -215,7 +296,7 @@ class ManagedUndiciDispatcher extends Dispatcher {
215
296
  return false;
216
297
  }
217
298
  const url = resolveUndiciDispatchUrl(options);
218
- const proxyUrl = url === undefined ? "" : this.#resolver.getProxyForUrl(url);
299
+ const proxyUrl = url === undefined ? "" : this.#resolver.getProxyForUrl(url, "undici");
219
300
  const dispatcher = proxyUrl === "" ? this.#directDispatcher : this.#proxyDispatcher(proxyUrl);
220
301
  return dispatcher.dispatch(options, handler);
221
302
  }
@@ -240,10 +321,7 @@ class ManagedUndiciDispatcher extends Dispatcher {
240
321
  if (existing !== undefined) {
241
322
  return existing;
242
323
  }
243
- const dispatcher = new UndiciProxyAgent({
244
- uri: proxyUrl,
245
- ...(this.#proxyCa !== undefined ? { proxyTls: { ca: this.#proxyCa } } : {}),
246
- });
324
+ const dispatcher = createUndiciProxyAgent(proxyUrl, this.#dispatcherOptions);
247
325
  this.#proxyDispatchers.set(proxyUrl, dispatcher);
248
326
  return dispatcher;
249
327
  }
@@ -267,15 +345,17 @@ class ManagedUndiciDispatcher extends Dispatcher {
267
345
  }
268
346
  }
269
347
  class AmbientUndiciDispatcher extends Dispatcher {
270
- #directDispatcher = new UndiciAgent();
348
+ [PROXYLINE_DISPATCHER_BRAND] = true;
349
+ #directDispatcher;
350
+ #dispatcherOptions;
271
351
  #env;
272
- #proxyCa;
273
352
  #proxyDispatchers = new Map();
274
353
  #closedError;
275
- constructor(env, proxyCa) {
354
+ constructor(env, dispatcherOptions) {
276
355
  super();
277
356
  this.#env = env;
278
- this.#proxyCa = proxyCa;
357
+ this.#dispatcherOptions = dispatcherOptions;
358
+ this.#directDispatcher = createUndiciAgent(dispatcherOptions.undici);
279
359
  }
280
360
  dispatch(options, handler) {
281
361
  if (this.#closedError !== undefined) {
@@ -311,10 +391,7 @@ class AmbientUndiciDispatcher extends Dispatcher {
311
391
  if (existing !== undefined) {
312
392
  return existing;
313
393
  }
314
- const dispatcher = new UndiciProxyAgent({
315
- uri: proxyUrl,
316
- ...(this.#proxyCa !== undefined ? { proxyTls: { ca: this.#proxyCa } } : {}),
317
- });
394
+ const dispatcher = createUndiciProxyAgent(proxyUrl, this.#dispatcherOptions);
318
395
  this.#proxyDispatchers.set(proxyUrl, dispatcher);
319
396
  return dispatcher;
320
397
  }
@@ -358,7 +435,7 @@ function restoreNodeHttpSnapshot(snapshot) {
358
435
  https.get = snapshot.httpsGet;
359
436
  https.globalAgent = snapshot.httpsGlobalAgent;
360
437
  }
361
- function installRuntime(resolver, dispatcherOptions, proxyCa) {
438
+ function installRuntime(resolver, dispatcherOptions, proxyCa, options) {
362
439
  if (activeRuntime !== undefined) {
363
440
  throw new ProxylineError("RUNTIME_ALREADY_ACTIVE", "Proxyline already has an active runtime.");
364
441
  }
@@ -378,8 +455,13 @@ function installRuntime(resolver, dispatcherOptions, proxyCa) {
378
455
  const originalHeaders = globalThis.Headers;
379
456
  const originalRequest = globalThis.Request;
380
457
  const originalResponse = globalThis.Response;
381
- const installedDispatcher = createUndiciProxyDispatcher(dispatcherOptions, proxyCa);
458
+ const installedDispatcher = createUndiciProxyDispatcher(dispatcherOptions, {
459
+ proxyCa,
460
+ undici: options.undici,
461
+ });
382
462
  const runtime = {
463
+ ambientEnv: options.ambientEnv,
464
+ bypassPolicy: options.bypassPolicy,
383
465
  installedDispatcher,
384
466
  mode: dispatcherOptions.mode,
385
467
  nodeHttpAgent,
@@ -390,7 +472,10 @@ function installRuntime(resolver, dispatcherOptions, proxyCa) {
390
472
  originalHeaders,
391
473
  originalRequest,
392
474
  originalResponse,
475
+ proxyCa,
476
+ proxyUrl: options.proxyUrl?.href,
393
477
  snapshot,
478
+ undiciOptions: options.undici,
394
479
  };
395
480
  activeRuntime = runtime;
396
481
  try {
@@ -438,24 +523,50 @@ function stopRuntime(runtime) {
438
523
  runtime.nodeHttpAgent.destroy();
439
524
  runtime.nodeHttpsAgent.destroy();
440
525
  activeRuntime = undefined;
526
+ activeHandle = undefined;
441
527
  }
442
528
  export function installProxyline(options) {
443
529
  const proxyUrl = options.mode === "managed" ? normalizeProxyUrl(options.proxyUrl) : undefined;
530
+ const ambientEnv = proxyUrl === undefined ? readProxyEnv() : undefined;
444
531
  if (options.mode === "managed" && proxyUrl === undefined) {
445
532
  throw new ProxylineError("MANAGED_PROXY_URL_REQUIRED", "Proxyline managed mode requires an explicit proxyUrl.");
446
533
  }
534
+ const activePolicy = options.ifActive ?? "error";
535
+ if (activeRuntime !== undefined) {
536
+ if (activePolicy === "replace") {
537
+ activeHandle?.stop();
538
+ }
539
+ else if (activePolicy === "reuse-compatible" &&
540
+ activeHandle !== undefined &&
541
+ activeRuntime.mode === options.mode &&
542
+ activeRuntime.proxyUrl === proxyUrl?.href &&
543
+ proxyEnvSnapshotKey(activeRuntime.ambientEnv) === proxyEnvSnapshotKey(ambientEnv) &&
544
+ activeRuntime.proxyCa === resolveProxyTlsCa(options.proxyTls) &&
545
+ activeRuntime.bypassPolicy === options.bypassPolicy &&
546
+ JSON.stringify(activeRuntime.undiciOptions ?? {}) === JSON.stringify(options.undici ?? {})) {
547
+ return activeHandle;
548
+ }
549
+ else {
550
+ throw new ProxylineError("RUNTIME_ALREADY_ACTIVE", "Proxyline already has an active runtime.");
551
+ }
552
+ }
447
553
  let stopped = false;
448
554
  const proxyCa = resolveProxyTlsCa(options.proxyTls);
449
- const ambientEnv = proxyUrl === undefined ? readProxyEnv() : undefined;
555
+ const dynamicBypasses = createDynamicBypassRegistry();
450
556
  const resolver = proxyUrl !== undefined
451
- ? createManagedProxyResolver(proxyUrl, options.bypassPolicy)
557
+ ? createManagedProxyResolver(proxyUrl, options.bypassPolicy, dynamicBypasses)
452
558
  : createAmbientProxyResolver(ambientEnv ?? EMPTY_PROXY_ENV);
453
559
  const redactedProxyUrl = resolver.describeProxy();
454
560
  const hasActiveProxy = resolver.active;
455
561
  const runtime = hasActiveProxy
456
562
  ? installRuntime(resolver, proxyUrl !== undefined
457
563
  ? { mode: "managed", resolver }
458
- : { mode: "ambient", env: ambientEnv ?? EMPTY_PROXY_ENV, active: hasActiveProxy }, proxyCa)
564
+ : { mode: "ambient", env: ambientEnv ?? EMPTY_PROXY_ENV, active: hasActiveProxy }, proxyCa, {
565
+ ambientEnv,
566
+ bypassPolicy: options.bypassPolicy,
567
+ proxyUrl,
568
+ undici: options.undici,
569
+ })
459
570
  : undefined;
460
571
  emit(options.onEvent, {
461
572
  type: "runtime.installed",
@@ -474,10 +585,10 @@ export function installProxyline(options) {
474
585
  return createNodeProxyAgent(resolver, proxyCa);
475
586
  },
476
587
  createUndiciDispatcher: () => stopped
477
- ? new UndiciAgent()
588
+ ? createUndiciAgent(options.undici)
478
589
  : createUndiciProxyDispatcher(proxyUrl !== undefined
479
590
  ? { mode: "managed", resolver }
480
- : { mode: "ambient", env: ambientEnv ?? EMPTY_PROXY_ENV, active: hasActiveProxy }, proxyCa),
591
+ : { mode: "ambient", env: ambientEnv ?? EMPTY_PROXY_ENV, active: hasActiveProxy }, { proxyCa, undici: options.undici }),
481
592
  createWebSocketAgent: () => {
482
593
  if (!hasActiveProxy || stopped) {
483
594
  return createDirectNodeAgent();
@@ -496,6 +607,12 @@ export function installProxyline(options) {
496
607
  emit(options.onEvent, { type: "decision", decision });
497
608
  return decision;
498
609
  },
610
+ registerBypass: (registration) => {
611
+ if (stopped || proxyUrl === undefined) {
612
+ return () => { };
613
+ }
614
+ return dynamicBypasses.add(registration);
615
+ },
499
616
  stop: () => {
500
617
  if (stopped) {
501
618
  return;
@@ -506,7 +623,29 @@ export function installProxyline(options) {
506
623
  }
507
624
  emit(options.onEvent, { type: "runtime.stopped", mode: options.mode });
508
625
  },
626
+ withBypass: (registration, run) => {
627
+ const unregister = handle.registerBypass(registration);
628
+ try {
629
+ const result = run();
630
+ if (isPromiseLike(result)) {
631
+ void Promise.resolve(result).then(unregister, unregister);
632
+ return result;
633
+ }
634
+ unregister();
635
+ return result;
636
+ }
637
+ catch (error) {
638
+ unregister();
639
+ throw error;
640
+ }
641
+ },
509
642
  };
643
+ activeHandle = hasActiveProxy ? handle : activeHandle;
510
644
  return handle;
511
645
  }
512
646
  export const installGlobalProxy = installProxyline;
647
+ function isPromiseLike(value) {
648
+ return typeof value === "object" &&
649
+ value !== null &&
650
+ typeof value.then === "function";
651
+ }
package/dist/types.d.ts CHANGED
@@ -8,7 +8,9 @@ export type ProxylineOptions = Readonly<{
8
8
  proxyUrl?: string | URL;
9
9
  proxyTls?: ProxylineTlsOptions;
10
10
  bypassPolicy?: ProxylineBypassPolicy;
11
+ ifActive?: "error" | "reuse-compatible" | "replace";
11
12
  onEvent?: (event: ProxylineEvent) => void;
13
+ undici?: ProxylineUndiciOptions;
12
14
  }>;
13
15
  export type ProxylineDecision = Readonly<{
14
16
  kind: "proxied" | "direct" | "blocked";
@@ -41,6 +43,19 @@ export type ProxylineEvent = Readonly<{
41
43
  export type ExplainOptions = Readonly<{
42
44
  surface?: ProxylineSurface;
43
45
  }>;
46
+ export type ProxylineBypassRegistration = Readonly<{
47
+ surface?: ProxylineSurface;
48
+ url: string | URL;
49
+ }>;
50
+ export type ProxylineUndiciOptions = Readonly<{
51
+ allowH2?: boolean;
52
+ bodyTimeout?: number;
53
+ headersTimeout?: number;
54
+ connect?: Readonly<{
55
+ autoSelectFamily?: boolean;
56
+ autoSelectFamilyAttemptTimeout?: number;
57
+ }>;
58
+ }>;
44
59
  export type ProxylineHandle = Readonly<{
45
60
  mode: ProxylineMode;
46
61
  active: boolean;
@@ -49,12 +64,14 @@ export type ProxylineHandle = Readonly<{
49
64
  createUndiciDispatcher: () => Dispatcher;
50
65
  createWebSocketAgent: () => HttpAgent;
51
66
  explain: (url: string | URL, options?: ExplainOptions) => ProxylineDecision;
67
+ registerBypass: (registration: ProxylineBypassRegistration) => () => void;
52
68
  stop: () => void;
69
+ withBypass: <T>(registration: ProxylineBypassRegistration, run: () => T) => T;
53
70
  }>;
54
71
  export type ProxyResolver = Readonly<{
55
72
  active: boolean;
56
73
  describeProxy: () => string | undefined;
57
74
  explain: (url: string | URL, surface: ProxylineSurface) => ProxylineDecision;
58
- getProxyForUrl: (url: string) => string;
75
+ getProxyForUrl: (url: string, surface?: ProxylineSurface) => string;
59
76
  }>;
60
77
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/proxyline",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Process-global proxy routing for Node.js.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -22,6 +22,10 @@
22
22
  ".": {
23
23
  "types": "./dist/index.d.ts",
24
24
  "default": "./dist/index.js"
25
+ },
26
+ "./dispatcher-brand": {
27
+ "types": "./dist/dispatcher-brand.d.ts",
28
+ "default": "./dist/dispatcher-brand.js"
25
29
  }
26
30
  },
27
31
  "files": [
@@ -40,6 +44,7 @@
40
44
  "docs:build": "node scripts/build-docs-site.mjs",
41
45
  "package:dry-run": "pnpm pack --dry-run",
42
46
  "prepack": "node scripts/prepack-build.mjs",
47
+ "prepare": "node scripts/prepack-build.mjs",
43
48
  "publish:dry-run": "pnpm publish --dry-run --access public",
44
49
  "test": "pnpm build && tsx --test test/index.test.ts test/e2e.test.ts test/package.test.ts",
45
50
  "typecheck": "pnpm build && tsc --noEmit"
@@ -49,12 +54,13 @@
49
54
  "@types/ws": "^8.18.1",
50
55
  "tsx": "^4.21.0",
51
56
  "typescript": "^5.9.3",
57
+ "undici": "^7.25.0",
52
58
  "ws": "^8.20.0"
53
59
  },
54
60
  "engines": {
55
61
  "node": ">=20.18.1"
56
62
  },
57
- "dependencies": {
58
- "undici": "^7.25.0"
63
+ "peerDependencies": {
64
+ "undici": ">=7.25.0 <9"
59
65
  }
60
66
  }