sidekick-shared 0.27.5 → 0.27.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +35 -34
  3. package/dist/accountHealth.d.ts +14 -0
  4. package/dist/accountHealth.js +61 -14
  5. package/dist/accountLaunch.d.ts +6 -0
  6. package/dist/accountLaunch.js +61 -4
  7. package/dist/accountLease.d.ts +5 -0
  8. package/dist/accountLease.js +98 -0
  9. package/dist/accountManager.d.ts +7 -0
  10. package/dist/accountManager.js +226 -89
  11. package/dist/accountSync.d.ts +1 -5
  12. package/dist/accountSync.js +22 -6
  13. package/dist/accountSyncTypes.d.ts +9 -0
  14. package/dist/accounts.d.ts +75 -18
  15. package/dist/accounts.js +712 -189
  16. package/dist/claudeCredentialDoctor.d.ts +50 -0
  17. package/dist/claudeCredentialDoctor.js +277 -0
  18. package/dist/claudeCredentialLedger.d.ts +15 -0
  19. package/dist/claudeCredentialLedger.js +130 -0
  20. package/dist/claudeCredentials.d.ts +20 -3
  21. package/dist/claudeCredentials.js +50 -3
  22. package/dist/claudeLiveGuard.d.ts +33 -0
  23. package/dist/claudeLiveGuard.js +46 -0
  24. package/dist/claudeProfiles.d.ts +14 -0
  25. package/dist/claudeProfiles.js +22 -0
  26. package/dist/claudeRefreshLock.d.ts +15 -0
  27. package/dist/claudeRefreshLock.js +145 -0
  28. package/dist/codexAuth.d.ts +4 -0
  29. package/dist/codexAuth.js +18 -0
  30. package/dist/codexCredentialDoctor.d.ts +33 -0
  31. package/dist/codexCredentialDoctor.js +302 -0
  32. package/dist/codexCredentialStore.d.ts +29 -0
  33. package/dist/codexCredentialStore.js +213 -0
  34. package/dist/codexKeepAlive.d.ts +2 -0
  35. package/dist/codexKeepAlive.js +116 -0
  36. package/dist/codexPaths.d.ts +8 -2
  37. package/dist/codexPaths.js +51 -7
  38. package/dist/codexProfiles.d.ts +37 -31
  39. package/dist/codexProfiles.js +842 -671
  40. package/dist/credentialIO.d.ts +67 -7
  41. package/dist/credentialIO.js +211 -47
  42. package/dist/ensureDefaultAccounts.js +1 -8
  43. package/dist/index.d.ts +14 -4
  44. package/dist/index.js +29 -6
  45. package/dist/keepAlive.d.ts +2 -1
  46. package/dist/keepAlive.js +116 -29
  47. package/dist/liveCredentialGuard.d.ts +28 -0
  48. package/dist/liveCredentialGuard.js +36 -0
  49. package/dist/processDetection.d.ts +10 -3
  50. package/dist/processDetection.js +44 -11
  51. package/dist/schemas/accountManager.d.ts +22 -0
  52. package/dist/schemas/accountManager.js +4 -0
  53. package/dist/schemas/assistantTurn.d.ts +2 -2
  54. package/dist/terminalSync.d.ts +12 -2
  55. package/dist/terminalSync.js +27 -2
  56. package/package.json +1 -1
@@ -7,30 +7,90 @@
7
7
  * Keychain is unavailable (locked, SSH) Claude Code falls back to the file on
8
8
  * macOS too, so reads consult the file after a Keychain miss.
9
9
  *
10
+ * Keychain writes mirror Claude Code 2.1.x exactly: the payload is hex-encoded
11
+ * (`-X`) and sent through `security -i` only while the command line fits the
12
+ * tool's line buffer; longer payloads go through argv. `security -i` silently
13
+ * truncates longer lines, which once stored half a credential (the `mcpOAuth`
14
+ * tokens make blobs of 4 KB and more) — a login Claude Code then reports as
15
+ * "Not logged in". Every write is read back and compared before it counts.
16
+ *
10
17
  * Both accounts.ts and credentials.ts consume this module so that all
11
18
  * credential access is platform-correct in one place.
12
19
  */
13
20
  export declare const KEYCHAIN_SERVICE = "Claude Code-credentials";
21
+ /**
22
+ * Claude Code's ceiling for a `security -i` command line (the tool reads at
23
+ * most 4095 bytes per line). Longer commands go through argv instead.
24
+ */
25
+ export declare const SECURITY_INTERACTIVE_LINE_LIMIT = 4032;
26
+ /**
27
+ * Written as the item comment (`-j`) on every Keychain item Sidekick creates,
28
+ * so ownership is provable from the item itself even after its directory and
29
+ * the ledger that described it are gone.
30
+ */
31
+ export declare const SIDEKICK_KEYCHAIN_COMMENT_PREFIX = "sidekick-agent-hub:";
32
+ export type ClaudeCredentialStoreSource = 'keychain' | 'file';
33
+ /**
34
+ * Outcome of reading one credential store. `error` (timeout, locked Keychain)
35
+ * is never treated like `absent`: guard decisions that may overwrite a store
36
+ * only proceed on a definite answer.
37
+ */
38
+ export type ClaudeCredentialStoreRead = {
39
+ status: 'ok';
40
+ blob: Record<string, unknown>;
41
+ source: ClaudeCredentialStoreSource;
42
+ } | {
43
+ status: 'absent';
44
+ } | {
45
+ status: 'corrupt';
46
+ source: ClaudeCredentialStoreSource;
47
+ length: number;
48
+ } | {
49
+ status: 'error';
50
+ reason: string;
51
+ };
52
+ /** A credential write that did not land, or could not be verified. */
53
+ export declare class ClaudeCredentialWriteError extends Error {
54
+ constructor(message: string);
55
+ }
56
+ /**
57
+ * Read one Claude credential store with a definite outcome. On macOS the
58
+ * Keychain item is authoritative; the file is consulted only when the item is
59
+ * absent (Claude Code's own fallback), unless `keychainOnly` is set.
60
+ */
61
+ export declare function readClaudeCredentialStore(configDir?: string, options?: {
62
+ keychainOnly?: boolean;
63
+ }): ClaudeCredentialStoreRead;
14
64
  /**
15
65
  * Read the active Claude Code credentials as a parsed object.
16
66
  *
17
67
  * - macOS: reads from system Keychain via the `security` CLI, then the file
18
68
  * - Linux / WSL / Windows: reads `<home>/.credentials.json`
19
69
  *
20
- * Returns `null` when credentials are absent or unreadable.
70
+ * Returns `null` when credentials are absent or unreadable. Callers that must
71
+ * tell "absent" from "could not read" use {@link readClaudeCredentialStore}.
21
72
  */
22
73
  export declare function readActiveCredentials(configDir?: string): unknown;
23
74
  /**
24
- * Write credentials to the active Claude Code credential store.
75
+ * Write credentials to a profile home's Claude Code credential store.
25
76
  *
26
- * - macOS: writes to system Keychain via the `security` CLI
27
- * - Linux / WSL / Windows: atomic-writes `<home>/.credentials.json`
77
+ * - macOS: the suffixed Keychain item for `configDir`
78
+ * - Linux / WSL / Windows: atomic-writes `<configDir>/.credentials.json`
28
79
  *
29
- * Throws on failure.
80
+ * `configDir` is required: the live store is written only through the guarded
81
+ * installer in accounts.ts, which refuses downgrades and captures the outgoing
82
+ * login first. Throws {@link ClaudeCredentialWriteError} when the write did
83
+ * not land intact.
30
84
  */
31
85
  export declare function writeActiveCredentials(credentials: unknown, configDir?: string): void;
86
+ /**
87
+ * Write the live store with no guard. Internal: the only caller is
88
+ * `installIntoLiveClaudeStore` in accounts.ts (a test enforces this).
89
+ */
90
+ export declare function writeLiveClaudeCredentialStoreUnguarded(credentials: unknown): void;
32
91
  /**
33
92
  * Remove the credential store of a config directory (an abandoned isolated
34
- * login, a removed profile). Best effort: never throws.
93
+ * login, a removed profile, the profile home of the account that became
94
+ * live). Never throws; returns true when the store is gone afterwards.
35
95
  */
36
- export declare function deleteStoredCredentials(configDir: string): void;
96
+ export declare function deleteStoredCredentials(configDir: string): boolean;
@@ -8,6 +8,13 @@
8
8
  * Keychain is unavailable (locked, SSH) Claude Code falls back to the file on
