agent-shim 11.74.0 → 11.75.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
@@ -37381,13 +37381,97 @@ var init_proxyBypass2 = __esm({
37381
37381
  }
37382
37382
  });
37383
37383
 
37384
+ // src/usage/account.ts
37385
+ function isObject2(value2) {
37386
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
37387
+ }
37388
+ function isIdentityName(name) {
37389
+ return IdentitySchema.shape.name.safeParse(name).success;
37390
+ }
37391
+ function claudeJsonPath(identitiesDir, identity) {
37392
+ return import_node_path24.default.join(identitiesDir, identity, CLAUDE_JSON);
37393
+ }
37394
+ function readAccountMetadata(fs31, identitiesDir, identity) {
37395
+ if (!isIdentityName(identity)) {
37396
+ throw new Error(`"${identity}" is not a valid identity name.`);
37397
+ }
37398
+ return readAccountMetadataFile(fs31, claudeJsonPath(identitiesDir, identity));
37399
+ }
37400
+ function readAccountMetadataFile(fs31, file2) {
37401
+ const raw = fs31.readFileUtf8(file2);
37402
+ if (raw === void 0) {
37403
+ return void 0;
37404
+ }
37405
+ let parsed;
37406
+ try {
37407
+ parsed = JSON.parse(raw);
37408
+ } catch {
37409
+ throw new AccountMetadataError(file2, "not valid JSON");
37410
+ }
37411
+ if (!isObject2(parsed)) {
37412
+ throw new AccountMetadataError(file2, "not a JSON object");
37413
+ }
37414
+ const oauthAccount = parsed.oauthAccount;
37415
+ if (!isObject2(oauthAccount)) {
37416
+ return void 0;
37417
+ }
37418
+ const picked = {};
37419
+ for (const key of Object.keys(AccountMetadataSchema.shape)) {
37420
+ const value2 = oauthAccount[key];
37421
+ if (value2 !== null && value2 !== void 0) {
37422
+ picked[key] = value2;
37423
+ }
37424
+ }
37425
+ const account = AccountMetadataSchema.safeParse(picked);
37426
+ if (!account.success) {
37427
+ throw new AccountMetadataError(file2, account.error.issues.map((issue2) => `${issue2.path.join(".")}: ${issue2.message}`).join("; "));
37428
+ }
37429
+ return account.data;
37430
+ }
37431
+ function createAccountReader(fs31, identitiesDir) {
37432
+ const cache = /* @__PURE__ */ new Map();
37433
+ return (identity) => {
37434
+ if (!isIdentityName(identity)) {
37435
+ throw new Error(`"${identity}" is not a valid identity name.`);
37436
+ }
37437
+ const stat = fs31.lstat(claudeJsonPath(identitiesDir, identity));
37438
+ const stamp = stat === void 0 ? "absent" : `${String(stat.mtimeMs)}:${String(stat.sizeBytes)}`;
37439
+ const cached2 = cache.get(identity);
37440
+ if (cached2?.stamp === stamp) {
37441
+ return cached2.account;
37442
+ }
37443
+ const account = readAccountMetadata(fs31, identitiesDir, identity);
37444
+ cache.set(identity, { stamp, account });
37445
+ return account;
37446
+ };
37447
+ }
37448
+ var import_node_path24, CLAUDE_JSON, AccountMetadataError;
37449
+ var init_account = __esm({
37450
+ "src/usage/account.ts"() {
37451
+ "use strict";
37452
+ import_node_path24 = __toESM(require("node:path"), 1);
37453
+ init_cliError();
37454
+ init_schema();
37455
+ init_schema2();
37456
+ CLAUDE_JSON = ".claude.json";
37457
+ AccountMetadataError = class extends CliError {
37458
+ constructor(file2, detail) {
37459
+ super(`${file2}: ${detail}, so its account metadata cannot be read.`);
37460
+ this.file = file2;
37461
+ this.name = "AccountMetadataError";
37462
+ }
37463
+ file;
37464
+ };
37465
+ }
37466
+ });
37467
+
37384
37468
  // package.json
37385
37469
  var package_default;
