@herdctl/core 5.6.0 → 5.7.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.
Files changed (54) hide show
  1. package/dist/config/__tests__/merge.test.js +1 -1
  2. package/dist/config/__tests__/merge.test.js.map +1 -1
  3. package/dist/config/schema.d.ts +10 -2
  4. package/dist/config/schema.d.ts.map +1 -1
  5. package/dist/config/schema.js +6 -2
  6. package/dist/config/schema.js.map +1 -1
  7. package/dist/scheduler/schedule-runner.d.ts.map +1 -1
  8. package/dist/scheduler/schedule-runner.js +6 -5
  9. package/dist/scheduler/schedule-runner.js.map +1 -1
  10. package/dist/state/__tests__/jsonl-parser.test.d.ts +5 -0
  11. package/dist/state/__tests__/jsonl-parser.test.d.ts.map +1 -0
  12. package/dist/state/__tests__/jsonl-parser.test.js +307 -0
  13. package/dist/state/__tests__/jsonl-parser.test.js.map +1 -0
  14. package/dist/state/__tests__/session-attribution.test.d.ts +2 -0
  15. package/dist/state/__tests__/session-attribution.test.d.ts.map +1 -0
  16. package/dist/state/__tests__/session-attribution.test.js +567 -0
  17. package/dist/state/__tests__/session-attribution.test.js.map +1 -0
  18. package/dist/state/__tests__/session-discovery.test.d.ts +2 -0
  19. package/dist/state/__tests__/session-discovery.test.d.ts.map +1 -0
  20. package/dist/state/__tests__/session-discovery.test.js +941 -0
  21. package/dist/state/__tests__/session-discovery.test.js.map +1 -0
  22. package/dist/state/__tests__/session-metadata.test.d.ts +2 -0
  23. package/dist/state/__tests__/session-metadata.test.d.ts.map +1 -0
  24. package/dist/state/__tests__/session-metadata.test.js +422 -0
  25. package/dist/state/__tests__/session-metadata.test.js.map +1 -0
  26. package/dist/state/__tests__/tool-parsing.test.d.ts +5 -0
  27. package/dist/state/__tests__/tool-parsing.test.d.ts.map +1 -0
  28. package/dist/state/__tests__/tool-parsing.test.js +315 -0
  29. package/dist/state/__tests__/tool-parsing.test.js.map +1 -0
  30. package/dist/state/index.d.ts +5 -0
  31. package/dist/state/index.d.ts.map +1 -1
  32. package/dist/state/index.js +10 -0
  33. package/dist/state/index.js.map +1 -1
  34. package/dist/state/jsonl-parser.d.ts +115 -0
  35. package/dist/state/jsonl-parser.d.ts.map +1 -0
  36. package/dist/state/jsonl-parser.js +437 -0
  37. package/dist/state/jsonl-parser.js.map +1 -0
  38. package/dist/state/session-attribution.d.ts +35 -0
  39. package/dist/state/session-attribution.d.ts.map +1 -0
  40. package/dist/state/session-attribution.js +179 -0
  41. package/dist/state/session-attribution.js.map +1 -0
  42. package/dist/state/session-discovery.d.ts +188 -0
  43. package/dist/state/session-discovery.d.ts.map +1 -0
  44. package/dist/state/session-discovery.js +513 -0
  45. package/dist/state/session-discovery.js.map +1 -0
  46. package/dist/state/session-metadata.d.ts +186 -0
  47. package/dist/state/session-metadata.d.ts.map +1 -0
  48. package/dist/state/session-metadata.js +297 -0
  49. package/dist/state/session-metadata.js.map +1 -0
  50. package/dist/state/tool-parsing.d.ts +88 -0
  51. package/dist/state/tool-parsing.d.ts.map +1 -0
  52. package/dist/state/tool-parsing.js +199 -0
  53. package/dist/state/tool-parsing.js.map +1 -0
  54. package/package.json +1 -1
