sidekick-shared 0.26.5 → 0.26.6
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/CHANGELOG.md +35 -0
- package/README.md +56 -51
- package/dist/accountChanges.js +21 -2
- package/dist/accountHealth.d.ts +72 -0
- package/dist/accountHealth.js +286 -0
- package/dist/accountLaunch.d.ts +30 -0
- package/dist/accountLaunch.js +124 -0
- package/dist/accountManager.d.ts +33 -8
- package/dist/accountManager.js +183 -50
- package/dist/accountRegistry.d.ts +10 -0
- package/dist/accountRegistry.js +42 -22
- package/dist/accountSwitch.d.ts +43 -0
- package/dist/accountSwitch.js +115 -0
- package/dist/accountSync.d.ts +30 -0
- package/dist/accountSync.js +180 -0
- package/dist/accountSyncTypes.d.ts +25 -0
- package/dist/accountSyncTypes.js +7 -0
- package/dist/accounts.d.ts +58 -6
- package/dist/accounts.js +408 -189
- package/dist/claudeCredentials.d.ts +38 -0
- package/dist/claudeCredentials.js +74 -0
- package/dist/claudeProfiles.d.ts +40 -0
- package/dist/claudeProfiles.js +102 -10
- package/dist/codexAuth.d.ts +32 -0
- package/dist/codexAuth.js +127 -0
- package/dist/codexPaths.d.ts +21 -0
- package/dist/codexPaths.js +117 -0
- package/dist/codexProfiles.d.ts +58 -5
- package/dist/codexProfiles.js +574 -289
- package/dist/credentialIO.d.ts +12 -5
- package/dist/credentialIO.js +63 -29
- package/dist/credentials.d.ts +8 -0
- package/dist/credentials.js +28 -32
- package/dist/ensureDefaultAccounts.d.ts +8 -0
- package/dist/ensureDefaultAccounts.js +42 -82
- package/dist/index.d.ts +27 -10
- package/dist/index.js +61 -9
- package/dist/keepAlive.d.ts +44 -0
- package/dist/keepAlive.js +106 -0
- package/dist/processDetection.d.ts +32 -0
- package/dist/processDetection.js +210 -0
- package/dist/schemas/accountManager.d.ts +283 -1
- package/dist/schemas/accountManager.js +122 -1
- package/dist/schemas/assistantTurn.d.ts +2 -2
- package/dist/schemas/index.d.ts +6 -1
- package/dist/schemas/index.js +14 -1
- package/dist/schemas/observedSessionV1.d.ts +21 -21
- package/dist/schemas/quota.d.ts +18 -18
- package/dist/schemas/quotaHistory.d.ts +1 -1
- package/dist/schemas/stateFile.d.ts +5 -5
- package/dist/terminalSync.d.ts +5 -5
- package/dist/terminalSync.js +7 -112
- package/dist/writers/atomic.d.ts +2 -0
- package/dist/writers/atomic.js +49 -2
- package/package.json +1 -1
package/dist/credentialIO.d.ts
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* Platform-aware credential I/O for Claude Code.
|
|
3
3
|
*
|
|
4
4
|
* On macOS, Claude Code stores OAuth credentials in the system Keychain
|
|
5
|
-
* (service "Claude Code-credentials"). On
|
|
6
|
-
* live in
|
|
5
|
+
* (service "Claude Code-credentials", suffixed per config directory). On
|
|
6
|
+
* Linux/WSL/Windows, credentials live in `<home>/.credentials.json`. When the
|
|
7
|
+
* Keychain is unavailable (locked, SSH) Claude Code falls back to the file on
|
|
8
|
+
* macOS too, so reads consult the file after a Keychain miss.
|
|
7
9
|
*
|
|
8
10
|
* Both accounts.ts and credentials.ts consume this module so that all
|
|
9
11
|
* credential access is platform-correct in one place.
|
|
@@ -12,8 +14,8 @@ export declare const KEYCHAIN_SERVICE = "Claude Code-credentials";
|
|
|
12
14
|
/**
|
|
13
15
|
* Read the active Claude Code credentials as a parsed object.
|
|
14
16
|
*
|
|
15
|
-
* - macOS: reads from system Keychain via the `security` CLI
|
|
16
|
-
* - Linux / WSL / Windows: reads
|
|
17
|
+
* - macOS: reads from system Keychain via the `security` CLI, then the file
|
|
18
|
+
* - Linux / WSL / Windows: reads `<home>/.credentials.json`
|
|
17
19
|
*
|
|
18
20
|
* Returns `null` when credentials are absent or unreadable.
|
|
19
21
|
*/
|
|
@@ -22,8 +24,13 @@ export declare function readActiveCredentials(configDir?: string): unknown;
|
|
|
22
24
|
* Write credentials to the active Claude Code credential store.
|
|
23
25
|
*
|
|
24
26
|
* - macOS: writes to system Keychain via the `security` CLI
|
|
25
|
-
* - Linux / WSL / Windows: atomic-writes
|
|
27
|
+
* - Linux / WSL / Windows: atomic-writes `<home>/.credentials.json`
|
|
26
28
|
*
|
|
27
29
|
* Throws on failure.
|
|
28
30
|
*/
|
|
29
31
|
export declare function writeActiveCredentials(credentials: unknown, configDir?: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Remove the credential store of a config directory (an abandoned isolated
|
|
34
|
+
* login, a removed profile). Best effort: never throws.
|
|
35
|
+
*/
|
|
36
|
+
export declare function deleteStoredCredentials(configDir: string): void;
|
package/dist/credentialIO.js
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
* Platform-aware credential I/O for Claude Code.
|
|
4
4
|
*
|
|
5
5
|
* On macOS, Claude Code stores OAuth credentials in the system Keychain
|
|
6
|
-
* (service "Claude Code-credentials"). On
|
|
7
|
-
* live in
|
|
6
|
+
* (service "Claude Code-credentials", suffixed per config directory). On
|
|
7
|
+
* Linux/WSL/Windows, credentials live in `<home>/.credentials.json`. When the
|
|
8
|
+
* Keychain is unavailable (locked, SSH) Claude Code falls back to the file on
|
|
9
|
+
* macOS too, so reads consult the file after a Keychain miss.
|
|
8
10
|
*
|
|
9
11
|
* Both accounts.ts and credentials.ts consume this module so that all
|
|
10
12
|
* credential access is platform-correct in one place.
|
|
@@ -46,12 +48,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
46
48
|
exports.KEYCHAIN_SERVICE = void 0;
|
|
47
49
|
exports.readActiveCredentials = readActiveCredentials;
|
|
48
50
|
exports.writeActiveCredentials = writeActiveCredentials;
|
|
51
|
+
exports.deleteStoredCredentials = deleteStoredCredentials;
|
|
49
52
|
const fs = __importStar(require("fs"));
|
|
50
53
|
const path = __importStar(require("path"));
|
|
51
|
-
const os = __importStar(require("os"));
|
|
52
54
|
const child_process_1 = require("child_process");
|
|
53
55
|
const claudeProfiles_1 = require("./claudeProfiles");
|
|
56
|
+
const atomic_1 = require("./writers/atomic");
|
|
54
57
|
exports.KEYCHAIN_SERVICE = 'Claude Code-credentials';
|
|
58
|
+
const SECURITY_TIMEOUT_MS = 4000;
|
|
55
59
|
function quoteSecurityInteractiveArg(value) {
|
|
56
60
|
// `security -i` is not a POSIX shell: adjacent quoted segments do NOT
|
|
57
61
|
// concatenate (so the shell-style '\'' splice splits the token), and
|
|
@@ -59,39 +63,49 @@ function quoteSecurityInteractiveArg(value) {
|
|
|
59
63
|
return `'${value.replace(/\\/g, '\\\\').replace(/'/g, `\\'`)}'`;
|
|
60
64
|
}
|
|
61
65
|
function getCredentialsFilePath(configDir) {
|
|
62
|
-
return path.join(configDir ??
|
|
66
|
+
return path.join(configDir ?? (0, claudeProfiles_1.getLiveClaudeHome)(), '.credentials.json');
|
|
67
|
+
}
|
|
68
|
+
function readCredentialsFile(configDir) {
|
|
69
|
+
try {
|
|
70
|
+
return JSON.parse(fs.readFileSync(getCredentialsFilePath(configDir), 'utf8'));
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function readKeychainItem(service) {
|
|
77
|
+
try {
|
|
78
|
+
const raw = (0, child_process_1.execFileSync)('security', ['find-generic-password', '-s', service, '-w'], {
|
|
79
|
+
encoding: 'utf8',
|
|
80
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
81
|
+
timeout: SECURITY_TIMEOUT_MS,
|
|
82
|
+
killSignal: 'SIGKILL',
|
|
83
|
+
});
|
|
84
|
+
return JSON.parse(raw.trim());
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
63
89
|
}
|
|
64
90
|
/**
|
|
65
91
|
* Read the active Claude Code credentials as a parsed object.
|
|
66
92
|
*
|
|
67
|
-
* - macOS: reads from system Keychain via the `security` CLI
|
|
68
|
-
* - Linux / WSL / Windows: reads
|
|
93
|
+
* - macOS: reads from system Keychain via the `security` CLI, then the file
|
|
94
|
+
* - Linux / WSL / Windows: reads `<home>/.credentials.json`
|
|
69
95
|
*
|
|
70
96
|
* Returns `null` when credentials are absent or unreadable.
|
|
71
97
|
*/
|
|
72
98
|
function readActiveCredentials(configDir) {
|
|
73
99
|
if (process.platform === 'darwin') {
|
|
74
|
-
|
|
75
|
-
const raw = (0, child_process_1.execFileSync)('security', ['find-generic-password', '-s', (0, claudeProfiles_1.claudeKeychainService)(configDir), '-w'], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 4000, killSignal: 'SIGKILL' });
|
|
76
|
-
return JSON.parse(raw.trim());
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
// Linux / WSL / Windows — file-based
|
|
83
|
-
try {
|
|
84
|
-
return JSON.parse(fs.readFileSync(getCredentialsFilePath(configDir), 'utf8'));
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
return null;
|
|
100
|
+
return readKeychainItem((0, claudeProfiles_1.claudeKeychainService)(configDir)) ?? readCredentialsFile(configDir);
|
|
88
101
|
}
|
|
102
|
+
return readCredentialsFile(configDir);
|
|
89
103
|
}
|
|
90
104
|
/**
|
|
91
105
|
* Write credentials to the active Claude Code credential store.
|
|
92
106
|
*
|
|
93
107
|
* - macOS: writes to system Keychain via the `security` CLI
|
|
94
|
-
* - Linux / WSL / Windows: atomic-writes
|
|
108
|
+
* - Linux / WSL / Windows: atomic-writes `<home>/.credentials.json`
|
|
95
109
|
*
|
|
96
110
|
* Throws on failure.
|
|
97
111
|
*/
|
|
@@ -100,28 +114,48 @@ function writeActiveCredentials(credentials, configDir) {
|
|
|
100
114
|
JSON.parse(json); // validate round-trip
|
|
101
115
|
if (process.platform === 'darwin') {
|
|
102
116
|
const service = (0, claudeProfiles_1.claudeKeychainService)(configDir);
|
|
103
|
-
const account = process.env.USER || 'user';
|
|
104
117
|
const command = [
|
|
105
118
|
'add-generic-password',
|
|
106
119
|
'-U',
|
|
107
120
|
'-s',
|
|
108
121
|
quoteSecurityInteractiveArg(service),
|
|
109
122
|
'-a',
|
|
110
|
-
quoteSecurityInteractiveArg(
|
|
123
|
+
quoteSecurityInteractiveArg((0, claudeProfiles_1.claudeKeychainAccountName)()),
|
|
111
124
|
'-w',
|
|
112
125
|
quoteSecurityInteractiveArg(json),
|
|
113
126
|
].join(' ');
|
|
114
127
|
(0, child_process_1.execFileSync)('security', ['-i'], {
|
|
115
128
|
input: command + '\n',
|
|
116
129
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
117
|
-
timeout:
|
|
130
|
+
timeout: SECURITY_TIMEOUT_MS,
|
|
118
131
|
killSignal: 'SIGKILL',
|
|
119
132
|
});
|
|
120
133
|
return;
|
|
121
134
|
}
|
|
122
|
-
// Linux / WSL / Windows — file-based
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
135
|
+
// Linux / WSL / Windows — file-based (tmp + fsync + rename, retried on Windows)
|
|
136
|
+
(0, atomic_1.atomicWriteFileSync)(getCredentialsFilePath(configDir), json, 0o600);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Remove the credential store of a config directory (an abandoned isolated
|
|
140
|
+
* login, a removed profile). Best effort: never throws.
|
|
141
|
+
*/
|
|
142
|
+
function deleteStoredCredentials(configDir) {
|
|
143
|
+
if (process.platform === 'darwin') {
|
|
144
|
+
try {
|
|
145
|
+
(0, child_process_1.execFileSync)('security', ['delete-generic-password', '-s', (0, claudeProfiles_1.claudeKeychainService)(configDir)], {
|
|
146
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
147
|
+
timeout: SECURITY_TIMEOUT_MS,
|
|
148
|
+
killSignal: 'SIGKILL',
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
/* no item, or keychain unavailable */
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
fs.rmSync(getCredentialsFilePath(configDir), { force: true });
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
/* best effort */
|
|
160
|
+
}
|
|
127
161
|
}
|
package/dist/credentials.d.ts
CHANGED
|
@@ -7,8 +7,10 @@ export interface ClaudeMaxCredentials {
|
|
|
7
7
|
accessToken: string;
|
|
8
8
|
refreshToken?: string;
|
|
9
9
|
expiresAt?: number;
|
|
10
|
+
refreshTokenExpiresAt?: number;
|
|
10
11
|
scopes?: string[];
|
|
11
12
|
subscriptionType?: string;
|
|
13
|
+
rateLimitTier?: string;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Reads Claude Max OAuth credentials.
|
|
@@ -18,6 +20,12 @@ export interface ClaudeMaxCredentials {
|
|
|
18
20
|
* absent, the token is missing, or the token is expired. Never throws.
|
|
19
21
|
*/
|
|
20
22
|
export declare function readClaudeMaxCredentials(): Promise<ClaudeMaxCredentials | null>;
|
|
23
|
+
/**
|
|
24
|
+
* Like {@link readClaudeMaxCredentials} but returns the stored credential even
|
|
25
|
+
* when the access token has lapsed: the CLI refreshes it on next use, so an
|
|
26
|
+
* expired access token is still a valid login (until the refresh token expires).
|
|
27
|
+
*/
|
|
28
|
+
export declare function readClaudeMaxCredentialsRaw(): ClaudeMaxCredentials | null;
|
|
21
29
|
/**
|
|
22
30
|
* Synchronous convenience — returns just the access token or `null`.
|
|
23
31
|
*/
|
package/dist/credentials.js
CHANGED
|
@@ -6,8 +6,18 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.readClaudeMaxCredentials = readClaudeMaxCredentials;
|
|
9
|
+
exports.readClaudeMaxCredentialsRaw = readClaudeMaxCredentialsRaw;
|
|
9
10
|
exports.readClaudeMaxAccessTokenSync = readClaudeMaxAccessTokenSync;
|
|
11
|
+
const claudeCredentials_1 = require("./claudeCredentials");
|
|
10
12
|
const credentialIO_1 = require("./credentialIO");
|
|
13
|
+
function readParsed() {
|
|
14
|
+
try {
|
|
15
|
+
return (0, claudeCredentials_1.parseClaudeCredentialBlob)((0, credentialIO_1.readActiveCredentials)());
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
11
21
|
/**
|
|
12
22
|
* Reads Claude Max OAuth credentials.
|
|
13
23
|
*
|
|
@@ -16,43 +26,29 @@ const credentialIO_1 = require("./credentialIO");
|
|
|
16
26
|
* absent, the token is missing, or the token is expired. Never throws.
|
|
17
27
|
*/
|
|
18
28
|
async function readClaudeMaxCredentials() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (!raw)
|
|
22
|
-
return null;
|
|
23
|
-
const oauth = raw.claudeAiOauth;
|
|
24
|
-
if (!oauth?.accessToken)
|
|
25
|
-
return null;
|
|
26
|
-
if (oauth.expiresAt && Date.now() > oauth.expiresAt)
|
|
27
|
-
return null;
|
|
28
|
-
return {
|
|
29
|
-
accessToken: oauth.accessToken,
|
|
30
|
-
refreshToken: oauth.refreshToken,
|
|
31
|
-
expiresAt: oauth.expiresAt,
|
|
32
|
-
scopes: oauth.scopes,
|
|
33
|
-
subscriptionType: oauth.subscriptionType,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
29
|
+
const parsed = readParsed();
|
|
30
|
+
if (!parsed)
|
|
37
31
|
return null;
|
|
38
|
-
|
|
32
|
+
if (parsed.expiresAt && Date.now() > parsed.expiresAt)
|
|
33
|
+
return null;
|
|
34
|
+
return parsed;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Like {@link readClaudeMaxCredentials} but returns the stored credential even
|
|
38
|
+
* when the access token has lapsed: the CLI refreshes it on next use, so an
|
|
39
|
+
* expired access token is still a valid login (until the refresh token expires).
|
|
40
|
+
*/
|
|
41
|
+
function readClaudeMaxCredentialsRaw() {
|
|
42
|
+
return readParsed();
|
|
39
43
|
}
|
|
40
44
|
/**
|
|
41
45
|
* Synchronous convenience — returns just the access token or `null`.
|
|
42
46
|
*/
|
|
43
47
|
function readClaudeMaxAccessTokenSync() {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (!raw)
|
|
47
|
-
return null;
|
|
48
|
-
const oauth = raw.claudeAiOauth;
|
|
49
|
-
if (!oauth?.accessToken)
|
|
50
|
-
return null;
|
|
51
|
-
if (oauth.expiresAt && Date.now() > oauth.expiresAt)
|
|
52
|
-
return null;
|
|
53
|
-
return oauth.accessToken;
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
48
|
+
const parsed = readParsed();
|
|
49
|
+
if (!parsed)
|
|
56
50
|
return null;
|
|
57
|
-
|
|
51
|
+
if (parsed.expiresAt && Date.now() > parsed.expiresAt)
|
|
52
|
+
return null;
|
|
53
|
+
return parsed.accessToken;
|
|
58
54
|
}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
import type { SyncReport } from './accountSyncTypes';
|
|
1
2
|
export type EnsureDefaultAccountStatus = 'registered' | 'skipped' | 'error';
|
|
2
3
|
export interface EnsureDefaultAccountsResult {
|
|
3
4
|
claude: EnsureDefaultAccountStatus;
|
|
4
5
|
codex: EnsureDefaultAccountStatus;
|
|
6
|
+
/** The full sync report behind the two statuses. */
|
|
7
|
+
sync?: SyncReport;
|
|
5
8
|
}
|
|
6
9
|
export interface EnsureDefaultAccountsOptions {
|
|
7
10
|
logger?: (message: string, error?: unknown) => void;
|
|
8
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Host startup hook: run the one-time on-disk migrations, drop abandoned
|
|
14
|
+
* isolated logins, then reconcile the live logins with the saved profiles
|
|
15
|
+
* (registering any login sidekick has never seen).
|
|
16
|
+
*/
|
|
9
17
|
export declare function ensureDefaultAccounts(options?: EnsureDefaultAccountsOptions): Promise<EnsureDefaultAccountsResult>;
|
|
@@ -1,45 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.ensureDefaultAccounts = ensureDefaultAccounts;
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
4
|
const accounts_1 = require("./accounts");
|
|
40
|
-
const accountRegistry_1 = require("./accountRegistry");
|
|
41
5
|
const codexProfiles_1 = require("./codexProfiles");
|
|
42
|
-
const
|
|
6
|
+
const accountSync_1 = require("./accountSync");
|
|
43
7
|
function logFailure(options, message, error) {
|
|
44
8
|
try {
|
|
45
9
|
options?.logger?.(message, error);
|
|
@@ -48,65 +12,61 @@ function logFailure(options, message, error) {
|
|
|
48
12
|
// Logging must never make account bootstrap fail.
|
|
49
13
|
}
|
|
50
14
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const credentials = await (0, credentials_1.readClaudeMaxCredentials)();
|
|
59
|
-
if (!credentials)
|
|
60
|
-
return 'skipped';
|
|
61
|
-
const result = (0, accounts_1.addCurrentAccount)('Default');
|
|
62
|
-
if (result.success)
|
|
63
|
-
return 'registered';
|
|
64
|
-
logFailure(options, 'Claude default account registration failed.', result.error ?? 'unknown error');
|
|
15
|
+
function statusFromReport(report) {
|
|
16
|
+
if (report.registered)
|
|
17
|
+
return 'registered';
|
|
18
|
+
// A keyring-mode Codex login is a steady state sidekick cannot act on, not a failure.
|
|
19
|
+
if (report.skipped === 'keyring')
|
|
20
|
+
return 'skipped';
|
|
21
|
+
if (report.warnings.length > 0)
|
|
65
22
|
return 'error';
|
|
23
|
+
return 'skipped';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Host startup hook: run the one-time on-disk migrations, drop abandoned
|
|
27
|
+
* isolated logins, then reconcile the live logins with the saved profiles
|
|
28
|
+
* (registering any login sidekick has never seen).
|
|
29
|
+
*/
|
|
30
|
+
async function ensureDefaultAccounts(options) {
|
|
31
|
+
try {
|
|
32
|
+
(0, accounts_1.reconcileClaudeAuthState)();
|
|
66
33
|
}
|
|
67
34
|
catch (error) {
|
|
68
|
-
logFailure(options, 'Claude
|
|
69
|
-
return 'error';
|
|
35
|
+
logFailure(options, 'Claude auth reconciliation failed.', error);
|
|
70
36
|
}
|
|
71
|
-
}
|
|
72
|
-
function cleanupPendingCodexProfile(profileId) {
|
|
73
|
-
fs.rmSync(path.join((0, codexProfiles_1.getCodexProfilesDir)(), profileId), { recursive: true, force: true });
|
|
74
|
-
}
|
|
75
|
-
async function ensureDefaultCodexAccount(options) {
|
|
76
37
|
try {
|
|
77
|
-
|
|
78
|
-
return 'skipped';
|
|
79
|
-
const systemAuthPath = path.join((0, codexProfiles_1.getSystemCodexHome)(), 'auth.json');
|
|
80
|
-
if (!fs.existsSync(systemAuthPath))
|
|
81
|
-
return 'skipped';
|
|
82
|
-
const result = await (0, codexProfiles_1.prepareCodexAccountAsync)('Default');
|
|
83
|
-
if (result.success && !result.needsLogin)
|
|
84
|
-
return 'registered';
|
|
85
|
-
if (result.profileId) {
|
|
86
|
-
cleanupPendingCodexProfile(result.profileId);
|
|
87
|
-
}
|
|
88
|
-
logFailure(options, 'Codex default account registration failed.', result.error ?? 'Codex auth could not be finalized.');
|
|
89
|
-
return 'error';
|
|
38
|
+
await (0, codexProfiles_1.reconcileCodexAuthStateAsync)();
|
|
90
39
|
}
|
|
91
40
|
catch (error) {
|
|
92
|
-
logFailure(options, 'Codex
|
|
93
|
-
return 'error';
|
|
41
|
+
logFailure(options, 'Codex auth reconciliation failed.', error);
|
|
94
42
|
}
|
|
95
|
-
}
|
|
96
|
-
async function ensureDefaultAccounts(options) {
|
|
97
|
-
const claude = await ensureDefaultClaudeAccount(options);
|
|
98
|
-
const codex = await ensureDefaultCodexAccount(options);
|
|
99
43
|
try {
|
|
100
|
-
(0,
|
|
44
|
+
(0, accountSync_1.cleanupAbandonedLogins)();
|
|
101
45
|
}
|
|
102
46
|
catch (error) {
|
|
103
|
-
logFailure(options, '
|
|
47
|
+
logFailure(options, 'Abandoned login cleanup failed.', error);
|
|
104
48
|
}
|
|
49
|
+
let sync;
|
|
105
50
|
try {
|
|
106
|
-
await (0,
|
|
51
|
+
sync = await (0, accountSync_1.syncLiveAccountState)({ reason: 'startup' });
|
|
107
52
|
}
|
|
108
53
|
catch (error) {
|
|
109
|
-
logFailure(options, '
|
|
54
|
+
logFailure(options, 'Account sync failed.', error);
|
|
55
|
+
return { claude: 'error', codex: 'error' };
|
|
110
56
|
}
|
|
111
|
-
|
|
57
|
+
for (const [provider, report] of [
|
|
58
|
+
['Claude', sync.claude],
|
|
59
|
+
['Codex', sync.codex],
|
|
60
|
+
]) {
|
|
61
|
+
if (report.skipped === 'keyring')
|
|
62
|
+
continue;
|
|
63
|
+
for (const warning of report.warnings) {
|
|
64
|
+
logFailure(options, `${provider} account sync: ${warning}`, undefined);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
claude: statusFromReport(sync.claude),
|
|
69
|
+
codex: statusFromReport(sync.codex),
|
|
70
|
+
sync,
|
|
71
|
+
};
|
|
112
72
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -154,27 +154,44 @@ export { calculateCompactionLedger, formatCompactionLedger } from './analytics/c
|
|
|
154
154
|
export type { CompactionLedger } from './analytics/compactionLedger';
|
|
155
155
|
export { generateHtmlReport, parseTranscript, parseTranscriptFromEvents, openInBrowser, } from './report';
|
|
156
156
|
export type { TranscriptContentBlock, TranscriptEntry, HtmlReportOptions } from './report';
|
|
157
|
-
export { readActiveCredentials, writeActiveCredentials } from './credentialIO';
|
|
158
|
-
export { readClaudeMaxCredentials, readClaudeMaxAccessTokenSync } from './credentials';
|
|
157
|
+
export { readActiveCredentials, writeActiveCredentials, deleteStoredCredentials, } from './credentialIO';
|
|
158
|
+
export { readClaudeMaxCredentials, readClaudeMaxCredentialsRaw, readClaudeMaxAccessTokenSync, } from './credentials';
|
|
159
159
|
export type { ClaudeMaxCredentials } from './credentials';
|
|
160
|
+
export { parseClaudeCredentialBlob, claudeCredentialFreshness, isNewerClaudeCredential, resolveClaudeRefreshExpiry, CLAUDE_ACCESS_TOKEN_LIFETIME_MS, CLAUDE_REFRESH_TOKEN_LIFETIME_ESTIMATE_MS, } from './claudeCredentials';
|
|
161
|
+
export type { ClaudeOauthCredentials } from './claudeCredentials';
|
|
162
|
+
export { parseAuthJson as parseCodexAuthJson, readAuthIdentityFromRaw as readCodexAuthIdentity, readLastRefresh as readCodexLastRefresh, readAccessTokenExpiry as readCodexAccessTokenExpiry, identitiesMatch as codexIdentitiesMatch, } from './codexAuth';
|
|
163
|
+
export type { CodexAuthIdentity, CodexAuthJsonFile } from './codexAuth';
|
|
160
164
|
export { ensureDefaultAccounts } from './ensureDefaultAccounts';
|
|
161
165
|
export type { EnsureDefaultAccountStatus, EnsureDefaultAccountsOptions, EnsureDefaultAccountsResult, } from './ensureDefaultAccounts';
|
|
162
|
-
export { readAccountRegistry, writeAccountRegistry, readActiveClaudeAccount, addCurrentAccount, switchToAccount, resolveActiveClaudeHome, applyActiveClaudeToLiveHome, reconcileClaudeAuthState, removeAccount, listAccounts, getActiveAccount, resolveActiveClaudeAccount, isMultiAccountEnabled, } from './accounts';
|
|
166
|
+
export { readAccountRegistry, writeAccountRegistry, readActiveClaudeAccount, addCurrentAccount, switchToAccount, switchToAccountAsync, syncClaudeLiveState, cleanupAbandonedClaudeLogins, resolveActiveClaudeHome, applyActiveClaudeToLiveHome, reconcileClaudeAuthState, removeAccount, listAccounts, getActiveAccount, resolveActiveClaudeAccount, isMultiAccountEnabled, } from './accounts';
|
|
163
167
|
export type { AccountEntry, AccountRegistry, ActiveAccountInfo, AccountManagerResult, } from './accounts';
|
|
164
|
-
export { beginAccountLogin, getAccountLoginStatus, getAccountLoginStatusAsync, finalizeAccountLogin, finalizeAccountLoginAsync, spawnAccountLogin, switchAccount, switchAccountAsync, listAllAccounts, resolveClaudeLoginCommand, } from './accountManager';
|
|
165
|
-
export type { AccountLoginCommand, AccountLoginState, AccountLoginStatus, BeginAccountLoginResult, FinalizeAccountLoginOptions, ListAllAccountsResult, SpawnAccountLoginOptions, } from './accountManager';
|
|
168
|
+
export { beginAccountLogin, getAccountLoginStatus, getAccountLoginStatusAsync, finalizeAccountLogin, finalizeAccountLoginAsync, spawnAccountLogin, switchAccount, switchAccountAsync, undoLastSwitch, getLastSwitch, listAllAccounts, resolveClaudeLoginCommand, } from './accountManager';
|
|
169
|
+
export type { AccountLoginCommand, AccountLoginState, AccountLoginStatus, BeginAccountLoginOptions, BeginAccountLoginResult, BeginAccountLoginSuccess, FinalizeAccountLoginOptions, ListAllAccountsResult, SpawnAccountLoginOptions, } from './accountManager';
|
|
170
|
+
export { readLastSwitch, getLastSwitchPath } from './accountSwitch';
|
|
171
|
+
export type { LastSwitchRecord, SwitchAccountOptions, SwitchAccountResult, SwitchVerification, } from './accountSwitch';
|
|
172
|
+
export { syncLiveAccountState, syncLiveAccountStateSync, cleanupAbandonedLogins, } from './accountSync';
|
|
173
|
+
export type { SyncLiveAccountStateOptions, CleanupAbandonedLoginsResult } from './accountSync';
|
|
174
|
+
export type { ProviderSyncReport, SyncReason, SyncReport } from './accountSyncTypes';
|
|
175
|
+
export { getAccountHealth, listAccountsWithHealth, readHealthSidecar, getHealthSidecarPath, } from './accountHealth';
|
|
176
|
+
export type { AccountHealth, AccountHealthOptions, AccountHealthSidecar, AccountHealthSource, AccountHealthState, AccountView, } from './accountHealth';
|
|
177
|
+
export { getAccountLaunchEnv } from './accountLaunch';
|
|
178
|
+
export type { AccountLaunchEnv, AccountLaunchOptions } from './accountLaunch';
|
|
179
|
+
export { refreshInactiveAccounts, keepAliveCommand } from './keepAlive';
|
|
180
|
+
export type { KeepAliveRunner, RefreshInactiveAccountsOptions, RefreshInactiveAccountsResult, } from './keepAlive';
|
|
181
|
+
export { findRunningProcesses, findRunningProcessesSync, detectRunningAccountConsumers, detectRunningAccountConsumersSync, describeAccountConsumer, ACCOUNT_CONSUMER_REACHABILITY, } from './processDetection';
|
|
182
|
+
export type { AccountConsumerKind, RunningAccountConsumer, RunningProcess, } from './processDetection';
|
|
166
183
|
export { getAccountsDir, readSavedAccountRegistry, writeSavedAccountRegistry, listSavedAccountProfiles, getActiveSavedAccount, upsertSavedAccountProfile, setActiveSavedAccount, replaceSavedAccountProfiles, removeSavedAccountProfile, } from './accountRegistry';
|
|
167
|
-
export type { AccountProviderId, AccountIdentityMetadata, ResolvedActiveAccount, SavedAccountProfile, SavedAccountRegistry, } from './accountRegistry';
|
|
184
|
+
export type { AccountProviderId, AccountIdentityMetadata, AccountProfileOrigin, ResolvedActiveAccount, SavedAccountProfile, SavedAccountRegistry, } from './accountRegistry';
|
|
168
185
|
export { ACCOUNT_PROVIDER_IDS } from './accountRegistry';
|
|
169
186
|
export { getActiveAccountStatus } from './accountStatus';
|
|
170
187
|
export type { ActiveAccountStatus, ActiveAccountStatusOptions, ActiveProviderAccountStatus, } from './accountStatus';
|
|
171
188
|
export { onAccountsChanged } from './accountChanges';
|
|
172
189
|
export type { AccountsChangedEvent, OnAccountsChangedOptions } from './accountChanges';
|
|
173
|
-
export { getClaudeProfilesDir, getClaudeProfileHome, claudeKeychainSuffix, claudeKeychainService, isClaudeProfileAuthenticated, readClaudeProfileIdentity, } from './claudeProfiles';
|
|
190
|
+
export { getClaudeProfilesDir, getClaudeProfileHome, getLiveClaudeHome, getDefaultClaudeHome, getClaudeConfigPath, claudeKeychainSuffix, claudeKeychainService, claudeKeychainAccountName, buildClaudeChildEnv, CLAUDE_SECURESTORAGE_CONFIG_DIR_ENV, isClaudeProfileAuthenticated, readClaudeProfileIdentity, readLiveClaudeIdentity, } from './claudeProfiles';
|
|
174
191
|
export type { ClaudeProfileIdentity } from './claudeProfiles';
|
|
175
|
-
export { getCodexProfilesDir, getCodexProfileHome, getCodexMonitoringHomes, getSystemCodexHome, listCodexAccounts, getActiveCodexAccount, resolveActiveCodexAccount, resolveSidekickCodexHome, getCodexExecutionEnv, prepareCodexAccount, prepareCodexAccountAsync, finalizeCodexAccount, finalizeCodexAccountAsync, switchToCodexAccount, switchToCodexAccountAsync, removeCodexAccount, } from './codexProfiles';
|
|
176
|
-
export type { CodexAccountManagerResult } from './codexProfiles';
|
|
177
|
-
export {
|
|
192
|
+
export { getCodexProfilesDir, getCodexProfileHome, getCodexMonitoringHomes, getSystemCodexHome, listCodexAccounts, getActiveCodexAccount, resolveActiveCodexAccount, resolveSidekickCodexHome, getCodexExecutionEnv, prepareCodexAccount, prepareCodexAccountAsync, finalizeCodexAccount, finalizeCodexAccountAsync, switchToCodexAccount, switchToCodexAccountAsync, removeCodexAccount, syncCodexLiveState, cleanupAbandonedCodexLogins, getCodexCredentialStoreMode, CODEX_KEYRING_FIX_HINT, } from './codexProfiles';
|
|
193
|
+
export type { CodexAccountManagerResult, CodexCredentialStoreMode } from './codexProfiles';
|
|
194
|
+
export { writeLauncher, removeLauncher } from './terminalSync';
|
|
178
195
|
export { DEFAULT_AUTO_SWITCH_CONFIG, decideAutoSwitch, AutoSwitchController } from './autoSwitch';
|
|
179
196
|
export type { AutoSwitchActiveAccount, AutoSwitchCandidate, AutoSwitchConfig, AutoSwitchControllerOptions, AutoSwitchDecision, AutoSwitchTransitionEvent, } from './autoSwitch';
|
|
180
197
|
export { FIVE_HOUR_WINDOW_MS, QUOTA_PROVIDER_IDS, SEVEN_DAY_WINDOW_MS, fetchQuota, projectQuotaWindow, withQuotaProjections, } from './quota';
|