sidekick-shared 0.27.5 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/README.md +93 -52
- package/dist/accountHealth.d.ts +14 -0
- package/dist/accountHealth.js +61 -14
- package/dist/accountLaunch.d.ts +6 -0
- package/dist/accountLaunch.js +61 -4
- package/dist/accountLease.d.ts +5 -0
- package/dist/accountLease.js +98 -0
- package/dist/accountManager.d.ts +7 -0
- package/dist/accountManager.js +226 -89
- package/dist/accountSync.d.ts +1 -5
- package/dist/accountSync.js +22 -6
- package/dist/accountSyncTypes.d.ts +9 -0
- package/dist/accounts.d.ts +75 -18
- package/dist/accounts.js +712 -189
- package/dist/browser.d.ts +13 -2
- package/dist/browser.js +30 -2
- package/dist/claudeCredentialDoctor.d.ts +50 -0
- package/dist/claudeCredentialDoctor.js +277 -0
- package/dist/claudeCredentialLedger.d.ts +15 -0
- package/dist/claudeCredentialLedger.js +130 -0
- package/dist/claudeCredentials.d.ts +20 -3
- package/dist/claudeCredentials.js +50 -3
- package/dist/claudeLiveGuard.d.ts +33 -0
- package/dist/claudeLiveGuard.js +46 -0
- package/dist/claudePaths.d.ts +11 -0
- package/dist/claudePaths.js +61 -0
- package/dist/claudeProfiles.d.ts +15 -8
- package/dist/claudeProfiles.js +30 -23
- package/dist/claudeRefreshLock.d.ts +15 -0
- package/dist/claudeRefreshLock.js +145 -0
- package/dist/codexAuth.d.ts +4 -0
- package/dist/codexAuth.js +18 -0
- package/dist/codexCredentialDoctor.d.ts +33 -0
- package/dist/codexCredentialDoctor.js +302 -0
- package/dist/codexCredentialStore.d.ts +29 -0
- package/dist/codexCredentialStore.js +213 -0
- package/dist/codexKeepAlive.d.ts +2 -0
- package/dist/codexKeepAlive.js +116 -0
- package/dist/codexPaths.d.ts +30 -2
- package/dist/codexPaths.js +118 -7
- package/dist/codexProfiles.d.ts +38 -35
- package/dist/codexProfiles.js +848 -715
- package/dist/credentialIO.d.ts +67 -7
- package/dist/credentialIO.js +211 -47
- package/dist/doctor.js +2 -2
- package/dist/ensureDefaultAccounts.js +1 -8
- package/dist/esm/accountChangeSignal.js +15 -0
- package/dist/esm/accountChanges.js +152 -0
- package/dist/esm/accountHealth.js +288 -0
- package/dist/esm/accountLaunch.js +145 -0
- package/dist/esm/accountLease.js +60 -0
- package/dist/esm/accountManager.js +606 -0
- package/dist/esm/accountRegistry.js +214 -0
- package/dist/esm/accountStatus.js +51 -0
- package/dist/esm/accountSwitch.js +74 -0
- package/dist/esm/accountSync.js +156 -0
- package/dist/esm/accountSyncTypes.js +4 -0
- package/dist/esm/accounts.js +1291 -0
- package/dist/esm/aggregation/EventAggregator.js +2034 -0
- package/dist/esm/aggregation/FrequencyTracker.js +69 -0
- package/dist/esm/aggregation/HeatmapTracker.js +89 -0
- package/dist/esm/aggregation/PatternExtractor.js +168 -0
- package/dist/esm/aggregation/costProvenance.js +31 -0
- package/dist/esm/aggregation/snapshot.js +161 -0
- package/dist/esm/aggregation/types.js +5 -0
- package/dist/esm/analytics/codeImpact.js +18 -0
- package/dist/esm/analytics/compactionLedger.js +37 -0
- package/dist/esm/analytics/qualityScore.js +112 -0
- package/dist/esm/autoSwitch.js +185 -0
- package/dist/esm/browser.js +34 -0
- package/dist/esm/claudeCredentialDoctor.js +239 -0
- package/dist/esm/claudeCredentialLedger.js +91 -0
- package/dist/esm/claudeCredentials.js +111 -0
- package/dist/esm/claudeLiveGuard.js +43 -0
- package/dist/esm/claudePaths.js +22 -0
- package/dist/esm/claudeProfiles.js +142 -0
- package/dist/esm/claudeRefreshLock.js +106 -0
- package/dist/esm/codexAuth.js +101 -0
- package/dist/esm/codexCredentialDoctor.js +265 -0
- package/dist/esm/codexCredentialStore.js +164 -0
- package/dist/esm/codexKeepAlive.js +112 -0
- package/dist/esm/codexPaths.js +172 -0
- package/dist/esm/codexProfiles.js +1251 -0
- package/dist/esm/codexQuota.js +564 -0
- package/dist/esm/codexQuotaWatcher.js +363 -0
- package/dist/esm/context/composer.js +71 -0
- package/dist/esm/context/sessionContext.js +546 -0
- package/dist/esm/credentialIO.js +283 -0
- package/dist/esm/credentials.js +49 -0
- package/dist/esm/doctor.js +305 -0
- package/dist/esm/ensureDefaultAccounts.js +62 -0
- package/dist/esm/errorHistory.js +56 -0
- package/dist/esm/extractors/errorTaxonomy.js +43 -0
- package/dist/esm/extractors/gatherAssets.js +32 -0
- package/dist/esm/extractors/sessionAssets.js +176 -0
- package/dist/esm/extractors/sources/claudeAssets.js +158 -0
- package/dist/esm/extractors/sources/codexAssets.js +234 -0
- package/dist/esm/extractors/tokenUsage.js +41 -0
- package/dist/esm/extractors/toolCall.js +142 -0
- package/dist/esm/failingTools.js +65 -0
- package/dist/esm/fileHead.js +27 -0
- package/dist/esm/formatters/eventHighlighter.js +332 -0
- package/dist/esm/formatters/noiseClassifier.js +209 -0
- package/dist/esm/formatters/sessionDump.js +328 -0
- package/dist/esm/formatters/toolSummary.js +226 -0
- package/dist/esm/formatting.js +82 -0
- package/dist/esm/handoffUrl.js +23 -0
- package/dist/esm/historicalStore.js +305 -0
- package/dist/esm/humanPrompt.js +88 -0
- package/dist/esm/index.js +213 -0
- package/dist/esm/keepAlive.js +189 -0
- package/dist/esm/liveCredentialGuard.js +33 -0
- package/dist/esm/modelAliases.js +51 -0
- package/dist/esm/modelCatalog.js +139 -0
- package/dist/esm/modelContext.js +280 -0
- package/dist/esm/modelInfo.js +832 -0
- package/dist/esm/multiProviderQuotaService.js +450 -0
- package/dist/esm/node.js +46 -0
- package/dist/esm/observedContextWindows.js +165 -0
- package/dist/esm/observedSessionCollector.js +939 -0
- package/dist/esm/parsers/changelogParser.js +71 -0
- package/dist/esm/parsers/codexHistory.js +89 -0
- package/dist/esm/parsers/codexParser.js +906 -0
- package/dist/esm/parsers/debugLogParser.js +126 -0
- package/dist/esm/parsers/jsonl.js +66 -0
- package/dist/esm/parsers/mcpToolName.js +28 -0
- package/dist/esm/parsers/openCodeParser.js +625 -0
- package/dist/esm/parsers/planExtractor.js +335 -0
- package/dist/esm/parsers/sessionActivityDetector.js +246 -0
- package/dist/esm/parsers/sessionPathResolver.js +713 -0
- package/dist/esm/parsers/subagentScanner.js +360 -0
- package/dist/esm/parsers/subagentStatsCache.js +45 -0
- package/dist/esm/parsers/subagentTraceParser.js +325 -0
- package/dist/esm/paths.js +134 -0
- package/dist/esm/peakHours.js +194 -0
- package/dist/esm/phrases.js +1330 -0
- package/dist/esm/pricingCatalog.js +247 -0
- package/dist/esm/processDetection.js +200 -0
- package/dist/esm/projectMigration.js +59 -0
- package/dist/esm/promptHistory.js +1221 -0
- package/dist/esm/providerFailure.js +362 -0
- package/dist/esm/providerIds.js +6 -0
- package/dist/esm/providerQuota.js +1 -0
- package/dist/esm/providerServiceStatus.js +145 -0
- package/dist/esm/providerServiceStatusTypes.js +1 -0
- package/dist/esm/providerStatus.js +117 -0
- package/dist/esm/providers/claudeCode.js +575 -0
- package/dist/esm/providers/claudeListing.js +121 -0
- package/dist/esm/providers/codex.js +1034 -0
- package/dist/esm/providers/codexDatabase.js +297 -0
- package/dist/esm/providers/codexRollouts.js +215 -0
- package/dist/esm/providers/detect.js +185 -0
- package/dist/esm/providers/diagnostics.js +83 -0
- package/dist/esm/providers/directoryListingCache.js +206 -0
- package/dist/esm/providers/factory.js +54 -0
- package/dist/esm/providers/openCode.js +2008 -0
- package/dist/esm/providers/openCodeDatabase.js +419 -0
- package/dist/esm/providers/rolloutWalker.js +252 -0
- package/dist/esm/providers/types.js +12 -0
- package/dist/esm/quota.js +182 -0
- package/dist/esm/quotaHistory.js +364 -0
- package/dist/esm/quotaPoller.js +230 -0
- package/dist/esm/quotaPresentation.js +97 -0
- package/dist/esm/quotaResolver.js +231 -0
- package/dist/esm/quotaSnapshots.js +130 -0
- package/dist/esm/quotaThresholds.js +85 -0
- package/dist/esm/readers/decisions.js +24 -0
- package/dist/esm/readers/handoff.js +20 -0
- package/dist/esm/readers/helpers.js +27 -0
- package/dist/esm/readers/history.js +9 -0
- package/dist/esm/readers/notes.js +48 -0
- package/dist/esm/readers/plans.js +225 -0
- package/dist/esm/readers/tasks.js +19 -0
- package/dist/esm/report/htmlHelpers.js +280 -0
- package/dist/esm/report/htmlReportGenerator.js +704 -0
- package/dist/esm/report/index.js +7 -0
- package/dist/esm/report/logo.js +2 -0
- package/dist/esm/report/openBrowser.js +19 -0
- package/dist/esm/report/sessionReportInputs.js +33 -0
- package/dist/esm/report/transcriptParser.js +83 -0
- package/dist/esm/report/types.js +4 -0
- package/dist/esm/schemas/accountManager.js +204 -0
- package/dist/esm/schemas/accountStatus.js +25 -0
- package/dist/esm/schemas/assistantTurn.js +74 -0
- package/dist/esm/schemas/index.js +25 -0
- package/dist/esm/schemas/observedSessionV1.js +77 -0
- package/dist/esm/schemas/providerFailure.js +37 -0
- package/dist/esm/schemas/quota.js +132 -0
- package/dist/esm/schemas/quotaHistory.js +40 -0
- package/dist/esm/schemas/sessionEvent.js +216 -0
- package/dist/esm/schemas/stateFile.js +75 -0
- package/dist/esm/schemas/tokenEstimation.js +7 -0
- package/dist/esm/schemas/transcript.js +86 -0
- package/dist/esm/schemas/usageNormalization.js +38 -0
- package/dist/esm/search/advancedFilter.js +197 -0
- package/dist/esm/search/sessionSearch.js +66 -0
- package/dist/esm/sessionFingerprint.js +40 -0
- package/dist/esm/sessionMonitor.js +198 -0
- package/dist/esm/sessionPreviews.js +522 -0
- package/dist/esm/sessionPromptHistory.js +254 -0
- package/dist/esm/sessionPromptSignals.js +364 -0
- package/dist/esm/sessionStats.js +160 -0
- package/dist/esm/sessionTokenTotals.js +98 -0
- package/dist/esm/sessionTranscripts.js +49 -0
- package/dist/esm/stateFile.js +119 -0
- package/dist/esm/statusline/BurnRateCalculator.js +40 -0
- package/dist/esm/statusline/claudeStatuslinePayload.js +148 -0
- package/dist/esm/statusline/formatter.js +122 -0
- package/dist/esm/statusline/index.js +8 -0
- package/dist/esm/terminalSync.js +95 -0
- package/dist/esm/testing/credentialGuard.js +197 -0
- package/dist/esm/testing/index.js +12 -0
- package/dist/esm/testing/sessionLogFixtures.js +128 -0
- package/dist/esm/tokenEstimation.js +67 -0
- package/dist/esm/tokenSummary.js +113 -0
- package/dist/esm/toolCategory.js +82 -0
- package/dist/esm/transcript.js +257 -0
- package/dist/esm/turns/assistantTurn.js +373 -0
- package/dist/esm/types/codex.js +23 -0
- package/dist/esm/types/decisionLog.js +5 -0
- package/dist/esm/types/historicalData.js +47 -0
- package/dist/esm/types/knowledgeNote.js +15 -0
- package/dist/esm/types/observedSessionV1.js +257 -0
- package/dist/esm/types/opencode.js +12 -0
- package/dist/esm/types/plan.js +7 -0
- package/dist/esm/types/sessionEvent.js +10 -0
- package/dist/esm/types/taskPersistence.js +12 -0
- package/dist/esm/usage/billingBlocks.js +148 -0
- package/dist/esm/usage/claudeUsageDedupe.js +189 -0
- package/dist/esm/usage/importSessionHistory.js +84 -0
- package/dist/esm/usage/subagentUsage.js +18 -0
- package/dist/esm/usage/usageEvents.js +402 -0
- package/dist/esm/usage/usageReports.js +202 -0
- package/dist/esm/usageNormalization.js +95 -0
- package/dist/esm/watchers/eventBridge.js +219 -0
- package/dist/esm/watchers/factory.js +63 -0
- package/dist/esm/watchers/jsonlTail.js +289 -0
- package/dist/esm/watchers/jsonlWatcher.js +435 -0
- package/dist/esm/watchers/providerReaderWatcher.js +118 -0
- package/dist/esm/watchers/sqliteWatcher.js +285 -0
- package/dist/esm/watchers/types.js +4 -0
- package/dist/esm/workspaceRoots.js +56 -0
- package/dist/esm/writers/atomic.js +375 -0
- package/dist/esm/writers/decisions.js +51 -0
- package/dist/esm/writers/notes.js +46 -0
- package/dist/esm/writers/tasks.js +63 -0
- package/dist/esm/zaiQuota.js +323 -0
- package/dist/esm/zaiQuotaApi.js +271 -0
- package/dist/esm/zaiQuotaWatcher.js +265 -0
- package/dist/fileHead.d.ts +22 -0
- package/dist/fileHead.js +33 -0
- package/dist/index.d.ts +30 -11
- package/dist/index.js +72 -15
- package/dist/keepAlive.d.ts +2 -1
- package/dist/keepAlive.js +116 -29
- package/dist/liveCredentialGuard.d.ts +28 -0
- package/dist/liveCredentialGuard.js +36 -0
- package/dist/node.d.ts +13 -1
- package/dist/node.js +43 -2
- package/dist/parsers/codexHistory.js +2 -2
- package/dist/parsers/codexParser.d.ts +12 -0
- package/dist/parsers/codexParser.js +34 -12
- package/dist/parsers/debugLogParser.js +2 -2
- package/dist/parsers/sessionPathResolver.js +5 -4
- package/dist/processDetection.d.ts +10 -3
- package/dist/processDetection.js +44 -11
- package/dist/promptHistory.d.ts +32 -0
- package/dist/promptHistory.js +115 -59
- package/dist/providerFailure.d.ts +12 -6
- package/dist/providerFailure.js +45 -0
- package/dist/providers/claudeCode.js +7 -99
- package/dist/providers/claudeListing.d.ts +22 -0
- package/dist/providers/claudeListing.js +158 -0
- package/dist/providers/codex.d.ts +3 -1
- package/dist/providers/codex.js +26 -227
- package/dist/providers/codexRollouts.d.ts +44 -0
- package/dist/providers/codexRollouts.js +261 -0
- package/dist/providers/detect.js +4 -4
- package/dist/readers/plans.js +3 -3
- package/dist/schemas/accountManager.d.ts +22 -0
- package/dist/schemas/accountManager.js +4 -0
- package/dist/schemas/assistantTurn.d.ts +2 -2
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.js +7 -2
- package/dist/schemas/providerFailure.d.ts +154 -0
- package/dist/schemas/providerFailure.js +40 -0
- package/dist/sessionPromptHistory.d.ts +12 -7
- package/dist/sessionPromptHistory.js +15 -3
- package/dist/sessionPromptSignals.d.ts +9 -0
- package/dist/sessionPromptSignals.js +13 -0
- package/dist/terminalSync.d.ts +12 -2
- package/dist/terminalSync.js +27 -2
- package/dist/testing/credentialGuard.d.ts +23 -0
- package/dist/testing/credentialGuard.js +233 -0
- package/dist/testing/index.d.ts +14 -0
- package/dist/testing/index.js +22 -0
- package/dist/testing/sessionLogFixtures.d.ts +28 -0
- package/dist/testing/sessionLogFixtures.js +169 -0
- package/dist/tokenEstimation.d.ts +2 -0
- package/dist/tokenEstimation.js +21 -11
- package/dist/toolCategory.d.ts +18 -0
- package/dist/toolCategory.js +86 -0
- package/dist/types/codex.d.ts +4 -0
- package/dist/usage/usageEvents.d.ts +16 -0
- package/dist/usage/usageEvents.js +53 -9
- package/dist/watchers/jsonlTail.d.ts +26 -1
- package/dist/watchers/jsonlTail.js +136 -28
- package/dist/watchers/jsonlWatcher.js +7 -0
- package/dist/watchers/providerReaderWatcher.js +1 -0
- package/dist/watchers/types.d.ts +6 -0
- package/dist/workspaceRoots.d.ts +23 -0
- package/dist/workspaceRoots.js +93 -0
- package/package.json +22 -2
package/dist/accountHealth.js
CHANGED
|
@@ -39,6 +39,7 @@ exports.claudeHealthSidecarFromBlob = claudeHealthSidecarFromBlob;
|
|
|
39
39
|
exports.writeClaudeHealthSidecar = writeClaudeHealthSidecar;
|
|
40
40
|
exports.codexHealthSidecarFromAuth = codexHealthSidecarFromAuth;
|
|
41
41
|
exports.writeCodexHealthSidecar = writeCodexHealthSidecar;
|
|
42
|
+
exports.readEffectiveClaudeCredential = readEffectiveClaudeCredential;
|
|
42
43
|
exports.getAccountHealth = getAccountHealth;
|
|
43
44
|
exports.listAccountsWithHealth = listAccountsWithHealth;
|
|
44
45
|
exports.describeClaudeCredential = describeClaudeCredential;
|
|
@@ -55,6 +56,7 @@ const credentialIO_1 = require("./credentialIO");
|
|
|
55
56
|
const codexAuth_1 = require("./codexAuth");
|
|
56
57
|
const codexPaths_1 = require("./codexPaths");
|
|
57
58
|
const accountRegistry_1 = require("./accountRegistry");
|
|
59
|
+
const codexCredentialStore_1 = require("./codexCredentialStore");
|
|
58
60
|
const atomic_1 = require("./writers/atomic");
|
|
59
61
|
/** Refresh tokens that expire within this window count as `expiring`. */
|
|
60
62
|
const REFRESH_EXPIRY_WARNING_MS = 3 * 24 * 60 * 60 * 1000;
|
|
@@ -93,6 +95,7 @@ function claudeHealthSidecarFromBlob(blob, source, now = Date.now()) {
|
|
|
93
95
|
refreshExpiryEstimated: refresh?.estimated,
|
|
94
96
|
hasRefreshToken: Boolean(credentials.refreshToken),
|
|
95
97
|
authMode: 'oauth',
|
|
98
|
+
refreshFp: (0, claudeCredentials_1.claudeRefreshFingerprint)(credentials) ?? undefined,
|
|
96
99
|
source,
|
|
97
100
|
};
|
|
98
101
|
}
|
|
@@ -114,7 +117,8 @@ function codexHealthSidecarFromAuth(authRaw, source, now = Date.now(), fallbackP
|
|
|
114
117
|
capturedAt: now,
|
|
115
118
|
accessExpiresAt: (0, codexAuth_1.readAccessTokenExpiry)(authRaw) ?? undefined,
|
|
116
119
|
lastRefreshAt,
|
|
117
|
-
hasRefreshToken:
|
|
120
|
+
hasRefreshToken: (0, codexAuth_1.codexRefreshFingerprint)(authRaw) !== null,
|
|
121
|
+
refreshFp: (0, codexAuth_1.codexRefreshFingerprint)(authRaw) ?? undefined,
|
|
118
122
|
authMode: identity.authMode,
|
|
119
123
|
source,
|
|
120
124
|
};
|
|
@@ -185,15 +189,54 @@ function isLiveCodexAccount(profile) {
|
|
|
185
189
|
workspaceId: profile.metadata?.workspaceId,
|
|
186
190
|
});
|
|
187
191
|
}
|
|
188
|
-
function
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
function readClaudeBackupBlob(accountId) {
|
|
193
|
+
try {
|
|
194
|
+
return JSON.parse(fs.readFileSync((0, claudeProfiles_1.getClaudeCredentialBackupPath)(accountId), 'utf8'));
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
191
199
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
/**
|
|
201
|
+
* The credential a Claude profile would use right now: the live store for the
|
|
202
|
+
* live account (its profile home is empty by design), otherwise the fresher of
|
|
203
|
+
* the profile-home store and Sidekick's backup.
|
|
204
|
+
*/
|
|
205
|
+
function readEffectiveClaudeCredential(accountId) {
|
|
206
|
+
if (isLiveClaudeAccount(accountId))
|
|
207
|
+
return (0, credentialIO_1.readActiveCredentials)();
|
|
208
|
+
const store = (0, credentialIO_1.readClaudeCredentialStore)((0, claudeProfiles_1.getClaudeProfileHome)(accountId));
|
|
209
|
+
const fromStore = store.status === 'ok' ? store.blob : null;
|
|
210
|
+
const backup = readClaudeBackupBlob(accountId);
|
|
211
|
+
const storeFreshness = (0, claudeCredentials_1.claudeCredentialFreshness)((0, claudeCredentials_1.parseClaudeCredentialBlob)(fromStore));
|
|
212
|
+
const backupFreshness = (0, claudeCredentials_1.claudeCredentialFreshness)((0, claudeCredentials_1.parseClaudeCredentialBlob)(backup));
|
|
213
|
+
if ((0, claudeCredentials_1.parseClaudeCredentialBlob)(backup) && backupFreshness > storeFreshness)
|
|
214
|
+
return backup;
|
|
215
|
+
return (0, claudeCredentials_1.parseClaudeCredentialBlob)(fromStore) ? fromStore : null;
|
|
216
|
+
}
|
|
217
|
+
function probeClaudeStore(accountId, now, persist = true) {
|
|
218
|
+
const blob = readEffectiveClaudeCredential(accountId);
|
|
219
|
+
if (!blob)
|
|
220
|
+
return null;
|
|
221
|
+
// A probe reads; it must not rewrite provenance (keep-alive relies on it).
|
|
222
|
+
const source = readHealthSidecar('claude-code', accountId)?.source ??
|
|
223
|
+
(isLiveClaudeAccount(accountId) ? 'live-sync' : 'migration');
|
|
224
|
+
return persist
|
|
225
|
+
? writeClaudeHealthSidecar(accountId, blob, source, now)
|
|
226
|
+
: claudeHealthSidecarFromBlob(blob, source, now);
|
|
227
|
+
}
|
|
228
|
+
function probeCodexStore(accountId, now, persist = true) {
|
|
229
|
+
const profile = (0, accountRegistry_1.listSavedAccountProfiles)('codex').find((p) => p.id === accountId);
|
|
230
|
+
const live = profile !== undefined && isLiveCodexAccount(profile);
|
|
231
|
+
const home = (0, codexCredentialStore_1.readCodexCredentialStore)(live ? (0, codexPaths_1.getSystemCodexHome)() : (0, codexPaths_1.getCodexProfileHome)(accountId));
|
|
232
|
+
const backup = live ? null : (0, codexCredentialStore_1.readCodexBackup)(accountId);
|
|
233
|
+
let raw = home.status === 'ok' ? home.snapshot.authRaw : null;
|
|
234
|
+
if (backup?.status === 'ok' &&
|
|
235
|
+
(!raw || (0, codexAuth_1.compareCodexAuthFreshness)(backup.snapshot.authRaw, raw) > 0))
|
|
236
|
+
raw = backup.snapshot.authRaw;
|
|
237
|
+
const source = readHealthSidecar('codex', accountId)?.source ?? (live ? 'live-sync' : 'migration');
|
|
238
|
+
const sidecar = codexHealthSidecarFromAuth(raw, source, now);
|
|
239
|
+
if (sidecar && persist)
|
|
197
240
|
writeSidecar('codex', accountId, sidecar);
|
|
198
241
|
return sidecar;
|
|
199
242
|
}
|
|
@@ -201,12 +244,14 @@ function hasStoredClaudeCredential(accountId) {
|
|
|
201
244
|
const home = (0, claudeProfiles_1.getClaudeProfileHome)(accountId);
|
|
202
245
|
return (fs.existsSync(path.join(home, '.credentials.json')) ||
|
|
203
246
|
fs.existsSync(path.join((0, claudeProfiles_1.getClaudeProfileDir)(accountId), 'health.json')) ||
|
|
204
|
-
fs.existsSync(
|
|
247
|
+
fs.existsSync((0, claudeProfiles_1.getClaudeCredentialBackupPath)(accountId)) ||
|
|
205
248
|
(process.platform === 'darwin' && fs.existsSync(path.join(home, '.claude.json'))));
|
|
206
249
|
}
|
|
207
250
|
function hasStoredCodexCredential(accountId) {
|
|
208
251
|
const home = (0, codexPaths_1.getCodexProfileHome)(accountId);
|
|
209
|
-
return (fs.existsSync(
|
|
252
|
+
return (fs.existsSync((0, codexPaths_1.getCodexBackupPath)(accountId)) ||
|
|
253
|
+
fs.existsSync((0, codexPaths_1.getCodexBackupPath)(accountId, true)) ||
|
|
254
|
+
fs.existsSync(path.join(home, 'auth.json')) ||
|
|
210
255
|
fs.existsSync(path.join(home, '.credentials.json')));
|
|
211
256
|
}
|
|
212
257
|
/**
|
|
@@ -224,17 +269,19 @@ function getAccountHealth(provider, accountId, options = {}) {
|
|
|
224
269
|
let sidecar = null;
|
|
225
270
|
if (probe === 'store') {
|
|
226
271
|
sidecar =
|
|
227
|
-
provider === 'codex'
|
|
272
|
+
provider === 'codex'
|
|
273
|
+
? probeCodexStore(accountId, now, options.persist)
|
|
274
|
+
: probeClaudeStore(accountId, now, options.persist);
|
|
228
275
|
}
|
|
229
276
|
sidecar ??= readHealthSidecar(provider, accountId);
|
|
230
277
|
if (!sidecar && provider === 'codex') {
|
|
231
278
|
// Codex sidecars are cheap to derive from the plaintext file.
|
|
232
|
-
sidecar = probeCodexStore(accountId, now);
|
|
279
|
+
sidecar = probeCodexStore(accountId, now, options.persist);
|
|
233
280
|
}
|
|
234
281
|
if (!sidecar && probe === 'auto' && hasStoredClaudeCredential(accountId)) {
|
|
235
282
|
// First look at a profile that predates the health model: read its store
|
|
236
283
|
// once and record the sidecar so later reads are cache hits.
|
|
237
|
-
sidecar = probeClaudeStore(accountId, now);
|
|
284
|
+
sidecar = probeClaudeStore(accountId, now, options.persist);
|
|
238
285
|
}
|
|
239
286
|
const base = { providerId: provider, accountId, checkedAt: now, isLive };
|
|
240
287
|
if (!sidecar) {
|
package/dist/accountLaunch.d.ts
CHANGED
|
@@ -26,5 +26,11 @@ export interface AccountLaunchOptions {
|
|
|
26
26
|
materialize?: boolean;
|
|
27
27
|
/** Launch even when the stored credential is reported expired. */
|
|
28
28
|
force?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Claude: when the profile home has no credential but its backup does,
|
|
31
|
+
* restore it there first (default true). Keep-alive passes false: it never
|
|
32
|
+
* restores backups.
|
|
33
|
+
*/
|
|
34
|
+
restoreBackup?: boolean;
|
|
29
35
|
}
|
|
30
36
|
export declare function getAccountLaunchEnv(provider: AccountProviderId, accountId: string, options?: AccountLaunchOptions): AccountLaunchEnv;
|
package/dist/accountLaunch.js
CHANGED
|
@@ -44,6 +44,9 @@ const path = __importStar(require("path"));
|
|
|
44
44
|
const accountRegistry_1 = require("./accountRegistry");
|
|
45
45
|
const accountHealth_1 = require("./accountHealth");
|
|
46
46
|
const claudeProfiles_1 = require("./claudeProfiles");
|
|
47
|
+
const accounts_1 = require("./accounts");
|
|
48
|
+
const codexCredentialStore_1 = require("./codexCredentialStore");
|
|
49
|
+
const codexProfiles_1 = require("./codexProfiles");
|
|
47
50
|
const codexPaths_1 = require("./codexPaths");
|
|
48
51
|
const atomic_1 = require("./writers/atomic");
|
|
49
52
|
function materializeClaudeHome(home) {
|
|
@@ -70,10 +73,11 @@ function materializeClaudeHome(home) {
|
|
|
70
73
|
function materializeCodexHome(home) {
|
|
71
74
|
fs.mkdirSync(home, { recursive: true, mode: 0o700 });
|
|
72
75
|
const configTarget = path.join(home, 'config.toml');
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
const current = (0, codexPaths_1.readFileOrNull)(configTarget);
|
|
77
|
+
const source = current ?? (0, codexPaths_1.readFileOrNull)(path.join((0, codexPaths_1.getSystemCodexHome)(), 'config.toml')) ?? '';
|
|
78
|
+
const fileMode = (0, codexPaths_1.forceFileCredentialStore)(source);
|
|
79
|
+
if (fileMode !== current)
|
|
80
|
+
(0, atomic_1.atomicWriteFileSync)(configTarget, fileMode);
|
|
77
81
|
}
|
|
78
82
|
function getAccountLaunchEnv(provider, accountId, options = {}) {
|
|
79
83
|
const profile = (0, accountRegistry_1.listSavedAccountProfiles)(provider).find((p) => p.id === accountId);
|
|
@@ -98,6 +102,40 @@ function getAccountLaunchEnv(provider, accountId, options = {}) {
|
|
|
98
102
|
if (!profile) {
|
|
99
103
|
return { ...base, error: `${provider} account ${accountId} not found.` };
|
|
100
104
|
}
|
|
105
|
+
if (provider === 'codex' && (0, codexCredentialStore_1.isSidekickCodexHome)((0, codexPaths_1.getSystemCodexHome)())) {
|
|
106
|
+
return {
|
|
107
|
+
...base,
|
|
108
|
+
error: 'Unset CODEX_HOME before managing accounts; it names a Sidekick-owned home.',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (provider === 'codex' && !['file', 'unknown'].includes((0, codexPaths_1.getCodexCredentialStoreMode)())) {
|
|
112
|
+
return { ...base, error: 'Codex account launches require readable file-mode credentials.' };
|
|
113
|
+
}
|
|
114
|
+
if (provider === 'codex' && (0, codexProfiles_1.isLiveCodexProfile)(profile)) {
|
|
115
|
+
const liveHome = (0, codexPaths_1.getSystemCodexHome)();
|
|
116
|
+
return {
|
|
117
|
+
...base,
|
|
118
|
+
home: liveHome,
|
|
119
|
+
env: { CODEX_HOME: liveHome },
|
|
120
|
+
warnings: ['This account is the live login, so the session uses the normal Codex home.'],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (provider === 'claude-code' && health.isLive) {
|
|
124
|
+
// The live account's only CLI-usable copy is the live store; a session in
|
|
125
|
+
// its profile home would be a second copy racing it over the refresh
|
|
126
|
+
// token. Point the session at the live home instead.
|
|
127
|
+
const liveHome = (0, claudeProfiles_1.getLiveClaudeHome)();
|
|
128
|
+
const customHome = !(0, claudeProfiles_1.isDefaultClaudeHome)();
|
|
129
|
+
return {
|
|
130
|
+
...base,
|
|
131
|
+
home: liveHome,
|
|
132
|
+
env: customHome ? { CLAUDE_CONFIG_DIR: liveHome } : {},
|
|
133
|
+
envUnset: customHome
|
|
134
|
+
? [claudeProfiles_1.CLAUDE_SECURESTORAGE_CONFIG_DIR_ENV]
|
|
135
|
+
: ['CLAUDE_CONFIG_DIR', claudeProfiles_1.CLAUDE_SECURESTORAGE_CONFIG_DIR_ENV],
|
|
136
|
+
warnings: ['This account is the live login, so the session uses the normal Claude home.'],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
101
139
|
if ((health.state === 'expired' || health.state === 'missing') && !options.force) {
|
|
102
140
|
return {
|
|
103
141
|
...base,
|
|
@@ -109,6 +147,25 @@ function getAccountLaunchEnv(provider, accountId, options = {}) {
|
|
|
109
147
|
}
|
|
110
148
|
if (health.state === 'expiring' && health.reason)
|
|
111
149
|
warnings.push(health.reason);
|
|
150
|
+
if (provider === 'claude-code' && options.restoreBackup !== false) {
|
|
151
|
+
if ((0, accounts_1.restoreClaudeProfileFromBackup)(accountId) === 'restored') {
|
|
152
|
+
warnings.push("Restored this account's saved login into its profile home. If a session elsewhere still uses this login, close it first: two copies of one login invalidate each other.");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (provider === 'codex') {
|
|
156
|
+
const restored = (0, codexProfiles_1.restoreCodexProfileFromBackup)(accountId, {
|
|
157
|
+
restore: options.restoreBackup !== false,
|
|
158
|
+
});
|
|
159
|
+
if (restored === 'none')
|
|
160
|
+
return { ...base, error: 'No safe inactive Codex credential is available; sign in again.' };
|
|
161
|
+
if (restored === 'live')
|
|
162
|
+
return { ...base, home: (0, codexPaths_1.getSystemCodexHome)(), env: { CODEX_HOME: (0, codexPaths_1.getSystemCodexHome)() } };
|
|
163
|
+
}
|
|
164
|
+
if (provider === 'codex' &&
|
|
165
|
+
options.materialize === false &&
|
|
166
|
+
!['file', 'unknown'].includes((0, codexPaths_1.getCodexCredentialStoreMode)(home))) {
|
|
167
|
+
return { ...base, error: 'The isolated Codex home must use file credential storage.' };
|
|
168
|
+
}
|
|
112
169
|
if (options.materialize !== false) {
|
|
113
170
|
try {
|
|
114
171
|
if (provider === 'codex')
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AccountProviderId } from './accountRegistry';
|
|
2
|
+
export declare function isAccountLeaseHeld(provider: AccountProviderId, accountId: string, now?: number): boolean;
|
|
3
|
+
/** Take the lease; the caller holds the provider's swap lock. False when held elsewhere. */
|
|
4
|
+
export declare function acquireAccountLease(provider: AccountProviderId, accountId: string, durationMs: number, now?: number): boolean;
|
|
5
|
+
export declare function releaseAccountLease(provider: AccountProviderId, accountId: string): void;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.isAccountLeaseHeld = isAccountLeaseHeld;
|
|
37
|
+
exports.acquireAccountLease = acquireAccountLease;
|
|
38
|
+
exports.releaseAccountLease = releaseAccountLease;
|
|
39
|
+
/**
|
|
40
|
+
* Keep-alive leases: while keep-alive runs a provider CLI inside a profile
|
|
41
|
+
* home, that home's credential may be mid-refresh. A switch to that account
|
|
42
|
+
* would copy the pre-refresh token into the live store just as the CLI kills
|
|
43
|
+
* it, so switches refuse a leased target. Leases are acquired under the
|
|
44
|
+
* provider's swap lock (the same lock a switch holds), expire on their own,
|
|
45
|
+
* and are ignored once their process is gone.
|
|
46
|
+
*/
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const claudeProfiles_1 = require("./claudeProfiles");
|
|
50
|
+
const codexPaths_1 = require("./codexPaths");
|
|
51
|
+
const atomic_1 = require("./writers/atomic");
|
|
52
|
+
function leasePath(provider, accountId) {
|
|
53
|
+
const dir = provider === 'codex' ? (0, codexPaths_1.getCodexProfileDir)(accountId) : (0, claudeProfiles_1.getClaudeProfileDir)(accountId);
|
|
54
|
+
return path.join(dir, 'keepalive.lease');
|
|
55
|
+
}
|
|
56
|
+
function processAlive(pid) {
|
|
57
|
+
if (pid === process.pid)
|
|
58
|
+
return true;
|
|
59
|
+
try {
|
|
60
|
+
process.kill(pid, 0);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
return error.code === 'EPERM';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function isAccountLeaseHeld(provider, accountId, now = Date.now()) {
|
|
68
|
+
try {
|
|
69
|
+
const lease = JSON.parse(fs.readFileSync(leasePath(provider, accountId), 'utf8'));
|
|
70
|
+
return (typeof lease.pid === 'number' &&
|
|
71
|
+
typeof lease.expiresAt === 'number' &&
|
|
72
|
+
lease.expiresAt > now &&
|
|
73
|
+
processAlive(lease.pid));
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Take the lease; the caller holds the provider's swap lock. False when held elsewhere. */
|
|
80
|
+
function acquireAccountLease(provider, accountId, durationMs, now = Date.now()) {
|
|
81
|
+
if (isAccountLeaseHeld(provider, accountId, now))
|
|
82
|
+
return false;
|
|
83
|
+
const target = leasePath(provider, accountId);
|
|
84
|
+
fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 });
|
|
85
|
+
(0, atomic_1.atomicWriteJsonSync)(target, {
|
|
86
|
+
pid: process.pid,
|
|
87
|
+
expiresAt: now + durationMs,
|
|
88
|
+
});
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
function releaseAccountLease(provider, accountId) {
|
|
92
|
+
try {
|
|
93
|
+
fs.rmSync(leasePath(provider, accountId), { force: true });
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* expires on its own */
|
|
97
|
+
}
|
|
98
|
+
}
|
package/dist/accountManager.d.ts
CHANGED
|
@@ -73,6 +73,13 @@ export declare function getAccountLoginStatusAsync(provider: AccountProviderId,
|
|
|
73
73
|
export declare function finalizeAccountLogin(provider: AccountProviderId, loginId: string, opts?: FinalizeAccountLoginOptions): AccountManagerResult;
|
|
74
74
|
/** {@link finalizeAccountLogin} without blocking the event loop on CLI probes. */
|
|
75
75
|
export declare function finalizeAccountLoginAsync(provider: AccountProviderId, loginId: string, opts?: FinalizeAccountLoginOptions): Promise<AccountManagerResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Abandon a login started with {@link beginAccountLogin} (cancelled, timed
|
|
78
|
+
* out, or failed): removes the temporary home and, for Claude, its Keychain
|
|
79
|
+
* item. Refuses ids that belong to a saved profile. Returns true when
|
|
80
|
+
* something was discarded.
|
|
81
|
+
*/
|
|
82
|
+
export declare function discardAccountLogin(provider: AccountProviderId, loginId: string): boolean;
|
|
76
83
|
export declare function spawnAccountLogin(provider: AccountProviderId, label: string, opts?: SpawnAccountLoginOptions): Promise<AccountManagerResult>;
|
|
77
84
|
export declare function switchAccount(provider: AccountProviderId, id: string, options?: SwitchAccountOptions): SwitchAccountResult;
|
|
78
85
|
/**
|