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 +247 -49
- package/dist/index.cjs +66 -37
- package/dist/index.mjs +67 -38
- package/package.json +1 -1
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
|
|
35369
|
-
|
|
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 === "" ?
|
|
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
|
-
|
|
35378
|
-
|
|
35379
|
-
|
|
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
|
-
|
|
35392
|
-
|
|
35393
|
-
|
|
35394
|
-
|
|
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
|
|
35397
|
-
|
|
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
|
|
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
|
|
35459
|
+
return declined(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
|
|
35405
35460
|
}
|
|
35406
35461
|
const token = unpackKeyringToken(result.stdout.trim());
|
|
35407
|
-
return 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
|
|
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
|
|
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 =
|
|
35435
|
-
attempts.push(line);
|
|
35436
|
-
if (
|
|
35437
|
-
warnings.push(
|
|
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
|
-
|
|
35441
|
-
|
|
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.
|
|
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,
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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:
|
|
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: { ...
|
|
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.
|
|
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
|
|
8312
|
-
|
|
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 === "" ?
|
|
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
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
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
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
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
|
|
8340
|
-
|
|
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
|
|
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
|
|
8352
|
+
return declined(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
|
|
8348
8353
|
}
|
|
8349
8354
|
const token = unpackKeyringToken(result.stdout.trim());
|
|
8350
|
-
return 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
|
|
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
|
|
8404
|
+
return liveResolution(target, outcome.token, source, warnings);
|
|
8376
8405
|
}
|
|
8377
|
-
const line =
|
|
8378
|
-
attempts.push(line);
|
|
8379
|
-
if (
|
|
8380
|
-
warnings.push(
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
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.
|
|
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
|
|
8284
|
-
|
|
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 === "" ?
|
|
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
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
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
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
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
|
|
8312
|
-
|
|
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
|
|
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
|
|
8324
|
+
return declined(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
|
|
8320
8325
|
}
|
|
8321
8326
|
const token = unpackKeyringToken(result.stdout.trim());
|
|
8322
|
-
return 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
|
|
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
|
|
8376
|
+
return liveResolution(target, outcome.token, source, warnings);
|
|
8348
8377
|
}
|
|
8349
|
-
const line =
|
|
8350
|
-
attempts.push(line);
|
|
8351
|
-
if (
|
|
8352
|
-
warnings.push(
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
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.
|
|
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>",
|