agent-shim 8.34.0 → 8.35.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
@@ -18047,7 +18047,7 @@ var require_api_pipeline = __commonJS({
18047
18047
  var {
18048
18048
  Readable: Readable2,
18049
18049
  Duplex,
18050
- PassThrough
18050
+ PassThrough: PassThrough2
18051
18051
  } = require("node:stream");
18052
18052
  var assert2 = require("node:assert");
18053
18053
  var { AsyncResource } = require("node:async_hooks");
@@ -18234,7 +18234,7 @@ var require_api_pipeline = __commonJS({
18234
18234
  this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler);
18235
18235
  return pipelineHandler.ret;
18236
18236
  } catch (err) {
18237
- return new PassThrough().destroy(err);
18237
+ return new PassThrough2().destroy(err);
18238
18238
  }
18239
18239
  }
18240
18240
  module2.exports = pipeline;
@@ -57101,13 +57101,21 @@ var CodexProviderConfigSchema = external_exports.strictObject({
57101
57101
  /** Which login the upstream call is made with; see `CODEX_LOGINS`. */
57102
57102
  login: external_exports.enum(CODEX_LOGINS).optional()
57103
57103
  });
57104
+ var ProviderRouteSchema = external_exports.strictObject({
57105
+ /** The condition, the same `when` union a configuration cascade entry takes: the object form or a trilean predicate tree over the request facts the door resolves (`request.model` and kin). */
57106
+ when: WhenSchema,
57107
+ /** The provider a matching request is sent to, by the name a provider file carries. */
57108
+ provider: external_exports.string().min(1)
57109
+ });
57104
57110
  var HttpProviderSchema = external_exports.strictObject({
57105
57111
  $schema: external_exports.string().optional(),
57106
57112
  kind: external_exports.literal("http").optional(),
57107
57113
  displayName: external_exports.string().min(1),
57108
57114
  baseUrl: external_exports.url(),
57109
57115
  credential: ProviderCredentialSchema,
57110
- env: ProviderEnvSchema.optional()
57116
+ env: ProviderEnvSchema.optional(),
57117
+ /** Per-request routing: when present, each request this provider would serve is matched against the list in order, and the first definite match is sent to that entry's provider instead (itself resolved exactly as a directly dialled request would be). Unmatched requests stay on this provider. */
57118
+ routes: external_exports.array(ProviderRouteSchema).optional()
57111
57119
  });
57112
57120
  var CodexProviderSchema = external_exports.strictObject({
57113
57121
  $schema: external_exports.string().optional(),
@@ -60930,7 +60938,9 @@ function resolversOf(context) {
60930
60938
  ...pool?.sevenDay === void 0 ? {} : { "quota.sevenDay.remaining": pool.sevenDay.remaining, "quota.sevenDay.utilization": pool.sevenDay.utilization, "quota.sevenDay.hoursUntilReset": pool.sevenDay.hoursUntilReset },
60931
60939
  ...pool?.burnPerHour === void 0 ? {} : { "quota.burnPerHour": pool.burnPerHour },
60932
60940
  ...pool?.resuming === void 0 ? {} : { "session.resuming": pool.resuming },
60933
- ...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo }
60941
+ ...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo },
60942
+ ...context.request?.model === void 0 ? {} : { "request.model": context.request.model },
60943
+ ...context.request?.hasImage === void 0 ? {} : { "request.hasImage": context.request.hasImage }
60934
60944
  };
60935
60945
  return {
60936
60946
  resolveValue: (key) => {
@@ -63665,7 +63675,7 @@ function registerIdentityCommand(program2, deps) {
63665
63675
  // package.json
63666
63676
  var package_default = {
63667
63677
  name: "agent-shim",
63668
- version: "8.34.0",
63678
+ version: "8.35.0",
63669
63679
  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.",
63670
63680
  license: "MIT",
63671
63681
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -77382,6 +77392,74 @@ function createPassthroughRoute(name, target) {
77382
77392
  };
77383
77393
  }
77384
77394
 
77395
+ // src/frontdoor/requestScan.ts
77396
+ var import_node_stream2 = require("node:stream");
77397
+ var BYTES_PER_KIB = 1024;
77398
+ var SCAN_KIB = 64;
77399
+ var REQUEST_SCAN_CAP_BYTES = SCAN_KIB * BYTES_PER_KIB;
77400
+ async function scanRequestHead(request7) {
77401
+ const body = request7.body;
77402
+ const head = [];
77403
+ let seen = 0;
77404
+ let text2 = "";
77405
+ let decided = false;
77406
+ let ended = false;
77407
+ let error62;
77408
+ const replay = new import_node_stream2.PassThrough();
77409
+ const modelIn = () => /"model"\s*:\s*"([^"]+)"/.exec(text2)?.[1];
77410
+ const settled = new Promise((resolve) => {
77411
+ const settle2 = () => {
77412
+ const model = modelIn();
77413
+ const hasImage = /"type"\s*:\s*"image"/.test(text2);
77414
+ for (const chunk of head) {
77415
+ replay.write(chunk);
77416
+ }
77417
+ resolve({ ...model === void 0 ? {} : { model }, hasImage, replayed: { ...request7, body: replay } });
77418
+ };
77419
+ body.on("data", (chunk) => {
77420
+ if (decided) {
77421
+ if (!replay.write(chunk)) {
77422
+ body.pause();
77423
+ replay.once("drain", () => {
77424
+ body.resume();
77425
+ });
77426
+ }
77427
+ return;
77428
+ }
77429
+ head.push(chunk);
77430
+ seen += chunk.length;
77431
+ text2 += chunk.toString("utf8");
77432
+ if (modelIn() !== void 0 || seen >= REQUEST_SCAN_CAP_BYTES) {
77433
+ decided = true;
77434
+ body.pause();
77435
+ replay.once("resume", () => {
77436
+ body.resume();
77437
+ });
77438
+ settle2();
77439
+ }
77440
+ });
77441
+ body.on("end", () => {
77442
+ ended = true;
77443
+ if (!decided) {
77444
+ decided = true;
77445
+ settle2();
77446
+ }
77447
+ replay.end();
77448
+ });
77449
+ body.on("error", (cause) => {
77450
+ error62 = cause;
77451
+ replay.destroy(cause);
77452
+ });
77453
+ body.on("close", () => {
77454
+ if (!decided && !ended && error62 === void 0) {
77455
+ decided = true;
77456
+ settle2();
77457
+ }
77458
+ });
77459
+ });
77460
+ return await settled;
77461
+ }
77462
+
77385
77463
  // src/frontdoor/providerRoute.ts
77386
77464
  function createProviderRouteResolver(deps) {
77387
77465
  const isRcSelfHostPath = (path46) => path46 === "/v1/code/sessions" || path46.startsWith("/v1/code/sessions/") || path46 === "/v1/sessions" || path46.startsWith("/v1/sessions/");
@@ -77446,7 +77524,64 @@ function createProviderRouteResolver(deps) {
77446
77524
  )
77447
77525
  };
77448
77526
  };
77449
- return async (request7) => await Promise.resolve(resolve(request7));
77527
+ const servingRewritten = (route, url2, body) => ({
77528
+ name: route.name,
77529
+ headroomEligible: route.headroomEligible,
77530
+ headroomUpstream: route.headroomUpstream,
77531
+ // The pipeline serves the route with the request it received; the routing layer's decisions (the rewritten target path, the replayed body) are substituted here, so the route sees exactly the request the resolution acted on.
77532
+ serve: async (request7, response) => {
77533
+ await route.serve({ ...request7, url: url2, body }, response);
77534
+ }
77535
+ });
77536
+ return async (request7) => {
77537
+ let current = request7;
77538
+ let replay;
77539
+ const visited = /* @__PURE__ */ new Set();
77540
+ for (; ; ) {
77541
+ const path46 = new URL(current.url, "http://127.0.0.1").pathname;
77542
+ const scoped = parseProviderPath(path46);
77543
+ const providerName = scoped?.provider ?? current.session.provider;
77544
+ if (providerName !== void 0 && visited.has(providerName)) {
77545
+ return { ok: false, status: HTTP_STATUS.internalServerError, message: `provider routing cycle: ${[...visited, providerName].join(" -> ")}` };
77546
+ }
77547
+ if (providerName !== void 0) {
77548
+ visited.add(providerName);
77549
+ }
77550
+ let routes;
77551
+ try {
77552
+ const definition = providerName === void 0 ? void 0 : loadProvider(deps.providersDir, providerName, deps.fs);
77553
+ routes = definition === void 0 || isCodexProvider(definition) ? void 0 : definition.routes;
77554
+ } catch {
77555
+ routes = void 0;
77556
+ }
77557
+ if (routes === void 0 || routes.length === 0) {
77558
+ const resolution = resolve(current);
77559
+ return resolution.ok && replay !== void 0 ? { ok: true, route: servingRewritten(resolution.route, current.url, replay.body) } : resolution;
77560
+ }
77561
+ const scan = await scanRequestHead(current);
77562
+ if (scan.replayed === void 0) {
77563
+ const resolution = resolve(current);
77564
+ return resolution.ok && replay !== void 0 ? { ok: true, route: servingRewritten(resolution.route, current.url, replay.body) } : resolution;
77565
+ }
77566
+ replay = scan.replayed;
77567
+ const context = { nowMs: Date.now(), env: deps.env, ...scan.model === void 0 && scan.hasImage === void 0 ? {} : { request: { ...scan.model === void 0 ? {} : { model: scan.model }, hasImage: scan.hasImage } } };
77568
+ let matched;
77569
+ for (const entry of routes) {
77570
+ const verdict = evaluateWhen(entry.when, context);
77571
+ if (verdict.status === "definite" && verdict.passed) {
77572
+ matched = entry.provider;
77573
+ break;
77574
+ }
77575
+ }
77576
+ if (matched === void 0) {
77577
+ const resolution = resolve(current);
77578
+ return resolution.ok ? { ok: true, route: servingRewritten(resolution.route, current.url, replay.body) } : resolution;
77579
+ }
77580
+ const rest = scoped === void 0 ? path46 : path46.slice(`${PROVIDER_PATH_PREFIX}${encodeURIComponent(scoped.provider)}`.length);
77581
+ const query = current.url.includes("?") ? current.url.slice(current.url.indexOf("?")) : "";
77582
+ current = { ...current, url: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(matched)}${rest}${query}`, body: replay.body };
77583
+ }
77584
+ };
77450
77585
  }
77451
77586
  function providerCredentialHeaders(credential) {
77452
77587
  return credential.target === "apiKey" ? { "x-api-key": credential.token } : { authorization: `Bearer ${credential.token}` };
package/dist/index.cjs CHANGED
@@ -589,13 +589,21 @@ var CodexProviderConfigSchema = import_zod.z.strictObject({
589
589
  /** Which login the upstream call is made with; see `CODEX_LOGINS`. */
590
590
  login: import_zod.z.enum(CODEX_LOGINS).optional()
591
591
  });
592
+ var ProviderRouteSchema = import_zod.z.strictObject({
593
+ /** The condition, the same `when` union a configuration cascade entry takes: the object form or a trilean predicate tree over the request facts the door resolves (`request.model` and kin). */
594
+ when: WhenSchema,
595
+ /** The provider a matching request is sent to, by the name a provider file carries. */
596
+ provider: import_zod.z.string().min(1)
597
+ });
592
598
  var HttpProviderSchema = import_zod.z.strictObject({
593
599
  $schema: import_zod.z.string().optional(),
594
600
  kind: import_zod.z.literal("http").optional(),
595
601
  displayName: import_zod.z.string().min(1),
596
602
  baseUrl: import_zod.z.url(),
597
603
  credential: ProviderCredentialSchema,
598
- env: ProviderEnvSchema.optional()
604
+ env: ProviderEnvSchema.optional(),
605
+ /** Per-request routing: when present, each request this provider would serve is matched against the list in order, and the first definite match is sent to that entry's provider instead (itself resolved exactly as a directly dialled request would be). Unmatched requests stay on this provider. */
606
+ routes: import_zod.z.array(ProviderRouteSchema).optional()
599
607
  });
600
608
  var CodexProviderSchema = import_zod.z.strictObject({
601
609
  $schema: import_zod.z.string().optional(),
@@ -1018,7 +1026,9 @@ function resolversOf(context) {
1018
1026
  ...pool?.sevenDay === void 0 ? {} : { "quota.sevenDay.remaining": pool.sevenDay.remaining, "quota.sevenDay.utilization": pool.sevenDay.utilization, "quota.sevenDay.hoursUntilReset": pool.sevenDay.hoursUntilReset },
1019
1027
  ...pool?.burnPerHour === void 0 ? {} : { "quota.burnPerHour": pool.burnPerHour },
1020
1028
  ...pool?.resuming === void 0 ? {} : { "session.resuming": pool.resuming },
1021
- ...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo }
1029
+ ...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo },
1030
+ ...context.request?.model === void 0 ? {} : { "request.model": context.request.model },
1031
+ ...context.request?.hasImage === void 0 ? {} : { "request.hasImage": context.request.hasImage }
1022
1032
  };
1023
1033
  return {
1024
1034
  resolveValue: (key) => {
@@ -5399,7 +5409,7 @@ var import_undici = require("undici");
5399
5409
  // package.json
5400
5410
  var package_default = {
5401
5411
  name: "agent-shim",
5402
- version: "8.34.0",
5412
+ version: "8.35.0",
5403
5413
  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.",
5404
5414
  license: "MIT",
5405
5415
  author: "Joseph Mearman <joseph@mearman.co.uk>",
package/dist/index.mjs CHANGED
@@ -277,13 +277,21 @@ var CodexProviderConfigSchema = z.strictObject({
277
277
  /** Which login the upstream call is made with; see `CODEX_LOGINS`. */
278
278
  login: z.enum(CODEX_LOGINS).optional()
279
279
  });
280
+ var ProviderRouteSchema = z.strictObject({
281
+ /** The condition, the same `when` union a configuration cascade entry takes: the object form or a trilean predicate tree over the request facts the door resolves (`request.model` and kin). */
282
+ when: WhenSchema,
283
+ /** The provider a matching request is sent to, by the name a provider file carries. */
284
+ provider: z.string().min(1)
285
+ });
280
286
  var HttpProviderSchema = z.strictObject({
281
287
  $schema: z.string().optional(),
282
288
  kind: z.literal("http").optional(),
283
289
  displayName: z.string().min(1),
284
290
  baseUrl: z.url(),
285
291
  credential: ProviderCredentialSchema,
286
- env: ProviderEnvSchema.optional()
292
+ env: ProviderEnvSchema.optional(),
293
+ /** Per-request routing: when present, each request this provider would serve is matched against the list in order, and the first definite match is sent to that entry's provider instead (itself resolved exactly as a directly dialled request would be). Unmatched requests stay on this provider. */
294
+ routes: z.array(ProviderRouteSchema).optional()
287
295
  });
288
296
  var CodexProviderSchema = z.strictObject({
289
297
  $schema: z.string().optional(),
@@ -706,7 +714,9 @@ function resolversOf(context) {
706
714
  ...pool?.sevenDay === void 0 ? {} : { "quota.sevenDay.remaining": pool.sevenDay.remaining, "quota.sevenDay.utilization": pool.sevenDay.utilization, "quota.sevenDay.hoursUntilReset": pool.sevenDay.hoursUntilReset },
707
715
  ...pool?.burnPerHour === void 0 ? {} : { "quota.burnPerHour": pool.burnPerHour },
708
716
  ...pool?.resuming === void 0 ? {} : { "session.resuming": pool.resuming },
709
- ...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo }
717
+ ...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo },
718
+ ...context.request?.model === void 0 ? {} : { "request.model": context.request.model },
719
+ ...context.request?.hasImage === void 0 ? {} : { "request.hasImage": context.request.hasImage }
710
720
  };
711
721
  return {
712
722
  resolveValue: (key) => {
@@ -5087,7 +5097,7 @@ import { Agent as Agent3, fetch as undiciFetch } from "undici";
5087
5097
  // package.json
5088
5098
  var package_default = {
5089
5099
  name: "agent-shim",
5090
- version: "8.34.0",
5100
+ version: "8.35.0",
5091
5101
  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.",
5092
5102
  license: "MIT",
5093
5103
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4,7 +4,7 @@ import * as zod from 'zod';
4
4
  import { z } from 'zod';
5
5
  import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'node:http';
6
6
  import * as net from 'node:net';
7
- import { Duplex } from 'node:stream';
7
+ import { Duplex, Readable } from 'node:stream';
8
8
  import * as _orpc_client from '@orpc/client';
9
9
  import * as zod_v4_core from 'zod/v4/core';
10
10
  import * as _orpc_server from '@orpc/server';
@@ -446,6 +446,81 @@ declare const ProviderSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
446
446
  }>>;
447
447
  }, z.core.$strict>;
448
448
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
449
+ routes: z.ZodOptional<z.ZodArray<z.ZodObject<{
450
+ when: z.ZodUnion<readonly [z.ZodObject<{
451
+ newerThan: z.ZodOptional<z.ZodString>;
452
+ olderThan: z.ZodOptional<z.ZodString>;
453
+ maxSizeBytes: z.ZodOptional<z.ZodInt>;
454
+ branch: z.ZodOptional<z.ZodString>;
455
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
456
+ }, z.core.$strict>, z.ZodDiscriminatedUnion<[z.ZodObject<{
457
+ kind: z.ZodLiteral<"not">;
458
+ operand: typeof PredicateNodeSchema;
459
+ }, z.core.$strip>, z.ZodObject<{
460
+ kind: z.ZodLiteral<"and">;
461
+ left: typeof PredicateNodeSchema;
462
+ right: typeof PredicateNodeSchema;
463
+ }, z.core.$strip>, z.ZodObject<{
464
+ kind: z.ZodLiteral<"or">;
465
+ left: typeof PredicateNodeSchema;
466
+ right: typeof PredicateNodeSchema;
467
+ }, z.core.$strip>, z.ZodObject<{
468
+ kind: z.ZodLiteral<"allOf">;
469
+ operands: z.ZodArray<typeof PredicateNodeSchema>;
470
+ }, z.core.$strip>, z.ZodObject<{
471
+ kind: z.ZodLiteral<"anyOf">;
472
+ operands: z.ZodArray<typeof PredicateNodeSchema>;
473
+ }, z.core.$strip>, z.ZodObject<{
474
+ kind: z.ZodLiteral<"compare">;
475
+ op: z.ZodEnum<{
476
+ gt: "gt";
477
+ gte: "gte";
478
+ lt: "lt";
479
+ lte: "lte";
480
+ eq: "eq";
481
+ neq: "neq";
482
+ }>;
483
+ left: typeof trilean.ExpressionNodeSchema;
484
+ right: typeof trilean.ExpressionNodeSchema;
485
+ }, z.core.$strip>, z.ZodObject<{
486
+ kind: z.ZodLiteral<"textCompare">;
487
+ op: z.ZodEnum<{
488
+ equals: "equals";
489
+ notEquals: "notEquals";
490
+ matches: "matches";
491
+ notMatches: "notMatches";
492
+ portableMatches: "portableMatches";
493
+ portableNotMatches: "portableNotMatches";
494
+ }>;
495
+ left: typeof trilean.ExpressionNodeSchema;
496
+ right: typeof trilean.ExpressionNodeSchema;
497
+ }, z.core.$strip>, z.ZodObject<{
498
+ kind: z.ZodLiteral<"memberOf">;
499
+ op: z.ZodEnum<{
500
+ in: "in";
501
+ notIn: "notIn";
502
+ }>;
503
+ operand: typeof trilean.ExpressionNodeSchema;
504
+ candidates: z.ZodArray<typeof trilean.ExpressionNodeSchema>;
505
+ }, z.core.$strip>, z.ZodObject<{
506
+ kind: z.ZodLiteral<"exists">;
507
+ operand: typeof trilean.ExpressionNodeSchema;
508
+ }, z.core.$strip>, z.ZodObject<{
509
+ kind: z.ZodLiteral<"some">;
510
+ collection: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
511
+ item: typeof PredicateNodeSchema;
512
+ filter: z.ZodOptional<typeof PredicateNodeSchema>;
513
+ }, z.core.$strip>, z.ZodObject<{
514
+ kind: z.ZodLiteral<"every">;
515
+ collection: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
516
+ item: typeof PredicateNodeSchema;
517
+ filter: z.ZodOptional<typeof PredicateNodeSchema>;
518
+ }, z.core.$strip>, z.ZodObject<{
519
+ kind: z.ZodLiteral<"treeReference">;
520
+ key: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
521
+ }, z.core.$strip>], "kind">]>;
522
+ provider: z.ZodString;
523
+ }, z.core.$strict>>>;
449
524
  }, z.core.$strict>, z.ZodObject<{
450
525
  $schema: z.ZodOptional<z.ZodString>;
451
526
  kind: z.ZodLiteral<"codex">;
@@ -2665,8 +2740,8 @@ interface RoutedRequest {
2665
2740
  readonly url: string;
2666
2741
  /** The request's headers with every internal header already stripped: exactly what a route may forward onwards. */
2667
2742
  readonly headers: IncomingHttpHeaders;
2668
- /** The request's body stream: a route either pipes it onward untouched or reads it whole, never both. */
2669
- readonly body: IncomingMessage;
2743
+ /** The request's body stream: a route either pipes it onward untouched or reads it whole, never both. A readable, not the socket-bound type the pipeline received it as, because the routing layer's scan hands routes a replayed body (the scanned head re-emitted in front of the unread remainder) that is a plain stream. */
2744
+ readonly body: Readable;
2670
2745
  /** Aborted the moment the client goes away; a route aborts its own upstream work with it. */
2671
2746
  readonly signal: AbortSignal;
2672
2747
  readonly session: SessionIdentity;
@@ -5378,12 +5453,12 @@ declare function createControlApiRouter(deps: ControlApiDeps): {
5378
5453
  identity: "identity";
5379
5454
  provider: "provider";
5380
5455
  pool: "pool";
5456
+ keychain: "keychain";
5381
5457
  "ambient-credential": "ambient-credential";
5382
5458
  "binary-discovery": "binary-discovery";
5383
5459
  "claude-shim": "claude-shim";
5384
5460
  "path-resolution": "path-resolution";
5385
5461
  "legacy-name": "legacy-name";
5386
- keychain: "keychain";
5387
5462
  "directory-rules": "directory-rules";
5388
5463
  "categories-local": "categories-local";
5389
5464
  "active-identity": "active-identity";
@@ -5959,12 +6034,12 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
5959
6034
  identity: "identity";
5960
6035
  provider: "provider";
5961
6036
  pool: "pool";
6037
+ keychain: "keychain";
5962
6038
  "ambient-credential": "ambient-credential";
5963
6039
  "binary-discovery": "binary-discovery";
5964
6040
  "claude-shim": "claude-shim";
5965
6041
  "path-resolution": "path-resolution";
5966
6042
  "legacy-name": "legacy-name";
5967
- keychain: "keychain";
5968
6043
  "directory-rules": "directory-rules";
5969
6044
  "categories-local": "categories-local";
5970
6045
  "active-identity": "active-identity";
@@ -6449,12 +6524,12 @@ declare const DoctorFindingSchema: z.ZodObject<{
6449
6524
  identity: "identity";
6450
6525
  provider: "provider";
6451
6526
  pool: "pool";
6527
+ keychain: "keychain";
6452
6528
  "ambient-credential": "ambient-credential";
6453
6529
  "binary-discovery": "binary-discovery";
6454
6530
  "claude-shim": "claude-shim";
6455
6531
  "path-resolution": "path-resolution";
6456
6532
  "legacy-name": "legacy-name";
6457
- keychain: "keychain";
6458
6533
  "directory-rules": "directory-rules";
6459
6534
  "categories-local": "categories-local";
6460
6535
  "active-identity": "active-identity";
@@ -6478,12 +6553,12 @@ declare const DoctorRunOutputSchema: z.ZodObject<{
6478
6553
  identity: "identity";
6479
6554
  provider: "provider";
6480
6555
  pool: "pool";
6556
+ keychain: "keychain";
6481
6557
  "ambient-credential": "ambient-credential";
6482
6558
  "binary-discovery": "binary-discovery";
6483
6559
  "claude-shim": "claude-shim";
6484
6560
  "path-resolution": "path-resolution";
6485
6561
  "legacy-name": "legacy-name";
6486
- keychain: "keychain";
6487
6562
  "directory-rules": "directory-rules";
6488
6563
  "categories-local": "categories-local";
6489
6564
  "active-identity": "active-identity";
@@ -7033,6 +7108,13 @@ interface ConditionContext {
7033
7108
  readonly resuming?: boolean;
7034
7109
  readonly lastPickHoursAgo?: number;
7035
7110
  };
7111
+ /**
7112
+ * The request facts a provider's route condition reads, present only when the condition routes a request the door is resolving: `request.model` (the Messages body's own model field) and `request.hasImage` (an image block anywhere in the scanned head of the body). A request the door could not read that far carries neither, so a condition naming them is indeterminate and the routing falls through, never to a cheaper provider by accident.
7113
+ */
7114
+ readonly request?: {
7115
+ readonly model?: string;
7116
+ readonly hasImage?: boolean;
7117
+ };
7036
7118
  }
7037
7119
  /**
7038
7120
  * The result of evaluating one `when`: definite, with which condition fields were present and which of those did not hold, or indeterminate, when a datum the condition needed is missing. Indeterminate is not false: a missing fact has not failed the condition, it has left it undecided, and the consumer decides what an undecided entry does (the resolver keeps today's behaviour of not passing it, so nothing changes for existing configurations; the pool ranking of #258 instead keeps such a member but ranks it last, naming the missing fact).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-shim",
3
- "version": "8.34.0",
3
+ "version": "8.35.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>",