@roomi-fields/notebooklm-mcp 1.3.6 → 1.5.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 (138) hide show
  1. package/README.md +69 -34
  2. package/dist/accounts/account-manager.d.ts +163 -0
  3. package/dist/accounts/account-manager.d.ts.map +1 -0
  4. package/dist/accounts/account-manager.js +614 -0
  5. package/dist/accounts/account-manager.js.map +1 -0
  6. package/dist/accounts/auto-login-manager.d.ts +62 -0
  7. package/dist/accounts/auto-login-manager.d.ts.map +1 -0
  8. package/dist/accounts/auto-login-manager.js +537 -0
  9. package/dist/accounts/auto-login-manager.js.map +1 -0
  10. package/dist/accounts/crypto.d.ts +45 -0
  11. package/dist/accounts/crypto.d.ts.map +1 -0
  12. package/dist/accounts/crypto.js +138 -0
  13. package/dist/accounts/crypto.js.map +1 -0
  14. package/dist/accounts/index.d.ts +14 -0
  15. package/dist/accounts/index.d.ts.map +1 -0
  16. package/dist/accounts/index.js +14 -0
  17. package/dist/accounts/index.js.map +1 -0
  18. package/dist/accounts/types.d.ts +103 -0
  19. package/dist/accounts/types.d.ts.map +1 -0
  20. package/dist/accounts/types.js +7 -0
  21. package/dist/accounts/types.js.map +1 -0
  22. package/dist/auth/auth-manager.d.ts +9 -2
  23. package/dist/auth/auth-manager.d.ts.map +1 -1
  24. package/dist/auth/auth-manager.js +60 -6
  25. package/dist/auth/auth-manager.js.map +1 -1
  26. package/dist/auto-discovery/auto-discovery.d.ts.map +1 -1
  27. package/dist/auto-discovery/auto-discovery.js +2 -1
  28. package/dist/auto-discovery/auto-discovery.js.map +1 -1
  29. package/dist/cli/accounts.d.ts +13 -0
  30. package/dist/cli/accounts.d.ts.map +1 -0
  31. package/dist/cli/accounts.js +195 -0
  32. package/dist/cli/accounts.js.map +1 -0
  33. package/dist/config.d.ts.map +1 -1
  34. package/dist/config.js +9 -0
  35. package/dist/config.js.map +1 -1
  36. package/dist/content/content-generator.d.ts +153 -0
  37. package/dist/content/content-generator.d.ts.map +1 -0
  38. package/dist/content/content-generator.js +637 -0
  39. package/dist/content/content-generator.js.map +1 -0
  40. package/dist/content/content-manager.d.ts +364 -0
  41. package/dist/content/content-manager.d.ts.map +1 -0
  42. package/dist/content/content-manager.js +3846 -0
  43. package/dist/content/content-manager.js.map +1 -0
  44. package/dist/content/content-templates.d.ts +183 -0
  45. package/dist/content/content-templates.d.ts.map +1 -0
  46. package/dist/content/content-templates.js +719 -0
  47. package/dist/content/content-templates.js.map +1 -0
  48. package/dist/content/index.d.ts +14 -0
  49. package/dist/content/index.d.ts.map +1 -0
  50. package/dist/content/index.js +14 -0
  51. package/dist/content/index.js.map +1 -0
  52. package/dist/content/types.d.ts +285 -0
  53. package/dist/content/types.d.ts.map +1 -0
  54. package/dist/content/types.js +10 -0
  55. package/dist/content/types.js.map +1 -0
  56. package/dist/errors.d.ts +1 -1
  57. package/dist/errors.d.ts.map +1 -1
  58. package/dist/errors.js.map +1 -1
  59. package/dist/http-wrapper.d.ts +7 -0
  60. package/dist/http-wrapper.d.ts.map +1 -1
  61. package/dist/http-wrapper.js +449 -29
  62. package/dist/http-wrapper.js.map +1 -1
  63. package/dist/index.js +26 -2
  64. package/dist/index.js.map +1 -1
  65. package/dist/library/notebook-library.d.ts +4 -0
  66. package/dist/library/notebook-library.d.ts.map +1 -1
  67. package/dist/library/notebook-library.js +20 -3
  68. package/dist/library/notebook-library.js.map +1 -1
  69. package/dist/session/browser-session.d.ts +35 -8
  70. package/dist/session/browser-session.d.ts.map +1 -1
  71. package/dist/session/browser-session.js +242 -28
  72. package/dist/session/browser-session.js.map +1 -1
  73. package/dist/session/session-manager.d.ts +6 -0
  74. package/dist/session/session-manager.d.ts.map +1 -1
  75. package/dist/session/session-manager.js +46 -14
  76. package/dist/session/session-manager.js.map +1 -1
  77. package/dist/session/shared-context-manager.d.ts +3 -3
  78. package/dist/session/shared-context-manager.d.ts.map +1 -1
  79. package/dist/session/shared-context-manager.js +8 -7
  80. package/dist/session/shared-context-manager.js.map +1 -1
  81. package/dist/stdio-http-proxy.d.ts +24 -0
  82. package/dist/stdio-http-proxy.d.ts.map +1 -0
  83. package/dist/stdio-http-proxy.js +592 -0
  84. package/dist/stdio-http-proxy.js.map +1 -0
  85. package/dist/tools/index.d.ts +106 -1
  86. package/dist/tools/index.d.ts.map +1 -1
  87. package/dist/tools/index.js +1028 -7
  88. package/dist/tools/index.js.map +1 -1
  89. package/dist/types.d.ts +81 -17
  90. package/dist/types.d.ts.map +1 -1
  91. package/dist/utils/citation-extractor.d.ts +66 -0
  92. package/dist/utils/citation-extractor.d.ts.map +1 -0
  93. package/dist/utils/citation-extractor.js +492 -0
  94. package/dist/utils/citation-extractor.js.map +1 -0
  95. package/dist/utils/page-utils.d.ts +8 -0
  96. package/dist/utils/page-utils.d.ts.map +1 -1
  97. package/dist/utils/page-utils.js +112 -8
  98. package/dist/utils/page-utils.js.map +1 -1
  99. package/docs/ARCHITECTURE_MIGRATION_STUDY.md +894 -0
  100. package/docs/CHROME_PROFILE_LIMITATION.md +15 -1
  101. package/docs/MULTI_ACCOUNT_SYSTEM.md +304 -0
  102. package/package.json +10 -10
  103. package/dist/__tests__/cleanup-manager.test.d.ts +0 -2
  104. package/dist/__tests__/cleanup-manager.test.d.ts.map +0 -1
  105. package/dist/__tests__/cleanup-manager.test.js +0 -341
  106. package/dist/__tests__/cleanup-manager.test.js.map +0 -1
  107. package/dist/__tests__/config-parsing.test.d.ts +0 -2
  108. package/dist/__tests__/config-parsing.test.d.ts.map +0 -1
  109. package/dist/__tests__/config-parsing.test.js +0 -338
  110. package/dist/__tests__/config-parsing.test.js.map +0 -1
  111. package/dist/__tests__/config.test.d.ts +0 -2
  112. package/dist/__tests__/config.test.d.ts.map +0 -1
  113. package/dist/__tests__/config.test.js +0 -267
  114. package/dist/__tests__/config.test.js.map +0 -1
  115. package/dist/__tests__/errors.test.d.ts +0 -2
  116. package/dist/__tests__/errors.test.d.ts.map +0 -1
  117. package/dist/__tests__/errors.test.js +0 -166
  118. package/dist/__tests__/errors.test.js.map +0 -1
  119. package/dist/__tests__/logger.test.d.ts +0 -2
  120. package/dist/__tests__/logger.test.d.ts.map +0 -1
  121. package/dist/__tests__/logger.test.js +0 -324
  122. package/dist/__tests__/logger.test.js.map +0 -1
  123. package/dist/__tests__/page-utils.test.d.ts +0 -2
  124. package/dist/__tests__/page-utils.test.d.ts.map +0 -1
  125. package/dist/__tests__/page-utils.test.js +0 -349
  126. package/dist/__tests__/page-utils.test.js.map +0 -1
  127. package/dist/__tests__/setup-verification.test.d.ts +0 -2
  128. package/dist/__tests__/setup-verification.test.d.ts.map +0 -1
  129. package/dist/__tests__/setup-verification.test.js +0 -15
  130. package/dist/__tests__/setup-verification.test.js.map +0 -1
  131. package/dist/__tests__/stealth-utils.test.d.ts +0 -2
  132. package/dist/__tests__/stealth-utils.test.d.ts.map +0 -1
  133. package/dist/__tests__/stealth-utils.test.js +0 -413
  134. package/dist/__tests__/stealth-utils.test.js.map +0 -1
  135. package/dist/__tests__/types.test.d.ts +0 -2
  136. package/dist/__tests__/types.test.d.ts.map +0 -1
  137. package/dist/__tests__/types.test.js +0 -461
  138. package/dist/__tests__/types.test.js.map +0 -1
