sidekick-shared 0.27.6 → 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 +28 -0
- package/README.md +58 -18
- package/dist/browser.d.ts +13 -2
- package/dist/browser.js +30 -2
- package/dist/claudePaths.d.ts +11 -0
- package/dist/claudePaths.js +61 -0
- package/dist/claudeProfiles.d.ts +2 -9
- package/dist/claudeProfiles.js +10 -25
- package/dist/codexPaths.d.ts +22 -0
- package/dist/codexPaths.js +67 -0
- package/dist/codexProfiles.d.ts +1 -4
- package/dist/codexProfiles.js +5 -43
- package/dist/doctor.js +2 -2
- 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 +16 -7
- package/dist/index.js +49 -15
- 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/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/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/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/promptHistory.js
CHANGED
|
@@ -57,6 +57,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
57
57
|
exports.__promptHistoryTesting = exports.DEFAULT_BOUNDS = void 0;
|
|
58
58
|
exports.collectPromptHistory = collectPromptHistory;
|
|
59
59
|
exports.emptyStats = emptyStats;
|
|
60
|
+
exports.isPromptHistorySessionSettled = isPromptHistorySessionSettled;
|
|
61
|
+
exports.parsePromptHistoryCursor = parsePromptHistoryCursor;
|
|
60
62
|
exports.compareStrings = compareStrings;
|
|
61
63
|
exports.resolveRoots = resolveRoots;
|
|
62
64
|
exports.listCandidates = listCandidates;
|
|
@@ -65,9 +67,11 @@ const crypto_1 = require("crypto");
|
|
|
65
67
|
const fs = __importStar(require("fs"));
|
|
66
68
|
const path = __importStar(require("path"));
|
|
67
69
|
const humanPrompt_1 = require("./humanPrompt");
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
const
|
|
70
|
+
const claudeListing_1 = require("./providers/claudeListing");
|
|
71
|
+
const codexRollouts_1 = require("./providers/codexRollouts");
|
|
72
|
+
const directoryListingCache_1 = require("./providers/directoryListingCache");
|
|
73
|
+
const workspaceRoots_1 = require("./workspaceRoots");
|
|
74
|
+
const fileHead_1 = require("./fileHead");
|
|
71
75
|
/** @internal */
|
|
72
76
|
exports.DEFAULT_BOUNDS = {
|
|
73
77
|
maxSessions: 1000,
|
|
@@ -78,7 +82,6 @@ exports.DEFAULT_BOUNDS = {
|
|
|
78
82
|
deadlineMs: 30_000,
|
|
79
83
|
};
|
|
80
84
|
const DEFAULT_READ_CHUNK_BYTES = 1024 * 1024;
|
|
81
|
-
const HEAD_BYTES = 4096;
|
|
82
85
|
const MAX_EXCLUSIONS = 1000;
|
|
83
86
|
const CHECK_EVERY_LINES = 500;
|
|
84
87
|
const ALL_PROVIDERS = ['claude-code', 'codex'];
|
|
@@ -99,7 +102,17 @@ async function collectPromptHistory(options) {
|
|
|
99
102
|
const cursor = { version: 3, sessions: { ...previous } };
|
|
100
103
|
const entries = [];
|
|
101
104
|
const exclusions = [];
|
|
105
|
+
const changed = new Map();
|
|
102
106
|
let hasMore = false;
|
|
107
|
+
let progressed = false;
|
|
108
|
+
let scannedRoots = [];
|
|
109
|
+
const markChanged = (candidate) => {
|
|
110
|
+
changed.set(candidate.key, {
|
|
111
|
+
provider: candidate.provider,
|
|
112
|
+
sessionId: candidate.sessionId,
|
|
113
|
+
sessionKey: candidate.key,
|
|
114
|
+
});
|
|
115
|
+
};
|
|
103
116
|
const shouldStop = () => {
|
|
104
117
|
if (options.signal?.aborted)
|
|
105
118
|
return 'aborted';
|
|
@@ -114,14 +127,19 @@ async function collectPromptHistory(options) {
|
|
|
114
127
|
boundsHit: [...boundsHit],
|
|
115
128
|
exclusions,
|
|
116
129
|
hasMore,
|
|
130
|
+
changed: [...changed.values()],
|
|
131
|
+
progressed,
|
|
132
|
+
roots: scannedRoots,
|
|
117
133
|
});
|
|
118
134
|
const realpaths = new Map();
|
|
119
135
|
const { roots, listingRoots } = resolveRoots(options.workspacePaths, options.includeWorktrees !== false, realpaths);
|
|
136
|
+
scannedRoots = roots;
|
|
120
137
|
if (roots.length === 0)
|
|
121
138
|
return finish();
|
|
122
139
|
const sinceMs = options.since ? options.since.getTime() : null;
|
|
123
140
|
const providers = options.providers ?? ALL_PROVIDERS;
|
|
124
141
|
const candidates = rotate(await listCandidates(providers, listingRoots, sinceMs), previousNext);
|
|
142
|
+
const moved = movedSessionKeys(previous, candidates);
|
|
125
143
|
const context = {
|
|
126
144
|
roots,
|
|
127
145
|
sinceMs,
|
|
@@ -160,7 +178,21 @@ async function collectPromptHistory(options) {
|
|
|
160
178
|
catch {
|
|
161
179
|
continue;
|
|
162
180
|
}
|
|
163
|
-
|
|
181
|
+
let prior = validSession(previous[candidate.key]);
|
|
182
|
+
const sessionRef = `${candidate.provider}:${candidate.sessionId}`;
|
|
183
|
+
const movedFrom = prior ? undefined : moved.get(sessionRef);
|
|
184
|
+
const carried = movedFrom ? validSession(previous[movedFrom]) : undefined;
|
|
185
|
+
// The same session under a new path (Codex archives a thread by moving its
|
|
186
|
+
// rollout): carry the entry over, but only when the new file starts with
|
|
187
|
+
// the recorded head. Another file that merely shares the id (an unlisted
|
|
188
|
+
// file is not necessarily gone) keeps its own entry and is read as new.
|
|
189
|
+
if (movedFrom && carried?.head && (await fileStartsWith(candidate.filePath, carried.head))) {
|
|
190
|
+
moved.delete(sessionRef);
|
|
191
|
+
prior = carried;
|
|
192
|
+
delete cursor.sessions[movedFrom];
|
|
193
|
+
cursor.sessions[candidate.key] = carried;
|
|
194
|
+
markChanged(candidate);
|
|
195
|
+
}
|
|
164
196
|
if (prior && isSettled(prior) && prior.size === stat.size && prior.mtimeMs === stat.mtimeMs) {
|
|
165
197
|
stats.sessionsSkippedUnchanged++;
|
|
166
198
|
continue;
|
|
@@ -191,7 +223,15 @@ async function collectPromptHistory(options) {
|
|
|
191
223
|
continue;
|
|
192
224
|
}
|
|
193
225
|
totalBytes += outcome.bytesRead;
|
|
226
|
+
for (const entry of outcome.entries)
|
|
227
|
+
entry.sessionKey = candidate.key;
|
|
194
228
|
entries.push(...outcome.entries);
|
|
229
|
+
if (outcome.progressed)
|
|
230
|
+
progressed = true;
|
|
231
|
+
if (!outcome.session ||
|
|
232
|
+
JSON.stringify(outcome.session) !== JSON.stringify(previous[candidate.key])) {
|
|
233
|
+
markChanged(candidate);
|
|
234
|
+
}
|
|
195
235
|
if (outcome.notInteractive)
|
|
196
236
|
stats.sessionsNotInteractive++;
|
|
197
237
|
else if (outcome.inScope === 0 && outcome.outOfScope > 0)
|
|
@@ -276,6 +316,33 @@ function validSession(session) {
|
|
|
276
316
|
typeof session.mtimeMs === 'number';
|
|
277
317
|
return valid ? session : undefined;
|
|
278
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* True when a cursor entry's last pass reached the end of its file with no
|
|
321
|
+
* prompt still waiting for its answer: an unchanged file needs no read.
|
|
322
|
+
*/
|
|
323
|
+
function isPromptHistorySessionSettled(session) {
|
|
324
|
+
return validSession(session) !== undefined && isSettled(session);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Validates a stored cursor (versions 1 to 3). Returns it as a version-3
|
|
328
|
+
* cursor with malformed session entries dropped, or undefined when it is
|
|
329
|
+
* not a cursor at all.
|
|
330
|
+
*/
|
|
331
|
+
function parsePromptHistoryCursor(value) {
|
|
332
|
+
if (!value || typeof value !== 'object')
|
|
333
|
+
return undefined;
|
|
334
|
+
const candidate = value;
|
|
335
|
+
if (typeof candidate.version !== 'number' || ![1, 2, 3].includes(candidate.version)) {
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
const { sessions, next } = acceptedCursor(value);
|
|
339
|
+
const valid = {};
|
|
340
|
+
for (const [key, session] of Object.entries(sessions)) {
|
|
341
|
+
if (validSession(session))
|
|
342
|
+
valid[key] = session;
|
|
343
|
+
}
|
|
344
|
+
return { version: 3, sessions: valid, ...(next !== undefined ? { next } : {}) };
|
|
345
|
+
}
|
|
279
346
|
/** A session whose last pass reached the end and needs no migration. */
|
|
280
347
|
function isSettled(session) {
|
|
281
348
|
if (session.backlog || session.skipping)
|
|
@@ -339,53 +406,15 @@ function rotate(candidates, nextKey) {
|
|
|
339
406
|
const index = nextKey ? candidates.findIndex((candidate) => candidate.key === nextKey) : -1;
|
|
340
407
|
return index <= 0 ? candidates : [...candidates.slice(index), ...candidates.slice(0, index)];
|
|
341
408
|
}
|
|
342
|
-
function realpathOrNull(input, cache) {
|
|
343
|
-
const cached = cache.get(input);
|
|
344
|
-
if (cached !== undefined)
|
|
345
|
-
return cached;
|
|
346
|
-
let resolved = null;
|
|
347
|
-
try {
|
|
348
|
-
resolved = path.isAbsolute(input) ? fs.realpathSync.native(input) : null;
|
|
349
|
-
}
|
|
350
|
-
catch {
|
|
351
|
-
resolved = null;
|
|
352
|
-
}
|
|
353
|
-
cache.set(input, resolved);
|
|
354
|
-
return resolved;
|
|
355
|
-
}
|
|
356
409
|
/** @internal */
|
|
357
410
|
function resolveRoots(workspacePaths, includeWorktrees, realpaths) {
|
|
358
|
-
|
|
359
|
-
const listingRoots = new Set();
|
|
360
|
-
const add = (candidate) => {
|
|
361
|
-
const real = realpathOrNull(candidate, realpaths);
|
|
362
|
-
if (!real)
|
|
363
|
-
return;
|
|
364
|
-
roots.add(real);
|
|
365
|
-
listingRoots.add(real);
|
|
366
|
-
listingRoots.add(path.resolve(candidate));
|
|
367
|
-
};
|
|
368
|
-
for (const workspacePath of workspacePaths) {
|
|
369
|
-
if (typeof workspacePath !== 'string' || !path.isAbsolute(workspacePath))
|
|
370
|
-
continue;
|
|
371
|
-
add(workspacePath);
|
|
372
|
-
if (!includeWorktrees)
|
|
373
|
-
continue;
|
|
374
|
-
const real = realpathOrNull(workspacePath, realpaths);
|
|
375
|
-
if (!real)
|
|
376
|
-
continue;
|
|
377
|
-
const mainRepo = (0, sessionPathResolver_1.resolveWorktreeMainRepo)(real) ?? real;
|
|
378
|
-
add(mainRepo);
|
|
379
|
-
for (const sibling of (0, sessionPathResolver_1.discoverWorktreeSiblings)(mainRepo))
|
|
380
|
-
add(sibling);
|
|
381
|
-
}
|
|
382
|
-
return { roots: [...roots], listingRoots: [...listingRoots] };
|
|
411
|
+
return (0, workspaceRoots_1.resolveWorkspaceRoots)(workspacePaths, { includeWorktrees }, realpaths);
|
|
383
412
|
}
|
|
384
413
|
/** Fail-closed scope check on a recorded working directory. */
|
|
385
414
|
function scopedCwd(cwd, roots, realpaths) {
|
|
386
415
|
if (typeof cwd !== 'string' || cwd.length === 0)
|
|
387
416
|
return null;
|
|
388
|
-
const real = realpathOrNull(cwd, realpaths);
|
|
417
|
+
const real = (0, workspaceRoots_1.realpathOrNull)(cwd, realpaths);
|
|
389
418
|
if (!real)
|
|
390
419
|
return null;
|
|
391
420
|
for (const root of roots) {
|
|
@@ -405,11 +434,12 @@ async function listCandidates(providers, listingRoots, sinceMs) {
|
|
|
405
434
|
if (!ALL_PROVIDERS.includes(provider))
|
|
406
435
|
continue;
|
|
407
436
|
// Listings are only candidate supersets; scope is re-checked per prompt.
|
|
408
|
-
const
|
|
437
|
+
const list = provider === 'claude-code' ? claudeListing_1.listClaudeSessionFilesAsync : codexRollouts_1.listCodexSessionFilesAsync;
|
|
438
|
+
const cache = new directoryListingCache_1.DirectoryListingCache();
|
|
409
439
|
for (const root of listingRoots) {
|
|
410
440
|
let files;
|
|
411
441
|
try {
|
|
412
|
-
files =
|
|
442
|
+
files = await list(root, listOptions, cache);
|
|
413
443
|
}
|
|
414
444
|
catch {
|
|
415
445
|
files = [];
|
|
@@ -426,18 +456,48 @@ async function listCandidates(providers, listingRoots, sinceMs) {
|
|
|
426
456
|
});
|
|
427
457
|
}
|
|
428
458
|
}
|
|
429
|
-
source.dispose();
|
|
430
459
|
}
|
|
431
460
|
return [...byPath.values()].sort((left, right) => compareStrings(left.provider, right.provider) ||
|
|
432
461
|
compareStrings(left.sessionId, right.sessionId) ||
|
|
433
462
|
compareStrings(left.key, right.key));
|
|
434
463
|
}
|
|
464
|
+
/** True when the file's first bytes still match a recorded head. */
|
|
465
|
+
async function fileStartsWith(filePath, head) {
|
|
466
|
+
let handle;
|
|
467
|
+
try {
|
|
468
|
+
handle = await fs.promises.open(filePath, 'r');
|
|
469
|
+
return (0, fileHead_1.headMatches)(head, await readAt(handle, 0, Math.min(fileHead_1.HEAD_BYTES, head.bytes)));
|
|
470
|
+
}
|
|
471
|
+
catch {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
finally {
|
|
475
|
+
await handle?.close();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Cursor entries whose file is no longer listed, by `provider:sessionId`, for
|
|
480
|
+
* sessions that are listed again under another path.
|
|
481
|
+
*/
|
|
482
|
+
function movedSessionKeys(previous, candidates) {
|
|
483
|
+
const listedKeys = new Set(candidates.map((candidate) => candidate.key));
|
|
484
|
+
const listedIds = new Set(candidates.map((candidate) => `${candidate.provider}:${candidate.sessionId}`));
|
|
485
|
+
const moved = new Map();
|
|
486
|
+
for (const [key, value] of Object.entries(previous)) {
|
|
487
|
+
if (listedKeys.has(key))
|
|
488
|
+
continue;
|
|
489
|
+
const session = validSession(value);
|
|
490
|
+
if (!session)
|
|
491
|
+
continue;
|
|
492
|
+
const id = `${session.provider}:${session.sessionId}`;
|
|
493
|
+
if (listedIds.has(id) && !moved.has(id))
|
|
494
|
+
moved.set(id, key);
|
|
495
|
+
}
|
|
496
|
+
return moved;
|
|
497
|
+
}
|
|
435
498
|
function hashPath(filePath) {
|
|
436
499
|
return (0, crypto_1.createHash)('sha256').update(filePath).digest('hex').slice(0, 12);
|
|
437
500
|
}
|
|
438
|
-
function hashBytes(buffer) {
|
|
439
|
-
return (0, crypto_1.createHash)('sha256').update(buffer).digest('hex').slice(0, 32);
|
|
440
|
-
}
|
|
441
501
|
async function readAt(handle, offset, length) {
|
|
442
502
|
const buffer = Buffer.alloc(length);
|
|
443
503
|
let read = 0;
|
|
@@ -457,7 +517,7 @@ function yieldToEventLoop() {
|
|
|
457
517
|
* Returns the head to store, or null when the file was truncated or rewritten.
|
|
458
518
|
*/
|
|
459
519
|
async function verifyFile(handle, size, session) {
|
|
460
|
-
const headBytes = Math.min(HEAD_BYTES, size);
|
|
520
|
+
const headBytes = Math.min(fileHead_1.HEAD_BYTES, size);
|
|
461
521
|
const head = await readAt(handle, 0, headBytes);
|
|
462
522
|
let bytesRead = head.length;
|
|
463
523
|
if (head.length !== headBytes)
|
|
@@ -466,12 +526,8 @@ async function verifyFile(handle, size, session) {
|
|
|
466
526
|
if (session.offset > size)
|
|
467
527
|
return null;
|
|
468
528
|
const known = session.head;
|
|
469
|
-
if (known)
|
|
470
|
-
|
|
471
|
-
return null;
|
|
472
|
-
if (hashBytes(head.subarray(0, known.bytes)) !== known.hash)
|
|
473
|
-
return null;
|
|
474
|
-
}
|
|
529
|
+
if (known && !(0, fileHead_1.headMatches)(known, head))
|
|
530
|
+
return null;
|
|
475
531
|
if (session.offset > 0 && !session.skipping) {
|
|
476
532
|
const before = await readAt(handle, session.offset - 1, 1);
|
|
477
533
|
bytesRead += before.length;
|
|
@@ -479,7 +535,7 @@ async function verifyFile(handle, size, session) {
|
|
|
479
535
|
return null;
|
|
480
536
|
}
|
|
481
537
|
}
|
|
482
|
-
return { head:
|
|
538
|
+
return { head: (0, fileHead_1.fileHeadOf)(head), bytesRead };
|
|
483
539
|
}
|
|
484
540
|
/** @internal */
|
|
485
541
|
async function scanFile(candidate, stat, prior, budget, context) {
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { AccountProviderId } from './providerIds';
|
|
2
|
-
export
|
|
2
|
+
export declare const PROVIDER_CREDENTIAL_KINDS: readonly ["oauth", "api-key", "unknown"];
|
|
3
|
+
export type ProviderCredentialKind = (typeof PROVIDER_CREDENTIAL_KINDS)[number];
|
|
4
|
+
export declare const PROVIDER_AUTHENTICATION_STATES: readonly ["authenticated", "missing", "signed-out", "expired", "rejected", "unknown"];
|
|
5
|
+
export declare const PROVIDER_AUTHENTICATION_SOURCES: readonly ["local-check", "provider-response"];
|
|
3
6
|
export interface ProviderAuthenticationEvidence {
|
|
4
7
|
credentialKind: ProviderCredentialKind;
|
|
5
|
-
state:
|
|
8
|
+
state: (typeof PROVIDER_AUTHENTICATION_STATES)[number];
|
|
6
9
|
checkedAt: string;
|
|
7
|
-
source:
|
|
10
|
+
source: (typeof PROVIDER_AUTHENTICATION_SOURCES)[number];
|
|
8
11
|
}
|
|
9
12
|
export interface ProviderFailureInput {
|
|
10
13
|
provider: AccountProviderId;
|
|
@@ -14,8 +17,10 @@ export interface ProviderFailureInput {
|
|
|
14
17
|
/** The caller owns freshness and relevance of this separate observation. */
|
|
15
18
|
authentication?: ProviderAuthenticationEvidence;
|
|
16
19
|
}
|
|
17
|
-
export
|
|
18
|
-
export type
|
|
20
|
+
export declare const PROVIDER_FAILURE_CODES: readonly ["missing_credentials", "oauth_reauthentication_required", "api_credentials_rejected", "authentication_rejected", "invalid_provider_session", "service_unavailable", "connection_failed", "timeout", "rate_limited", "overloaded", "execution_policy_denied", "runtime_unavailable", "context_overflow", "unknown"];
|
|
21
|
+
export type ProviderFailureCode = (typeof PROVIDER_FAILURE_CODES)[number];
|
|
22
|
+
export declare const PROVIDER_RECOVERY_ACTIONS: readonly ["sign_in", "update_credentials", "check_authentication", "start_new_session", "retry_later", "check_connection", "review_execution_policy", "repair_runtime", "reduce_context", "inspect_error"];
|
|
23
|
+
export type ProviderRecoveryAction = (typeof PROVIDER_RECOVERY_ACTIONS)[number];
|
|
19
24
|
export type ProviderRetryAfter = {
|
|
20
25
|
kind: 'delay';
|
|
21
26
|
delayMs: number;
|
|
@@ -23,8 +28,9 @@ export type ProviderRetryAfter = {
|
|
|
23
28
|
kind: 'date';
|
|
24
29
|
at: string;
|
|
25
30
|
};
|
|
31
|
+
export declare const PROVIDER_FAILURE_EVIDENCE_SOURCES: readonly ["structured-error", "http-status", "message", "authentication-check"];
|
|
26
32
|
export interface ProviderFailureEvidence {
|
|
27
|
-
source:
|
|
33
|
+
source: (typeof PROVIDER_FAILURE_EVIDENCE_SOURCES)[number];
|
|
28
34
|
rule: ProviderFailureCode;
|
|
29
35
|
checkedAt?: string;
|
|
30
36
|
}
|
package/dist/providerFailure.js
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROVIDER_FAILURE_EVIDENCE_SOURCES = exports.PROVIDER_RECOVERY_ACTIONS = exports.PROVIDER_FAILURE_CODES = exports.PROVIDER_AUTHENTICATION_SOURCES = exports.PROVIDER_AUTHENTICATION_STATES = exports.PROVIDER_CREDENTIAL_KINDS = void 0;
|
|
3
4
|
exports.diagnoseProviderFailure = diagnoseProviderFailure;
|
|
5
|
+
exports.PROVIDER_CREDENTIAL_KINDS = ['oauth', 'api-key', 'unknown'];
|
|
6
|
+
exports.PROVIDER_AUTHENTICATION_STATES = [
|
|
7
|
+
'authenticated',
|
|
8
|
+
'missing',
|
|
9
|
+
'signed-out',
|
|
10
|
+
'expired',
|
|
11
|
+
'rejected',
|
|
12
|
+
'unknown',
|
|
13
|
+
];
|
|
14
|
+
exports.PROVIDER_AUTHENTICATION_SOURCES = ['local-check', 'provider-response'];
|
|
15
|
+
exports.PROVIDER_FAILURE_CODES = [
|
|
16
|
+
'missing_credentials',
|
|
17
|
+
'oauth_reauthentication_required',
|
|
18
|
+
'api_credentials_rejected',
|
|
19
|
+
'authentication_rejected',
|
|
20
|
+
'invalid_provider_session',
|
|
21
|
+
'service_unavailable',
|
|
22
|
+
'connection_failed',
|
|
23
|
+
'timeout',
|
|
24
|
+
'rate_limited',
|
|
25
|
+
'overloaded',
|
|
26
|
+
'execution_policy_denied',
|
|
27
|
+
'runtime_unavailable',
|
|
28
|
+
'context_overflow',
|
|
29
|
+
'unknown',
|
|
30
|
+
];
|
|
31
|
+
exports.PROVIDER_RECOVERY_ACTIONS = [
|
|
32
|
+
'sign_in',
|
|
33
|
+
'update_credentials',
|
|
34
|
+
'check_authentication',
|
|
35
|
+
'start_new_session',
|
|
36
|
+
'retry_later',
|
|
37
|
+
'check_connection',
|
|
38
|
+
'review_execution_policy',
|
|
39
|
+
'repair_runtime',
|
|
40
|
+
'reduce_context',
|
|
41
|
+
'inspect_error',
|
|
42
|
+
];
|
|
43
|
+
exports.PROVIDER_FAILURE_EVIDENCE_SOURCES = [
|
|
44
|
+
'structured-error',
|
|
45
|
+
'http-status',
|
|
46
|
+
'message',
|
|
47
|
+
'authentication-check',
|
|
48
|
+
];
|
|
4
49
|
function read(value, key) {
|
|
5
50
|
try {
|
|
6
51
|
return value && typeof value === 'object' ? value[key] : undefined;
|
|
@@ -44,7 +44,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.ClaudeCodeProvider = void 0;
|
|
46
46
|
const fs = __importStar(require("fs"));
|
|
47
|
-
const os = __importStar(require("os"));
|
|
48
47
|
const path = __importStar(require("path"));
|
|
49
48
|
const string_decoder_1 = require("string_decoder");
|
|
50
49
|
const sessionContext_1 = require("../context/sessionContext");
|
|
@@ -57,6 +56,8 @@ const sessionPathResolver_1 = require("../parsers/sessionPathResolver");
|
|
|
57
56
|
const subagentScanner_1 = require("../parsers/subagentScanner");
|
|
58
57
|
const modelContext_1 = require("../modelContext");
|
|
59
58
|
const sessionEvent_1 = require("../schemas/sessionEvent");
|
|
59
|
+
const claudePaths_1 = require("../claudePaths");
|
|
60
|
+
const claudeListing_1 = require("./claudeListing");
|
|
60
61
|
/** Type guard for content blocks with a `type` string property */
|
|
61
62
|
function isTypedBlock(block) {
|
|
62
63
|
return (block !== null &&
|
|
@@ -96,22 +97,6 @@ function extractSearchableText(event) {
|
|
|
96
97
|
* worktree suffix of it, or a directory ending in the workspace's basename.
|
|
97
98
|
* Without a workspace every directory matches.
|
|
98
99
|
*/
|
|
99
|
-
function workspaceDirectoryFilter(workspacePath) {
|
|
100
|
-
if (!workspacePath)
|
|
101
|
-
return () => true;
|
|
102
|
-
const encodedWorkspace = (0, sessionPathResolver_1.encodeWorkspacePath)(workspacePath).toLowerCase();
|
|
103
|
-
const workspaceBasename = path
|
|
104
|
-
.basename(workspacePath)
|
|
105
|
-
.replace(/[^a-zA-Z0-9]/g, '-')
|
|
106
|
-
.toLowerCase();
|
|
107
|
-
return (directoryName) => {
|
|
108
|
-
const name = directoryName.toLowerCase();
|
|
109
|
-
return (name === encodedWorkspace ||
|
|
110
|
-
name.startsWith(`${encodedWorkspace}-`) ||
|
|
111
|
-
name === workspaceBasename ||
|
|
112
|
-
name.endsWith(`-${workspaceBasename}`));
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
100
|
function extractClaudeLabelFromPrefix(chunk) {
|
|
116
101
|
for (const line of chunk.split('\n')) {
|
|
117
102
|
const trimmed = line.trim();
|
|
@@ -368,89 +353,12 @@ class ClaudeCodeProvider {
|
|
|
368
353
|
* event; `since` filters files and shares the caveat.
|
|
369
354
|
*/
|
|
370
355
|
async listSessionFilesAsync(workspacePath, options = {}) {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
options.stats.directoriesListed ??= 0;
|
|
374
|
-
options.stats.directoriesStatted ??= 0;
|
|
375
|
-
options.stats.filesStatted ??= 0;
|
|
376
|
-
}
|
|
377
|
-
const root = await this.directoryCache.listDirectory(projectsRoot, () => false, {
|
|
378
|
-
revalidateRecent: options.revalidateRecent,
|
|
379
|
-
stats: options.stats,
|
|
380
|
-
});
|
|
381
|
-
if (!root) {
|
|
382
|
-
this.recordHomeStatus('listSessionFilesAsync');
|
|
383
|
-
return [];
|
|
356
|
+
try {
|
|
357
|
+
return await (0, claudeListing_1.listClaudeSessionFilesAsync)(workspacePath, options, this.directoryCache);
|
|
384
358
|
}
|
|
385
|
-
|
|
386
|
-
? Math.max(0, Math.floor(options.limit))
|
|
387
|
-
: null;
|
|
388
|
-
if (limit === 0) {
|
|
359
|
+
finally {
|
|
389
360
|
this.recordHomeStatus('listSessionFilesAsync');
|
|
390
|
-
return [];
|
|
391
|
-
}
|
|
392
|
-
const since = options.since !== undefined && Number.isFinite(options.since) ? options.since : null;
|
|
393
|
-
const matchesWorkspace = workspaceDirectoryFilter(workspacePath);
|
|
394
|
-
const candidates = [];
|
|
395
|
-
let sinceYield = 0;
|
|
396
|
-
for (const name of root.subdirectories) {
|
|
397
|
-
if (!matchesWorkspace(name))
|
|
398
|
-
continue;
|
|
399
|
-
const directory = path.join(projectsRoot, name);
|
|
400
|
-
try {
|
|
401
|
-
const stat = await fs.promises.stat(directory);
|
|
402
|
-
if (options.stats) {
|
|
403
|
-
options.stats.directoriesStatted = (options.stats.directoriesStatted ?? 0) + 1;
|
|
404
|
-
}
|
|
405
|
-
if (stat.isDirectory())
|
|
406
|
-
candidates.push({ directory, stat });
|
|
407
|
-
}
|
|
408
|
-
catch {
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
if (++sinceYield >= 50) {
|
|
412
|
-
sinceYield = 0;
|
|
413
|
-
await new Promise((resolve) => setImmediate(resolve));
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
if (limit !== null)
|
|
417
|
-
candidates.sort((left, right) => right.stat.mtimeMs - left.stat.mtimeMs);
|
|
418
|
-
const byNewest = (left, right) => right.mtime.getTime() - left.mtime.getTime();
|
|
419
|
-
const results = [];
|
|
420
|
-
let cutoffMs = null;
|
|
421
|
-
for (const candidate of candidates) {
|
|
422
|
-
if (limit !== null && cutoffMs !== null && candidate.stat.mtimeMs < cutoffMs)
|
|
423
|
-
break;
|
|
424
|
-
const listing = await this.directoryCache.listDirectory(candidate.directory, (name) => this.isSessionFile(name), {
|
|
425
|
-
dirStat: candidate.stat,
|
|
426
|
-
revalidateRecent: options.revalidateRecent,
|
|
427
|
-
stats: options.stats,
|
|
428
|
-
});
|
|
429
|
-
if (!listing)
|
|
430
|
-
continue;
|
|
431
|
-
for (const [name, stat] of listing.files) {
|
|
432
|
-
if (stat.sizeBytes <= 0)
|
|
433
|
-
continue;
|
|
434
|
-
if (since !== null && stat.mtimeMs < since)
|
|
435
|
-
continue;
|
|
436
|
-
const sessionPath = path.join(candidate.directory, name);
|
|
437
|
-
results.push({
|
|
438
|
-
path: sessionPath,
|
|
439
|
-
mtime: new Date(stat.mtimeMs),
|
|
440
|
-
sizeBytes: stat.sizeBytes,
|
|
441
|
-
sessionId: this.getSessionId(sessionPath),
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
if (limit !== null && results.length >= limit) {
|
|
445
|
-
results.sort(byNewest);
|
|
446
|
-
results.length = limit;
|
|
447
|
-
cutoffMs = results[limit - 1].mtime.getTime();
|
|
448
|
-
}
|
|
449
|
-
await new Promise((resolve) => setImmediate(resolve));
|
|
450
361
|
}
|
|
451
|
-
this.recordHomeStatus('listSessionFilesAsync');
|
|
452
|
-
results.sort(byNewest);
|
|
453
|
-
return limit !== null && results.length > limit ? results.slice(0, limit) : results;
|
|
454
362
|
}
|
|
455
363
|
/**
|
|
456
364
|
* Resolve a recursive-watch event under the projects root with one stat.
|
|
@@ -478,7 +386,7 @@ class ClaudeCodeProvider {
|
|
|
478
386
|
const [directoryName, fileName] = segments;
|
|
479
387
|
if (!this.isSessionFile(fileName))
|
|
480
388
|
return { status: 'ignored' };
|
|
481
|
-
if (!workspaceDirectoryFilter(workspacePath)(directoryName))
|
|
389
|
+
if (!(0, claudeListing_1.workspaceDirectoryFilter)(workspacePath)(directoryName))
|
|
482
390
|
return { status: 'ignored' };
|
|
483
391
|
const sessionId = this.getSessionId(fullPath);
|
|
484
392
|
const stat = await this.directoryCache.refreshFile(fullPath);
|
|
@@ -593,7 +501,7 @@ class ClaudeCodeProvider {
|
|
|
593
501
|
return results;
|
|
594
502
|
}
|
|
595
503
|
getProjectsBaseDir() {
|
|
596
|
-
return
|
|
504
|
+
return (0, claudePaths_1.getClaudeProjectsDir)();
|
|
597
505
|
}
|
|
598
506
|
getWatchRoots() {
|
|
599
507
|
return [this.getProjectsBaseDir()];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code session-file listing, kept apart from the provider class so a
|
|
3
|
+
* caller that only lists files does not bundle the provider's stats,
|
|
4
|
+
* context and transcript code.
|
|
5
|
+
*/
|
|
6
|
+
import { DirectoryListingCache } from './directoryListingCache';
|
|
7
|
+
import type { ListSessionFilesOptions, SessionFileInfo } from './types';
|
|
8
|
+
/** Matches project directory names that may hold sessions for `workspacePath`. */
|
|
9
|
+
export declare function workspaceDirectoryFilter(workspacePath?: string): (directoryName: string) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Enumerate session files across project directories through the
|
|
12
|
+
* directory cache: one stat per project directory, a readdir only for
|
|
13
|
+
* directories whose mtime changed, and a stat only for files new to a
|
|
14
|
+
* changed directory (or recently modified, with `revalidateRecent`).
|
|
15
|
+
*
|
|
16
|
+
* With `limit`, directories are visited newest-mtime first and the walk
|
|
17
|
+
* stops once the remaining directories are older than the newest `limit`
|
|
18
|
+
* files found. A directory's mtime ignores appends, so a cold limited walk
|
|
19
|
+
* can miss a long-running session in an old directory until its next watch
|
|
20
|
+
* event; `since` filters files and shares the caveat.
|
|
21
|
+
*/
|
|
22
|
+
export declare function listClaudeSessionFilesAsync(workspacePath?: string, options?: ListSessionFilesOptions, cache?: DirectoryListingCache): Promise<SessionFileInfo[]>;
|