@roomi-fields/notebooklm-mcp 1.1.2

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 (67) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +548 -0
  3. package/dist/auth/auth-manager.d.ts +139 -0
  4. package/dist/auth/auth-manager.d.ts.map +1 -0
  5. package/dist/auth/auth-manager.js +981 -0
  6. package/dist/auth/auth-manager.js.map +1 -0
  7. package/dist/config.d.ts +89 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +216 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/errors.d.ts +26 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +41 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/http-wrapper.d.ts +8 -0
  16. package/dist/http-wrapper.d.ts.map +1 -0
  17. package/dist/http-wrapper.js +221 -0
  18. package/dist/http-wrapper.js.map +1 -0
  19. package/dist/index.d.ts +32 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +499 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/library/notebook-library.d.ts +81 -0
  24. package/dist/library/notebook-library.d.ts.map +1 -0
  25. package/dist/library/notebook-library.js +362 -0
  26. package/dist/library/notebook-library.js.map +1 -0
  27. package/dist/library/types.d.ts +67 -0
  28. package/dist/library/types.d.ts.map +1 -0
  29. package/dist/library/types.js +8 -0
  30. package/dist/library/types.js.map +1 -0
  31. package/dist/session/browser-session.d.ts +108 -0
  32. package/dist/session/browser-session.d.ts.map +1 -0
  33. package/dist/session/browser-session.js +630 -0
  34. package/dist/session/browser-session.js.map +1 -0
  35. package/dist/session/session-manager.d.ts +76 -0
  36. package/dist/session/session-manager.d.ts.map +1 -0
  37. package/dist/session/session-manager.js +273 -0
  38. package/dist/session/session-manager.js.map +1 -0
  39. package/dist/session/shared-context-manager.d.ts +107 -0
  40. package/dist/session/shared-context-manager.d.ts.map +1 -0
  41. package/dist/session/shared-context-manager.js +447 -0
  42. package/dist/session/shared-context-manager.js.map +1 -0
  43. package/dist/tools/index.d.ts +225 -0
  44. package/dist/tools/index.d.ts.map +1 -0
  45. package/dist/tools/index.js +1396 -0
  46. package/dist/tools/index.js.map +1 -0
  47. package/dist/types.d.ts +82 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +5 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/utils/cleanup-manager.d.ts +133 -0
  52. package/dist/utils/cleanup-manager.d.ts.map +1 -0
  53. package/dist/utils/cleanup-manager.js +673 -0
  54. package/dist/utils/cleanup-manager.js.map +1 -0
  55. package/dist/utils/logger.d.ts +61 -0
  56. package/dist/utils/logger.d.ts.map +1 -0
  57. package/dist/utils/logger.js +92 -0
  58. package/dist/utils/logger.js.map +1 -0
  59. package/dist/utils/page-utils.d.ts +54 -0
  60. package/dist/utils/page-utils.d.ts.map +1 -0
  61. package/dist/utils/page-utils.js +422 -0
  62. package/dist/utils/page-utils.js.map +1 -0
  63. package/dist/utils/stealth-utils.d.ts +135 -0
  64. package/dist/utils/stealth-utils.d.ts.map +1 -0
  65. package/dist/utils/stealth-utils.js +398 -0
  66. package/dist/utils/stealth-utils.js.map +1 -0
  67. package/package.json +71 -0
