@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,719 @@
1
+ /**
2
+ * Content Templates Configuration
3
+ *
4
+ * Defines configuration for each content type in NotebookLM Studio:
5
+ * - Button selectors to find the generation trigger
6
+ * - Format selection selectors for sub-format options
7
+ * - Exists selectors to detect if content already exists
8
+ * - Chat prompt templates for fallback generation
9
+ * - Wait timeouts for generation completion
10
+ *
11
+ * These configurations enable the generic ContentGenerator to handle
12
+ * all content types uniformly while respecting their specific UI patterns.
13
+ */
14
+ /**
15
+ * Common language selector configuration
16
+ * Used across all content types that support language selection
17
+ * NotebookLM supports 80+ languages for content generation
18
+ */
19
+ export const COMMON_LANGUAGE_SELECTORS = {
20
+ dropdownTrigger: [
21
+ // Language dropdown triggers
22
+ 'button:has-text("Language")',
23
+ 'button:has-text("Select language")',
24
+ '[aria-label*="language" i]',
25
+ '[aria-label*="Language"]',
26
+ 'button:has(mat-icon:has-text("translate"))',
27
+ 'button:has(mat-icon:has-text("language"))',
28
+ '[class*="language-selector"]',
29
+ '[class*="language-dropdown"]',
30
+ 'mat-select[aria-label*="language" i]',
31
+ // Material Design selects
32
+ '.mat-mdc-select:has-text("Language")',
33
+ '.mdc-select:has-text("Language")',
34
+ ],
35
+ optionPattern: [
36
+ // Pattern with {language} placeholder
37
+ '[role="option"]:has-text("{language}")',
38
+ '[role="menuitem"]:has-text("{language}")',
39
+ 'mat-option:has-text("{language}")',
40
+ '.mdc-list-item:has-text("{language}")',
41
+ '[class*="option"]:has-text("{language}")',
42
+ 'li:has-text("{language}")',
43
+ ],
44
+ };
45
+ /**
46
+ * Video style selectors for Nano Banana AI visual styles
47
+ */
48
+ export const VIDEO_STYLE_SELECTORS = {
49
+ classroom: {
50
+ selectors: [
51
+ 'button:has-text("Classroom")',
52
+ 'button:has-text("classroom")',
53
+ '[role="option"]:has-text("Classroom")',
54
+ '[role="menuitem"]:has-text("Classroom")',
55
+ '[class*="style"]:has-text("Classroom")',
56
+ 'mat-option:has-text("Classroom")',
57
+ ],
58
+ displayName: 'Classroom',
59
+ },
60
+ documentary: {
61
+ selectors: [
62
+ 'button:has-text("Documentary")',
63
+ 'button:has-text("documentary")',
64
+ '[role="option"]:has-text("Documentary")',
65
+ '[role="menuitem"]:has-text("Documentary")',
66
+ '[class*="style"]:has-text("Documentary")',
67
+ 'mat-option:has-text("Documentary")',
68
+ ],
69
+ displayName: 'Documentary',
70
+ },
71
+ animated: {
72
+ selectors: [
73
+ 'button:has-text("Animated")',
74
+ 'button:has-text("animated")',
75
+ '[role="option"]:has-text("Animated")',
76
+ '[role="menuitem"]:has-text("Animated")',
77
+ '[class*="style"]:has-text("Animated")',
78
+ 'mat-option:has-text("Animated")',
79
+ ],
80
+ displayName: 'Animated',
81
+ },
82
+ corporate: {
83
+ selectors: [
84
+ 'button:has-text("Corporate")',
85
+ 'button:has-text("corporate")',
86
+ 'button:has-text("Business")',
87
+ '[role="option"]:has-text("Corporate")',
88
+ '[role="menuitem"]:has-text("Corporate")',
89
+ '[class*="style"]:has-text("Corporate")',
90
+ 'mat-option:has-text("Corporate")',
91
+ ],
92
+ displayName: 'Corporate',
93
+ },
94
+ cinematic: {
95
+ selectors: [
96
+ 'button:has-text("Cinematic")',
97
+ 'button:has-text("cinematic")',
98
+ '[role="option"]:has-text("Cinematic")',
99
+ '[role="menuitem"]:has-text("Cinematic")',
100
+ '[class*="style"]:has-text("Cinematic")',
101
+ 'mat-option:has-text("Cinematic")',
102
+ ],
103
+ displayName: 'Cinematic',
104
+ },
105
+ minimalist: {
106
+ selectors: [
107
+ 'button:has-text("Minimalist")',
108
+ 'button:has-text("minimalist")',
109
+ 'button:has-text("Simple")',
110
+ '[role="option"]:has-text("Minimalist")',
111
+ '[role="menuitem"]:has-text("Minimalist")',
112
+ '[class*="style"]:has-text("Minimalist")',
113
+ 'mat-option:has-text("Minimalist")',
114
+ ],
115
+ displayName: 'Minimalist',
116
+ },
117
+ };
118
+ /**
119
+ * Content type configurations for all Phase 1 content types
120
+ *
121
+ * Button selectors are based on NotebookLM Studio UI patterns:
122
+ * - Material Design buttons with text
123
+ * - Aria-label patterns for accessibility
124
+ * - Icon-based buttons with mat-icon
125
+ */
126
+ export const CONTENT_CONFIGS = {
127
+ // ============================================================================
128
+ // Audio Overview (existing, proven implementation)
129
+ // ============================================================================
130
+ audio_overview: {
131
+ type: 'audio_overview',
132
+ displayName: 'Audio Overview',
133
+ buttonSelectors: [
134
+ // Primary patterns
135
+ 'button:has-text("Audio")',
136
+ 'button:has-text("Generate audio")',
137
+ 'button:has-text("Deep Dive")',
138
+ // Localized patterns
139
+ 'button:has-text("Audio Overview")',
140
+ 'button:has-text("Podcast")',
141
+ // Aria patterns
142
+ 'button[aria-label*="audio" i]',
143
+ 'button[aria-label*="Audio"]',
144
+ // Icon-based patterns
145
+ 'button:has(mat-icon:has-text("mic"))',
146
+ 'button:has(mat-icon:has-text("podcast"))',
147
+ 'button:has(mat-icon:has-text("headphones"))',
148
+ // Card/section patterns
149
+ '[class*="audio"] button',
150
+ '.audio-overview button',
151
+ ],
152
+ languageSelectors: COMMON_LANGUAGE_SELECTORS,
153
+ existsSelectors: [
154
+ 'audio',
155
+ '.audio-player',
156
+ '[class*="audio-overview"]',
157
+ '[data-component="audio-player"]',
158
+ '[class*="audio-card"]',
159
+ ],
160
+ chatPromptTemplate: 'Create an audio overview (Deep Dive podcast) for this notebook.{languageInstruction} Generate a conversational podcast script that covers the main topics from all sources.{customInstructions}',
161
+ waitTimeout: 600000, // 10 minutes (audio generation is slow)
162
+ isMedia: true,
163
+ mimeType: 'audio/wav',
164
+ supportsCustomInstructions: true,
165
+ },
166
+ // ============================================================================
167
+ // Video
168
+ // ============================================================================
169
+ video: {
170
+ type: 'video',
171
+ displayName: 'Video',
172
+ buttonSelectors: [
173
+ // Primary patterns
174
+ 'button:has-text("Video")',
175
+ 'button:has-text("Generate video")',
176
+ 'button:has-text("Create video")',
177
+ // Aria patterns
178
+ 'button[aria-label*="video" i]',
179
+ 'button[aria-label*="Video"]',
180
+ // Icon-based patterns
181
+ 'button:has(mat-icon:has-text("videocam"))',
182
+ 'button:has(mat-icon:has-text("movie"))',
183
+ 'button:has(mat-icon:has-text("play_circle"))',
184
+ // Card/section patterns
185
+ '[class*="video"] button',
186
+ '.video-card button',
187
+ ],
188
+ formatSelectors: {
189
+ brief: {
190
+ selectors: [
191
+ 'button:has-text("Brief")',
192
+ 'button:has-text("brief")',
193
+ '[role="option"]:has-text("Brief")',
194
+ '[role="menuitem"]:has-text("Brief")',
195
+ '.format-option:has-text("Brief")',
196
+ '[class*="format"]:has-text("Brief")',
197
+ 'mat-option:has-text("Brief")',
198
+ ],
199
+ displayName: 'Brief',
200
+ },
201
+ explainer: {
202
+ selectors: [
203
+ 'button:has-text("Explainer")',
204
+ 'button:has-text("explainer")',
205
+ '[role="option"]:has-text("Explainer")',
206
+ '[role="menuitem"]:has-text("Explainer")',
207
+ '.format-option:has-text("Explainer")',
208
+ '[class*="format"]:has-text("Explainer")',
209
+ 'mat-option:has-text("Explainer")',
210
+ ],
211
+ displayName: 'Explainer',
212
+ },
213
+ },
214
+ defaultFormat: 'brief',
215
+ styleSelectors: VIDEO_STYLE_SELECTORS,
216
+ defaultStyle: 'animated',
217
+ languageSelectors: COMMON_LANGUAGE_SELECTORS,
218
+ existsSelectors: [
219
+ 'video',
220
+ '.video-player',
221
+ '[class*="video-overview"]',
222
+ '[data-component="video-player"]',
223
+ '[class*="video-card"][class*="ready"]',
224
+ ],
225
+ chatPromptTemplate: 'Create a {formatInstruction} video for this notebook.{languageInstruction}{styleInstruction} {formatDescription}{customInstructions}',
226
+ formatPrompts: {
227
+ brief: 'BRIEF (short, 1-2 minute)',
228
+ explainer: 'detailed EXPLAINER (comprehensive, 5-10 minute)',
229
+ },
230
+ stylePrompts: {
231
+ classroom: 'Use a CLASSROOM style with educational whiteboard-style visuals.',
232
+ documentary: 'Use a DOCUMENTARY style with news/documentary-like visuals.',
233
+ animated: 'Use an ANIMATED style with colorful animated graphics.',
234
+ corporate: 'Use a CORPORATE style with professional business visuals.',
235
+ cinematic: 'Use a CINEMATIC style with film-like visual aesthetics.',
236
+ minimalist: 'Use a MINIMALIST style with clean, simple visuals.',
237
+ },
238
+ waitTimeout: 600000, // 10 minutes (video generation can be slow)
239
+ isMedia: true,
240
+ mimeType: 'video/mp4',
241
+ supportsCustomInstructions: true,
242
+ },
243
+ // ============================================================================
244
+ // Infographic
245
+ // ============================================================================
246
+ infographic: {
247
+ type: 'infographic',
248
+ displayName: 'Infographic',
249
+ buttonSelectors: [
250
+ // Primary patterns
251
+ 'button:has-text("Infographic")',
252
+ 'button:has-text("Generate infographic")',
253
+ 'button:has-text("Create infographic")',
254
+ // Aria patterns
255
+ 'button[aria-label*="infographic" i]',
256
+ 'button[aria-label*="Infographic"]',
257
+ // Icon-based patterns
258
+ 'button:has(mat-icon:has-text("insert_chart"))',
259
+ 'button:has(mat-icon:has-text("analytics"))',
260
+ 'button:has(mat-icon:has-text("assessment"))',
261
+ 'button:has(mat-icon:has-text("bar_chart"))',
262
+ // Card/section patterns
263
+ '[class*="infographic"] button',
264
+ '.infographic-card button',
265
+ ],
266
+ formatSelectors: {
267
+ horizontal: {
268
+ selectors: [
269
+ 'button:has-text("Horizontal")',
270
+ 'button:has-text("horizontal")',
271
+ 'button:has-text("Landscape")',
272
+ '[role="option"]:has-text("Horizontal")',
273
+ '[role="menuitem"]:has-text("Horizontal")',
274
+ '.format-option:has-text("Horizontal")',
275
+ '[class*="format"]:has-text("Horizontal")',
276
+ 'mat-option:has-text("Horizontal")',
277
+ ],
278
+ displayName: 'Horizontal',
279
+ },
280
+ vertical: {
281
+ selectors: [
282
+ 'button:has-text("Vertical")',
283
+ 'button:has-text("vertical")',
284
+ 'button:has-text("Portrait")',
285
+ '[role="option"]:has-text("Vertical")',
286
+ '[role="menuitem"]:has-text("Vertical")',
287
+ '.format-option:has-text("Vertical")',
288
+ '[class*="format"]:has-text("Vertical")',
289
+ 'mat-option:has-text("Vertical")',
290
+ ],
291
+ displayName: 'Vertical',
292
+ },
293
+ },
294
+ defaultFormat: 'horizontal',
295
+ languageSelectors: COMMON_LANGUAGE_SELECTORS,
296
+ existsSelectors: [
297
+ '.infographic-viewer',
298
+ '[class*="infographic-preview"]',
299
+ '[class*="infographic-card"][class*="ready"]',
300
+ 'img[class*="infographic"]',
301
+ '[data-component="infographic"]',
302
+ ],
303
+ chatPromptTemplate: 'Create a {formatInstruction} infographic for this notebook.{languageInstruction} {formatDescription}{customInstructions}',
304
+ formatPrompts: {
305
+ horizontal: 'HORIZONTAL (landscape orientation, wide format)',
306
+ vertical: 'VERTICAL (portrait orientation, tall format)',
307
+ },
308
+ waitTimeout: 300000, // 5 minutes
309
+ isMedia: true,
310
+ mimeType: 'image/png',
311
+ supportsCustomInstructions: true,
312
+ },
313
+ // ============================================================================
314
+ // Report (Briefing Document)
315
+ // ============================================================================
316
+ report: {
317
+ type: 'report',
318
+ displayName: 'Report',
319
+ buttonSelectors: [
320
+ // Primary patterns
321
+ 'button:has-text("Briefing")',
322
+ 'button:has-text("Report")',
323
+ 'button:has-text("Briefing doc")',
324
+ 'button:has-text("Briefing Document")',
325
+ 'button:has-text("Generate report")',
326
+ // Aria patterns
327
+ 'button[aria-label*="briefing" i]',
328
+ 'button[aria-label*="report" i]',
329
+ 'button[aria-label*="Briefing"]',
330
+ 'button[aria-label*="Report"]',
331
+ // Icon-based patterns
332
+ 'button:has(mat-icon:has-text("description"))',
333
+ 'button:has(mat-icon:has-text("article"))',
334
+ 'button:has(mat-icon:has-text("summarize"))',
335
+ // Card/section patterns
336
+ '[class*="briefing"] button',
337
+ '[class*="report"] button',
338
+ '.briefing-card button',
339
+ ],
340
+ formatSelectors: {
341
+ summary: {
342
+ selectors: [
343
+ 'button:has-text("Summary")',
344
+ 'button:has-text("summary")',
345
+ 'button:has-text("Brief")',
346
+ '[role="option"]:has-text("Summary")',
347
+ '[role="menuitem"]:has-text("Summary")',
348
+ '.format-option:has-text("Summary")',
349
+ '[class*="format"]:has-text("Summary")',
350
+ 'mat-option:has-text("Summary")',
351
+ ],
352
+ displayName: 'Summary',
353
+ },
354
+ detailed: {
355
+ selectors: [
356
+ 'button:has-text("Detailed")',
357
+ 'button:has-text("detailed")',
358
+ 'button:has-text("Comprehensive")',
359
+ 'button:has-text("Full")',
360
+ '[role="option"]:has-text("Detailed")',
361
+ '[role="menuitem"]:has-text("Detailed")',
362
+ '.format-option:has-text("Detailed")',
363
+ '[class*="format"]:has-text("Detailed")',
364
+ 'mat-option:has-text("Detailed")',
365
+ ],
366
+ displayName: 'Detailed',
367
+ },
368
+ },
369
+ defaultFormat: 'summary',
370
+ languageSelectors: COMMON_LANGUAGE_SELECTORS,
371
+ existsSelectors: [
372
+ '.report-viewer',
373
+ '[class*="briefing-preview"]',
374
+ '[class*="report-card"][class*="ready"]',
375
+ '[data-component="report"]',
376
+ '[class*="briefing-doc"]',
377
+ ],
378
+ chatPromptTemplate: 'Create a {formatInstruction} briefing document for this notebook.{languageInstruction} {formatDescription}',
379
+ formatPrompts: {
380
+ summary: 'SUMMARY (concise, 1-2 page executive brief)',
381
+ detailed: 'DETAILED (comprehensive, in-depth analysis with all key findings)',
382
+ },
383
+ waitTimeout: 180000, // 3 minutes
384
+ isMedia: false,
385
+ supportsCustomInstructions: false, // Report does not support custom prompts
386
+ },
387
+ // ============================================================================
388
+ // Presentation (Slides)
389
+ // ============================================================================
390
+ presentation: {
391
+ type: 'presentation',
392
+ displayName: 'Presentation',
393
+ buttonSelectors: [
394
+ // Primary patterns
395
+ 'button:has-text("Slides")',
396
+ 'button:has-text("Presentation")',
397
+ 'button:has-text("Generate slides")',
398
+ 'button:has-text("Create presentation")',
399
+ 'button:has-text("Diaporama")',
400
+ // Aria patterns
401
+ 'button[aria-label*="slides" i]',
402
+ 'button[aria-label*="presentation" i]',
403
+ 'button[aria-label*="Slides"]',
404
+ 'button[aria-label*="Presentation"]',
405
+ // Icon-based patterns
406
+ 'button:has(mat-icon:has-text("slideshow"))',
407
+ 'button:has(mat-icon:has-text("present_to_all"))',
408
+ 'button:has(mat-icon:has-text("co_present"))',
409
+ // Card/section patterns
410
+ '[class*="slides"] button',
411
+ '[class*="presentation"] button',
412
+ '.slides-card button',
413
+ ],
414
+ // Style: detailed_slideshow vs presenter_notes
415
+ formatSelectors: {
416
+ detailed_slideshow: {
417
+ selectors: [
418
+ 'button:has-text("Detailed slideshow")',
419
+ 'button:has-text("Diaporama détaillé")',
420
+ 'button:has-text("detailed slideshow")',
421
+ '[role="option"]:has-text("Detailed slideshow")',
422
+ '[role="option"]:has-text("Diaporama détaillé")',
423
+ '[role="menuitem"]:has-text("Detailed slideshow")',
424
+ '.format-option:has-text("Detailed")',
425
+ '[class*="format"]:has-text("Detailed slideshow")',
426
+ 'mat-option:has-text("Detailed slideshow")',
427
+ ],
428
+ displayName: 'Detailed Slideshow',
429
+ },
430
+ presenter_notes: {
431
+ selectors: [
432
+ 'button:has-text("Presenter notes")',
433
+ 'button:has-text("Presenter slide")',
434
+ 'button:has-text("Diapositive du présentateur")',
435
+ 'button:has-text("presenter notes")',
436
+ '[role="option"]:has-text("Presenter")',
437
+ '[role="option"]:has-text("Diapositive du présentateur")',
438
+ '[role="menuitem"]:has-text("Presenter")',
439
+ '.format-option:has-text("Presenter")',
440
+ '[class*="format"]:has-text("Presenter")',
441
+ 'mat-option:has-text("Presenter")',
442
+ ],
443
+ displayName: 'Presenter Notes',
444
+ },
445
+ },
446
+ defaultFormat: 'detailed_slideshow',
447
+ // Length: short vs default
448
+ lengthSelectors: {
449
+ short: {
450
+ selectors: [
451
+ 'button:has-text("Short")',
452
+ 'button:has-text("Court")',
453
+ 'button:has-text("short")',
454
+ '[role="option"]:has-text("Short")',
455
+ '[role="option"]:has-text("Court")',
456
+ '[role="menuitem"]:has-text("Short")',
457
+ '.length-option:has-text("Short")',
458
+ '[class*="length"]:has-text("Short")',
459
+ 'mat-option:has-text("Short")',
460
+ ],
461
+ displayName: 'Short',
462
+ },
463
+ default: {
464
+ selectors: [
465
+ 'button:has-text("Default")',
466
+ 'button:has-text("Par défaut")',
467
+ 'button:has-text("Standard")',
468
+ '[role="option"]:has-text("Default")',
469
+ '[role="option"]:has-text("Par défaut")',
470
+ '[role="menuitem"]:has-text("Default")',
471
+ '.length-option:has-text("Default")',
472
+ '[class*="length"]:has-text("Default")',
473
+ 'mat-option:has-text("Default")',
474
+ ],
475
+ displayName: 'Default',
476
+ },
477
+ },
478
+ defaultLength: 'default',
479
+ languageSelectors: COMMON_LANGUAGE_SELECTORS,
480
+ existsSelectors: [
481
+ '.presentation-viewer',
482
+ '[class*="slides-preview"]',
483
+ '[class*="presentation-card"][class*="ready"]',
484
+ '[data-component="presentation"]',
485
+ '[class*="slides-viewer"]',
486
+ ],
487
+ chatPromptTemplate: 'Create a {formatInstruction} presentation for this notebook.{lengthInstruction}{languageInstruction} {formatDescription}{customInstructions}',
488
+ formatPrompts: {
489
+ detailed_slideshow: 'DETAILED SLIDESHOW with full visual slides',
490
+ presenter_notes: 'PRESENTER NOTES style slides with speaker notes',
491
+ },
492
+ waitTimeout: 300000, // 5 minutes
493
+ isMedia: true, // Can be exported to Google Slides/PDF
494
+ mimeType: 'application/pdf', // Primary download format
495
+ supportsCustomInstructions: true,
496
+ },
497
+ // ============================================================================
498
+ // Data Table (exports to Google Sheets)
499
+ // ============================================================================
500
+ data_table: {
501
+ type: 'data_table',
502
+ displayName: 'Data Table',
503
+ buttonSelectors: [
504
+ // Primary patterns
505
+ 'button:has-text("Table")',
506
+ 'button:has-text("Data")',
507
+ 'button:has-text("Data table")',
508
+ 'button:has-text("Generate table")',
509
+ 'button:has-text("Tableau")',
510
+ // Aria patterns
511
+ 'button[aria-label*="table" i]',
512
+ 'button[aria-label*="data" i]',
513
+ 'button[aria-label*="Table"]',
514
+ 'button[aria-label*="Data"]',
515
+ // Icon-based patterns
516
+ 'button:has(mat-icon:has-text("table_chart"))',
517
+ 'button:has(mat-icon:has-text("grid_on"))',
518
+ 'button:has(mat-icon:has-text("view_list"))',
519
+ // Card/section patterns
520
+ '[class*="table"] button',
521
+ '[class*="data-table"] button',
522
+ '.table-card button',
523
+ ],
524
+ // No format selectors - data table has no sub-formats in UI
525
+ languageSelectors: COMMON_LANGUAGE_SELECTORS,
526
+ existsSelectors: [
527
+ '.table-viewer',
528
+ '[class*="data-table-preview"]',
529
+ '[class*="table-card"][class*="ready"]',
530
+ '[data-component="data-table"]',
531
+ 'table[class*="generated"]',
532
+ // Google Sheets export button
533
+ 'button:has-text("Open in Sheets")',
534
+ 'button:has-text("Ouvrir dans Sheets")',
535
+ 'a[href*="docs.google.com/spreadsheets"]',
536
+ ],
537
+ chatPromptTemplate: 'Create a data table for this notebook.{languageInstruction} Extract key data points, metrics, and facts into a structured table format.{customInstructions}',
538
+ waitTimeout: 180000, // 3 minutes
539
+ isMedia: true, // Exports to Google Sheets
540
+ mimeType: 'application/vnd.google-apps.spreadsheet', // Google Sheets
541
+ supportsCustomInstructions: true,
542
+ },
543
+ };
544
+ /**
545
+ * Get configuration for a content type
546
+ * @param type Content type
547
+ * @returns Configuration or undefined if not found
548
+ */
549
+ export function getContentConfig(type) {
550
+ return CONTENT_CONFIGS[type];
551
+ }
552
+ /**
553
+ * Get all supported content types
554
+ * @returns Array of content type identifiers
555
+ */
556
+ export function getSupportedContentTypes() {
557
+ return Object.keys(CONTENT_CONFIGS);
558
+ }
559
+ /**
560
+ * Check if a content type is supported
561
+ * @param type Content type to check
562
+ * @returns True if supported
563
+ */
564
+ export function isContentTypeSupported(type) {
565
+ return type in CONTENT_CONFIGS;
566
+ }
567
+ /**
568
+ * Format descriptions for each content type, providing detailed instructions
569
+ */
570
+ const FORMAT_DESCRIPTIONS = {
571
+ audio_overview: {},
572
+ video: {
573
+ brief: 'Generate a structured video script that provides a quick, concise summary of the main topics. Keep it focused and punchy.',
574
+ explainer: 'Generate a comprehensive, educational video script that thoroughly explains each topic with examples and details.',
575
+ },
576
+ infographic: {
577
+ horizontal: 'Design the infographic in landscape orientation (wide format) suitable for presentations and widescreen displays.',
578
+ vertical: 'Design the infographic in portrait orientation (tall format) suitable for social media, mobile viewing, and print.',
579
+ },
580
+ report: {
581
+ summary: 'Write a concise executive summary that captures the essential findings and key takeaways.',
582
+ detailed: 'Write a comprehensive report with thorough analysis, detailed findings, supporting evidence, and recommendations.',
583
+ },
584
+ presentation: {
585
+ detailed_slideshow: 'Create a full visual slideshow with graphics, diagrams, and formatted content on each slide.',
586
+ presenter_notes: 'Create slides with comprehensive speaker notes for the presenter.',
587
+ },
588
+ data_table: {},
589
+ };
590
+ /**
591
+ * Length descriptions for presentation
592
+ */
593
+ const LENGTH_DESCRIPTIONS = {
594
+ short: 'Keep the presentation concise (5-8 slides).',
595
+ default: 'Create a standard-length presentation (10-15 slides).',
596
+ };
597
+ /**
598
+ * Get the format/style value from ContentGenerationInput based on content type
599
+ * @param input Content generation input
600
+ * @returns Format value or undefined
601
+ */
602
+ export function getFormatFromInput(input) {
603
+ switch (input.type) {
604
+ case 'video':
605
+ return input.videoFormat;
606
+ case 'infographic':
607
+ return input.infographicFormat;
608
+ case 'report':
609
+ return input.reportFormat;
610
+ case 'presentation':
611
+ return input.presentationStyle;
612
+ case 'data_table':
613
+ return undefined; // No format options for data table
614
+ default:
615
+ return undefined;
616
+ }
617
+ }
618
+ /**
619
+ * Get the length value from ContentGenerationInput (for presentation)
620
+ * @param input Content generation input
621
+ * @returns Length value or undefined
622
+ */
623
+ export function getLengthFromInput(input) {
624
+ if (input.type === 'presentation') {
625
+ return input.presentationLength;
626
+ }
627
+ return undefined;
628
+ }
629
+ /**
630
+ * Build a chat prompt from template, format, and custom instructions
631
+ * @param config Content type configuration
632
+ * @param input Content generation input (contains format options)
633
+ * @param customInstructions Optional custom instructions to include (fallback if not in input)
634
+ * @returns Formatted prompt string
635
+ */
636
+ export function buildChatPrompt(config, inputOrInstructions, customInstructions) {
637
+ let prompt = config.chatPromptTemplate;
638
+ // Handle both old signature (config, customInstructions) and new signature (config, input, customInstructions)
639
+ let format;
640
+ let length;
641
+ let instructions;
642
+ let language;
643
+ let videoStyle;
644
+ let input;
645
+ if (typeof inputOrInstructions === 'string') {
646
+ // Old signature: buildChatPrompt(config, customInstructions)
647
+ instructions = inputOrInstructions;
648
+ }
649
+ else if (inputOrInstructions) {
650
+ // New signature: buildChatPrompt(config, input, customInstructions)
651
+ input = inputOrInstructions;
652
+ format = getFormatFromInput(input);
653
+ length = getLengthFromInput(input);
654
+ instructions = customInstructions || input.customInstructions;
655
+ language = input.language;
656
+ videoStyle = input.videoStyle;
657
+ }
658
+ // Use default format if not specified
659
+ if (!format && config.defaultFormat) {
660
+ format = config.defaultFormat;
661
+ }
662
+ // Use default length if not specified
663
+ if (!length && config.defaultLength) {
664
+ length = config.defaultLength;
665
+ }
666
+ // Replace {formatInstruction} with format-specific text
667
+ if (format && config.formatPrompts && config.formatPrompts[format]) {
668
+ prompt = prompt.replace('{formatInstruction}', config.formatPrompts[format]);
669
+ }
670
+ else {
671
+ // Fallback: remove placeholder if no format
672
+ prompt = prompt.replace('{formatInstruction}', config.displayName.toLowerCase());
673
+ }
674
+ // Replace {formatDescription} with detailed description
675
+ const formatDescriptions = FORMAT_DESCRIPTIONS[config.type];
676
+ if (format && formatDescriptions && formatDescriptions[format]) {
677
+ prompt = prompt.replace('{formatDescription}', formatDescriptions[format]);
678
+ }
679
+ else {
680
+ prompt = prompt.replace('{formatDescription}', '');
681
+ }
682
+ // Replace {lengthInstruction} with length-specific text (for presentation)
683
+ if (length && LENGTH_DESCRIPTIONS[length]) {
684
+ prompt = prompt.replace('{lengthInstruction}', ` ${LENGTH_DESCRIPTIONS[length]}`);
685
+ }
686
+ else {
687
+ prompt = prompt.replace('{lengthInstruction}', '');
688
+ }
689
+ // Replace {languageInstruction} with language-specific text
690
+ if (language) {
691
+ prompt = prompt.replace('{languageInstruction}', ` Generate the content in ${language}.`);
692
+ }
693
+ else {
694
+ // Default: remove placeholder (English is assumed)
695
+ prompt = prompt.replace('{languageInstruction}', '');
696
+ }
697
+ // Replace {styleInstruction} with video style-specific text
698
+ if (videoStyle && config.stylePrompts && config.stylePrompts[videoStyle]) {
699
+ prompt = prompt.replace('{styleInstruction}', ` ${config.stylePrompts[videoStyle]}`);
700
+ }
701
+ else if (config.defaultStyle &&
702
+ config.stylePrompts &&
703
+ config.stylePrompts[config.defaultStyle]) {
704
+ // Use default style if none specified
705
+ prompt = prompt.replace('{styleInstruction}', ` ${config.stylePrompts[config.defaultStyle]}`);
706
+ }
707
+ else {
708
+ prompt = prompt.replace('{styleInstruction}', '');
709
+ }
710
+ // Replace {customInstructions}
711
+ if (instructions) {
712
+ prompt = prompt.replace('{customInstructions}', `\n\nCustom instructions: ${instructions}`);
713
+ }
714
+ else {
715
+ prompt = prompt.replace('{customInstructions}', '');
716
+ }
717
+ return prompt;
718
+ }
719
+ //# sourceMappingURL=content-templates.js.map