9
9
  * macOS too, so reads consult the file after a Keychain miss.
10
10
  *
11
+ * Keychain writes mirror Claude Code 2.1.x exactly: the payload is hex-encoded
12
+ * (`-X`) and sent through `security -i` only while the command line fits the
13
+ * tool's line buffer; longer payloads go through argv. `security -i` silently
14
+ * truncates longer lines, which once stored half a credential (the `mcpOAuth`
15
+ * tokens make blobs of 4 KB and more) — a login Claude Code then reports as
16
+ * "Not logged in". Every write is read back and compared before it counts.
17
+ *
11
18
  * Both accounts.ts and credentials.ts consume this module so that all
12
19
  * credential access is platform-correct in one place.
13
20
  */
@@ -45,17 +52,41 @@ var __importStar = (this && this.__importStar) || (function () {
45
52
  };
46
53
  })();
47
54
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.KEYCHAIN_SERVICE = void 0;
55
+ exports.ClaudeCredentialWriteError = exports.SIDEKICK_KEYCHAIN_COMMENT_PREFIX = exports.SECURITY_INTERACTIVE_LINE_LIMIT = exports.KEYCHAIN_SERVICE = void 0;
56
+ exports.readClaudeCredentialStore = readClaudeCredentialStore;
49
57
  exports.readActiveCredentials = readActiveCredentials;
50
58
  exports.writeActiveCredentials = writeActiveCredentials;
59
+ exports.writeLiveClaudeCredentialStoreUnguarded = writeLiveClaudeCredentialStoreUnguarded;
51
60
  exports.deleteStoredCredentials = deleteStoredCredentials;
52
61
  const fs = __importStar(require("fs"));
53
62
  const path = __importStar(require("path"));
54
63
  const child_process_1 = require("child_process");
55
64
  const claudeProfiles_1 = require("./claudeProfiles");
65
+ const claudeCredentialLedger_1 = require("./claudeCredentialLedger");
56
66
  const atomic_1 = require("./writers/atomic");
57
67
  exports.KEYCHAIN_SERVICE = 'Claude Code-credentials';
58
68
  const SECURITY_TIMEOUT_MS = 4000;
