agent-shim 7.3.0 → 7.4.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/dist/cli.cjs CHANGED
@@ -61051,7 +61051,7 @@ function resolveLaunchIdentity(paths, cwd) {
61051
61051
  // package.json
61052
61052
  var package_default = {
61053
61053
  name: "agent-shim",
61054
- version: "7.3.0",
61054
+ version: "7.4.0",
61055
61055
  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.",
61056
61056
  license: "MIT",
61057
61057
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -64859,6 +64859,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
64859
64859
 
64860
64860
  // src/frontdoor/connect.ts
64861
64861
  var CONNECT_INTERCEPT_HOST = "api.anthropic.com";
64862
+ var CONNECT_INTERCEPT_HOSTS = [CONNECT_INTERCEPT_HOST, "platform.claude.com"];
64862
64863
  var ROUTED_PATH_PREFIX = "/v1/";
64863
64864
  var HTTPS_PORT = 443;
64864
64865
  var MAX_PORT = 65535;
@@ -64898,9 +64899,6 @@ function parseConnectTarget(authority) {
64898
64899
  }
64899
64900
  return { host, port };
64900
64901
  }
64901
- function isInterceptedHost(host, interceptHost) {
64902
- return host === interceptHost;
64903
- }
64904
64902
  function servedByPipeline(path38) {
64905
64903
  return path38?.startsWith(ROUTED_PATH_PREFIX) === true;
64906
64904
  }
@@ -64970,28 +64968,34 @@ function caParses(ca) {
64970
64968
  }
64971
64969
  }