@@ -0,0 +1,673 @@
1
+ /**
2
+ * Cleanup Manager for NotebookLM MCP Server
3
+ *
4
+ * ULTRATHINK EDITION - Complete cleanup across all platforms!
5
+ *
6
+ * Handles safe removal of:
7
+ * - Legacy data from notebooklm-mcp-nodejs
8
+ * - Current installation data
9
+ * - Browser profiles and session data
10
+ * - NPM/NPX cache
11
+ * - Claude CLI MCP logs
12
+ * - Claude Projects cache
13
+ * - Temporary backups
14
+ * - Editor logs (Cursor, VSCode)
15
+ * - Trash files (optional)
16
+ *
17
+ * Platform support: Linux, Windows, macOS
18
+ */
19
+ import fs from "fs/promises";
20
+ import path from "path";
21
+ import { globby } from "globby";
22
+ import envPaths from "env-paths";
23
+ import os from "os";
24
+ import { log } from "./logger.js";
25
+ export class CleanupManager {
26
+ legacyPaths;
27
+ currentPaths;
28
+ homeDir;
29
+ tempDir;
30
+ constructor() {
31
+ // envPaths() does NOT create directories - it just returns path strings
32
+ // IMPORTANT: envPaths() has a default suffix 'nodejs', so we must explicitly disable it!
33
+ // Legacy paths with -nodejs suffix (using default suffix behavior)
34
+ this.legacyPaths = envPaths("notebooklm-mcp"); // This becomes notebooklm-mcp-nodejs by default
35
+ // Current paths without suffix (disable the default suffix with empty string)
36
+ this.currentPaths = envPaths("notebooklm-mcp", { suffix: "" });
37
+ // Platform-agnostic paths
38
+ this.homeDir = os.homedir();
39
+ this.tempDir = os.tmpdir();
40
+ }
41
+ // ============================================================================
42
+ // Platform-Specific Path Resolution
43
+ // ============================================================================
44
+ /**
45
+ * Get NPM cache directory (platform-specific)
46
+ */
47
+ getNpmCachePath() {
48
+ return path.join(this.homeDir, ".npm");
49
+ }
50
+ /**
51
+ * Get Claude CLI cache directory (platform-specific)
52
+ */
53
+ getClaudeCliCachePath() {
54
+ const platform = process.platform;
55
+ if (platform === "win32") {
56
+ const localAppData = process.env.LOCALAPPDATA || path.join(this.homeDir, "AppData", "Local");
57
+ return path.join(localAppData, "claude-cli-nodejs");
58
+ }
59
+ else if (platform === "darwin") {
60
+ return path.join(this.homeDir, "Library", "Caches", "claude-cli-nodejs");
61
+ }
62
+ else {
63
+ // Linux and others
64
+ return path.join(this.homeDir, ".cache", "claude-cli-nodejs");
65
+ }
66
+ }
67
+ /**
68
+ * Get Claude projects directory (platform-specific)
69
+ */
70
+ getClaudeProjectsPath() {
71
+ const platform = process.platform;
72
+ if (platform === "win32") {
73
+ const appData = process.env.APPDATA || path.join(this.homeDir, "AppData", "Roaming");
74
+ return path.join(appData, ".claude", "projects");
75
+ }
76
+ else if (platform === "darwin") {
77
+ return path.join(this.homeDir, "Library", "Application Support", "claude", "projects");
78
+ }
79
+ else {
80
+ // Linux and others
81
+ return path.join(this.homeDir, ".claude", "projects");
82
+ }
83
+ }
84
+ /**
85
+ * Get editor config paths (Cursor, VSCode)
86
+ */
87
+ getEditorConfigPaths() {
88
+ const platform = process.platform;
89
+ const paths = [];
90
+ if (platform === "win32") {
91
+ const appData = process.env.APPDATA || path.join(this.homeDir, "AppData", "Roaming");
92
+ paths.push(path.join(appData, "Cursor", "logs"), path.join(appData, "Code", "logs"));
93
+ }
94
+ else if (platform === "darwin") {
95
+ paths.push(path.join(this.homeDir, "Library", "Application Support", "Cursor", "logs"), path.join(this.homeDir, "Library", "Application Support", "Code", "logs"));
96
+ }
97
+ else {
98
+ // Linux
99
+ paths.push(path.join(this.homeDir, ".config", "Cursor", "logs"), path.join(this.homeDir, ".config", "Code", "logs"));
100
+ }
101
+ return paths;
102
+ }
103
+ /**
104
+ * Get trash directory (platform-specific)
105
+ */
106
+ getTrashPath() {
107
+ const platform = process.platform;
108
+ if (platform === "darwin") {
109
+ return path.join(this.homeDir, ".Trash");
110
+ }
111
+ else if (platform === "linux") {
112
+ return path.join(this.homeDir, ".local", "share", "Trash");
113
+ }
114
+ else {
115
+ // Windows Recycle Bin is complex, skip for now
116
+ return null;
117
+ }
118
+ }
119
+ /**
120
+ * Get manual legacy config paths that might not be caught by envPaths
121
+ * This ensures we catch ALL legacy installations including old config.json files
122
+ */
123
+ getManualLegacyPaths() {
124
+ const paths = [];
125
+ const platform = process.platform;
126
+ if (platform === "linux") {
127
+ // Linux-specific paths
128
+ paths.push(path.join(this.homeDir, ".config", "notebooklm-mcp"), path.join(this.homeDir, ".config", "notebooklm-mcp-nodejs"), path.join(this.homeDir, ".local", "share", "notebooklm-mcp"), path.join(this.homeDir, ".local", "share", "notebooklm-mcp-nodejs"), path.join(this.homeDir, ".cache", "notebooklm-mcp"), path.join(this.homeDir, ".cache", "notebooklm-mcp-nodejs"), path.join(this.homeDir, ".local", "state", "notebooklm-mcp"), path.join(this.homeDir, ".local", "state", "notebooklm-mcp-nodejs"));
129
+ }
130
+ else if (platform === "darwin") {
131
+ // macOS-specific paths
132
+ paths.push(path.join(this.homeDir, "Library", "Application Support", "notebooklm-mcp"), path.join(this.homeDir, "Library", "Application Support", "notebooklm-mcp-nodejs"), path.join(this.homeDir, "Library", "Preferences", "notebooklm-mcp"), path.join(this.homeDir, "Library", "Preferences", "notebooklm-mcp-nodejs"), path.join(this.homeDir, "Library", "Caches", "notebooklm-mcp"), path.join(this.homeDir, "Library", "Caches", "notebooklm-mcp-nodejs"), path.join(this.homeDir, "Library", "Logs", "notebooklm-mcp"), path.join(this.homeDir, "Library", "Logs", "notebooklm-mcp-nodejs"));
133
+ }
134
+ else if (platform === "win32") {
135
+ // Windows-specific paths
136
+ const localAppData = process.env.LOCALAPPDATA || path.join(this.homeDir, "AppData", "Local");
137
+ const appData = process.env.APPDATA || path.join(this.homeDir, "AppData", "Roaming");
138
+ paths.push(path.join(localAppData, "notebooklm-mcp"), path.join(localAppData, "notebooklm-mcp-nodejs"), path.join(appData, "notebooklm-mcp"), path.join(appData, "notebooklm-mcp-nodejs"));
139
+ }
140
+ return paths;
141
+ }
142
+ // ============================================================================
143
+ // Search Methods for Different File Types
144
+ // ============================================================================
145
+ /**
146
+ * Find NPM/NPX cache files
147
+ */
148
+ async findNpmCache() {
149
+ const found = [];
150
+ try {
151
+ const npmCachePath = this.getNpmCachePath();
152
+ const npxPath = path.join(npmCachePath, "_npx");
153
+ if (!(await this.pathExists(npxPath))) {
154
+ return found;
155
+ }
156
+ // Search for notebooklm-mcp in npx cache
157
+ const pattern = path.join(npxPath, "*/node_modules/notebooklm-mcp");
158
+ const matches = await globby(pattern, { onlyDirectories: true, absolute: true });
159
+ found.push(...matches);
160
+ }
161
+ catch (error) {
162
+ log.warning(`โš ๏ธ Error searching NPM cache: ${error}`);
163
+ }
164
+ return found;
165
+ }
166
+ /**
167
+ * Find Claude CLI MCP logs
168
+ */
169
+ async findClaudeCliLogs() {
170
+ const found = [];
171
+ try {
172
+ const claudeCliPath = this.getClaudeCliCachePath();
173
+ if (!(await this.pathExists(claudeCliPath))) {
174
+ return found;
175
+ }
176
+ // Search for notebooklm MCP logs
177
+ const patterns = [
178
+ path.join(claudeCliPath, "*/mcp-logs-notebooklm"),
179
+ path.join(claudeCliPath, "*notebooklm-mcp*"),
180
+ ];
181
+ for (const pattern of patterns) {
182
+ const matches = await globby(pattern, { onlyDirectories: true, absolute: true });
183
+ found.push(...matches);
184
+ }
185
+ }
186
+ catch (error) {
187
+ log.warning(`โš ๏ธ Error searching Claude CLI cache: ${error}`);
188
+ }
189
+ return found;
190
+ }
191
+ /**
192
+ * Find Claude projects cache
193
+ */
194
+ async findClaudeProjects() {
195
+ const found = [];
196
+ try {
197
+ const projectsPath = this.getClaudeProjectsPath();
198
+ if (!(await this.pathExists(projectsPath))) {
199
+ return found;
200
+ }
201
+ // Search for notebooklm-mcp projects
202
+ const pattern = path.join(projectsPath, "*notebooklm-mcp*");
203
+ const matches = await globby(pattern, { onlyDirectories: true, absolute: true });
204
+ found.push(...matches);
205
+ }
206
+ catch (error) {
207
+ log.warning(`โš ๏ธ Error searching Claude projects: ${error}`);
208
+ }
209
+ return found;
210
+ }
211
+ /**
212
+ * Find temporary backups
213
+ */
214
+ async findTemporaryBackups() {
215
+ const found = [];
216
+ try {
217
+ // Search for notebooklm backup directories in temp
218
+ const pattern = path.join(this.tempDir, "notebooklm-backup-*");
219
+ const matches = await globby(pattern, { onlyDirectories: true, absolute: true });
220
+ found.push(...matches);
221
+ }
222
+ catch (error) {
223
+ log.warning(`โš ๏ธ Error searching temp backups: ${error}`);
224
+ }
225
+ return found;
226
+ }
227
+ /**
228
+ * Find editor logs (Cursor, VSCode)
229
+ */
230
+ async findEditorLogs() {
231
+ const found = [];
232
+ try {
233
+ const editorPaths = this.getEditorConfigPaths();
234
+ for (const editorPath of editorPaths) {
235
+ if (!(await this.pathExists(editorPath))) {
236
+ continue;
237
+ }
238
+ // Search for MCP notebooklm logs
239
+ const pattern = path.join(editorPath, "**/exthost/**/*notebooklm*.log");
240
+ const matches = await globby(pattern, { onlyFiles: true, absolute: true });
241
+ found.push(...matches);
242
+ }
243
+ }
244
+ catch (error) {
245
+ log.warning(`โš ๏ธ Error searching editor logs: ${error}`);
246
+ }
247
+ return found;
248
+ }
249
+ /**
250
+ * Find trash files
251
+ */
252
+ async findTrashFiles() {
253
+ const found = [];
254
+ try {
255
+ const trashPath = this.getTrashPath();
256
+ if (!trashPath || !(await this.pathExists(trashPath))) {
257
+ return found;
258
+ }
259
+ // Search for notebooklm files in trash
260
+ const patterns = [
261
+ path.join(trashPath, "**/*notebooklm*"),
262
+ ];
263
+ for (const pattern of patterns) {
264
+ const matches = await globby(pattern, { absolute: true });
265
+ found.push(...matches);
266
+ }
267
+ }
268
+ catch (error) {
269
+ log.warning(`โš ๏ธ Error searching trash: ${error}`);
270
+ }
271
+ return found;
272
+ }
273
+ // ============================================================================
274
+ // Main Cleanup Methods
275
+ // ============================================================================
276
+ /**
277
+ * Get all paths that would be deleted for a given mode (with categorization)
278
+ */
279
+ async getCleanupPaths(mode, preserveLibrary = false) {
280
+ const categories = [];
281
+ const allPaths = new Set();
282
+ let totalSizeBytes = 0;
283
+ // Category 1: Legacy Paths (notebooklm-mcp-nodejs & manual legacy paths)
284
+ if (mode === "legacy" || mode === "all" || mode === "deep") {
285
+ const legacyPaths = [];
286
+ let legacyBytes = 0;
287
+ // Check envPaths-based legacy directories
288
+ const legacyDirs = [
289
+ this.legacyPaths.data,
290
+ this.legacyPaths.config,
291
+ this.legacyPaths.cache,
292
+ this.legacyPaths.log,
293
+ this.legacyPaths.temp,
294
+ ];
295
+ for (const dir of legacyDirs) {
296
+ if (await this.pathExists(dir)) {
297
+ const size = await this.getDirectorySize(dir);
298
+ legacyPaths.push(dir);
299
+ legacyBytes += size;
300
+ allPaths.add(dir);
301
+ }
302
+ }
303
+ // CRITICAL: Also check manual legacy paths to catch old config.json files
304
+ // and any paths that envPaths might miss
305
+ const manualLegacyPaths = this.getManualLegacyPaths();
306
+ for (const dir of manualLegacyPaths) {
307
+ if (await this.pathExists(dir) && !allPaths.has(dir)) {
308
+ const size = await this.getDirectorySize(dir);
309
+ legacyPaths.push(dir);
310
+ legacyBytes += size;
311
+ allPaths.add(dir);
312
+ }
313
+ }
314
+ if (legacyPaths.length > 0) {
315
+ categories.push({
316
+ name: "Legacy Installation (notebooklm-mcp-nodejs)",
317
+ description: "Old installation data with -nodejs suffix and legacy config files",
318
+ paths: legacyPaths,
319
+ totalBytes: legacyBytes,
320
+ optional: false,
321
+ });
322
+ totalSizeBytes += legacyBytes;
323
+ }
324
+ }
325
+ // Category 2: Current Installation
326
+ if (mode === "all" || mode === "deep") {
327
+ const currentPaths = [];
328
+ let currentBytes = 0;
329
+ // If preserveLibrary is true, don't delete the data directory itself
330
+ // Instead, only delete subdirectories
331
+ const currentDirs = preserveLibrary
332
+ ? [
333
+ // Don't include data directory to preserve library.json
334
+ this.currentPaths.config,
335
+ this.currentPaths.cache,
336
+ this.currentPaths.log,
337
+ this.currentPaths.temp,
338
+ // Only delete subdirectories, not the parent
339
+ path.join(this.currentPaths.data, "browser_state"),
340
+ path.join(this.currentPaths.data, "chrome_profile"),
341
+ path.join(this.currentPaths.data, "chrome_profile_instances"),
342
+ ]
343
+ : [
344
+ // Delete everything including data directory
345
+ this.currentPaths.data,
346
+ this.currentPaths.config,
347
+ this.currentPaths.cache,
348
+ this.currentPaths.log,
349
+ this.currentPaths.temp,
350
+ // Specific subdirectories (only if parent doesn't exist)
351
+ path.join(this.currentPaths.data, "browser_state"),
352
+ path.join(this.currentPaths.data, "chrome_profile"),
353
+ path.join(this.currentPaths.data, "chrome_profile_instances"),
354
+ ];
355
+ for (const dir of currentDirs) {
356
+ if (await this.pathExists(dir) && !allPaths.has(dir)) {
357
+ const size = await this.getDirectorySize(dir);
358
+ currentPaths.push(dir);
359
+ currentBytes += size;
360
+ allPaths.add(dir);
361
+ }
362
+ }
363
+ if (currentPaths.length > 0) {
364
+ const description = preserveLibrary
365
+ ? "Active installation data and browser profiles (library.json will be preserved)"
366
+ : "Active installation data and browser profiles";
367
+ categories.push({
368
+ name: "Current Installation (notebooklm-mcp)",
369
+ description,
370
+ paths: currentPaths,
371
+ totalBytes: currentBytes,
372
+ optional: false,
373
+ });
374
+ totalSizeBytes += currentBytes;
375
+ }
376
+ }
377
+ // Category 3: NPM Cache
378
+ if (mode === "all" || mode === "deep") {
379
+ const npmPaths = await this.findNpmCache();
380
+ if (npmPaths.length > 0) {
381
+ let npmBytes = 0;
382
+ for (const p of npmPaths) {
383
+ if (!allPaths.has(p)) {
384
+ npmBytes += await this.getDirectorySize(p);
385
+ allPaths.add(p);
386
+ }
387
+ }
388
+ if (npmBytes > 0) {
389
+ categories.push({
390
+ name: "NPM/NPX Cache",
391
+ description: "NPX cached installations of notebooklm-mcp",
392
+ paths: npmPaths,
393
+ totalBytes: npmBytes,
394
+ optional: false,
395
+ });
396
+ totalSizeBytes += npmBytes;
397
+ }
398
+ }
399
+ }
400
+ // Category 4: Claude CLI Logs
401
+ if (mode === "all" || mode === "deep") {
402
+ const claudeCliPaths = await this.findClaudeCliLogs();
403
+ if (claudeCliPaths.length > 0) {
404
+ let claudeCliBytes = 0;
405
+ for (const p of claudeCliPaths) {
406
+ if (!allPaths.has(p)) {
407
+ claudeCliBytes += await this.getDirectorySize(p);
408
+ allPaths.add(p);
409
+ }
410
+ }
411
+ if (claudeCliBytes > 0) {
412
+ categories.push({
413
+ name: "Claude CLI MCP Logs",
414
+ description: "MCP server logs from Claude CLI",
415
+ paths: claudeCliPaths,
416
+ totalBytes: claudeCliBytes,
417
+ optional: false,
418
+ });
419
+ totalSizeBytes += claudeCliBytes;
420
+ }
421
+ }
422
+ }
423
+ // Category 5: Temporary Backups
424
+ if (mode === "all" || mode === "deep") {
425
+ const backupPaths = await this.findTemporaryBackups();
426
+ if (backupPaths.length > 0) {
427
+ let backupBytes = 0;
428
+ for (const p of backupPaths) {
429
+ if (!allPaths.has(p)) {
430
+ backupBytes += await this.getDirectorySize(p);
431
+ allPaths.add(p);
432
+ }
433
+ }
434
+ if (backupBytes > 0) {
435
+ categories.push({
436
+ name: "Temporary Backups",
437
+ description: "Temporary backup directories in system temp",
438
+ paths: backupPaths,
439
+ totalBytes: backupBytes,
440
+ optional: false,
441
+ });
442
+ totalSizeBytes += backupBytes;
443
+ }
444
+ }
445
+ }
446
+ // Category 6: Claude Projects (deep mode only)
447
+ if (mode === "deep") {
448
+ const projectPaths = await this.findClaudeProjects();
449
+ if (projectPaths.length > 0) {
450
+ let projectBytes = 0;
451
+ for (const p of projectPaths) {
452
+ if (!allPaths.has(p)) {
453
+ projectBytes += await this.getDirectorySize(p);
454
+ allPaths.add(p);
455
+ }
456
+ }
457
+ if (projectBytes > 0) {
458
+ categories.push({
459
+ name: "Claude Projects Cache",
460
+ description: "Project-specific cache in Claude config",
461
+ paths: projectPaths,
462
+ totalBytes: projectBytes,
463
+ optional: true,
464
+ });
465
+ totalSizeBytes += projectBytes;
466
+ }
467
+ }
468
+ }
469
+ // Category 7: Editor Logs (deep mode only)
470
+ if (mode === "deep") {
471
+ const editorPaths = await this.findEditorLogs();
472
+ if (editorPaths.length > 0) {
473
+ let editorBytes = 0;
474
+ for (const p of editorPaths) {
475
+ if (!allPaths.has(p)) {
476
+ editorBytes += await this.getFileSize(p);
477
+ allPaths.add(p);
478
+ }
479
+ }
480
+ if (editorBytes > 0) {
481
+ categories.push({
482
+ name: "Editor Logs (Cursor/VSCode)",
483
+ description: "MCP logs from code editors",
484
+ paths: editorPaths,
485
+ totalBytes: editorBytes,
486
+ optional: true,
487
+ });
488
+ totalSizeBytes += editorBytes;
489
+ }
490
+ }
491
+ }
492
+ // Category 8: Trash Files (deep mode only)
493
+ if (mode === "deep") {
494
+ const trashPaths = await this.findTrashFiles();
495
+ if (trashPaths.length > 0) {
496
+ let trashBytes = 0;
497
+ for (const p of trashPaths) {
498
+ if (!allPaths.has(p)) {
499
+ trashBytes += await this.getFileSize(p);
500
+ allPaths.add(p);
501
+ }
502
+ }
503
+ if (trashBytes > 0) {
504
+ categories.push({
505
+ name: "Trash Files",
506
+ description: "Deleted notebooklm files in system trash",
507
+ paths: trashPaths,
508
+ totalBytes: trashBytes,
509
+ optional: true,
510
+ });
511
+ totalSizeBytes += trashBytes;
512
+ }
513
+ }
514
+ }
515
+ return {
516
+ categories,
517
+ totalPaths: Array.from(allPaths),
518
+ totalSizeBytes,
519
+ };
520
+ }
521
+ /**
522
+ * Perform cleanup with safety checks and detailed reporting
523
+ */
524
+ async performCleanup(mode, preserveLibrary = false) {
525
+ log.info(`๐Ÿงน Starting cleanup in "${mode}" mode...`);
526
+ if (preserveLibrary) {
527
+ log.info(`๐Ÿ“š Library preservation enabled - library.json will be kept!`);
528
+ }
529
+ const { categories, totalSizeBytes } = await this.getCleanupPaths(mode, preserveLibrary);
530
+ const deletedPaths = [];
531
+ const failedPaths = [];
532
+ const categorySummary = {};
533
+ // Delete by category
534
+ for (const category of categories) {
535
+ log.info(`\n๐Ÿ“ฆ ${category.name} (${category.paths.length} items, ${this.formatBytes(category.totalBytes)})`);
536
+ if (category.optional) {
537
+ log.warning(` โš ๏ธ Optional category - ${category.description}`);
538
+ }
539
+ let categoryDeleted = 0;
540
+ let categoryBytes = 0;
541
+ for (const itemPath of category.paths) {
542
+ try {
543
+ if (await this.pathExists(itemPath)) {
544
+ const size = await this.getDirectorySize(itemPath);
545
+ log.info(` ๐Ÿ—‘๏ธ Deleting: ${itemPath}`);
546
+ await fs.rm(itemPath, { recursive: true, force: true });
547
+ deletedPaths.push(itemPath);
548
+ categoryDeleted++;
549
+ categoryBytes += size;
550
+ log.success(` โœ… Deleted: ${itemPath} (${this.formatBytes(size)})`);
551
+ }
552
+ }
553
+ catch (error) {
554
+ log.error(` โŒ Failed to delete: ${itemPath} - ${error}`);
555
+ failedPaths.push(itemPath);
556
+ }
557
+ }
558
+ categorySummary[category.name] = {
559
+ count: categoryDeleted,
560
+ bytes: categoryBytes,
561
+ };
562
+ }
563
+ const success = failedPaths.length === 0;
564
+ if (success) {
565
+ log.success(`\nโœ… Cleanup complete! Deleted ${deletedPaths.length} items (${this.formatBytes(totalSizeBytes)})`);
566
+ }
567
+ else {
568
+ log.warning(`\nโš ๏ธ Cleanup completed with ${failedPaths.length} errors`);
569
+ log.success(` Deleted: ${deletedPaths.length} items`);
570
+ log.error(` Failed: ${failedPaths.length} items`);
571
+ }
572
+ return {
573
+ success,
574
+ mode,
575
+ deletedPaths,
576
+ failedPaths,
577
+ totalSizeBytes,
578
+ categorySummary,
579
+ };
580
+ }
581
+ // ============================================================================
582
+ // Helper Methods
583
+ // ============================================================================
584
+ /**
585
+ * Check if a path exists
586
+ */
587
+ async pathExists(dirPath) {
588
+ try {
589
+ await fs.access(dirPath);
590
+ return true;
591
+ }
592
+ catch {
593
+ return false;
594
+ }
595
+ }
596
+ /**
597
+ * Get the size of a single file
598
+ */
599
+ async getFileSize(filePath) {
600
+ try {
601
+ const stats = await fs.stat(filePath);
602
+ return stats.size;
603
+ }
604
+ catch {
605
+ return 0;
606
+ }
607
+ }
608
+ /**
609
+ * Get the total size of a directory (recursive)
610
+ */
611
+ async getDirectorySize(dirPath) {
612
+ try {
613
+ const stats = await fs.stat(dirPath);
614
+ if (!stats.isDirectory()) {
615
+ return stats.size;
616
+ }
617
+ let totalSize = 0;
618
+ const files = await fs.readdir(dirPath);
619
+ for (const file of files) {
620
+ const filePath = path.join(dirPath, file);
621
+ const fileStats = await fs.stat(filePath);
622
+ if (fileStats.isDirectory()) {
623
+ totalSize += await this.getDirectorySize(filePath);
624
+ }
625
+ else {
626
+ totalSize += fileStats.size;
627
+ }
628
+ }
629
+ return totalSize;
630
+ }
631
+ catch {
632
+ return 0;
633
+ }
634
+ }
635
+ /**
636
+ * Format bytes to human-readable string
637
+ */
638
+ formatBytes(bytes) {
639
+ if (bytes === 0)
640
+ return "0 Bytes";
641
+ const k = 1024;
642
+ const sizes = ["Bytes", "KB", "MB", "GB"];
643
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
644
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
645
+ }
646
+ /**
647
+ * Get platform-specific path info
648
+ */
649
+ getPlatformInfo() {
650
+ const platform = process.platform;
651
+ let platformName = "Unknown";
652
+ switch (platform) {
653
+ case "win32":
654
+ platformName = "Windows";
655
+ break;
656
+ case "darwin":
657
+ platformName = "macOS";
658
+ break;
659
+ case "linux":
660
+ platformName = "Linux";
661
+ break;
662
+ }
663
+ return {
664
+ platform: platformName,
665
+ legacyBasePath: this.legacyPaths.data,
666
+ currentBasePath: this.currentPaths.data,
667
+ npmCachePath: this.getNpmCachePath(),
668
+ claudeCliCachePath: this.getClaudeCliCachePath(),
669
+ claudeProjectsPath: this.getClaudeProjectsPath(),
670
+ };
671
+ }
672
+ }
673
+ //# sourceMappingURL=cleanup-manager.js.map