@@ -0,0 +1,513 @@
1
+ /**
2
+ * Session Discovery Service
3
+ *
4
+ * Orchestrates session enumeration by tying together JSONL parsing,
5
+ * session attribution, and CLI session path utilities. Provides cached
6
+ * discovery of Claude Code sessions from the filesystem.
7
+ */
8
+ import { readdir, stat } from "node:fs/promises";
9
+ import os from "node:os";
10
+ import path from "node:path";
11
+ import { encodePathForCli, getCliSessionFile } from "../runner/runtime/cli-session-path.js";
12
+ import { createLogger } from "../utils/logger.js";
13
+ import { extractLastSummary, extractSessionMetadata, extractSessionUsage, isSidechainSession, parseSessionMessages, } from "./jsonl-parser.js";
14
+ import { buildAttributionIndex, } from "./session-attribution.js";
15
+ import { SessionMetadataStore } from "./session-metadata.js";
16
+ // =============================================================================
17
+ // Logger
18
+ // =============================================================================
19
+ const logger = createLogger("SessionDiscoveryService");
20
+ // =============================================================================
21
+ // Helper Functions
22
+ // =============================================================================
23
+ /**
24
+ * Decode an encoded path back to a display path.
25
+ *
26
+ * The encoded path (e.g., "-Users-ed-Code-herdctl") is decoded by:
27
+ * - Replacing leading "-" with "/" (Unix)
28
+ * - Replacing remaining "-" with "/"
29
+ *
30
+ * This is lossy but good enough for display purposes.
31
+ */
32
+ function decodePathForDisplay(encodedPath) {
33
+ // Handle Unix paths: leading "-" becomes "/"
34
+ if (encodedPath.startsWith("-")) {
35
+ return "/" + encodedPath.slice(1).replace(/-/g, "/");
36
+ }
37
+ // Handle Windows paths: "C:-Users-..." becomes "C:/Users/..."
38
+ // Check for drive letter pattern
39
+ if (/^[A-Za-z]:-/.test(encodedPath)) {
40
+ return encodedPath[0] + ":" + encodedPath.slice(2).replace(/-/g, "/");
41
+ }
42
+ // Fallback: just replace all hyphens
43
+ return encodedPath.replace(/-/g, "/");
44
+ }
45
+ /**
46
+ * Check if a path is a temp directory that should be filtered out
47
+ */
48
+ function isTempDirectory(decodedPath) {
49
+ const tmpDir = os.tmpdir();
50
+ const tempPatterns = ["/tmp/", "/private/tmp/", "/var/folders/", tmpDir];
51
+ for (const pattern of tempPatterns) {
52
+ if (decodedPath.startsWith(pattern)) {
53
+ return true;
54
+ }
55
+ }
56
+ return false;
57
+ }
58
+ // =============================================================================
59
+ // SessionDiscoveryService
60
+ // =============================================================================
61
+ /**
62
+ * Service for discovering and enumerating Claude Code sessions.
63
+ *
64
+ * Provides cached access to session files, with attribution from job metadata
65
+ * and platform session files, plus custom names from the session metadata store.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const discovery = new SessionDiscoveryService({
70
+ * stateDir: '/path/to/.herdctl',
71
+ * });
72
+ *
73
+ * // Get sessions for a specific agent
74
+ * const sessions = await discovery.getAgentSessions('my-agent', '/path/to/workspace', false);
75
+ *
76
+ * // Get all sessions grouped by directory
77
+ * const groups = await discovery.getAllSessions([
78
+ * { name: 'agent-1', workingDirectory: '/path/to/project', dockerEnabled: false }
79
+ * ]);
80
+ * ```
81
+ */
82
+ export class SessionDiscoveryService {
83
+ claudeHomePath;
84
+ stateDir;
85
+ cacheTtlMs;
86
+ attributionIndex = null;
87
+ attributionFetchedAt = 0;
88
+ directoryCache = new Map();
89
+ metadataCache = new Map();
90
+ sessionMetadataStore;
91
+ /**
92
+ * Create a new SessionDiscoveryService
93
+ *
94
+ * @param options - Configuration options
95
+ */
96
+ constructor(options) {
97
+ this.claudeHomePath = options.claudeHomePath ?? path.join(os.homedir(), ".claude");
98
+ this.stateDir = options.stateDir;
99
+ this.cacheTtlMs = options.cacheTtlMs ?? 30_000;
100
+ this.sessionMetadataStore = new SessionMetadataStore(options.stateDir);
101
+ }
102
+ /**
103
+ * Check if the attribution index cache is valid
104
+ */
105
+ isAttributionCacheValid() {
106
+ return (this.attributionIndex !== null && Date.now() - this.attributionFetchedAt < this.cacheTtlMs);
107
+ }
108
+ /**
109
+ * Check if a directory cache entry is valid
110
+ */
111
+ isDirectoryCacheValid(entry) {
112
+ return entry !== undefined && Date.now() - entry.fetchedAt < this.cacheTtlMs;
113
+ }
114
+ /**
115
+ * Get or refresh the attribution index
116
+ */
117
+ async getAttributionIndex() {
118
+ if (this.isAttributionCacheValid()) {
119
+ return this.attributionIndex;
120
+ }
121
+ logger.debug("Building attribution index");
122
+ this.attributionIndex = await buildAttributionIndex(this.stateDir);
123
+ this.attributionFetchedAt = Date.now();
124
+ logger.debug(`Attribution index built with ${this.attributionIndex.size} entries`);
125
+ return this.attributionIndex;
126
+ }
127
+ /**
128
+ * List session files in a directory with their modification times
129
+ */
130
+ async listSessionFiles(sessionDir) {
131
+ // Check cache first
132
+ const cached = this.directoryCache.get(sessionDir);
133
+ if (this.isDirectoryCacheValid(cached)) {
134
+ return cached.sessions;
135
+ }
136
+ // Read directory
137
+ let fileNames;
138
+ try {
139
+ fileNames = await readdir(sessionDir);
140
+ }
141
+ catch (error) {
142
+ if (error.code === "ENOENT") {
143
+ logger.debug(`Session directory does not exist: ${sessionDir}`);
144
+ return [];
145
+ }
146
+ logger.warn(`Failed to read session directory: ${sessionDir}: ${error.message}`);
147
+ return [];
148
+ }
149
+ // Filter to .jsonl files and get stats
150
+ const jsonlFiles = fileNames.filter((name) => name.endsWith(".jsonl"));
151
+ const sessions = [];
152
+ for (const fileName of jsonlFiles) {
153
+ const filePath = path.join(sessionDir, fileName);
154
+ try {
155
+ const stats = await stat(filePath);
156
+ sessions.push({
157
+ sessionId: fileName.replace(/\.jsonl$/, ""),
158
+ mtime: stats.mtime,
159
+ });
160
+ }
161
+ catch (error) {
162
+ // File may have been deleted between readdir and stat
163
+ logger.debug(`Failed to stat session file: ${filePath}: ${error.message}`);
164
+ }
165
+ }
166
+ // Sort by mtime descending (newest first)
167
+ sessions.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
168
+ // Cache the result
169
+ this.directoryCache.set(sessionDir, {
170
+ sessions,
171
+ fetchedAt: Date.now(),
172
+ });
173
+ return sessions;
174
+ }
175
+ /**
176
+ * Resolve the auto-generated name for a session.
177
+ *
178
+ * Checks if the cached autoName is still valid (based on file mtime).
179
+ * If not, extracts a new name from the JSONL summary field.
180
+ *
181
+ * @param agentName - The agent's qualified name (use "adhoc" for unattributed sessions)
182
+ * @param sessionId - The session ID
183
+ * @param fileMtime - ISO 8601 timestamp of the session file's modification time
184
+ * @param workingDirectory - The session's working directory
185
+ * @returns Object with autoName and whether an update is needed
186
+ */
187
+ async resolveAutoName(agentName, sessionId, fileMtime, workingDirectory) {
188
+ // Check cache
189
+ const cached = await this.sessionMetadataStore.getAutoName(agentName, sessionId);
190
+ if (cached?.autoNameMtime && cached.autoNameMtime >= fileMtime) {
191
+ // Cache is valid
192
+ return { autoName: cached.autoName, needsUpdate: false };
193
+ }
194
+ // Need to extract from JSONL
195
+ const filePath = getCliSessionFile(workingDirectory, sessionId);
196
+ const summary = await extractLastSummary(filePath);
197
+ if (summary) {
198
+ return { autoName: summary, needsUpdate: true };
199
+ }
200
+ return { autoName: undefined, needsUpdate: false };
201
+ }
202
+ /**
203
+ * Get sessions for a specific agent.
204
+ *
205
+ * Returns sessions from the agent's working directory, attributed and
206
+ * enriched with custom names from the metadata store.
207
+ *
208
+ * @param agentName - The agent's qualified name
209
+ * @param workingDirectory - The agent's working directory
210
+ * @param dockerEnabled - Whether Docker is enabled for the agent (affects resumability)
211
+ * @param options - Optional settings (limit for top-N optimization)
212
+ * @returns Array of discovered sessions sorted by mtime descending
213
+ */
214
+ async getAgentSessions(agentName, workingDirectory, dockerEnabled, options) {
215
+ const limit = options?.limit;
216
+ const encodedPath = encodePathForCli(workingDirectory);
217
+ const sessionDir = path.join(this.claudeHomePath, "projects", encodedPath);
218
+ logger.debug(`Getting sessions for agent ${agentName}`, { sessionDir });
219
+ // Get session files (already sorted by mtime descending)
220
+ const sessionFiles = await this.listSessionFiles(sessionDir);
221
+ if (sessionFiles.length === 0) {
222
+ return [];
223
+ }
224
+ // Only enrich the top N sessions when limit is set
225
+ const filesToEnrich = limit !== undefined ? sessionFiles.slice(0, limit) : sessionFiles;
226
+ // Get attribution index
227
+ const attributionIndex = await this.getAttributionIndex();
228
+ // Build discovered sessions and collect autoName updates
229
+ const sessions = [];
230
+ const autoNameUpdates = [];
231
+ for (const { sessionId, mtime } of filesToEnrich) {
232
+ // Filter out sidechain (sub-agent) sessions. Claude Code marks sessions
233
+ // as sidechain when they're Task tool sub-agents or when --resume is used.
234
+ // These are mostly prompt-cache warmup sessions ("Warmup" + single response)
235
+ // that clutter the UI with no useful content. We check only the first JSONL
236
+ // line so this is O(1) per file.
237
+ const filePath = getCliSessionFile(workingDirectory, sessionId);
238
+ if (await isSidechainSession(filePath)) {
239
+ continue;
240
+ }
241
+ const attribution = attributionIndex.getAttribute(sessionId);
242
+ // Only show sessions that are attributed to this specific agent.
243
+ // When multiple agents share a working directory, this prevents the same
244
+ // native CLI sessions from appearing under every agent. Unattributed sessions
245
+ // are still visible in the global recent sessions list and All Chats view.
246
+ if (attribution.agentName !== agentName) {
247
+ continue;
248
+ }
249
+ const customName = await this.sessionMetadataStore.getCustomName(agentName, sessionId);
250
+ const mtimeStr = mtime.toISOString();
251
+ // Resolve autoName with caching
252
+ const { autoName, needsUpdate } = await this.resolveAutoName(agentName, sessionId, mtimeStr, workingDirectory);
253
+ if (needsUpdate && autoName) {
254
+ autoNameUpdates.push({ sessionId, autoName, mtime: mtimeStr });
255
+ }
256
+ sessions.push({
257
+ sessionId,
258
+ workingDirectory,
259
+ mtime: mtimeStr,
260
+ origin: attribution.origin,
261
+ agentName: attribution.agentName ?? agentName,
262
+ resumable: !dockerEnabled,
263
+ customName,
264
+ autoName,
265
+ preview: undefined, // Lazy - loaded via getSessionMetadata
266
+ });
267
+ }
268
+ // Batch write any autoName updates
269
+ if (autoNameUpdates.length > 0) {
270
+ await this.sessionMetadataStore.batchSetAutoNames(agentName, autoNameUpdates);
271
+ }
272
+ return sessions;
273
+ }
274
+ /**
275
+ * Get all sessions grouped by working directory.
276
+ *
277
+ * Scans the Claude projects directory and groups sessions by their
278
+ * working directories. Filters out temp directories and enriches
279
+ * sessions with attribution and custom names.
280
+ *
281
+ * When a limit is provided, only the most recent `limit` sessions
282
+ * (by mtime) are enriched with names, avoiding expensive JSONL parsing
283
+ * for sessions that won't be returned.
284
+ *
285
+ * @param agents - Array of known agents for matching sessions
286
+ * @param options - Optional settings (limit for top-N optimization)
287
+ * @returns Array of directory groups sorted by most recent session
288
+ */
289
+ async getAllSessions(agents, options) {
290
+ const limit = options?.limit;
291
+ // Build agent lookup by encoded path
292
+ const agentLookup = new Map();
293
+ for (const agent of agents) {
294
+ const encodedPath = encodePathForCli(agent.workingDirectory);
295
+ agentLookup.set(encodedPath, {
296
+ agentName: agent.name,
297
+ dockerEnabled: agent.dockerEnabled,
298
+ });
299
+ }
300
+ // Scan projects directory
301
+ const projectsDir = path.join(this.claudeHomePath, "projects");
302
+ let encodedPaths;
303
+ try {
304
+ encodedPaths = await readdir(projectsDir);
305
+ }
306
+ catch (error) {
307
+ if (error.code === "ENOENT") {
308
+ logger.debug(`Projects directory does not exist: ${projectsDir}`);
309
+ return [];
310
+ }
311
+ logger.warn(`Failed to read projects directory: ${projectsDir}: ${error.message}`);
312
+ return [];
313
+ }
314
+ // Get attribution index
315
+ const attributionIndex = await this.getAttributionIndex();
316
+ const directories = [];
317
+ for (const encodedPath of encodedPaths) {
318
+ const sessionDir = path.join(projectsDir, encodedPath);
319
+ // Check if it's a directory
320
+ try {
321
+ const stats = await stat(sessionDir);
322
+ if (!stats.isDirectory()) {
323
+ continue;
324
+ }
325
+ }
326
+ catch (error) {
327
+ logger.debug(`Failed to stat: ${sessionDir}: ${error.message}`);
328
+ continue;
329
+ }
330
+ // Decode path for display and filtering
331
+ const decodedPath = decodePathForDisplay(encodedPath);
332
+ // Filter out temp directories
333
+ if (isTempDirectory(decodedPath)) {
334
+ logger.debug(`Skipping temp directory: ${decodedPath}`);
335
+ continue;
336
+ }
337
+ // Get session files (already sorted by mtime descending)
338
+ const sessionFiles = await this.listSessionFiles(sessionDir);
339
+ if (sessionFiles.length === 0) {
340
+ continue;
341
+ }
342
+ // Check if this matches a known agent
343
+ const agentMatch = agentLookup.get(encodedPath);
344
+ const agentName = agentMatch?.agentName;
345
+ const dockerEnabled = agentMatch?.dockerEnabled ?? false;
346
+ const metadataKey = agentName ?? "adhoc";
347
+ directories.push({
348
+ encodedPath,
349
+ decodedPath,
350
+ agentName,
351
+ metadataKey,
352
+ dockerEnabled,
353
+ sessionFiles,
354
+ });
355
+ }
356
+ // Phase 2: If limit is set, find the top N sessions by mtime across all directories
357
+ // Each directory's sessionFiles are already sorted by mtime descending,
358
+ // so we merge-select the top N using pointers into each sorted list.
359
+ let selectedSessionIds;
360
+ if (limit !== undefined) {
361
+ // Merge pointers: index into each directory's sorted sessionFiles
362
+ const pointers = directories.map(() => 0);
363
+ selectedSessionIds = new Set();
364
+ for (let picked = 0; picked < limit; picked++) {
365
+ let bestDir = -1;
366
+ let bestMtime = null;
367
+ for (let d = 0; d < directories.length; d++) {
368
+ const dir = directories[d];
369
+ if (pointers[d] >= dir.sessionFiles.length)
370
+ continue;
371
+ const candidate = dir.sessionFiles[pointers[d]];
372
+ if (bestMtime === null || candidate.mtime > bestMtime) {
373
+ bestMtime = candidate.mtime;
374
+ bestDir = d;
375
+ }
376
+ }
377
+ if (bestDir === -1)
378
+ break; // No more sessions
379
+ selectedSessionIds.add(directories[bestDir].sessionFiles[pointers[bestDir]].sessionId);
380
+ pointers[bestDir]++;
381
+ }
382
+ }
383
+ // Phase 3: Enrich sessions (only selected ones when limit is set)
384
+ const groups = [];
385
+ for (const dir of directories) {
386
+ const sessions = [];
387
+ const autoNameUpdates = [];
388
+ for (const { sessionId, mtime } of dir.sessionFiles) {
389
+ // Skip sessions not in the selected set when limit is active
390
+ if (selectedSessionIds && !selectedSessionIds.has(sessionId)) {
391
+ continue;
392
+ }
393
+ // Filter out sidechain (sub-agent) sessions — see comment in getAgentSessions()
394
+ const filePath = getCliSessionFile(dir.decodedPath, sessionId);
395
+ if (await isSidechainSession(filePath)) {
396
+ continue;
397
+ }
398
+ const attribution = attributionIndex.getAttribute(sessionId);
399
+ const mtimeStr = mtime.toISOString();
400
+ // Get custom name (works for both attributed and unattributed sessions)
401
+ const customName = await this.sessionMetadataStore.getCustomName(dir.metadataKey, sessionId);
402
+ // Resolve autoName with caching
403
+ const { autoName, needsUpdate } = await this.resolveAutoName(dir.metadataKey, sessionId, mtimeStr, dir.decodedPath);
404
+ if (needsUpdate && autoName) {
405
+ autoNameUpdates.push({ sessionId, autoName, mtime: mtimeStr });
406
+ }
407
+ sessions.push({
408
+ sessionId,
409
+ workingDirectory: dir.decodedPath,
410
+ mtime: mtimeStr,
411
+ origin: attribution.origin,
412
+ agentName: attribution.agentName ?? dir.agentName,
413
+ resumable: !dir.dockerEnabled,
414
+ customName,
415
+ autoName,
416
+ preview: undefined,
417
+ });
418
+ }
419
+ // Batch write any autoName updates for this directory
420
+ if (autoNameUpdates.length > 0) {
421
+ await this.sessionMetadataStore.batchSetAutoNames(dir.metadataKey, autoNameUpdates);
422
+ }
423
+ if (sessions.length > 0) {
424
+ groups.push({
425
+ workingDirectory: dir.decodedPath,
426
+ encodedPath: dir.encodedPath,
427
+ agentName: dir.agentName,
428
+ sessionCount: dir.sessionFiles.length,
429
+ sessions,
430
+ });
431
+ }
432
+ }
433
+ // Sort groups by most recent session mtime descending
434
+ groups.sort((a, b) => {
435
+ const aLatest = a.sessions[0]?.mtime ?? "";
436
+ const bLatest = b.sessions[0]?.mtime ?? "";
437
+ return bLatest.localeCompare(aLatest);
438
+ });
439
+ return groups;
440
+ }
441
+ /**
442
+ * Get parsed chat messages from a session.
443
+ *
444
+ * Delegates to the JSONL parser.
445
+ *
446
+ * @param workingDirectory - The session's working directory
447
+ * @param sessionId - The session ID
448
+ * @returns Array of chat messages
449
+ */
450
+ async getSessionMessages(workingDirectory, sessionId) {
451
+ const filePath = getCliSessionFile(workingDirectory, sessionId);
452
+ return parseSessionMessages(filePath);
453
+ }
454
+ /**
455
+ * Get metadata for a session.
456
+ *
457
+ * Caches the result for efficiency when called repeatedly.
458
+ *
459
+ * @param workingDirectory - The session's working directory
460
+ * @param sessionId - The session ID
461
+ * @returns Session metadata
462
+ */
463
+ async getSessionMetadata(workingDirectory, sessionId) {
464
+ const filePath = getCliSessionFile(workingDirectory, sessionId);
465
+ // Check cache
466
+ const cached = this.metadataCache.get(filePath);
467
+ if (cached !== undefined) {
468
+ return cached;
469
+ }
470
+ // Extract metadata
471
+ const metadata = await extractSessionMetadata(filePath);
472
+ // Cache and return
473
+ this.metadataCache.set(filePath, metadata);
474
+ return metadata;
475
+ }
476
+ /**
477
+ * Get usage data for a session.
478
+ *
479
+ * Delegates to the JSONL parser.
480
+ *
481
+ * @param workingDirectory - The session's working directory
482
+ * @param sessionId - The session ID
483
+ * @returns Session usage data
484
+ */
485
+ async getSessionUsage(workingDirectory, sessionId) {
486
+ const filePath = getCliSessionFile(workingDirectory, sessionId);
487
+ return extractSessionUsage(filePath);
488
+ }
489
+ /**
490
+ * Invalidate cached data.
491
+ *
492
+ * If a working directory is provided, only that directory's cache entry
493
+ * is cleared. Otherwise, all caches are cleared.
494
+ *
495
+ * @param workingDirectory - Optional working directory to clear cache for
496
+ */
497
+ invalidateCache(workingDirectory) {
498
+ if (workingDirectory !== undefined) {
499
+ const encodedPath = encodePathForCli(workingDirectory);
500
+ const sessionDir = path.join(this.claudeHomePath, "projects", encodedPath);
501
+ this.directoryCache.delete(sessionDir);
502
+ logger.debug(`Invalidated cache for directory: ${sessionDir}`);
503
+ }
504
+ else {
505
+ this.directoryCache.clear();
506
+ this.attributionIndex = null;
507
+ this.attributionFetchedAt = 0;
508
+ this.metadataCache.clear();
509
+ logger.debug("Invalidated all caches");
510
+ }
511
+ }
512
+ }
513
+ //# sourceMappingURL=session-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-discovery.js","sourceRoot":"","sources":["../../src/state/session-discovery.ts"],"names":[],"mappings":"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"}