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/accountManager.js
CHANGED
|
@@ -39,6 +39,7 @@ exports.getAccountLoginStatus = getAccountLoginStatus;
|
|
|
39
39
|
exports.getAccountLoginStatusAsync = getAccountLoginStatusAsync;
|
|
40
40
|
exports.finalizeAccountLogin = finalizeAccountLogin;
|
|
41
41
|
exports.finalizeAccountLoginAsync = finalizeAccountLoginAsync;
|
|
42
|
+
exports.discardAccountLogin = discardAccountLogin;
|
|
42
43
|
exports.spawnAccountLogin = spawnAccountLogin;
|
|
43
44
|
exports.switchAccount = switchAccount;
|
|
44
45
|
exports.switchAccountAsync = switchAccountAsync;
|
|
@@ -54,7 +55,9 @@ const atomic_1 = require("./writers/atomic");
|
|
|
54
55
|
const accounts_1 = require("./accounts");
|
|
55
56
|
const claudeProfiles_1 = require("./claudeProfiles");
|
|
56
57
|
const credentialIO_1 = require("./credentialIO");
|
|
58
|
+
const claudeCredentialLedger_1 = require("./claudeCredentialLedger");
|
|
57
59
|
const codexProfiles_1 = require("./codexProfiles");
|
|
60
|
+
const codexPaths_1 = require("./codexPaths");
|
|
58
61
|
const accountSwitch_1 = require("./accountSwitch");
|
|
59
62
|
function getPendingClaudeProfilePath(loginId) {
|
|
60
63
|
return path.join((0, claudeProfiles_1.getClaudeProfileDir)(loginId), 'profile.json');
|
|
@@ -109,7 +112,16 @@ function copyClaudeProfileToCanonicalHome(sourceHome, accountUuid, credentials,
|
|
|
109
112
|
fs.mkdirSync(canonicalHome, { recursive: true, mode: 0o700 });
|
|
110
113
|
if (path.resolve(sourceHome) !== path.resolve(canonicalHome)) {
|
|
111
114
|
try {
|
|
112
|
-
|
|
115
|
+
// Credentials go only through the chokepoint below: when this account is
|
|
116
|
+
// the live one its profile home must not receive a CLI-usable copy.
|
|
117
|
+
fs.cpSync(sourceHome, canonicalHome, {
|
|
118
|
+
recursive: true,
|
|
119
|
+
force: true,
|
|
120
|
+
filter: (src) => {
|
|
121
|
+
const base = path.basename(src);
|
|
122
|
+
return base !== '.credentials.json' && !base.startsWith('.oauth_refresh.lock');
|
|
123
|
+
},
|
|
124
|
+
});
|
|
113
125
|
}
|
|
114
126
|
catch {
|
|
115
127
|
// The credential and identity files are re-written below when possible.
|
|
@@ -148,7 +160,7 @@ function beginAccountLogin(provider, label, opts = {}) {
|
|
|
148
160
|
const effectiveLabel = existing
|
|
149
161
|
? `${existing.label ?? existing.email ?? 'codex'} (re-login ${(0, crypto_1.randomUUID)().slice(0, 8)})`
|
|
150
162
|
: label.trim() || `Codex ${(0, codexProfiles_1.listCodexAccounts)().length + 1}`;
|
|
151
|
-
const prepared = (0, codexProfiles_1.prepareCodexAccount)(effectiveLabel);
|
|
163
|
+
const prepared = (0, codexProfiles_1.prepareCodexAccount)(effectiveLabel, { importCurrent: false });
|
|
152
164
|
if (!prepared.success || !prepared.profileId || !prepared.codexHome) {
|
|
153
165
|
return { success: false, error: prepared.error ?? 'Could not prepare Codex account login.' };
|
|
154
166
|
}
|
|
@@ -186,6 +198,9 @@ function beginAccountLogin(provider, label, opts = {}) {
|
|
|
186
198
|
existingAccountId: existing?.id,
|
|
187
199
|
});
|
|
188
200
|
seedClaudeLoginHome(home);
|
|
201
|
+
// Claude Code creates this home's Keychain item itself; record the home
|
|
202
|
+
// first so the item is provably Sidekick's even if everything else fails.
|
|
203
|
+
(0, claudeCredentialLedger_1.recordClaudeCredentialHome)(home, 'login');
|
|
189
204
|
const loginCommand = resolveClaudeLoginCommand(opts);
|
|
190
205
|
return {
|
|
191
206
|
success: true,
|
|
@@ -207,7 +222,7 @@ function getClaudeAccountLoginStatus(loginId) {
|
|
|
207
222
|
}
|
|
208
223
|
function getAccountLoginStatus(provider, loginId) {
|
|
209
224
|
if (provider === 'codex') {
|
|
210
|
-
const codexHome = (0,
|
|
225
|
+
const codexHome = (0, codexPaths_1.getCodexLoginHome)(loginId);
|
|
211
226
|
if (!(0, codexProfiles_1.isCodexProfileAuthenticated)(codexHome)) {
|
|
212
227
|
return { state: 'pending' };
|
|
213
228
|
}
|
|
@@ -226,7 +241,7 @@ function getAccountLoginStatus(provider, loginId) {
|
|
|
226
241
|
*/
|
|
227
242
|
async function getAccountLoginStatusAsync(provider, loginId) {
|
|
228
243
|
if (provider === 'codex') {
|
|
229
|
-
const codexHome = (0,
|
|
244
|
+
const codexHome = (0, codexPaths_1.getCodexLoginHome)(loginId);
|
|
230
245
|
if (!(await (0, codexProfiles_1.isCodexProfileAuthenticatedAsync)(codexHome))) {
|
|
231
246
|
return { state: 'pending' };
|
|
232
247
|
}
|
|
@@ -257,44 +272,55 @@ function finalizeClaudeAccountLogin(loginId, opts = {}) {
|
|
|
257
272
|
if (!identity) {
|
|
258
273
|
return { success: false, error: 'Claude profile is not authenticated yet.' };
|
|
259
274
|
}
|
|
260
|
-
const
|
|
261
|
-
if (
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const oauthAccount = readClaudeOauthAccount(home);
|
|
265
|
-
if (!oauthAccount) {
|
|
266
|
-
return { success: false, error: 'Could not read Claude profile config.' };
|
|
275
|
+
const read = (0, credentialIO_1.readClaudeCredentialStore)(home);
|
|
276
|
+
if (read.status === 'error') {
|
|
277
|
+
// Transient (locked Keychain, timeout): keep the login home for a retry.
|
|
278
|
+
return { success: false, error: 'Could not read the new Claude login yet; try again.' };
|
|
267
279
|
}
|
|
268
|
-
const pending = readPendingClaudeProfile(loginId);
|
|
269
|
-
const existing = (0, accountRegistry_1.listSavedAccountProfiles)('claude-code').find((account) => (account.providerAccountId ?? account.id) === identity.uuid);
|
|
270
|
-
copyClaudeProfileToCanonicalHome(home, identity.uuid, credentials, oauthAccount);
|
|
271
280
|
const warnings = [];
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
providerAccountId: identity.uuid,
|
|
279
|
-
email: identity.email,
|
|
280
|
-
label: existing?.label ?? (pending?.label || identity.email),
|
|
281
|
-
addedAt: existing?.addedAt ?? pending?.addedAt ?? new Date().toISOString(),
|
|
282
|
-
metadata: {
|
|
283
|
-
...existing?.metadata,
|
|
284
|
-
email: identity.email,
|
|
285
|
-
origin: 'login',
|
|
286
|
-
},
|
|
287
|
-
});
|
|
288
|
-
removePendingClaudeProfile(loginId);
|
|
289
|
-
if (loginId !== identity.uuid) {
|
|
290
|
-
removePendingClaudeProfile(identity.uuid);
|
|
291
|
-
// The temporary home's keychain item holds live tokens; nothing references it now.
|
|
292
|
-
(0, credentialIO_1.deleteStoredCredentials)((0, claudeProfiles_1.getClaudeProfileHome)(loginId));
|
|
293
|
-
try {
|
|
294
|
-
fs.rmSync((0, claudeProfiles_1.getClaudeProfileDir)(loginId), { recursive: true, force: true });
|
|
281
|
+
try {
|
|
282
|
+
if (read.status !== 'ok') {
|
|
283
|
+
return {
|
|
284
|
+
success: false,
|
|
285
|
+
error: 'The sign-in finished without a readable credential; sign in again.',
|
|
286
|
+
};
|
|
295
287
|
}
|
|
296
|
-
|
|
297
|
-
|
|
288
|
+
const oauthAccount = readClaudeOauthAccount(home);
|
|
289
|
+
if (!oauthAccount) {
|
|
290
|
+
return { success: false, error: 'Could not read Claude profile config.' };
|
|
291
|
+
}
|
|
292
|
+
const pending = readPendingClaudeProfile(loginId);
|
|
293
|
+
const existing = (0, accountRegistry_1.listSavedAccountProfiles)('claude-code').find((account) => (account.providerAccountId ?? account.id) === identity.uuid);
|
|
294
|
+
// The chokepoint writes the private backup first, so a failure below
|
|
295
|
+
// still leaves the new login saved.
|
|
296
|
+
copyClaudeProfileToCanonicalHome(home, identity.uuid, read.blob, oauthAccount);
|
|
297
|
+
if (pending?.existingAccountId && pending.existingAccountId !== identity.uuid) {
|
|
298
|
+
warnings.push(`You signed in as ${identity.email}, which is a different account from the one you chose to re-authenticate; it was saved separately.`);
|
|
299
|
+
}
|
|
300
|
+
(0, accountRegistry_1.upsertSavedAccountProfile)({
|
|
301
|
+
id: existing?.id ?? identity.uuid,
|
|
302
|
+
providerId: 'claude-code',
|
|
303
|
+
providerAccountId: identity.uuid,
|
|
304
|
+
email: identity.email,
|
|
305
|
+
label: existing?.label ?? (pending?.label || identity.email),
|
|
306
|
+
addedAt: existing?.addedAt ?? pending?.addedAt ?? new Date().toISOString(),
|
|
307
|
+
metadata: {
|
|
308
|
+
...existing?.metadata,
|
|
309
|
+
email: identity.email,
|
|
310
|
+
origin: 'login',
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
return { success: false, error: `Could not save the new Claude login: ${err}` };
|
|
316
|
+
}
|
|
317
|
+
finally {
|
|
318
|
+
// Every exit after authentication: the temporary home's Keychain item
|
|
319
|
+
// holds a live refresh token that nothing will ever reference again.
|
|
320
|
+
removePendingClaudeProfile(loginId);
|
|
321
|
+
if (loginId !== identity.uuid) {
|
|
322
|
+
removePendingClaudeProfile(identity.uuid);
|
|
323
|
+
discardClaudeLoginHome(loginId);
|
|
298
324
|
}
|
|
299
325
|
}
|
|
300
326
|
if (opts.activate === false) {
|
|
@@ -306,6 +332,8 @@ function finalizeClaudeAccountLogin(loginId, opts = {}) {
|
|
|
306
332
|
const applied = (0, accounts_1.applyClaudeProfileToLiveHome)(identity.uuid);
|
|
307
333
|
if (!applied.success)
|
|
308
334
|
return applied;
|
|
335
|
+
if (applied.warning)
|
|
336
|
+
warnings.push(applied.warning);
|
|
309
337
|
}
|
|
310
338
|
const switched = (0, accounts_1.switchToAccount)(identity.uuid);
|
|
311
339
|
return warnings.length
|
|
@@ -356,22 +384,82 @@ function latestHomeActivity(home) {
|
|
|
356
384
|
}
|
|
357
385
|
return latest;
|
|
358
386
|
}
|
|
387
|
+
/** Delete a temporary Claude login home: its Keychain item first, then the directory. */
|
|
388
|
+
function discardClaudeLoginHome(loginId) {
|
|
389
|
+
const dir = (0, claudeProfiles_1.getClaudeProfileDir)(loginId);
|
|
390
|
+
if (!path.resolve(dir).startsWith(path.resolve((0, accountRegistry_1.getAccountsDir)()) + path.sep))
|
|
391
|
+
return;
|
|
392
|
+
(0, credentialIO_1.deleteStoredCredentials)((0, claudeProfiles_1.getClaudeProfileHome)(loginId));
|
|
393
|
+
try {
|
|
394
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
/* the temporary login home is disposable */
|
|
398
|
+
}
|
|
399
|
+
}
|
|
359
400
|
function discardPendingLogin(provider, loginId) {
|
|
360
401
|
try {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
: (0, claudeProfiles_1.getClaudeProfileDir)(loginId);
|
|
364
|
-
if (!dir.startsWith((0, accountRegistry_1.getAccountsDir)()))
|
|
402
|
+
if (provider === 'claude-code') {
|
|
403
|
+
discardClaudeLoginHome(loginId);
|
|
365
404
|
return;
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
405
|
+
}
|
|
406
|
+
(0, codexProfiles_1.discardCodexLogin)(loginId);
|
|
369
407
|
}
|
|
370
408
|
catch {
|
|
371
409
|
/* best effort */
|
|
372
410
|
}
|
|
373
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* Abandon a login started with {@link beginAccountLogin} (cancelled, timed
|
|
414
|
+
* out, or failed): removes the temporary home and, for Claude, its Keychain
|
|
415
|
+
* item. Refuses ids that belong to a saved profile. Returns true when
|
|
416
|
+
* something was discarded.
|
|
417
|
+
*/
|
|
418
|
+
function discardAccountLogin(provider, loginId) {
|
|
419
|
+
const registered = provider === 'codex'
|
|
420
|
+
? (0, codexProfiles_1.listCodexAccounts)().some((account) => account.id === loginId)
|
|
421
|
+
: (0, accountRegistry_1.listSavedAccountProfiles)('claude-code').some((account) => account.id === loginId || account.providerAccountId === loginId);
|
|
422
|
+
if (registered)
|
|
423
|
+
return false;
|
|
424
|
+
if (provider === 'claude-code' && !readPendingClaudeProfile(loginId)) {
|
|
425
|
+
// Not a pending login; still drop a stray item for a home we created.
|
|
426
|
+
(0, credentialIO_1.deleteStoredCredentials)((0, claudeProfiles_1.getClaudeProfileHome)(loginId));
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
discardPendingLogin(provider, loginId);
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
class AccountLoginWriterActiveError extends Error {
|
|
433
|
+
}
|
|
374
434
|
async function spawnAccountLogin(provider, label, opts = {}) {
|
|
435
|
+
let loginId;
|
|
436
|
+
let result;
|
|
437
|
+
let writerActive = false;
|
|
438
|
+
try {
|
|
439
|
+
result = await runAccountLogin(provider, label, opts, (id) => {
|
|
440
|
+
loginId = id;
|
|
441
|
+
});
|
|
442
|
+
return result;
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
if (error instanceof AccountLoginWriterActiveError) {
|
|
446
|
+
writerActive = true;
|
|
447
|
+
return {
|
|
448
|
+
success: false,
|
|
449
|
+
error: 'The Codex login process could not be stopped. Its temporary home was preserved; close that process before retrying.',
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
throw error;
|
|
453
|
+
}
|
|
454
|
+
finally {
|
|
455
|
+
// Every exit that did not end in a saved login (spawn error, early exit,
|
|
456
|
+
// abort, timeout, a throw) removes the temporary home and its Keychain item.
|
|
457
|
+
if (!writerActive && loginId && (provider === 'codex' || !result?.success)) {
|
|
458
|
+
discardPendingLogin(provider, loginId);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async function runAccountLogin(provider, label, opts, onBegin) {
|
|
375
463
|
if (opts.signal?.aborted) {
|
|
376
464
|
return { success: false, error: 'Account login aborted.' };
|
|
377
465
|
}
|
|
@@ -381,6 +469,7 @@ async function spawnAccountLogin(provider, label, opts = {}) {
|
|
|
381
469
|
});
|
|
382
470
|
if (!begin.success)
|
|
383
471
|
return { success: false, error: begin.error };
|
|
472
|
+
onBegin(begin.loginId);
|
|
384
473
|
if (begin.alreadyComplete) {
|
|
385
474
|
return finalizeAccountLoginAsync(provider, begin.loginId, { activate: opts.activate ?? true });
|
|
386
475
|
}
|
|
@@ -419,57 +508,105 @@ async function spawnAccountLogin(provider, label, opts = {}) {
|
|
|
419
508
|
childExited = true;
|
|
420
509
|
childState.spawnError = error;
|
|
421
510
|
});
|
|
422
|
-
const
|
|
423
|
-
|
|
511
|
+
const stopCodexChild = async () => {
|
|
512
|
+
if (provider !== 'codex' || childExited)
|
|
513
|
+
return;
|
|
514
|
+
const waitForExit = (ms) => new Promise((resolve) => {
|
|
515
|
+
if (childExited) {
|
|
516
|
+
resolve();
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
const done = () => {
|
|
520
|
+
clearTimeout(timer);
|
|
521
|
+
child.off('exit', done);
|
|
522
|
+
child.off('error', done);
|
|
523
|
+
resolve();
|
|
524
|
+
};
|
|
525
|
+
const timer = setTimeout(done, ms);
|
|
526
|
+
child.once('exit', done);
|
|
527
|
+
child.once('error', done);
|
|
528
|
+
});
|
|
529
|
+
await waitForExit(100);
|
|
530
|
+
try {
|
|
531
|
+
if (!childExited) {
|
|
532
|
+
child.kill();
|
|
533
|
+
await waitForExit(1000);
|
|
534
|
+
}
|
|
535
|
+
if (!childExited) {
|
|
536
|
+
child.kill('SIGKILL');
|
|
537
|
+
await waitForExit(1000);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
catch {
|
|
541
|
+
throw new AccountLoginWriterActiveError();
|
|
542
|
+
}
|
|
543
|
+
if (!childExited)
|
|
544
|
+
throw new AccountLoginWriterActiveError();
|
|
545
|
+
};
|
|
546
|
+
const abort = async () => {
|
|
547
|
+
if (provider === 'codex')
|
|
548
|
+
await stopCodexChild();
|
|
549
|
+
else
|
|
550
|
+
child.kill();
|
|
424
551
|
discardPendingLogin(provider, begin.loginId);
|
|
425
552
|
emitStatus(opts, { state: 'failed', error: 'Account login aborted.' });
|
|
426
553
|
return { success: false, error: 'Account login aborted.' };
|
|
427
554
|
};
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
437
|
-
if (childExited) {
|
|
438
|
-
if (childState.spawnError) {
|
|
439
|
-
const error = `Could not spawn account login: ${childState.spawnError.message}`;
|
|
440
|
-
discardPendingLogin(provider, begin.loginId);
|
|
441
|
-
emitStatus(opts, { state: 'failed', error });
|
|
442
|
-
return { success: false, error };
|
|
443
|
-
}
|
|
444
|
-
const finalStatus = emitStatus(opts, await getAccountLoginStatusAsync(provider, begin.loginId));
|
|
445
|
-
if (finalStatus.state === 'authenticated') {
|
|
446
|
-
return finalizeAccountLoginAsync(provider, begin.loginId, {
|
|
555
|
+
try {
|
|
556
|
+
while (true) {
|
|
557
|
+
if (opts.signal?.aborted)
|
|
558
|
+
return await abort();
|
|
559
|
+
const status = emitStatus(opts, await getAccountLoginStatusAsync(provider, begin.loginId));
|
|
560
|
+
if (status.state === 'authenticated') {
|
|
561
|
+
await stopCodexChild();
|
|
562
|
+
return await finalizeAccountLoginAsync(provider, begin.loginId, {
|
|
447
563
|
activate: opts.activate ?? true,
|
|
448
564
|
});
|
|
449
565
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
566
|
+
if (childExited) {
|
|
567
|
+
if (childState.spawnError) {
|
|
568
|
+
const error = `Could not spawn account login: ${childState.spawnError.message}`;
|
|
569
|
+
discardPendingLogin(provider, begin.loginId);
|
|
570
|
+
emitStatus(opts, { state: 'failed', error });
|
|
571
|
+
return { success: false, error };
|
|
572
|
+
}
|
|
573
|
+
const finalStatus = emitStatus(opts, await getAccountLoginStatusAsync(provider, begin.loginId));
|
|
574
|
+
if (finalStatus.state === 'authenticated') {
|
|
575
|
+
await stopCodexChild();
|
|
576
|
+
return await finalizeAccountLoginAsync(provider, begin.loginId, {
|
|
577
|
+
activate: opts.activate ?? true,
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
discardPendingLogin(provider, begin.loginId);
|
|
581
|
+
emitStatus(opts, {
|
|
582
|
+
state: 'failed',
|
|
583
|
+
error: `Account login exited before authentication completed${childExitCode === null ? '.' : ` (exit ${childExitCode}).`}`,
|
|
584
|
+
});
|
|
585
|
+
return { success: false, error: 'Account login did not complete.' };
|
|
586
|
+
}
|
|
587
|
+
const now = Date.now();
|
|
588
|
+
const mtime = latestHomeActivity(begin.configDir);
|
|
589
|
+
if (mtime > lastSeenMtime) {
|
|
590
|
+
lastSeenMtime = mtime;
|
|
591
|
+
lastActivity = now;
|
|
592
|
+
}
|
|
593
|
+
const remainingMs = Math.min(inactivityMs - (now - lastActivity), maxMs - (now - startedAt));
|
|
594
|
+
if (remainingMs <= 0) {
|
|
595
|
+
if (provider === 'codex')
|
|
596
|
+
await stopCodexChild();
|
|
597
|
+
else
|
|
598
|
+
child.kill();
|
|
599
|
+
discardPendingLogin(provider, begin.loginId);
|
|
600
|
+
emitStatus(opts, { state: 'failed', error: 'Account login timed out.' });
|
|
601
|
+
return { success: false, error: 'Account login timed out.' };
|
|
602
|
+
}
|
|
603
|
+
const shouldContinue = await waitForNextPoll(Math.min(2_000, remainingMs), opts.signal);
|
|
604
|
+
if (!shouldContinue)
|
|
605
|
+
return await abort();
|
|
469
606
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
607
|
+
}
|
|
608
|
+
finally {
|
|
609
|
+
await stopCodexChild();
|
|
473
610
|
}
|
|
474
611
|
}
|
|
475
612
|
function switchAccount(provider, id, options = {}) {
|
package/dist/accountSync.d.ts
CHANGED
|
@@ -12,11 +12,6 @@ export interface SyncLiveAccountStateOptions {
|
|
|
12
12
|
keychainFoldIntervalMs?: number;
|
|
13
13
|
now?: number;
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Reconcile the live logins with the saved profiles for both providers.
|
|
17
|
-
* Safe to call from watchers: re-entrant calls return an empty report, and
|
|
18
|
-
* `onlyIfChanged` short-circuits when the live files are unchanged.
|
|
19
|
-
*/
|
|
20
15
|
export declare function syncLiveAccountStateSync(options?: SyncLiveAccountStateOptions): SyncReport;
|
|
21
16
|
/** Promise-returning twin of {@link syncLiveAccountStateSync} for async hosts. */
|
|
22
17
|
export declare function syncLiveAccountState(options?: SyncLiveAccountStateOptions): Promise<SyncReport>;
|
|
@@ -28,3 +23,4 @@ export interface CleanupAbandonedLoginsResult {
|
|
|
28
23
|
}
|
|
29
24
|
/** Remove isolated login homes that never authenticated (both providers). */
|
|
30
25
|
export declare function cleanupAbandonedLogins(olderThanMs?: number, now?: number): CleanupAbandonedLoginsResult;
|
|
26
|
+
export declare function cleanupAbandonedLoginsAsync(olderThanMs?: number, now?: number): Promise<CleanupAbandonedLoginsResult>;
|
package/dist/accountSync.js
CHANGED
|
@@ -37,6 +37,7 @@ exports.syncLiveAccountStateSync = syncLiveAccountStateSync;
|
|
|
37
37
|
exports.syncLiveAccountState = syncLiveAccountState;
|
|
38
38
|
exports._resetSyncFingerprints = _resetSyncFingerprints;
|
|
39
39
|
exports.cleanupAbandonedLogins = cleanupAbandonedLogins;
|
|
40
|
+
exports.cleanupAbandonedLoginsAsync = cleanupAbandonedLoginsAsync;
|
|
40
41
|
/**
|
|
41
42
|
* Continuous reconciliation between the live provider logins and sidekick's
|
|
42
43
|
* saved profiles. One engine replaces the old bootstrap/reconcile/backup
|
|
@@ -50,6 +51,7 @@ const accounts_1 = require("./accounts");
|
|
|
50
51
|
const claudeProfiles_1 = require("./claudeProfiles");
|
|
51
52
|
const codexProfiles_1 = require("./codexProfiles");
|
|
52
53
|
const codexPaths_1 = require("./codexPaths");
|
|
54
|
+
const processDetection_1 = require("./processDetection");
|
|
53
55
|
const accountSyncTypes_1 = require("./accountSyncTypes");
|
|
54
56
|
const DEFAULT_KEYCHAIN_FOLD_INTERVAL_MS = 10 * 60 * 1000;
|
|
55
57
|
const fingerprints = {
|
|
@@ -89,7 +91,7 @@ function sourceForReason(reason) {
|
|
|
89
91
|
return reason === 'pre-switch' ? 'switch' : 'live-sync';
|
|
90
92
|
}
|
|
91
93
|
function shouldSync(provider, fingerprint, options) {
|
|
92
|
-
if (!options.onlyIfChanged)
|
|
94
|
+
if (!options.onlyIfChanged || (provider === 'codex' && (0, codexProfiles_1.hasPendingCodexRepair)()))
|
|
93
95
|
return true;
|
|
94
96
|
const state = fingerprints[provider];
|
|
95
97
|
if (state.fingerprint !== fingerprint)
|
|
@@ -101,7 +103,7 @@ function shouldSync(provider, fingerprint, options) {
|
|
|
101
103
|
return false;
|
|
102
104
|
}
|
|
103
105
|
/** Sync one provider under its swap lock; never throws. */
|
|
104
|
-
function syncProvider(provider, reason, options) {
|
|
106
|
+
function syncProvider(provider, reason, options, scan) {
|
|
105
107
|
const fingerprint = provider === 'codex' ? codexFingerprint() : claudeFingerprint();
|
|
106
108
|
if (!shouldSync(provider, fingerprint, options)) {
|
|
107
109
|
return { ...(0, accountSyncTypes_1.emptyProviderSyncReport)(), skipped: 'unchanged' };
|
|
@@ -109,9 +111,11 @@ function syncProvider(provider, reason, options) {
|
|
|
109
111
|
const source = sourceForReason(reason);
|
|
110
112
|
let report;
|
|
111
113
|
try {
|
|
114
|
+
if (provider === 'codex')
|
|
115
|
+
scan ??= (0, processDetection_1.inspectRunningAccountConsumersSync)('codex');
|
|
112
116
|
report =
|
|
113
117
|
provider === 'codex'
|
|
114
|
-
? (0, codexProfiles_1.withCodexAuthSwapLock)(() => (0, codexProfiles_1.syncCodexLiveStateUnlocked)(source))
|
|
118
|
+
? (0, codexProfiles_1.withCodexAuthSwapLock)(() => (0, codexProfiles_1.syncCodexLiveStateUnlocked)(source, { scan }))
|
|
115
119
|
: (0, accounts_1.withClaudeAuthSwapLock)(() => (0, accounts_1.syncClaudeLiveStateUnlocked)(source));
|
|
116
120
|
}
|
|
117
121
|
catch (err) {
|
|
@@ -130,7 +134,7 @@ function syncProvider(provider, reason, options) {
|
|
|
130
134
|
* Safe to call from watchers: re-entrant calls return an empty report, and
|
|
131
135
|
* `onlyIfChanged` short-circuits when the live files are unchanged.
|
|
132
136
|
*/
|
|
133
|
-
function
|
|
137
|
+
function syncLiveAccountStateCore(options = {}, scan) {
|
|
134
138
|
const reason = options.reason ?? 'manual';
|
|
135
139
|
const now = options.now ?? Date.now();
|
|
136
140
|
const resolved = {
|
|
@@ -155,16 +159,22 @@ function syncLiveAccountStateSync(options = {}) {
|
|
|
155
159
|
if (providers.includes('claude-code'))
|
|
156
160
|
report.claude = syncProvider('claude-code', reason, resolved);
|
|
157
161
|
if (providers.includes('codex'))
|
|
158
|
-
report.codex = syncProvider('codex', reason, resolved);
|
|
162
|
+
report.codex = syncProvider('codex', reason, resolved, scan);
|
|
159
163
|
}
|
|
160
164
|
finally {
|
|
161
165
|
syncInProgress = false;
|
|
162
166
|
}
|
|
163
167
|
return report;
|
|
164
168
|
}
|
|
169
|
+
function syncLiveAccountStateSync(options = {}) {
|
|
170
|
+
return syncLiveAccountStateCore(options);
|
|
171
|
+
}
|
|
165
172
|
/** Promise-returning twin of {@link syncLiveAccountStateSync} for async hosts. */
|
|
166
173
|
async function syncLiveAccountState(options = {}) {
|
|
167
|
-
|
|
174
|
+
const scan = !options.providers || options.providers.includes('codex')
|
|
175
|
+
? await (0, processDetection_1.inspectRunningAccountConsumers)('codex')
|
|
176
|
+
: undefined;
|
|
177
|
+
return syncLiveAccountStateCore(options, scan);
|
|
168
178
|
}
|
|
169
179
|
/** Forget the change fingerprints (tests, or after an external reset). */
|
|
170
180
|
function _resetSyncFingerprints() {
|
|
@@ -178,3 +188,9 @@ function cleanupAbandonedLogins(olderThanMs = 6 * 60 * 60 * 1000, now = Date.now
|
|
|
178
188
|
codex: (0, codexProfiles_1.cleanupAbandonedCodexLogins)(olderThanMs, now),
|
|
179
189
|
};
|
|
180
190
|
}
|
|
191
|
+
async function cleanupAbandonedLoginsAsync(olderThanMs = 24 * 60 * 60 * 1000, now = Date.now()) {
|
|
192
|
+
return {
|
|
193
|
+
claude: (0, accounts_1.cleanupAbandonedClaudeLogins)(olderThanMs, now),
|
|
194
|
+
codex: await (0, codexProfiles_1.cleanupAbandonedCodexLoginsAsync)(olderThanMs, now),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
@@ -11,6 +11,15 @@ export interface ProviderSyncReport {
|
|
|
11
11
|
repointed?: string;
|
|
12
12
|
/** Duplicate profiles merged away (ids of the removed losers). */
|
|
13
13
|
merged?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* The live account's profile home held a CLI-usable copy of its login; it
|
|
16
|
+
* was removed (the account that is live keeps exactly one copy: live).
|
|
17
|
+
*/
|
|
18
|
+
demoted?: string;
|
|
19
|
+
/** That copy was strictly newer than live, so it replaced the dying live login first. */
|
|
20
|
+
repaired?: string;
|
|
21
|
+
/** A switch that crashed mid-way was finished or rolled back from its journal. */
|
|
22
|
+
journal?: 'finished' | 'rolled-back' | 'cleared';
|
|
14
23
|
/** Why nothing was synced (`logged-out`, `keyring`, `no-identity`, `unchanged`). */
|
|
15
24
|
skipped?: string;
|
|
16
25
|
warnings: string[];
|