@@ -0,0 +1,637 @@
1
+ /**
2
+ * Generic Content Generator
3
+ *
4
+ * Provides a unified approach for generating all content types in NotebookLM Studio.
5
+ * This class reuses existing patterns from ContentManager and stealth utilities
6
+ * to interact with the NotebookLM UI reliably.
7
+ *
8
+ * Key features:
9
+ * - Generic content generation flow that works for all content types
10
+ * - Button discovery with multiple fallback selectors
11
+ * - Chat-based fallback when Studio buttons are not available
12
+ * - Streaming-aware response waiting
13
+ *
14
+ * This is the foundation for Phase 1 content types:
15
+ * - audio_overview, video, infographic, report, presentation, data_table
16
+ */
17
+ import { randomDelay, realisticClick, humanType } from '../utils/stealth-utils.js';
18
+ import { waitForLatestAnswer, snapshotAllResponses, isErrorMessage } from '../utils/page-utils.js';
19
+ import { log } from '../utils/logger.js';
20
+ import { getContentConfig, buildChatPrompt, getFormatFromInput, } from './content-templates.js';
21
+ /**
22
+ * Generic Content Generator for NotebookLM Studio
23
+ *
24
+ * This class provides a unified content generation flow that:
25
+ * 1. Navigates to the Studio panel
26
+ * 2. Checks if content already exists
27
+ * 3. Finds and clicks the generation button
28
+ * 4. Falls back to chat-based generation if needed
29
+ * 5. Waits for content completion with streaming detection
30
+ */
31
+ export class ContentGenerator {
32
+ page;
33
+ constructor(page) {
34
+ this.page = page;
35
+ }
36
+ // ============================================================================
37
+ // Public API
38
+ // ============================================================================
39
+ /**
40
+ * Generate content of any supported type
41
+ *
42
+ * @param input Content generation input with type and options
43
+ * @returns Content generation result
44
+ */
45
+ async generate(input) {
46
+ const config = getContentConfig(input.type);
47
+ if (!config) {
48
+ return {
49
+ success: false,
50
+ contentType: input.type,
51
+ error: `Unsupported content type: ${input.type}`,
52
+ };
53
+ }
54
+ log.info(`Generating ${config.displayName}...`);
55
+ try {
56
+ // Step 1: Navigate to Studio panel
57
+ await this.navigateToStudio();
58
+ await this.page.waitForTimeout(1000);
59
+ // Step 2: Check if content already exists
60
+ const exists = await this.checkContentExists(config);
61
+ if (exists) {
62
+ log.info(` ${config.displayName} already exists`);
63
+ return {
64
+ success: true,
65
+ contentType: input.type,
66
+ status: 'ready',
67
+ };
68
+ }
69
+ // Step 3: Try to find and click the generation button
70
+ const buttonResult = await this.findButton(config.buttonSelectors);
71
+ if (buttonResult.found && buttonResult.selector) {
72
+ log.info(` Found ${config.displayName} button: ${buttonResult.selector}`);
73
+ // Click the button to start generation
74
+ await realisticClick(this.page, buttonResult.selector, true);
75
+ log.info(` Clicked ${config.displayName} button`);
76
+ // Step 3.5: Handle format selection if this content type has format options
77
+ const formatSelected = await this.selectFormat(input, config);
78
+ if (formatSelected) {
79
+ log.info(` Format selected successfully`);
80
+ }
81
+ // Step 3.6: Handle language selection if specified
82
+ const languageSelected = await this.selectLanguage(input, config);
83
+ if (languageSelected) {
84
+ log.info(` Language selected successfully`);
85
+ }
86
+ // Step 3.7: Handle style selection for video content
87
+ const styleSelected = await this.selectStyle(input, config);
88
+ if (styleSelected) {
89
+ log.info(` Style selected successfully`);
90
+ }
91
+ log.info(` Started ${config.displayName} generation via Studio button`);
92
+ // Wait for generation to complete
93
+ const waitResult = await this.waitForContentGeneration(input.type, config);
94
+ if (waitResult.ready) {
95
+ log.success(` ${config.displayName} generated successfully via Studio`);
96
+ return {
97
+ success: true,
98
+ contentType: input.type,
99
+ status: 'ready',
100
+ textContent: waitResult.content,
101
+ };
102
+ }
103
+ else if (waitResult.error) {
104
+ log.error(` ${config.displayName} generation failed: ${waitResult.error}`);
105
+ return {
106
+ success: false,
107
+ contentType: input.type,
108
+ status: 'failed',
109
+ error: waitResult.error,
110
+ };
111
+ }
112
+ }
113
+ // Step 4: Fallback to chat-based generation
114
+ log.info(` No Studio button found, trying chat-based approach...`);
115
+ return await this.generateViaChatFallback(input, config);
116
+ }
117
+ catch (error) {
118
+ const errorMsg = error instanceof Error ? error.message : String(error);
119
+ log.error(`Content generation failed: ${errorMsg}`);
120
+ return {
121
+ success: false,
122
+ contentType: input.type,
123
+ error: errorMsg,
124
+ };
125
+ }
126
+ }
127
+ // ============================================================================
128
+ // Navigation Methods (reused from ContentManager patterns)
129
+ // ============================================================================
130
+ /**
131
+ * Navigate to the Studio panel in NotebookLM
132
+ * Uses the same approach as ContentManager.navigateToStudio()
133
+ */
134
+ async navigateToStudio() {
135
+ // Updated selectors based on current NotebookLM UI (Dec 2024)
136
+ // The tabs are: Sources | Discussion | Studio
137
+ const studioSelectors = [
138
+ 'div.mdc-tab:has-text("Studio")', // Material Design tab with text
139
+ '.mat-mdc-tab:has-text("Studio")', // Angular Material tab
140
+ '[role="tab"]:has-text("Studio")', // Tab role with Studio text
141
+ 'div.mdc-tab >> text=Studio', // Playwright text selector
142
+ '.notebook-guide', // Legacy fallback
143
+ ];
144
+ for (const selector of studioSelectors) {
145
+ try {
146
+ const el = this.page.locator(selector).first();
147
+ if (await el.isVisible({ timeout: 2000 })) {
148
+ // Check if already selected
149
+ const isActive = (await el.getAttribute('aria-selected')) === 'true' ||
150
+ (await el.getAttribute('class'))?.includes('mdc-tab--active');
151
+ if (!isActive) {
152
+ await el.click();
153
+ await randomDelay(800, 1200);
154
+ log.info(` Clicked Studio tab`);
155
+ }
156
+ else {
157
+ log.info(` Studio tab already active`);
158
+ }
159
+ return;
160
+ }
161
+ }
162
+ catch {
163
+ continue;
164
+ }
165
+ }
166
+ // Try clicking by finding the tab list and clicking the third tab
167
+ try {
168
+ const tabList = this.page.locator('.mat-mdc-tab-list .mdc-tab').nth(2); // Studio is 3rd tab (0-indexed)
169
+ if (await tabList.isVisible({ timeout: 1000 })) {
170
+ await tabList.click();
171
+ await randomDelay(800, 1200);
172
+ log.info(` Studio tab accessed via tab list`);
173
+ return;
174
+ }
175
+ }
176
+ catch {
177
+ // Continue to fallback
178
+ }
179
+ log.warning(` Could not find Studio tab, content generation may fail`);
180
+ }
181
+ /**
182
+ * Navigate to the Discussion panel (chat)
183
+ * Uses the same approach as ContentManager.navigateToDiscussion()
184
+ */
185
+ async navigateToDiscussion() {
186
+ const discussionSelectors = [
187
+ 'div.mdc-tab:has-text("Discussion")',
188
+ '.mat-mdc-tab:has-text("Discussion")',
189
+ '[role="tab"]:has-text("Discussion")',
190
+ 'div.mdc-tab >> text=Discussion',
191
+ ];
192
+ for (const selector of discussionSelectors) {
193
+ try {
194
+ const el = this.page.locator(selector).first();
195
+ if (await el.isVisible({ timeout: 2000 })) {
196
+ // Check if already selected
197
+ const isActive = (await el.getAttribute('aria-selected')) === 'true' ||
198
+ (await el.getAttribute('class'))?.includes('mdc-tab--active');
199
+ if (!isActive) {
200
+ await el.click();
201
+ await randomDelay(500, 800);
202
+ log.info(` Clicked Discussion tab`);
203
+ }
204
+ else {
205
+ log.info(` Discussion tab already active`);
206
+ }
207
+ return;
208
+ }
209
+ }
210
+ catch {
211
+ continue;
212
+ }
213
+ }
214
+ // Discussion might already be active or accessible
215
+ log.info(` Discussion panel should be accessible`);
216
+ }
217
+ // ============================================================================
218
+ // Button Discovery
219
+ // ============================================================================
220
+ /**
221
+ * Find a button using multiple selectors
222
+ * Tries each selector in order and returns the first visible match
223
+ *
224
+ * @param selectors Array of CSS selectors to try
225
+ * @returns Result with found status and matching selector
226
+ */
227
+ async findButton(selectors) {
228
+ for (const selector of selectors) {
229
+ try {
230
+ const button = this.page.locator(selector).first();
231
+ if (await button.isVisible({ timeout: 1000 })) {
232
+ return { found: true, selector };
233
+ }
234
+ }
235
+ catch {
236
+ continue;
237
+ }
238
+ }
239
+ return { found: false };
240
+ }
241
+ // ============================================================================
242
+ // Format Selection
243
+ // ============================================================================
244
+ /**
245
+ * Select format option after clicking the main content button
246
+ * Looks for format selection UI (buttons, dropdowns, options) and clicks the appropriate one
247
+ *
248
+ * @param input Content generation input with format options
249
+ * @param config Content type configuration
250
+ * @returns True if a format was selected, false if no format UI found
251
+ */
252
+ async selectFormat(input, config) {
253
+ // Check if this content type has format options
254
+ if (!config.formatSelectors) {
255
+ return false;
256
+ }
257
+ // Get the format value from input
258
+ const format = getFormatFromInput(input);
259
+ const effectiveFormat = format || config.defaultFormat;
260
+ if (!effectiveFormat) {
261
+ log.info(` No format specified and no default, skipping format selection`);
262
+ return false;
263
+ }
264
+ // Get selectors for this format
265
+ const formatConfig = config.formatSelectors[effectiveFormat];
266
+ if (!formatConfig) {
267
+ log.warning(` Unknown format '${effectiveFormat}' for ${config.displayName}`);
268
+ return false;
269
+ }
270
+ log.info(` Looking for ${formatConfig.displayName} format option...`);
271
+ // Wait a moment for the format selection UI to appear after clicking main button
272
+ await randomDelay(500, 1000);
273
+ // Try to find and click the format button
274
+ const formatButtonResult = await this.findButton(formatConfig.selectors);
275
+ if (formatButtonResult.found && formatButtonResult.selector) {
276
+ log.info(` Found ${formatConfig.displayName} format button: ${formatButtonResult.selector}`);
277
+ await realisticClick(this.page, formatButtonResult.selector, true);
278
+ await randomDelay(300, 600);
279
+ log.info(` Selected ${formatConfig.displayName} format`);
280
+ return true;
281
+ }
282
+ // Format button not found - this is normal if UI doesn't have format selection
283
+ log.info(` No format selection UI found, proceeding with default`);
284
+ return false;
285
+ }
286
+ // ============================================================================
287
+ // Style Selection (Video)
288
+ // ============================================================================
289
+ /**
290
+ * Select video style option after clicking the main content button
291
+ * Looks for style selection UI (buttons, dropdowns, options) and clicks the appropriate one
292
+ *
293
+ * @param input Content generation input with style options
294
+ * @param config Content type configuration
295
+ * @returns True if a style was selected, false if no style UI found
296
+ */
297
+ async selectStyle(input, config) {
298
+ // Check if this content type has style options (only video)
299
+ if (!config.styleSelectors || input.type !== 'video') {
300
+ return false;
301
+ }
302
+ // Get the style value from input or use default
303
+ const style = input.videoStyle || config.defaultStyle;
304
+ if (!style) {
305
+ log.info(` No style specified and no default, skipping style selection`);
306
+ return false;
307
+ }
308
+ // Get selectors for this style
309
+ const styleConfig = config.styleSelectors[style];
310
+ if (!styleConfig) {
311
+ log.warning(` Unknown style '${style}' for ${config.displayName}`);
312
+ return false;
313
+ }
314
+ log.info(` Looking for ${styleConfig.displayName} style option...`);
315
+ // Wait a moment for the style selection UI to appear
316
+ await randomDelay(300, 600);
317
+ // Try to find and click the style button
318
+ const styleButtonResult = await this.findButton(styleConfig.selectors);
319
+ if (styleButtonResult.found && styleButtonResult.selector) {
320
+ log.info(` Found ${styleConfig.displayName} style button: ${styleButtonResult.selector}`);
321
+ await realisticClick(this.page, styleButtonResult.selector, true);
322
+ await randomDelay(300, 600);
323
+ log.info(` Selected ${styleConfig.displayName} style`);
324
+ return true;
325
+ }
326
+ // Style button not found - this is normal if UI doesn't have style selection
327
+ log.info(` No style selection UI found, proceeding with default`);
328
+ return false;
329
+ }
330
+ // ============================================================================
331
+ // Language Selection
332
+ // ============================================================================
333
+ /**
334
+ * Select language option for content generation
335
+ * Opens the language dropdown and selects the specified language
336
+ *
337
+ * @param input Content generation input with language option
338
+ * @param config Content type configuration
339
+ * @returns True if a language was selected, false if no language UI found
340
+ */
341
+ async selectLanguage(input, config) {
342
+ // Check if this content type has language options and a language is specified
343
+ if (!config.languageSelectors || !input.language) {
344
+ return false;
345
+ }
346
+ log.info(` Looking for language selector (${input.language})...`);
347
+ // Try to open the language dropdown
348
+ const dropdownResult = await this.findButton(config.languageSelectors.dropdownTrigger);
349
+ if (!dropdownResult.found || !dropdownResult.selector) {
350
+ log.info(` No language dropdown found, proceeding with default`);
351
+ return false;
352
+ }
353
+ // Click to open dropdown
354
+ await realisticClick(this.page, dropdownResult.selector, true);
355
+ await randomDelay(500, 800);
356
+ // Build language-specific selectors by replacing {language} placeholder
357
+ const languageSelectors = config.languageSelectors.optionPattern.map((s) => s.replace('{language}', input.language));
358
+ // Try to find and click the language option
359
+ const languageResult = await this.findButton(languageSelectors);
360
+ if (languageResult.found && languageResult.selector) {
361
+ await realisticClick(this.page, languageResult.selector, true);
362
+ await randomDelay(300, 600);
363
+ log.info(` Selected language: ${input.language}`);
364
+ return true;
365
+ }
366
+ // Language option not found - close dropdown by pressing Escape
367
+ log.info(` Language '${input.language}' not found in dropdown`);
368
+ await this.page.keyboard.press('Escape');
369
+ return false;
370
+ }
371
+ // ============================================================================
372
+ // Content Existence Check
373
+ // ============================================================================
374
+ /**
375
+ * Check if content of the specified type already exists
376
+ *
377
+ * @param config Content type configuration
378
+ * @returns True if content exists
379
+ */
380
+ async checkContentExists(config) {
381
+ for (const selector of config.existsSelectors) {
382
+ try {
383
+ const element = this.page.locator(selector).first();
384
+ if (await element.isVisible({ timeout: 500 })) {
385
+ return true;
386
+ }
387
+ }
388
+ catch {
389
+ continue;
390
+ }
391
+ }
392
+ return false;
393
+ }
394
+ // ============================================================================
395
+ // Content Generation Waiting
396
+ // ============================================================================
397
+ /**
398
+ * Wait for content generation to complete
399
+ * Monitors the UI for completion indicators or errors
400
+ *
401
+ * @param type Content type being generated
402
+ * @param config Content type configuration
403
+ * @returns Wait result with status and optional content
404
+ */
405
+ async waitForContentGeneration(_type, config) {
406
+ log.info(` Waiting for ${config.displayName} generation (up to ${config.waitTimeout / 60000} minutes)...`);
407
+ const startTime = Date.now();
408
+ const pollInterval = 2000; // Poll every 2 seconds
409
+ while (Date.now() - startTime < config.waitTimeout) {
410
+ // Check for errors
411
+ const errorEl = await this.page.$('.error-message, [role="alert"]:has-text("error")');
412
+ if (errorEl) {
413
+ const errorText = await errorEl.textContent();
414
+ return {
415
+ source: 'studio',
416
+ ready: false,
417
+ error: errorText || `${config.displayName} generation failed`,
418
+ };
419
+ }
420
+ // Check if content now exists
421
+ const exists = await this.checkContentExists(config);
422
+ if (exists) {
423
+ return {
424
+ source: 'studio',
425
+ ready: true,
426
+ };
427
+ }
428
+ // Check for progress indicators
429
+ const progressEl = await this.page.$('[role="progressbar"], .progress-bar, .loading');
430
+ if (progressEl) {
431
+ const progress = await progressEl.getAttribute('aria-valuenow');
432
+ if (progress) {
433
+ log.info(` Generation progress: ${progress}%`);
434
+ }
435
+ }
436
+ await this.page.waitForTimeout(pollInterval);
437
+ }
438
+ return {
439
+ source: 'studio',
440
+ ready: false,
441
+ error: `Timeout waiting for ${config.displayName} generation after ${config.waitTimeout / 1000}s`,
442
+ };
443
+ }
444
+ // ============================================================================
445
+ // Chat-Based Fallback
446
+ // ============================================================================
447
+ /**
448
+ * Generate content using chat-based fallback when Studio button is not available
449
+ *
450
+ * @param input Content generation input
451
+ * @param config Content type configuration
452
+ * @returns Content generation result
453
+ */
454
+ async generateViaChatFallback(input, config) {
455
+ try {
456
+ // Navigate to Discussion panel
457
+ await this.navigateToDiscussion();
458
+ // Build the prompt with format and custom instructions
459
+ // Pass the full input so format options are included in the prompt
460
+ const prompt = buildChatPrompt(config, input);
461
+ // Send the chat message
462
+ await this.sendChatMessage(prompt);
463
+ // Wait for response using the proven page-utils approach
464
+ const result = await this.waitForChatResponse(config);
465
+ if (result.ready && result.content) {
466
+ log.success(` ${config.displayName} generated via chat fallback`);
467
+ return {
468
+ success: true,
469
+ contentType: input.type,
470
+ status: 'ready',
471
+ textContent: result.content,
472
+ };
473
+ }
474
+ return {
475
+ success: false,
476
+ contentType: input.type,
477
+ status: 'failed',
478
+ error: result.error || `Failed to generate ${config.displayName} via chat`,
479
+ };
480
+ }
481
+ catch (error) {
482
+ const errorMsg = error instanceof Error ? error.message : String(error);
483
+ return {
484
+ success: false,
485
+ contentType: input.type,
486
+ error: `Chat fallback failed: ${errorMsg}`,
487
+ };
488
+ }
489
+ }
490
+ /**
491
+ * Send a message in the chat interface
492
+ * Uses the same approach as ContentManager.sendChatMessage()
493
+ *
494
+ * @param message Message to send
495
+ */
496
+ async sendChatMessage(message) {
497
+ log.info(` Sending chat message: "${message.substring(0, 50)}..."`);
498
+ // Find the chat input (same approach as BrowserSession.findChatInput)
499
+ const chatInputSelectors = [
500
+ 'textarea.query-box-input', // PRIMARY - same as Python implementation
501
+ 'textarea[aria-label*="query"]',
502
+ 'textarea[aria-label*="Zone de requete"]',
503
+ ];
504
+ let inputSelector = null;
505
+ for (const selector of chatInputSelectors) {
506
+ try {
507
+ const input = await this.page.waitForSelector(selector, {
508
+ state: 'visible',
509
+ timeout: 3000,
510
+ });
511
+ if (input) {
512
+ inputSelector = selector;
513
+ log.info(` Found chat input: ${selector}`);
514
+ break;
515
+ }
516
+ }
517
+ catch {
518
+ continue;
519
+ }
520
+ }
521
+ if (!inputSelector) {
522
+ throw new Error('Chat input not found');
523
+ }
524
+ // Clear any existing text first
525
+ const inputEl = await this.page.$(inputSelector);
526
+ if (inputEl) {
527
+ await inputEl.click();
528
+ await this.page.keyboard.press('Control+A');
529
+ await this.page.keyboard.press('Backspace');
530
+ await randomDelay(200, 400);
531
+ }
532
+ // Type the message with human-like behavior
533
+ log.info(` Typing message with human-like behavior...`);
534
+ await humanType(this.page, inputSelector, message, {
535
+ withTypos: false, // No typos for prompts to avoid confusion
536
+ wpm: 150, // Faster typing for long prompts
537
+ });
538
+ // Small pause before submitting
539
+ await randomDelay(500, 1000);
540
+ // Submit with Enter key
541
+ log.info(` Submitting message...`);
542
+ await this.page.keyboard.press('Enter');
543
+ // Small pause after submit
544
+ await randomDelay(1000, 1500);
545
+ log.info(` Message sent`);
546
+ }
547
+ /**
548
+ * Wait for chat response with streaming detection
549
+ * Uses the proven waitForLatestAnswer from page-utils
550
+ *
551
+ * @param config Content type configuration
552
+ * @returns Wait result with content
553
+ */
554
+ async waitForChatResponse(config) {
555
+ log.info(` Waiting for ${config.displayName} response (up to ${config.waitTimeout / 60000} minutes)...`);
556
+ // Scroll to bottom to ensure we see all messages
557
+ await this.scrollChatToBottom();
558
+ // Snapshot existing chat responses to ignore them
559
+ const existingResponses = await snapshotAllResponses(this.page);
560
+ log.info(` Ignoring ${existingResponses.length} existing chat responses`);
561
+ // Use the proven logic from page-utils
562
+ const response = await waitForLatestAnswer(this.page, {
563
+ question: '', // Empty question since we already sent the message
564
+ timeoutMs: config.waitTimeout,
565
+ pollIntervalMs: 2000, // Poll every 2 seconds
566
+ ignoreTexts: existingResponses,
567
+ debug: true, // Enable debug to see what's happening
568
+ });
569
+ // Check if response is an error message from NotebookLM
570
+ if (response && isErrorMessage(response)) {
571
+ log.error(` NotebookLM returned an error: "${response}"`);
572
+ return {
573
+ source: 'chat',
574
+ ready: false,
575
+ error: `NotebookLM error: ${response}`,
576
+ };
577
+ }
578
+ if (response && response.length > 50) {
579
+ log.success(` Content received (${response.length} chars)`);
580
+ return {
581
+ source: 'chat',
582
+ ready: true,
583
+ content: response,
584
+ };
585
+ }
586
+ return {
587
+ source: 'chat',
588
+ ready: false,
589
+ error: `Timeout waiting for ${config.displayName} response`,
590
+ };
591
+ }
592
+ /**
593
+ * Scroll chat container to bottom to ensure latest messages are visible
594
+ */
595
+ async scrollChatToBottom() {
596
+ try {
597
+ // Try multiple selectors for the chat container
598
+ const chatContainerSelectors = [
599
+ '.chat-scroll-container',
600
+ '.messages-container',
601
+ '[class*="scroll"]',
602
+ '.query-container',
603
+ ];
604
+ for (const selector of chatContainerSelectors) {
605
+ const container = await this.page.$(selector);
606
+ if (container) {
607
+ await container.evaluate((el) => {
608
+ el.scrollTop = el.scrollHeight;
609
+ });
610
+ log.debug(` Scrolled chat to bottom using ${selector}`);
611
+ return;
612
+ }
613
+ }
614
+ // Fallback: scroll the whole page
615
+ await this.page.evaluate(`window.scrollTo(0, document.body.scrollHeight)`);
616
+ log.debug(` Scrolled page to bottom (fallback)`);
617
+ }
618
+ catch (error) {
619
+ log.debug(` Could not scroll: ${error}`);
620
+ }
621
+ }
622
+ }
623
+ // ============================================================================
624
+ // Factory Function
625
+ // ============================================================================
626
+ /**
627
+ * Create a ContentGenerator instance for a page
628
+ *
629
+ * @param page Playwright page instance
630
+ * @returns ContentGenerator instance
631
+ */
632
+ export function createContentGenerator(page) {
633
+ return new ContentGenerator(page);
634
+ }
635
+ // Note: CONTENT_CONFIGS, getContentConfig, buildChatPrompt, getFormatFromInput
636
+ // are exported from content-templates.ts and re-exported via index.ts
637
+ //# sourceMappingURL=content-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-generator.js","sourceRoot":"","sources":["../../src/content/content-generator.ts"],"names":[],"mappings":"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"}