@hasna/accounts 0.1.6 → 0.1.7
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/README.md +20 -0
- package/dist/cli.js +35075 -27
- package/dist/index.js +46 -16
- package/dist/lib/agents.d.ts +37 -0
- package/dist/lib/agents.d.ts.map +1 -0
- package/dist/lib/apply.d.ts.map +1 -1
- package/dist/lib/claude-auth.d.ts +9 -1
- package/dist/lib/claude-auth.d.ts.map +1 -1
- package/dist/mcp.js +47 -17
- package/dist/storage.d.ts +74 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +4336 -0
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -4085,6 +4085,16 @@ function assertSafeWritePath(filePath, opts) {
|
|
|
4085
4085
|
}
|
|
4086
4086
|
|
|
4087
4087
|
// src/storage.ts
|
|
4088
|
+
var ACCOUNTS_STORAGE_ENV = {
|
|
4089
|
+
mode: "HASNA_ACCOUNTS_STORAGE_MODE",
|
|
4090
|
+
s3Bucket: "HASNA_ACCOUNTS_S3_BUCKET",
|
|
4091
|
+
s3Prefix: "HASNA_ACCOUNTS_S3_PREFIX",
|
|
4092
|
+
awsRegion: "HASNA_ACCOUNTS_AWS_REGION",
|
|
4093
|
+
s3Endpoint: "HASNA_ACCOUNTS_S3_ENDPOINT",
|
|
4094
|
+
s3ForcePathStyle: "HASNA_ACCOUNTS_S3_FORCE_PATH_STYLE",
|
|
4095
|
+
machineId: "HASNA_ACCOUNTS_MACHINE_ID"
|
|
4096
|
+
};
|
|
4097
|
+
var STORAGE_MODE_ENV = ACCOUNTS_STORAGE_ENV.mode;
|
|
4088
4098
|
function validateEnvPath(value, label) {
|
|
4089
4099
|
const trimmed = value.trim();
|
|
4090
4100
|
if (!trimmed || trimmed.includes("\x00") || /[\r\n]/.test(trimmed)) {
|
|
@@ -4551,7 +4561,7 @@ function currentProfile(toolId) {
|
|
|
4551
4561
|
return store.profiles.find((p) => p.name === name);
|
|
4552
4562
|
}
|
|
4553
4563
|
// src/lib/claude-auth.ts
|
|
4554
|
-
import { copyFileSync, existsSync as existsSync5, lstatSync as lstatSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4564
|
+
import { copyFileSync, existsSync as existsSync5, lstatSync as lstatSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync3, statSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4555
4565
|
import { dirname as dirname4, join as join6 } from "node:path";
|
|
4556
4566
|
|
|
4557
4567
|
// src/lib/claude-layout.ts
|
|
@@ -4673,14 +4683,26 @@ function writeJsonFile(path, data, stayUnder) {
|
|
|
4673
4683
|
`, { mode: 384 });
|
|
4674
4684
|
}
|
|
4675
4685
|
function readOAuthFromPaths(paths) {
|
|
4686
|
+
return findOAuthSource(paths)?.oauth;
|
|
4687
|
+
}
|
|
4688
|
+
function findOAuthSource(paths) {
|
|
4676
4689
|
for (const p of paths) {
|
|
4677
4690
|
const data = readJsonFile(p);
|
|
4678
4691
|
const oauth = data?.oauthAccount;
|
|
4679
4692
|
if (oauth && typeof oauth === "object")
|
|
4680
|
-
return oauth;
|
|
4693
|
+
return { path: p, oauth };
|
|
4681
4694
|
}
|
|
4682
4695
|
return;
|
|
4683
4696
|
}
|
|
4697
|
+
function snapshotIsStale(sourcePath, snapshotPath) {
|
|
4698
|
+
if (!existsSync5(snapshotPath))
|
|
4699
|
+
return true;
|
|
4700
|
+
try {
|
|
4701
|
+
return statSync(sourcePath).mtimeMs > statSync(snapshotPath).mtimeMs;
|
|
4702
|
+
} catch {
|
|
4703
|
+
return false;
|
|
4704
|
+
}
|
|
4705
|
+
}
|
|
4684
4706
|
function mergeOAuthInto(paths, oauth, allowDelete, stayUnder) {
|
|
4685
4707
|
const primary = paths[0];
|
|
4686
4708
|
if (!primary)
|
|
@@ -4704,6 +4726,12 @@ function mergeOAuthInto(paths, oauth, allowDelete, stayUnder) {
|
|
|
4704
4726
|
}
|
|
4705
4727
|
}
|
|
4706
4728
|
}
|
|
4729
|
+
function liveOAuthEmail() {
|
|
4730
|
+
const live = liveClaudePaths();
|
|
4731
|
+
const oauth = readOAuthFromPaths([live.homeJson]);
|
|
4732
|
+
const email = oauth?.emailAddress;
|
|
4733
|
+
return typeof email === "string" && email ? email : undefined;
|
|
4734
|
+
}
|
|
4707
4735
|
function snapshotLiveAuthToProfile(profileDir, _tool) {
|
|
4708
4736
|
const authDir = profileAuthDir(profileDir);
|
|
4709
4737
|
assertSafeWritePath(join6(authDir, OAUTH_SNAPSHOT), { mustStayUnder: profileDir });
|
|
@@ -4727,19 +4755,19 @@ function snapshotClaudeAuthToProfile(profileDir, tool) {
|
|
|
4727
4755
|
snapshotLiveAuthToProfile(profileDir, tool);
|
|
4728
4756
|
}
|
|
4729
4757
|
function ensureProfileAuthSnapshot(profileDir, tool, opts = {}) {
|
|
4730
|
-
if (!opts.overwrite && hasAuthSnapshot(profileDir))
|
|
4731
|
-
return;
|
|
4732
4758
|
const authDir = profileAuthDir(profileDir);
|
|
4733
4759
|
assertSafeWritePath(join6(authDir, OAUTH_SNAPSHOT), { mustStayUnder: profileDir });
|
|
4734
4760
|
mkdirSync4(authDir, { recursive: true });
|
|
4735
|
-
const
|
|
4736
|
-
|
|
4737
|
-
|
|
4761
|
+
const oauthSource = findOAuthSource(profileAccountJsonPaths(profileDir, tool));
|
|
4762
|
+
const oauthSnap = profileOAuthSnapshot(profileDir);
|
|
4763
|
+
if (oauthSource && (opts.overwrite || snapshotIsStale(oauthSource.path, oauthSnap))) {
|
|
4764
|
+
writeJsonFile(oauthSnap, { oauthAccount: oauthSource.oauth }, profileDir);
|
|
4765
|
+
}
|
|
4738
4766
|
const credFile = join6(profileDir, ".credentials.json");
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
assertSafeWritePath(
|
|
4742
|
-
copyFileSync(credFile,
|
|
4767
|
+
const credSnap = profileCredentialsSnapshot(profileDir);
|
|
4768
|
+
if (existsSync5(credFile) && (opts.overwrite || snapshotIsStale(credFile, credSnap))) {
|
|
4769
|
+
assertSafeWritePath(credSnap, { mustStayUnder: profileDir });
|
|
4770
|
+
copyFileSync(credFile, credSnap);
|
|
4743
4771
|
}
|
|
4744
4772
|
}
|
|
4745
4773
|
function profileHasAuth(profileDir, tool) {
|
|
@@ -4829,6 +4857,9 @@ function withApplyLock(fn) {
|
|
|
4829
4857
|
}
|
|
4830
4858
|
|
|
4831
4859
|
// src/lib/apply.ts
|
|
4860
|
+
function singleMatch(profiles) {
|
|
4861
|
+
return profiles.length === 1 ? profiles[0] : undefined;
|
|
4862
|
+
}
|
|
4832
4863
|
function appliedProfile(toolId) {
|
|
4833
4864
|
const store = loadStore();
|
|
4834
4865
|
const name = store.applied[toolId];
|
|
@@ -4850,11 +4881,10 @@ function applyProfileUnlocked(name, toolId) {
|
|
|
4850
4881
|
}
|
|
4851
4882
|
const store = loadStore();
|
|
4852
4883
|
const previous = store.applied[tool.id];
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
}
|
|
4884
|
+
const liveEmail = liveOAuthEmail();
|
|
4885
|
+
const owner = liveEmail && singleMatch(store.profiles.filter((p) => p.tool === tool.id && p.email === liveEmail)) || (previous ? store.profiles.find((p) => p.name === previous && p.tool === tool.id) : undefined);
|
|
4886
|
+
if (owner)
|
|
4887
|
+
snapshotLiveAuthToProfile(owner.dir, tool);
|
|
4858
4888
|
ensureProfileAuthSnapshot(profile.dir, tool);
|
|
4859
4889
|
restoreClaudeAuthFromProfile(profile.dir, tool, name);
|
|
4860
4890
|
store.applied[tool.id] = name;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Profile } from "../types.js";
|
|
2
|
+
export type AgentEntry = Record<string, unknown>;
|
|
3
|
+
export interface ProfileAgents {
|
|
4
|
+
profile: string;
|
|
5
|
+
tool: string;
|
|
6
|
+
email?: string;
|
|
7
|
+
dir: string;
|
|
8
|
+
agents: AgentEntry[];
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AgentsRunnerResult {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
raw: string;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
export type AgentsRunner = (profile: Profile) => AgentsRunnerResult;
|
|
17
|
+
/**
|
|
18
|
+
* Extract the first top-level JSON array from output that may be wrapped in
|
|
19
|
+
* pty/ANSI noise (`claude agents --json` only works on a TTY, so we run it
|
|
20
|
+
* under `script` and the JSON arrives surrounded by control sequences).
|
|
21
|
+
*/
|
|
22
|
+
export declare function extractJsonArray(raw: string): unknown[] | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Run `<bin> agents --json` for a profile's config dir under a pseudo-TTY.
|
|
25
|
+
* Claude Code switches to print-mode argument parsing when stdout is not a
|
|
26
|
+
* TTY and never reaches the `agents` subcommand, so a plain pipe won't work.
|
|
27
|
+
*/
|
|
28
|
+
export declare function runClaudeAgentsJson(profile: Profile, timeoutMs?: number): AgentsRunnerResult;
|
|
29
|
+
export interface ListAgentsOptions {
|
|
30
|
+
tool?: string;
|
|
31
|
+
profile?: string;
|
|
32
|
+
backgroundOnly?: boolean;
|
|
33
|
+
runner?: AgentsRunner;
|
|
34
|
+
}
|
|
35
|
+
/** List agent sessions for every profile of a tool (default: claude). */
|
|
36
|
+
export declare function listAgentsAcrossProfiles(opts?: ListAgentsOptions): ProfileAgents[];
|
|
37
|
+
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/lib/agents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,kBAAkB,CAAC;AAEpE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,SAAS,CA+BnE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,SAAS,GAAG,kBAAkB,CAqB5F;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,yEAAyE;AACzE,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,iBAAsB,GAAG,aAAa,EAAE,CAwBtF"}
|
package/dist/lib/apply.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/lib/apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/lib/apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAkB3C,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAKlE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAEnG"}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import type { ToolDef } from "../types.js";
|
|
2
|
+
/** Email address of the account currently authenticated on the live Claude paths. */
|
|
3
|
+
export declare function liveOAuthEmail(): string | undefined;
|
|
2
4
|
/** Snapshot live Claude auth into a profile directory (used when switching away on apply). */
|
|
3
5
|
export declare function snapshotLiveAuthToProfile(profileDir: string, _tool: ToolDef): void;
|
|
4
6
|
/** @deprecated Use snapshotLiveAuthToProfile */
|
|
5
7
|
export declare function snapshotClaudeAuthToProfile(profileDir: string, tool: ToolDef): void;
|
|
6
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Build auth snapshots from files already present in the profile config dir.
|
|
10
|
+
* Snapshots are refreshed per-file whenever the source in the profile dir is
|
|
11
|
+
* newer than the existing snapshot — a running tool rotates its OAuth tokens
|
|
12
|
+
* in place, and restoring a login-time snapshot over rotated tokens logs the
|
|
13
|
+
* account out (rotated-out refresh tokens are revoked server-side).
|
|
14
|
+
*/
|
|
7
15
|
export declare function ensureProfileAuthSnapshot(profileDir: string, tool: ToolDef, opts?: {
|
|
8
16
|
overwrite?: boolean;
|
|
9
17
|
}): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-auth.d.ts","sourceRoot":"","sources":["../../src/lib/claude-auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-auth.d.ts","sourceRoot":"","sources":["../../src/lib/claude-auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAyF3C,qFAAqF;AACrF,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CAKnD;AAED,8FAA8F;AAC9F,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAmBlF;AAED,gDAAgD;AAChD,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAEnF;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,EACb,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,IAAI,CAiBN;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAEzE;AAED,6DAA6D;AAC7D,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI,CAqDN;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAM3D"}
|
package/dist/mcp.js
CHANGED
|
@@ -16721,6 +16721,16 @@ function assertSafeWritePath(filePath, opts) {
|
|
|
16721
16721
|
}
|
|
16722
16722
|
|
|
16723
16723
|
// src/storage.ts
|
|
16724
|
+
var ACCOUNTS_STORAGE_ENV = {
|
|
16725
|
+
mode: "HASNA_ACCOUNTS_STORAGE_MODE",
|
|
16726
|
+
s3Bucket: "HASNA_ACCOUNTS_S3_BUCKET",
|
|
16727
|
+
s3Prefix: "HASNA_ACCOUNTS_S3_PREFIX",
|
|
16728
|
+
awsRegion: "HASNA_ACCOUNTS_AWS_REGION",
|
|
16729
|
+
s3Endpoint: "HASNA_ACCOUNTS_S3_ENDPOINT",
|
|
16730
|
+
s3ForcePathStyle: "HASNA_ACCOUNTS_S3_FORCE_PATH_STYLE",
|
|
16731
|
+
machineId: "HASNA_ACCOUNTS_MACHINE_ID"
|
|
16732
|
+
};
|
|
16733
|
+
var STORAGE_MODE_ENV = ACCOUNTS_STORAGE_ENV.mode;
|
|
16724
16734
|
function validateEnvPath(value, label) {
|
|
16725
16735
|
const trimmed = value.trim();
|
|
16726
16736
|
if (!trimmed || trimmed.includes("\x00") || /[\r\n]/.test(trimmed)) {
|
|
@@ -16956,7 +16966,7 @@ function currentProfile(toolId) {
|
|
|
16956
16966
|
}
|
|
16957
16967
|
|
|
16958
16968
|
// src/lib/claude-auth.ts
|
|
16959
|
-
import { copyFileSync, existsSync as existsSync3, lstatSync as lstatSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
16969
|
+
import { copyFileSync, existsSync as existsSync3, lstatSync as lstatSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2, statSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
16960
16970
|
import { dirname as dirname3, join as join4 } from "node:path";
|
|
16961
16971
|
|
|
16962
16972
|
// src/lib/claude-layout.ts
|
|
@@ -17078,14 +17088,26 @@ function writeJsonFile(path, data, stayUnder) {
|
|
|
17078
17088
|
`, { mode: 384 });
|
|
17079
17089
|
}
|
|
17080
17090
|
function readOAuthFromPaths(paths) {
|
|
17091
|
+
return findOAuthSource(paths)?.oauth;
|
|
17092
|
+
}
|
|
17093
|
+
function findOAuthSource(paths) {
|
|
17081
17094
|
for (const p of paths) {
|
|
17082
17095
|
const data = readJsonFile(p);
|
|
17083
17096
|
const oauth = data?.oauthAccount;
|
|
17084
17097
|
if (oauth && typeof oauth === "object")
|
|
17085
|
-
return oauth;
|
|
17098
|
+
return { path: p, oauth };
|
|
17086
17099
|
}
|
|
17087
17100
|
return;
|
|
17088
17101
|
}
|
|
17102
|
+
function snapshotIsStale(sourcePath, snapshotPath) {
|
|
17103
|
+
if (!existsSync3(snapshotPath))
|
|
17104
|
+
return true;
|
|
17105
|
+
try {
|
|
17106
|
+
return statSync(sourcePath).mtimeMs > statSync(snapshotPath).mtimeMs;
|
|
17107
|
+
} catch {
|
|
17108
|
+
return false;
|
|
17109
|
+
}
|
|
17110
|
+
}
|
|
17089
17111
|
function mergeOAuthInto(paths, oauth, allowDelete, stayUnder) {
|
|
17090
17112
|
const primary = paths[0];
|
|
17091
17113
|
if (!primary)
|
|
@@ -17109,6 +17131,12 @@ function mergeOAuthInto(paths, oauth, allowDelete, stayUnder) {
|
|
|
17109
17131
|
}
|
|
17110
17132
|
}
|
|
17111
17133
|
}
|
|
17134
|
+
function liveOAuthEmail() {
|
|
17135
|
+
const live = liveClaudePaths();
|
|
17136
|
+
const oauth = readOAuthFromPaths([live.homeJson]);
|
|
17137
|
+
const email2 = oauth?.emailAddress;
|
|
17138
|
+
return typeof email2 === "string" && email2 ? email2 : undefined;
|
|
17139
|
+
}
|
|
17112
17140
|
function snapshotLiveAuthToProfile(profileDir, _tool) {
|
|
17113
17141
|
const authDir = profileAuthDir(profileDir);
|
|
17114
17142
|
assertSafeWritePath(join4(authDir, OAUTH_SNAPSHOT), { mustStayUnder: profileDir });
|
|
@@ -17129,19 +17157,19 @@ function snapshotLiveAuthToProfile(profileDir, _tool) {
|
|
|
17129
17157
|
}
|
|
17130
17158
|
}
|
|
17131
17159
|
function ensureProfileAuthSnapshot(profileDir, tool, opts = {}) {
|
|
17132
|
-
if (!opts.overwrite && hasAuthSnapshot(profileDir))
|
|
17133
|
-
return;
|
|
17134
17160
|
const authDir = profileAuthDir(profileDir);
|
|
17135
17161
|
assertSafeWritePath(join4(authDir, OAUTH_SNAPSHOT), { mustStayUnder: profileDir });
|
|
17136
17162
|
mkdirSync3(authDir, { recursive: true });
|
|
17137
|
-
const
|
|
17138
|
-
|
|
17139
|
-
|
|
17163
|
+
const oauthSource = findOAuthSource(profileAccountJsonPaths(profileDir, tool));
|
|
17164
|
+
const oauthSnap = profileOAuthSnapshot(profileDir);
|
|
17165
|
+
if (oauthSource && (opts.overwrite || snapshotIsStale(oauthSource.path, oauthSnap))) {
|
|
17166
|
+
writeJsonFile(oauthSnap, { oauthAccount: oauthSource.oauth }, profileDir);
|
|
17167
|
+
}
|
|
17140
17168
|
const credFile = join4(profileDir, ".credentials.json");
|
|
17141
|
-
|
|
17142
|
-
|
|
17143
|
-
assertSafeWritePath(
|
|
17144
|
-
copyFileSync(credFile,
|
|
17169
|
+
const credSnap = profileCredentialsSnapshot(profileDir);
|
|
17170
|
+
if (existsSync3(credFile) && (opts.overwrite || snapshotIsStale(credFile, credSnap))) {
|
|
17171
|
+
assertSafeWritePath(credSnap, { mustStayUnder: profileDir });
|
|
17172
|
+
copyFileSync(credFile, credSnap);
|
|
17145
17173
|
}
|
|
17146
17174
|
}
|
|
17147
17175
|
function profileHasAuth(profileDir, tool) {
|
|
@@ -17231,6 +17259,9 @@ function withApplyLock(fn) {
|
|
|
17231
17259
|
}
|
|
17232
17260
|
|
|
17233
17261
|
// src/lib/apply.ts
|
|
17262
|
+
function singleMatch(profiles) {
|
|
17263
|
+
return profiles.length === 1 ? profiles[0] : undefined;
|
|
17264
|
+
}
|
|
17234
17265
|
function appliedProfile(toolId) {
|
|
17235
17266
|
const store = loadStore();
|
|
17236
17267
|
const name = store.applied[toolId];
|
|
@@ -17252,11 +17283,10 @@ function applyProfileUnlocked(name, toolId) {
|
|
|
17252
17283
|
}
|
|
17253
17284
|
const store = loadStore();
|
|
17254
17285
|
const previous = store.applied[tool.id];
|
|
17255
|
-
|
|
17256
|
-
|
|
17257
|
-
|
|
17258
|
-
|
|
17259
|
-
}
|
|
17286
|
+
const liveEmail = liveOAuthEmail();
|
|
17287
|
+
const owner = liveEmail && singleMatch(store.profiles.filter((p) => p.tool === tool.id && p.email === liveEmail)) || (previous ? store.profiles.find((p) => p.name === previous && p.tool === tool.id) : undefined);
|
|
17288
|
+
if (owner)
|
|
17289
|
+
snapshotLiveAuthToProfile(owner.dir, tool);
|
|
17260
17290
|
ensureProfileAuthSnapshot(profile.dir, tool);
|
|
17261
17291
|
restoreClaudeAuthFromProfile(profile.dir, tool, name);
|
|
17262
17292
|
store.applied[tool.id] = name;
|
|
@@ -17434,7 +17464,7 @@ function ok(data) {
|
|
|
17434
17464
|
function fail(message) {
|
|
17435
17465
|
return { content: [{ type: "text", text: JSON.stringify({ error: message }) }], isError: true };
|
|
17436
17466
|
}
|
|
17437
|
-
var server = new Server({ name: "accounts", version: "0.1.
|
|
17467
|
+
var server = new Server({ name: "accounts", version: "0.1.7" }, { capabilities: { tools: {} } });
|
|
17438
17468
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
17439
17469
|
tools: [
|
|
17440
17470
|
{
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,4 +1,69 @@
|
|
|
1
1
|
import { type Store } from "./types.js";
|
|
2
|
+
export declare const ACCOUNTS_STORAGE_ENV: {
|
|
3
|
+
readonly mode: "HASNA_ACCOUNTS_STORAGE_MODE";
|
|
4
|
+
readonly s3Bucket: "HASNA_ACCOUNTS_S3_BUCKET";
|
|
5
|
+
readonly s3Prefix: "HASNA_ACCOUNTS_S3_PREFIX";
|
|
6
|
+
readonly awsRegion: "HASNA_ACCOUNTS_AWS_REGION";
|
|
7
|
+
readonly s3Endpoint: "HASNA_ACCOUNTS_S3_ENDPOINT";
|
|
8
|
+
readonly s3ForcePathStyle: "HASNA_ACCOUNTS_S3_FORCE_PATH_STYLE";
|
|
9
|
+
readonly machineId: "HASNA_ACCOUNTS_MACHINE_ID";
|
|
10
|
+
};
|
|
11
|
+
export declare const ACCOUNTS_STORAGE_FALLBACK_ENV: {
|
|
12
|
+
readonly mode: "ACCOUNTS_STORAGE_MODE";
|
|
13
|
+
readonly s3Bucket: "ACCOUNTS_S3_BUCKET";
|
|
14
|
+
readonly s3Prefix: "ACCOUNTS_S3_PREFIX";
|
|
15
|
+
readonly awsRegion: "ACCOUNTS_AWS_REGION";
|
|
16
|
+
readonly s3Endpoint: "ACCOUNTS_S3_ENDPOINT";
|
|
17
|
+
readonly s3ForcePathStyle: "ACCOUNTS_S3_FORCE_PATH_STYLE";
|
|
18
|
+
readonly machineId: "ACCOUNTS_MACHINE_ID";
|
|
19
|
+
};
|
|
20
|
+
export declare const STORAGE_MODE_ENV: "HASNA_ACCOUNTS_STORAGE_MODE";
|
|
21
|
+
export declare const STORAGE_TABLES: readonly [];
|
|
22
|
+
export type AccountsStorageMode = "local" | "remote" | "hybrid";
|
|
23
|
+
export interface AccountsStorageConfig {
|
|
24
|
+
mode: AccountsStorageMode;
|
|
25
|
+
s3Bucket?: string;
|
|
26
|
+
s3Prefix: string;
|
|
27
|
+
awsRegion?: string;
|
|
28
|
+
s3Endpoint?: string;
|
|
29
|
+
s3ForcePathStyle?: boolean;
|
|
30
|
+
machineId: string;
|
|
31
|
+
}
|
|
32
|
+
export interface AccountsStorageStatus {
|
|
33
|
+
configured: boolean;
|
|
34
|
+
mode: AccountsStorageMode;
|
|
35
|
+
local: {
|
|
36
|
+
home: string;
|
|
37
|
+
storePath: string;
|
|
38
|
+
profilesDir: string;
|
|
39
|
+
};
|
|
40
|
+
remote: {
|
|
41
|
+
configured: boolean;
|
|
42
|
+
bucketEnv: string;
|
|
43
|
+
bucket?: string;
|
|
44
|
+
prefix: string;
|
|
45
|
+
regionEnv: string;
|
|
46
|
+
endpointConfigured: boolean;
|
|
47
|
+
};
|
|
48
|
+
env: typeof ACCOUNTS_STORAGE_ENV;
|
|
49
|
+
fallbackEnv: typeof ACCOUNTS_STORAGE_FALLBACK_ENV;
|
|
50
|
+
tables: readonly [];
|
|
51
|
+
}
|
|
52
|
+
export interface AccountsStorageSnapshot {
|
|
53
|
+
schemaVersion: 1;
|
|
54
|
+
source: "accounts";
|
|
55
|
+
createdAt: string;
|
|
56
|
+
machineId: string;
|
|
57
|
+
store: Store;
|
|
58
|
+
}
|
|
59
|
+
export interface AccountsStorageSyncResult {
|
|
60
|
+
mode: AccountsStorageMode;
|
|
61
|
+
pushed: number;
|
|
62
|
+
pulled: number;
|
|
63
|
+
skipped: boolean;
|
|
64
|
+
key: string;
|
|
65
|
+
reason?: string;
|
|
66
|
+
}
|
|
2
67
|
/** Base directory for all accounts state. Override with `ACCOUNTS_HOME`. */
|
|
3
68
|
export declare function accountsHome(): string;
|
|
4
69
|
/** Path to the registry file. Override with `ACCOUNTS_STORE_PATH`. */
|
|
@@ -7,4 +72,13 @@ export declare function storePath(): string;
|
|
|
7
72
|
export declare function profilesDir(): string;
|
|
8
73
|
export declare function loadStore(): Store;
|
|
9
74
|
export declare function saveStore(store: Store): void;
|
|
75
|
+
export declare function getAccountsStorageConfig(env?: NodeJS.ProcessEnv): AccountsStorageConfig;
|
|
76
|
+
export declare function getAccountsStorageStatus(env?: NodeJS.ProcessEnv): AccountsStorageStatus;
|
|
77
|
+
export declare function createAccountsStorageSnapshot(env?: NodeJS.ProcessEnv): AccountsStorageSnapshot;
|
|
78
|
+
export declare function restoreAccountsStorageSnapshot(snapshot: AccountsStorageSnapshot): void;
|
|
79
|
+
export declare function accountsStorageSnapshotKey(env?: NodeJS.ProcessEnv): string;
|
|
80
|
+
export declare function storagePush(env?: NodeJS.ProcessEnv): Promise<AccountsStorageSyncResult>;
|
|
81
|
+
export declare function storagePull(env?: NodeJS.ProcessEnv): Promise<AccountsStorageSyncResult>;
|
|
82
|
+
export declare function storageSync(env?: NodeJS.ProcessEnv): Promise<AccountsStorageSyncResult>;
|
|
83
|
+
export declare const getStorageStatus: typeof getAccountsStorageStatus;
|
|
10
84
|
//# sourceMappingURL=storage.d.ts.map
|
package/dist/storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
|