37386
37470
  var init_package = __esm({
37387
37471
  "package.json"() {
37388
37472
  package_default = {
37389
37473
  name: "agent-shim",
37390
- version: "11.74.0",
37474
+ version: "11.75.0",
37391
37475
  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.",
37392
37476
  license: "MIT",
37393
37477
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -37493,90 +37577,6 @@ var init_package = __esm({
37493
37577
  }
37494
37578
  });
37495
37579
 
37496
- // src/usage/account.ts
37497
- function isObject2(value2) {
37498
- return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
37499
- }
37500
- function isIdentityName(name) {
37501
- return IdentitySchema.shape.name.safeParse(name).success;
37502
- }
37503
- function claudeJsonPath(identitiesDir, identity) {
37504
- return import_node_path25.default.join(identitiesDir, identity, CLAUDE_JSON);
37505
- }
37506
- function readAccountMetadata(fs31, identitiesDir, identity) {
37507
- if (!isIdentityName(identity)) {
37508
- throw new Error(`"${identity}" is not a valid identity name.`);
37509
- }
37510
- return readAccountMetadataFile(fs31, claudeJsonPath(identitiesDir, identity));
37511
- }
37512
- function readAccountMetadataFile(fs31, file2) {
37513
- const raw = fs31.readFileUtf8(file2);
37514
- if (raw === void 0) {
37515
- return void 0;
37516
- }
37517
- let parsed;
37518
- try {
37519
- parsed = JSON.parse(raw);
37520
- } catch {
37521
- throw new AccountMetadataError(file2, "not valid JSON");
37522
- }
37523
- if (!isObject2(parsed)) {
37524
- throw new AccountMetadataError(file2, "not a JSON object");
37525
- }
37526
- const oauthAccount = parsed.oauthAccount;
37527
- if (!isObject2(oauthAccount)) {
37528
- return void 0;
37529
- }
37530
- const picked = {};
37531
- for (const key of Object.keys(AccountMetadataSchema.shape)) {
37532
- const value2 = oauthAccount[key];
37533
- if (value2 !== null && value2 !== void 0) {
37534
- picked[key] = value2;
37535
- }
37536
- }
37537
- const account = AccountMetadataSchema.safeParse(picked);
37538
- if (!account.success) {
37539
- throw new AccountMetadataError(file2, account.error.issues.map((issue2) => `${issue2.path.join(".")}: ${issue2.message}`).join("; "));
37540
- }
37541
- return account.data;
37542
- }
37543
- function createAccountReader(fs31, identitiesDir) {
37544
- const cache = /* @__PURE__ */ new Map();
37545
- return (identity) => {
37546
- if (!isIdentityName(identity)) {
37547
- throw new Error(`"${identity}" is not a valid identity name.`);
37548
- }
37549
- const stat = fs31.lstat(claudeJsonPath(identitiesDir, identity));
37550
- const stamp = stat === void 0 ? "absent" : `${String(stat.mtimeMs)}:${String(stat.sizeBytes)}`;
37551
- const cached2 = cache.get(identity);
37552
- if (cached2?.stamp === stamp) {
37553
- return cached2.account;
37554
- }
37555
- const account = readAccountMetadata(fs31, identitiesDir, identity);
37556
- cache.set(identity, { stamp, account });
37557
- return account;
37558
- };
37559
- }
37560
- var import_node_path25, CLAUDE_JSON, AccountMetadataError;
37561
- var init_account = __esm({
37562
- "src/usage/account.ts"() {
37563
- "use strict";
37564
- import_node_path25 = __toESM(require("node:path"), 1);
37565
- init_cliError();
37566
- init_schema();
37567
- init_schema2();
37568
- CLAUDE_JSON = ".claude.json";
37569
- AccountMetadataError = class extends CliError {
37570
- constructor(file2, detail) {
37571
- super(`${file2}: ${detail}, so its account metadata cannot be read.`);
37572
- this.file = file2;
37573
- this.name = "AccountMetadataError";
37574
- }
37575
- file;
37576
- };
37577
- }
37578
- });
37579
-
37580
37580
  // src/usage/plan.ts
37581
37581
  function planOf(account) {
37582
37582
  const userTier = account?.userRateLimitTier;
@@ -117056,7 +117056,7 @@ function resolveLaunchIdentity(paths, cwd) {
117056
117056
  }
117057
117057
 
117058
117058
  // src/identityManager.ts
117059
- var import_node_path24 = __toESM(require("node:path"), 1);
117059
+ var import_node_path25 = __toESM(require("node:path"), 1);
117060
117060
  init_commandDeps();
117061
117061
 
117062
117062
  // src/cli/credentialOption.ts
@@ -117526,6 +117526,71 @@ function registerProfileCommand(program2, deps) {
117526
117526
  // src/identityManager.ts
117527
117527
  init_identity();
117528
117528
  init_realPorts();
117529
+
117530
+ // src/identityAccounts.ts
117531
+ init_account();
117532
+
117533
+ // src/usage/accountDescription.ts
117534
+ function describeAccountOrganisation(account) {
117535
+ const parts = [account.organizationName, account.organizationType].filter((part) => part !== void 0);
117536
+ return parts.length === 0 ? void 0 : parts.join(", ");
117537
+ }
117538
+ function describeAccountPlan(account) {
117539
+ const parts = [account.billingType === void 0 ? void 0 : `billing ${account.billingType}`, account.seatTier === void 0 ? void 0 : `seat tier ${account.seatTier}`].filter((part) => part !== void 0);
117540
+ return parts.length === 0 ? void 0 : parts.join(", ");
117541
+ }
117542
+
117543
+ // src/identityAccounts.ts
117544
+ function readIdentityAccount(fs31, identitiesDir, identity) {
117545
+ try {
117546
+ const account = readAccountMetadata(fs31, identitiesDir, identity);
117547
+ return account === void 0 ? void 0 : { account };
117548
+ } catch (error63) {
117549
+ if (error63 instanceof AccountMetadataError) {
117550
+ return { problem: error63.message };
117551
+ }
117552
+ throw error63;
117553
+ }
117554
+ }
117555
+ function summariseIdentityAccount(account) {
117556
+ const summary = {
117557
+ ...account.emailAddress === void 0 ? {} : { emailAddress: account.emailAddress },
117558
+ ...account.organizationName === void 0 ? {} : { organizationName: account.organizationName },
117559
+ ...account.organizationType === void 0 ? {} : { organizationType: account.organizationType },
117560
+ ...account.organizationRole === void 0 ? {} : { organizationRole: account.organizationRole },
117561
+ ...account.billingType === void 0 ? {} : { billingType: account.billingType },
117562
+ ...account.seatTier === void 0 ? {} : { seatTier: account.seatTier }
117563
+ };
117564
+ return Object.keys(summary).length === 0 ? void 0 : summary;
117565
+ }
117566
+ function loginKeyOf(account) {
117567
+ return account.accountUuid === void 0 ? void 0 : JSON.stringify([account.accountUuid, account.organizationUuid ?? null]);
117568
+ }
117569
+ function groupByLogin(items, loginOf) {
117570
+ const groups = /* @__PURE__ */ new Map();
117571
+ for (const item of items) {
117572
+ const key = loginOf(item) ?? /* @__PURE__ */ Symbol("no login");
117573
+ const group = groups.get(key);
117574
+ if (group === void 0) {
117575
+ groups.set(key, [item]);
117576
+ } else {
117577
+ group.push(item);
117578
+ }
117579
+ }
117580
+ return [...groups.values()].flat();
117581
+ }
117582
+ function describeAccountHolder(summary) {
117583
+ const organisation = describeAccountOrganisation(summary);
117584
+ if (summary.emailAddress === void 0) {
117585
+ return organisation;
117586
+ }
117587
+ return organisation === void 0 ? summary.emailAddress : `${summary.emailAddress} (${organisation})`;
117588
+ }
117589
+ function describeIdentityAccount(summary) {
117590
+ return [describeAccountHolder(summary), summary.organizationRole === void 0 ? void 0 : `role ${summary.organizationRole}`, describeAccountPlan(summary)].filter((part) => part !== void 0).join("; ");
117591
+ }
117592
+
117593
+ // src/identityManager.ts
117529
117594
  async function runIdentityWizard(prompts, paths, name, options = {}) {
117530
117595
  if (!IdentitySchema.safeParse({ name, allowAmbientCredential: false }).success) {
117531
117596
  throw new InvalidIdentityNameError(name);
@@ -117589,28 +117654,43 @@ async function tryRunAtIdentityShortcut(deps, argv) {
117589
117654
  await selectIdentity(deps, token.slice(1));
117590
117655
  return true;
117591
117656
  }
117592
- function toIdentityView(paths, entry) {
117657
+ function toIdentityView(paths, { entry, read }, sharesLoginWith) {
117658
+ const account = read?.account === void 0 ? void 0 : summariseIdentityAccount(read.account);
117593
117659
  return {
117594
117660
  name: entry.name,
117595
117661
  active: entry.isActive,
117596
- directory: import_node_path24.default.join(paths.identitiesDir, entry.name),
117662
+ directory: import_node_path25.default.join(paths.identitiesDir, entry.name),
117597
117663
  ...entry.problem === void 0 ? {
117598
117664
  ...entry.identity.defaultConfigProfile === void 0 ? {} : { defaultConfigProfile: entry.identity.defaultConfigProfile },
117599
117665
  allowAmbientCredential: entry.identity.allowAmbientCredential,
117600
117666
  ...entry.identity.credential === void 0 ? {} : { credential: summariseCredential(entry.identity.credential) },
117601
117667
  ...entry.identity.anchors === void 0 ? {} : { anchors: entry.identity.anchors }
117602
- } : { problem: entry.problem }
117668
+ } : { problem: entry.problem },
117669
+ ...account === void 0 ? {} : { account },
117670
+ ...read?.problem === void 0 ? {} : { accountProblem: read.problem },
117671
+ ...sharesLoginWith.length === 0 ? {} : { sharesLoginWith }
117603
117672
  };
117604
117673
  }
117605
- function formatIdentityLine(entry) {
117674
+ function collectIdentityRows(paths, entries) {
117675
+ const items = entries.map((entry) => ({ entry, read: readIdentityAccount(realFarmFs, paths.identitiesDir, entry.name) }));
117676
+ const loginOf = (item) => item.read?.account === void 0 ? void 0 : loginKeyOf(item.read.account);
117677
+ return groupByLogin(items, loginOf).map((item) => {
117678
+ const login = loginOf(item);
117679
+ const sharing = login === void 0 ? [] : items.filter((other) => other !== item && loginOf(other) === login).map((other) => other.entry.name);
117680
+ return { entry: item.entry, view: toIdentityView(paths, item, sharing) };
117681
+ });
117682
+ }
117683
+ function formatIdentityLine(entry, view) {
117606
117684
  const marker = entry.isActive ? "* " : " ";
117685
+ const account = view.account === void 0 ? "" : ` ${describeIdentityAccount(view.account)}`;
117686
+ const accountProblem = view.accountProblem === void 0 ? "" : ` [account unreadable: ${view.accountProblem}]`;
117607
117687
  if (entry.problem !== void 0) {
117608
- return `${marker}${entry.name} [unreadable: ${entry.problem}]`;
117688
+ return `${marker}${entry.name} [unreadable: ${entry.problem}]${account}${accountProblem}`;
117609
117689
  }
117610
117690
  const defaultProfile = entry.identity.defaultConfigProfile === void 0 ? "" : ` (default profile: ${entry.identity.defaultConfigProfile})`;
117611
117691
  const ambient = entry.identity.allowAmbientCredential ? " [allows ambient credential]" : "";
117612
117692
  const credential = entry.identity.credential === void 0 ? "" : ` [credential ${describeCredential(entry.identity.credential)}]`;
117613
- return `${marker}${entry.name}${defaultProfile}${ambient}${credential}`;
117693
+ return `${marker}${entry.name}${defaultProfile}${ambient}${credential}${account}${accountProblem}`;
117614
117694
  }
117615
117695
  function registerIdentityCommand(program2, deps) {
117616
117696
  const { paths } = deps;
@@ -117630,16 +117710,17 @@ function registerIdentityCommand(program2, deps) {
117630
117710
  withExamples(
117631
117711
  identity.command("list").description("List every identity, marking the active one with *.").option("--json", "Print the identities as JSON.").action((options) => {
117632
117712
  const entries = listIdentities(paths);
117713
+ const rows = collectIdentityRows(paths, entries);
117633
117714
  if (options.json === true) {
117634
- printJson(entries.map((entry) => toIdentityView(paths, entry)));
117715
+ printJson(rows.map((row) => row.view));
117635
117716
  return;
117636
117717
  }
117637
- if (entries.length === 0) {
117718
+ if (rows.length === 0) {
117638
117719
  console.log("No identities yet. Run `agent-shim identity add <name>` to create one.");
117639
117720
  return;
117640
117721
  }
117641
- for (const entry of entries) {
117642
- console.log(formatIdentityLine(entry));
117722
+ for (const row of rows) {
117723
+ console.log(formatIdentityLine(row.entry, row.view));
117643
117724
  }
117644
117725
  if (entries.some((entry) => entry.problem !== void 0)) {
117645
117726
  console.log("\nRun `agent-shim doctor` for the full detail on every unreadable entry.");
@@ -117649,17 +117730,34 @@ function registerIdentityCommand(program2, deps) {
117649
117730
  );
117650
117731
  withExamples(
117651
117732
  identity.command("show <name>").description("Show one identity's settings and directory.").option("--json", "Print the identity as JSON.").action((name, options) => {
117652
- const entry = listIdentities(paths).find((candidate) => candidate.name === name);
117653
- if (entry === void 0) {
117733
+ const row = collectIdentityRows(paths, listIdentities(paths)).find((candidate) => candidate.entry.name === name);
117734
+ if (row === void 0) {
117654
117735
  throw new IdentityNotFoundError(name);
117655
117736
  }
117656
- const view = toIdentityView(paths, entry);
117737
+ const { entry, view } = row;
117657
117738
  if (options.json === true) {
117658
117739
  printJson(view);
117659
117740
  return;
117660
117741
  }
117661
117742
  console.log(`Identity: ${view.name}${view.active ? " (active)" : ""}`);
117662
117743
  console.log(`Directory: ${view.directory}`);
117744
+ const holder = view.account === void 0 ? void 0 : describeAccountHolder(view.account);
117745
+ if (holder !== void 0) {
117746
+ console.log(`Account: ${holder}`);
117747
+ }
117748
+ if (view.account?.organizationRole !== void 0) {
117749
+ console.log(`Role: ${view.account.organizationRole}`);
117750
+ }
117751
+ const plan = view.account === void 0 ? void 0 : describeAccountPlan(view.account);
117752
+ if (plan !== void 0) {
117753
+ console.log(`Plan: ${plan}`);
117754
+ }
117755
+ if (view.accountProblem !== void 0) {
117756
+ console.log(`Account unreadable: ${view.accountProblem}`);
117757
+ }
117758
+ if (view.sharesLoginWith !== void 0) {
117759
+ console.log(`Shares login with: ${view.sharesLoginWith.join(", ")}`);
117760
+ }
117663
117761
  if (view.problem !== void 0) {
117664
117762
  console.log(`Unreadable: ${view.problem}`);
117665
117763
  return;
@@ -117752,7 +117850,7 @@ function registerIdentityCommand(program2, deps) {
117752
117850
  if (!identityExists(paths, name)) {
117753
117851
  throw new IdentityNotFoundError(name);
117754
117852
  }
117755
- await confirmRemoval(deps, options.yes, `identity "${name}" and its directory ${import_node_path24.default.join(paths.identitiesDir, name)}`);
117853
+ await confirmRemoval(deps, options.yes, `identity "${name}" and its directory ${import_node_path25.default.join(paths.identitiesDir, name)}`);
117756
117854
  removeIdentity(paths, name);
117757
117855
  reportMutation(options.json, { action: "removed", kind: "identity", name }, () => {
117758
117856
  console.log(`Removed identity "${name}".`);
@@ -157346,9 +157444,9 @@ function formatAccounts(views) {
157346
157444
  if (account === void 0) {
157347
157445
  lines.push("Account: (no stored login profile: never logged in, or a setup-token identity, which has no profile scope)");
157348
157446
  } else {
157349
- const organisation = [account.organizationName, account.organizationType].filter((part) => part !== void 0).join(", ");
157447
+ const organisation = describeAccountOrganisation(account);
157350
157448
  lines.push(
157351
- `Account: ${account.emailAddress ?? "(no email)"}${organisation === "" ? "" : ` (${organisation})`}`,
157449
+ `Account: ${account.emailAddress ?? "(no email)"}${organisation === void 0 ? "" : ` (${organisation})`}`,
157352
157450
  `Plan: billing ${account.billingType ?? "unknown"}, seat tier ${account.seatTier ?? "none"}`,
157353
157451
  `Rate-limit tier: organisation ${account.organizationRateLimitTier ?? "unknown"}, user ${account.userRateLimitTier ?? "unknown"}`,
157354
157452
  `Extra usage: ${account.hasExtraUsageEnabled === void 0 ? "unknown" : account.hasExtraUsageEnabled ? "enabled" : "disabled"}`
package/dist/index.cjs CHANGED
@@ -4762,7 +4762,7 @@ var init_package = __esm({
4762
4762
  "package.json"() {
4763
4763
  package_default = {
4764
4764
  name: "agent-shim",
4765
- version: "11.74.0",
4765
+ version: "11.75.0",
4766
4766
  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
4767
  license: "MIT",
4768
4768
  author: "Joseph Mearman <joseph@mearman.co.uk>",
package/dist/index.mjs CHANGED
@@ -4738,7 +4738,7 @@ var init_package = __esm({
4738
4738
  "package.json"() {
4739
4739
  package_default = {
4740
4740
  name: "agent-shim",
4741
- version: "11.74.0",
4741
+ version: "11.75.0",
4742
4742
  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
4743
  license: "MIT",
4744
4744
  author: "Joseph Mearman <joseph@mearman.co.uk>",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-shim",
3
- "version": "11.74.0",
3
+ "version": "11.75.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>",