@pan-sec/notebooklm-mcp 1.6.0 → 1.8.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 (134) hide show
  1. package/dist/config.d.ts +4 -0
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +10 -0
  4. package/dist/config.js.map +1 -1
  5. package/dist/events/event-emitter.d.ts +45 -0
  6. package/dist/events/event-emitter.d.ts.map +1 -0
  7. package/dist/events/event-emitter.js +100 -0
  8. package/dist/events/event-emitter.js.map +1 -0
  9. package/dist/events/event-types.d.ts +124 -0
  10. package/dist/events/event-types.d.ts.map +1 -0
  11. package/dist/events/event-types.js +18 -0
  12. package/dist/events/event-types.js.map +1 -0
  13. package/dist/gemini/gemini-client.d.ts +45 -0
  14. package/dist/gemini/gemini-client.d.ts.map +1 -0
  15. package/dist/gemini/gemini-client.js +211 -0
  16. package/dist/gemini/gemini-client.js.map +1 -0
  17. package/dist/gemini/index.d.ts +8 -0
  18. package/dist/gemini/index.d.ts.map +1 -0
  19. package/dist/gemini/index.js +8 -0
  20. package/dist/gemini/index.js.map +1 -0
  21. package/dist/gemini/types.d.ts +136 -0
  22. package/dist/gemini/types.d.ts.map +1 -0
  23. package/dist/gemini/types.js +10 -0
  24. package/dist/gemini/types.js.map +1 -0
  25. package/dist/index.js +76 -3
  26. package/dist/index.js.map +1 -1
  27. package/dist/library/notebook-library.d.ts +25 -2
  28. package/dist/library/notebook-library.d.ts.map +1 -1
  29. package/dist/library/notebook-library.js +142 -2
  30. package/dist/library/notebook-library.js.map +1 -1
  31. package/dist/library/types.d.ts +15 -0
  32. package/dist/library/types.d.ts.map +1 -1
  33. package/dist/notebook-creation/audio-manager.d.ts +56 -0
  34. package/dist/notebook-creation/audio-manager.d.ts.map +1 -0
  35. package/dist/notebook-creation/audio-manager.js +335 -0
  36. package/dist/notebook-creation/audio-manager.js.map +1 -0
  37. package/dist/notebook-creation/discover-creation-flow.d.ts +8 -0
  38. package/dist/notebook-creation/discover-creation-flow.d.ts.map +1 -0
  39. package/dist/notebook-creation/discover-creation-flow.js +177 -0
  40. package/dist/notebook-creation/discover-creation-flow.js.map +1 -0
  41. package/dist/notebook-creation/discover-quota.d.ts +8 -0
  42. package/dist/notebook-creation/discover-quota.d.ts.map +1 -0
  43. package/dist/notebook-creation/discover-quota.js +195 -0
  44. package/dist/notebook-creation/discover-quota.js.map +1 -0
  45. package/dist/notebook-creation/discover-source-dialog.d.ts +8 -0
  46. package/dist/notebook-creation/discover-source-dialog.d.ts.map +1 -0
  47. package/dist/notebook-creation/discover-source-dialog.js +134 -0
  48. package/dist/notebook-creation/discover-source-dialog.js.map +1 -0
  49. package/dist/notebook-creation/discover-sources.d.ts +8 -0
  50. package/dist/notebook-creation/discover-sources.d.ts.map +1 -0
  51. package/dist/notebook-creation/discover-sources.js +273 -0
  52. package/dist/notebook-creation/discover-sources.js.map +1 -0
  53. package/dist/notebook-creation/discover-text-input.d.ts +7 -0
  54. package/dist/notebook-creation/discover-text-input.d.ts.map +1 -0
  55. package/dist/notebook-creation/discover-text-input.js +135 -0
  56. package/dist/notebook-creation/discover-text-input.js.map +1 -0
  57. package/dist/notebook-creation/index.d.ts +12 -0
  58. package/dist/notebook-creation/index.d.ts.map +1 -0
  59. package/dist/notebook-creation/index.js +12 -0
  60. package/dist/notebook-creation/index.js.map +1 -0
  61. package/dist/notebook-creation/notebook-creator.d.ts +95 -0
  62. package/dist/notebook-creation/notebook-creator.d.ts.map +1 -0
  63. package/dist/notebook-creation/notebook-creator.js +689 -0
  64. package/dist/notebook-creation/notebook-creator.js.map +1 -0
  65. package/dist/notebook-creation/notebook-sync.d.ts +93 -0
  66. package/dist/notebook-creation/notebook-sync.d.ts.map +1 -0
  67. package/dist/notebook-creation/notebook-sync.js +370 -0
  68. package/dist/notebook-creation/notebook-sync.js.map +1 -0
  69. package/dist/notebook-creation/run-discovery.d.ts +11 -0
  70. package/dist/notebook-creation/run-discovery.d.ts.map +1 -0
  71. package/dist/notebook-creation/run-discovery.js +151 -0
  72. package/dist/notebook-creation/run-discovery.js.map +1 -0
  73. package/dist/notebook-creation/selector-discovery.d.ts +65 -0
  74. package/dist/notebook-creation/selector-discovery.d.ts.map +1 -0
  75. package/dist/notebook-creation/selector-discovery.js +421 -0
  76. package/dist/notebook-creation/selector-discovery.js.map +1 -0
  77. package/dist/notebook-creation/selectors.d.ts +150 -0
  78. package/dist/notebook-creation/selectors.d.ts.map +1 -0
  79. package/dist/notebook-creation/selectors.js +225 -0
  80. package/dist/notebook-creation/selectors.js.map +1 -0
  81. package/dist/notebook-creation/source-manager.d.ts +73 -0
  82. package/dist/notebook-creation/source-manager.d.ts.map +1 -0
  83. package/dist/notebook-creation/source-manager.js +486 -0
  84. package/dist/notebook-creation/source-manager.js.map +1 -0
  85. package/dist/notebook-creation/test-create.d.ts +8 -0
  86. package/dist/notebook-creation/test-create.d.ts.map +1 -0
  87. package/dist/notebook-creation/test-create.js +72 -0
  88. package/dist/notebook-creation/test-create.js.map +1 -0
  89. package/dist/notebook-creation/types.d.ts +173 -0
  90. package/dist/notebook-creation/types.d.ts.map +1 -0
  91. package/dist/notebook-creation/types.js +5 -0
  92. package/dist/notebook-creation/types.js.map +1 -0
  93. package/dist/quota/index.d.ts +8 -0
  94. package/dist/quota/index.d.ts.map +1 -0
  95. package/dist/quota/index.js +8 -0
  96. package/dist/quota/index.js.map +1 -0
  97. package/dist/quota/quota-manager.d.ts +125 -0
  98. package/dist/quota/quota-manager.d.ts.map +1 -0
  99. package/dist/quota/quota-manager.js +330 -0
  100. package/dist/quota/quota-manager.js.map +1 -0
  101. package/dist/session/session-manager.d.ts +5 -0
  102. package/dist/session/session-manager.d.ts.map +1 -1
  103. package/dist/session/session-manager.js +6 -0
  104. package/dist/session/session-manager.js.map +1 -1
  105. package/dist/tools/definitions/gemini.d.ts +12 -0
  106. package/dist/tools/definitions/gemini.d.ts.map +1 -0
  107. package/dist/tools/definitions/gemini.js +135 -0
  108. package/dist/tools/definitions/gemini.js.map +1 -0
  109. package/dist/tools/definitions/notebook-management.d.ts.map +1 -1
  110. package/dist/tools/definitions/notebook-management.js +525 -0
  111. package/dist/tools/definitions/notebook-management.js.map +1 -1
  112. package/dist/tools/definitions/system.d.ts.map +1 -1
  113. package/dist/tools/definitions/system.js +158 -0
  114. package/dist/tools/definitions/system.js.map +1 -1
  115. package/dist/tools/definitions.d.ts.map +1 -1
  116. package/dist/tools/definitions.js +2 -0
  117. package/dist/tools/definitions.js.map +1 -1
  118. package/dist/tools/handlers.d.ts +257 -0
  119. package/dist/tools/handlers.d.ts.map +1 -1
  120. package/dist/tools/handlers.js +1097 -0
  121. package/dist/tools/handlers.js.map +1 -1
  122. package/dist/webhooks/index.d.ts +8 -0
  123. package/dist/webhooks/index.d.ts.map +1 -0
  124. package/dist/webhooks/index.js +8 -0
  125. package/dist/webhooks/index.js.map +1 -0
  126. package/dist/webhooks/types.d.ts +57 -0
  127. package/dist/webhooks/types.d.ts.map +1 -0
  128. package/dist/webhooks/types.js +5 -0
  129. package/dist/webhooks/types.js.map +1 -0
  130. package/dist/webhooks/webhook-dispatcher.d.ts +120 -0
  131. package/dist/webhooks/webhook-dispatcher.d.ts.map +1 -0
  132. package/dist/webhooks/webhook-dispatcher.js +519 -0
  133. package/dist/webhooks/webhook-dispatcher.js.map +1 -0
  134. package/package.json +2 -1
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Discover Quota/License UI Elements
3
+ *
4
+ * Finds where license tier and usage limits are displayed in NotebookLM.
5
+ * Run: node dist/notebook-creation/discover-quota.js
6
+ */
7
+ import { AuthManager } from "../auth/auth-manager.js";
8
+ import { SharedContextManager } from "../session/shared-context-manager.js";
9
+ import { log } from "../utils/logger.js";
10
+ const NOTEBOOKLM_URL = "https://notebooklm.google.com/";
11
+ async function findQuotaElements(page, description) {
12
+ log.info(`\nšŸ“‹ ${description}:`);
13
+ // Look for quota-related text patterns
14
+ const quotaInfo = await page.evaluate(() => {
15
+ const results = [];
16
+ // Get all text content and look for quota patterns
17
+ // @ts-expect-error - DOM types
18
+ const allElements = document.querySelectorAll('*');
19
+ for (const el of allElements) {
20
+ const text = el.textContent?.trim() || "";
21
+ // Skip very long text (likely containers)
22
+ if (text.length > 200)
23
+ continue;
24
+ // Look for quota-related patterns
25
+ const patterns = [
26
+ /pro/i,
27
+ /free/i,
28
+ /limit/i,
29
+ /\d+\s*\/\s*\d+/, // X/Y format
30
+ /source/i,
31
+ /notebook/i,
32
+ /quota/i,
33
+ /usage/i,
34
+ /upgrade/i,
35
+ /plan/i,
36
+ /subscription/i,
37
+ ];
38
+ for (const pattern of patterns) {
39
+ if (pattern.test(text) && text.length < 100) {
40
+ // Get more context
41
+ const tag = el.tagName;
42
+ const className = el.className?.substring?.(0, 50) || "";
43
+ const ariaLabel = el.getAttribute("aria-label") || "";
44
+ results.push(`[${tag}] "${text}" class="${className}" aria="${ariaLabel}"`);
45
+ break;
46
+ }
47
+ }
48
+ }
49
+ // Deduplicate
50
+ return [...new Set(results)];
51
+ });
52
+ for (const item of quotaInfo) {
53
+ log.dim(` ${item}`);
54
+ }
55
+ }
56
+ async function extractQuotaFromHomepage(page) {
57
+ log.info("\nšŸ” Extracting quota info from homepage...");
58
+ const info = await page.evaluate(() => {
59
+ const result = { rawTexts: [] };
60
+ // Look for PRO/FREE badge
61
+ // @ts-expect-error - DOM types
62
+ const allText = document.body.innerText;
63
+ if (allText.includes("PRO")) {
64
+ result.tier = "pro";
65
+ }
66
+ else if (allText.match(/free\s*(tier|plan|account)/i)) {
67
+ result.tier = "free";
68
+ }
69
+ // Count notebooks in the table
70
+ // @ts-expect-error - DOM types
71
+ const rows = document.querySelectorAll('tr');
72
+ let notebookCount = 0;
73
+ for (const row of rows) {
74
+ if (row.textContent?.includes("Source")) {
75
+ notebookCount++;
76
+ }
77
+ }
78
+ if (notebookCount > 0) {
79
+ result.notebookCount = notebookCount;
80
+ }
81
+ // Look for X/Y patterns (like "0/300")
82
+ const limitMatches = allText.match(/(\d+)\s*\/\s*(\d+)/g) || [];
83
+ result.rawTexts = limitMatches;
84
+ return result;
85
+ });
86
+ log.info(` Tier: ${info.tier || "unknown"}`);
87
+ log.info(` Notebook count: ${info.notebookCount || "unknown"}`);
88
+ log.info(` Limit patterns found: ${info.rawTexts?.join(", ") || "none"}`);
89
+ return info;
90
+ }
91
+ async function checkSettingsPage(page) {
92
+ log.info("\nšŸ“‹ Checking Settings for quota info...");
93
+ // Try to click Settings button
94
+ const settingsClicked = await page.evaluate(() => {
95
+ // @ts-expect-error - DOM types
96
+ const buttons = document.querySelectorAll('button');
97
+ for (const btn of buttons) {
98
+ const aria = btn.getAttribute("aria-label")?.toLowerCase() || "";
99
+ const text = btn.textContent?.toLowerCase() || "";
100
+ if (aria.includes("settings") || text.includes("settings")) {
101
+ btn.click();
102
+ return true;
103
+ }
104
+ }
105
+ return false;
106
+ });
107
+ if (settingsClicked) {
108
+ log.success(" āœ… Clicked Settings button");
109
+ await page.waitForTimeout(2000);
110
+ await findQuotaElements(page, "Settings dialog elements");
111
+ }
112
+ else {
113
+ log.warning(" āš ļø Could not find Settings button");
114
+ }
115
+ }
116
+ async function checkSourceDialog(page) {
117
+ log.info("\nšŸ“‹ Checking Source Dialog for limits...");
118
+ // Create a new notebook to see the source dialog
119
+ const createClicked = await page.evaluate(() => {
120
+ // @ts-expect-error - DOM types
121
+ const buttons = document.querySelectorAll('button');
122
+ for (const btn of buttons) {
123
+ const aria = btn.getAttribute("aria-label") || "";
124
+ if (aria.includes("Create new notebook")) {
125
+ btn.click();
126
+ return true;
127
+ }
128
+ }
129
+ return false;
130
+ });
131
+ if (createClicked) {
132
+ log.success(" āœ… Created new notebook");
133
+ await page.waitForTimeout(3000);
134
+ // Look for source limit indicator
135
+ const sourceLimitInfo = await page.evaluate(() => {
136
+ // @ts-expect-error - DOM types
137
+ const spans = document.querySelectorAll('span');
138
+ for (const span of spans) {
139
+ const text = span.textContent?.trim() || "";
140
+ // Look for "X/Y" pattern near "Source"
141
+ if (text.match(/\d+\s*\/\s*\d+/)) {
142
+ return text;
143
+ }
144
+ if (text.toLowerCase().includes("source limit")) {
145
+ return text;
146
+ }
147
+ }
148
+ return null;
149
+ });
150
+ if (sourceLimitInfo) {
151
+ log.success(` āœ… Source limit indicator: "${sourceLimitInfo}"`);
152
+ }
153
+ await findQuotaElements(page, "Source dialog quota elements");
154
+ }
155
+ }
156
+ async function main() {
157
+ log.info("šŸ” Discovering Quota/License UI Elements...\n");
158
+ const authManager = new AuthManager();
159
+ const contextManager = new SharedContextManager(authManager);
160
+ try {
161
+ const context = await contextManager.getOrCreateContext(true);
162
+ const isAuth = await authManager.validateCookiesExpiry(context);
163
+ if (!isAuth) {
164
+ log.error("āŒ Not authenticated. Run setup_auth first.");
165
+ return;
166
+ }
167
+ const page = await context.newPage();
168
+ // Navigate to NotebookLM homepage
169
+ log.info("šŸ“ Navigating to NotebookLM homepage...");
170
+ await page.goto(NOTEBOOKLM_URL, { waitUntil: "domcontentloaded" });
171
+ await page.waitForLoadState("networkidle").catch(() => { });
172
+ await page.waitForTimeout(3000);
173
+ // 1. Check homepage for quota info
174
+ await findQuotaElements(page, "Homepage quota-related elements");
175
+ await extractQuotaFromHomepage(page);
176
+ // 2. Check Settings dialog
177
+ await checkSettingsPage(page);
178
+ // Close any dialog
179
+ await page.keyboard.press("Escape");
180
+ await page.waitForTimeout(1000);
181
+ // 3. Check source dialog in new notebook
182
+ await checkSourceDialog(page);
183
+ // Keep browser open for inspection
184
+ log.info("\nāœ… Discovery complete. Browser open for 60 seconds...");
185
+ await page.waitForTimeout(60000);
186
+ }
187
+ catch (error) {
188
+ log.error(`āŒ Error: ${error}`);
189
+ }
190
+ finally {
191
+ await contextManager.closeContext();
192
+ }
193
+ }
194
+ main().catch(console.error);
195
+ //# sourceMappingURL=discover-quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-quota.js","sourceRoot":"","sources":["../../src/notebook-creation/discover-quota.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Discover Source Dialog Options
3
+ *
4
+ * Dumps elements available after clicking "Add source" button.
5
+ * Run: node dist/notebook-creation/discover-source-dialog.js
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=discover-source-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-source-dialog.d.ts","sourceRoot":"","sources":["../../src/notebook-creation/discover-source-dialog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Discover Source Dialog Options
3
+ *
4
+ * Dumps elements available after clicking "Add source" button.
5
+ * Run: node dist/notebook-creation/discover-source-dialog.js
6
+ */
7
+ import { AuthManager } from "../auth/auth-manager.js";
8
+ import { SharedContextManager } from "../session/shared-context-manager.js";
9
+ import { log } from "../utils/logger.js";
10
+ const NOTEBOOKLM_URL = "https://notebooklm.google.com/";
11
+ async function dumpElements(page, description) {
12
+ log.info(`\nšŸ“‹ ${description}:`);
13
+ const elements = await page.evaluate(() => {
14
+ const results = [];
15
+ // @ts-expect-error - DOM types
16
+ const els = document.querySelectorAll('button, input, textarea, [role="button"], [role="menuitem"], [role="option"], [role="tab"], a, [contenteditable="true"], span');
17
+ for (const el of els) {
18
+ const text = el.textContent?.trim().substring(0, 60) || "";
19
+ const ariaLabel = el.getAttribute("aria-label") || "";
20
+ const role = el.getAttribute("role") || "";
21
+ const visible = el.offsetParent !== null;
22
+ // Skip empty or hidden elements
23
+ if (!visible)
24
+ continue;
25
+ if (!text && !ariaLabel)
26
+ continue;
27
+ if (text.length > 200)
28
+ continue; // Skip large text blocks
29
+ results.push({
30
+ tag: el.tagName,
31
+ text: text.substring(0, 60),
32
+ ariaLabel: ariaLabel,
33
+ role: role,
34
+ type: el.getAttribute("type") || "",
35
+ });
36
+ }
37
+ return results;
38
+ });
39
+ // Log interesting elements
40
+ for (const el of elements) {
41
+ const info = [];
42
+ if (el.text)
43
+ info.push(`"${el.text}"`);
44
+ if (el.ariaLabel)
45
+ info.push(`aria="${el.ariaLabel}"`);
46
+ if (el.role)
47
+ info.push(`role=${el.role}`);
48
+ if (el.type)
49
+ info.push(`type=${el.type}`);
50
+ if (info.length > 0) {
51
+ log.dim(` ${el.tag}: ${info.join(", ")}`);
52
+ }
53
+ }
54
+ }
55
+ async function main() {
56
+ log.info("šŸ” Discovering Source Dialog Options...\n");
57
+ const authManager = new AuthManager();
58
+ const contextManager = new SharedContextManager(authManager);
59
+ try {
60
+ const context = await contextManager.getOrCreateContext(true);
61
+ const isAuth = await authManager.validateCookiesExpiry(context);
62
+ if (!isAuth) {
63
+ log.error("āŒ Not authenticated. Run setup_auth first.");
64
+ return;
65
+ }
66
+ const page = await context.newPage();
67
+ // Navigate to NotebookLM
68
+ log.info("šŸ“ Navigating to NotebookLM...");
69
+ await page.goto(NOTEBOOKLM_URL, { waitUntil: "domcontentloaded" });
70
+ await page.waitForLoadState("networkidle").catch(() => { });
71
+ await page.waitForTimeout(3000);
72
+ // Click create new notebook first
73
+ log.info("šŸ“ Creating new notebook...");
74
+ const createButton = await page.$('button[aria-label="Create new notebook"]');
75
+ if (createButton) {
76
+ await createButton.click();
77
+ await page.waitForTimeout(3000);
78
+ log.success("āœ… Clicked Create new notebook");
79
+ }
80
+ else {
81
+ log.error("āŒ Could not find Create new notebook button");
82
+ return;
83
+ }
84
+ // Check current URL
85
+ log.info(`šŸ“ Current URL: ${page.url()}`);
86
+ // Now click Add source
87
+ log.info("\nšŸ“ Looking for Add source button...");
88
+ await dumpElements(page, "Before Add source click - looking for add buttons");
89
+ const addSourceButton = await page.$('button[aria-label="Opens the upload source dialogue"]');
90
+ if (addSourceButton) {
91
+ await addSourceButton.click();
92
+ await page.waitForTimeout(2000);
93
+ log.success("āœ… Clicked Add source button");
94
+ }
95
+ else {
96
+ log.warning("āš ļø Primary selector failed, trying fallback...");
97
+ // Try text-based click
98
+ const clicked = await page.evaluate(() => {
99
+ // @ts-expect-error - DOM types
100
+ const buttons = document.querySelectorAll('button, [role="button"]');
101
+ for (const btn of buttons) {
102
+ const text = btn.textContent?.toLowerCase() || "";
103
+ const aria = btn.getAttribute("aria-label")?.toLowerCase() || "";
104
+ if (text.includes("add source") || aria.includes("upload") || aria.includes("source")) {
105
+ btn.click();
106
+ return true;
107
+ }
108
+ }
109
+ return false;
110
+ });
111
+ if (clicked) {
112
+ await page.waitForTimeout(2000);
113
+ log.success("āœ… Clicked Add source (fallback)");
114
+ }
115
+ else {
116
+ log.error("āŒ Could not find Add source button");
117
+ return;
118
+ }
119
+ }
120
+ // Dump source dialog options
121
+ await dumpElements(page, "SOURCE DIALOG OPTIONS (after clicking Add source)");
122
+ // Keep browser open for inspection
123
+ log.info("\nāœ… Discovery complete. Browser open for 60 seconds...");
124
+ await page.waitForTimeout(60000);
125
+ }
126
+ catch (error) {
127
+ log.error(`āŒ Error: ${error}`);
128
+ }
129
+ finally {
130
+ await contextManager.closeContext();
131
+ }
132
+ }
133
+ main().catch(console.error);
134
+ //# sourceMappingURL=discover-source-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-source-dialog.js","sourceRoot":"","sources":["../../src/notebook-creation/discover-source-dialog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Discover Source Management UI Elements
3
+ *
4
+ * Finds selectors for listing, adding, and removing sources in NotebookLM.
5
+ * Run: node dist/notebook-creation/discover-sources.js
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=discover-sources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-sources.d.ts","sourceRoot":"","sources":["../../src/notebook-creation/discover-sources.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,273 @@
1
+ /**
2
+ * Discover Source Management UI Elements
3
+ *
4
+ * Finds selectors for listing, adding, and removing sources in NotebookLM.
5
+ * Run: node dist/notebook-creation/discover-sources.js
6
+ */
7
+ import { AuthManager } from "../auth/auth-manager.js";
8
+ import { SharedContextManager } from "../session/shared-context-manager.js";
9
+ import { log } from "../utils/logger.js";
10
+ // Use a notebook URL with existing sources for discovery
11
+ const TEST_NOTEBOOK_URL = process.env.TEST_NOTEBOOK_URL || "";
12
+ // Future: Interface for discovered selectors (when UI discovery is complete)
13
+ // interface DiscoveredSourceSelectors {
14
+ // sourceListContainer: string | null;
15
+ // sourceItems: string[];
16
+ // sourceTitle: string | null;
17
+ // sourceDeleteButton: string | null;
18
+ // sourceOptionsMenu: string | null;
19
+ // sourceCount: string | null;
20
+ // }
21
+ async function dumpSourceElements(page) {
22
+ return await page.evaluate(() => {
23
+ const results = [];
24
+ // Look for source-related elements
25
+ // @ts-expect-error - DOM types
26
+ const allElements = document.querySelectorAll("*");
27
+ for (const el of allElements) {
28
+ const text = el.textContent?.trim().substring(0, 100) || "";
29
+ const ariaLabel = el.getAttribute("aria-label") || "";
30
+ const classes = el.className || "";
31
+ const tag = el.tagName;
32
+ // Skip if no useful info
33
+ if (!text && !ariaLabel && !classes)
34
+ continue;
35
+ // Look for source-related patterns
36
+ const patterns = [
37
+ /source/i,
38
+ /document/i,
39
+ /upload/i,
40
+ /file/i,
41
+ /delete/i,
42
+ /remove/i,
43
+ /trash/i,
44
+ /more.*options/i,
45
+ /\d+\s*(source|file|document)/i,
46
+ ];
47
+ const isRelevant = patterns.some((p) => p.test(text) || p.test(ariaLabel) || p.test(classes));
48
+ if (isRelevant && text.length < 200) {
49
+ // Get data attributes
50
+ const dataAttrs = {};
51
+ for (const attr of Array.from(el.attributes)) {
52
+ if (attr.name.startsWith("data-")) {
53
+ dataAttrs[attr.name] = attr.value;
54
+ }
55
+ }
56
+ results.push({
57
+ selector: el.id ? `#${el.id}` : `.${classes.split(" ")[0]}`,
58
+ text: text.substring(0, 100),
59
+ ariaLabel,
60
+ classes: classes.substring(0, 100),
61
+ tag,
62
+ dataAttrs,
63
+ });
64
+ }
65
+ }
66
+ return results;
67
+ });
68
+ }
69
+ async function findSourceListElements(page) {
70
+ log.info("\nšŸ“‹ Looking for source list elements...");
71
+ // Look for the sources panel/sidebar
72
+ const sourceElements = await page.evaluate(() => {
73
+ const results = [];
74
+ // Common patterns for source lists
75
+ const listSelectors = [
76
+ '[class*="source-list"]',
77
+ '[class*="sources-panel"]',
78
+ '[class*="sidebar"]',
79
+ '[role="list"]',
80
+ '[role="listbox"]',
81
+ "mat-list",
82
+ "mat-nav-list",
83
+ ];
84
+ for (const selector of listSelectors) {
85
+ // @ts-expect-error - DOM types
86
+ const elements = document.querySelectorAll(selector);
87
+ for (const el of elements) {
88
+ const text = el.textContent?.substring(0, 200) || "";
89
+ if (text.toLowerCase().includes("source")) {
90
+ results.push({
91
+ selector,
92
+ childCount: el.children.length,
93
+ text: text.substring(0, 100),
94
+ });
95
+ }
96
+ }
97
+ }
98
+ return results;
99
+ });
100
+ for (const item of sourceElements) {
101
+ log.dim(` Found: ${item.selector} (${item.childCount} children)`);
102
+ log.dim(` Text: "${item.text}"`);
103
+ }
104
+ }
105
+ async function findSourceItems(page) {
106
+ log.info("\nšŸ“‹ Looking for individual source items...");
107
+ const items = await page.evaluate(() => {
108
+ const results = [];
109
+ // Look for list items that might be sources
110
+ // @ts-expect-error - DOM types
111
+ const listItems = document.querySelectorAll('mat-list-item, [role="listitem"], .source-item, [class*="source"]');
112
+ for (const item of listItems) {
113
+ const text = item.textContent?.trim().substring(0, 100) || "";
114
+ const classes = item.className || "";
115
+ // Skip if it's clearly not a source item
116
+ if (text.toLowerCase().includes("add") && text.length < 20)
117
+ continue;
118
+ results.push({
119
+ tag: item.tagName,
120
+ classes: classes.substring(0, 80),
121
+ text,
122
+ hasCheckbox: !!item.querySelector('input[type="checkbox"], mat-checkbox'),
123
+ hasDeleteBtn: !!item.querySelector('[aria-label*="delete" i], [aria-label*="remove" i], button[class*="delete"]'),
124
+ hasOptionsBtn: !!item.querySelector('[aria-label*="more" i], [aria-label*="option" i], button[class*="menu"]'),
125
+ });
126
+ }
127
+ return results;
128
+ });
129
+ for (const item of items) {
130
+ log.dim(` [${item.tag}] "${item.text}"`);
131
+ log.dim(` Classes: ${item.classes}`);
132
+ log.dim(` Has: checkbox=${item.hasCheckbox}, delete=${item.hasDeleteBtn}, options=${item.hasOptionsBtn}`);
133
+ }
134
+ }
135
+ async function findDeleteButtons(page) {
136
+ log.info("\nšŸ“‹ Looking for delete/remove buttons...");
137
+ const buttons = await page.evaluate(() => {
138
+ const results = [];
139
+ // @ts-expect-error - DOM types
140
+ const allButtons = document.querySelectorAll("button, [role='button']");
141
+ for (const btn of allButtons) {
142
+ const ariaLabel = btn.getAttribute("aria-label") || "";
143
+ const text = btn.textContent?.trim() || "";
144
+ const classes = btn.className || "";
145
+ const isDelete = /delete|remove|trash|discard/i.test(ariaLabel) ||
146
+ /delete|remove|trash|discard/i.test(text) ||
147
+ /delete|remove|trash/i.test(classes);
148
+ if (isDelete) {
149
+ results.push({
150
+ tag: btn.tagName,
151
+ ariaLabel,
152
+ text: text.substring(0, 50),
153
+ classes: classes.substring(0, 80),
154
+ });
155
+ }
156
+ }
157
+ return results;
158
+ });
159
+ for (const btn of buttons) {
160
+ log.dim(` [${btn.tag}] aria="${btn.ariaLabel}" text="${btn.text}"`);
161
+ log.dim(` Classes: ${btn.classes}`);
162
+ }
163
+ }
164
+ async function findSourceCount(page) {
165
+ log.info("\nšŸ“‹ Looking for source count indicator...");
166
+ const counts = await page.evaluate(() => {
167
+ const results = [];
168
+ // Look for "X sources" or "X/Y" patterns
169
+ // @ts-expect-error - DOM types
170
+ const allText = document.body.innerText;
171
+ const matches = allText.match(/(\d+)\s*(source|file|document)s?/gi) || [];
172
+ // Also look for specific elements
173
+ // @ts-expect-error - DOM types
174
+ const spans = document.querySelectorAll("span, div, p");
175
+ for (const el of spans) {
176
+ const text = el.textContent?.trim() || "";
177
+ if (/^\d+\s*(source|file|document)s?$/i.test(text) || /^\d+\s*\/\s*\d+$/.test(text)) {
178
+ results.push({
179
+ tag: el.tagName,
180
+ text,
181
+ classes: (el.className || "").substring(0, 80),
182
+ });
183
+ }
184
+ }
185
+ return { textMatches: matches, elements: results };
186
+ });
187
+ log.dim(` Text matches: ${counts.textMatches.join(", ") || "none"}`);
188
+ for (const el of counts.elements) {
189
+ log.dim(` [${el.tag}] "${el.text}" class="${el.classes}"`);
190
+ }
191
+ }
192
+ async function main() {
193
+ log.info("šŸ” Discovering Source Management UI Elements...\n");
194
+ if (!TEST_NOTEBOOK_URL) {
195
+ log.warning("āš ļø No TEST_NOTEBOOK_URL environment variable set.");
196
+ log.warning(" Set it to a notebook URL with existing sources:");
197
+ log.warning(" TEST_NOTEBOOK_URL=https://notebooklm.google.com/notebook/xxx node dist/notebook-creation/discover-sources.js");
198
+ log.warning("\n Continuing without URL - will navigate to homepage first...\n");
199
+ }
200
+ const authManager = new AuthManager();
201
+ const contextManager = new SharedContextManager(authManager);
202
+ try {
203
+ const context = await contextManager.getOrCreateContext(true);
204
+ const isAuth = await authManager.validateCookiesExpiry(context);
205
+ if (!isAuth) {
206
+ log.error("āŒ Not authenticated. Run setup_auth first.");
207
+ return;
208
+ }
209
+ const page = await context.newPage();
210
+ // Navigate to notebook or homepage
211
+ const url = TEST_NOTEBOOK_URL || "https://notebooklm.google.com/";
212
+ log.info(`šŸ“ Navigating to: ${url}`);
213
+ await page.goto(url, { waitUntil: "domcontentloaded" });
214
+ await page.waitForLoadState("networkidle").catch(() => { });
215
+ await page.waitForTimeout(3000);
216
+ // If on homepage, try to click on first notebook
217
+ if (!TEST_NOTEBOOK_URL) {
218
+ log.info("šŸ“ Looking for a notebook to open...");
219
+ const clicked = await page.evaluate(() => {
220
+ // @ts-expect-error - DOM types
221
+ const rows = document.querySelectorAll("tr");
222
+ for (const row of rows) {
223
+ if (row.textContent?.includes("Source")) {
224
+ row.click();
225
+ return true;
226
+ }
227
+ }
228
+ return false;
229
+ });
230
+ if (clicked) {
231
+ log.success(" āœ… Clicked on a notebook");
232
+ await page.waitForTimeout(3000);
233
+ }
234
+ else {
235
+ log.warning(" āš ļø No notebooks found to click");
236
+ }
237
+ }
238
+ // Run discovery
239
+ log.info("\n=== Source UI Discovery ===\n");
240
+ // 1. Dump all source-related elements
241
+ log.info("šŸ“‹ All source-related elements:");
242
+ const allElements = await dumpSourceElements(page);
243
+ for (const el of allElements.slice(0, 20)) {
244
+ log.dim(` [${el.tag}] "${el.text}" aria="${el.ariaLabel}"`);
245
+ }
246
+ if (allElements.length > 20) {
247
+ log.dim(` ... and ${allElements.length - 20} more`);
248
+ }
249
+ // 2. Find source list container
250
+ await findSourceListElements(page);
251
+ // 3. Find individual source items
252
+ await findSourceItems(page);
253
+ // 4. Find delete buttons
254
+ await findDeleteButtons(page);
255
+ // 5. Find source count
256
+ await findSourceCount(page);
257
+ // Take a screenshot for reference
258
+ const screenshotPath = "/tmp/notebooklm-sources-discovery.png";
259
+ await page.screenshot({ path: screenshotPath, fullPage: true });
260
+ log.info(`\nšŸ“ø Screenshot saved: ${screenshotPath}`);
261
+ // Keep browser open for inspection
262
+ log.info("\nāœ… Discovery complete. Browser open for 60 seconds...");
263
+ await page.waitForTimeout(60000);
264
+ }
265
+ catch (error) {
266
+ log.error(`āŒ Error: ${error}`);
267
+ }
268
+ finally {
269
+ await contextManager.closeContext();
270
+ }
271
+ }
272
+ main().catch(console.error);
273
+ //# sourceMappingURL=discover-sources.js.map