agent-shim 11.74.0 → 11.76.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/index.cjs CHANGED
@@ -1229,6 +1229,8 @@ var init_schema = __esm({
1229
1229
  $schema: import_zod3.z.string().optional(),
1230
1230
  name: FileNameSchema,
1231
1231
  defaultConfigProfile: StoredNameSchema.optional(),
1232
+ /** The provider this identity exists for: a launch on the identity routes through it unless `--provider`, `--no-provider` or a cascade layer's `launch.provider` says otherwise. Its sessions run on the provider's credential, so the identity needs no stored login. */
1233
+ provider: StoredNameSchema.optional(),
1232
1234
  allowAmbientCredential: import_zod3.z.boolean().default(false),
1233
1235
  credential: CredentialSchema.optional(),
1234
1236
  /** When this identity's five-hour window should be open: the front door opens one at each anchor if none is. Absent, nothing is opened on a schedule. */
@@ -4762,7 +4764,7 @@ var init_package = __esm({
4762
4764
  "package.json"() {
4763
4765
  package_default = {
4764
4766
  name: "agent-shim",
4765
- version: "11.74.0",
4767
+ version: "11.76.0",
4766
4768
  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.",
4767
4769
  license: "MIT",
4768
4770
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -9049,6 +9051,12 @@ function providerJsonPath(paths, name) {
9049
9051
  function providerExists(paths, name) {
9050
9052
  return import_node_fs6.default.existsSync(providerJsonPath(paths, name));
9051
9053
  }
9054
+ function requireProviderExists(paths, name) {
9055
+ const canonical = canonicalProviderName(name, (candidate) => providerExists(paths, candidate), () => readProviderAliases(paths));
9056
+ if (!providerExists(paths, canonical)) {
9057
+ throw new ProviderNotFoundError(name);
9058
+ }
9059
+ }
9052
9060
  function isRecord7(value) {
9053
9061
  return typeof value === "object" && value !== null && !Array.isArray(value);
9054
9062
  }
@@ -9283,18 +9291,18 @@ function removeProvider(paths, name) {
9283
9291
  }
9284
9292
  import_node_fs6.default.rmSync(providerJsonPath(paths, name));
9285
9293
  }
9286
- function cascadeProviderName(cascade) {
9294
+ function cascadeProviderName(cascade, identityProvider) {
9287
9295
  let name;
9288
9296
  for (const layer of assembleCascade(cascade).layers) {
9289
9297
  if (layer.launch?.provider !== void 0) {
9290
9298
  name = layer.launch.provider;
9291
9299
  }
9292
9300
  }
9293
- return name;
9301
+ return name ?? identityProvider;
9294
9302
  }
9295
9303
  function selectProvider(params) {
9296
9304
  const cliName = params.cliProvider !== void 0 && params.cliProvider !== "" ? params.cliProvider : void 0;
9297
- const named = cliName ?? (params.cascade === void 0 ? void 0 : cascadeProviderName(params.cascade));
9305
+ const named = cliName ?? (params.cascade === void 0 ? params.identityProvider : cascadeProviderName(params.cascade, params.identityProvider));
9298
9306
  if (named === void 0) {
9299
9307
  return void 0;
9300
9308
  }
@@ -9454,6 +9462,9 @@ function decideSignIn(facts) {
9454
9462
  if (facts.hasCredentialBlock) {
9455
9463
  return { state: "token", detail: "supplies its own credential through a credential block, so a stored login is not what a launch uses" };
9456
9464
  }
9465
+ if (facts.provider !== void 0) {
9466
+ return { state: "token", detail: "runs provider sessions with the provider's credential, so a stored login is not what a launch uses" };
9467
+ }
9457
9468
  if (facts.keychainItem === true) {
9458
9469
  return { state: "signed-in", detail: "a login is stored in the macOS Keychain" };
9459
9470
  }
@@ -9466,9 +9477,10 @@ function credentialsFilePath(farmRoot) {
9466
9477
  return import_node_path25.default.join(farmRoot, CREDENTIALS_FILE);
9467
9478
  }
9468
9479
  function identitySignIn(fs14, probe, identity) {
9469
- const probing = !identity.hasCredentialBlock;
9480
+ const probing = !identity.hasCredentialBlock && identity.provider === void 0;
9470
9481
  return decideSignIn({
9471
9482
  hasCredentialBlock: identity.hasCredentialBlock,
9483
+ provider: identity.provider,
9472
9484
  keychainItem: probing && probe.platform === "darwin" && probe.run !== void 0 ? keychainHasItem(probe.run, identity.farmRoot) : void 0,
9473
9485
  credentialsFile: probing && fs14.lstat(credentialsFilePath(identity.farmRoot)) !== void 0,
9474
9486
  platform: probe.platform
@@ -11731,7 +11743,8 @@ function decideLaunch(params, readOnly) {
11731
11743
  paths,
11732
11744
  port: fs14,
11733
11745
  ...parsedArgv.provider === void 0 || parsedArgv.provider === false ? {} : { cliProvider: parsedArgv.provider },
11734
- ...farmContext === void 0 ? {} : { cascade: farmContext.cascade }
11746
+ ...farmContext === void 0 ? {} : { cascade: farmContext.cascade },
11747
+ ...loadedIdentity?.config.provider === void 0 ? {} : { identityProvider: loadedIdentity.config.provider }
11735
11748
  };
11736
11749
  let selectedProvider;
11737
11750
  let resolvedProvider;
@@ -12352,7 +12365,7 @@ function realPrepareLaunchParams(paths, options) {
12352
12365
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
12353
12366
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
12354
12367
  hold: realHoldPort,
12355
- hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: import_node_path41.default.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
12368
+ hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: import_node_path41.default.join(paths.identitiesDir, identity), hasCredentialBlock: false, provider: void 0 }).state !== "signed-out",
12356
12369
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
12357
12370
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
12358
12371
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
@@ -16485,7 +16498,7 @@ function collectCheckReport(params) {
16485
16498
  read,
16486
16499
  ...configProfileDecision.name === void 0 ? {} : { baseConfigProfile: configProfileDecision.name }
16487
16500
  }).input;
16488
- const providerName = cascadeProviderName(cascade);
16501
+ const providerName = cascadeProviderName(cascade, identityConfig?.provider);
16489
16502
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
16490
16503
  const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path26.default.join(paths.identitiesDir, identityDecision.name);
16491
16504
  const settingsFiles = {
@@ -16914,6 +16927,12 @@ function setDefaultConfigProfile(paths, identityName, profileName) {
16914
16927
  defaultConfigProfile: profileName
16915
16928
  });
16916
16929
  }
16930
+ function setIdentityProvider(paths, identityName, providerName) {
16931
+ if (!identityExists(paths, identityName)) {
16932
+ throw new IdentityNotFoundError(identityName);
16933
+ }
16934
+ return applyPatch(identityJsonPath(paths, identityName), IdentitySchema, { provider: providerName });
16935
+ }
16917
16936
  function setAllowAmbientCredential(paths, identityName, allow) {
16918
16937
  if (!identityExists(paths, identityName)) {
16919
16938
  throw new IdentityNotFoundError(identityName);
@@ -17582,6 +17601,7 @@ function runDoctor(params) {
17582
17601
  }
17583
17602
  }
17584
17603
  const validProfileNames = new Set(profileSources.keys());
17604
+ const validProviderNames = /* @__PURE__ */ new Set([...params.providers.map((entry) => entry.name), ...Object.keys(params.providerAliases ?? {})]);
17585
17605
  const validIdentityNames = /* @__PURE__ */ new Set();
17586
17606
  for (const entry of params.identities) {
17587
17607
  const validated3 = validate(IdentitySchema, entry, "identity", entry.name);
@@ -17591,35 +17611,47 @@ function runDoctor(params) {
17591
17611
  }
17592
17612
  validIdentityNames.add(entry.name);
17593
17613
  const defaultProfile = validated3.data.defaultConfigProfile;
17614
+ let consistent = true;
17594
17615
  if (defaultProfile !== void 0 && !validProfileNames.has(defaultProfile)) {
17616
+ consistent = false;
17595
17617
  push(
17596
17618
  "identity",
17597
17619
  "fail",
17598
17620
  `Identity "${entry.name}" names configuration profile "${defaultProfile}" as its default, but no such profile exists.`,
17599
17621
  entry.name
17600
17622
  );
17601
- } else {
17602
- const credential = validated3.data.credential;
17603
- const cache = credential === void 0 ? { text: "", unreadable: false } : cacheClause(params.credentialCache, `identity ${entry.name}`, credential);
17604
- push(
17605
- "identity",
17606
- cache.unreadable ? "fail" : "pass",
17607
- `${entry.name} is valid and authenticates with ${credential === void 0 ? "its stored login" : `credential ${describeCredential(credential)}`}${cache.text}.`,
17608
- entry.name
17609
- );
17610
- const signIn = decideSignIn({
17611
- hasCredentialBlock: credential !== void 0,
17612
- keychainItem: params.platform === "darwin" && params.run !== void 0 ? keychainHasItem(params.run, entry.farmRoot) : void 0,
17613
- credentialsFile: entry.credentialsFilePresent,
17614
- platform: params.platform
17615
- });
17616
- push(
17617
- "sign-in",
17618
- signIn.state === "signed-out" ? "warn" : "pass",
17619
- signIn.state === "signed-out" ? `${entry.name} is signed out (${signIn.detail}). Run \`agent-shim run @${entry.name}\` and sign in.` : `${entry.name} ${signIn.state === "token" ? "uses a credential block" : "is signed in"} (${signIn.detail}).`,
17620
- entry.name
17621
- );
17622
17623
  }
17624
+ const identityProvider = validated3.data.provider;
17625
+ if (identityProvider !== void 0 && !validProviderNames.has(identityProvider)) {
17626
+ consistent = false;
17627
+ push("identity", "fail", `Identity "${entry.name}" names provider "${identityProvider}" as its provider, but no such provider exists.`, entry.name);
17628
+ }
17629
+ if (!consistent) {
17630
+ continue;
17631
+ }
17632
+ const credential = validated3.data.credential;
17633
+ const cache = credential === void 0 ? { text: "", unreadable: false } : cacheClause(params.credentialCache, `identity ${entry.name}`, credential);
17634
+ const authenticatesWith = credential !== void 0 ? `credential ${describeCredential(credential)}` : identityProvider !== void 0 ? `the credential of provider "${identityProvider}"` : "its stored login";
17635
+ push(
17636
+ "identity",
17637
+ cache.unreadable ? "fail" : "pass",
17638
+ `${entry.name} is valid and authenticates with ${authenticatesWith}${cache.text}.`,
17639
+ entry.name
17640
+ );
17641
+ const standing = credential !== void 0 ? "uses a credential block" : identityProvider !== void 0 ? `exists for provider "${identityProvider}"` : "is signed in";
17642
+ const signIn = decideSignIn({
17643
+ hasCredentialBlock: credential !== void 0,
17644
+ provider: identityProvider,
17645
+ keychainItem: params.platform === "darwin" && params.run !== void 0 ? keychainHasItem(params.run, entry.farmRoot) : void 0,
17646
+ credentialsFile: entry.credentialsFilePresent,
17647
+ platform: params.platform
17648
+ });
17649
+ push(
17650
+ "sign-in",
17651
+ signIn.state === "signed-out" ? "warn" : "pass",
17652
+ signIn.state === "signed-out" ? `${entry.name} is signed out (${signIn.detail}). Run \`agent-shim run @${entry.name}\` and sign in.` : `${entry.name} ${standing} (${signIn.detail}).`,
17653
+ entry.name
17654
+ );
17623
17655
  }
17624
17656
  const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
17625
17657
  const pools = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.pools ?? {} : {};
@@ -18282,6 +18314,7 @@ var storedMutationOutput = (kind, action, value) => import_zod30.z.strictObject(
18282
18314
  var IdentityValueSchema = import_zod30.z.strictObject({
18283
18315
  name: import_zod30.z.string(),
18284
18316
  defaultConfigProfile: import_zod30.z.string().optional(),
18317
+ provider: import_zod30.z.string().optional(),
18285
18318
  allowAmbientCredential: import_zod30.z.boolean(),
18286
18319
  credential: CredentialSummarySchema2.optional(),
18287
18320
  anchors: import_zod30.z.array(AnchorSchema).optional()
@@ -18301,6 +18334,8 @@ var ConfigIdentityAddOutputSchema = storedMutationOutput("identity", "created",
18301
18334
  var ConfigIdentitySetInputSchema = import_zod30.z.strictObject({
18302
18335
  name: import_zod30.z.string().min(1),
18303
18336
  defaultConfigProfile: import_zod30.z.union([import_zod30.z.string().min(1), import_zod30.z.literal(false)]).optional(),
18337
+ /** The provider the identity exists for; `false` clears it. */
18338
+ provider: import_zod30.z.union([import_zod30.z.string().min(1), import_zod30.z.literal(false)]).optional(),
18304
18339
  allowAmbientCredential: import_zod30.z.boolean().optional(),
18305
18340
  credential: import_zod30.z.union([import_zod30.z.literal(false), CredentialWriteSchema(CREDENTIAL_TARGETS)]).optional(),
18306
18341
  /** `false` removes the anchors; a list replaces them. */
@@ -18445,6 +18480,7 @@ function identityValue(name, paths) {
18445
18480
  return {
18446
18481
  name: identity.name,
18447
18482
  ...identity.defaultConfigProfile === void 0 ? {} : { defaultConfigProfile: identity.defaultConfigProfile },
18483
+ ...identity.provider === void 0 ? {} : { provider: identity.provider },
18448
18484
  allowAmbientCredential: identity.allowAmbientCredential,
18449
18485
  ...identity.credential === void 0 ? {} : { credential: summariseCredential(identity.credential) },
18450
18486
  ...identity.anchors === void 0 ? {} : { anchors: identity.anchors }
@@ -18477,18 +18513,24 @@ function createConfigApiRouter(deps) {
18477
18513
  return { action: "created", kind: "identity", name: input.name, value: identityValue(input.name, paths) };
18478
18514
  })
18479
18515
  ),
18480
- set: route("/rest/config/identity/set", "Update an identity's default profile, ambient-credential setting, credential or anchors").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
18516
+ set: route("/rest/config/identity/set", "Update an identity's default profile, provider, ambient-credential setting, credential or anchors").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
18481
18517
  ({ input }) => guarded(() => {
18482
- requireChange(input.defaultConfigProfile !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0 || input.anchors !== void 0, "defaultConfigProfile, allowAmbientCredential, credential or anchors");
18518
+ requireChange(input.defaultConfigProfile !== void 0 || input.provider !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0 || input.anchors !== void 0, "defaultConfigProfile, provider, allowAmbientCredential, credential or anchors");
18483
18519
  if (!identityExists(paths, input.name)) {
18484
18520
  throw new IdentityNotFoundError(input.name);
18485
18521
  }
18486
18522
  if (typeof input.defaultConfigProfile === "string") {
18487
18523
  requireProfileExists(paths, input.defaultConfigProfile);
18488
18524
  }
18525
+ if (typeof input.provider === "string") {
18526
+ requireProviderExists(paths, input.provider);
18527
+ }
18489
18528
  if (input.defaultConfigProfile !== void 0) {
18490
18529
  setDefaultConfigProfile(paths, input.name, input.defaultConfigProfile === false ? void 0 : input.defaultConfigProfile);
18491
18530
  }
18531
+ if (input.provider !== void 0) {
18532
+ setIdentityProvider(paths, input.name, input.provider === false ? void 0 : input.provider);
18533
+ }
18492
18534
  if (input.allowAmbientCredential !== void 0) {
18493
18535
  setAllowAmbientCredential(paths, input.name, input.allowAmbientCredential);
18494
18536
  }
package/dist/index.mjs CHANGED
@@ -1207,6 +1207,8 @@ var init_schema = __esm({
1207
1207
  $schema: z3.string().optional(),
1208
1208
  name: FileNameSchema,
1209
1209
  defaultConfigProfile: StoredNameSchema.optional(),
1210
+ /** The provider this identity exists for: a launch on the identity routes through it unless `--provider`, `--no-provider` or a cascade layer's `launch.provider` says otherwise. Its sessions run on the provider's credential, so the identity needs no stored login. */
1211
+ provider: StoredNameSchema.optional(),
1210
1212
  allowAmbientCredential: z3.boolean().default(false),
1211
1213
  credential: CredentialSchema.optional(),
1212
1214
  /** When this identity's five-hour window should be open: the front door opens one at each anchor if none is. Absent, nothing is opened on a schedule. */
@@ -4738,7 +4740,7 @@ var init_package = __esm({
4738
4740
  "package.json"() {
4739
4741
  package_default = {
4740
4742
  name: "agent-shim",
4741
- version: "11.74.0",
4743
+ version: "11.76.0",
4742
4744
  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.",
4743
4745
  license: "MIT",
4744
4746
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -9023,6 +9025,12 @@ function providerJsonPath(paths, name) {
9023
9025
  function providerExists(paths, name) {
9024
9026
  return fs7.existsSync(providerJsonPath(paths, name));
9025
9027
  }
9028
+ function requireProviderExists(paths, name) {
9029
+ const canonical = canonicalProviderName(name, (candidate) => providerExists(paths, candidate), () => readProviderAliases(paths));
9030
+ if (!providerExists(paths, canonical)) {
9031
+ throw new ProviderNotFoundError(name);
9032
+ }
9033
+ }
9026
9034
  function isRecord7(value) {
9027
9035
  return typeof value === "object" && value !== null && !Array.isArray(value);
9028
9036
  }
@@ -9257,18 +9265,18 @@ function removeProvider(paths, name) {
9257
9265
  }
9258
9266
  fs7.rmSync(providerJsonPath(paths, name));
9259
9267
  }
9260
- function cascadeProviderName(cascade) {
9268
+ function cascadeProviderName(cascade, identityProvider) {
9261
9269
  let name;
9262
9270
  for (const layer of assembleCascade(cascade).layers) {
9263
9271
  if (layer.launch?.provider !== void 0) {
9264
9272
  name = layer.launch.provider;
9265
9273
  }
9266
9274
  }
9267
- return name;
9275
+ return name ?? identityProvider;
9268
9276
  }
9269
9277
  function selectProvider(params) {
9270
9278
  const cliName = params.cliProvider !== void 0 && params.cliProvider !== "" ? params.cliProvider : void 0;
9271
- const named = cliName ?? (params.cascade === void 0 ? void 0 : cascadeProviderName(params.cascade));
9279
+ const named = cliName ?? (params.cascade === void 0 ? params.identityProvider : cascadeProviderName(params.cascade, params.identityProvider));
9272
9280
  if (named === void 0) {
9273
9281
  return void 0;
9274
9282
  }
@@ -9429,6 +9437,9 @@ function decideSignIn(facts) {
9429
9437
  if (facts.hasCredentialBlock) {
9430
9438
  return { state: "token", detail: "supplies its own credential through a credential block, so a stored login is not what a launch uses" };
9431
9439
  }
9440
+ if (facts.provider !== void 0) {
9441
+ return { state: "token", detail: "runs provider sessions with the provider's credential, so a stored login is not what a launch uses" };
9442
+ }
9432
9443
  if (facts.keychainItem === true) {
9433
9444
  return { state: "signed-in", detail: "a login is stored in the macOS Keychain" };
9434
9445
  }
@@ -9441,9 +9452,10 @@ function credentialsFilePath(farmRoot) {
9441
9452
  return path25.join(farmRoot, CREDENTIALS_FILE);
9442
9453
  }
9443
9454
  function identitySignIn(fs14, probe, identity) {
9444
- const probing = !identity.hasCredentialBlock;
9455
+ const probing = !identity.hasCredentialBlock && identity.provider === void 0;
9445
9456
  return decideSignIn({
9446
9457
  hasCredentialBlock: identity.hasCredentialBlock,
9458
+ provider: identity.provider,
9447
9459
  keychainItem: probing && probe.platform === "darwin" && probe.run !== void 0 ? keychainHasItem(probe.run, identity.farmRoot) : void 0,
9448
9460
  credentialsFile: probing && fs14.lstat(credentialsFilePath(identity.farmRoot)) !== void 0,
9449
9461
  platform: probe.platform
@@ -11706,7 +11718,8 @@ function decideLaunch(params, readOnly) {
11706
11718
  paths,
11707
11719
  port: fs14,
11708
11720
  ...parsedArgv.provider === void 0 || parsedArgv.provider === false ? {} : { cliProvider: parsedArgv.provider },
11709
- ...farmContext === void 0 ? {} : { cascade: farmContext.cascade }
11721
+ ...farmContext === void 0 ? {} : { cascade: farmContext.cascade },
11722
+ ...loadedIdentity?.config.provider === void 0 ? {} : { identityProvider: loadedIdentity.config.provider }
11710
11723
  };
11711
11724
  let selectedProvider;
11712
11725
  let resolvedProvider;
@@ -12325,7 +12338,7 @@ function realPrepareLaunchParams(paths, options) {
12325
12338
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
12326
12339
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
12327
12340
  hold: realHoldPort,
12328
- hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: path41.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
12341
+ hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: path41.join(paths.identitiesDir, identity), hasCredentialBlock: false, provider: void 0 }).state !== "signed-out",
12329
12342
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
12330
12343
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
12331
12344
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
@@ -16070,7 +16083,7 @@ function collectCheckReport(params) {
16070
16083
  read,
16071
16084
  ...configProfileDecision.name === void 0 ? {} : { baseConfigProfile: configProfileDecision.name }
16072
16085
  }).input;
16073
- const providerName = cascadeProviderName(cascade);
16086
+ const providerName = cascadeProviderName(cascade, identityConfig?.provider);
16074
16087
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
16075
16088
  const farmRoot = identityDecision.name === void 0 ? void 0 : path26.join(paths.identitiesDir, identityDecision.name);
16076
16089
  const settingsFiles = {
@@ -16499,6 +16512,12 @@ function setDefaultConfigProfile(paths, identityName, profileName) {
16499
16512
  defaultConfigProfile: profileName
16500
16513
  });
16501
16514
  }
16515
+ function setIdentityProvider(paths, identityName, providerName) {
16516
+ if (!identityExists(paths, identityName)) {
16517
+ throw new IdentityNotFoundError(identityName);
16518
+ }
16519
+ return applyPatch(identityJsonPath(paths, identityName), IdentitySchema, { provider: providerName });
16520
+ }
16502
16521
  function setAllowAmbientCredential(paths, identityName, allow) {
16503
16522
  if (!identityExists(paths, identityName)) {
16504
16523
  throw new IdentityNotFoundError(identityName);
@@ -17167,6 +17186,7 @@ function runDoctor(params) {
17167
17186
  }
17168
17187
  }
17169
17188
  const validProfileNames = new Set(profileSources.keys());
17189
+ const validProviderNames = /* @__PURE__ */ new Set([...params.providers.map((entry) => entry.name), ...Object.keys(params.providerAliases ?? {})]);
17170
17190
  const validIdentityNames = /* @__PURE__ */ new Set();
17171
17191
  for (const entry of params.identities) {
17172
17192
  const validated3 = validate(IdentitySchema, entry, "identity", entry.name);
@@ -17176,35 +17196,47 @@ function runDoctor(params) {
17176
17196
  }
17177
17197
  validIdentityNames.add(entry.name);
17178
17198
  const defaultProfile = validated3.data.defaultConfigProfile;
17199
+ let consistent = true;
17179
17200
  if (defaultProfile !== void 0 && !validProfileNames.has(defaultProfile)) {
17201
+ consistent = false;
17180
17202
  push(
17181
17203
  "identity",
17182
17204
  "fail",
17183
17205
  `Identity "${entry.name}" names configuration profile "${defaultProfile}" as its default, but no such profile exists.`,
17184
17206
  entry.name
17185
17207
  );
17186
- } else {
17187
- const credential = validated3.data.credential;
17188
- const cache = credential === void 0 ? { text: "", unreadable: false } : cacheClause(params.credentialCache, `identity ${entry.name}`, credential);
17189
- push(
17190
- "identity",
17191
- cache.unreadable ? "fail" : "pass",
17192
- `${entry.name} is valid and authenticates with ${credential === void 0 ? "its stored login" : `credential ${describeCredential(credential)}`}${cache.text}.`,
17193
- entry.name
17194
- );
17195
- const signIn = decideSignIn({
17196
- hasCredentialBlock: credential !== void 0,
17197
- keychainItem: params.platform === "darwin" && params.run !== void 0 ? keychainHasItem(params.run, entry.farmRoot) : void 0,
17198
- credentialsFile: entry.credentialsFilePresent,
17199
- platform: params.platform
17200
- });
17201
- push(
17202
- "sign-in",
17203
- signIn.state === "signed-out" ? "warn" : "pass",
17204
- signIn.state === "signed-out" ? `${entry.name} is signed out (${signIn.detail}). Run \`agent-shim run @${entry.name}\` and sign in.` : `${entry.name} ${signIn.state === "token" ? "uses a credential block" : "is signed in"} (${signIn.detail}).`,
17205
- entry.name
17206
- );
17207
17208
  }
17209
+ const identityProvider = validated3.data.provider;
17210
+ if (identityProvider !== void 0 && !validProviderNames.has(identityProvider)) {
17211
+ consistent = false;
17212
+ push("identity", "fail", `Identity "${entry.name}" names provider "${identityProvider}" as its provider, but no such provider exists.`, entry.name);
17213
+ }
17214
+ if (!consistent) {
17215
+ continue;
17216
+ }
17217
+ const credential = validated3.data.credential;
17218
+ const cache = credential === void 0 ? { text: "", unreadable: false } : cacheClause(params.credentialCache, `identity ${entry.name}`, credential);
17219
+ const authenticatesWith = credential !== void 0 ? `credential ${describeCredential(credential)}` : identityProvider !== void 0 ? `the credential of provider "${identityProvider}"` : "its stored login";
17220
+ push(
17221
+ "identity",
17222
+ cache.unreadable ? "fail" : "pass",
17223
+ `${entry.name} is valid and authenticates with ${authenticatesWith}${cache.text}.`,
17224
+ entry.name
17225
+ );
17226
+ const standing = credential !== void 0 ? "uses a credential block" : identityProvider !== void 0 ? `exists for provider "${identityProvider}"` : "is signed in";
17227
+ const signIn = decideSignIn({
17228
+ hasCredentialBlock: credential !== void 0,
17229
+ provider: identityProvider,
17230
+ keychainItem: params.platform === "darwin" && params.run !== void 0 ? keychainHasItem(params.run, entry.farmRoot) : void 0,
17231
+ credentialsFile: entry.credentialsFilePresent,
17232
+ platform: params.platform
17233
+ });
17234
+ push(
17235
+ "sign-in",
17236
+ signIn.state === "signed-out" ? "warn" : "pass",
17237
+ signIn.state === "signed-out" ? `${entry.name} is signed out (${signIn.detail}). Run \`agent-shim run @${entry.name}\` and sign in.` : `${entry.name} ${standing} (${signIn.detail}).`,
17238
+ entry.name
17239
+ );
17208
17240
  }
17209
17241
  const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
17210
17242
  const pools = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.pools ?? {} : {};
@@ -17867,6 +17899,7 @@ var storedMutationOutput = (kind, action, value) => z30.strictObject({ action: z
17867
17899
  var IdentityValueSchema = z30.strictObject({
17868
17900
  name: z30.string(),
17869
17901
  defaultConfigProfile: z30.string().optional(),
17902
+ provider: z30.string().optional(),
17870
17903
  allowAmbientCredential: z30.boolean(),
17871
17904
  credential: CredentialSummarySchema2.optional(),
17872
17905
  anchors: z30.array(AnchorSchema).optional()
@@ -17886,6 +17919,8 @@ var ConfigIdentityAddOutputSchema = storedMutationOutput("identity", "created",
17886
17919
  var ConfigIdentitySetInputSchema = z30.strictObject({
17887
17920
  name: z30.string().min(1),
17888
17921
  defaultConfigProfile: z30.union([z30.string().min(1), z30.literal(false)]).optional(),
17922
+ /** The provider the identity exists for; `false` clears it. */
17923
+ provider: z30.union([z30.string().min(1), z30.literal(false)]).optional(),
17889
17924
  allowAmbientCredential: z30.boolean().optional(),
17890
17925
  credential: z30.union([z30.literal(false), CredentialWriteSchema(CREDENTIAL_TARGETS)]).optional(),
17891
17926
  /** `false` removes the anchors; a list replaces them. */
@@ -18030,6 +18065,7 @@ function identityValue(name, paths) {
18030
18065
  return {
18031
18066
  name: identity.name,
18032
18067
  ...identity.defaultConfigProfile === void 0 ? {} : { defaultConfigProfile: identity.defaultConfigProfile },
18068
+ ...identity.provider === void 0 ? {} : { provider: identity.provider },
18033
18069
  allowAmbientCredential: identity.allowAmbientCredential,
18034
18070
  ...identity.credential === void 0 ? {} : { credential: summariseCredential(identity.credential) },
18035
18071
  ...identity.anchors === void 0 ? {} : { anchors: identity.anchors }
@@ -18062,18 +18098,24 @@ function createConfigApiRouter(deps) {
18062
18098
  return { action: "created", kind: "identity", name: input.name, value: identityValue(input.name, paths) };
18063
18099
  })
18064
18100
  ),
18065
- set: route("/rest/config/identity/set", "Update an identity's default profile, ambient-credential setting, credential or anchors").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
18101
+ set: route("/rest/config/identity/set", "Update an identity's default profile, provider, ambient-credential setting, credential or anchors").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
18066
18102
  ({ input }) => guarded(() => {
18067
- requireChange(input.defaultConfigProfile !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0 || input.anchors !== void 0, "defaultConfigProfile, allowAmbientCredential, credential or anchors");
18103
+ requireChange(input.defaultConfigProfile !== void 0 || input.provider !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0 || input.anchors !== void 0, "defaultConfigProfile, provider, allowAmbientCredential, credential or anchors");
18068
18104
  if (!identityExists(paths, input.name)) {
18069
18105
  throw new IdentityNotFoundError(input.name);
18070
18106
  }
18071
18107
  if (typeof input.defaultConfigProfile === "string") {
18072
18108
  requireProfileExists(paths, input.defaultConfigProfile);
18073
18109
  }
18110
+ if (typeof input.provider === "string") {
18111
+ requireProviderExists(paths, input.provider);
18112
+ }
18074
18113
  if (input.defaultConfigProfile !== void 0) {
18075
18114
  setDefaultConfigProfile(paths, input.name, input.defaultConfigProfile === false ? void 0 : input.defaultConfigProfile);
18076
18115
  }
18116
+ if (input.provider !== void 0) {
18117
+ setIdentityProvider(paths, input.name, input.provider === false ? void 0 : input.provider);
18118
+ }
18077
18119
  if (input.allowAmbientCredential !== void 0) {
18078
18120
  setAllowAmbientCredential(paths, input.name, input.allowAmbientCredential);
18079
18121
  }
@@ -5413,6 +5413,7 @@ declare const IdentitySchema: z.ZodObject<{
5413
5413
  $schema: z.ZodOptional<z.ZodString>;
5414
5414
  name: z.ZodString;
5415
5415
  defaultConfigProfile: z.ZodOptional<z.ZodString>;
5416
+ provider: z.ZodOptional<z.ZodString>;
5416
5417
  allowAmbientCredential: z.ZodDefault<z.ZodBoolean>;
5417
5418
  credential: z.ZodOptional<z.ZodObject<{
5418
5419
  sources: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
@@ -9472,6 +9473,7 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
9472
9473
  value: zod.ZodObject<{
9473
9474
  name: zod.ZodString;
9474
9475
  defaultConfigProfile: zod.ZodOptional<zod.ZodString>;
9476
+ provider: zod.ZodOptional<zod.ZodString>;
9475
9477
  allowAmbientCredential: zod.ZodBoolean;
9476
9478
  credential: zod.ZodOptional<zod.ZodObject<{
9477
9479
  target: zod.ZodEnum<{
@@ -9524,6 +9526,7 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
9524
9526
  set: _orpc_server.DecoratedProcedure<DoorApiContext & object, IntersectPick<TInitialContext, $OutContext>, zod.ZodObject<{
9525
9527
  name: zod.ZodString;
9526
9528
  defaultConfigProfile: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
9529
+ provider: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
9527
9530
  allowAmbientCredential: zod.ZodOptional<zod.ZodBoolean>;
9528
9531
  credential: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodLiteral<false>, zod.ZodObject<{
9529
9532
  sources: zod.ZodOptional<zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
@@ -9577,6 +9580,7 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
9577
9580
  value: zod.ZodObject<{
9578
9581
  name: zod.ZodString;
9579
9582
  defaultConfigProfile: zod.ZodOptional<zod.ZodString>;
9583
+ provider: zod.ZodOptional<zod.ZodString>;
9580
9584
  allowAmbientCredential: zod.ZodBoolean;
9581
9585
  credential: zod.ZodOptional<zod.ZodObject<{
9582
9586
  target: zod.ZodEnum<{
@@ -16537,6 +16541,7 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
16537
16541
  value: zod.ZodObject<{
16538
16542
  name: zod.ZodString;
16539
16543
  defaultConfigProfile: zod.ZodOptional<zod.ZodString>;
16544
+ provider: zod.ZodOptional<zod.ZodString>;
16540
16545
  allowAmbientCredential: zod.ZodBoolean;
16541
16546
  credential: zod.ZodOptional<zod.ZodObject<{
16542
16547
  target: zod.ZodEnum<{
@@ -16589,6 +16594,7 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
16589
16594
  set: _orpc_server.DecoratedProcedure<DoorApiContext & object, IntersectPick<TInitialContext, $OutContext>, zod.ZodObject<{
16590
16595
  name: zod.ZodString;
16591
16596
  defaultConfigProfile: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
16597
+ provider: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
16592
16598
  allowAmbientCredential: zod.ZodOptional<zod.ZodBoolean>;
16593
16599
  credential: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodLiteral<false>, zod.ZodObject<{
16594
16600
  sources: zod.ZodOptional<zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
@@ -16642,6 +16648,7 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
16642
16648
  value: zod.ZodObject<{
16643
16649
  name: zod.ZodString;
16644
16650
  defaultConfigProfile: zod.ZodOptional<zod.ZodString>;
16651
+ provider: zod.ZodOptional<zod.ZodString>;
16645
16652
  allowAmbientCredential: zod.ZodBoolean;
16646
16653
  credential: zod.ZodOptional<zod.ZodObject<{
16647
16654
  target: zod.ZodEnum<{
@@ -21060,6 +21067,7 @@ declare const ConfigIdentityAddOutputSchema: z.ZodObject<{
21060
21067
  value: z.ZodObject<{
21061
21068
  name: z.ZodString;
21062
21069
  defaultConfigProfile: z.ZodOptional<z.ZodString>;
21070
+ provider: z.ZodOptional<z.ZodString>;
21063
21071
  allowAmbientCredential: z.ZodBoolean;
21064
21072
  credential: z.ZodOptional<z.ZodObject<{
21065
21073
  target: z.ZodEnum<{
@@ -21113,6 +21121,7 @@ declare const ConfigIdentityAddOutputSchema: z.ZodObject<{
21113
21121
  declare const ConfigIdentitySetInputSchema: z.ZodObject<{
21114
21122
  name: z.ZodString;
21115
21123
  defaultConfigProfile: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
21124
+ provider: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
21116
21125
  allowAmbientCredential: z.ZodOptional<z.ZodBoolean>;
21117
21126
  credential: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
21118
21127
  sources: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
@@ -21167,6 +21176,7 @@ declare const ConfigIdentitySetOutputSchema: z.ZodObject<{
21167
21176
  value: z.ZodObject<{
21168
21177
  name: z.ZodString;
21169
21178
  defaultConfigProfile: z.ZodOptional<z.ZodString>;
21179
+ provider: z.ZodOptional<z.ZodString>;
21170
21180
  allowAmbientCredential: z.ZodBoolean;
21171
21181
  credential: z.ZodOptional<z.ZodObject<{
21172
21182
  target: z.ZodEnum<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-shim",
3
- "version": "11.74.0",
3
+ "version": "11.76.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>",