@hasna/accounts 0.1.18 → 0.1.20
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.js +171 -99
- package/dist/index.js +160 -88
- package/dist/lib/safe-path.d.ts.map +1 -1
- package/dist/mcp.js +146 -74
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +111 -39
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -12804,8 +12804,8 @@ More information can be found at: https://a.co/c895JFp`);
|
|
|
12804
12804
|
};
|
|
12805
12805
|
var createUserAgentStringParsingProvider = ({ serviceId, clientVersion }) => async (config2) => {
|
|
12806
12806
|
const module2 = await Promise.resolve().then(() => __toESM(require_es5()));
|
|
12807
|
-
const
|
|
12808
|
-
const parsedUA = typeof window !== "undefined" && window?.navigator?.userAgent ?
|
|
12807
|
+
const parse2 = module2.parse ?? module2.default.parse ?? (() => "");
|
|
12808
|
+
const parsedUA = typeof window !== "undefined" && window?.navigator?.userAgent ? parse2(window.navigator.userAgent) : undefined;
|
|
12809
12809
|
const sections = [
|
|
12810
12810
|
["aws-sdk-js", clientVersion],
|
|
12811
12811
|
["ua", "2.1"],
|
|
@@ -14563,7 +14563,7 @@ var require_dist_cjs9 = __commonJS((exports) => {
|
|
|
14563
14563
|
var require_util = __commonJS((exports) => {
|
|
14564
14564
|
var protocols = require_protocols();
|
|
14565
14565
|
var validate = (str) => typeof str === "string" && str.indexOf("arn:") === 0 && str.split(":").length >= 6;
|
|
14566
|
-
var
|
|
14566
|
+
var parse2 = (arn) => {
|
|
14567
14567
|
const segments = arn.split(":");
|
|
14568
14568
|
if (segments.length < 6 || segments[0] !== "arn")
|
|
14569
14569
|
throw new Error("Malformed ARN");
|
|
@@ -14613,7 +14613,7 @@ var require_util = __commonJS((exports) => {
|
|
|
14613
14613
|
}
|
|
14614
14614
|
exports.build = build;
|
|
14615
14615
|
exports.formatUrl = formatUrl;
|
|
14616
|
-
exports.parse =
|
|
14616
|
+
exports.parse = parse2;
|
|
14617
14617
|
exports.validate = validate;
|
|
14618
14618
|
});
|
|
14619
14619
|
|
|
@@ -30104,12 +30104,12 @@ var require_fromHttp = __commonJS((exports) => {
|
|
|
30104
30104
|
var fromHttp = (options = {}) => {
|
|
30105
30105
|
options.logger?.debug("@aws-sdk/credential-provider-http - fromHttp");
|
|
30106
30106
|
let host;
|
|
30107
|
-
const
|
|
30107
|
+
const relative2 = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI];
|
|
30108
30108
|
const full = options.awsContainerCredentialsFullUri ?? process.env[AWS_CONTAINER_CREDENTIALS_FULL_URI];
|
|
30109
30109
|
const token = options.awsContainerAuthorizationToken ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN];
|
|
30110
30110
|
const tokenFile = options.awsContainerAuthorizationTokenFile ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE];
|
|
30111
30111
|
const warn = options.logger?.constructor?.name === "NoOpLogger" || !options.logger?.warn ? console.warn : options.logger.warn.bind(options.logger);
|
|
30112
|
-
if (
|
|
30112
|
+
if (relative2 && full) {
|
|
30113
30113
|
warn("@aws-sdk/credential-provider-http: " + "you have set both awsContainerCredentialsRelativeUri and awsContainerCredentialsFullUri.");
|
|
30114
30114
|
warn("awsContainerCredentialsFullUri will take precedence.");
|
|
30115
30115
|
}
|
|
@@ -30119,8 +30119,8 @@ var require_fromHttp = __commonJS((exports) => {
|
|
|
30119
30119
|
}
|
|
30120
30120
|
if (full) {
|
|
30121
30121
|
host = full;
|
|
30122
|
-
} else if (
|
|
30123
|
-
host = `${DEFAULT_LINK_LOCAL_HOST}${
|
|
30122
|
+
} else if (relative2) {
|
|
30123
|
+
host = `${DEFAULT_LINK_LOCAL_HOST}${relative2}`;
|
|
30124
30124
|
} else {
|
|
30125
30125
|
throw new config_1.CredentialsProviderError(`No HTTP credential provider host provided.
|
|
30126
30126
|
Set AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.`, { logger: options.logger });
|
|
@@ -36799,7 +36799,7 @@ var require_dist_cjs22 = __commonJS((exports) => {
|
|
|
36799
36799
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
36800
36800
|
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "node:fs";
|
|
36801
36801
|
import { homedir as homedir6 } from "node:os";
|
|
36802
|
-
import { dirname as dirname5, join as
|
|
36802
|
+
import { dirname as dirname5, join as join14 } from "node:path";
|
|
36803
36803
|
import { fileURLToPath } from "node:url";
|
|
36804
36804
|
|
|
36805
36805
|
// node_modules/commander/esm.mjs
|
|
@@ -42002,62 +42002,131 @@ class AccountsError extends Error {
|
|
|
42002
42002
|
|
|
42003
42003
|
// src/lib/tools.ts
|
|
42004
42004
|
import { homedir as homedir3 } from "node:os";
|
|
42005
|
-
import { join as
|
|
42005
|
+
import { join as join4 } from "node:path";
|
|
42006
42006
|
|
|
42007
42007
|
// src/storage.ts
|
|
42008
42008
|
import { homedir as homedir2 } from "node:os";
|
|
42009
42009
|
import { hostname } from "node:os";
|
|
42010
|
-
import { join as
|
|
42011
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "node:fs";
|
|
42010
|
+
import { join as join3 } from "node:path";
|
|
42011
|
+
import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "node:fs";
|
|
42012
42012
|
|
|
42013
42013
|
// src/lib/safe-path.ts
|
|
42014
42014
|
import { existsSync as existsSync2, lstatSync, mkdirSync, realpathSync } from "node:fs";
|
|
42015
|
-
import { dirname, resolve } from "node:path";
|
|
42015
|
+
import { dirname, isAbsolute, join as join2, parse, relative, resolve, sep } from "node:path";
|
|
42016
|
+
function lstatIfExists(path) {
|
|
42017
|
+
try {
|
|
42018
|
+
return lstatSync(path);
|
|
42019
|
+
} catch (err) {
|
|
42020
|
+
if (err.code !== "ENOENT")
|
|
42021
|
+
throw err;
|
|
42022
|
+
return;
|
|
42023
|
+
}
|
|
42024
|
+
}
|
|
42016
42025
|
function throwIfSymlink(path, label) {
|
|
42017
|
-
if (
|
|
42026
|
+
if (lstatIfExists(path)?.isSymbolicLink()) {
|
|
42018
42027
|
throw new AccountsError(`${label}: ${path}`);
|
|
42019
42028
|
}
|
|
42020
42029
|
}
|
|
42021
|
-
function
|
|
42022
|
-
|
|
42023
|
-
|
|
42024
|
-
|
|
42025
|
-
|
|
42026
|
-
|
|
42027
|
-
|
|
42028
|
-
|
|
42029
|
-
|
|
42030
|
-
|
|
42031
|
-
|
|
42032
|
-
|
|
42033
|
-
}
|
|
42034
|
-
|
|
42035
|
-
|
|
42036
|
-
|
|
42037
|
-
|
|
42030
|
+
function isAllowedSystemDirectorySymlink(path) {
|
|
42031
|
+
if (path !== "/var" && path !== "/tmp")
|
|
42032
|
+
return false;
|
|
42033
|
+
try {
|
|
42034
|
+
return realpathSync(path) === `/private${path}`;
|
|
42035
|
+
} catch {
|
|
42036
|
+
return false;
|
|
42037
|
+
}
|
|
42038
|
+
}
|
|
42039
|
+
function assertDirectory(path, label, opts) {
|
|
42040
|
+
const stat = lstatIfExists(path);
|
|
42041
|
+
if (!stat) {
|
|
42042
|
+
throw new AccountsError(`refusing to write under missing directory: ${path}`);
|
|
42043
|
+
}
|
|
42044
|
+
if (stat.isSymbolicLink()) {
|
|
42045
|
+
if (opts?.allowSystemSymlink && isAllowedSystemDirectorySymlink(path))
|
|
42046
|
+
return;
|
|
42047
|
+
throw new AccountsError(`${label}: ${path}`);
|
|
42048
|
+
}
|
|
42049
|
+
if (!stat.isDirectory()) {
|
|
42050
|
+
throw new AccountsError(`refusing to write under non-directory path: ${path}`);
|
|
42051
|
+
}
|
|
42052
|
+
}
|
|
42053
|
+
function assertInsideBase(absPath, base, originalPath) {
|
|
42054
|
+
const rel = relative(base, absPath);
|
|
42055
|
+
if (rel === "")
|
|
42056
|
+
return rel;
|
|
42057
|
+
if (rel === ".." || rel.startsWith(".." + sep) || isAbsolute(rel)) {
|
|
42058
|
+
throw new AccountsError(`refusing to write outside profile directory: ${originalPath}`);
|
|
42059
|
+
}
|
|
42060
|
+
return rel;
|
|
42061
|
+
}
|
|
42062
|
+
function assertExistingDirectoryComponentsSafe(path, label) {
|
|
42063
|
+
const root = parse(path).root;
|
|
42064
|
+
const rel = relative(root, path);
|
|
42065
|
+
const segments = rel ? rel.split(sep).filter(Boolean) : [];
|
|
42066
|
+
let cursor = root;
|
|
42067
|
+
assertDirectory(cursor, label, { allowSystemSymlink: true });
|
|
42068
|
+
for (const segment of segments) {
|
|
42069
|
+
cursor = join2(cursor, segment);
|
|
42070
|
+
if (!lstatIfExists(cursor))
|
|
42071
|
+
return;
|
|
42072
|
+
assertDirectory(cursor, label, { allowSystemSymlink: true });
|
|
42073
|
+
}
|
|
42074
|
+
}
|
|
42075
|
+
function ensureBoundaryRootSafe(base) {
|
|
42076
|
+
const missing = [];
|
|
42077
|
+
let cursor = base;
|
|
42078
|
+
while (!lstatIfExists(cursor)) {
|
|
42079
|
+
missing.unshift(cursor);
|
|
42080
|
+
const parent = dirname(cursor);
|
|
42081
|
+
if (parent === cursor)
|
|
42082
|
+
break;
|
|
42083
|
+
cursor = parent;
|
|
42084
|
+
}
|
|
42085
|
+
assertDirectory(cursor, "refusing to use symlink base directory");
|
|
42086
|
+
for (const dir of missing) {
|
|
42087
|
+
if (lstatIfExists(dir)) {
|
|
42088
|
+
assertDirectory(dir, "refusing to use symlink base directory");
|
|
42089
|
+
} else {
|
|
42090
|
+
mkdirSync(dir);
|
|
42091
|
+
assertDirectory(dir, "refusing to use symlink base directory");
|
|
42038
42092
|
}
|
|
42039
|
-
}
|
|
42040
|
-
|
|
42041
|
-
|
|
42042
|
-
|
|
42043
|
-
|
|
42044
|
-
|
|
42045
|
-
|
|
42046
|
-
|
|
42093
|
+
}
|
|
42094
|
+
assertDirectory(base, "refusing to use symlink base directory");
|
|
42095
|
+
}
|
|
42096
|
+
function ensureDirectoryChainSafe(parent, startAt) {
|
|
42097
|
+
const root = startAt ?? parse(parent).root;
|
|
42098
|
+
const rel = relative(root, parent);
|
|
42099
|
+
const segments = rel ? rel.split(sep).filter(Boolean) : [];
|
|
42100
|
+
let cursor = root;
|
|
42101
|
+
if (startAt)
|
|
42102
|
+
assertDirectory(startAt, "refusing to write under symlink directory");
|
|
42103
|
+
for (const segment of segments) {
|
|
42104
|
+
cursor = join2(cursor, segment);
|
|
42105
|
+
if (lstatIfExists(cursor)) {
|
|
42106
|
+
assertDirectory(cursor, "refusing to write under symlink directory");
|
|
42107
|
+
} else {
|
|
42108
|
+
mkdirSync(cursor);
|
|
42109
|
+
assertDirectory(cursor, "refusing to write under symlink directory");
|
|
42047
42110
|
}
|
|
42048
42111
|
}
|
|
42049
42112
|
}
|
|
42050
42113
|
function assertSafeWritePath(filePath, opts) {
|
|
42051
42114
|
const absFile = resolve(filePath);
|
|
42052
42115
|
const parent = dirname(absFile);
|
|
42053
|
-
|
|
42054
|
-
|
|
42116
|
+
const base = opts?.mustStayUnder ? resolve(opts.mustStayUnder) : undefined;
|
|
42117
|
+
if (base) {
|
|
42118
|
+
assertInsideBase(absFile, base, filePath);
|
|
42119
|
+
assertExistingDirectoryComponentsSafe(base, "refusing to use symlink base directory");
|
|
42120
|
+
ensureBoundaryRootSafe(base);
|
|
42121
|
+
ensureDirectoryChainSafe(parent, base);
|
|
42122
|
+
} else {
|
|
42123
|
+
ensureDirectoryChainSafe(parent);
|
|
42124
|
+
}
|
|
42055
42125
|
throwIfSymlink(absFile, "refusing to write through symlink");
|
|
42056
|
-
assertDirChainSafe(absFile, opts?.mustStayUnder);
|
|
42057
42126
|
const resolved = realpathSync(existsSync2(absFile) ? absFile : parent);
|
|
42058
|
-
if (
|
|
42059
|
-
const
|
|
42060
|
-
if (resolved !==
|
|
42127
|
+
if (base) {
|
|
42128
|
+
const realBase = realpathSync(base);
|
|
42129
|
+
if (resolved !== realBase && !resolved.startsWith(realBase + sep)) {
|
|
42061
42130
|
throw new AccountsError(`refusing to write outside profile directory: ${filePath}`);
|
|
42062
42131
|
}
|
|
42063
42132
|
}
|
|
@@ -42096,16 +42165,16 @@ function accountsHome() {
|
|
|
42096
42165
|
const override = process.env.ACCOUNTS_HOME;
|
|
42097
42166
|
if (override && override.trim())
|
|
42098
42167
|
return validateEnvPath(override, "ACCOUNTS_HOME");
|
|
42099
|
-
return
|
|
42168
|
+
return join3(homedir2(), ".hasna", "accounts");
|
|
42100
42169
|
}
|
|
42101
42170
|
function storePath() {
|
|
42102
42171
|
const override = process.env.ACCOUNTS_STORE_PATH;
|
|
42103
42172
|
if (override && override.trim())
|
|
42104
42173
|
return validateEnvPath(override, "ACCOUNTS_STORE_PATH");
|
|
42105
|
-
return
|
|
42174
|
+
return join3(accountsHome(), "accounts.json");
|
|
42106
42175
|
}
|
|
42107
42176
|
function profilesDir() {
|
|
42108
|
-
return
|
|
42177
|
+
return join3(accountsHome(), "profiles");
|
|
42109
42178
|
}
|
|
42110
42179
|
var EMPTY_STORE = { version: 1, current: {}, applied: {}, profiles: [], tools: [] };
|
|
42111
42180
|
function loadStore() {
|
|
@@ -42148,9 +42217,12 @@ function loadStore() {
|
|
|
42148
42217
|
function saveStore(store) {
|
|
42149
42218
|
const path = storePath();
|
|
42150
42219
|
assertSafeWritePath(path, { mustStayUnder: accountsHome() });
|
|
42151
|
-
mkdirSync2(
|
|
42220
|
+
mkdirSync2(join3(path, ".."), { recursive: true });
|
|
42221
|
+
if (existsSync3(path))
|
|
42222
|
+
chmodSync(path, 384);
|
|
42152
42223
|
writeFileSync(path, JSON.stringify(store, null, 2) + `
|
|
42153
42224
|
`, { mode: 384 });
|
|
42225
|
+
chmodSync(path, 384);
|
|
42154
42226
|
}
|
|
42155
42227
|
function firstEnv(env2, primary, fallback) {
|
|
42156
42228
|
return env2[primary] || env2[fallback] || undefined;
|
|
@@ -42299,7 +42371,7 @@ var BUILTIN_TOOLS = [
|
|
|
42299
42371
|
extraEnv: {
|
|
42300
42372
|
TELEGRAM_STATE_DIR: "{profileDir}/channels/telegram"
|
|
42301
42373
|
},
|
|
42302
|
-
defaultDir:
|
|
42374
|
+
defaultDir: join4(homedir3(), ".claude"),
|
|
42303
42375
|
bin: "claude",
|
|
42304
42376
|
loginHint: "run /login inside Claude, then /exit when done",
|
|
42305
42377
|
resumeArgs: ["--continue"],
|
|
@@ -42319,7 +42391,7 @@ var BUILTIN_TOOLS = [
|
|
|
42319
42391
|
id: "codex-app",
|
|
42320
42392
|
label: "Codex App",
|
|
42321
42393
|
envVar: "CODEX_HOME",
|
|
42322
|
-
defaultDir:
|
|
42394
|
+
defaultDir: join4(homedir3(), ".codex"),
|
|
42323
42395
|
bin: "/Applications/Codex.app/Contents/MacOS/Codex",
|
|
42324
42396
|
loginHint: "sign in inside Codex.app, then quit the app when the profile is ready",
|
|
42325
42397
|
launchArgs: ["--user-data-dir={profileDir}/electron-user-data"],
|
|
@@ -42329,7 +42401,7 @@ var BUILTIN_TOOLS = [
|
|
|
42329
42401
|
id: "codex",
|
|
42330
42402
|
label: "Codex CLI",
|
|
42331
42403
|
envVar: "CODEX_HOME",
|
|
42332
|
-
defaultDir:
|
|
42404
|
+
defaultDir: join4(homedir3(), ".codex"),
|
|
42333
42405
|
bin: "codex",
|
|
42334
42406
|
loginArgs: ["login"],
|
|
42335
42407
|
loginHint: "complete the Codex login flow for this CODEX_HOME",
|
|
@@ -42342,7 +42414,7 @@ var BUILTIN_TOOLS = [
|
|
|
42342
42414
|
id: "takumi",
|
|
42343
42415
|
label: "Takumi",
|
|
42344
42416
|
envVar: "TAKUMI_CONFIG_DIR",
|
|
42345
|
-
defaultDir:
|
|
42417
|
+
defaultDir: join4(homedir3(), ".takumi"),
|
|
42346
42418
|
bin: "takumi",
|
|
42347
42419
|
loginHint: "complete Takumi auth in this TAKUMI_CONFIG_DIR",
|
|
42348
42420
|
resumeArgs: ["--continue"],
|
|
@@ -42362,7 +42434,7 @@ var BUILTIN_TOOLS = [
|
|
|
42362
42434
|
id: "gemini",
|
|
42363
42435
|
label: "Gemini CLI",
|
|
42364
42436
|
envVar: "GEMINI_CONFIG_DIR",
|
|
42365
|
-
defaultDir:
|
|
42437
|
+
defaultDir: join4(homedir3(), ".gemini"),
|
|
42366
42438
|
bin: "gemini",
|
|
42367
42439
|
loginHint: "complete Gemini auth in this GEMINI_CONFIG_DIR",
|
|
42368
42440
|
permissionArgs: {
|
|
@@ -42380,7 +42452,7 @@ var BUILTIN_TOOLS = [
|
|
|
42380
42452
|
XDG_CONFIG_HOME: "{profileDir}/xdg-config",
|
|
42381
42453
|
XDG_DATA_HOME: "{profileDir}/xdg-data"
|
|
42382
42454
|
},
|
|
42383
|
-
defaultDir:
|
|
42455
|
+
defaultDir: join4(homedir3(), ".config", "opencode"),
|
|
42384
42456
|
bin: "opencode",
|
|
42385
42457
|
loginArgs: ["auth", "login"],
|
|
42386
42458
|
loginHint: "complete opencode auth login for this isolated config/data root",
|
|
@@ -42390,7 +42462,7 @@ var BUILTIN_TOOLS = [
|
|
|
42390
42462
|
id: "cursor",
|
|
42391
42463
|
label: "Cursor Agent",
|
|
42392
42464
|
envVar: "CURSOR_CONFIG_DIR",
|
|
42393
|
-
defaultDir:
|
|
42465
|
+
defaultDir: join4(homedir3(), ".cursor"),
|
|
42394
42466
|
bin: "cursor-agent",
|
|
42395
42467
|
loginArgs: ["login"],
|
|
42396
42468
|
loginHint: "complete cursor-agent login for this CURSOR_CONFIG_DIR"
|
|
@@ -42399,7 +42471,7 @@ var BUILTIN_TOOLS = [
|
|
|
42399
42471
|
id: "pi",
|
|
42400
42472
|
label: "Pi Coding Agent",
|
|
42401
42473
|
envVar: "PI_CODING_AGENT_HOME",
|
|
42402
|
-
defaultDir:
|
|
42474
|
+
defaultDir: join4(homedir3(), ".pi"),
|
|
42403
42475
|
bin: "pi",
|
|
42404
42476
|
loginHint: "complete Pi coding agent auth in this PI_CODING_AGENT_HOME"
|
|
42405
42477
|
},
|
|
@@ -42407,7 +42479,7 @@ var BUILTIN_TOOLS = [
|
|
|
42407
42479
|
id: "hermes",
|
|
42408
42480
|
label: "Hermes",
|
|
42409
42481
|
envVar: "HERMES_HOME",
|
|
42410
|
-
defaultDir:
|
|
42482
|
+
defaultDir: join4(homedir3(), ".hermes"),
|
|
42411
42483
|
bin: "hermes",
|
|
42412
42484
|
loginHint: "complete Hermes auth in this HERMES_HOME",
|
|
42413
42485
|
permissionArgs: {
|
|
@@ -42419,7 +42491,7 @@ var BUILTIN_TOOLS = [
|
|
|
42419
42491
|
id: "kimi",
|
|
42420
42492
|
label: "Kimi Code",
|
|
42421
42493
|
envVar: "KIMI_CODE_HOME",
|
|
42422
|
-
defaultDir:
|
|
42494
|
+
defaultDir: join4(homedir3(), ".kimi-code"),
|
|
42423
42495
|
bin: "kimi",
|
|
42424
42496
|
loginArgs: ["login"],
|
|
42425
42497
|
loginHint: "complete kimi login for this KIMI_CODE_HOME",
|
|
@@ -42434,7 +42506,7 @@ var BUILTIN_TOOLS = [
|
|
|
42434
42506
|
id: "grok",
|
|
42435
42507
|
label: "Grok Build",
|
|
42436
42508
|
envVar: "HOME",
|
|
42437
|
-
defaultDir:
|
|
42509
|
+
defaultDir: join4(homedir3(), ".grok"),
|
|
42438
42510
|
bin: "grok",
|
|
42439
42511
|
loginArgs: ["login"],
|
|
42440
42512
|
loginHint: "complete grok login in this process-scoped HOME; prefer launch/shell over exporting HOME globally"
|
|
@@ -42541,18 +42613,18 @@ function removeCustomTool(id) {
|
|
|
42541
42613
|
|
|
42542
42614
|
// src/lib/profiles.ts
|
|
42543
42615
|
import { homedir as homedir4 } from "node:os";
|
|
42544
|
-
import { isAbsolute, join as
|
|
42616
|
+
import { isAbsolute as isAbsolute2, join as join6, relative as relative2, resolve as resolve2 } from "node:path";
|
|
42545
42617
|
import { existsSync as existsSync5, mkdirSync as mkdirSync3, rmSync } from "node:fs";
|
|
42546
42618
|
|
|
42547
42619
|
// src/lib/detect.ts
|
|
42548
42620
|
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "node:fs";
|
|
42549
|
-
import { dirname as dirname2, join as
|
|
42621
|
+
import { dirname as dirname2, join as join5 } from "node:path";
|
|
42550
42622
|
function detectEmail(dir, tool) {
|
|
42551
42623
|
if (!tool.accountFile || !tool.emailPath)
|
|
42552
42624
|
return;
|
|
42553
|
-
const candidates = [
|
|
42625
|
+
const candidates = [join5(dir, tool.accountFile)];
|
|
42554
42626
|
if (dir === tool.defaultDir)
|
|
42555
|
-
candidates.push(
|
|
42627
|
+
candidates.push(join5(dirname2(dir), tool.accountFile));
|
|
42556
42628
|
for (const file of candidates) {
|
|
42557
42629
|
const email = readEmail(file, tool.emailPath);
|
|
42558
42630
|
if (email)
|
|
@@ -42588,8 +42660,8 @@ function expandPath(p) {
|
|
|
42588
42660
|
if (out === "~")
|
|
42589
42661
|
out = homedir4();
|
|
42590
42662
|
else if (out.startsWith("~/"))
|
|
42591
|
-
out =
|
|
42592
|
-
return
|
|
42663
|
+
out = join6(homedir4(), out.slice(2));
|
|
42664
|
+
return isAbsolute2(out) ? out : resolve2(process.cwd(), out);
|
|
42593
42665
|
}
|
|
42594
42666
|
function listProfiles(toolId) {
|
|
42595
42667
|
const profiles = loadStore().profiles;
|
|
@@ -42600,8 +42672,8 @@ function profileMatches(name, toolId) {
|
|
|
42600
42672
|
return loadStore().profiles.filter((p) => p.name === name && (!toolId || p.tool === toolId));
|
|
42601
42673
|
}
|
|
42602
42674
|
function isManagedProfileDir(dir) {
|
|
42603
|
-
const rel =
|
|
42604
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
42675
|
+
const rel = relative2(resolve2(profilesDir()), resolve2(dir));
|
|
42676
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute2(rel);
|
|
42605
42677
|
}
|
|
42606
42678
|
function getProfile(name, toolId) {
|
|
42607
42679
|
const matches = profileMatches(name, toolId);
|
|
@@ -42626,7 +42698,7 @@ function addProfile(opts) {
|
|
|
42626
42698
|
if (store.profiles.some((p) => p.name === name && p.tool === toolId)) {
|
|
42627
42699
|
throw new AccountsError(`a ${toolId} profile named "${name}" already exists`);
|
|
42628
42700
|
}
|
|
42629
|
-
const dir = opts.dir ? expandPath(opts.dir) :
|
|
42701
|
+
const dir = opts.dir ? expandPath(opts.dir) : join6(profilesDir(), toolId, name);
|
|
42630
42702
|
if (store.profiles.some((p) => p.dir === dir)) {
|
|
42631
42703
|
throw new AccountsError(`a profile already uses config dir ${dir}`);
|
|
42632
42704
|
}
|
|
@@ -42768,11 +42840,11 @@ function currentProfile(toolId) {
|
|
|
42768
42840
|
|
|
42769
42841
|
// src/lib/claude-auth.ts
|
|
42770
42842
|
import { copyFileSync, existsSync as existsSync6, lstatSync as lstatSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync3, statSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
42771
|
-
import { dirname as dirname4, join as
|
|
42843
|
+
import { dirname as dirname4, join as join8 } from "node:path";
|
|
42772
42844
|
|
|
42773
42845
|
// src/lib/claude-layout.ts
|
|
42774
42846
|
import { homedir as homedir5 } from "node:os";
|
|
42775
|
-
import { dirname as dirname3, join as
|
|
42847
|
+
import { dirname as dirname3, join as join7 } from "node:path";
|
|
42776
42848
|
var CLAUDE_KEYCHAIN_SERVICE = "Claude Code-credentials";
|
|
42777
42849
|
var ACCOUNTS_AUTH_DIR = ".accounts-auth";
|
|
42778
42850
|
var OAUTH_SNAPSHOT = "oauth-account.json";
|
|
@@ -42784,32 +42856,32 @@ function liveClaudeBase() {
|
|
|
42784
42856
|
}
|
|
42785
42857
|
function liveClaudePaths() {
|
|
42786
42858
|
const base = liveClaudeBase();
|
|
42787
|
-
const configDir =
|
|
42859
|
+
const configDir = join7(base, ".claude");
|
|
42788
42860
|
return {
|
|
42789
42861
|
configDir,
|
|
42790
|
-
homeJson:
|
|
42791
|
-
credentialsFile:
|
|
42862
|
+
homeJson: join7(base, ".claude.json"),
|
|
42863
|
+
credentialsFile: join7(configDir, ".credentials.json")
|
|
42792
42864
|
};
|
|
42793
42865
|
}
|
|
42794
42866
|
function profileAccountJsonPaths(profileDir, tool) {
|
|
42795
42867
|
if (!tool.accountFile)
|
|
42796
42868
|
return [];
|
|
42797
|
-
const paths = [
|
|
42869
|
+
const paths = [join7(profileDir, tool.accountFile)];
|
|
42798
42870
|
if (profileDir === tool.defaultDir)
|
|
42799
|
-
paths.push(
|
|
42871
|
+
paths.push(join7(dirname3(profileDir), tool.accountFile));
|
|
42800
42872
|
return paths;
|
|
42801
42873
|
}
|
|
42802
42874
|
function profileAuthDir(profileDir) {
|
|
42803
|
-
return
|
|
42875
|
+
return join7(profileDir, ACCOUNTS_AUTH_DIR);
|
|
42804
42876
|
}
|
|
42805
42877
|
function profileOAuthSnapshot(profileDir) {
|
|
42806
|
-
return
|
|
42878
|
+
return join7(profileAuthDir(profileDir), OAUTH_SNAPSHOT);
|
|
42807
42879
|
}
|
|
42808
42880
|
function profileCredentialsSnapshot(profileDir) {
|
|
42809
|
-
return
|
|
42881
|
+
return join7(profileAuthDir(profileDir), CREDENTIALS_SNAPSHOT);
|
|
42810
42882
|
}
|
|
42811
42883
|
function profileKeychainSnapshot(profileDir) {
|
|
42812
|
-
return
|
|
42884
|
+
return join7(profileAuthDir(profileDir), KEYCHAIN_SNAPSHOT);
|
|
42813
42885
|
}
|
|
42814
42886
|
|
|
42815
42887
|
// src/lib/keychain.ts
|
|
@@ -42963,7 +43035,7 @@ function mergeOAuthInto(paths, oauth, allowDelete, stayUnder) {
|
|
|
42963
43035
|
}
|
|
42964
43036
|
}
|
|
42965
43037
|
function sanitizeSettingsFile(configDir, stayUnder) {
|
|
42966
|
-
const settingsPath =
|
|
43038
|
+
const settingsPath = join8(configDir, "settings.json");
|
|
42967
43039
|
const settings = readJsonFile(settingsPath);
|
|
42968
43040
|
if (!settings)
|
|
42969
43041
|
return false;
|
|
@@ -43010,7 +43082,7 @@ function liveOAuthEmail() {
|
|
|
43010
43082
|
}
|
|
43011
43083
|
function snapshotLiveAuthToProfile(profileDir, _tool) {
|
|
43012
43084
|
const authDir = profileAuthDir(profileDir);
|
|
43013
|
-
assertSafeWritePath(
|
|
43085
|
+
assertSafeWritePath(join8(authDir, OAUTH_SNAPSHOT), { mustStayUnder: profileDir });
|
|
43014
43086
|
mkdirSync4(authDir, { recursive: true });
|
|
43015
43087
|
const live = liveClaudePaths();
|
|
43016
43088
|
const oauth = readOAuthFromPaths([live.homeJson]);
|
|
@@ -43029,14 +43101,14 @@ function snapshotLiveAuthToProfile(profileDir, _tool) {
|
|
|
43029
43101
|
}
|
|
43030
43102
|
function ensureProfileAuthSnapshot(profileDir, tool, opts = {}) {
|
|
43031
43103
|
const authDir = profileAuthDir(profileDir);
|
|
43032
|
-
assertSafeWritePath(
|
|
43104
|
+
assertSafeWritePath(join8(authDir, OAUTH_SNAPSHOT), { mustStayUnder: profileDir });
|
|
43033
43105
|
mkdirSync4(authDir, { recursive: true });
|
|
43034
43106
|
const oauthSource = findOAuthSource(profileAccountJsonPaths(profileDir, tool));
|
|
43035
43107
|
const oauthSnap = profileOAuthSnapshot(profileDir);
|
|
43036
43108
|
if (oauthSource && (opts.overwrite || snapshotIsStale(oauthSource.path, oauthSnap))) {
|
|
43037
43109
|
writeJsonFile(oauthSnap, { oauthAccount: oauthSource.oauth }, profileDir);
|
|
43038
43110
|
}
|
|
43039
|
-
const credFile =
|
|
43111
|
+
const credFile = join8(profileDir, ".credentials.json");
|
|
43040
43112
|
const credSnap = profileCredentialsSnapshot(profileDir);
|
|
43041
43113
|
if (existsSync6(credFile) && (opts.overwrite || snapshotIsStale(credFile, credSnap))) {
|
|
43042
43114
|
assertSafeWritePath(credSnap, { mustStayUnder: profileDir });
|
|
@@ -43098,9 +43170,9 @@ function hasAuthSnapshot(profileDir) {
|
|
|
43098
43170
|
|
|
43099
43171
|
// src/lib/apply-lock.ts
|
|
43100
43172
|
import { closeSync, existsSync as existsSync7, mkdirSync as mkdirSync5, openSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
43101
|
-
import { join as
|
|
43173
|
+
import { join as join9 } from "node:path";
|
|
43102
43174
|
function lockPath() {
|
|
43103
|
-
return
|
|
43175
|
+
return join9(accountsHome(), ".apply.lock");
|
|
43104
43176
|
}
|
|
43105
43177
|
function withApplyLock(fn) {
|
|
43106
43178
|
const home = accountsHome();
|
|
@@ -43349,7 +43421,7 @@ function listAgentsAcrossProfiles(opts = {}) {
|
|
|
43349
43421
|
|
|
43350
43422
|
// src/lib/import-profile.ts
|
|
43351
43423
|
import { cpSync, existsSync as existsSync9 } from "node:fs";
|
|
43352
|
-
import { join as
|
|
43424
|
+
import { join as join10 } from "node:path";
|
|
43353
43425
|
function importProfile(opts) {
|
|
43354
43426
|
const toolId = opts.tool ?? DEFAULT_TOOL;
|
|
43355
43427
|
const tool = getTool(toolId);
|
|
@@ -43359,7 +43431,7 @@ function importProfile(opts) {
|
|
|
43359
43431
|
throw new AccountsError(`config dir does not exist: ${sourceDir}`);
|
|
43360
43432
|
}
|
|
43361
43433
|
if (opts.copy) {
|
|
43362
|
-
const targetDir =
|
|
43434
|
+
const targetDir = join10(profilesDir(), toolId, name);
|
|
43363
43435
|
if (existsSync9(targetDir)) {
|
|
43364
43436
|
throw new AccountsError(`managed copy target already exists: ${targetDir}`);
|
|
43365
43437
|
}
|
|
@@ -43445,7 +43517,7 @@ async function pickProfile(opts = {}) {
|
|
|
43445
43517
|
|
|
43446
43518
|
// src/lib/hook.ts
|
|
43447
43519
|
import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
43448
|
-
import { join as
|
|
43520
|
+
import { join as join11 } from "node:path";
|
|
43449
43521
|
var HOOK_FILE = "claude-hook.sh";
|
|
43450
43522
|
var MARKER = "# accounts-claude-hook";
|
|
43451
43523
|
var NAME_PATTERN = "^[a-z0-9][a-z0-9-]*$";
|
|
@@ -43453,7 +43525,7 @@ function shellQuotePath(path) {
|
|
|
43453
43525
|
return `'${path.replace(/'/g, `'\\''`)}'`;
|
|
43454
43526
|
}
|
|
43455
43527
|
function hookPath() {
|
|
43456
|
-
return
|
|
43528
|
+
return join11(accountsHome(), HOOK_FILE);
|
|
43457
43529
|
}
|
|
43458
43530
|
function hookScript() {
|
|
43459
43531
|
const quotedHook = shellQuotePath(hookPath());
|
|
@@ -43504,7 +43576,7 @@ function shellSnippet() {
|
|
|
43504
43576
|
|
|
43505
43577
|
// src/lib/codex-app.ts
|
|
43506
43578
|
import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
43507
|
-
import { join as
|
|
43579
|
+
import { join as join12 } from "node:path";
|
|
43508
43580
|
var FILE_CREDENTIALS_LINE = 'cli_auth_credentials_store = "file"';
|
|
43509
43581
|
function insertRootConfigLine(config, line) {
|
|
43510
43582
|
if (config.trim() === "")
|
|
@@ -43531,7 +43603,7 @@ ${after}${after.endsWith(`
|
|
|
43531
43603
|
}
|
|
43532
43604
|
function ensureCodexAppProfileConfig(profileDir) {
|
|
43533
43605
|
mkdirSync7(profileDir, { recursive: true });
|
|
43534
|
-
const configPath =
|
|
43606
|
+
const configPath = join12(profileDir, "config.toml");
|
|
43535
43607
|
const current = existsSync11(configPath) ? readFileSync6(configPath, "utf8") : "";
|
|
43536
43608
|
if (/^\s*cli_auth_credentials_store\s*=/.test(current))
|
|
43537
43609
|
return;
|
|
@@ -43631,20 +43703,20 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
43631
43703
|
import { createHash } from "node:crypto";
|
|
43632
43704
|
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync7, readdirSync, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
43633
43705
|
import { createConnection, createServer } from "node:net";
|
|
43634
|
-
import { basename, join as
|
|
43706
|
+
import { basename, join as join13 } from "node:path";
|
|
43635
43707
|
var STATE_SUFFIX = ".json";
|
|
43636
43708
|
function supervisorDir() {
|
|
43637
|
-
return
|
|
43709
|
+
return join13(accountsHome(), "supervisors");
|
|
43638
43710
|
}
|
|
43639
43711
|
function supervisorStatePath(toolId) {
|
|
43640
|
-
return
|
|
43712
|
+
return join13(supervisorDir(), `${toolId}${STATE_SUFFIX}`);
|
|
43641
43713
|
}
|
|
43642
43714
|
function supervisorSocketPath(toolId) {
|
|
43643
43715
|
if (process.platform === "win32") {
|
|
43644
43716
|
const hash = createHash("sha1").update(accountsHome()).digest("hex").slice(0, 12);
|
|
43645
43717
|
return `\\\\.\\pipe\\hasna-accounts-${hash}-${toolId}`;
|
|
43646
43718
|
}
|
|
43647
|
-
return
|
|
43719
|
+
return join13(supervisorDir(), `${toolId}.sock`);
|
|
43648
43720
|
}
|
|
43649
43721
|
function nowIso2() {
|
|
43650
43722
|
return new Date().toISOString();
|
|
@@ -44242,7 +44314,7 @@ program2.command("switch").argument("<name>", "profile name").argument("[args...
|
|
|
44242
44314
|
}
|
|
44243
44315
|
}));
|
|
44244
44316
|
var hook = program2.command("hook").description("install a shell wrapper for claude");
|
|
44245
|
-
hook.command("install").description(`write ${
|
|
44317
|
+
hook.command("install").description(`write ${join14(accountsHome(), "claude-hook.sh")}`).action(action(() => {
|
|
44246
44318
|
const { path, created } = installHook();
|
|
44247
44319
|
console.log(source_default.green(created ? `✓ installed hook at ${path}` : `✓ updated hook at ${path}`));
|
|
44248
44320
|
console.log(source_default.dim(` add to ~/.zshrc: ${shellSnippet()}`));
|
|
@@ -44482,7 +44554,7 @@ tools.command("add").argument("<id>", "tool id, e.g. cursor").description("regis
|
|
|
44482
44554
|
label: opts.label,
|
|
44483
44555
|
envVar: opts.envVar,
|
|
44484
44556
|
bin: opts.bin,
|
|
44485
|
-
defaultDir: opts.defaultDir ? expandPath(opts.defaultDir) :
|
|
44557
|
+
defaultDir: opts.defaultDir ? expandPath(opts.defaultDir) : join14(homedir6(), `.${id}`),
|
|
44486
44558
|
...Object.keys(extraEnv).length > 0 ? { extraEnv } : {},
|
|
44487
44559
|
...opts.loginArg ? { loginArgs: opts.loginArg } : {},
|
|
44488
44560
|
...opts.launchArg ? { launchArgs: opts.launchArg } : {},
|
|
@@ -44554,7 +44626,7 @@ program2.parseAsync(process.argv);
|
|
|
44554
44626
|
function getVersion() {
|
|
44555
44627
|
try {
|
|
44556
44628
|
const here = dirname5(fileURLToPath(import.meta.url));
|
|
44557
|
-
for (const candidate of [
|
|
44629
|
+
for (const candidate of [join14(here, "..", "package.json"), join14(here, "package.json")]) {
|
|
44558
44630
|
if (existsSync13(candidate)) {
|
|
44559
44631
|
const pkg = JSON.parse(readFileSync8(candidate, "utf8"));
|
|
44560
44632
|
if (pkg.version)
|