@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.
- package/README.md +69 -34
- package/dist/accounts/account-manager.d.ts +163 -0
- package/dist/accounts/account-manager.d.ts.map +1 -0
- package/dist/accounts/account-manager.js +614 -0
- package/dist/accounts/account-manager.js.map +1 -0
- package/dist/accounts/auto-login-manager.d.ts +62 -0
- package/dist/accounts/auto-login-manager.d.ts.map +1 -0
- package/dist/accounts/auto-login-manager.js +537 -0
- package/dist/accounts/auto-login-manager.js.map +1 -0
- package/dist/accounts/crypto.d.ts +45 -0
- package/dist/accounts/crypto.d.ts.map +1 -0
- package/dist/accounts/crypto.js +138 -0
- package/dist/accounts/crypto.js.map +1 -0
- package/dist/accounts/index.d.ts +14 -0
- package/dist/accounts/index.d.ts.map +1 -0
- package/dist/accounts/index.js +14 -0
- package/dist/accounts/index.js.map +1 -0
- package/dist/accounts/types.d.ts +103 -0
- package/dist/accounts/types.d.ts.map +1 -0
- package/dist/accounts/types.js +7 -0
- package/dist/accounts/types.js.map +1 -0
- package/dist/auth/auth-manager.d.ts +9 -2
- package/dist/auth/auth-manager.d.ts.map +1 -1
- package/dist/auth/auth-manager.js +60 -6
- package/dist/auth/auth-manager.js.map +1 -1
- package/dist/auto-discovery/auto-discovery.d.ts.map +1 -1
- package/dist/auto-discovery/auto-discovery.js +2 -1
- package/dist/auto-discovery/auto-discovery.js.map +1 -1
- package/dist/cli/accounts.d.ts +13 -0
- package/dist/cli/accounts.d.ts.map +1 -0
- package/dist/cli/accounts.js +195 -0
- package/dist/cli/accounts.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -0
- package/dist/config.js.map +1 -1
- package/dist/content/content-generator.d.ts +153 -0
- package/dist/content/content-generator.d.ts.map +1 -0
- package/dist/content/content-generator.js +637 -0
- package/dist/content/content-generator.js.map +1 -0
- package/dist/content/content-manager.d.ts +364 -0
- package/dist/content/content-manager.d.ts.map +1 -0
- package/dist/content/content-manager.js +3846 -0
- package/dist/content/content-manager.js.map +1 -0
- package/dist/content/content-templates.d.ts +183 -0
- package/dist/content/content-templates.d.ts.map +1 -0
- package/dist/content/content-templates.js +719 -0
- package/dist/content/content-templates.js.map +1 -0
- package/dist/content/index.d.ts +14 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +14 -0
- package/dist/content/index.js.map +1 -0
- package/dist/content/types.d.ts +285 -0
- package/dist/content/types.d.ts.map +1 -0
- package/dist/content/types.js +10 -0
- package/dist/content/types.js.map +1 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/http-wrapper.d.ts +7 -0
- package/dist/http-wrapper.d.ts.map +1 -1
- package/dist/http-wrapper.js +449 -29
- package/dist/http-wrapper.js.map +1 -1
- package/dist/index.js +26 -2
- package/dist/index.js.map +1 -1
- package/dist/library/notebook-library.d.ts +4 -0
- package/dist/library/notebook-library.d.ts.map +1 -1
- package/dist/library/notebook-library.js +20 -3
- package/dist/library/notebook-library.js.map +1 -1
- package/dist/session/browser-session.d.ts +35 -8
- package/dist/session/browser-session.d.ts.map +1 -1
- package/dist/session/browser-session.js +242 -28
- package/dist/session/browser-session.js.map +1 -1
- package/dist/session/session-manager.d.ts +6 -0
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +46 -14
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/shared-context-manager.d.ts +3 -3
- package/dist/session/shared-context-manager.d.ts.map +1 -1
- package/dist/session/shared-context-manager.js +8 -7
- package/dist/session/shared-context-manager.js.map +1 -1
- package/dist/stdio-http-proxy.d.ts +24 -0
- package/dist/stdio-http-proxy.d.ts.map +1 -0
- package/dist/stdio-http-proxy.js +592 -0
- package/dist/stdio-http-proxy.js.map +1 -0
- package/dist/tools/index.d.ts +106 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1028 -7
- package/dist/tools/index.js.map +1 -1
- package/dist/types.d.ts +81 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/citation-extractor.d.ts +66 -0
- package/dist/utils/citation-extractor.d.ts.map +1 -0
- package/dist/utils/citation-extractor.js +492 -0
- package/dist/utils/citation-extractor.js.map +1 -0
- package/dist/utils/page-utils.d.ts +8 -0
- package/dist/utils/page-utils.d.ts.map +1 -1
- package/dist/utils/page-utils.js +112 -8
- package/dist/utils/page-utils.js.map +1 -1
- package/docs/ARCHITECTURE_MIGRATION_STUDY.md +894 -0
- package/docs/CHROME_PROFILE_LIMITATION.md +15 -1
- package/docs/MULTI_ACCOUNT_SYSTEM.md +304 -0
- package/package.json +10 -10
- package/dist/__tests__/cleanup-manager.test.d.ts +0 -2
- package/dist/__tests__/cleanup-manager.test.d.ts.map +0 -1
- package/dist/__tests__/cleanup-manager.test.js +0 -341
- package/dist/__tests__/cleanup-manager.test.js.map +0 -1
- package/dist/__tests__/config-parsing.test.d.ts +0 -2
- package/dist/__tests__/config-parsing.test.d.ts.map +0 -1
- package/dist/__tests__/config-parsing.test.js +0 -338
- package/dist/__tests__/config-parsing.test.js.map +0 -1
- package/dist/__tests__/config.test.d.ts +0 -2
- package/dist/__tests__/config.test.d.ts.map +0 -1
- package/dist/__tests__/config.test.js +0 -267
- package/dist/__tests__/config.test.js.map +0 -1
- package/dist/__tests__/errors.test.d.ts +0 -2
- package/dist/__tests__/errors.test.d.ts.map +0 -1
- package/dist/__tests__/errors.test.js +0 -166
- package/dist/__tests__/errors.test.js.map +0 -1
- package/dist/__tests__/logger.test.d.ts +0 -2
- package/dist/__tests__/logger.test.d.ts.map +0 -1
- package/dist/__tests__/logger.test.js +0 -324
- package/dist/__tests__/logger.test.js.map +0 -1
- package/dist/__tests__/page-utils.test.d.ts +0 -2
- package/dist/__tests__/page-utils.test.d.ts.map +0 -1
- package/dist/__tests__/page-utils.test.js +0 -349
- package/dist/__tests__/page-utils.test.js.map +0 -1
- package/dist/__tests__/setup-verification.test.d.ts +0 -2
- package/dist/__tests__/setup-verification.test.d.ts.map +0 -1
- package/dist/__tests__/setup-verification.test.js +0 -15
- package/dist/__tests__/setup-verification.test.js.map +0 -1
- package/dist/__tests__/stealth-utils.test.d.ts +0 -2
- package/dist/__tests__/stealth-utils.test.d.ts.map +0 -1
- package/dist/__tests__/stealth-utils.test.js +0 -413
- package/dist/__tests__/stealth-utils.test.js.map +0 -1
- package/dist/__tests__/types.test.d.ts +0 -2
- package/dist/__tests__/types.test.d.ts.map +0 -1
- package/dist/__tests__/types.test.js +0 -461
- 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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"}
|