sidekick-shared 0.21.3 → 0.21.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -1
- package/dist/accountRegistry.d.ts +17 -0
- package/dist/accountStatus.js +7 -10
- package/dist/accounts.d.ts +13 -0
- package/dist/accounts.js +50 -0
- package/dist/codexProfiles.d.ts +15 -1
- package/dist/codexProfiles.js +51 -0
- package/dist/codexQuotaWatcher.js +9 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +6 -4
- package/dist/multiProviderQuotaService.d.ts +2 -2
- package/dist/multiProviderQuotaService.js +4 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ npm install sidekick-shared
|
|
|
47
47
|
| **Model Info & Pricing** | Model family parsing (Anthropic / OpenAI / Google, including legacy `claude-3-opus-…` and `claude-3-5-sonnet-…` IDs), context-window lookup (including Fable 5 / Opus 4.8 / Opus 4.7 / Sonnet 4.7 1M and GPT-5.x variants), pricing tables with optional LiteLLM hydration, null-aware cost (`calculateCost()`), provenance-preserving cost (`calculateCostWithProvenance()`, `mergeCostSources()`), and display helpers (`shortModelName()`, `getModelDisplayInfo()`, `compareModelIds()`, `sortModelIds()`, `formatCost()`) |
|
|
48
48
|
| **Quota Polling** | `QuotaPoller` class with exponential backoff, active/idle intervals, and cached fallback |
|
|
49
49
|
| **Multi-Provider Quota** | `MultiProviderQuotaService` orchestrates Claude polling + peak-hours + account labels + Codex/z.ai quota updates behind one typed event stream. `CodexQuotaWatcher` watches the active Codex rollout for live rate limits with snapshot fallback; z.ai quota uses the API resolver with snapshot fallback |
|
|
50
|
-
| **Accounts** | Multi-provider account registry (v2) with per-provider active account, save/switch/remove, v1 migration, `ensureDefaultAccounts()` for first-run bootstrap of the active system Claude/Codex credentials as a "Default" saved account,
|
|
50
|
+
| **Accounts** | Multi-provider account registry (v2) with per-provider active account, save/switch/remove, v1 migration, `ensureDefaultAccounts()` for first-run bootstrap of the active system Claude/Codex credentials as a "Default" saved account, `getActiveAccountStatus()` for a single-pass active-account read across providers, and live-first `resolveActiveClaudeAccount()` / `resolveActiveCodexAccount()` that report the currently logged-in account (self-healing the saved pointer) for display |
|
|
51
51
|
| **Account Management 2.0** | Provider-neutral acquisition + switching: `beginAccountLogin()` / `getAccountLoginStatus()` / `finalizeAccountLogin()` / `spawnAccountLogin()` drive a TTY-less, profile-isolated login that doesn't disturb the active account until finalization; `listAllAccounts()` and `switchAccount()` expose a shared switcher across Claude and Codex. Claude accounts get canonical profile homes with account-scoped macOS keychain suffixes and startup migration from legacy flat backups |
|
|
52
52
|
| **Terminal sync & auto-switch** | Opt-in terminal profile pointers, shell-hook/launcher helpers, and a default-off `AutoSwitchController` (`decideAutoSwitch()`) that moves to a healthier saved account when quota crosses a configured threshold |
|
|
53
53
|
| **Codex Profiles** | Codex account lifecycle — prepare, finalize, switch, remove — switching atomically swaps the profile's backed-up credentials into the system `~/.codex/auth.json`, with rotated-token staleness protection, one-time dual-home migration, and legacy multi-home session monitoring |
|
|
@@ -359,6 +359,21 @@ console.log(status.claude.present, status.claude.email);
|
|
|
359
359
|
console.log(status.codex.present, status.codex.label);
|
|
360
360
|
```
|
|
361
361
|
|
|
362
|
+
For display surfaces that must reflect the **currently logged-in** account — even after a native `claude /login` or `codex login` outside Sidekick — use the live-first resolvers. They prefer the live provider auth (`~/.claude/.claude.json` oauthAccount; the `~/.codex/auth.json` id_token JWT) over the saved `activeByProvider` pointer, fall back to the registry, and self-heal the saved pointer on an unambiguous match (best-effort, never creating or deleting profiles):
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
import { resolveActiveClaudeAccount, resolveActiveCodexAccount } from 'sidekick-shared';
|
|
366
|
+
import type { ResolvedActiveAccount } from 'sidekick-shared';
|
|
367
|
+
|
|
368
|
+
const claude: ResolvedActiveAccount = resolveActiveClaudeAccount();
|
|
369
|
+
// source: 'live' → identity came from the live provider auth (label filled when it matches a saved profile)
|
|
370
|
+
// source: 'registry' → no usable live identity; fell back to the saved active pointer
|
|
371
|
+
// source: 'none' → neither a live identity nor a saved active account
|
|
372
|
+
console.log(claude.email, claude.label, claude.source);
|
|
373
|
+
|
|
374
|
+
const codex = resolveActiveCodexAccount();
|
|
375
|
+
```
|
|
376
|
+
|
|
362
377
|
### Track cost provenance for honest UI rollups
|
|
363
378
|
|
|
364
379
|
```typescript
|
|
@@ -19,6 +19,23 @@ export interface SavedAccountRegistry {
|
|
|
19
19
|
activeByProvider: Record<AccountProviderId, string | null>;
|
|
20
20
|
accounts: SavedAccountProfile[];
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* The currently active account resolved from the *live* provider auth, with the
|
|
24
|
+
* saved registry used only to enrich the display label.
|
|
25
|
+
*
|
|
26
|
+
* - `source: 'live'` — identity came from the provider's live auth file. This
|
|
27
|
+
* is the source of truth; `label` is filled in only when the live identity
|
|
28
|
+
* matches a saved profile.
|
|
29
|
+
* - `source: 'registry'` — no usable live identity (logged out, api-key auth,
|
|
30
|
+
* unparseable token); fell back to the saved active pointer.
|
|
31
|
+
* - `source: 'none'` — neither a live identity nor a saved active account.
|
|
32
|
+
*/
|
|
33
|
+
export interface ResolvedActiveAccount {
|
|
34
|
+
email?: string;
|
|
35
|
+
label?: string;
|
|
36
|
+
providerAccountId?: string;
|
|
37
|
+
source: 'live' | 'registry' | 'none';
|
|
38
|
+
}
|
|
22
39
|
export declare function getAccountsDir(): string;
|
|
23
40
|
export declare function readSavedAccountRegistry(): SavedAccountRegistry | null;
|
|
24
41
|
export declare function writeSavedAccountRegistry(registry: SavedAccountRegistry): void;
|
package/dist/accountStatus.js
CHANGED
|
@@ -14,23 +14,20 @@ function errorMessage(error) {
|
|
|
14
14
|
*/
|
|
15
15
|
function getActiveAccountStatus(error) {
|
|
16
16
|
try {
|
|
17
|
-
const claudeAccount = (0, accounts_1.
|
|
18
|
-
const codexAccount = (0, codexProfiles_1.
|
|
19
|
-
const claude = claudeAccount
|
|
17
|
+
const claudeAccount = (0, accounts_1.resolveActiveClaudeAccount)();
|
|
18
|
+
const codexAccount = (0, codexProfiles_1.resolveActiveCodexAccount)();
|
|
19
|
+
const claude = claudeAccount.source !== 'none'
|
|
20
20
|
? {
|
|
21
21
|
present: true,
|
|
22
22
|
email: claudeAccount.email,
|
|
23
|
-
label: claudeAccount.email,
|
|
23
|
+
label: claudeAccount.label ?? claudeAccount.email,
|
|
24
24
|
}
|
|
25
25
|
: { present: false };
|
|
26
|
-
const codex = codexAccount
|
|
26
|
+
const codex = codexAccount.source !== 'none'
|
|
27
27
|
? {
|
|
28
28
|
present: true,
|
|
29
|
-
email: codexAccount.email
|
|
30
|
-
label: codexAccount.label ??
|
|
31
|
-
codexAccount.email ??
|
|
32
|
-
codexAccount.metadata?.email ??
|
|
33
|
-
codexAccount.id,
|
|
29
|
+
email: codexAccount.email,
|
|
30
|
+
label: codexAccount.label ?? codexAccount.email ?? codexAccount.providerAccountId,
|
|
34
31
|
}
|
|
35
32
|
: { present: false };
|
|
36
33
|
return {
|
package/dist/accounts.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Handles saving, listing, switching, and removing Claude accounts.
|
|
5
5
|
* Both the VS Code extension and CLI consume this module.
|
|
6
6
|
*/
|
|
7
|
+
import { type ResolvedActiveAccount } from './accountRegistry';
|
|
7
8
|
export interface AccountEntry {
|
|
8
9
|
uuid: string;
|
|
9
10
|
email: string;
|
|
@@ -38,4 +39,16 @@ export declare function reconcileClaudeAuthState(): void;
|
|
|
38
39
|
export declare function removeAccount(uuid: string): AccountManagerResult;
|
|
39
40
|
export declare function listAccounts(): AccountEntry[];
|
|
40
41
|
export declare function getActiveAccount(): AccountEntry | null;
|
|
42
|
+
/**
|
|
43
|
+
* Resolves the *currently logged-in* Claude account for display, preferring the
|
|
44
|
+
* live `~/.claude/.claude.json` identity over the saved registry pointer (which
|
|
45
|
+
* only sidekick's own switch flow updates and therefore goes stale after a native
|
|
46
|
+
* `claude /login`).
|
|
47
|
+
*
|
|
48
|
+
* Safe self-heal: when the live account matches a saved profile (by account UUID,
|
|
49
|
+
* email as fallback) that isn't the current active pointer, the pointer is
|
|
50
|
+
* re-pointed so registry-keyed data tracks reality too. Never creates or deletes
|
|
51
|
+
* profiles; an unknown live account is shown as-is with no label and no write.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveActiveClaudeAccount(): ResolvedActiveAccount;
|
|
41
54
|
export declare function isMultiAccountEnabled(): boolean;
|
package/dist/accounts.js
CHANGED
|
@@ -50,6 +50,7 @@ exports.reconcileClaudeAuthState = reconcileClaudeAuthState;
|
|
|
50
50
|
exports.removeAccount = removeAccount;
|
|
51
51
|
exports.listAccounts = listAccounts;
|
|
52
52
|
exports.getActiveAccount = getActiveAccount;
|
|
53
|
+
exports.resolveActiveClaudeAccount = resolveActiveClaudeAccount;
|
|
53
54
|
exports.isMultiAccountEnabled = isMultiAccountEnabled;
|
|
54
55
|
const fs = __importStar(require("fs"));
|
|
55
56
|
const path = __importStar(require("path"));
|
|
@@ -513,6 +514,55 @@ function getActiveAccount() {
|
|
|
513
514
|
addedAt: active.addedAt,
|
|
514
515
|
};
|
|
515
516
|
}
|
|
517
|
+
/**
|
|
518
|
+
* Resolves the *currently logged-in* Claude account for display, preferring the
|
|
519
|
+
* live `~/.claude/.claude.json` identity over the saved registry pointer (which
|
|
520
|
+
* only sidekick's own switch flow updates and therefore goes stale after a native
|
|
521
|
+
* `claude /login`).
|
|
522
|
+
*
|
|
523
|
+
* Safe self-heal: when the live account matches a saved profile (by account UUID,
|
|
524
|
+
* email as fallback) that isn't the current active pointer, the pointer is
|
|
525
|
+
* re-pointed so registry-keyed data tracks reality too. Never creates or deletes
|
|
526
|
+
* profiles; an unknown live account is shown as-is with no label and no write.
|
|
527
|
+
*/
|
|
528
|
+
function resolveActiveClaudeAccount() {
|
|
529
|
+
const live = readActiveClaudeAccount();
|
|
530
|
+
if (live) {
|
|
531
|
+
const profiles = (0, accountRegistry_1.listSavedAccountProfiles)('claude-code');
|
|
532
|
+
const match = profiles.find((p) => (p.providerAccountId ?? p.id) === live.uuid) ??
|
|
533
|
+
profiles.find((p) => (p.email ?? p.metadata?.email) === live.email);
|
|
534
|
+
if (match) {
|
|
535
|
+
const active = (0, accountRegistry_1.getActiveSavedAccount)('claude-code');
|
|
536
|
+
if (!active || active.id !== match.id) {
|
|
537
|
+
// Self-heal is best-effort: a registry write failure (read-only/full
|
|
538
|
+
// disk) must never break display or extension activation. We still
|
|
539
|
+
// return the correct live identity below.
|
|
540
|
+
try {
|
|
541
|
+
(0, accountRegistry_1.setActiveSavedAccount)('claude-code', match.id);
|
|
542
|
+
}
|
|
543
|
+
catch {
|
|
544
|
+
/* keep going with the live identity */
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return {
|
|
549
|
+
email: live.email,
|
|
550
|
+
label: match?.label,
|
|
551
|
+
providerAccountId: live.uuid,
|
|
552
|
+
source: 'live',
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
const active = getActiveAccount();
|
|
556
|
+
if (active) {
|
|
557
|
+
return {
|
|
558
|
+
email: active.email,
|
|
559
|
+
label: active.label,
|
|
560
|
+
providerAccountId: active.uuid,
|
|
561
|
+
source: 'registry',
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
return { source: 'none' };
|
|
565
|
+
}
|
|
516
566
|
function isMultiAccountEnabled() {
|
|
517
567
|
return (0, accountRegistry_1.listSavedAccountProfiles)('claude-code').length >= 1;
|
|
518
568
|
}
|
package/dist/codexProfiles.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AccountIdentityMetadata, SavedAccountProfile } from './accountRegistry';
|
|
1
|
+
import type { AccountIdentityMetadata, ResolvedActiveAccount, SavedAccountProfile } from './accountRegistry';
|
|
2
2
|
import type { AccountManagerResult } from './accounts';
|
|
3
3
|
export interface CodexAccountManagerResult extends AccountManagerResult {
|
|
4
4
|
needsLogin?: boolean;
|
|
@@ -14,6 +14,20 @@ export declare function isCodexProfileAuthenticated(codexHome: string): boolean;
|
|
|
14
14
|
export declare function listCodexAccounts(): SavedAccountProfile[];
|
|
15
15
|
export declare function getActiveCodexAccount(): SavedAccountProfile | null;
|
|
16
16
|
export declare function resolveSidekickCodexHome(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the *currently logged-in* Codex account for display, preferring the
|
|
19
|
+
* live `auth.json` identity over the saved registry pointer (which only sidekick's
|
|
20
|
+
* own switch flow updates and therefore goes stale after a native `codex login`).
|
|
21
|
+
*
|
|
22
|
+
* Uses the cheap JWT decode from `auth.json` directly — NOT `readCodexAccountMetadata`,
|
|
23
|
+
* whose fallback spawns `codex login status` (a multi-second subprocess) unsuitable
|
|
24
|
+
* for a render path.
|
|
25
|
+
*
|
|
26
|
+
* Safe self-heal: when the live identity unambiguously matches a saved profile that
|
|
27
|
+
* isn't the current active pointer, the pointer is re-pointed so registry-keyed data
|
|
28
|
+
* (quota history, auto-switch) tracks reality too. Never creates or deletes profiles.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveActiveCodexAccount(): ResolvedActiveAccount;
|
|
17
31
|
export declare function getCodexExecutionEnv(baseEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
18
32
|
export declare function prepareCodexAccount(label: string): CodexAccountManagerResult;
|
|
19
33
|
export declare function finalizeCodexAccount(profileId: string, opts?: {
|
package/dist/codexProfiles.js
CHANGED
|
@@ -42,6 +42,7 @@ exports.isCodexProfileAuthenticated = isCodexProfileAuthenticated;
|
|
|
42
42
|
exports.listCodexAccounts = listCodexAccounts;
|
|
43
43
|
exports.getActiveCodexAccount = getActiveCodexAccount;
|
|
44
44
|
exports.resolveSidekickCodexHome = resolveSidekickCodexHome;
|
|
45
|
+
exports.resolveActiveCodexAccount = resolveActiveCodexAccount;
|
|
45
46
|
exports.getCodexExecutionEnv = getCodexExecutionEnv;
|
|
46
47
|
exports.prepareCodexAccount = prepareCodexAccount;
|
|
47
48
|
exports.finalizeCodexAccount = finalizeCodexAccount;
|
|
@@ -346,6 +347,56 @@ function resolveSidekickCodexHome() {
|
|
|
346
347
|
// home (or an explicit CODEX_HOME) is always the single live home.
|
|
347
348
|
return getSystemCodexHome();
|
|
348
349
|
}
|
|
350
|
+
/**
|
|
351
|
+
* Resolves the *currently logged-in* Codex account for display, preferring the
|
|
352
|
+
* live `auth.json` identity over the saved registry pointer (which only sidekick's
|
|
353
|
+
* own switch flow updates and therefore goes stale after a native `codex login`).
|
|
354
|
+
*
|
|
355
|
+
* Uses the cheap JWT decode from `auth.json` directly — NOT `readCodexAccountMetadata`,
|
|
356
|
+
* whose fallback spawns `codex login status` (a multi-second subprocess) unsuitable
|
|
357
|
+
* for a render path.
|
|
358
|
+
*
|
|
359
|
+
* Safe self-heal: when the live identity unambiguously matches a saved profile that
|
|
360
|
+
* isn't the current active pointer, the pointer is re-pointed so registry-keyed data
|
|
361
|
+
* (quota history, auto-switch) tracks reality too. Never creates or deletes profiles.
|
|
362
|
+
*/
|
|
363
|
+
function resolveActiveCodexAccount() {
|
|
364
|
+
const identity = readAuthIdentityFromRaw(readFileOrNull(path.join(resolveSidekickCodexHome(), 'auth.json')));
|
|
365
|
+
if (identity && (identity.email || identity.workspaceId)) {
|
|
366
|
+
const match = findProfileForIdentity(identity);
|
|
367
|
+
if (match) {
|
|
368
|
+
const active = (0, accountRegistry_1.getActiveSavedAccount)('codex');
|
|
369
|
+
if (!active || active.id !== match.id) {
|
|
370
|
+
// Self-heal is best-effort: a registry write failure (read-only/full
|
|
371
|
+
// disk) must never break display, extension activation, or the quota
|
|
372
|
+
// watcher's hot path. We still return the correct live identity below.
|
|
373
|
+
try {
|
|
374
|
+
(0, accountRegistry_1.setActiveSavedAccount)('codex', match.id);
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
/* keep going with the live identity */
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
email: identity.email ?? match?.email ?? match?.metadata?.email,
|
|
383
|
+
label: match?.label,
|
|
384
|
+
providerAccountId: match?.providerAccountId ?? identity.workspaceId,
|
|
385
|
+
source: 'live',
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
// api-key auth, unparseable token, or logged out → fall back to the registry.
|
|
389
|
+
const active = getActiveCodexAccount();
|
|
390
|
+
if (active) {
|
|
391
|
+
return {
|
|
392
|
+
email: active.email ?? active.metadata?.email,
|
|
393
|
+
label: active.label,
|
|
394
|
+
providerAccountId: active.providerAccountId,
|
|
395
|
+
source: 'registry',
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
return { source: 'none' };
|
|
399
|
+
}
|
|
349
400
|
function getCodexExecutionEnv(baseEnv = process.env) {
|
|
350
401
|
return {
|
|
351
402
|
...baseEnv,
|
|
@@ -96,7 +96,15 @@ class CodexQuotaWatcher {
|
|
|
96
96
|
this.discoveryPollIntervalMs =
|
|
97
97
|
options.discoveryPollIntervalMs ?? DEFAULT_DISCOVERY_POLL_INTERVAL_MS;
|
|
98
98
|
this.providerFactory = options.providerFactory ?? (() => new codex_1.CodexProvider());
|
|
99
|
-
|
|
99
|
+
// Self-heal the registry pointer to the live login before reading it, so the
|
|
100
|
+
// history key (account.id) and the display label track the currently
|
|
101
|
+
// logged-in account even after a native `codex login`. Overridable for tests.
|
|
102
|
+
this.getActiveAccount =
|
|
103
|
+
options.getActiveAccount ??
|
|
104
|
+
(() => {
|
|
105
|
+
(0, codexProfiles_1.resolveActiveCodexAccount)();
|
|
106
|
+
return (0, codexProfiles_1.getActiveCodexAccount)();
|
|
107
|
+
});
|
|
100
108
|
this.readSnapshot = options.readSnapshot ?? quotaSnapshots_1.readQuotaSnapshot;
|
|
101
109
|
this.writeSnapshot = options.writeSnapshot ?? quotaSnapshots_1.writeQuotaSnapshot;
|
|
102
110
|
this.watchFile = options.watchFile ?? fs.watch;
|
package/dist/index.d.ts
CHANGED
|
@@ -93,17 +93,17 @@ export { readClaudeMaxCredentials, readClaudeMaxAccessTokenSync } from './creden
|
|
|
93
93
|
export type { ClaudeMaxCredentials } from './credentials';
|
|
94
94
|
export { ensureDefaultAccounts } from './ensureDefaultAccounts';
|
|
95
95
|
export type { EnsureDefaultAccountStatus, EnsureDefaultAccountsOptions, EnsureDefaultAccountsResult, } from './ensureDefaultAccounts';
|
|
96
|
-
export { readAccountRegistry, writeAccountRegistry, readActiveClaudeAccount, addCurrentAccount, switchToAccount, resolveActiveClaudeHome, applyActiveClaudeToLiveHome, reconcileClaudeAuthState, removeAccount, listAccounts, getActiveAccount, isMultiAccountEnabled, } from './accounts';
|
|
96
|
+
export { readAccountRegistry, writeAccountRegistry, readActiveClaudeAccount, addCurrentAccount, switchToAccount, resolveActiveClaudeHome, applyActiveClaudeToLiveHome, reconcileClaudeAuthState, removeAccount, listAccounts, getActiveAccount, resolveActiveClaudeAccount, isMultiAccountEnabled, } from './accounts';
|
|
97
97
|
export type { AccountEntry, AccountRegistry, ActiveAccountInfo, AccountManagerResult, } from './accounts';
|
|
98
98
|
export { beginAccountLogin, getAccountLoginStatus, finalizeAccountLogin, spawnAccountLogin, switchAccount, listAllAccounts, resolveClaudeLoginCommand, } from './accountManager';
|
|
99
99
|
export type { AccountLoginCommand, AccountLoginState, AccountLoginStatus, BeginAccountLoginResult, FinalizeAccountLoginOptions, ListAllAccountsResult, SpawnAccountLoginOptions, } from './accountManager';
|
|
100
100
|
export { getAccountsDir, readSavedAccountRegistry, writeSavedAccountRegistry, listSavedAccountProfiles, getActiveSavedAccount, upsertSavedAccountProfile, setActiveSavedAccount, replaceSavedAccountProfiles, removeSavedAccountProfile, } from './accountRegistry';
|
|
101
|
-
export type { AccountProviderId, AccountIdentityMetadata, SavedAccountProfile, SavedAccountRegistry, } from './accountRegistry';
|
|
101
|
+
export type { AccountProviderId, AccountIdentityMetadata, ResolvedActiveAccount, SavedAccountProfile, SavedAccountRegistry, } from './accountRegistry';
|
|
102
102
|
export { getActiveAccountStatus } from './accountStatus';
|
|
103
103
|
export type { ActiveAccountStatus, ActiveProviderAccountStatus } from './accountStatus';
|
|
104
104
|
export { getClaudeProfilesDir, getClaudeProfileHome, claudeKeychainSuffix, claudeKeychainService, isClaudeProfileAuthenticated, readClaudeProfileIdentity, } from './claudeProfiles';
|
|
105
105
|
export type { ClaudeProfileIdentity } from './claudeProfiles';
|
|
106
|
-
export { getCodexProfilesDir, getCodexProfileHome, getCodexMonitoringHomes, getSystemCodexHome, listCodexAccounts, getActiveCodexAccount, resolveSidekickCodexHome, getCodexExecutionEnv, prepareCodexAccount, finalizeCodexAccount, switchToCodexAccount, removeCodexAccount, } from './codexProfiles';
|
|
106
|
+
export { getCodexProfilesDir, getCodexProfileHome, getCodexMonitoringHomes, getSystemCodexHome, listCodexAccounts, getActiveCodexAccount, resolveActiveCodexAccount, resolveSidekickCodexHome, getCodexExecutionEnv, prepareCodexAccount, finalizeCodexAccount, switchToCodexAccount, removeCodexAccount, } from './codexProfiles';
|
|
107
107
|
export type { CodexAccountManagerResult } from './codexProfiles';
|
|
108
108
|
export { setTerminalActiveProfile, installShellHook, uninstallShellHook, isShellHookInstalled, writeLauncher, removeLauncher, } from './terminalSync';
|
|
109
109
|
export { DEFAULT_AUTO_SWITCH_CONFIG, decideAutoSwitch, AutoSwitchController } from './autoSwitch';
|
package/dist/index.js
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.discoverSessionDirectory = exports.getClaudeSessionDirectory = exports.encodeClaudeWorkspacePath = exports.detectSessionActivity = exports.extractTaskInfo = exports.scanSubagentDir = 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.CodexProvider = exports.getOpenCodeDataDir = exports.OpenCodeProvider = exports.ClaudeCodeProvider = exports.getAllDetectedProviders = exports.detectProvider = exports.readClaudeCodePlanFiles = exports.getPlanAnalytics = exports.writePlans = exports.getLatestPlan = exports.readPlans = exports.readLatestHandoff = exports.readHistory = exports.readNotes = exports.readDecisions = exports.readTasks = exports.getProjectSlugRaw = exports.getProjectSlug = exports.encodeWorkspacePath = exports.getGlobalDataPath = exports.getProjectDataPath = exports.getConfigDir = exports.MAX_PLANS_PER_PROJECT = exports.PLAN_SCHEMA_VERSION = exports.createEmptyTokenTotals = exports.HISTORICAL_DATA_SCHEMA_VERSION = exports.STALENESS_THRESHOLDS = exports.IMPORTANCE_DECAY_FACTORS = exports.KNOWLEDGE_NOTE_SCHEMA_VERSION = exports.DECISION_LOG_SCHEMA_VERSION = exports.normalizeTaskStatus = exports.TASK_PERSISTENCE_SCHEMA_VERSION = void 0;
|
|
7
7
|
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.formatTokenCount = exports.formatDurationMs = exports.createJsonlTail = exports.toFollowEvents = 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.scanSubagentTraces = exports.findAllSessionsWithWorktrees = exports.discoverWorktreeSiblings = exports.resolveWorktreeMainRepo = exports.getAllClaudeProjectFolders = exports.decodeEncodedPath = exports.getMostRecentlyActiveSessionDir = exports.findSubdirectorySessionDirs = exports.findSessionsInDirectory = exports.findAllClaudeSessions = exports.findActiveClaudeSession = void 0;
|
|
8
|
-
exports.
|
|
9
|
-
exports.
|
|
10
|
-
exports.
|
|
11
|
-
exports.scopePeakHoursToSessionProvider = exports.isClaudeCodeSessionProvider = exports.fetchPeakHoursStatus = exports.createPeakHoursNotApplicableState = 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.quotaSourceSchema = exports.quotaProviderIdSchema = exports.quotaFailureKindSchema = exports.quotaStateSchema = exports.quotaWindowSchema = exports.extractSessionEvents = void 0;
|
|
8
|
+
exports.upsertSavedAccountProfile = exports.getActiveSavedAccount = exports.listSavedAccountProfiles = exports.writeSavedAccountRegistry = exports.readSavedAccountRegistry = exports.getAccountsDir = exports.resolveClaudeLoginCommand = exports.listAllAccounts = exports.switchAccount = exports.spawnAccountLogin = exports.finalizeAccountLogin = exports.getAccountLoginStatus = exports.beginAccountLogin = exports.isMultiAccountEnabled = exports.resolveActiveClaudeAccount = exports.getActiveAccount = exports.listAccounts = exports.removeAccount = exports.reconcileClaudeAuthState = exports.applyActiveClaudeToLiveHome = exports.resolveActiveClaudeHome = exports.switchToAccount = exports.addCurrentAccount = exports.readActiveClaudeAccount = exports.writeAccountRegistry = exports.readAccountRegistry = exports.ensureDefaultAccounts = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentials = exports.writeActiveCredentials = exports.readActiveCredentials = exports.openInBrowser = exports.parseTranscriptFromEvents = exports.parseTranscript = exports.generateHtmlReport = exports.PatternExtractor = exports.HeatmapTracker = exports.FrequencyTracker = exports.getSnapshotPath = exports.isSnapshotValid = exports.deleteSnapshot = exports.loadSnapshot = exports.saveSnapshot = exports.parseTodoDependencies = exports.EventAggregator = exports.getRandomPhrase = exports.PHRASE_CATEGORIES = exports.ALL_PHRASES = exports.HIGHLIGHT_CSS = exports.clearHighlightCache = void 0;
|
|
9
|
+
exports.resolveCodexQuota = exports.readLatestCodexQuotaFromRollouts = exports.quotaFromCodexRateLimits = exports.fetchCodexQuotaFromApi = exports.getWorkspaceIdFromPath = exports.pruneQuotaHistory = exports.readQuotaHistoryDailyBuckets = exports.readQuotaHistoryRange = exports.appendQuotaHistorySample = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.QuotaPoller = exports.describeQuotaFailure = exports.withQuotaProjections = exports.projectQuotaWindow = exports.fetchQuota = exports.SEVEN_DAY_WINDOW_MS = exports.FIVE_HOUR_WINDOW_MS = exports.AutoSwitchController = exports.decideAutoSwitch = exports.DEFAULT_AUTO_SWITCH_CONFIG = exports.removeLauncher = exports.writeLauncher = exports.isShellHookInstalled = exports.uninstallShellHook = exports.installShellHook = exports.setTerminalActiveProfile = exports.removeCodexAccount = exports.switchToCodexAccount = exports.finalizeCodexAccount = exports.prepareCodexAccount = exports.getCodexExecutionEnv = exports.resolveSidekickCodexHome = exports.resolveActiveCodexAccount = exports.getActiveCodexAccount = exports.listCodexAccounts = exports.getSystemCodexHome = exports.getCodexMonitoringHomes = exports.getCodexProfileHome = exports.getCodexProfilesDir = exports.readClaudeProfileIdentity = exports.isClaudeProfileAuthenticated = exports.claudeKeychainService = exports.claudeKeychainSuffix = exports.getClaudeProfileHome = exports.getClaudeProfilesDir = exports.getActiveAccountStatus = exports.removeSavedAccountProfile = exports.replaceSavedAccountProfiles = exports.setActiveSavedAccount = void 0;
|
|
10
|
+
exports.sessionMessageSchema = exports.messageUsageSchema = exports.gatherAssetsForCwd = exports.codexSessions = exports.readCodexAssets = exports.claudeSessions = exports.readClaudeAssets = exports.extractCommands = exports.extractFilePaths = exports.extractUrls = exports.extractToolCalls = exports.extractToolCall = exports.extractTokenUsage = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.formatCost = exports.sortModelIds = exports.compareModelIds = exports.getModelDisplayInfo = exports.shortModelName = exports.mergeCostSources = exports.calculateCostWithProvenance = exports.calculateCostWithPricing = exports.calculateCost = exports.getModelInfo = exports.getModelPricing = exports.parseModelId = exports.DEFAULT_CONTEXT_WINDOW = exports.getModelContextWindowSize = exports.MultiProviderQuotaService = exports.resolveZaiQuota = exports.readZaiCredentials = exports.quotaStateFromZaiQuotaLimitPayload = exports.fetchZaiQuotaFromApi = exports.ZaiQuotaWatcher = exports.ZAI_TIER_BUDGETS = exports.ZAI_PROVIDER_IDS = exports.ZAI_PROMPT_INVOCATIONS = exports.turnTokenWeight = exports.rowsToZaiTurnsAndErrors = exports.resolveZaiTier = exports.parseZaiQuotaError = exports.makeUnavailableZaiQuotaState = exports.isZaiProviderId = exports.inferZaiQuotaState = exports.extractNextFlushTime = exports.accumulateZaiUsage = exports.CodexQuotaWatcher = exports.resolveCodexQuotaFromLocalSources = void 0;
|
|
11
|
+
exports.scopePeakHoursToSessionProvider = exports.isClaudeCodeSessionProvider = exports.fetchPeakHoursStatus = exports.createPeakHoursNotApplicableState = 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.quotaSourceSchema = exports.quotaProviderIdSchema = exports.quotaFailureKindSchema = exports.quotaStateSchema = exports.quotaWindowSchema = exports.extractSessionEvents = exports.permissionModeSchema = exports.sessionEventSchema = void 0;
|
|
12
12
|
var taskPersistence_1 = require("./types/taskPersistence");
|
|
13
13
|
Object.defineProperty(exports, "TASK_PERSISTENCE_SCHEMA_VERSION", { enumerable: true, get: function () { return taskPersistence_1.TASK_PERSISTENCE_SCHEMA_VERSION; } });
|
|
14
14
|
Object.defineProperty(exports, "normalizeTaskStatus", { enumerable: true, get: function () { return taskPersistence_1.normalizeTaskStatus; } });
|
|
@@ -220,6 +220,7 @@ Object.defineProperty(exports, "reconcileClaudeAuthState", { enumerable: true, g
|
|
|
220
220
|
Object.defineProperty(exports, "removeAccount", { enumerable: true, get: function () { return accounts_1.removeAccount; } });
|
|
221
221
|
Object.defineProperty(exports, "listAccounts", { enumerable: true, get: function () { return accounts_1.listAccounts; } });
|
|
222
222
|
Object.defineProperty(exports, "getActiveAccount", { enumerable: true, get: function () { return accounts_1.getActiveAccount; } });
|
|
223
|
+
Object.defineProperty(exports, "resolveActiveClaudeAccount", { enumerable: true, get: function () { return accounts_1.resolveActiveClaudeAccount; } });
|
|
223
224
|
Object.defineProperty(exports, "isMultiAccountEnabled", { enumerable: true, get: function () { return accounts_1.isMultiAccountEnabled; } });
|
|
224
225
|
var accountManager_1 = require("./accountManager");
|
|
225
226
|
Object.defineProperty(exports, "beginAccountLogin", { enumerable: true, get: function () { return accountManager_1.beginAccountLogin; } });
|
|
@@ -255,6 +256,7 @@ Object.defineProperty(exports, "getCodexMonitoringHomes", { enumerable: true, ge
|
|
|
255
256
|
Object.defineProperty(exports, "getSystemCodexHome", { enumerable: true, get: function () { return codexProfiles_1.getSystemCodexHome; } });
|
|
256
257
|
Object.defineProperty(exports, "listCodexAccounts", { enumerable: true, get: function () { return codexProfiles_1.listCodexAccounts; } });
|
|
257
258
|
Object.defineProperty(exports, "getActiveCodexAccount", { enumerable: true, get: function () { return codexProfiles_1.getActiveCodexAccount; } });
|
|
259
|
+
Object.defineProperty(exports, "resolveActiveCodexAccount", { enumerable: true, get: function () { return codexProfiles_1.resolveActiveCodexAccount; } });
|
|
258
260
|
Object.defineProperty(exports, "resolveSidekickCodexHome", { enumerable: true, get: function () { return codexProfiles_1.resolveSidekickCodexHome; } });
|
|
259
261
|
Object.defineProperty(exports, "getCodexExecutionEnv", { enumerable: true, get: function () { return codexProfiles_1.getCodexExecutionEnv; } });
|
|
260
262
|
Object.defineProperty(exports, "prepareCodexAccount", { enumerable: true, get: function () { return codexProfiles_1.prepareCodexAccount; } });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveActiveClaudeAccount } from './accounts';
|
|
2
2
|
import type { ClaudeMaxCredentials } from './credentials';
|
|
3
3
|
import type { PeakHoursState } from './peakHours';
|
|
4
4
|
import type { QuotaState } from './quota';
|
|
@@ -25,7 +25,7 @@ export interface MultiProviderQuotaServiceOptions {
|
|
|
25
25
|
codexWatcher?: CodexWatcherLike | null;
|
|
26
26
|
zaiWatcher?: ZaiWatcherLike | null;
|
|
27
27
|
readClaudeCredentials?: () => Promise<ClaudeMaxCredentials | null>;
|
|
28
|
-
readClaudeAccount?: typeof
|
|
28
|
+
readClaudeAccount?: typeof resolveActiveClaudeAccount;
|
|
29
29
|
fetchClaudeQuota?: (accessToken: string) => Promise<QuotaState>;
|
|
30
30
|
fetchPeakHours?: () => Promise<PeakHoursState>;
|
|
31
31
|
log?: Logger;
|
|
@@ -82,7 +82,7 @@ class MultiProviderQuotaService {
|
|
|
82
82
|
this.peakHoursCacheMaxAgeMs = options.peakHoursCacheMaxAgeMs ?? PEAK_HOURS_CACHE_MAX_AGE_MS;
|
|
83
83
|
this.includePeakHours = options.includePeakHours ?? true;
|
|
84
84
|
this.readClaudeCredentials = options.readClaudeCredentials ?? credentials_1.readClaudeMaxCredentials;
|
|
85
|
-
this.readClaudeAccount = options.readClaudeAccount ?? accounts_1.
|
|
85
|
+
this.readClaudeAccount = options.readClaudeAccount ?? accounts_1.resolveActiveClaudeAccount;
|
|
86
86
|
this.fetchClaudeQuota = options.fetchClaudeQuota ?? quota_1.fetchQuota;
|
|
87
87
|
this.fetchPeakHours = options.fetchPeakHours ?? peakHours_1.fetchPeakHoursStatus;
|
|
88
88
|
this.log = options.log;
|
|
@@ -353,7 +353,8 @@ class MultiProviderQuotaService {
|
|
|
353
353
|
this.timer = setTimeout(() => void this.poll(), delay);
|
|
354
354
|
}
|
|
355
355
|
withClaudeAccountDetails(state) {
|
|
356
|
-
const
|
|
356
|
+
const resolved = this.readClaudeAccount();
|
|
357
|
+
const accountEmail = resolved.email;
|
|
357
358
|
if (!accountEmail) {
|
|
358
359
|
const nextState = { ...state };
|
|
359
360
|
delete nextState.accountLabel;
|
|
@@ -362,7 +363,7 @@ class MultiProviderQuotaService {
|
|
|
362
363
|
}
|
|
363
364
|
return {
|
|
364
365
|
...state,
|
|
365
|
-
accountLabel: accountEmail,
|
|
366
|
+
accountLabel: resolved.label ?? accountEmail,
|
|
366
367
|
accountDetail: accountEmail,
|
|
367
368
|
};
|
|
368
369
|
}
|
package/package.json
CHANGED