64972
64970
  async function startConnectServer(config2, effects, preferredPort) {
64973
- const handler = (request6, response) => {
64974
- if (servedByPipeline(request6.url)) {
64975
- config2.serveRouted(request6, response);
64976
- return;
64977
- }
64978
- effects.forwardHttp(config2.upstream, request6, response, config2.capture?.observePassthrough(request6));
64979
- };
64980
- const httpSession = effects.createHttpSession(handler, config2.capture === void 0 ? void 0 : (request6) => config2.capture?.upgrade(request6));
64981
- const tlsAcceptor = effects.createTlsAcceptor(config2.leafFor(config2.interceptHost), (secure) => {
64982
- httpSession.serve(secure);
64971
+ const onUpgrade = config2.capture === void 0 ? void 0 : (request6) => config2.capture?.upgrade(request6);
64972
+ const sessions = config2.interceptHosts.map((host) => {
64973
+ const handler = (request6, response) => {
64974
+ if (host === config2.routedHost && servedByPipeline(request6.url)) {
64975
+ config2.serveRouted(request6, response);
64976
+ return;
64977
+ }
64978
+ effects.forwardHttp(config2.upstreamFor(host), request6, response, config2.capture?.observePassthrough(request6));
64979
+ };
64980
+ const httpSession = effects.createHttpSession(handler, onUpgrade);
64981
+ const tlsAcceptor = effects.createTlsAcceptor(config2.leafFor(host), (secure) => {
64982
+ httpSession.serve(secure);
64983
+ });
64984
+ return { host, httpSession, tlsAcceptor };
64983
64985
  });
64984
64986
  const ledger = createConnectionLedger(config2.limits, config2.isLiveCapability);
64985
64987
  const listener = await effects.listenLoopback(preferredPort, (socket) => {
64986
- handleConnect(socket, { config: config2, effects, tlsAcceptor, ledger });
64988
+ handleConnect(socket, { config: config2, effects, sessions, ledger });
64987
64989
  });
64988
64990
  return {
64989
64991
  port: listener.port,
64990
64992
  close: async () => {
64991
64993
  ledger.close();
64992
64994
  await listener.close();
64993
- tlsAcceptor.close();
64994
- httpSession.close();
64995
+ for (const { httpSession, tlsAcceptor } of sessions) {
64996
+ tlsAcceptor.close();
64997
+ httpSession.close();
64998
+ }
64995
64999
  }
64996
65000
  };
64997
65001
  }
@@ -65111,7 +65115,7 @@ function proxyAuthorizationOf(head) {
65111
65115
  return values.length === 1 ? value : void 0;
65112
65116
  }
65113
65117
  function routeConnect(socket, head, context) {
65114
- const { config: config2, effects, tlsAcceptor, ledger } = context;
65118
+ const { config: config2, effects, sessions, ledger } = context;
65115
65119
  const credential = proxyAuthorizationOf(head);
65116
65120
  const capability = credential === void 0 ? void 0 : capabilityFromProxyAuthorization(credential);
65117
65121
  if (capability === void 0 || !config2.isLiveCapability(capability)) {
@@ -65130,10 +65134,11 @@ function routeConnect(socket, head, context) {
65130
65134
  refuse(socket, REFUSAL.serviceUnavailable);
65131
65135
  return;
65132
65136
  }
65133
- config2.capture?.connect(target, isInterceptedHost(target.host, config2.interceptHost));
65137
+ const session = sessions.find((entry) => entry.host === target.host);
65138
+ config2.capture?.connect(target, session !== void 0);
65134
65139
  socket.write(CONNECT_ESTABLISHED);
65135
- if (isInterceptedHost(target.host, config2.interceptHost)) {
65136
- tlsAcceptor.accept(socket);
65140
+ if (session !== void 0) {
65141
+ session.tlsAcceptor.accept(socket);
65137
65142
  return;
65138
65143
  }
65139
65144
  void blindTunnel(socket, target, effects);
@@ -66967,7 +66972,8 @@ function realFrontDoorSupervisorPorts(paths) {
66967
66972
  }
66968
66973
  const server = await startConnectServer(
66969
66974
  {
66970
- interceptHost: CONNECT_INTERCEPT_HOST,
66975
+ interceptHosts: CONNECT_INTERCEPT_HOSTS,
66976
+ routedHost: CONNECT_INTERCEPT_HOST,
66971
66977
  serveRouted: (request6, response) => {
66972
66978
  const abort = new AbortController();
66973
66979
  response.on("close", () => {
@@ -66988,7 +66994,7 @@ function realFrontDoorSupervisorPorts(paths) {
66988
66994
  );
66989
66995
  },
66990
66996
  leafFor,
66991
- upstream: { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT, tls: true },
66997
+ upstreamFor: (host) => ({ host, port: HTTPS_PORT, tls: true }),
66992
66998
  isLiveCapability: isLiveToken,
66993
66999
  limits: CONNECT_LIMITS,
66994
67000
  ...capture === void 0 ? {} : { capture }
package/dist/index.cjs CHANGED
@@ -32,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  AMBIENT_CREDENTIAL_VARS: () => AMBIENT_CREDENTIAL_VARS,
34
34
  CONNECT_INTERCEPT_HOST: () => CONNECT_INTERCEPT_HOST,
35
+ CONNECT_INTERCEPT_HOSTS: () => CONNECT_INTERCEPT_HOSTS,
35
36
  CONNECT_LIMITS: () => CONNECT_LIMITS,
36
37
  FARM_MANIFEST_FILENAME: () => FARM_MANIFEST_FILENAME,
37
38
  FrontDoorStartError: () => FrontDoorStartError,
@@ -2325,6 +2326,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2325
2326
 
2326
2327
  // src/frontdoor/connect.ts
2327
2328
  var CONNECT_INTERCEPT_HOST = "api.anthropic.com";
2329
+ var CONNECT_INTERCEPT_HOSTS = [CONNECT_INTERCEPT_HOST, "platform.claude.com"];
2328
2330
  var ROUTED_PATH_PREFIX = "/v1/";
2329
2331
  var HTTPS_PORT = 443;
2330
2332
  var MAX_PORT = 65535;
@@ -2364,8 +2366,8 @@ function parseConnectTarget(authority) {
2364
2366
  }
2365
2367
  return { host, port };
2366
2368
  }
2367
- function isInterceptedHost(host, interceptHost) {
2368
- return host === interceptHost;
2369
+ function isInterceptedHost(host, interceptHosts) {
2370
+ return interceptHosts.includes(host);
2369
2371
  }
2370
2372
  function servedByPipeline(path8) {
2371
2373
  return path8?.startsWith(ROUTED_PATH_PREFIX) === true;
@@ -2435,28 +2437,34 @@ function caParses(ca) {
2435
2437
  }
2436
2438
  }
2437
2439
  async function startConnectServer(config, effects, preferredPort) {
2438
- const handler = (request3, response) => {
2439
- if (servedByPipeline(request3.url)) {
2440
- config.serveRouted(request3, response);
2441
- return;
2442
- }
2443
- effects.forwardHttp(config.upstream, request3, response, config.capture?.observePassthrough(request3));
2444
- };
2445
- const httpSession = effects.createHttpSession(handler, config.capture === void 0 ? void 0 : (request3) => config.capture?.upgrade(request3));
2446
- const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(config.interceptHost), (secure) => {
2447
- httpSession.serve(secure);
2440
+ const onUpgrade = config.capture === void 0 ? void 0 : (request3) => config.capture?.upgrade(request3);
2441
+ const sessions = config.interceptHosts.map((host) => {
2442
+ const handler = (request3, response) => {
2443
+ if (host === config.routedHost && servedByPipeline(request3.url)) {
2444
+ config.serveRouted(request3, response);
2445
+ return;
2446
+ }
2447
+ effects.forwardHttp(config.upstreamFor(host), request3, response, config.capture?.observePassthrough(request3));
2448
+ };
2449
+ const httpSession = effects.createHttpSession(handler, onUpgrade);
2450
+ const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(host), (secure) => {
2451
+ httpSession.serve(secure);
2452
+ });
2453
+ return { host, httpSession, tlsAcceptor };
2448
2454
  });
2449
2455
  const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
2450
2456
  const listener = await effects.listenLoopback(preferredPort, (socket) => {
2451
- handleConnect(socket, { config, effects, tlsAcceptor, ledger });
2457
+ handleConnect(socket, { config, effects, sessions, ledger });
2452
2458
  });
2453
2459
  return {
2454
2460
  port: listener.port,
2455
2461
  close: async () => {
2456
2462
  ledger.close();
2457
2463
  await listener.close();
2458
- tlsAcceptor.close();
2459
- httpSession.close();
2464
+ for (const { httpSession, tlsAcceptor } of sessions) {
2465
+ tlsAcceptor.close();
2466
+ httpSession.close();
2467
+ }
2460
2468
  }
2461
2469
  };
2462
2470
  }
@@ -2576,7 +2584,7 @@ function proxyAuthorizationOf(head) {
2576
2584
  return values.length === 1 ? value : void 0;
2577
2585
  }
2578
2586
  function routeConnect(socket, head, context) {
2579
- const { config, effects, tlsAcceptor, ledger } = context;
2587
+ const { config, effects, sessions, ledger } = context;
2580
2588
  const credential = proxyAuthorizationOf(head);
2581
2589
  const capability = credential === void 0 ? void 0 : capabilityFromProxyAuthorization(credential);
2582
2590
  if (capability === void 0 || !config.isLiveCapability(capability)) {
@@ -2595,10 +2603,11 @@ function routeConnect(socket, head, context) {
2595
2603
  refuse(socket, REFUSAL.serviceUnavailable);
2596
2604
  return;
2597
2605
  }
2598
- config.capture?.connect(target, isInterceptedHost(target.host, config.interceptHost));
2606
+ const session = sessions.find((entry) => entry.host === target.host);
2607
+ config.capture?.connect(target, session !== void 0);
2599
2608
  socket.write(CONNECT_ESTABLISHED);
2600
- if (isInterceptedHost(target.host, config.interceptHost)) {
2601
- tlsAcceptor.accept(socket);
2609
+ if (session !== void 0) {
2610
+ session.tlsAcceptor.accept(socket);
2602
2611
  return;
2603
2612
  }
2604
2613
  void blindTunnel(socket, target, effects);
@@ -3601,6 +3610,7 @@ function evaluateAmbientCredentialGuard(params) {
3601
3610
  0 && (module.exports = {
3602
3611
  AMBIENT_CREDENTIAL_VARS,
3603
3612
  CONNECT_INTERCEPT_HOST,
3613
+ CONNECT_INTERCEPT_HOSTS,
3604
3614
  CONNECT_LIMITS,
3605
3615
  FARM_MANIFEST_FILENAME,
3606
3616
  FrontDoorStartError,
package/dist/index.mjs CHANGED
@@ -2251,6 +2251,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2251
2251
 
2252
2252
  // src/frontdoor/connect.ts
2253
2253
  var CONNECT_INTERCEPT_HOST = "api.anthropic.com";
2254
+ var CONNECT_INTERCEPT_HOSTS = [CONNECT_INTERCEPT_HOST, "platform.claude.com"];
2254
2255
  var ROUTED_PATH_PREFIX = "/v1/";
2255
2256
  var HTTPS_PORT = 443;
2256
2257
  var MAX_PORT = 65535;
@@ -2290,8 +2291,8 @@ function parseConnectTarget(authority) {
2290
2291
  }
2291
2292
  return { host, port };
2292
2293
  }
2293
- function isInterceptedHost(host, interceptHost) {
2294
- return host === interceptHost;
2294
+ function isInterceptedHost(host, interceptHosts) {
2295
+ return interceptHosts.includes(host);
2295
2296
  }
2296
2297
  function servedByPipeline(path8) {
2297
2298
  return path8?.startsWith(ROUTED_PATH_PREFIX) === true;
@@ -2361,28 +2362,34 @@ function caParses(ca) {
2361
2362
  }
2362
2363
  }
2363
2364
  async function startConnectServer(config, effects, preferredPort) {
2364
- const handler = (request3, response) => {
2365
- if (servedByPipeline(request3.url)) {
2366
- config.serveRouted(request3, response);
2367
- return;
2368
- }
2369
- effects.forwardHttp(config.upstream, request3, response, config.capture?.observePassthrough(request3));
2370
- };
2371
- const httpSession = effects.createHttpSession(handler, config.capture === void 0 ? void 0 : (request3) => config.capture?.upgrade(request3));
2372
- const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(config.interceptHost), (secure) => {
2373
- httpSession.serve(secure);
2365
+ const onUpgrade = config.capture === void 0 ? void 0 : (request3) => config.capture?.upgrade(request3);
2366
+ const sessions = config.interceptHosts.map((host) => {
2367
+ const handler = (request3, response) => {
2368
+ if (host === config.routedHost && servedByPipeline(request3.url)) {
2369
+ config.serveRouted(request3, response);
2370
+ return;
2371
+ }
2372
+ effects.forwardHttp(config.upstreamFor(host), request3, response, config.capture?.observePassthrough(request3));
2373
+ };
2374
+ const httpSession = effects.createHttpSession(handler, onUpgrade);
2375
+ const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(host), (secure) => {
2376
+ httpSession.serve(secure);
2377
+ });
2378
+ return { host, httpSession, tlsAcceptor };
2374
2379
  });
2375
2380
  const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
2376
2381
  const listener = await effects.listenLoopback(preferredPort, (socket) => {
2377
- handleConnect(socket, { config, effects, tlsAcceptor, ledger });
2382
+ handleConnect(socket, { config, effects, sessions, ledger });
2378
2383
  });
2379
2384
  return {
2380
2385
  port: listener.port,
2381
2386
  close: async () => {
2382
2387
  ledger.close();
2383
2388
  await listener.close();
2384
- tlsAcceptor.close();
2385
- httpSession.close();
2389
+ for (const { httpSession, tlsAcceptor } of sessions) {
2390
+ tlsAcceptor.close();
2391
+ httpSession.close();
2392
+ }
2386
2393
  }
2387
2394
  };
2388
2395
  }
@@ -2502,7 +2509,7 @@ function proxyAuthorizationOf(head) {
2502
2509
  return values.length === 1 ? value : void 0;
2503
2510
  }
2504
2511
  function routeConnect(socket, head, context) {
2505
- const { config, effects, tlsAcceptor, ledger } = context;
2512
+ const { config, effects, sessions, ledger } = context;
2506
2513
  const credential = proxyAuthorizationOf(head);
2507
2514
  const capability = credential === void 0 ? void 0 : capabilityFromProxyAuthorization(credential);
2508
2515
  if (capability === void 0 || !config.isLiveCapability(capability)) {
@@ -2521,10 +2528,11 @@ function routeConnect(socket, head, context) {
2521
2528
  refuse(socket, REFUSAL.serviceUnavailable);
2522
2529
  return;
2523
2530
  }
2524
- config.capture?.connect(target, isInterceptedHost(target.host, config.interceptHost));
2531
+ const session = sessions.find((entry) => entry.host === target.host);
2532
+ config.capture?.connect(target, session !== void 0);
2525
2533
  socket.write(CONNECT_ESTABLISHED);
2526
- if (isInterceptedHost(target.host, config.interceptHost)) {
2527
- tlsAcceptor.accept(socket);
2534
+ if (session !== void 0) {
2535
+ session.tlsAcceptor.accept(socket);
2528
2536
  return;
2529
2537
  }
2530
2538
  void blindTunnel(socket, target, effects);
@@ -3526,6 +3534,7 @@ function evaluateAmbientCredentialGuard(params) {
3526
3534
  export {
3527
3535
  AMBIENT_CREDENTIAL_VARS,
3528
3536
  CONNECT_INTERCEPT_HOST,
3537
+ CONNECT_INTERCEPT_HOSTS,
3529
3538
  CONNECT_LIMITS,
3530
3539
  FARM_MANIFEST_FILENAME,
3531
3540
  FrontDoorStartError,
@@ -6,10 +6,14 @@ import type { ConnectCapture, PassthroughObserver } from "./capture";
6
6
  *
7
7
  * Nothing is tunnelled or intercepted for a client that has not authenticated: every CONNECT request must present a live launch's capability as its proxy credential (`Proxy-Authorization: Basic`, which clients derive from the credential in the `HTTPS_PROXY` URL the launcher sets), or it is answered 407 before any target is dialled, so the port is no open proxy for other local processes. Pending and authenticated connections are bounded by `ConnectLimits`.
8
8
  *
9
- * Every authenticated CONNECT target is blind-tunnelled byte for byte EXCEPT the intercept host (Claude Code's own API), whose TLS this surface terminates with a leaf certificate signed by a locally generated CA. On the terminated session, the paths the front door routes (`/v1/`) are handed to the same ordered pipeline the provider listener serves (the client's Authorization header passes through untouched), and every other path is piped by this surface to the real upstream over TLS, so Remote Control's streaming, OAuth refreshes, and unknown endpoints bypass the pipeline entirely. When a `capture` is configured, those piped exchanges and every CONNECT target are recorded through it (see `./capture.ts`); the forwarding itself is identical either way.
9
+ * Every authenticated CONNECT target is blind-tunnelled byte for byte EXCEPT the intercept hosts (Claude Code's own API and the claude.ai control plane), whose TLS this surface terminates with leaf certificates signed by a locally generated CA. On the API host's terminated session, the paths the front door routes (`/v1/`) are handed to the same ordered pipeline the provider listener serves (the client's Authorization header passes through untouched), and every other path there, and every path on the control plane's session, is piped by this surface to that session's own real upstream over TLS, so Remote Control's streaming, OAuth refreshes, and unknown endpoints bypass the pipeline entirely. When a `capture` is configured, those piped exchanges and every CONNECT target are recorded through it (see `./capture.ts`); the forwarding itself is identical either way.
10
10
  */
11
- /** The one CONNECT host whose TLS gets terminated: Claude Code's own API, the upstream every OAuth session is really talking to. */
11
+ /** The API host: Claude Code's own upstream, the one host whose `/v1/` paths the routed pipeline serves. */
12
12
  export declare const CONNECT_INTERCEPT_HOST = "api.anthropic.com";
13
+ /**
14
+ * Every CONNECT host whose TLS this surface terminates, each with its own leaf and its own HTTP parser: the API host above, and `platform.claude.com`, the claude.ai control plane where Remote Control's long-lived channel and its handshake live. Terminating the second one is what makes a Remote Control login rejection observable at all: its bytes cross this surface either way, and blind-tunnelling them hides exactly the exchange that failed. Only the API host's `/v1/` paths ever reach the routed pipeline; everything else on either session is piped to that session's own real upstream, so the pipeline's identification and authorisation are never asked to serve another host's traffic.
15
+ */
16
+ export declare const CONNECT_INTERCEPT_HOSTS: readonly string[];
13
17
  /** Paths under this prefix are what the routed pipeline serves; everything else on the terminated session goes to the real upstream. */
14
18
  export declare const ROUTED_PATH_PREFIX = "/v1/";
15
19
  /** The port HTTPS is served on, both the default when a CONNECT authority names none and the port non-headroom paths are piped to on the real upstream. */
@@ -52,8 +56,8 @@ export interface ConnectTarget {
52
56
  }
53
57
  /** Parses a CONNECT authority (`host:port`, or a bare `host` meaning 443), or undefined when it names no host or a non-numeric port. */
54
58
  export declare function parseConnectTarget(authority: string): ConnectTarget | undefined;
55
- /** Whether a CONNECT target's host (port already stripped) is the one whose TLS this proxy terminates. */
56
- export declare function isInterceptedHost(host: string, interceptHost: string): boolean;
59
+ /** Whether a CONNECT target's host (port already stripped) is one whose TLS this proxy terminates. */
60
+ export declare function isInterceptedHost(host: string, interceptHosts: readonly string[]): boolean;
57
61
  /** Whether a request path on the terminated session is one the routed pipeline serves. The query string stays part of the path: `/v1/messages?beta=true` is still the pipeline's. */
58
62
  export declare function servedByPipeline(path: string | undefined): boolean;
59
63
  /**
@@ -142,16 +146,20 @@ export interface ConnectEffects {
142
146
  }
143
147
  /** Everything the connect surface needs to route, resolved before it starts. */
144
148
  export interface ConnectServerConfig {
145
- /** The CONNECT host whose TLS gets terminated. */
146
- readonly interceptHost: string;
149
+ /** The CONNECT hosts whose TLS get terminated, each with its own leaf, its own HTTP parser and its own upstream. */
150
+ readonly interceptHosts: readonly string[];
151
+ /**
152
+ * The one intercept host whose `/v1/` paths `serveRouted` handles: the API host, whose pipeline identification, authorisation and headroom hop are about Anthropic sessions and no other host's traffic.
153
+ */
154
+ readonly routedHost: string;
147
155
  /**
148
156
  * Serves one routed path (`/v1/...`) from the terminated session: the same ordered pipeline the provider listener hands requests to, so an OAuth session and a provider session run identical identification, middleware and routing.
149
157
  */
150
158
  readonly serveRouted: ConnectRequestHandler;
151
- /** The leaf to terminate `interceptHost` with, minted and cached per host. */
159
+ /** The leaf to terminate each intercept host with, minted and cached per host. */
152
160
  readonly leafFor: (host: string) => LeafCert;
153
- /** Where non-routed paths on the terminated session are piped: the real upstream over TLS. */
154
- readonly upstream: ConnectForwardTarget;
161
+ /** Where non-routed paths on one host's terminated session are piped: that host's own real upstream over TLS. */
162
+ readonly upstreamFor: (host: string) => ConnectForwardTarget;
155
163
  /** 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. */
156
164
  readonly isLiveCapability: (token: string) => boolean;
157
165
  /** The connection deadlines and caps; production passes `CONNECT_LIMITS`. */
@@ -11,7 +11,7 @@
11
11
  export { resolveDecisions, topLevelNames, type ResolveDecisionsInput, type ResolvedState } from "./resolve/pipeline";
12
12
  export type { CompiledRule, Decision, Diagnostic, EliminatedRule, EntryFact, EntryFacts, FlattenedCascade, Layer, LayerId } from "./resolve/types";
13
13
  export { buildEntryFacts, carryOver, FARM_MANIFEST_FILENAME, readFarmManifest, recoverFarm, recoveryDiagnostics, resyncFarm, type BuildEntryFactsParams, type CarryOverParams, type CarryOverResult, type RecoverFarmParams, type RecoveryResult, type ResyncFarmParams, type ResyncFarmResult, } from "./launcher/farm";
14
- export { CONNECT_INTERCEPT_HOST, CONNECT_LIMITS, createLeafCache, ensureCa, forwardableHeaders, generateCa, isInterceptedHost, mintLeaf, parseConnectTarget, realConnectCertStore, realConnectEffects, ROUTED_PATH_PREFIX, servedByPipeline, startConnectServer, type CaMaterial, type ConnectCertStore, type ConnectEffects, type ConnectLimits, type ConnectServerConfig, type ConnectServerHandle, type ConnectTarget, type LeafCert, } from "./frontdoor/connect";
14
+ export { CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, createLeafCache, ensureCa, forwardableHeaders, generateCa, isInterceptedHost, mintLeaf, parseConnectTarget, realConnectCertStore, realConnectEffects, ROUTED_PATH_PREFIX, servedByPipeline, startConnectServer, type CaMaterial, type ConnectCertStore, type ConnectEffects, type ConnectLimits, type ConnectServerConfig, type ConnectServerHandle, type ConnectTarget, type LeafCert, } from "./frontdoor/connect";
15
15
  export { ensureFrontDoor, FrontDoorStartError, type EnsureFrontDoorPorts } from "./frontdoor/ensure";
16
16
  export { runFrontDoorSupervisor, type FrontDoorSupervisorPorts, type RunFrontDoorSupervisorOptions } from "./frontdoor/supervisor";
17
17
  export { listUsageSnapshots, readUsageSnapshot, snapshotPath, UsageSnapshotError, type UsageReadFs } from "./usage/read";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-shim",
3
- "version": "7.3.0",
3
+ "version": "7.4.0",
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>",