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
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type LiveClaudeWriteIntent = 'switch' | 'relogin' | 'repair' | 'rollback';
|
|
2
|
+
/** The live store as read just before the write. */
|
|
3
|
+
export type LiveClaudeStoreState = {
|
|
4
|
+
status: 'ok';
|
|
5
|
+
blob: unknown;
|
|
6
|
+
} | {
|
|
7
|
+
status: 'absent';
|
|
8
|
+
} | {
|
|
9
|
+
status: 'corrupt';
|
|
10
|
+
} | {
|
|
11
|
+
status: 'error';
|
|
12
|
+
};
|
|
13
|
+
export interface LiveClaudeWriteRequest {
|
|
14
|
+
intent: LiveClaudeWriteIntent;
|
|
15
|
+
live: LiveClaudeStoreState;
|
|
16
|
+
/** Account uuid of the live identity (`oauthAccount`), null when logged out. */
|
|
17
|
+
liveAccountUuid: string | null;
|
|
18
|
+
candidate: unknown;
|
|
19
|
+
candidateAccountUuid: string;
|
|
20
|
+
/** `switch`: the outgoing live credential was saved and verified. */
|
|
21
|
+
capturedOutgoing?: boolean;
|
|
22
|
+
/** `rollback`: the blob the failed switch wrote. */
|
|
23
|
+
written?: unknown;
|
|
24
|
+
}
|
|
25
|
+
export type LiveClaudeWriteRefusal = 'live-unreadable' | 'invalid-candidate' | 'same-account' | 'different-account' | 'same-link' | 'not-captured' | 'not-newer' | 'live-changed';
|
|
26
|
+
export type LiveClaudeWriteDecision = {
|
|
27
|
+
allow: true;
|
|
28
|
+
} | {
|
|
29
|
+
allow: false;
|
|
30
|
+
code: LiveClaudeWriteRefusal;
|
|
31
|
+
reason: string;
|
|
32
|
+
};
|
|
33
|
+
export declare function decideLiveClaudeWrite(request: LiveClaudeWriteRequest): LiveClaudeWriteDecision;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decideLiveClaudeWrite = decideLiveClaudeWrite;
|
|
4
|
+
/**
|
|
5
|
+
* The decision every write into the live Claude credential store must pass.
|
|
6
|
+
* Pure: callers read the stores, this decides.
|
|
7
|
+
*
|
|
8
|
+
* Claude Code rotates the refresh token on every refresh, so the live store
|
|
9
|
+
* always holds the newest link of its chain. Writing an older link over it
|
|
10
|
+
* destroys a working login, and installing another account without saving the
|
|
11
|
+
* live one first loses that account's chain. The rules:
|
|
12
|
+
*
|
|
13
|
+
* - `switch`: another account replaces live. Allowed only after the outgoing
|
|
14
|
+
* live credential was captured (whenever live holds one), and never with a
|
|
15
|
+
* candidate that is the same refresh-token link as live.
|
|
16
|
+
* - `relogin` / `repair`: the same account's credential replaces live. Allowed
|
|
17
|
+
* only when the candidate is strictly fresher (a different refresh token
|
|
18
|
+
* with a later expiry); otherwise live is kept.
|
|
19
|
+
* - `rollback`: restore what a failed switch displaced. Allowed only while the
|
|
20
|
+
* live store still holds exactly what that switch wrote (or is empty or
|
|
21
|
+
* unparseable); a write Claude Code made in between is never clobbered.
|
|
22
|
+
* - An unreadable live store (`error`: timeout, locked Keychain) refuses all.
|
|
23
|
+
*/
|
|
24
|
+
const liveCredentialGuard_1 = require("./liveCredentialGuard");
|
|
25
|
+
const claudeCredentials_1 = require("./claudeCredentials");
|
|
26
|
+
function decideLiveClaudeWrite(request) {
|
|
27
|
+
const candidate = (0, claudeCredentials_1.parseClaudeCredentialBlob)(request.candidate);
|
|
28
|
+
const live = request.live.status === 'ok' ? (0, claudeCredentials_1.parseClaudeCredentialBlob)(request.live.blob) : null;
|
|
29
|
+
const liveFp = (0, claudeCredentials_1.claudeRefreshFingerprint)(live);
|
|
30
|
+
return (0, liveCredentialGuard_1.decideLiveCredentialWrite)({
|
|
31
|
+
provider: 'Claude',
|
|
32
|
+
intent: request.intent,
|
|
33
|
+
liveStatus: request.live.status,
|
|
34
|
+
candidateValid: candidate !== null,
|
|
35
|
+
liveHasCredential: live !== null,
|
|
36
|
+
liveAccountId: request.liveAccountUuid,
|
|
37
|
+
candidateAccountId: request.candidateAccountUuid,
|
|
38
|
+
sameLink: liveFp !== null && liveFp === (0, claudeCredentials_1.claudeRefreshFingerprint)(candidate),
|
|
39
|
+
strictlyNewer: (0, claudeCredentials_1.claudeCredentialFreshness)(candidate) > (0, claudeCredentials_1.claudeCredentialFreshness)(live),
|
|
40
|
+
capturedOutgoing: request.capturedOutgoing,
|
|
41
|
+
matchesWritten: request.live.status === 'ok' &&
|
|
42
|
+
JSON.stringify(request.live.blob) === JSON.stringify(request.written),
|
|
43
|
+
allowNonOkRollback: true,
|
|
44
|
+
requireDifferentLinkForAdvance: true,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function getDefaultClaudeHome(): string;
|
|
2
|
+
/** True when this process runs against the default `~/.claude` home. */
|
|
3
|
+
export declare function isDefaultClaudeHome(): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* The home the `claude` CLI reads and writes for this process: `CLAUDE_CONFIG_DIR`
|
|
6
|
+
* when set, else `~/.claude`. Every "live" credential or identity read goes
|
|
7
|
+
* through this so sidekick follows the same home the CLI does.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getLiveClaudeHome(): string;
|
|
10
|
+
/** Where the `claude` CLI writes session transcripts for this process. */
|
|
11
|
+
export declare function getClaudeProjectsDir(): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
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.getDefaultClaudeHome = getDefaultClaudeHome;
|
|
37
|
+
exports.isDefaultClaudeHome = isDefaultClaudeHome;
|
|
38
|
+
exports.getLiveClaudeHome = getLiveClaudeHome;
|
|
39
|
+
exports.getClaudeProjectsDir = getClaudeProjectsDir;
|
|
40
|
+
const os = __importStar(require("os"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
function getDefaultClaudeHome() {
|
|
43
|
+
return path.join(os.homedir(), '.claude');
|
|
44
|
+
}
|
|
45
|
+
/** True when this process runs against the default `~/.claude` home. */
|
|
46
|
+
function isDefaultClaudeHome() {
|
|
47
|
+
return !process.env.CLAUDE_CONFIG_DIR?.trim();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The home the `claude` CLI reads and writes for this process: `CLAUDE_CONFIG_DIR`
|
|
51
|
+
* when set, else `~/.claude`. Every "live" credential or identity read goes
|
|
52
|
+
* through this so sidekick follows the same home the CLI does.
|
|
53
|
+
*/
|
|
54
|
+
function getLiveClaudeHome() {
|
|
55
|
+
const explicit = process.env.CLAUDE_CONFIG_DIR?.trim();
|
|
56
|
+
return explicit ? explicit : getDefaultClaudeHome();
|
|
57
|
+
}
|
|
58
|
+
/** Where the `claude` CLI writes session transcripts for this process. */
|
|
59
|
+
function getClaudeProjectsDir() {
|
|
60
|
+
return path.join(getLiveClaudeHome(), 'projects');
|
|
61
|
+
}
|
package/dist/claudeProfiles.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getDefaultClaudeHome, getLiveClaudeHome, isDefaultClaudeHome } from './claudePaths';
|
|
2
|
+
export { getDefaultClaudeHome, getLiveClaudeHome, isDefaultClaudeHome };
|
|
1
3
|
/**
|
|
2
4
|
* Claude Code honours this variable ahead of `CLAUDE_CONFIG_DIR` when it
|
|
3
5
|
* derives the keychain item name. Any `claude` child sidekick spawns must not
|
|
@@ -8,18 +10,23 @@ export interface ClaudeProfileIdentity {
|
|
|
8
10
|
email: string;
|
|
9
11
|
uuid: string;
|
|
10
12
|
}
|
|
11
|
-
export declare function
|
|
12
|
-
/** True when this process runs against the default `~/.claude` home. */
|
|
13
|
-
export declare function isDefaultClaudeHome(): boolean;
|
|
13
|
+
export declare function getClaudeProfilesDir(): string;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* True when the live home is one of sidekick's own profile homes: a shell
|
|
16
|
+
* that eval'd `sidekick accounts env` or runs inside `sidekick accounts shell`.
|
|
17
|
+
* That profile's store then reads as the live store, so sync, re-login, and
|
|
18
|
+
* switching must not treat it as live: they would delete the shell's only
|
|
19
|
+
* usable copy and re-point the active account at it.
|
|
18
20
|
*/
|
|
19
|
-
export declare function
|
|
20
|
-
export declare function getClaudeProfilesDir(): string;
|
|
21
|
+
export declare function isLiveClaudeHomeSidekickProfile(): boolean;
|
|
21
22
|
export declare function getClaudeProfileDir(uuid: string): string;
|
|
22
23
|
export declare function getClaudeProfileHome(uuid: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Sidekick's private backup of a profile's credential. Claude Code never reads
|
|
26
|
+
* it, so it is not a CLI-usable copy: this is where the live account's
|
|
27
|
+
* credential is mirrored while its profile home stays empty.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getClaudeCredentialBackupPath(uuid: string): string;
|
|
23
30
|
export declare function ensureClaudeProfileDirs(uuid: string): void;
|
|
24
31
|
/**
|
|
25
32
|
* Claude Code hashes the NFC-normalised config directory; macOS hands paths
|
package/dist/claudeProfiles.js
CHANGED
|
@@ -33,13 +33,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.CLAUDE_SECURESTORAGE_CONFIG_DIR_ENV = void 0;
|
|
37
|
-
exports.getDefaultClaudeHome = getDefaultClaudeHome;
|
|
38
|
-
exports.isDefaultClaudeHome = isDefaultClaudeHome;
|
|
39
|
-
exports.getLiveClaudeHome = getLiveClaudeHome;
|
|
36
|
+
exports.CLAUDE_SECURESTORAGE_CONFIG_DIR_ENV = exports.isDefaultClaudeHome = exports.getLiveClaudeHome = exports.getDefaultClaudeHome = void 0;
|
|
40
37
|
exports.getClaudeProfilesDir = getClaudeProfilesDir;
|
|
38
|
+
exports.isLiveClaudeHomeSidekickProfile = isLiveClaudeHomeSidekickProfile;
|
|
41
39
|
exports.getClaudeProfileDir = getClaudeProfileDir;
|
|
42
40
|
exports.getClaudeProfileHome = getClaudeProfileHome;
|
|
41
|
+
exports.getClaudeCredentialBackupPath = getClaudeCredentialBackupPath;
|
|
43
42
|
exports.ensureClaudeProfileDirs = ensureClaudeProfileDirs;
|
|
44
43
|
exports.claudeKeychainSuffix = claudeKeychainSuffix;
|
|
45
44
|
exports.claudeKeychainService = claudeKeychainService;
|
|
@@ -56,6 +55,10 @@ const fs = __importStar(require("fs"));
|
|
|
56
55
|
const os = __importStar(require("os"));
|
|
57
56
|
const path = __importStar(require("path"));
|
|
58
57
|
const accountRegistry_1 = require("./accountRegistry");
|
|
58
|
+
const claudePaths_1 = require("./claudePaths");
|
|
59
|
+
Object.defineProperty(exports, "getDefaultClaudeHome", { enumerable: true, get: function () { return claudePaths_1.getDefaultClaudeHome; } });
|
|
60
|
+
Object.defineProperty(exports, "getLiveClaudeHome", { enumerable: true, get: function () { return claudePaths_1.getLiveClaudeHome; } });
|
|
61
|
+
Object.defineProperty(exports, "isDefaultClaudeHome", { enumerable: true, get: function () { return claudePaths_1.isDefaultClaudeHome; } });
|
|
59
62
|
const DEFAULT_CLAUDE_KEYCHAIN_SERVICE = 'Claude Code-credentials';
|
|
60
63
|
const KEYCHAIN_ACCOUNT_PATTERN = /^[a-zA-Z0-9._-]+$/;
|
|
61
64
|
const KEYCHAIN_FALLBACK_ACCOUNT = 'claude-code-user';
|
|
@@ -65,24 +68,20 @@ const KEYCHAIN_FALLBACK_ACCOUNT = 'claude-code-user';
|
|
|
65
68
|
* inherit it, or the login would land in an item nobody else reads.
|
|
66
69
|
*/
|
|
67
70
|
exports.CLAUDE_SECURESTORAGE_CONFIG_DIR_ENV = 'CLAUDE_SECURESTORAGE_CONFIG_DIR';
|
|
68
|
-
function
|
|
69
|
-
return path.join(
|
|
70
|
-
}
|
|
71
|
-
/** True when this process runs against the default `~/.claude` home. */
|
|
72
|
-
function isDefaultClaudeHome() {
|
|
73
|
-
return !process.env.CLAUDE_CONFIG_DIR?.trim();
|
|
71
|
+
function getClaudeProfilesDir() {
|
|
72
|
+
return path.join((0, accountRegistry_1.getAccountsDir)(), 'claude', 'profiles');
|
|
74
73
|
}
|
|
75
74
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
75
|
+
* True when the live home is one of sidekick's own profile homes: a shell
|
|
76
|
+
* that eval'd `sidekick accounts env` or runs inside `sidekick accounts shell`.
|
|
77
|
+
* That profile's store then reads as the live store, so sync, re-login, and
|
|
78
|
+
* switching must not treat it as live: they would delete the shell's only
|
|
79
|
+
* usable copy and re-point the active account at it.
|
|
79
80
|
*/
|
|
80
|
-
function
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
function getClaudeProfilesDir() {
|
|
85
|
-
return path.join((0, accountRegistry_1.getAccountsDir)(), 'claude', 'profiles');
|
|
81
|
+
function isLiveClaudeHomeSidekickProfile() {
|
|
82
|
+
const liveHome = path.resolve((0, claudePaths_1.getLiveClaudeHome)());
|
|
83
|
+
const profilesDir = path.resolve(getClaudeProfilesDir());
|
|
84
|
+
return liveHome === profilesDir || liveHome.startsWith(profilesDir + path.sep);
|
|
86
85
|
}
|
|
87
86
|
function getClaudeProfileDir(uuid) {
|
|
88
87
|
return path.join(getClaudeProfilesDir(), uuid);
|
|
@@ -90,6 +89,14 @@ function getClaudeProfileDir(uuid) {
|
|
|
90
89
|
function getClaudeProfileHome(uuid) {
|
|
91
90
|
return path.join(getClaudeProfileDir(uuid), 'home');
|
|
92
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Sidekick's private backup of a profile's credential. Claude Code never reads
|
|
94
|
+
* it, so it is not a CLI-usable copy: this is where the live account's
|
|
95
|
+
* credential is mirrored while its profile home stays empty.
|
|
96
|
+
*/
|
|
97
|
+
function getClaudeCredentialBackupPath(uuid) {
|
|
98
|
+
return path.join((0, accountRegistry_1.getAccountsDir)(), 'credentials', `${uuid}.credentials.json`);
|
|
99
|
+
}
|
|
93
100
|
function ensureClaudeProfileDirs(uuid) {
|
|
94
101
|
fs.mkdirSync(getClaudeProfileHome(uuid), { recursive: true, mode: 0o700 });
|
|
95
102
|
}
|
|
@@ -107,7 +114,7 @@ function claudeKeychainSuffix(configDir) {
|
|
|
107
114
|
* `~/.claude` — so the no-argument form follows the process environment.
|
|
108
115
|
*/
|
|
109
116
|
function claudeKeychainService(configDir) {
|
|
110
|
-
const dir = configDir ?? (isDefaultClaudeHome() ? undefined : getLiveClaudeHome());
|
|
117
|
+
const dir = configDir ?? ((0, claudePaths_1.isDefaultClaudeHome)() ? undefined : (0, claudePaths_1.getLiveClaudeHome)());
|
|
111
118
|
return dir
|
|
112
119
|
? `${DEFAULT_CLAUDE_KEYCHAIN_SERVICE}-${claudeKeychainSuffix(dir)}`
|
|
113
120
|
: DEFAULT_CLAUDE_KEYCHAIN_SERVICE;
|
|
@@ -145,11 +152,11 @@ function readOauthAccount(configPath) {
|
|
|
145
152
|
* when it carries an identity, otherwise fall back to the legacy location for
|
|
146
153
|
* the default home only.
|
|
147
154
|
*/
|
|
148
|
-
function getClaudeConfigPath(home = getLiveClaudeHome()) {
|
|
155
|
+
function getClaudeConfigPath(home = (0, claudePaths_1.getLiveClaudeHome)()) {
|
|
149
156
|
const primary = path.join(home, '.claude.json');
|
|
150
157
|
if (readOauthAccount(primary))
|
|
151
158
|
return primary;
|
|
152
|
-
if (path.resolve(home) === path.resolve(getDefaultClaudeHome())) {
|
|
159
|
+
if (path.resolve(home) === path.resolve((0, claudePaths_1.getDefaultClaudeHome)())) {
|
|
153
160
|
return path.join(os.homedir(), '.claude.json');
|
|
154
161
|
}
|
|
155
162
|
return primary;
|
|
@@ -160,7 +167,7 @@ function identityFromOauthAccount(oauthAccount) {
|
|
|
160
167
|
return typeof email === 'string' && typeof uuid === 'string' ? { email, uuid } : null;
|
|
161
168
|
}
|
|
162
169
|
/** Identity of the account currently logged in to a Claude home (default: the live home). */
|
|
163
|
-
function readLiveClaudeIdentity(home = getLiveClaudeHome()) {
|
|
170
|
+
function readLiveClaudeIdentity(home = (0, claudePaths_1.getLiveClaudeHome)()) {
|
|
164
171
|
return identityFromOauthAccount(readOauthAccount(getClaudeConfigPath(home)));
|
|
165
172
|
}
|
|
166
173
|
function readClaudeProfileIdentity(home) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Claude Code treats a lock older than this as abandoned (proper-lockfile `stale`). */
|
|
2
|
+
export declare const CLAUDE_REFRESH_LOCK_STALE_MS = 60000;
|
|
3
|
+
/** Claude Code is refreshing a login in one of the homes; retry shortly. */
|
|
4
|
+
export declare class ClaudeRefreshLockBusyError extends Error {
|
|
5
|
+
constructor(lockPath: string);
|
|
6
|
+
}
|
|
7
|
+
export declare function claudeRefreshLockPaths(home: string): string[];
|
|
8
|
+
/**
|
|
9
|
+
* Run `operation` holding the refresh locks of every existing home (a home
|
|
10
|
+
* that does not exist has no CLI using it). Throws
|
|
11
|
+
* {@link ClaudeRefreshLockBusyError} when a lock stays held past `waitMs`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function withClaudeRefreshLocksSync<T>(homes: string[], operation: () => T, options?: {
|
|
14
|
+
waitMs?: number;
|
|
15
|
+
}): T;
|
|
@@ -0,0 +1,145 @@
|
|
|
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.ClaudeRefreshLockBusyError = exports.CLAUDE_REFRESH_LOCK_STALE_MS = void 0;
|
|
37
|
+
exports.claudeRefreshLockPaths = claudeRefreshLockPaths;
|
|
38
|
+
exports.withClaudeRefreshLocksSync = withClaudeRefreshLocksSync;
|
|
39
|
+
/**
|
|
40
|
+
* Borrow Claude Code's own token-refresh lock while Sidekick reads and
|
|
41
|
+
* replaces a home's credential.
|
|
42
|
+
*
|
|
43
|
+
* Claude Code 2.1.x serialises refreshes per config directory with a
|
|
44
|
+
* proper-lockfile directory lock at `<configDir>/.oauth_refresh.lock` (stale
|
|
45
|
+
* after 60 s) plus a legacy `<realpath(configDir)>.lock`. Under that lock it
|
|
46
|
+
* re-reads the store before refreshing and adopts a token someone else wrote,
|
|
47
|
+
* so holding both locks keeps a refresh (which rotates the refresh token) out
|
|
48
|
+
* of the window between Sidekick's read and its write.
|
|
49
|
+
*
|
|
50
|
+
* Best effort by construction: this layers on Claude Code internals. If they
|
|
51
|
+
* change we lose only the exclusion; the callers' fingerprint re-checks still
|
|
52
|
+
* catch a store that moved. Held briefly (a few `security` calls), well under
|
|
53
|
+
* the 60 s stale window, and released on every exit.
|
|
54
|
+
*/
|
|
55
|
+
const fs = __importStar(require("fs"));
|
|
56
|
+
const path = __importStar(require("path"));
|
|
57
|
+
/** Claude Code treats a lock older than this as abandoned (proper-lockfile `stale`). */
|
|
58
|
+
exports.CLAUDE_REFRESH_LOCK_STALE_MS = 60_000;
|
|
59
|
+
const DEFAULT_WAIT_MS = 5_000;
|
|
60
|
+
const POLL_MS = 50;
|
|
61
|
+
const sleepView = new Int32Array(new SharedArrayBuffer(4));
|
|
62
|
+
/** Claude Code is refreshing a login in one of the homes; retry shortly. */
|
|
63
|
+
class ClaudeRefreshLockBusyError extends Error {
|
|
64
|
+
constructor(lockPath) {
|
|
65
|
+
super(`Claude Code is refreshing a login (${lockPath} is held); try again in a few seconds.`);
|
|
66
|
+
this.name = 'ClaudeRefreshLockBusyError';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.ClaudeRefreshLockBusyError = ClaudeRefreshLockBusyError;
|
|
70
|
+
function claudeRefreshLockPaths(home) {
|
|
71
|
+
let real = path.resolve(home);
|
|
72
|
+
try {
|
|
73
|
+
real = fs.realpathSync(home);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
/* keep the resolved path */
|
|
77
|
+
}
|
|
78
|
+
return [path.join(home, '.oauth_refresh.lock'), `${real}.lock`];
|
|
79
|
+
}
|
|
80
|
+
function tryAcquire(lockPath, now) {
|
|
81
|
+
try {
|
|
82
|
+
fs.mkdirSync(lockPath);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error.code !== 'EEXIST')
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const stat = fs.statSync(lockPath);
|
|
91
|
+
if (now - stat.mtimeMs > exports.CLAUDE_REFRESH_LOCK_STALE_MS) {
|
|
92
|
+
// proper-lockfile's own recovery: an abandoned lock is removed and retaken.
|
|
93
|
+
fs.rmSync(lockPath, { recursive: true, force: true });
|
|
94
|
+
fs.mkdirSync(lockPath);
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
/* released or retaken between checks; poll again */
|
|
100
|
+
}
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Run `operation` holding the refresh locks of every existing home (a home
|
|
105
|
+
* that does not exist has no CLI using it). Throws
|
|
106
|
+
* {@link ClaudeRefreshLockBusyError} when a lock stays held past `waitMs`.
|
|
107
|
+
*/
|
|
108
|
+
function withClaudeRefreshLocksSync(homes, operation, options = {}) {
|
|
109
|
+
const waitMs = options.waitMs ?? DEFAULT_WAIT_MS;
|
|
110
|
+
const lockPaths = [
|
|
111
|
+
...new Set(homes
|
|
112
|
+
.filter((home) => {
|
|
113
|
+
try {
|
|
114
|
+
return fs.statSync(home).isDirectory();
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
.flatMap(claudeRefreshLockPaths)),
|
|
121
|
+
];
|
|
122
|
+
const held = [];
|
|
123
|
+
try {
|
|
124
|
+
const deadline = Date.now() + waitMs;
|
|
125
|
+
for (const lockPath of lockPaths) {
|
|
126
|
+
while (!tryAcquire(lockPath, Date.now())) {
|
|
127
|
+
if (Date.now() >= deadline)
|
|
128
|
+
throw new ClaudeRefreshLockBusyError(lockPath);
|
|
129
|
+
Atomics.wait(sleepView, 0, 0, POLL_MS);
|
|
130
|
+
}
|
|
131
|
+
held.push(lockPath);
|
|
132
|
+
}
|
|
133
|
+
return operation();
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
for (const lockPath of held.reverse()) {
|
|
137
|
+
try {
|
|
138
|
+
fs.rmSync(lockPath, { recursive: true, force: true });
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
/* Claude Code recovers a stale lock after 60 s */
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
package/dist/codexAuth.d.ts
CHANGED
|
@@ -30,3 +30,7 @@ export declare function identitiesMatch(a: {
|
|
|
30
30
|
email?: string;
|
|
31
31
|
workspaceId?: string;
|
|
32
32
|
} | null | undefined): boolean;
|
|
33
|
+
/** Non-secret chain-link identifier; raw token values never belong in diagnostics. */
|
|
34
|
+
export declare function codexRefreshFingerprint(raw: string | null): string | null;
|
|
35
|
+
/** Compare evidence, never filesystem timestamps. Incomparable credentials tie. */
|
|
36
|
+
export declare function compareCodexAuthFreshness(a: string | null, b: string | null): number;
|
package/dist/codexAuth.js
CHANGED
|
@@ -40,11 +40,14 @@ exports.readAuthIdentityFromRaw = readAuthIdentityFromRaw;
|
|
|
40
40
|
exports.readLastRefresh = readLastRefresh;
|
|
41
41
|
exports.readAccessTokenExpiry = readAccessTokenExpiry;
|
|
42
42
|
exports.identitiesMatch = identitiesMatch;
|
|
43
|
+
exports.codexRefreshFingerprint = codexRefreshFingerprint;
|
|
44
|
+
exports.compareCodexAuthFreshness = compareCodexAuthFreshness;
|
|
43
45
|
/**
|
|
44
46
|
* Pure helpers over the Codex CLI `auth.json` payload. No filesystem access
|
|
45
47
|
* beyond an optional mtime fallback, no child processes.
|
|
46
48
|
*/
|
|
47
49
|
const fs = __importStar(require("fs"));
|
|
50
|
+
const crypto_1 = require("crypto");
|
|
48
51
|
// Codex refreshes OAuth tokens at most every 8 days; a stored refresh token
|
|
49
52
|
// older than that may already be rejected by the auth server.
|
|
50
53
|
exports.STALE_AUTH_THRESHOLD_MS = 8 * 24 * 60 * 60 * 1000;
|
|
@@ -125,3 +128,18 @@ function identitiesMatch(a, b) {
|
|
|
125
128
|
return a.workspaceId === b.workspaceId;
|
|
126
129
|
return Boolean(a.email && b.email && a.email === b.email);
|
|
127
130
|
}
|
|
131
|
+
/** Non-secret chain-link identifier; raw token values never belong in diagnostics. */
|
|
132
|
+
function codexRefreshFingerprint(raw) {
|
|
133
|
+
const token = parseAuthJson(raw)?.tokens?.refresh_token;
|
|
134
|
+
return typeof token === 'string' && token
|
|
135
|
+
? (0, crypto_1.createHash)('sha256').update(token).digest('hex').slice(0, 16)
|
|
136
|
+
: null;
|
|
137
|
+
}
|
|
138
|
+
/** Compare evidence, never filesystem timestamps. Incomparable credentials tie. */
|
|
139
|
+
function compareCodexAuthFreshness(a, b) {
|
|
140
|
+
const ar = readLastRefresh(a), br = readLastRefresh(b);
|
|
141
|
+
if (ar !== null && br !== null && ar !== br)
|
|
142
|
+
return ar > br ? 1 : -1;
|
|
143
|
+
const ae = readAccessTokenExpiry(a), be = readAccessTokenExpiry(b);
|
|
144
|
+
return ae !== null && be !== null && ae !== be ? (ae > be ? 1 : -1) : 0;
|
|
145
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ProviderSyncReport } from './accountSyncTypes';
|
|
2
|
+
export interface CodexCredentialFinding {
|
|
3
|
+
kind: 'live-duplicate' | 'stale-stash' | 'orphan' | 'corrupt' | 'unreadable' | 'pending-switch';
|
|
4
|
+
configDir: string;
|
|
5
|
+
/** Present for old timestamped stash files. */
|
|
6
|
+
file?: string;
|
|
7
|
+
ownership: 'profile-home' | 'login-home' | 'stash' | 'live' | 'journal' | 'backup';
|
|
8
|
+
accountId?: string;
|
|
9
|
+
email?: string;
|
|
10
|
+
fingerprint?: string;
|
|
11
|
+
detail: string;
|
|
12
|
+
action: string;
|
|
13
|
+
}
|
|
14
|
+
export interface CodexCredentialInspection {
|
|
15
|
+
findings: CodexCredentialFinding[];
|
|
16
|
+
homesChecked: number;
|
|
17
|
+
}
|
|
18
|
+
export interface CodexCredentialRepairResult extends CodexCredentialInspection {
|
|
19
|
+
dryRun: boolean;
|
|
20
|
+
repaired: Array<{
|
|
21
|
+
finding: CodexCredentialFinding;
|
|
22
|
+
ok: boolean;
|
|
23
|
+
error?: string;
|
|
24
|
+
}>;
|
|
25
|
+
sync?: ProviderSyncReport;
|
|
26
|
+
}
|
|
27
|
+
export declare function inspectCodexCredentialStores(options?: {
|
|
28
|
+
now?: number;
|
|
29
|
+
}): CodexCredentialInspection;
|
|
30
|
+
export declare function repairCodexCredentialStores(options?: {
|
|
31
|
+
now?: number;
|
|
32
|
+
dryRun?: boolean;
|
|
33
|
+
}): CodexCredentialRepairResult;
|