69
+ /** `security` exits with this status when no item matches. */
70
+ const SECURITY_ITEM_NOT_FOUND = 44;
71
+ /**
72
+ * Claude Code's ceiling for a `security -i` command line (the tool reads at
73
+ * most 4095 bytes per line). Longer commands go through argv instead.
74
+ */
75
+ exports.SECURITY_INTERACTIVE_LINE_LIMIT = 4032;
76
+ /**
77
+ * Written as the item comment (`-j`) on every Keychain item Sidekick creates,
78
+ * so ownership is provable from the item itself even after its directory and
79
+ * the ledger that described it are gone.
80
+ */
81
+ exports.SIDEKICK_KEYCHAIN_COMMENT_PREFIX = 'sidekick-agent-hub:';
82
+ /** A credential write that did not land, or could not be verified. */
83
+ class ClaudeCredentialWriteError extends Error {
84
+ constructor(message) {
85
+ super(message);
86
+ this.name = 'ClaudeCredentialWriteError';
87
+ }
88
+ }
89
+ exports.ClaudeCredentialWriteError = ClaudeCredentialWriteError;
59
90
  function quoteSecurityInteractiveArg(value) {
60
91
  // `security -i` is not a POSIX shell: adjacent quoted segments do NOT
61
92
  // concatenate (so the shell-style '\'' splice splits the token), and
@@ -65,27 +96,69 @@ function quoteSecurityInteractiveArg(value) {
65
96
  function getCredentialsFilePath(configDir) {
66
97
  return path.join(configDir ?? (0, claudeProfiles_1.getLiveClaudeHome)(), '.credentials.json');
67
98
  }
68
- function readCredentialsFile(configDir) {
99
+ function parseStoredText(raw, source) {
100
+ const text = raw.trim();
101
+ if (!text)
102
+ return { status: 'corrupt', source, length: 0 };
103
+ // `security -w` prints hex when the stored bytes are not plain text.
104
+ const decoded = source === 'keychain' && !text.startsWith('{') && /^(?:[0-9a-f]{2})+$/i.test(text)
105
+ ? Buffer.from(text, 'hex').toString('utf8')
106
+ : text;
69
107
  try {
70
- return JSON.parse(fs.readFileSync(getCredentialsFilePath(configDir), 'utf8'));
108
+ const parsed = JSON.parse(decoded);
109
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
110
+ return { status: 'ok', blob: parsed, source };
111
+ }
71
112
  }
72
113
  catch {
73
- return null;
114
+ /* fall through */
74
115
  }
116
+ return { status: 'corrupt', source, length: decoded.length };
75
117
  }
76
- function readKeychainItem(service) {
118
+ function readCredentialsFileStore(configDir) {
119
+ let raw;
77
120
  try {
78
- const raw = (0, child_process_1.execFileSync)('security', ['find-generic-password', '-s', service, '-w'], {
121
+ raw = fs.readFileSync(getCredentialsFilePath(configDir), 'utf8');
122
+ }
123
+ catch (error) {
124
+ return error.code === 'ENOENT'
125
+ ? { status: 'absent' }
126
+ : { status: 'error', reason: String(error.message ?? error) };
127
+ }
128
+ return parseStoredText(raw, 'file');
129
+ }
130
+ function securityErrorStatus(error) {
131
+ const status = error.status;
132
+ return typeof status === 'number' ? status : null;
133
+ }
134
+ function readKeychainStore(service) {
135
+ try {
136
+ const raw = (0, child_process_1.execFileSync)('security', ['find-generic-password', '-a', (0, claudeProfiles_1.claudeKeychainAccountName)(), '-s', service, '-w'], {
79
137
  encoding: 'utf8',
80
138
  stdio: ['pipe', 'pipe', 'pipe'],
81
139
  timeout: SECURITY_TIMEOUT_MS,
82
140
  killSignal: 'SIGKILL',
83
141
  });
84
- return JSON.parse(raw.trim());
142
+ return parseStoredText(String(raw), 'keychain');
85
143
  }
86
- catch {
87
- return null;
144
+ catch (error) {
145
+ if (securityErrorStatus(error) === SECURITY_ITEM_NOT_FOUND)
146
+ return { status: 'absent' };
147
+ return { status: 'error', reason: String(error?.message ?? error) };
148
+ }
149
+ }
150
+ /**
151
+ * Read one Claude credential store with a definite outcome. On macOS the
152
+ * Keychain item is authoritative; the file is consulted only when the item is
153
+ * absent (Claude Code's own fallback), unless `keychainOnly` is set.
154
+ */
155
+ function readClaudeCredentialStore(configDir, options = {}) {
156
+ if (process.platform === 'darwin') {
157
+ const keychain = readKeychainStore((0, claudeProfiles_1.claudeKeychainService)(configDir));
158
+ if (keychain.status !== 'absent' || options.keychainOnly)
159
+ return keychain;
88
160
  }
161
+ return readCredentialsFileStore(configDir);
89
162
  }
90
163
  /**
91
164
  * Read the active Claude Code credentials as a parsed object.
@@ -93,69 +166,160 @@ function readKeychainItem(service) {
93
166
  * - macOS: reads from system Keychain via the `security` CLI, then the file
94
167
  * - Linux / WSL / Windows: reads `<home>/.credentials.json`
95
168
  *
96
- * Returns `null` when credentials are absent or unreadable.
169
+ * Returns `null` when credentials are absent or unreadable. Callers that must
170
+ * tell "absent" from "could not read" use {@link readClaudeCredentialStore}.
97
171
  */
98
172
  function readActiveCredentials(configDir) {
99
173
  if (process.platform === 'darwin') {
100
- return readKeychainItem((0, claudeProfiles_1.claudeKeychainService)(configDir)) ?? readCredentialsFile(configDir);
174
+ const keychain = readKeychainStore((0, claudeProfiles_1.claudeKeychainService)(configDir));
175
+ if (keychain.status === 'ok')
176
+ return keychain.blob;
101
177
  }
102
- return readCredentialsFile(configDir);
178
+ const file = readCredentialsFileStore(configDir);
179
+ return file.status === 'ok' ? file.blob : null;
180
+ }
181
+ function runKeychainWrite(service, hex, comment) {
182
+ const account = (0, claudeProfiles_1.claudeKeychainAccountName)();
183
+ const args = ['add-generic-password', '-U', '-a', account, '-s', service];
184
+ const interactive = [
185
+ 'add-generic-password',
186
+ '-U',
187
+ '-a',
188
+ quoteSecurityInteractiveArg(account),
189
+ '-s',
190
+ quoteSecurityInteractiveArg(service),
191
+ ];
192
+ if (comment) {
193
+ args.push('-j', comment);
194
+ interactive.push('-j', quoteSecurityInteractiveArg(comment));
195
+ }
196
+ args.push('-X', hex);
197
+ interactive.push('-X', quoteSecurityInteractiveArg(hex));
198
+ const line = `${interactive.join(' ')}\n`;
199
+ if (Buffer.byteLength(line, 'utf8') <= exports.SECURITY_INTERACTIVE_LINE_LIMIT) {
200
+ (0, child_process_1.execFileSync)('security', ['-i'], {
201
+ input: line,
202
+ stdio: ['pipe', 'pipe', 'pipe'],
203
+ timeout: SECURITY_TIMEOUT_MS,
204
+ killSignal: 'SIGKILL',
205
+ });
206
+ return;
207
+ }
208
+ // The same trade-off Claude Code makes for large payloads: the hex is on the
209
+ // command line (visible to `ps`) for the duration of this call.
210
+ (0, child_process_1.execFileSync)('security', args, {
211
+ stdio: ['ignore', 'pipe', 'pipe'],
212
+ timeout: SECURITY_TIMEOUT_MS,
213
+ killSignal: 'SIGKILL',
214
+ });
103
215
  }
104
216
  /**
105
- * Write credentials to the active Claude Code credential store.
106
- *
107
- * - macOS: writes to system Keychain via the `security` CLI
108
- * - Linux / WSL / Windows: atomic-writes `<home>/.credentials.json`
109
- *
110
- * Throws on failure.
217
+ * Write a credential blob to a store and verify it by reading it back.
218
+ * `configDir` undefined targets the live home; only the guarded live installer
219
+ * in accounts.ts may do that (see {@link writeLiveClaudeCredentialStoreUnguarded}).
111
220
  */
112
- function writeActiveCredentials(credentials, configDir) {
221
+ function writeClaudeCredentialStore(credentials, configDir) {
113
222
  const json = JSON.stringify(credentials);
114
- JSON.parse(json); // validate round-trip
223
+ let expected;
224
+ try {
225
+ expected = JSON.stringify(JSON.parse(json));
226
+ }
227
+ catch {
228
+ throw new ClaudeCredentialWriteError('Refusing to store a credential that is not JSON.');
229
+ }
115
230
  if (process.platform === 'darwin') {
116
231
  const service = (0, claudeProfiles_1.claudeKeychainService)(configDir);
117
- const command = [
118
- 'add-generic-password',
119
- '-U',
232
+ const comment = configDir
233
+ ? `${exports.SIDEKICK_KEYCHAIN_COMMENT_PREFIX}${path.resolve(configDir)}`
234
+ : null;
235
+ try {
236
+ runKeychainWrite(service, Buffer.from(json, 'utf8').toString('hex'), comment);
237
+ }
238
+ catch (error) {
239
+ throw new ClaudeCredentialWriteError(`Keychain write failed: ${error?.message ?? error}`);
240
+ }
241
+ const readBack = readKeychainStore(service);
242
+ if (readBack.status === 'error') {
243
+ throw new ClaudeCredentialWriteError('The Keychain write could not be verified (read-back failed); treating it as not written.');
244
+ }
245
+ if (readBack.status !== 'ok' || JSON.stringify(readBack.blob) !== expected) {
246
+ throw new ClaudeCredentialWriteError('The Keychain item did not hold the credential after writing it.');
247
+ }
248
+ return;
249
+ }
250
+ // Linux / WSL / Windows — file-based (tmp + fsync + rename, retried on Windows)
251
+ (0, atomic_1.atomicWriteFileSync)(getCredentialsFilePath(configDir), json, 0o600);
252
+ const readBack = readCredentialsFileStore(configDir);
253
+ if (readBack.status !== 'ok' || JSON.stringify(readBack.blob) !== expected) {
254
+ throw new ClaudeCredentialWriteError('The credentials file did not hold the credential after writing it.');
255
+ }
256
+ }
257
+ /**
258
+ * Write credentials to a profile home's Claude Code credential store.
259
+ *
260
+ * - macOS: the suffixed Keychain item for `configDir`
261
+ * - Linux / WSL / Windows: atomic-writes `<configDir>/.credentials.json`
262
+ *
263
+ * `configDir` is required: the live store is written only through the guarded
264
+ * installer in accounts.ts, which refuses downgrades and captures the outgoing
265
+ * login first. Throws {@link ClaudeCredentialWriteError} when the write did
266
+ * not land intact.
267
+ */
268
+ function writeActiveCredentials(credentials, configDir) {
269
+ if (!configDir) {
270
+ throw new ClaudeCredentialWriteError('writeActiveCredentials() needs a config directory; the live Claude login is only written through a guarded account switch.');
271
+ }
272
+ (0, claudeCredentialLedger_1.recordClaudeCredentialHome)(configDir, 'profile');
273
+ writeClaudeCredentialStore(credentials, configDir);
274
+ }
275
+ /**
276
+ * Write the live store with no guard. Internal: the only caller is
277
+ * `installIntoLiveClaudeStore` in accounts.ts (a test enforces this).
278
+ */
279
+ function writeLiveClaudeCredentialStoreUnguarded(credentials) {
280
+ writeClaudeCredentialStore(credentials, undefined);
281
+ }
282
+ function deleteKeychainItem(service, withAccount) {
283
+ try {
284
+ (0, child_process_1.execFileSync)('security', [
285
+ 'delete-generic-password',
286
+ ...(withAccount ? ['-a', (0, claudeProfiles_1.claudeKeychainAccountName)()] : []),
120
287
  '-s',
121
- quoteSecurityInteractiveArg(service),
122
- '-a',
123
- quoteSecurityInteractiveArg((0, claudeProfiles_1.claudeKeychainAccountName)()),
124
- '-w',
125
- quoteSecurityInteractiveArg(json),
126
- ].join(' ');
127
- (0, child_process_1.execFileSync)('security', ['-i'], {
128
- input: command + '\n',
129
- stdio: ['pipe', 'pipe', 'pipe'],
288
+ service,
289
+ ], {
290
+ stdio: ['ignore', 'ignore', 'ignore'],
130
291
  timeout: SECURITY_TIMEOUT_MS,
131
292
  killSignal: 'SIGKILL',
132
293
  });
133
- return;
294
+ return 'deleted';
295
+ }
296
+ catch (error) {
297
+ return securityErrorStatus(error) === SECURITY_ITEM_NOT_FOUND ? 'absent' : 'error';
134
298
  }
135
- // Linux / WSL / Windows — file-based (tmp + fsync + rename, retried on Windows)
136
- (0, atomic_1.atomicWriteFileSync)(getCredentialsFilePath(configDir), json, 0o600);
137
299
  }
138
300
  /**
139
301
  * Remove the credential store of a config directory (an abandoned isolated
140
- * login, a removed profile). Best effort: never throws.
302
+ * login, a removed profile, the profile home of the account that became
303
+ * live). Never throws; returns true when the store is gone afterwards.
141
304
  */
142
305
  function deleteStoredCredentials(configDir) {
306
+ let gone = true;
143
307
  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
- }
308
+ const service = (0, claudeProfiles_1.claudeKeychainService)(configDir);
309
+ let outcome = deleteKeychainItem(service, true);
310
+ // Items written before the account name was pinned may carry another one.
311
+ if (outcome === 'absent')
312
+ outcome = deleteKeychainItem(service, false);
313
+ if (outcome === 'error')
314
+ gone = false;
154
315
  }
155
316
  try {
156
317
  fs.rmSync(getCredentialsFilePath(configDir), { force: true });
157
318
  }
158
319
  catch {
159
- /* best effort */
320
+ gone = false;
160
321
  }
322
+ if (gone)
323
+ (0, claudeCredentialLedger_1.forgetClaudeCredentialHome)(configDir);
324
+ return gone;
161
325
  }
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ensureDefaultAccounts = ensureDefaultAccounts;
4
4
  const accounts_1 = require("./accounts");
5
- const codexProfiles_1 = require("./codexProfiles");
6
5
  const accountSync_1 = require("./accountSync");
7
6
  function logFailure(options, message, error) {
8
7
  try {
@@ -35,13 +34,7 @@ async function ensureDefaultAccounts(options) {
35
34
  logFailure(options, 'Claude auth reconciliation failed.', error);
36
35
  }
37
36
  try {
38
- await (0, codexProfiles_1.reconcileCodexAuthStateAsync)();
39
- }
40
- catch (error) {
41
- logFailure(options, 'Codex auth reconciliation failed.', error);
42
- }
43
- try {
44
- (0, accountSync_1.cleanupAbandonedLogins)();
37
+ await (0, accountSync_1.cleanupAbandonedLoginsAsync)();
45
38
  }
46
39
  catch (error) {
47
40
  logFailure(options, 'Abandoned login cleanup failed.', error);
package/dist/index.d.ts CHANGED
@@ -165,10 +165,17 @@ export { calculateCompactionLedger, formatCompactionLedger } from './analytics/c
165
165
  export type { CompactionLedger } from './analytics/compactionLedger';
166
166
  export { generateHtmlReport, parseTranscript, parseTranscriptFromEvents, openInBrowser, } from './report';
167
167
  export type { TranscriptContentBlock, TranscriptEntry, HtmlReportOptions } from './report';
168
- export { readActiveCredentials, writeActiveCredentials, deleteStoredCredentials, } from './credentialIO';
168
+ export { readActiveCredentials, readClaudeCredentialStore, writeActiveCredentials, deleteStoredCredentials, ClaudeCredentialWriteError, SIDEKICK_KEYCHAIN_COMMENT_PREFIX, } from './credentialIO';
169
+ export type { ClaudeCredentialStoreRead, ClaudeCredentialStoreSource } from './credentialIO';
170
+ export { decideLiveClaudeWrite } from './claudeLiveGuard';
171
+ export type { LiveClaudeStoreState, LiveClaudeWriteDecision, LiveClaudeWriteIntent, LiveClaudeWriteRefusal, LiveClaudeWriteRequest, } from './claudeLiveGuard';
172
+ export { readClaudeCredentialLedger, getClaudeCredentialLedgerPath, } from './claudeCredentialLedger';
173
+ export type { ClaudeCredentialLedgerEntry, ClaudeCredentialHomePurpose, } from './claudeCredentialLedger';
174
+ export { inspectClaudeCredentialStores, repairClaudeCredentialStores, parseKeychainDump, } from './claudeCredentialDoctor';
175
+ export type { ClaudeCredentialFinding, ClaudeCredentialFindingKind, ClaudeCredentialInspection, ClaudeCredentialRepairOutcome, ClaudeCredentialRepairResult, InspectClaudeCredentialStoresOptions, KeychainItemSummary, } from './claudeCredentialDoctor';
169
176
  export { readClaudeMaxCredentials, readClaudeMaxCredentialsRaw, readClaudeMaxAccessTokenSync, } from './credentials';
170
177
  export type { ClaudeMaxCredentials } from './credentials';
171
- export { parseClaudeCredentialBlob, claudeCredentialFreshness, isNewerClaudeCredential, resolveClaudeRefreshExpiry, CLAUDE_ACCESS_TOKEN_LIFETIME_MS, CLAUDE_REFRESH_TOKEN_LIFETIME_ESTIMATE_MS, } from './claudeCredentials';
178
+ export { parseClaudeCredentialBlob, claudeCredentialFreshness, isNewerClaudeCredential, resolveClaudeRefreshExpiry, claudeRefreshFingerprint, claudeLoginOnly, mergeClaudeLoginIntoLive, CLAUDE_ACCESS_TOKEN_LIFETIME_MS, CLAUDE_REFRESH_TOKEN_LIFETIME_ESTIMATE_MS, } from './claudeCredentials';
172
179
  export type { ClaudeOauthCredentials } from './claudeCredentials';
173
180
  export { parseAuthJson as parseCodexAuthJson, readAuthIdentityFromRaw as readCodexAuthIdentity, readLastRefresh as readCodexLastRefresh, readAccessTokenExpiry as readCodexAccessTokenExpiry, identitiesMatch as codexIdentitiesMatch, } from './codexAuth';
174
181
  export type { CodexAuthIdentity, CodexAuthJsonFile } from './codexAuth';
@@ -176,7 +183,7 @@ export { ensureDefaultAccounts } from './ensureDefaultAccounts';
176
183
  export type { EnsureDefaultAccountStatus, EnsureDefaultAccountsOptions, EnsureDefaultAccountsResult, } from './ensureDefaultAccounts';
177
184
  export { readAccountRegistry, writeAccountRegistry, readActiveClaudeAccount, addCurrentAccount, switchToAccount, switchToAccountAsync, syncClaudeLiveState, cleanupAbandonedClaudeLogins, resolveActiveClaudeHome, applyActiveClaudeToLiveHome, reconcileClaudeAuthState, removeAccount, listAccounts, getActiveAccount, resolveActiveClaudeAccount, isMultiAccountEnabled, } from './accounts';
178
185
  export type { AccountEntry, AccountRegistry, ActiveAccountInfo, AccountManagerResult, } from './accounts';
179
- export { beginAccountLogin, getAccountLoginStatus, getAccountLoginStatusAsync, finalizeAccountLogin, finalizeAccountLoginAsync, spawnAccountLogin, switchAccount, switchAccountAsync, undoLastSwitch, getLastSwitch, listAllAccounts, resolveClaudeLoginCommand, } from './accountManager';
186
+ export { beginAccountLogin, getAccountLoginStatus, getAccountLoginStatusAsync, finalizeAccountLogin, finalizeAccountLoginAsync, spawnAccountLogin, switchAccount, switchAccountAsync, undoLastSwitch, getLastSwitch, listAllAccounts, resolveClaudeLoginCommand, discardAccountLogin, } from './accountManager';
180
187
  export type { AccountLoginCommand, AccountLoginState, AccountLoginStatus, BeginAccountLoginOptions, BeginAccountLoginResult, BeginAccountLoginSuccess, FinalizeAccountLoginOptions, ListAllAccountsResult, SpawnAccountLoginOptions, } from './accountManager';
181
188
  export { readLastSwitch, getLastSwitchPath } from './accountSwitch';
182
189
  export type { LastSwitchRecord, SwitchAccountOptions, SwitchAccountResult, SwitchVerification, } from './accountSwitch';
@@ -202,7 +209,7 @@ export { getClaudeProfilesDir, getClaudeProfileHome, getLiveClaudeHome, getDefau
202
209
  export type { ClaudeProfileIdentity } from './claudeProfiles';
203
210
  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';
204
211
  export type { CodexAccountManagerResult, CodexCredentialStoreMode } from './codexProfiles';
205
- export { writeLauncher, removeLauncher } from './terminalSync';
212
+ export { writeAccountLauncher, writeLauncher, removeLauncher } from './terminalSync';
206
213
  export { DEFAULT_AUTO_SWITCH_CONFIG, decideAutoSwitch, AutoSwitchController } from './autoSwitch';
207
214
  export type { AutoSwitchActiveAccount, AutoSwitchCandidate, AutoSwitchConfig, AutoSwitchControllerOptions, AutoSwitchDecision, AutoSwitchTransitionEvent, } from './autoSwitch';
208
215
  export { FIVE_HOUR_WINDOW_MS, QUOTA_PROVIDER_IDS, SEVEN_DAY_WINDOW_MS, fetchQuota, projectQuotaWindow, withQuotaProjections, } from './quota';
@@ -275,3 +282,6 @@ export { diagnoseProviderFailure } from './providerFailure';
275
282
  export type { ProviderCredentialKind, ProviderAuthenticationEvidence, ProviderFailureInput, ProviderFailureCode, ProviderRecoveryAction, ProviderRetryAfter, ProviderFailureEvidence, ProviderFailureDiagnosis, } from './providerFailure';
276
283
  export type { ProviderServiceSeverity, ProviderServiceComponent, ProviderServiceIncident, ProviderServiceStatusFailureReason, ObservedProviderServiceStatus, UnavailableProviderServiceStatus, ProviderServiceStatus, FetchProviderServiceStatusOptions, } from './providerServiceStatusTypes';
277
284
  export { fetchProviderServiceStatus } from './providerServiceStatus';
285
+ export { inspectCodexCredentialStores, repairCodexCredentialStores } from './codexCredentialDoctor';
286
+ export type { CodexCredentialFinding, CodexCredentialInspection, CodexCredentialRepairResult, } from './codexCredentialDoctor';
287
+ export { readStoredCodexAccount, syncCodexLiveStateAsync } from './codexProfiles';
package/dist/index.js CHANGED
@@ -8,12 +8,12 @@ exports.updateJsonStoreAtomic = exports.atomicWriteFileSync = exports.atomicWrit
8
8
  exports.classifySessionActivity = exports.subagentTokenTotals = exports.scanSessionSubagents = exports.readMainThreadTokenTotals = exports.combineSessionTokenTotals = exports.collectSessionTokenTotals = exports.addUsageToSubagent = exports.normalizeClaudeUsage = exports.dedupedRawClaudeUsage = exports.SYNTHETIC_MODEL = exports.ClaudeUsageDeduper = exports.readAgentMeta = exports.extractTaskInfo = exports.scanSubagentDir = exports.resolveCodexCallUsage = exports.normalizeCodexToolInput = exports.normalizeCodexToolName = exports.extractPatchFilePaths = exports.CodexRolloutParser = exports.parseDbPartData = exports.parseDbMessageData = exports.convertOpenCodeMessage = exports.detectPlanModeFromText = exports.normalizeToolInput = exports.normalizeToolName = exports.TRUNCATION_PATTERNS = exports.JsonlParser = exports.walkRolloutFilesAsync = exports.walkRolloutFiles = exports.findCodexRolloutFile = exports.CodexProvider = exports.getOpenCodeDataDir = exports.OpenCodeProvider = exports.ClaudeCodeProvider = exports.getAllDetectedProviders = exports.detectProvider = exports._resetProviderDetectionCache = exports.getObservedActivityReason = exports.derivePendingUserRequestV1 = exports.createProviderSessionAdapterV1 = exports.createSessionProviders = exports.SESSION_PROVIDER_IDS = exports.renderHandoffUrlTemplate = exports.addNote = exports.decisionFingerprint = exports.addDecision = exports.completeTask = exports.addTask = exports.withFileLockSync = exports.updateJsonStoreAtomicSync = void 0;
9
9
  exports.toFollowEvents = exports.resolveSessionPath = exports.createWatcher = exports.parseChangelog = exports.extractProposedPlanShared = exports.parsePlanMarkdownShared = exports.PlanExtractor = exports.segmentAssistantTurn = exports.reasoningSummary = exports.isAssistantTurnSubagentTool = exports.extractTurnSubagents = exports.assistantTurnEventsFromSessionEvents = exports.readSessionContextSnapshot = exports.createSessionContextProjector = exports.calculateSessionContextPressure = exports.buildSessionContextSnapshot = exports.composeContext = exports.FilterEngine = exports.searchSessions = exports.CodexDatabase = exports.OpenCodeDatabase = exports.discoverDebugLogs = exports.collapseDuplicates = exports.filterByLevel = exports.parseDebugLog = exports.readSessionPreviewAsync = exports.readSessionPreview = exports.listSessionPreviewsAsync = exports.listSessionPreviews = exports.readCodexHistory = exports.parseMcpToolName = exports.scanSubagentTraces = exports.findAllSessionsWithWorktrees = exports.discoverWorktreeSiblings = exports.resolveWorktreeMainRepo = exports.getAllClaudeProjectFolders = exports.decodeEncodedPath = exports.getMostRecentlyActiveSessionDir = exports.findSubdirectorySessionDirs = exports.findSessionFilesWithStats = exports.findSessionsInDirectory = exports.findAllClaudeSessions = exports.findActiveClaudeSession = exports.discoverSessionDirectory = exports.getClaudeSessionDirectory = exports.encodeClaudeWorkspacePath = exports.SESSION_ACTIVITY_STALENESS_MS = exports.SESSION_ACTIVITY_GRACE_PERIOD_MS = exports.refreshSessionActivityState = exports.detectSessionActivity = void 0;
10
10
  exports.parseTranscript = exports.generateHtmlReport = exports.formatCompactionLedger = exports.calculateCompactionLedger = exports.describeCostProvenance = exports.classifyCostProvenance = exports.calculateCodeImpact = exports.scoreSessionQuality = exports.calculateQualityTrend = exports.PatternExtractor = exports.HeatmapTracker = exports.FrequencyTracker = exports.readErrorHistory = exports.getTopFailingTools = exports.appendErrorHistory = exports.MAX_ERROR_HISTORY_SESSIONS = exports.ERROR_HISTORY_SCHEMA_VERSION = exports.getSnapshotPath = exports.MAX_SNAPSHOT_FILES = exports.pruneSnapshots = exports.isSnapshotValid = exports.deleteSnapshot = exports.loadSnapshot = exports.saveSnapshot = exports.SessionMonitor = exports.parseTodoDependencies = exports.EventAggregator = exports.getRandomPhrase = exports.PHRASE_CATEGORIES = exports.ALL_PHRASES = exports.HIGHLIGHT_CSS = exports.clearHighlightCache = exports.highlightEvent = exports.formatSessionJson = exports.formatSessionMarkdown = exports.formatSessionText = exports.classifyNoise = exports.shouldMergeWithPrevious = exports.classifyFollowEvent = exports.classifyMessage = exports.getSoftNoiseReason = exports.isHardNoiseFollowEvent = exports.isHardNoise = exports.formatToolSummary = exports.parseLocalDateKey = exports.formatTokenCount = exports.formatLocalDateKey = exports.formatDurationMs = exports.addLocalDays = exports.createJsonlTail = void 0;
11
- exports.getLastSwitchPath = exports.readLastSwitch = exports.resolveClaudeLoginCommand = exports.listAllAccounts = exports.getLastSwitch = exports.undoLastSwitch = exports.switchAccountAsync = exports.switchAccount = exports.spawnAccountLogin = exports.finalizeAccountLoginAsync = exports.finalizeAccountLogin = exports.getAccountLoginStatusAsync = exports.getAccountLoginStatus = exports.beginAccountLogin = exports.isMultiAccountEnabled = exports.resolveActiveClaudeAccount = exports.getActiveAccount = exports.listAccounts = exports.removeAccount = exports.reconcileClaudeAuthState = exports.applyActiveClaudeToLiveHome = exports.resolveActiveClaudeHome = exports.cleanupAbandonedClaudeLogins = exports.syncClaudeLiveState = exports.switchToAccountAsync = exports.switchToAccount = exports.addCurrentAccount = exports.readActiveClaudeAccount = exports.writeAccountRegistry = exports.readAccountRegistry = exports.ensureDefaultAccounts = exports.codexIdentitiesMatch = exports.readCodexAccessTokenExpiry = exports.readCodexLastRefresh = exports.readCodexAuthIdentity = exports.parseCodexAuthJson = exports.CLAUDE_REFRESH_TOKEN_LIFETIME_ESTIMATE_MS = exports.CLAUDE_ACCESS_TOKEN_LIFETIME_MS = exports.resolveClaudeRefreshExpiry = exports.isNewerClaudeCredential = exports.claudeCredentialFreshness = exports.parseClaudeCredentialBlob = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentialsRaw = exports.readClaudeMaxCredentials = exports.deleteStoredCredentials = exports.writeActiveCredentials = exports.readActiveCredentials = exports.openInBrowser = exports.parseTranscriptFromEvents = void 0;
12
- exports.getCodexExecutionEnv = exports.resolveSidekickCodexHome = exports.resolveActiveCodexAccount = exports.getActiveCodexAccount = exports.listCodexAccounts = exports.getSystemCodexHome = exports.getCodexMonitoringHomes = exports.getCodexProfileHome = exports.getCodexProfilesDir = exports.readLiveClaudeIdentity = exports.readClaudeProfileIdentity = exports.isClaudeProfileAuthenticated = exports.CLAUDE_SECURESTORAGE_CONFIG_DIR_ENV = exports.buildClaudeChildEnv = exports.claudeKeychainAccountName = exports.claudeKeychainService = exports.claudeKeychainSuffix = exports.getClaudeConfigPath = exports.getDefaultClaudeHome = exports.getLiveClaudeHome = exports.getClaudeProfileHome = exports.getClaudeProfilesDir = exports.onAccountsChanged = exports.getActiveAccountStatus = exports.ACCOUNT_PROVIDER_IDS = exports.removeSavedAccountProfile = exports.replaceSavedAccountProfiles = exports.setActiveSavedAccount = exports.upsertSavedAccountProfile = exports.getActiveSavedAccount = exports.listSavedAccountProfiles = exports.writeSavedAccountRegistry = exports.readSavedAccountRegistry = exports.getAccountsDir = exports.ACCOUNT_CONSUMER_REACHABILITY = exports.describeAccountConsumer = exports.detectRunningAccountConsumersSync = exports.detectRunningAccountConsumers = exports.findRunningProcessesSync = exports.findRunningProcesses = exports.keepAliveCommand = exports.refreshInactiveAccounts = exports.getAccountLaunchEnv = exports.getHealthSidecarPath = exports.readHealthSidecar = exports.listAccountsWithHealth = exports.getAccountHealth = exports.cleanupAbandonedLogins = exports.syncLiveAccountStateSync = exports.syncLiveAccountState = void 0;
13
- exports.quotaStateFromZaiQuotaLimitPayload = exports.fetchZaiQuotaFromApi = exports.CodexQuotaWatcher = exports.resolveCodexQuotaFromLocalSources = exports.resolveCodexQuota = exports.readLatestCodexQuotaFromRollouts = exports.quotaFromCodexRateLimits = exports.fetchCodexQuotaFromApi = exports.fetchCodexResetCreditsFromApi = exports.getWorkspaceIdFromPath = exports.pruneQuotaHistory = exports.readQuotaHistoryDailyBuckets = exports.readQuotaHistoryRange = exports.appendQuotaHistorySample = exports.quotaFromStatuslinePayload = exports.parseClaudeStatuslinePayload = exports.evaluateQuotaThresholds = exports.describeQuotaThresholdAlert = exports.DEFAULT_QUOTA_THRESHOLDS = exports.QUOTA_FRESH_MAX_AGE_MS = exports.QUOTA_AGING_MAX_AGE_MS = exports.formatQuotaAge = exports.classifyQuotaFreshness = exports.resolveQuota = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.QuotaPoller = exports.describeQuotaFailure = exports.withQuotaProjections = exports.projectQuotaWindow = exports.fetchQuota = exports.SEVEN_DAY_WINDOW_MS = exports.QUOTA_PROVIDER_IDS = exports.FIVE_HOUR_WINDOW_MS = exports.AutoSwitchController = exports.decideAutoSwitch = exports.DEFAULT_AUTO_SWITCH_CONFIG = exports.removeLauncher = exports.writeLauncher = exports.CODEX_KEYRING_FIX_HINT = exports.getCodexCredentialStoreMode = exports.cleanupAbandonedCodexLogins = exports.syncCodexLiveState = exports.removeCodexAccount = exports.switchToCodexAccountAsync = exports.switchToCodexAccount = exports.finalizeCodexAccountAsync = exports.finalizeCodexAccount = exports.prepareCodexAccountAsync = exports.prepareCodexAccount = void 0;
14
- exports.extractToolCalls = exports.extractToolCall = exports.extractErrorMessage = exports.categorizeError = exports.gatherAssetsForCwd = exports.codexSessions = exports.readCodexAssets = exports.claudeSessions = exports.readClaudeAssets = exports.extractCommands = exports.extractFilePaths = exports.extractUrls = exports.extractTokenUsage = exports.getObservedContextWindowPath = exports.recordObservedContextWindow = exports.loadObservedContextWindows = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmContextWindows = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.RESOLVED_MODEL_CATALOG_SCHEMA_VERSION = exports.resolveModelAlias = exports.registerModelAlias = exports.importResolvedModelCatalog = exports.exportResolvedModelCatalog = exports.MODEL_PROVIDER_IDS = exports.formatCost = exports.sortModelIds = exports.compareModelIds = exports.getModelDisplayInfo = exports.shortModelName = exports.mergeCostSources = exports.calculateCostWithProvenance = exports.calculateCostWithPricing = exports.calculateCost = exports.getModelInfo = exports.resolveModelPricing = exports.getModelPricing = exports.parseModelId = exports.DEFAULT_CONTEXT_WINDOW = exports.resolveModelContextWindow = exports.getModelContextWindowSize = exports.selectStatuslineAccount = exports.formatStatusline = exports.estimateTimeToQuota = exports.BurnRateCalculator = exports.RUNTIME_QUOTA_PROVIDER_IDS = exports.MultiProviderQuotaService = exports.resolveZaiQuota = exports.readZaiCredentials = void 0;
15
- exports.getSessionDiagnostics = exports.formatHealthReport = exports.toLegacyProviderStatus = exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.assistantTurnToolRefSchema = exports.assistantTurnToolGroupStepSchema = exports.assistantTurnTimelineItemSchema = exports.assistantTurnSubagentStatusSchema = exports.assistantTurnSubagentSchema = exports.assistantTurnReasoningTimelineItemSchema = exports.assistantTurnProjectionSchema = exports.assistantTurnProcessStepSchema = exports.assistantTurnProcessSchema = exports.assistantTurnNarrationStepSchema = exports.assistantTurnEventTypeSchema = exports.assistantTurnEventSchema = exports.listAllAccountsResultSchema = exports.savedAccountProfileSchema = exports.accountEntrySchema = exports.accountLoginStatusSchema = exports.beginAccountLoginResultSchema = exports.accountManagerResultSchema = exports.accountProviderIdSchema = exports.activeAccountStatusSchema = exports.activeProviderAccountStatusSchema = exports.quotaHistoryDailyBucketSchema = exports.quotaHistorySampleSchema = exports.quotaHistoryRuntimeProviderSchema = exports.providerQuotaMapSchema = exports.zaiProviderQuotaStateSchema = exports.codexProviderQuotaStateSchema = exports.claudeProviderQuotaStateSchema = exports.providerQuotaStateSchema = exports.runtimeQuotaProviderSchema = exports.quotaFailureDescriptorSchema = exports.peakHoursStateSchema = exports.codexResetCreditsSnapshotSchema = exports.codexResetCreditSchema = exports.quotaSourceSchema = exports.quotaProviderIdSchema = exports.quotaFailureKindSchema = exports.quotaStateSchema = exports.quotaWindowSchema = exports.extractSessionEvents = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.ToolCallTracker = void 0;
16
- exports.fetchProviderServiceStatus = exports.diagnoseProviderFailure = exports.mergeFailingToolWindows = exports.failingToolTrend = exports.FAILING_TOOL_TREND_ARROWS = exports.scopePeakHoursToSessionProvider = exports.PEAK_HOURS_DESCRIPTION = exports.PEAK_HOURS_CACHE_MS = exports.isClaudeCodeSessionProvider = exports.getScheduledPeakHoursState = exports.fetchPeakHoursStatus = exports.DEFAULT_PEAK_HOURS_TIMEOUT_MS = exports.createPeakHoursNotApplicableState = exports._resetPeakHoursCache = exports.runDoctor = void 0;
11
+ exports.getAccountLoginStatus = exports.beginAccountLogin = exports.isMultiAccountEnabled = exports.resolveActiveClaudeAccount = exports.getActiveAccount = exports.listAccounts = exports.removeAccount = exports.reconcileClaudeAuthState = exports.applyActiveClaudeToLiveHome = exports.resolveActiveClaudeHome = exports.cleanupAbandonedClaudeLogins = exports.syncClaudeLiveState = exports.switchToAccountAsync = exports.switchToAccount = exports.addCurrentAccount = exports.readActiveClaudeAccount = exports.writeAccountRegistry = exports.readAccountRegistry = exports.ensureDefaultAccounts = exports.codexIdentitiesMatch = exports.readCodexAccessTokenExpiry = exports.readCodexLastRefresh = exports.readCodexAuthIdentity = exports.parseCodexAuthJson = exports.CLAUDE_REFRESH_TOKEN_LIFETIME_ESTIMATE_MS = exports.CLAUDE_ACCESS_TOKEN_LIFETIME_MS = exports.mergeClaudeLoginIntoLive = exports.claudeLoginOnly = exports.claudeRefreshFingerprint = exports.resolveClaudeRefreshExpiry = exports.isNewerClaudeCredential = exports.claudeCredentialFreshness = exports.parseClaudeCredentialBlob = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentialsRaw = exports.readClaudeMaxCredentials = exports.parseKeychainDump = exports.repairClaudeCredentialStores = exports.inspectClaudeCredentialStores = exports.getClaudeCredentialLedgerPath = exports.readClaudeCredentialLedger = exports.decideLiveClaudeWrite = exports.SIDEKICK_KEYCHAIN_COMMENT_PREFIX = exports.ClaudeCredentialWriteError = exports.deleteStoredCredentials = exports.writeActiveCredentials = exports.readClaudeCredentialStore = exports.readActiveCredentials = exports.openInBrowser = exports.parseTranscriptFromEvents = void 0;
12
+ exports.buildClaudeChildEnv = exports.claudeKeychainAccountName = exports.claudeKeychainService = exports.claudeKeychainSuffix = exports.getClaudeConfigPath = exports.getDefaultClaudeHome = exports.getLiveClaudeHome = exports.getClaudeProfileHome = exports.getClaudeProfilesDir = exports.onAccountsChanged = exports.getActiveAccountStatus = exports.ACCOUNT_PROVIDER_IDS = exports.removeSavedAccountProfile = exports.replaceSavedAccountProfiles = exports.setActiveSavedAccount = exports.upsertSavedAccountProfile = exports.getActiveSavedAccount = exports.listSavedAccountProfiles = exports.writeSavedAccountRegistry = exports.readSavedAccountRegistry = exports.getAccountsDir = exports.ACCOUNT_CONSUMER_REACHABILITY = exports.describeAccountConsumer = exports.detectRunningAccountConsumersSync = exports.detectRunningAccountConsumers = exports.findRunningProcessesSync = exports.findRunningProcesses = exports.keepAliveCommand = exports.refreshInactiveAccounts = exports.getAccountLaunchEnv = exports.getHealthSidecarPath = exports.readHealthSidecar = exports.listAccountsWithHealth = exports.getAccountHealth = exports.cleanupAbandonedLogins = exports.syncLiveAccountStateSync = exports.syncLiveAccountState = exports.getLastSwitchPath = exports.readLastSwitch = exports.discardAccountLogin = exports.resolveClaudeLoginCommand = exports.listAllAccounts = exports.getLastSwitch = exports.undoLastSwitch = exports.switchAccountAsync = exports.switchAccount = exports.spawnAccountLogin = exports.finalizeAccountLoginAsync = exports.finalizeAccountLogin = exports.getAccountLoginStatusAsync = void 0;
13
+ exports.quotaFromStatuslinePayload = exports.parseClaudeStatuslinePayload = exports.evaluateQuotaThresholds = exports.describeQuotaThresholdAlert = exports.DEFAULT_QUOTA_THRESHOLDS = exports.QUOTA_FRESH_MAX_AGE_MS = exports.QUOTA_AGING_MAX_AGE_MS = exports.formatQuotaAge = exports.classifyQuotaFreshness = exports.resolveQuota = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.QuotaPoller = exports.describeQuotaFailure = exports.withQuotaProjections = exports.projectQuotaWindow = exports.fetchQuota = exports.SEVEN_DAY_WINDOW_MS = exports.QUOTA_PROVIDER_IDS = exports.FIVE_HOUR_WINDOW_MS = exports.AutoSwitchController = exports.decideAutoSwitch = exports.DEFAULT_AUTO_SWITCH_CONFIG = exports.removeLauncher = exports.writeLauncher = exports.writeAccountLauncher = exports.CODEX_KEYRING_FIX_HINT = exports.getCodexCredentialStoreMode = exports.cleanupAbandonedCodexLogins = exports.syncCodexLiveState = exports.removeCodexAccount = exports.switchToCodexAccountAsync = exports.switchToCodexAccount = exports.finalizeCodexAccountAsync = exports.finalizeCodexAccount = exports.prepareCodexAccountAsync = exports.prepareCodexAccount = exports.getCodexExecutionEnv = exports.resolveSidekickCodexHome = exports.resolveActiveCodexAccount = exports.getActiveCodexAccount = exports.listCodexAccounts = exports.getSystemCodexHome = exports.getCodexMonitoringHomes = exports.getCodexProfileHome = exports.getCodexProfilesDir = exports.readLiveClaudeIdentity = exports.readClaudeProfileIdentity = exports.isClaudeProfileAuthenticated = exports.CLAUDE_SECURESTORAGE_CONFIG_DIR_ENV = void 0;
14
+ exports.recordObservedContextWindow = exports.loadObservedContextWindows = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmContextWindows = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.RESOLVED_MODEL_CATALOG_SCHEMA_VERSION = exports.resolveModelAlias = exports.registerModelAlias = exports.importResolvedModelCatalog = exports.exportResolvedModelCatalog = exports.MODEL_PROVIDER_IDS = exports.formatCost = exports.sortModelIds = exports.compareModelIds = exports.getModelDisplayInfo = exports.shortModelName = exports.mergeCostSources = exports.calculateCostWithProvenance = exports.calculateCostWithPricing = exports.calculateCost = exports.getModelInfo = exports.resolveModelPricing = exports.getModelPricing = exports.parseModelId = exports.DEFAULT_CONTEXT_WINDOW = exports.resolveModelContextWindow = exports.getModelContextWindowSize = exports.selectStatuslineAccount = exports.formatStatusline = exports.estimateTimeToQuota = exports.BurnRateCalculator = exports.RUNTIME_QUOTA_PROVIDER_IDS = exports.MultiProviderQuotaService = exports.resolveZaiQuota = exports.readZaiCredentials = exports.quotaStateFromZaiQuotaLimitPayload = exports.fetchZaiQuotaFromApi = exports.CodexQuotaWatcher = exports.resolveCodexQuotaFromLocalSources = exports.resolveCodexQuota = exports.readLatestCodexQuotaFromRollouts = exports.quotaFromCodexRateLimits = exports.fetchCodexQuotaFromApi = exports.fetchCodexResetCreditsFromApi = exports.getWorkspaceIdFromPath = exports.pruneQuotaHistory = exports.readQuotaHistoryDailyBuckets = exports.readQuotaHistoryRange = exports.appendQuotaHistorySample = void 0;
15
+ exports.assistantTurnNarrationStepSchema = exports.assistantTurnEventTypeSchema = exports.assistantTurnEventSchema = exports.listAllAccountsResultSchema = exports.savedAccountProfileSchema = exports.accountEntrySchema = exports.accountLoginStatusSchema = exports.beginAccountLoginResultSchema = exports.accountManagerResultSchema = exports.accountProviderIdSchema = exports.activeAccountStatusSchema = exports.activeProviderAccountStatusSchema = exports.quotaHistoryDailyBucketSchema = exports.quotaHistorySampleSchema = exports.quotaHistoryRuntimeProviderSchema = exports.providerQuotaMapSchema = exports.zaiProviderQuotaStateSchema = exports.codexProviderQuotaStateSchema = exports.claudeProviderQuotaStateSchema = exports.providerQuotaStateSchema = exports.runtimeQuotaProviderSchema = exports.quotaFailureDescriptorSchema = exports.peakHoursStateSchema = exports.codexResetCreditsSnapshotSchema = exports.codexResetCreditSchema = exports.quotaSourceSchema = exports.quotaProviderIdSchema = exports.quotaFailureKindSchema = exports.quotaStateSchema = exports.quotaWindowSchema = exports.extractSessionEvents = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.ToolCallTracker = exports.extractToolCalls = exports.extractToolCall = exports.extractErrorMessage = exports.categorizeError = exports.gatherAssetsForCwd = exports.codexSessions = exports.readCodexAssets = exports.claudeSessions = exports.readClaudeAssets = exports.extractCommands = exports.extractFilePaths = exports.extractUrls = exports.extractTokenUsage = exports.getObservedContextWindowPath = void 0;
16
+ exports.syncCodexLiveStateAsync = exports.readStoredCodexAccount = exports.repairCodexCredentialStores = exports.inspectCodexCredentialStores = exports.fetchProviderServiceStatus = exports.diagnoseProviderFailure = exports.mergeFailingToolWindows = exports.failingToolTrend = exports.FAILING_TOOL_TREND_ARROWS = exports.scopePeakHoursToSessionProvider = exports.PEAK_HOURS_DESCRIPTION = exports.PEAK_HOURS_CACHE_MS = exports.isClaudeCodeSessionProvider = exports.getScheduledPeakHoursState = exports.fetchPeakHoursStatus = exports.DEFAULT_PEAK_HOURS_TIMEOUT_MS = exports.createPeakHoursNotApplicableState = exports._resetPeakHoursCache = exports.runDoctor = exports.getSessionDiagnostics = exports.formatHealthReport = exports.toLegacyProviderStatus = exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.assistantTurnToolRefSchema = exports.assistantTurnToolGroupStepSchema = exports.assistantTurnTimelineItemSchema = exports.assistantTurnSubagentStatusSchema = exports.assistantTurnSubagentSchema = exports.assistantTurnReasoningTimelineItemSchema = exports.assistantTurnProjectionSchema = exports.assistantTurnProcessStepSchema = exports.assistantTurnProcessSchema = void 0;
17
17
  var usageNormalization_1 = require("./usageNormalization");
18
18
  Object.defineProperty(exports, "normalizeProviderUsage", { enumerable: true, get: function () { return usageNormalization_1.normalizeProviderUsage; } });
19
19
  Object.defineProperty(exports, "extractNormalizedUsage", { enumerable: true, get: function () { return usageNormalization_1.extractNormalizedUsage; } });
@@ -385,8 +385,20 @@ Object.defineProperty(exports, "openInBrowser", { enumerable: true, get: functio
385
385
  // Credential I/O (platform-aware: Keychain on macOS, file on Linux/Windows)
386
386
  var credentialIO_1 = require("./credentialIO");
387
387
  Object.defineProperty(exports, "readActiveCredentials", { enumerable: true, get: function () { return credentialIO_1.readActiveCredentials; } });
388
+ Object.defineProperty(exports, "readClaudeCredentialStore", { enumerable: true, get: function () { return credentialIO_1.readClaudeCredentialStore; } });
388
389
  Object.defineProperty(exports, "writeActiveCredentials", { enumerable: true, get: function () { return credentialIO_1.writeActiveCredentials; } });
389
390
  Object.defineProperty(exports, "deleteStoredCredentials", { enumerable: true, get: function () { return credentialIO_1.deleteStoredCredentials; } });
391
+ Object.defineProperty(exports, "ClaudeCredentialWriteError", { enumerable: true, get: function () { return credentialIO_1.ClaudeCredentialWriteError; } });
392
+ Object.defineProperty(exports, "SIDEKICK_KEYCHAIN_COMMENT_PREFIX", { enumerable: true, get: function () { return credentialIO_1.SIDEKICK_KEYCHAIN_COMMENT_PREFIX; } });
393
+ var claudeLiveGuard_1 = require("./claudeLiveGuard");
394
+ Object.defineProperty(exports, "decideLiveClaudeWrite", { enumerable: true, get: function () { return claudeLiveGuard_1.decideLiveClaudeWrite; } });
395
+ var claudeCredentialLedger_1 = require("./claudeCredentialLedger");
396
+ Object.defineProperty(exports, "readClaudeCredentialLedger", { enumerable: true, get: function () { return claudeCredentialLedger_1.readClaudeCredentialLedger; } });
397
+ Object.defineProperty(exports, "getClaudeCredentialLedgerPath", { enumerable: true, get: function () { return claudeCredentialLedger_1.getClaudeCredentialLedgerPath; } });
398
+ var claudeCredentialDoctor_1 = require("./claudeCredentialDoctor");
399
+ Object.defineProperty(exports, "inspectClaudeCredentialStores", { enumerable: true, get: function () { return claudeCredentialDoctor_1.inspectClaudeCredentialStores; } });
400
+ Object.defineProperty(exports, "repairClaudeCredentialStores", { enumerable: true, get: function () { return claudeCredentialDoctor_1.repairClaudeCredentialStores; } });
401
+ Object.defineProperty(exports, "parseKeychainDump", { enumerable: true, get: function () { return claudeCredentialDoctor_1.parseKeychainDump; } });
390
402
  // Credentials
391
403
  var credentials_1 = require("./credentials");
392
404
  Object.defineProperty(exports, "readClaudeMaxCredentials", { enumerable: true, get: function () { return credentials_1.readClaudeMaxCredentials; } });
@@ -397,6 +409,9 @@ Object.defineProperty(exports, "parseClaudeCredentialBlob", { enumerable: true,
397
409
  Object.defineProperty(exports, "claudeCredentialFreshness", { enumerable: true, get: function () { return claudeCredentials_1.claudeCredentialFreshness; } });
398
410
  Object.defineProperty(exports, "isNewerClaudeCredential", { enumerable: true, get: function () { return claudeCredentials_1.isNewerClaudeCredential; } });
399
411
  Object.defineProperty(exports, "resolveClaudeRefreshExpiry", { enumerable: true, get: function () { return claudeCredentials_1.resolveClaudeRefreshExpiry; } });
412
+ Object.defineProperty(exports, "claudeRefreshFingerprint", { enumerable: true, get: function () { return claudeCredentials_1.claudeRefreshFingerprint; } });
413
+ Object.defineProperty(exports, "claudeLoginOnly", { enumerable: true, get: function () { return claudeCredentials_1.claudeLoginOnly; } });
414
+ Object.defineProperty(exports, "mergeClaudeLoginIntoLive", { enumerable: true, get: function () { return claudeCredentials_1.mergeClaudeLoginIntoLive; } });
400
415
  Object.defineProperty(exports, "CLAUDE_ACCESS_TOKEN_LIFETIME_MS", { enumerable: true, get: function () { return claudeCredentials_1.CLAUDE_ACCESS_TOKEN_LIFETIME_MS; } });
401
416
  Object.defineProperty(exports, "CLAUDE_REFRESH_TOKEN_LIFETIME_ESTIMATE_MS", { enumerable: true, get: function () { return claudeCredentials_1.CLAUDE_REFRESH_TOKEN_LIFETIME_ESTIMATE_MS; } });
402
417
  var codexAuth_1 = require("./codexAuth");
@@ -438,6 +453,7 @@ Object.defineProperty(exports, "undoLastSwitch", { enumerable: true, get: functi
438
453
  Object.defineProperty(exports, "getLastSwitch", { enumerable: true, get: function () { return accountManager_1.getLastSwitch; } });
439
454
  Object.defineProperty(exports, "listAllAccounts", { enumerable: true, get: function () { return accountManager_1.listAllAccounts; } });
440
455
  Object.defineProperty(exports, "resolveClaudeLoginCommand", { enumerable: true, get: function () { return accountManager_1.resolveClaudeLoginCommand; } });
456
+ Object.defineProperty(exports, "discardAccountLogin", { enumerable: true, get: function () { return accountManager_1.discardAccountLogin; } });
441
457
  var accountSwitch_1 = require("./accountSwitch");
442
458
  Object.defineProperty(exports, "readLastSwitch", { enumerable: true, get: function () { return accountSwitch_1.readLastSwitch; } });
443
459
  Object.defineProperty(exports, "getLastSwitchPath", { enumerable: true, get: function () { return accountSwitch_1.getLastSwitchPath; } });
@@ -514,6 +530,7 @@ Object.defineProperty(exports, "cleanupAbandonedCodexLogins", { enumerable: true
514
530
  Object.defineProperty(exports, "getCodexCredentialStoreMode", { enumerable: true, get: function () { return codexProfiles_1.getCodexCredentialStoreMode; } });
515
531
  Object.defineProperty(exports, "CODEX_KEYRING_FIX_HINT", { enumerable: true, get: function () { return codexProfiles_1.CODEX_KEYRING_FIX_HINT; } });
516
532
  var terminalSync_1 = require("./terminalSync");
533
+ Object.defineProperty(exports, "writeAccountLauncher", { enumerable: true, get: function () { return terminalSync_1.writeAccountLauncher; } });
517
534
  Object.defineProperty(exports, "writeLauncher", { enumerable: true, get: function () { return terminalSync_1.writeLauncher; } });
518
535
  Object.defineProperty(exports, "removeLauncher", { enumerable: true, get: function () { return terminalSync_1.removeLauncher; } });
519
536
  var autoSwitch_1 = require("./autoSwitch");
@@ -725,3 +742,9 @@ var providerFailure_1 = require("./providerFailure");
725
742
  Object.defineProperty(exports, "diagnoseProviderFailure", { enumerable: true, get: function () { return providerFailure_1.diagnoseProviderFailure; } });
726
743
  var providerServiceStatus_1 = require("./providerServiceStatus");
727
744
  Object.defineProperty(exports, "fetchProviderServiceStatus", { enumerable: true, get: function () { return providerServiceStatus_1.fetchProviderServiceStatus; } });
745
+ var codexCredentialDoctor_1 = require("./codexCredentialDoctor");
746
+ Object.defineProperty(exports, "inspectCodexCredentialStores", { enumerable: true, get: function () { return codexCredentialDoctor_1.inspectCodexCredentialStores; } });
747
+ Object.defineProperty(exports, "repairCodexCredentialStores", { enumerable: true, get: function () { return codexCredentialDoctor_1.repairCodexCredentialStores; } });
748
+ var codexProfiles_2 = require("./codexProfiles");
749
+ Object.defineProperty(exports, "readStoredCodexAccount", { enumerable: true, get: function () { return codexProfiles_2.readStoredCodexAccount; } });
750
+ Object.defineProperty(exports, "syncCodexLiveStateAsync", { enumerable: true, get: function () { return codexProfiles_2.syncCodexLiveStateAsync; } });