agent-shim 8.0.1 → 8.0.2
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/dist/cli.cjs +54 -14
- package/dist/index.cjs +53 -13
- package/dist/index.mjs +53 -13
- package/dist/types/index.d.ts +10 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -61039,7 +61039,7 @@ function registerIdentityCommand(program2, deps) {
|
|
|
61039
61039
|
// package.json
|
|
61040
61040
|
var package_default = {
|
|
61041
61041
|
name: "agent-shim",
|
|
61042
|
-
version: "8.0.
|
|
61042
|
+
version: "8.0.2",
|
|
61043
61043
|
description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
|
|
61044
61044
|
license: "MIT",
|
|
61045
61045
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -64665,14 +64665,11 @@ ${request6.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
64665
64665
|
};
|
|
64666
64666
|
const sessions = config2.interceptHosts.map((host) => {
|
|
64667
64667
|
if (config2.tapHosts.includes(host)) {
|
|
64668
|
-
const
|
|
64669
|
-
config2.
|
|
64670
|
-
|
|
64671
|
-
|
|
64672
|
-
|
|
64673
|
-
TAP_ALPN_PROTOCOLS
|
|
64674
|
-
);
|
|
64675
|
-
return { host, tlsAcceptor: tlsAcceptor2 };
|
|
64668
|
+
const serveSecure2 = (secure) => {
|
|
64669
|
+
pumpTapSession(secure, async (clientAlpn) => await effects.connectTlsUpstream(host, HTTPS_PORT, clientAlpn), config2.capture?.tapStream?.(host));
|
|
64670
|
+
};
|
|
64671
|
+
const tlsAcceptor2 = effects.createTlsAcceptor(config2.leafFor(host), serveSecure2, TAP_ALPN_PROTOCOLS);
|
|
64672
|
+
return { host, serveSecure: serveSecure2, tlsAcceptor: tlsAcceptor2 };
|
|
64676
64673
|
}
|
|
64677
64674
|
const handler = (request6, response) => {
|
|
64678
64675
|
if (host === config2.routedHost && servedByPipeline(request6.url)) {
|
|
@@ -64686,19 +64683,29 @@ ${request6.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
64686
64683
|
effects.forwardHttp(config2.upstreamFor(host), request6, response, config2.capture?.observePassthrough(request6));
|
|
64687
64684
|
};
|
|
64688
64685
|
const httpSession = effects.createHttpSession(handler, onUpgrade(host));
|
|
64689
|
-
const
|
|
64690
|
-
tunnelTokens.set(secure,
|
|
64686
|
+
const serveSecure = (secure, capability) => {
|
|
64687
|
+
tunnelTokens.set(secure, capability);
|
|
64691
64688
|
httpSession.serve(secure);
|
|
64692
|
-
}
|
|
64693
|
-
|
|
64689
|
+
};
|
|
64690
|
+
const tlsAcceptor = effects.createTlsAcceptor(config2.leafFor(host), serveSecure);
|
|
64691
|
+
return { host, serveSecure, httpSession, tlsAcceptor };
|
|
64694
64692
|
});
|
|
64695
64693
|
const ledger = createConnectionLedger(config2.limits, config2.isLiveCapability);
|
|
64696
64694
|
const listener = await effects.listenLoopback(preferredPort, (socket) => {
|
|
64697
64695
|
handleConnect(socket, { config: config2, effects, sessions, ledger });
|
|
64698
64696
|
});
|
|
64699
64697
|
const apiSession = sessions.find((session) => session.host === config2.routedHost);
|
|
64698
|
+
const sessionByHost = new Map(sessions.map((session) => [session.host, session]));
|
|
64699
|
+
const sniAcceptor = effects.createSniTlsAcceptor(config2.interceptHosts, config2.leafFor, (secure, host) => {
|
|
64700
|
+
const session = sessionByHost.get(host);
|
|
64701
|
+
if (session === void 0) {
|
|
64702
|
+
secure.destroy();
|
|
64703
|
+
return;
|
|
64704
|
+
}
|
|
64705
|
+
session.serveSecure(secure, config2.transparentCapability ?? "");
|
|
64706
|
+
});
|
|
64700
64707
|
const transparent = config2.transparentPort === void 0 || apiSession === void 0 ? void 0 : await effects.listenLoopback(config2.transparentPort, (socket) => {
|
|
64701
|
-
|
|
64708
|
+
sniAcceptor.accept(socket);
|
|
64702
64709
|
});
|
|
64703
64710
|
return {
|
|
64704
64711
|
port: listener.port,
|
|
@@ -64707,6 +64714,7 @@ ${request6.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
64707
64714
|
ledger.close();
|
|
64708
64715
|
await listener.close();
|
|
64709
64716
|
await transparent?.close();
|
|
64717
|
+
sniAcceptor.close();
|
|
64710
64718
|
for (const { httpSession, tlsAcceptor } of sessions) {
|
|
64711
64719
|
tlsAcceptor.close();
|
|
64712
64720
|
httpSession?.close();
|
|
@@ -65036,6 +65044,38 @@ function realConnectEffects() {
|
|
|
65036
65044
|
}
|
|
65037
65045
|
};
|
|
65038
65046
|
},
|
|
65047
|
+
createSniTlsAcceptor: (hosts, leafFor, onSecure) => {
|
|
65048
|
+
const contexts = new Map(
|
|
65049
|
+
hosts.map((host) => {
|
|
65050
|
+
const leaf = leafFor(host);
|
|
65051
|
+
return [host, tls.createSecureContext({ key: leaf.keyPem, cert: leaf.certPem })];
|
|
65052
|
+
})
|
|
65053
|
+
);
|
|
65054
|
+
const server = tls.createServer(
|
|
65055
|
+
{
|
|
65056
|
+
// No default key or cert exists, so the SNI selection is the only source of credentials: an unserved name fails its handshake here, and a client that sent no SNI at all never reaches the selection and fails for want of any certificate, which is exactly the fail-closed shape this surface wants.
|
|
65057
|
+
SNICallback: (servername, callback) => {
|
|
65058
|
+
const context = contexts.get(servername);
|
|
65059
|
+
callback(context === void 0 ? new Error(`the transparent surface serves no host named ${servername}`) : null, context);
|
|
65060
|
+
}
|
|
65061
|
+
},
|
|
65062
|
+
(secure) => {
|
|
65063
|
+
onSecure(secure, typeof secure.servername === "string" ? secure.servername : "");
|
|
65064
|
+
}
|
|
65065
|
+
);
|
|
65066
|
+
server.on("clientError", (_error, socket) => {
|
|
65067
|
+
socket.destroy();
|
|
65068
|
+
});
|
|
65069
|
+
return {
|
|
65070
|
+
// The same hand-off the single-leaf acceptor uses: emitting the connection event runs the TLS server's own connection listener on a socket this process already owns (the redirect half of the connection) rather than one the server accepted itself.
|
|
65071
|
+
accept: (socket) => {
|
|
65072
|
+
server.emit("connection", socket);
|
|
65073
|
+
},
|
|
65074
|
+
close: () => {
|
|
65075
|
+
server.close();
|
|
65076
|
+
}
|
|
65077
|
+
};
|
|
65078
|
+
},
|
|
65039
65079
|
createHttpSession: (handler, onUpgrade) => {
|
|
65040
65080
|
const server = http.createServer(handler);
|
|
65041
65081
|
server.on("clientError", (_error, socket) => {
|
package/dist/index.cjs
CHANGED
|
@@ -2959,14 +2959,11 @@ ${request3.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
2959
2959
|
};
|
|
2960
2960
|
const sessions = config.interceptHosts.map((host) => {
|
|
2961
2961
|
if (config.tapHosts.includes(host)) {
|
|
2962
|
-
const
|
|
2963
|
-
config.
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
TAP_ALPN_PROTOCOLS
|
|
2968
|
-
);
|
|
2969
|
-
return { host, tlsAcceptor: tlsAcceptor2 };
|
|
2962
|
+
const serveSecure2 = (secure) => {
|
|
2963
|
+
pumpTapSession(secure, async (clientAlpn) => await effects.connectTlsUpstream(host, HTTPS_PORT, clientAlpn), config.capture?.tapStream?.(host));
|
|
2964
|
+
};
|
|
2965
|
+
const tlsAcceptor2 = effects.createTlsAcceptor(config.leafFor(host), serveSecure2, TAP_ALPN_PROTOCOLS);
|
|
2966
|
+
return { host, serveSecure: serveSecure2, tlsAcceptor: tlsAcceptor2 };
|
|
2970
2967
|
}
|
|
2971
2968
|
const handler = (request3, response) => {
|
|
2972
2969
|
if (host === config.routedHost && servedByPipeline(request3.url)) {
|
|
@@ -2980,19 +2977,29 @@ ${request3.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
2980
2977
|
effects.forwardHttp(config.upstreamFor(host), request3, response, config.capture?.observePassthrough(request3));
|
|
2981
2978
|
};
|
|
2982
2979
|
const httpSession = effects.createHttpSession(handler, onUpgrade(host));
|
|
2983
|
-
const
|
|
2984
|
-
tunnelTokens.set(secure,
|
|
2980
|
+
const serveSecure = (secure, capability) => {
|
|
2981
|
+
tunnelTokens.set(secure, capability);
|
|
2985
2982
|
httpSession.serve(secure);
|
|
2986
|
-
}
|
|
2987
|
-
|
|
2983
|
+
};
|
|
2984
|
+
const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(host), serveSecure);
|
|
2985
|
+
return { host, serveSecure, httpSession, tlsAcceptor };
|
|
2988
2986
|
});
|
|
2989
2987
|
const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
|
|
2990
2988
|
const listener = await effects.listenLoopback(preferredPort, (socket) => {
|
|
2991
2989
|
handleConnect(socket, { config, effects, sessions, ledger });
|
|
2992
2990
|
});
|
|
2993
2991
|
const apiSession = sessions.find((session) => session.host === config.routedHost);
|
|
2992
|
+
const sessionByHost = new Map(sessions.map((session) => [session.host, session]));
|
|
2993
|
+
const sniAcceptor = effects.createSniTlsAcceptor(config.interceptHosts, config.leafFor, (secure, host) => {
|
|
2994
|
+
const session = sessionByHost.get(host);
|
|
2995
|
+
if (session === void 0) {
|
|
2996
|
+
secure.destroy();
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
session.serveSecure(secure, config.transparentCapability ?? "");
|
|
3000
|
+
});
|
|
2994
3001
|
const transparent = config.transparentPort === void 0 || apiSession === void 0 ? void 0 : await effects.listenLoopback(config.transparentPort, (socket) => {
|
|
2995
|
-
|
|
3002
|
+
sniAcceptor.accept(socket);
|
|
2996
3003
|
});
|
|
2997
3004
|
return {
|
|
2998
3005
|
port: listener.port,
|
|
@@ -3001,6 +3008,7 @@ ${request3.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
3001
3008
|
ledger.close();
|
|
3002
3009
|
await listener.close();
|
|
3003
3010
|
await transparent?.close();
|
|
3011
|
+
sniAcceptor.close();
|
|
3004
3012
|
for (const { httpSession, tlsAcceptor } of sessions) {
|
|
3005
3013
|
tlsAcceptor.close();
|
|
3006
3014
|
httpSession?.close();
|
|
@@ -3330,6 +3338,38 @@ function realConnectEffects() {
|
|
|
3330
3338
|
}
|
|
3331
3339
|
};
|
|
3332
3340
|
},
|
|
3341
|
+
createSniTlsAcceptor: (hosts, leafFor, onSecure) => {
|
|
3342
|
+
const contexts = new Map(
|
|
3343
|
+
hosts.map((host) => {
|
|
3344
|
+
const leaf = leafFor(host);
|
|
3345
|
+
return [host, tls.createSecureContext({ key: leaf.keyPem, cert: leaf.certPem })];
|
|
3346
|
+
})
|
|
3347
|
+
);
|
|
3348
|
+
const server = tls.createServer(
|
|
3349
|
+
{
|
|
3350
|
+
// No default key or cert exists, so the SNI selection is the only source of credentials: an unserved name fails its handshake here, and a client that sent no SNI at all never reaches the selection and fails for want of any certificate, which is exactly the fail-closed shape this surface wants.
|
|
3351
|
+
SNICallback: (servername, callback) => {
|
|
3352
|
+
const context = contexts.get(servername);
|
|
3353
|
+
callback(context === void 0 ? new Error(`the transparent surface serves no host named ${servername}`) : null, context);
|
|
3354
|
+
}
|
|
3355
|
+
},
|
|
3356
|
+
(secure) => {
|
|
3357
|
+
onSecure(secure, typeof secure.servername === "string" ? secure.servername : "");
|
|
3358
|
+
}
|
|
3359
|
+
);
|
|
3360
|
+
server.on("clientError", (_error, socket) => {
|
|
3361
|
+
socket.destroy();
|
|
3362
|
+
});
|
|
3363
|
+
return {
|
|
3364
|
+
// The same hand-off the single-leaf acceptor uses: emitting the connection event runs the TLS server's own connection listener on a socket this process already owns (the redirect half of the connection) rather than one the server accepted itself.
|
|
3365
|
+
accept: (socket) => {
|
|
3366
|
+
server.emit("connection", socket);
|
|
3367
|
+
},
|
|
3368
|
+
close: () => {
|
|
3369
|
+
server.close();
|
|
3370
|
+
}
|
|
3371
|
+
};
|
|
3372
|
+
},
|
|
3333
3373
|
createHttpSession: (handler, onUpgrade) => {
|
|
3334
3374
|
const server = http.createServer(handler);
|
|
3335
3375
|
server.on("clientError", (_error, socket) => {
|
package/dist/index.mjs
CHANGED
|
@@ -2793,14 +2793,11 @@ ${request3.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
2793
2793
|
};
|
|
2794
2794
|
const sessions = config.interceptHosts.map((host) => {
|
|
2795
2795
|
if (config.tapHosts.includes(host)) {
|
|
2796
|
-
const
|
|
2797
|
-
config.
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
TAP_ALPN_PROTOCOLS
|
|
2802
|
-
);
|
|
2803
|
-
return { host, tlsAcceptor: tlsAcceptor2 };
|
|
2796
|
+
const serveSecure2 = (secure) => {
|
|
2797
|
+
pumpTapSession(secure, async (clientAlpn) => await effects.connectTlsUpstream(host, HTTPS_PORT, clientAlpn), config.capture?.tapStream?.(host));
|
|
2798
|
+
};
|
|
2799
|
+
const tlsAcceptor2 = effects.createTlsAcceptor(config.leafFor(host), serveSecure2, TAP_ALPN_PROTOCOLS);
|
|
2800
|
+
return { host, serveSecure: serveSecure2, tlsAcceptor: tlsAcceptor2 };
|
|
2804
2801
|
}
|
|
2805
2802
|
const handler = (request3, response) => {
|
|
2806
2803
|
if (host === config.routedHost && servedByPipeline(request3.url)) {
|
|
@@ -2814,19 +2811,29 @@ ${request3.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
2814
2811
|
effects.forwardHttp(config.upstreamFor(host), request3, response, config.capture?.observePassthrough(request3));
|
|
2815
2812
|
};
|
|
2816
2813
|
const httpSession = effects.createHttpSession(handler, onUpgrade(host));
|
|
2817
|
-
const
|
|
2818
|
-
tunnelTokens.set(secure,
|
|
2814
|
+
const serveSecure = (secure, capability) => {
|
|
2815
|
+
tunnelTokens.set(secure, capability);
|
|
2819
2816
|
httpSession.serve(secure);
|
|
2820
|
-
}
|
|
2821
|
-
|
|
2817
|
+
};
|
|
2818
|
+
const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(host), serveSecure);
|
|
2819
|
+
return { host, serveSecure, httpSession, tlsAcceptor };
|
|
2822
2820
|
});
|
|
2823
2821
|
const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
|
|
2824
2822
|
const listener = await effects.listenLoopback(preferredPort, (socket) => {
|
|
2825
2823
|
handleConnect(socket, { config, effects, sessions, ledger });
|
|
2826
2824
|
});
|
|
2827
2825
|
const apiSession = sessions.find((session) => session.host === config.routedHost);
|
|
2826
|
+
const sessionByHost = new Map(sessions.map((session) => [session.host, session]));
|
|
2827
|
+
const sniAcceptor = effects.createSniTlsAcceptor(config.interceptHosts, config.leafFor, (secure, host) => {
|
|
2828
|
+
const session = sessionByHost.get(host);
|
|
2829
|
+
if (session === void 0) {
|
|
2830
|
+
secure.destroy();
|
|
2831
|
+
return;
|
|
2832
|
+
}
|
|
2833
|
+
session.serveSecure(secure, config.transparentCapability ?? "");
|
|
2834
|
+
});
|
|
2828
2835
|
const transparent = config.transparentPort === void 0 || apiSession === void 0 ? void 0 : await effects.listenLoopback(config.transparentPort, (socket) => {
|
|
2829
|
-
|
|
2836
|
+
sniAcceptor.accept(socket);
|
|
2830
2837
|
});
|
|
2831
2838
|
return {
|
|
2832
2839
|
port: listener.port,
|
|
@@ -2835,6 +2842,7 @@ ${request3.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
2835
2842
|
ledger.close();
|
|
2836
2843
|
await listener.close();
|
|
2837
2844
|
await transparent?.close();
|
|
2845
|
+
sniAcceptor.close();
|
|
2838
2846
|
for (const { httpSession, tlsAcceptor } of sessions) {
|
|
2839
2847
|
tlsAcceptor.close();
|
|
2840
2848
|
httpSession?.close();
|
|
@@ -3164,6 +3172,38 @@ function realConnectEffects() {
|
|
|
3164
3172
|
}
|
|
3165
3173
|
};
|
|
3166
3174
|
},
|
|
3175
|
+
createSniTlsAcceptor: (hosts, leafFor, onSecure) => {
|
|
3176
|
+
const contexts = new Map(
|
|
3177
|
+
hosts.map((host) => {
|
|
3178
|
+
const leaf = leafFor(host);
|
|
3179
|
+
return [host, tls.createSecureContext({ key: leaf.keyPem, cert: leaf.certPem })];
|
|
3180
|
+
})
|
|
3181
|
+
);
|
|
3182
|
+
const server = tls.createServer(
|
|
3183
|
+
{
|
|
3184
|
+
// No default key or cert exists, so the SNI selection is the only source of credentials: an unserved name fails its handshake here, and a client that sent no SNI at all never reaches the selection and fails for want of any certificate, which is exactly the fail-closed shape this surface wants.
|
|
3185
|
+
SNICallback: (servername, callback) => {
|
|
3186
|
+
const context = contexts.get(servername);
|
|
3187
|
+
callback(context === void 0 ? new Error(`the transparent surface serves no host named ${servername}`) : null, context);
|
|
3188
|
+
}
|
|
3189
|
+
},
|
|
3190
|
+
(secure) => {
|
|
3191
|
+
onSecure(secure, typeof secure.servername === "string" ? secure.servername : "");
|
|
3192
|
+
}
|
|
3193
|
+
);
|
|
3194
|
+
server.on("clientError", (_error, socket) => {
|
|
3195
|
+
socket.destroy();
|
|
3196
|
+
});
|
|
3197
|
+
return {
|
|
3198
|
+
// The same hand-off the single-leaf acceptor uses: emitting the connection event runs the TLS server's own connection listener on a socket this process already owns (the redirect half of the connection) rather than one the server accepted itself.
|
|
3199
|
+
accept: (socket) => {
|
|
3200
|
+
server.emit("connection", socket);
|
|
3201
|
+
},
|
|
3202
|
+
close: () => {
|
|
3203
|
+
server.close();
|
|
3204
|
+
}
|
|
3205
|
+
};
|
|
3206
|
+
},
|
|
3167
3207
|
createHttpSession: (handler, onUpgrade) => {
|
|
3168
3208
|
const server = http.createServer(handler);
|
|
3169
3209
|
server.on("clientError", (_error, socket) => {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1509,6 +1509,13 @@ interface TlsAcceptor {
|
|
|
1509
1509
|
/** Drops every session this acceptor is terminating. */
|
|
1510
1510
|
readonly close: () => void;
|
|
1511
1511
|
}
|
|
1512
|
+
/** Presents every served host's leaf on one handshake, selected by the SNI name the client sent: the transparent surface's terminator, answering each redirected connection as the host it named. */
|
|
1513
|
+
interface SniTlsAcceptor {
|
|
1514
|
+
/** Starts the TLS handshake on a redirected socket; a handshake that completes for a served host hands its secure session to the acceptor's `onSecure` with that host's name. */
|
|
1515
|
+
readonly accept: (socket: net.Socket) => void;
|
|
1516
|
+
/** Drops every session this acceptor is terminating. */
|
|
1517
|
+
readonly close: () => void;
|
|
1518
|
+
}
|
|
1512
1519
|
/** Parses HTTP over terminated sockets and serves each request through the handler, keep-alive included. */
|
|
1513
1520
|
interface HttpParserSession {
|
|
1514
1521
|
readonly serve: (socket: net.Socket) => void;
|
|
@@ -1522,6 +1529,8 @@ interface ConnectEffects {
|
|
|
1522
1529
|
readonly listenLoopback: (preferredPort: number | undefined, onSocket: (socket: net.Socket) => void) => Promise<ConnectListenerHandle>;
|
|
1523
1530
|
/** Builds the TLS terminator for one leaf, handing each successfully handshaked session to `onSecure` together with the context its `accept` call carried. `alpnProtocols`, when given, is advertised during the handshake, which is how a tap host's session can offer HTTP/2 the way its real server does. */
|
|
1524
1531
|
readonly createTlsAcceptor: (leaf: LeafCert, onSecure: (secure: net.Socket, context: string) => void, alpnProtocols?: readonly string[]) => TlsAcceptor;
|
|
1532
|
+
/** Builds the transparent surface's TLS terminator: one handshake whose SNI name selects which served host's leaf answers it, so a connection redirected from any of the hosts sharing the redirected address is terminated as the host it named. A name the surface does not serve is answered with no certificate at all (a client that sends no SNI never reaches the selection and finds no default certificate either), because the only leaf that could answer such a name is another host's, which the client's own hostname check would reject anyway. No ALPN is offered: node's TLS server negotiates ALPN from the listener's own options and ignores protocols named on an SNI-selected secure context, and the API host's terminated session is parsed as HTTP/1.1, which a negotiated `h2` would strand. */
|
|
1533
|
+
readonly createSniTlsAcceptor: (hosts: readonly string[], leafFor: (host: string) => LeafCert, onSecure: (secure: net.Socket, host: string) => void) => SniTlsAcceptor;
|
|
1525
1534
|
/** Opens a TLS connection to a real host, presenting its name as SNI, for a tap session's upstream half. `clientAlpn`, when given, is the protocol the client negotiated with the surface and the only one offered upstream, so the tap never changes the channel's protocol. */
|
|
1526
1535
|
readonly connectTlsUpstream: (host: string, port: number, clientAlpn: string | undefined) => Promise<net.Socket>;
|
|
1527
1536
|
/** Builds the HTTP parser bound to one request handler. `onUpgrade`, when given, owns every HTTP upgrade request arriving on a terminated session, socket and already-read bytes included; a session without one lets Node destroy the upgrade, its own no-listener behaviour. */
|
|
@@ -1550,7 +1559,7 @@ interface ConnectServerConfig {
|
|
|
1550
1559
|
/** Whether a capability presented as a CONNECT request's proxy credential belongs to a live launch: the same constant-time check against the same registry the routed pipeline's admission makes, read fresh on every call because launches come and go. */
|
|
1551
1560
|
readonly isLiveCapability: (token: string) => boolean;
|
|
1552
1561
|
/**
|
|
1553
|
-
* Binds a second listener that
|
|
1562
|
+
* Binds a second listener that terminates redirected connections per host, with no CONNECT handshake to authenticate: what an operating-system redirect (a pf rule sending the real hosts' address to this port) delivers, pre-established. A redirect names addresses, and several real hosts share the API host's, so the client's TLS SNI name is what says which host arrived: each intercept host is served with its own leaf and its own session exactly as a CONNECT-tunnelled connection to that host is (the API host's `/v1/` rides the routed pipeline, a tap host's stream is pumped to its real host), and a name outside the intercept set, or a connection presenting none, is refused with no certificate at all, because the only leaf that could answer it is another host's. There is no capability to check on this surface: the connection carried no proxy credential, so every request rides the pipeline anonymously, admitted the way a tunnel's own header-less requests are (by nothing, which is exactly what they present), and the surface exists solely for clients that ignore proxies and would otherwise be invisible to the door entirely.
|
|
1554
1563
|
*/
|
|
1555
1564
|
readonly transparentPort?: number;
|
|
1556
1565
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-shim",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.2",
|
|
4
4
|
"description": "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Joseph Mearman <joseph@mearman.co.uk>",
|