claude-use 11.55.0 → 11.56.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
@@ -29545,11 +29545,59 @@ function hasDesktopSession() {
29545
29545
  const result = (0, import_node_child_process2.spawnSync)("launchctl", ["managername"], { encoding: "utf8" });
29546
29546
  return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
29547
29547
  }
29548
+ return hasDisplayServer();
29549
+ }
29550
+ function hasDisplayServer() {
29548
29551
  if (process.platform === "win32") {
29549
29552
  return false;
29550
29553
  }
29551
29554
  return (process.env.DISPLAY ?? "") !== "" || (process.env.WAYLAND_DISPLAY ?? "") !== "";
29552
29555
  }
29556
+ async function hasDesktopSessionAsync() {
29557
+ if (process.platform !== "darwin") {
29558
+ return hasDisplayServer();
29559
+ }
29560
+ return await new Promise((resolve2) => {
29561
+ (0, import_node_child_process2.execFile)("launchctl", ["managername"], { encoding: "utf8" }, (error63, stdout2) => {
29562
+ resolve2(error63 === null && stdout2.trim() === MACOS_GUI_SESSION_MANAGER);
29563
+ });
29564
+ });
29565
+ }
29566
+ async function runCredentialCommand(argv, options) {
29567
+ const [command, ...args] = argv;
29568
+ return await new Promise((resolve2) => {
29569
+ const child = (0, import_node_child_process2.spawn)(command, args, { stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"] });
29570
+ let stdout2 = "";
29571
+ let stderr = "";
29572
+ let timedOut = false;
29573
+ const timer = setTimeout(() => {
29574
+ timedOut = true;
29575
+ child.kill();
29576
+ }, options.timeoutMs);
29577
+ let settled = false;
29578
+ const settle2 = (result) => {
29579
+ if (!settled) {
29580
+ settled = true;
29581
+ clearTimeout(timer);
29582
+ resolve2(result);
29583
+ }
29584
+ };
29585
+ child.stdout?.setEncoding("utf8");
29586
+ child.stdout?.on("data", (chunk2) => {
29587
+ stdout2 += chunk2;
29588
+ });
29589
+ child.stderr?.setEncoding("utf8");
29590
+ child.stderr?.on("data", (chunk2) => {
29591
+ stderr += chunk2;
29592
+ });
29593
+ child.once("error", (error63) => {
29594
+ settle2({ status: null, stdout: "", stderr: error63.message, timedOut: false });
29595
+ });
29596
+ child.once("close", (status) => {
29597
+ settle2(timedOut ? { status: null, stdout: "", stderr: "", timedOut: true } : { status, stdout: stdout2, stderr: options.interactive ? "" : stderr, timedOut: false });
29598
+ });
29599
+ });
29600
+ }
29553
29601
  function resolveGitBranch(run, cwd) {
29554
29602
  const result = run.run("git", ["-C", cwd, "rev-parse", "--abbrev-ref", "HEAD"]);
29555
29603
  if (result.status !== 0) {
@@ -29746,7 +29794,7 @@ function realResolveClaudeBinary(isOwnBinary) {
29746
29794
  function realInstalledClaudeVersions() {
29747
29795
  return installedVersions(listVersionsDir(defaultVersionsDir()));
29748
29796
  }
29749
- var import_node_child_process2, import_node_crypto4, import_node_fs3, import_node_os2, import_node_path9, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, KEY_POLL_MS, CTRL_C_BYTE, realHoldPort, LINE_FEED, UTF8_CONTINUATION_MASK, UTF8_CONTINUATION_BITS, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
29797
+ var import_node_child_process2, import_node_crypto4, import_node_fs3, import_node_os2, import_node_path9, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, KEY_POLL_MS, CTRL_C_BYTE, realHoldPort, LINE_FEED, UTF8_CONTINUATION_MASK, UTF8_CONTINUATION_BITS, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, realAsyncCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
29750
29798
  var init_realPorts = __esm({
29751
29799
  "src/realPorts.ts"() {
29752
29800
  "use strict";
@@ -29962,6 +30010,11 @@ var init_realPorts = __esm({
29962
30010
  },
29963
30011
  personPresent: () => process.stdin.isTTY || hasDesktopSession()
29964
30012
  };
30013
+ realAsyncCredentialPort = {
30014
+ readSecretFile: (filePath) => realCredentialPort.readSecretFile(filePath),
30015
+ runCommand: runCredentialCommand,
30016
+ personPresent: async () => process.stdin.isTTY || await hasDesktopSessionAsync()
30017
+ };
29965
30018
  SOCKET_PERMISSION_BITS = 4095;
29966
30019
  realHeadroomSocketTrust = {
29967
30020
  platform: process.platform,
@@ -35365,51 +35418,87 @@ function unpackKeyringToken(raw) {
35365
35418
  }
35366
35419
  return trimmed;
35367
35420
  }
35368
- function trySource(source, params) {
35369
- const none = (reason, warn = false) => ({ ok: false, reason, warn });
35421
+ function declined(reason, warn = false) {
35422
+ return { ok: false, reason, warn };
35423
+ }
35424
+ function isCommandBacked(source) {
35425
+ return "command" in source || "op" in source || "keychain" in source;
35426
+ }
35427
+ function immediateOutcome(source, params) {
35370
35428
  if ("env" in source) {
35371
35429
  const value2 = params.env[source.env];
35372
- return value2 === void 0 || value2 === "" ? none("is unset or empty") : { ok: true, token: unpackKeyringToken(value2) };
35430
+ return value2 === void 0 || value2 === "" ? declined("is unset or empty") : { ok: true, token: unpackKeyringToken(value2) };
35373
35431
  }
35374
35432
  if ("literal" in source) {
35375
35433
  return { ok: true, token: source.literal };
35376
35434
  }
35377
- if ("file" in source) {
35378
- const read = params.port.readSecretFile(source.file);
35379
- if (!read.found) {
35380
- return none("does not exist");
35381
- }
35382
- if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
35383
- return none(
35384
- `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS2).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
35385
- true
35386
- );
35387
- }
35388
- const token2 = unpackKeyringToken(read.content.trim());
35389
- return token2 === "" ? none("is empty") : { ok: true, token: token2 };
35435
+ const read = params.port.readSecretFile(source.file);
35436
+ if (!read.found) {
35437
+ return declined("does not exist");
35390
35438
  }
35391
- const argv = commandArgv(source);
35392
- const interactive = isInteractiveSource(source, params.env);
35393
- if (interactive && !params.port.personPresent()) {
35394
- return none("needs a person to approve it, but there is no terminal or desktop session");
35439
+ if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
35440
+ return declined(
35441
+ `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS2).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
35442
+ true
35443
+ );
35395
35444
  }
35396
- const timeoutMs = source.timeoutMs ?? (interactive ? CREDENTIAL_INTERACTIVE_TIMEOUT_MS : CREDENTIAL_COMMAND_TIMEOUT_MS);
35397
- const result = params.port.runCommand(argv, { timeoutMs, interactive });
35445
+ const token = unpackKeyringToken(read.content.trim());
35446
+ return token === "" ? declined("is empty") : { ok: true, token };
35447
+ }
35448
+ function commandRunOf(source, env) {
35449
+ const interactive = isInteractiveSource(source, env);
35450
+ return { argv: commandArgv(source), interactive, timeoutMs: source.timeoutMs ?? (interactive ? CREDENTIAL_INTERACTIVE_TIMEOUT_MS : CREDENTIAL_COMMAND_TIMEOUT_MS) };
35451
+ }
35452
+ function commandOutcome(result, timeoutMs) {
35398
35453
  if (result.timedOut) {
35399
- return none(`timed out after ${String(timeoutMs)}ms`);
35454
+ return declined(`timed out after ${String(timeoutMs)}ms`);
35400
35455
  }
35401
35456
  if (result.status !== 0) {
35402
35457
  const stderr = result.stderr.trim();
35403
35458
  const outcome = result.status === null ? "could not be run or was killed by a signal" : `exited with status ${String(result.status)}`;
35404
- return none(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
35459
+ return declined(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
35405
35460
  }
35406
35461
  const token = unpackKeyringToken(result.stdout.trim());
35407
- return token === "" ? none("printed no token") : { ok: true, token };
35462
+ return token === "" ? declined("printed no token") : { ok: true, token };
35463
+ }
35464
+ function trySource(source, params) {
35465
+ if (!isCommandBacked(source)) {
35466
+ return immediateOutcome(source, params);
35467
+ }
35468
+ const run = commandRunOf(source, params.env);
35469
+ if (run.interactive && !params.port.personPresent()) {
35470
+ return declined(NO_PERSON_REASON);
35471
+ }
35472
+ return commandOutcome(params.port.runCommand(run.argv, { timeoutMs: run.timeoutMs, interactive: run.interactive }), run.timeoutMs);
35473
+ }
35474
+ async function trySourceAsync(source, params) {
35475
+ if (!isCommandBacked(source)) {
35476
+ return immediateOutcome(source, params);
35477
+ }
35478
+ const run = commandRunOf(source, params.env);
35479
+ if (run.interactive && !await params.port.personPresent()) {
35480
+ return declined(NO_PERSON_REASON);
35481
+ }
35482
+ return commandOutcome(await params.port.runCommand(run.argv, { timeoutMs: run.timeoutMs, interactive: run.interactive }), run.timeoutMs);
35408
35483
  }
35409
35484
  function warmCommandFor(subject) {
35410
35485
  const [kind, name] = subject.split(" ");
35411
35486
  return kind === "provider" ? `agent-shim credential warm --provider ${name ?? ""}` : `agent-shim credential warm ${name ?? ""}`;
35412
35487
  }
35488
+ function cachedResolution(target, entry) {
35489
+ return { ok: true, credential: { target, token: entry.token, source: entry.source, warnings: [], cachedAt: entry.fetchedAt } };
35490
+ }
35491
+ function liveResolution(target, token, source, warnings) {
35492
+ return { ok: true, credential: { target, token, source, warnings } };
35493
+ }
35494
+ function unresolved(subject, cacheBlock, attempts) {
35495
+ const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(subject)}\``;
35496
+ return { ok: false, message: `agent-shim: ${subject} has no usable credential: ${attempts.join("; ")}${hint}` };
35497
+ }
35498
+ function declinedLine(source, outcome, subject) {
35499
+ const attempt = `${describeSource(source)} ${outcome.reason}`;
35500
+ return { attempt, warning: outcome.warn ? `agent-shim: ${subject}: skipped ${attempt}` : void 0 };
35501
+ }
35413
35502
  function resolveCredential(params) {
35414
35503
  const target = params.credential.target ?? "bearer";
35415
35504
  const cacheBlock = params.credential.cache;
@@ -35418,7 +35507,7 @@ function resolveCredential(params) {
35418
35507
  if (cacheBlock !== void 0 && cache !== void 0 && store !== void 0 && params.refresh !== true) {
35419
35508
  const entry = cache.port.read(store, params.subject);
35420
35509
  if (entry !== void 0 && isFresh(entry, cacheBlock, cache.now())) {
35421
- return { ok: true, credential: { target, token: entry.token, source: entry.source, warnings: [], cachedAt: entry.fetchedAt } };
35510
+ return cachedResolution(target, entry);
35422
35511
  }
35423
35512
  }
35424
35513
  const attempts = [];
@@ -35429,16 +35518,59 @@ function resolveCredential(params) {
35429
35518
  if (cache !== void 0 && store !== void 0) {
35430
35519
  cache.port.write(store, params.subject, { token: outcome.token, fetchedAt: cache.now(), source });
35431
35520
  }
35432
- return { ok: true, credential: { target, token: outcome.token, source, warnings } };
35521
+ return liveResolution(target, outcome.token, source, warnings);
35522
+ }
35523
+ const line = declinedLine(source, outcome, params.subject);
35524
+ attempts.push(line.attempt);
35525
+ if (line.warning !== void 0) {
35526
+ warnings.push(line.warning);
35527
+ }
35528
+ }
35529
+ return unresolved(params.subject, cacheBlock, attempts);
35530
+ }
35531
+ async function resolveCredentialAsync(params) {
35532
+ const target = params.credential.target ?? "bearer";
35533
+ const cacheBlock = params.credential.cache;
35534
+ const cache = cacheBlock === void 0 ? void 0 : params.port.cache;
35535
+ const store = cacheBlock === void 0 || cache === void 0 ? void 0 : effectiveStore(cacheBlock, cache.platform);
35536
+ if (cacheBlock !== void 0 && cache !== void 0 && store !== void 0 && params.refresh !== true) {
35537
+ const entry = await cache.port.read(store, params.subject);
35538
+ if (entry !== void 0 && isFresh(entry, cacheBlock, cache.now())) {
35539
+ return cachedResolution(target, entry);
35540
+ }
35541
+ }
35542
+ const attempts = [];
35543
+ const warnings = [];
35544
+ for (const source of params.credential.sources) {
35545
+ const outcome = await trySourceAsync(source, params);
35546
+ if (outcome.ok) {
35547
+ if (cache !== void 0 && store !== void 0) {
35548
+ await cache.port.write(store, params.subject, { token: outcome.token, fetchedAt: cache.now(), source });
35549
+ }
35550
+ return liveResolution(target, outcome.token, source, warnings);
35433
35551
  }
35434
- const line = `${describeSource(source)} ${outcome.reason}`;
35435
- attempts.push(line);
35436
- if (outcome.warn) {
35437
- warnings.push(`agent-shim: ${params.subject}: skipped ${line}`);
35552
+ const line = declinedLine(source, outcome, params.subject);
35553
+ attempts.push(line.attempt);
35554
+ if (line.warning !== void 0) {
35555
+ warnings.push(line.warning);
35438
35556
  }
35439
35557
  }
35440
- const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(params.subject)}\``;
35441
- return { ok: false, message: `agent-shim: ${params.subject} has no usable credential: ${attempts.join("; ")}${hint}` };
35558
+ return unresolved(params.subject, cacheBlock, attempts);
35559
+ }
35560
+ function shareInFlightResolutions(resolve2) {
35561
+ const inFlight = /* @__PURE__ */ new Map();
35562
+ return async (params) => {
35563
+ const key = JSON.stringify([params.subject, params.credential, params.refresh === true]);
35564
+ const running = inFlight.get(key);
35565
+ if (running !== void 0) {
35566
+ return await running;
35567
+ }
35568
+ const started = resolve2(params).finally(() => {
35569
+ inFlight.delete(key);
35570
+ });
35571
+ inFlight.set(key, started);
35572
+ return await started;
35573
+ };
35442
35574
  }
35443
35575
  function credentialVariables(target, token) {
35444
35576
  return {
@@ -35447,7 +35579,7 @@ function credentialVariables(target, token) {
35447
35579
  CLAUDE_CODE_OAUTH_TOKEN: target === "oauthToken" ? token : void 0
35448
35580
  };
35449
35581
  }
35450
- var CREDENTIAL_UNAVAILABLE_EXIT, CREDENTIAL_COMMAND_TIMEOUT_MS, CREDENTIAL_INTERACTIVE_TIMEOUT_MS, GROUP_OTHER_PERMISSION_BITS, PERMISSION_BITS2, OCTAL_RADIX2, GO_KEYRING_BASE64_PREFIX;
35582
+ var CREDENTIAL_UNAVAILABLE_EXIT, CREDENTIAL_COMMAND_TIMEOUT_MS, CREDENTIAL_INTERACTIVE_TIMEOUT_MS, GROUP_OTHER_PERMISSION_BITS, PERMISSION_BITS2, OCTAL_RADIX2, GO_KEYRING_BASE64_PREFIX, NO_PERSON_REASON;
35451
35583
  var init_credential = __esm({
35452
35584
  "src/credential.ts"() {
35453
35585
  "use strict";
@@ -35459,6 +35591,7 @@ var init_credential = __esm({
35459
35591
  PERMISSION_BITS2 = 511;
35460
35592
  OCTAL_RADIX2 = 8;
35461
35593
  GO_KEYRING_BASE64_PREFIX = "go-keyring-base64:";
35594
+ NO_PERSON_REASON = "needs a person to approve it, but there is no terminal or desktop session";
35462
35595
  }
35463
35596
  });
35464
35597
 
@@ -36633,7 +36766,7 @@ var init_package = __esm({
36633
36766
  "package.json"() {
36634
36767
  package_default = {
36635
36768
  name: "claude-use",
36636
- version: "11.55.0",
36769
+ version: "11.56.0",
36637
36770
  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.",
36638
36771
  license: "MIT",
36639
36772
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -38070,6 +38203,30 @@ function security(args, stdin2) {
38070
38203
  const result = (0, import_node_child_process3.spawnSync)("security", args, { encoding: "utf8", ...stdin2 === void 0 ? {} : { input: stdin2 }, stdio: ["pipe", "pipe", "ignore"] });
38071
38204
  return { status: result.status, stdout: result.stdout };
38072
38205
  }
38206
+ async function securityAsync(args, stdin2) {
38207
+ return await new Promise((resolve2) => {
38208
+ const child = (0, import_node_child_process3.spawn)("security", args, { stdio: ["pipe", "pipe", "ignore"] });
38209
+ let stdout2 = "";
38210
+ let settled = false;
38211
+ const settle2 = (status) => {
38212
+ if (!settled) {
38213
+ settled = true;
38214
+ resolve2({ status, stdout: stdout2 });
38215
+ }
38216
+ };
38217
+ child.stdout.setEncoding("utf8");
38218
+ child.stdout.on("data", (chunk2) => {
38219
+ stdout2 += chunk2;
38220
+ });
38221
+ child.stdin.on("error", () => {
38222
+ });
38223
+ child.stdin.end(stdin2);
38224
+ child.once("error", () => {
38225
+ settle2(null);
38226
+ });
38227
+ child.once("close", settle2);
38228
+ });
38229
+ }
38073
38230
  function createRealCredentialCache(root) {
38074
38231
  const dir = import_node_path29.default.join(root, "credential-cache");
38075
38232
  const filePath = (owner) => import_node_path29.default.join(dir, cacheFileNameFor(owner));
@@ -38118,6 +38275,46 @@ function createRealCredentialCache(root) {
38118
38275
  function realCredentialCacheEnv(paths) {
38119
38276
  return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
38120
38277
  }
38278
+ function createAsyncRealCredentialCache(root) {
38279
+ const dir = import_node_path29.default.join(root, "credential-cache");
38280
+ const filePath = (owner) => import_node_path29.default.join(dir, cacheFileNameFor(owner));
38281
+ return {
38282
+ async read(store, owner) {
38283
+ if (store === "file") {
38284
+ try {
38285
+ return parseEntry(await import_node_fs9.default.promises.readFile(filePath(owner), "utf8"));
38286
+ } catch {
38287
+ return void 0;
38288
+ }
38289
+ }
38290
+ requireKeychain();
38291
+ const result = await securityAsync(["find-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner, "-w"]);
38292
+ return result.status === 0 ? parseEntry(Buffer.from(result.stdout.trim(), "base64").toString("utf8")) : void 0;
38293
+ },
38294
+ async write(store, owner, entry) {
38295
+ const serialised = JSON.stringify(entry);
38296
+ if (store === "file") {
38297
+ await import_node_fs9.default.promises.mkdir(dir, { recursive: true, mode: CACHE_DIR_MODE });
38298
+ await import_node_fs9.default.promises.chmod(dir, CACHE_DIR_MODE);
38299
+ const target = filePath(owner);
38300
+ const temp = `${target}.${String(process.pid)}.tmp`;
38301
+ await import_node_fs9.default.promises.writeFile(temp, serialised, { mode: CACHE_FILE_MODE });
38302
+ await import_node_fs9.default.promises.rename(temp, target);
38303
+ return;
38304
+ }
38305
+ requireKeychain();
38306
+ const encoded = Buffer.from(serialised, "utf8").toString("base64");
38307
+ const result = await securityAsync(["-i"], `add-generic-password -U -s ${KEYCHAIN_CACHE_SERVICE} -a ${JSON.stringify(owner)} -w ${encoded}
38308
+ `);
38309
+ if (result.status !== 0) {
38310
+ throw new Error(`could not write the keychain credential cache for ${owner}`);
38311
+ }
38312
+ }
38313
+ };
38314
+ }
38315
+ function realAsyncCredentialCacheEnv(paths) {
38316
+ return { port: createAsyncRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
38317
+ }
38121
38318
  var import_node_child_process3, import_node_fs9, import_node_path29, KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
38122
38319
  var init_realCredentialCache = __esm({
38123
38320
  "src/realCredentialCache.ts"() {
@@ -68677,13 +68874,13 @@ function resolveLaunch(params) {
68677
68874
  environment
68678
68875
  };
68679
68876
  }
68680
- function runLaunchPlan(plan, spawn8) {
68877
+ function runLaunchPlan(plan, spawn9) {
68681
68878
  try {
68682
68879
  if (plan.hold() === "cancelled") {
68683
68880
  return LAUNCH_CANCELLED_EXIT;
68684
68881
  }
68685
68882
  plan.markChildStarted();
68686
- const result = spawn8.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
68883
+ const result = spawn9.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
68687
68884
  if (result.error !== void 0) {
68688
68885
  throw result.error;
68689
68886
  }
@@ -69171,7 +69368,7 @@ function createQuotaRefresher(deps) {
69171
69368
  const fetchNow = async (identity, provider, lookup, adapter) => {
69172
69369
  const key = `${identity}\0${provider}`;
69173
69370
  try {
69174
- const apiKey = lookup.apiKey();
69371
+ const apiKey = await lookup.apiKey();
69175
69372
  const quota = await adapter.fetch(apiKey, deps.http, AbortSignal.timeout(QUOTA_REQUEST_TIMEOUT_MS), deps.now());
69176
69373
  if (!deps.record(identity, provider, quota)) {
69177
69374
  return { status: "no-usage" };
@@ -69241,8 +69438,8 @@ function createProviderLookup(ports) {
69241
69438
  }
69242
69439
  return {
69243
69440
  baseUrl,
69244
- apiKey: () => {
69245
- const resolution = resolveCredential({ credential: isRouterProvider(definition) ? { sources: [] } : definition.credential, env: ports.env, port: ports.credentials, subject: `provider ${name}` });
69441
+ apiKey: async () => {
69442
+ const resolution = await resolveCredentialAsync({ credential: isRouterProvider(definition) ? { sources: [] } : definition.credential, env: ports.env, port: ports.credentials, subject: `provider ${name}` });
69246
69443
  if (!resolution.ok) {
69247
69444
  throw new Error(resolution.message);
69248
69445
  }
@@ -132748,7 +132945,7 @@ function createAntigravityRoute(ports) {
132748
132945
  body: JSON.stringify({ type: "error", error: { type: "not_found_error", message: "no provider specified in path" } })
132749
132946
  };
132750
132947
  }
132751
- const lookup = ports.loadProvider(providerName);
132948
+ const lookup = await ports.loadProvider(providerName);
132752
132949
  if (!lookup.ok) {
132753
132950
  return {
132754
132951
  status: lookup.status,
@@ -133262,6 +133459,7 @@ function resolveAccountTarget(model, models) {
133262
133459
  }
133263
133460
  function createProviderRouteResolver(deps) {
133264
133461
  const oauthRoute = createPassthroughRoute("anthropic", { baseUrl: `https://${CONNECT_INTERCEPT_HOST}:${String(HTTPS_PORT)}`, stripPrefix: void 0, headroomUpstream: void 0 });
133462
+ const resolveCredential2 = shareInFlightResolutions(resolveCredentialAsync);
133265
133463
  const antigravityQuotaSources = /* @__PURE__ */ new Map();
133266
133464
  const antigravityRoutingMemory = /* @__PURE__ */ new Map();
133267
133465
  const definesProvider = (name) => {
@@ -133290,7 +133488,7 @@ function createProviderRouteResolver(deps) {
133290
133488
  const source = createCachedAntigravityQuotaSource({
133291
133489
  now: () => Date.now(),
133292
133490
  fetchSummary: async (nowMs) => {
133293
- const res = resolveCredential({ credential: definition.credential, env: deps.env, port: deps.credentials, subject: `provider ${provider}` });
133491
+ const res = await resolveCredential2({ credential: definition.credential, env: deps.env, port: deps.credentials, subject: `provider ${provider}` });
133294
133492
  if (!res.ok) {
133295
133493
  return void 0;
133296
133494
  }
@@ -133356,8 +133554,8 @@ function createProviderRouteResolver(deps) {
133356
133554
  ok: true,
133357
133555
  route: createAntigravityRouteMount(
133358
133556
  {
133359
- loadProvider: () => {
133360
- const res = resolveCredential({
133557
+ loadProvider: async () => {
133558
+ const res = await resolveCredential2({
133361
133559
  credential: antigravityProvider.credential,
133362
133560
  env: deps.env,
133363
133561
  port: deps.credentials,
@@ -133393,7 +133591,7 @@ function createProviderRouteResolver(deps) {
133393
133591
  stripPrefix: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(provider)}`,
133394
133592
  headroomUpstream: directOrigin2(deps.directPort())
133395
133593
  }),
133396
- { provider, credential: httpProvider.credential, env: deps.env, port: deps.credentials }
133594
+ { provider, credential: httpProvider.credential, env: deps.env, port: deps.credentials, resolve: resolveCredential2 }
133397
133595
  )
133398
133596
  };
133399
133597
  };
@@ -133539,7 +133737,7 @@ function attachingProviderCredential(route, deps) {
133539
133737
  headroomEligible: route.headroomEligible,
133540
133738
  headroomUpstream: route.headroomUpstream,
133541
133739
  serve: async (request7, response) => {
133542
- const resolution = resolveCredential({ credential: deps.credential, env: deps.env, port: deps.port, subject: `provider ${deps.provider}` });
133740
+ const resolution = await deps.resolve({ credential: deps.credential, env: deps.env, port: deps.port, subject: `provider ${deps.provider}` });
133543
133741
  if (!resolution.ok) {
133544
133742
  response.start(HTTP_STATUS.badGateway, { "Content-Type": "application/json" });
133545
133743
  await response.write(
@@ -136581,7 +136779,7 @@ init_read();
136581
136779
  function createRealQuotaRefresher(params) {
136582
136780
  const { paths, store, log } = params;
136583
136781
  return createQuotaRefresher({
136584
- lookup: createProviderLookup({ fs: realFsPort, providersDir: paths.providersDir, env: process.env, credentials: realCredentialPort }),
136782
+ lookup: createProviderLookup({ fs: realFsPort, providersDir: paths.providersDir, env: process.env, credentials: realAsyncCredentialPort }),
136585
136783
  http: realQuotaHttpGet,
136586
136784
  readQuota: (identity, provider) => {
136587
136785
  try {
@@ -136699,7 +136897,7 @@ function realFrontDoorSupervisorPorts(paths, respawnGeneration, retire, trackTun
136699
136897
  directPort: () => directPort,
136700
136898
  // The same port (cache included) the launcher resolves a launch's provider with, so the credential the door attaches at the route and the one the launcher handed the child are the same resolution of the same block.
136701
136899
  env: process.env,
136702
- credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
136900
+ credentials: { ...realAsyncCredentialPort, cache: realAsyncCredentialCacheEnv(paths) },
136703
136901
  usageSnapshotOf: (identity) => identity === void 0 ? void 0 : routingSnapshots.get(identity) ?? readUsageSnapshot(realFarmFs, paths.usageSnapshotsDir, identity),
136704
136902
  // An `acct:` model member is served by relaunch: the door leaves a move request for the session's supervisor (found across every pool's registry, since the door does not know which pool launched the session) and answers the request with what is happening. A session nothing supervises gets the message naming the command to run instead.
136705
136903
  observations: (target) => observations.observation(target),
package/dist/index.cjs CHANGED
@@ -4450,7 +4450,7 @@ var init_package = __esm({
4450
4450
  "package.json"() {
4451
4451
  package_default = {
4452
4452
  name: "claude-use",
4453
- version: "11.55.0",
4453
+ version: "11.56.0",
4454
4454
  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.",
4455
4455
  license: "MIT",
4456
4456
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -5737,6 +5737,9 @@ function hasDesktopSession() {
5737
5737
  const result = (0, import_node_child_process2.spawnSync)("launchctl", ["managername"], { encoding: "utf8" });
5738
5738
  return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
5739
5739
  }
5740
+ return hasDisplayServer();
5741
+ }
5742
+ function hasDisplayServer() {
5740
5743
  if (process.platform === "win32") {
5741
5744
  return false;
5742
5745
  }
@@ -8308,51 +8311,77 @@ function unpackKeyringToken(raw) {
8308
8311
  }
8309
8312
  return trimmed;
8310
8313
  }
8311
- function trySource(source, params) {
8312
- const none = (reason, warn = false) => ({ ok: false, reason, warn });
8314
+ function declined(reason, warn = false) {
8315
+ return { ok: false, reason, warn };
8316
+ }
8317
+ function isCommandBacked(source) {
8318
+ return "command" in source || "op" in source || "keychain" in source;
8319
+ }
8320
+ function immediateOutcome(source, params) {
8313
8321
  if ("env" in source) {
8314
8322
  const value = params.env[source.env];
8315
- return value === void 0 || value === "" ? none("is unset or empty") : { ok: true, token: unpackKeyringToken(value) };
8323
+ return value === void 0 || value === "" ? declined("is unset or empty") : { ok: true, token: unpackKeyringToken(value) };
8316
8324
  }
8317
8325
  if ("literal" in source) {
8318
8326
  return { ok: true, token: source.literal };
8319
8327
  }
8320
- if ("file" in source) {
8321
- const read = params.port.readSecretFile(source.file);
8322
- if (!read.found) {
8323
- return none("does not exist");
8324
- }
8325
- if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
8326
- return none(
8327
- `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS2).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
8328
- true
8329
- );
8330
- }
8331
- const token2 = unpackKeyringToken(read.content.trim());
8332
- return token2 === "" ? none("is empty") : { ok: true, token: token2 };
8328
+ const read = params.port.readSecretFile(source.file);
8329
+ if (!read.found) {
8330
+ return declined("does not exist");
8333
8331
  }
8334
- const argv = commandArgv(source);
8335
- const interactive = isInteractiveSource(source, params.env);
8336
- if (interactive && !params.port.personPresent()) {
8337
- return none("needs a person to approve it, but there is no terminal or desktop session");
8332
+ if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
8333
+ return declined(
8334
+ `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS2).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
8335
+ true
8336
+ );
8338
8337
  }
8339
- const timeoutMs = source.timeoutMs ?? (interactive ? CREDENTIAL_INTERACTIVE_TIMEOUT_MS : CREDENTIAL_COMMAND_TIMEOUT_MS);
8340
- const result = params.port.runCommand(argv, { timeoutMs, interactive });
8338
+ const token = unpackKeyringToken(read.content.trim());
8339
+ return token === "" ? declined("is empty") : { ok: true, token };
8340
+ }
8341
+ function commandRunOf(source, env) {
8342
+ const interactive = isInteractiveSource(source, env);
8343
+ return { argv: commandArgv(source), interactive, timeoutMs: source.timeoutMs ?? (interactive ? CREDENTIAL_INTERACTIVE_TIMEOUT_MS : CREDENTIAL_COMMAND_TIMEOUT_MS) };
8344
+ }
8345
+ function commandOutcome(result, timeoutMs) {
8341
8346
  if (result.timedOut) {
8342
- return none(`timed out after ${String(timeoutMs)}ms`);
8347
+ return declined(`timed out after ${String(timeoutMs)}ms`);
8343
8348
  }
8344
8349
  if (result.status !== 0) {
8345
8350
  const stderr = result.stderr.trim();
8346
8351
  const outcome = result.status === null ? "could not be run or was killed by a signal" : `exited with status ${String(result.status)}`;
8347
- return none(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
8352
+ return declined(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
8348
8353
  }
8349
8354
  const token = unpackKeyringToken(result.stdout.trim());
8350
- return token === "" ? none("printed no token") : { ok: true, token };
8355
+ return token === "" ? declined("printed no token") : { ok: true, token };
8356
+ }
8357
+ function trySource(source, params) {
8358
+ if (!isCommandBacked(source)) {
8359
+ return immediateOutcome(source, params);
8360
+ }
8361
+ const run = commandRunOf(source, params.env);
8362
+ if (run.interactive && !params.port.personPresent()) {
8363
+ return declined(NO_PERSON_REASON);
8364
+ }
8365
+ return commandOutcome(params.port.runCommand(run.argv, { timeoutMs: run.timeoutMs, interactive: run.interactive }), run.timeoutMs);
8351
8366
  }
8352
8367
  function warmCommandFor(subject) {
8353
8368
  const [kind, name] = subject.split(" ");
8354
8369
  return kind === "provider" ? `agent-shim credential warm --provider ${name ?? ""}` : `agent-shim credential warm ${name ?? ""}`;
8355
8370
  }
8371
+ function cachedResolution(target, entry) {
8372
+ return { ok: true, credential: { target, token: entry.token, source: entry.source, warnings: [], cachedAt: entry.fetchedAt } };
8373
+ }
8374
+ function liveResolution(target, token, source, warnings) {
8375
+ return { ok: true, credential: { target, token, source, warnings } };
8376
+ }
8377
+ function unresolved(subject, cacheBlock, attempts) {
8378
+ const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(subject)}\``;
8379
+ return { ok: false, message: `agent-shim: ${subject} has no usable credential: ${attempts.join("; ")}${hint}` };
8380
+ }
8381
+ function declinedLine(source, outcome, subject) {
8382
+ const attempt = `${describeSource(source)} ${outcome.reason}`;
8383
+ return { attempt, warning: outcome.warn ? `agent-shim: ${subject}: skipped ${attempt}` : void 0 };
8384
+ }
8356
8385
  function resolveCredential(params) {
8357
8386
  const target = params.credential.target ?? "bearer";
8358
8387
  const cacheBlock = params.credential.cache;
@@ -8361,7 +8390,7 @@ function resolveCredential(params) {
8361
8390
  if (cacheBlock !== void 0 && cache !== void 0 && store !== void 0 && params.refresh !== true) {
8362
8391
  const entry = cache.port.read(store, params.subject);
8363
8392
  if (entry !== void 0 && isFresh(entry, cacheBlock, cache.now())) {
8364
- return { ok: true, credential: { target, token: entry.token, source: entry.source, warnings: [], cachedAt: entry.fetchedAt } };
8393
+ return cachedResolution(target, entry);
8365
8394
  }
8366
8395
  }
8367
8396
  const attempts = [];
@@ -8372,16 +8401,15 @@ function resolveCredential(params) {
8372
8401
  if (cache !== void 0 && store !== void 0) {
8373
8402
  cache.port.write(store, params.subject, { token: outcome.token, fetchedAt: cache.now(), source });
8374
8403
  }
8375
- return { ok: true, credential: { target, token: outcome.token, source, warnings } };
8404
+ return liveResolution(target, outcome.token, source, warnings);
8376
8405
  }
8377
- const line = `${describeSource(source)} ${outcome.reason}`;
8378
- attempts.push(line);
8379
- if (outcome.warn) {
8380
- warnings.push(`agent-shim: ${params.subject}: skipped ${line}`);
8406
+ const line = declinedLine(source, outcome, params.subject);
8407
+ attempts.push(line.attempt);
8408
+ if (line.warning !== void 0) {
8409
+ warnings.push(line.warning);
8381
8410
  }
8382
8411
  }
8383
- const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(params.subject)}\``;
8384
- return { ok: false, message: `agent-shim: ${params.subject} has no usable credential: ${attempts.join("; ")}${hint}` };
8412
+ return unresolved(params.subject, cacheBlock, attempts);
8385
8413
  }
8386
8414
  function credentialVariables(target, token) {
8387
8415
  return {
@@ -8390,7 +8418,7 @@ function credentialVariables(target, token) {
8390
8418
  CLAUDE_CODE_OAUTH_TOKEN: target === "oauthToken" ? token : void 0
8391
8419
  };
8392
8420
  }
8393
- var CREDENTIAL_UNAVAILABLE_EXIT, CREDENTIAL_COMMAND_TIMEOUT_MS, CREDENTIAL_INTERACTIVE_TIMEOUT_MS, GROUP_OTHER_PERMISSION_BITS, PERMISSION_BITS2, OCTAL_RADIX2, GO_KEYRING_BASE64_PREFIX;
8421
+ var CREDENTIAL_UNAVAILABLE_EXIT, CREDENTIAL_COMMAND_TIMEOUT_MS, CREDENTIAL_INTERACTIVE_TIMEOUT_MS, GROUP_OTHER_PERMISSION_BITS, PERMISSION_BITS2, OCTAL_RADIX2, GO_KEYRING_BASE64_PREFIX, NO_PERSON_REASON;
8394
8422
  var init_credential = __esm({
8395
8423
  "src/credential.ts"() {
8396
8424
  "use strict";
@@ -8402,6 +8430,7 @@ var init_credential = __esm({
8402
8430
  PERMISSION_BITS2 = 511;
8403
8431
  OCTAL_RADIX2 = 8;
8404
8432
  GO_KEYRING_BASE64_PREFIX = "go-keyring-base64:";
8433
+ NO_PERSON_REASON = "needs a person to approve it, but there is no terminal or desktop session";
8405
8434
  }
8406
8435
  });
8407
8436
 
@@ -11498,13 +11527,13 @@ function resolveLaunch(params) {
11498
11527
  environment
11499
11528
  };
11500
11529
  }
11501
- function runLaunchPlan(plan, spawn3) {
11530
+ function runLaunchPlan(plan, spawn4) {
11502
11531
  try {
11503
11532
  if (plan.hold() === "cancelled") {
11504
11533
  return LAUNCH_CANCELLED_EXIT;
11505
11534
  }
11506
11535
  plan.markChildStarted();
11507
- const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11536
+ const result = spawn4.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11508
11537
  if (result.error !== void 0) {
11509
11538
  throw result.error;
11510
11539
  }
package/dist/index.mjs CHANGED
@@ -4426,7 +4426,7 @@ var init_package = __esm({
4426
4426
  "package.json"() {
4427
4427
  package_default = {
4428
4428
  name: "claude-use",
4429
- version: "11.55.0",
4429
+ version: "11.56.0",
4430
4430
  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.",
4431
4431
  license: "MIT",
4432
4432
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -5718,6 +5718,9 @@ function hasDesktopSession() {
5718
5718
  const result = spawnSync("launchctl", ["managername"], { encoding: "utf8" });
5719
5719
  return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
5720
5720
  }
5721
+ return hasDisplayServer();
5722
+ }
5723
+ function hasDisplayServer() {
5721
5724
  if (process.platform === "win32") {
5722
5725
  return false;
5723
5726
  }
@@ -8053,7 +8056,7 @@ var init_credentialCache = __esm({
8053
8056
  });
8054
8057
 
8055
8058
  // src/realCredentialCache.ts
8056
- import { spawnSync as spawnSync2 } from "node:child_process";
8059
+ import { spawn as spawn3, spawnSync as spawnSync2 } from "node:child_process";
8057
8060
  import fs6 from "node:fs";
8058
8061
  import path24 from "node:path";
8059
8062
  function cacheFileNameFor(owner) {
@@ -8280,51 +8283,77 @@ function unpackKeyringToken(raw) {
8280
8283
  }
8281
8284
  return trimmed;
8282
8285
  }
8283
- function trySource(source, params) {
8284
- const none = (reason, warn = false) => ({ ok: false, reason, warn });
8286
+ function declined(reason, warn = false) {
8287
+ return { ok: false, reason, warn };
8288
+ }
8289
+ function isCommandBacked(source) {
8290
+ return "command" in source || "op" in source || "keychain" in source;
8291
+ }
8292
+ function immediateOutcome(source, params) {
8285
8293
  if ("env" in source) {
8286
8294
  const value = params.env[source.env];
8287
- return value === void 0 || value === "" ? none("is unset or empty") : { ok: true, token: unpackKeyringToken(value) };
8295
+ return value === void 0 || value === "" ? declined("is unset or empty") : { ok: true, token: unpackKeyringToken(value) };
8288
8296
  }
8289
8297
  if ("literal" in source) {
8290
8298
  return { ok: true, token: source.literal };
8291
8299
  }
8292
- if ("file" in source) {
8293
- const read = params.port.readSecretFile(source.file);
8294
- if (!read.found) {
8295
- return none("does not exist");
8296
- }
8297
- if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
8298
- return none(
8299
- `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS2).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
8300
- true
8301
- );
8302
- }
8303
- const token2 = unpackKeyringToken(read.content.trim());
8304
- return token2 === "" ? none("is empty") : { ok: true, token: token2 };
8300
+ const read = params.port.readSecretFile(source.file);
8301
+ if (!read.found) {
8302
+ return declined("does not exist");
8305
8303
  }
8306
- const argv = commandArgv(source);
8307
- const interactive = isInteractiveSource(source, params.env);
8308
- if (interactive && !params.port.personPresent()) {
8309
- return none("needs a person to approve it, but there is no terminal or desktop session");
8304
+ if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
8305
+ return declined(
8306
+ `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS2).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
8307
+ true
8308
+ );
8310
8309
  }
8311
- const timeoutMs = source.timeoutMs ?? (interactive ? CREDENTIAL_INTERACTIVE_TIMEOUT_MS : CREDENTIAL_COMMAND_TIMEOUT_MS);
8312
- const result = params.port.runCommand(argv, { timeoutMs, interactive });
8310
+ const token = unpackKeyringToken(read.content.trim());
8311
+ return token === "" ? declined("is empty") : { ok: true, token };
8312
+ }
8313
+ function commandRunOf(source, env) {
8314
+ const interactive = isInteractiveSource(source, env);
8315
+ return { argv: commandArgv(source), interactive, timeoutMs: source.timeoutMs ?? (interactive ? CREDENTIAL_INTERACTIVE_TIMEOUT_MS : CREDENTIAL_COMMAND_TIMEOUT_MS) };
8316
+ }
8317
+ function commandOutcome(result, timeoutMs) {
8313
8318
  if (result.timedOut) {
8314
- return none(`timed out after ${String(timeoutMs)}ms`);
8319
+ return declined(`timed out after ${String(timeoutMs)}ms`);
8315
8320
  }
8316
8321
  if (result.status !== 0) {
8317
8322
  const stderr = result.stderr.trim();
8318
8323
  const outcome = result.status === null ? "could not be run or was killed by a signal" : `exited with status ${String(result.status)}`;
8319
- return none(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
8324
+ return declined(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
8320
8325
  }
8321
8326
  const token = unpackKeyringToken(result.stdout.trim());
8322
- return token === "" ? none("printed no token") : { ok: true, token };
8327
+ return token === "" ? declined("printed no token") : { ok: true, token };
8328
+ }
8329
+ function trySource(source, params) {
8330
+ if (!isCommandBacked(source)) {
8331
+ return immediateOutcome(source, params);
8332
+ }
8333
+ const run = commandRunOf(source, params.env);
8334
+ if (run.interactive && !params.port.personPresent()) {
8335
+ return declined(NO_PERSON_REASON);
8336
+ }
8337
+ return commandOutcome(params.port.runCommand(run.argv, { timeoutMs: run.timeoutMs, interactive: run.interactive }), run.timeoutMs);
8323
8338
  }
8324
8339
  function warmCommandFor(subject) {
8325
8340
  const [kind, name] = subject.split(" ");
8326
8341
  return kind === "provider" ? `agent-shim credential warm --provider ${name ?? ""}` : `agent-shim credential warm ${name ?? ""}`;
8327
8342
  }
8343
+ function cachedResolution(target, entry) {
8344
+ return { ok: true, credential: { target, token: entry.token, source: entry.source, warnings: [], cachedAt: entry.fetchedAt } };
8345
+ }
8346
+ function liveResolution(target, token, source, warnings) {
8347
+ return { ok: true, credential: { target, token, source, warnings } };
8348
+ }
8349
+ function unresolved(subject, cacheBlock, attempts) {
8350
+ const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(subject)}\``;
8351
+ return { ok: false, message: `agent-shim: ${subject} has no usable credential: ${attempts.join("; ")}${hint}` };
8352
+ }
8353
+ function declinedLine(source, outcome, subject) {
8354
+ const attempt = `${describeSource(source)} ${outcome.reason}`;
8355
+ return { attempt, warning: outcome.warn ? `agent-shim: ${subject}: skipped ${attempt}` : void 0 };
8356
+ }
8328
8357
  function resolveCredential(params) {
8329
8358
  const target = params.credential.target ?? "bearer";
8330
8359
  const cacheBlock = params.credential.cache;
@@ -8333,7 +8362,7 @@ function resolveCredential(params) {
8333
8362
  if (cacheBlock !== void 0 && cache !== void 0 && store !== void 0 && params.refresh !== true) {
8334
8363
  const entry = cache.port.read(store, params.subject);
8335
8364
  if (entry !== void 0 && isFresh(entry, cacheBlock, cache.now())) {
8336
- return { ok: true, credential: { target, token: entry.token, source: entry.source, warnings: [], cachedAt: entry.fetchedAt } };
8365
+ return cachedResolution(target, entry);
8337
8366
  }
8338
8367
  }
8339
8368
  const attempts = [];
@@ -8344,16 +8373,15 @@ function resolveCredential(params) {
8344
8373
  if (cache !== void 0 && store !== void 0) {
8345
8374
  cache.port.write(store, params.subject, { token: outcome.token, fetchedAt: cache.now(), source });
8346
8375
  }
8347
- return { ok: true, credential: { target, token: outcome.token, source, warnings } };
8376
+ return liveResolution(target, outcome.token, source, warnings);
8348
8377
  }
8349
- const line = `${describeSource(source)} ${outcome.reason}`;
8350
- attempts.push(line);
8351
- if (outcome.warn) {
8352
- warnings.push(`agent-shim: ${params.subject}: skipped ${line}`);
8378
+ const line = declinedLine(source, outcome, params.subject);
8379
+ attempts.push(line.attempt);
8380
+ if (line.warning !== void 0) {
8381
+ warnings.push(line.warning);
8353
8382
  }
8354
8383
  }
8355
- const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(params.subject)}\``;
8356
- return { ok: false, message: `agent-shim: ${params.subject} has no usable credential: ${attempts.join("; ")}${hint}` };
8384
+ return unresolved(params.subject, cacheBlock, attempts);
8357
8385
  }
8358
8386
  function credentialVariables(target, token) {
8359
8387
  return {
@@ -8362,7 +8390,7 @@ function credentialVariables(target, token) {
8362
8390
  CLAUDE_CODE_OAUTH_TOKEN: target === "oauthToken" ? token : void 0
8363
8391
  };
8364
8392
  }
8365
- var CREDENTIAL_UNAVAILABLE_EXIT, CREDENTIAL_COMMAND_TIMEOUT_MS, CREDENTIAL_INTERACTIVE_TIMEOUT_MS, GROUP_OTHER_PERMISSION_BITS, PERMISSION_BITS2, OCTAL_RADIX2, GO_KEYRING_BASE64_PREFIX;
8393
+ var CREDENTIAL_UNAVAILABLE_EXIT, CREDENTIAL_COMMAND_TIMEOUT_MS, CREDENTIAL_INTERACTIVE_TIMEOUT_MS, GROUP_OTHER_PERMISSION_BITS, PERMISSION_BITS2, OCTAL_RADIX2, GO_KEYRING_BASE64_PREFIX, NO_PERSON_REASON;
8366
8394
  var init_credential = __esm({
8367
8395
  "src/credential.ts"() {
8368
8396
  "use strict";
@@ -8374,6 +8402,7 @@ var init_credential = __esm({
8374
8402
  PERMISSION_BITS2 = 511;
8375
8403
  OCTAL_RADIX2 = 8;
8376
8404
  GO_KEYRING_BASE64_PREFIX = "go-keyring-base64:";
8405
+ NO_PERSON_REASON = "needs a person to approve it, but there is no terminal or desktop session";
8377
8406
  }
8378
8407
  });
8379
8408
 
@@ -11472,13 +11501,13 @@ function resolveLaunch(params) {
11472
11501
  environment
11473
11502
  };
11474
11503
  }
11475
- function runLaunchPlan(plan, spawn3) {
11504
+ function runLaunchPlan(plan, spawn4) {
11476
11505
  try {
11477
11506
  if (plan.hold() === "cancelled") {
11478
11507
  return LAUNCH_CANCELLED_EXIT;
11479
11508
  }
11480
11509
  plan.markChildStarted();
11481
- const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11510
+ const result = spawn4.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11482
11511
  if (result.error !== void 0) {
11483
11512
  throw result.error;
11484
11513
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-use",
3
- "version": "11.55.0",
3
+ "version": "11.56.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>",