@pan-sec/notebooklm-mcp 1.4.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 (145) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +289 -0
  3. package/SECURITY.md +539 -0
  4. package/dist/auth/auth-manager.d.ts +137 -0
  5. package/dist/auth/auth-manager.d.ts.map +1 -0
  6. package/dist/auth/auth-manager.js +984 -0
  7. package/dist/auth/auth-manager.js.map +1 -0
  8. package/dist/auth/mcp-auth.d.ts +102 -0
  9. package/dist/auth/mcp-auth.d.ts.map +1 -0
  10. package/dist/auth/mcp-auth.js +286 -0
  11. package/dist/auth/mcp-auth.js.map +1 -0
  12. package/dist/config.d.ts +89 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +216 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/errors.d.ts +26 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +41 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/index.d.ts +32 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +371 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/library/notebook-library.d.ts +70 -0
  25. package/dist/library/notebook-library.d.ts.map +1 -0
  26. package/dist/library/notebook-library.js +279 -0
  27. package/dist/library/notebook-library.js.map +1 -0
  28. package/dist/library/types.d.ts +67 -0
  29. package/dist/library/types.d.ts.map +1 -0
  30. package/dist/library/types.js +8 -0
  31. package/dist/library/types.js.map +1 -0
  32. package/dist/resources/resource-handlers.d.ts +22 -0
  33. package/dist/resources/resource-handlers.d.ts.map +1 -0
  34. package/dist/resources/resource-handlers.js +216 -0
  35. package/dist/resources/resource-handlers.js.map +1 -0
  36. package/dist/session/browser-session.d.ts +108 -0
  37. package/dist/session/browser-session.d.ts.map +1 -0
  38. package/dist/session/browser-session.js +621 -0
  39. package/dist/session/browser-session.js.map +1 -0
  40. package/dist/session/session-manager.d.ts +77 -0
  41. package/dist/session/session-manager.d.ts.map +1 -0
  42. package/dist/session/session-manager.js +314 -0
  43. package/dist/session/session-manager.js.map +1 -0
  44. package/dist/session/session-timeout.d.ts +122 -0
  45. package/dist/session/session-timeout.d.ts.map +1 -0
  46. package/dist/session/session-timeout.js +281 -0
  47. package/dist/session/session-timeout.js.map +1 -0
  48. package/dist/session/shared-context-manager.d.ts +107 -0
  49. package/dist/session/shared-context-manager.d.ts.map +1 -0
  50. package/dist/session/shared-context-manager.js +447 -0
  51. package/dist/session/shared-context-manager.js.map +1 -0
  52. package/dist/tools/definitions/ask-question.d.ts +8 -0
  53. package/dist/tools/definitions/ask-question.d.ts.map +1 -0
  54. package/dist/tools/definitions/ask-question.js +211 -0
  55. package/dist/tools/definitions/ask-question.js.map +1 -0
  56. package/dist/tools/definitions/notebook-management.d.ts +3 -0
  57. package/dist/tools/definitions/notebook-management.d.ts.map +1 -0
  58. package/dist/tools/definitions/notebook-management.js +243 -0
  59. package/dist/tools/definitions/notebook-management.js.map +1 -0
  60. package/dist/tools/definitions/session-management.d.ts +3 -0
  61. package/dist/tools/definitions/session-management.d.ts.map +1 -0
  62. package/dist/tools/definitions/session-management.js +41 -0
  63. package/dist/tools/definitions/session-management.js.map +1 -0
  64. package/dist/tools/definitions/system.d.ts +3 -0
  65. package/dist/tools/definitions/system.d.ts.map +1 -0
  66. package/dist/tools/definitions/system.js +143 -0
  67. package/dist/tools/definitions/system.js.map +1 -0
  68. package/dist/tools/definitions.d.ts +12 -0
  69. package/dist/tools/definitions.d.ts.map +1 -0
  70. package/dist/tools/definitions.js +26 -0
  71. package/dist/tools/definitions.js.map +1 -0
  72. package/dist/tools/handlers.d.ts +213 -0
  73. package/dist/tools/handlers.d.ts.map +1 -0
  74. package/dist/tools/handlers.js +813 -0
  75. package/dist/tools/handlers.js.map +1 -0
  76. package/dist/tools/index.d.ts +8 -0
  77. package/dist/tools/index.d.ts.map +1 -0
  78. package/dist/tools/index.js +8 -0
  79. package/dist/tools/index.js.map +1 -0
  80. package/dist/types.d.ts +82 -0
  81. package/dist/types.d.ts.map +1 -0
  82. package/dist/types.js +5 -0
  83. package/dist/types.js.map +1 -0
  84. package/dist/utils/audit-logger.d.ts +140 -0
  85. package/dist/utils/audit-logger.d.ts.map +1 -0
  86. package/dist/utils/audit-logger.js +361 -0
  87. package/dist/utils/audit-logger.js.map +1 -0
  88. package/dist/utils/cert-pinning.d.ts +97 -0
  89. package/dist/utils/cert-pinning.d.ts.map +1 -0
  90. package/dist/utils/cert-pinning.js +328 -0
  91. package/dist/utils/cert-pinning.js.map +1 -0
  92. package/dist/utils/cleanup-manager.d.ts +133 -0
  93. package/dist/utils/cleanup-manager.d.ts.map +1 -0
  94. package/dist/utils/cleanup-manager.js +673 -0
  95. package/dist/utils/cleanup-manager.js.map +1 -0
  96. package/dist/utils/cli-handler.d.ts +16 -0
  97. package/dist/utils/cli-handler.d.ts.map +1 -0
  98. package/dist/utils/cli-handler.js +102 -0
  99. package/dist/utils/cli-handler.js.map +1 -0
  100. package/dist/utils/crypto.d.ts +175 -0
  101. package/dist/utils/crypto.d.ts.map +1 -0
  102. package/dist/utils/crypto.js +612 -0
  103. package/dist/utils/crypto.js.map +1 -0
  104. package/dist/utils/logger.d.ts +61 -0
  105. package/dist/utils/logger.d.ts.map +1 -0
  106. package/dist/utils/logger.js +92 -0
  107. package/dist/utils/logger.js.map +1 -0
  108. package/dist/utils/page-utils.d.ts +54 -0
  109. package/dist/utils/page-utils.d.ts.map +1 -0
  110. package/dist/utils/page-utils.js +405 -0
  111. package/dist/utils/page-utils.js.map +1 -0
  112. package/dist/utils/response-validator.d.ts +98 -0
  113. package/dist/utils/response-validator.d.ts.map +1 -0
  114. package/dist/utils/response-validator.js +352 -0
  115. package/dist/utils/response-validator.js.map +1 -0
  116. package/dist/utils/secrets-scanner.d.ts +126 -0
  117. package/dist/utils/secrets-scanner.d.ts.map +1 -0
  118. package/dist/utils/secrets-scanner.js +443 -0
  119. package/dist/utils/secrets-scanner.js.map +1 -0
  120. package/dist/utils/secure-memory.d.ts +130 -0
  121. package/dist/utils/secure-memory.d.ts.map +1 -0
  122. package/dist/utils/secure-memory.js +279 -0
  123. package/dist/utils/secure-memory.js.map +1 -0
  124. package/dist/utils/security.d.ts +83 -0
  125. package/dist/utils/security.d.ts.map +1 -0
  126. package/dist/utils/security.js +272 -0
  127. package/dist/utils/security.js.map +1 -0
  128. package/dist/utils/settings-manager.d.ts +37 -0
  129. package/dist/utils/settings-manager.d.ts.map +1 -0
  130. package/dist/utils/settings-manager.js +125 -0
  131. package/dist/utils/settings-manager.js.map +1 -0
  132. package/dist/utils/stealth-utils.d.ts +135 -0
  133. package/dist/utils/stealth-utils.d.ts.map +1 -0
  134. package/dist/utils/stealth-utils.js +398 -0
  135. package/dist/utils/stealth-utils.js.map +1 -0
  136. package/dist/utils/tool-validation.d.ts +93 -0
  137. package/dist/utils/tool-validation.d.ts.map +1 -0
  138. package/dist/utils/tool-validation.js +277 -0
  139. package/dist/utils/tool-validation.js.map +1 -0
  140. package/docs/SECURITY_IMPLEMENTATION_PLAN.md +437 -0
  141. package/docs/configuration.md +94 -0
  142. package/docs/tools.md +34 -0
  143. package/docs/troubleshooting.md +59 -0
  144. package/docs/usage-guide.md +245 -0
  145. package/package.json +82 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Console logging utilities with colors and formatting
3
+ * Similar to Python's rich.console
4
+ */
5
+ type LogLevel = "info" | "success" | "warning" | "error" | "debug" | "dim";
6
+ /**
7
+ * Logger class for consistent console output
8
+ */
9
+ export declare class Logger {
10
+ private enabled;
11
+ constructor(enabled?: boolean);
12
+ /**
13
+ * Log a message with a specific style
14
+ */
15
+ log(message: string, level?: LogLevel): void;
16
+ /**
17
+ * Log info message
18
+ */
19
+ info(message: string): void;
20
+ /**
21
+ * Log success message
22
+ */
23
+ success(message: string): void;
24
+ /**
25
+ * Log warning message
26
+ */
27
+ warning(message: string): void;
28
+ /**
29
+ * Log error message
30
+ */
31
+ error(message: string): void;
32
+ /**
33
+ * Log debug message
34
+ */
35
+ debug(message: string): void;
36
+ /**
37
+ * Log dim message (for less important info)
38
+ */
39
+ dim(message: string): void;
40
+ /**
41
+ * Enable or disable logging
42
+ */
43
+ setEnabled(enabled: boolean): void;
44
+ }
45
+ /**
46
+ * Global logger instance
47
+ */
48
+ export declare const logger: Logger;
49
+ /**
50
+ * Convenience functions for quick logging
51
+ */
52
+ export declare const log: {
53
+ info: (msg: string) => void;
54
+ success: (msg: string) => void;
55
+ warning: (msg: string) => void;
56
+ error: (msg: string) => void;
57
+ debug: (msg: string) => void;
58
+ dim: (msg: string) => void;
59
+ };
60
+ export {};
61
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;AAkB3E;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAU;gBAEb,OAAO,GAAE,OAAc;IAInC;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,QAAiB,GAAG,IAAI;IAWpD;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI1B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAGnC;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,QAAe,CAAC;AAEnC;;GAEG;AACH,eAAO,MAAM,GAAG;gBACF,MAAM;mBACH,MAAM;mBACN,MAAM;iBACR,MAAM;iBACN,MAAM;eACR,MAAM;CAClB,CAAC"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Console logging utilities with colors and formatting
3
+ * Similar to Python's rich.console
4
+ */
5
+ const STYLES = {
6
+ info: { prefix: "ℹ️", color: "\x1b[36m" }, // Cyan
7
+ success: { prefix: "✅", color: "\x1b[32m" }, // Green
8
+ warning: { prefix: "⚠️", color: "\x1b[33m" }, // Yellow
9
+ error: { prefix: "❌", color: "\x1b[31m" }, // Red
10
+ debug: { prefix: "🔍", color: "\x1b[35m" }, // Magenta
11
+ dim: { prefix: " ", color: "\x1b[2m" }, // Dim
12
+ };
13
+ const RESET = "\x1b[0m";
14
+ /**
15
+ * Logger class for consistent console output
16
+ */
17
+ export class Logger {
18
+ enabled;
19
+ constructor(enabled = true) {
20
+ this.enabled = enabled;
21
+ }
22
+ /**
23
+ * Log a message with a specific style
24
+ */
25
+ log(message, level = "info") {
26
+ if (!this.enabled)
27
+ return;
28
+ const style = STYLES[level];
29
+ const timestamp = new Date().toISOString().split("T")[1].slice(0, 8);
30
+ const formattedMessage = `${style.color}${style.prefix} [${timestamp}] ${message}${RESET}`;
31
+ // Use stderr for logs to keep stdout clean for MCP JSON-RPC
32
+ console.error(formattedMessage);
33
+ }
34
+ /**
35
+ * Log info message
36
+ */
37
+ info(message) {
38
+ this.log(message, "info");
39
+ }
40
+ /**
41
+ * Log success message
42
+ */
43
+ success(message) {
44
+ this.log(message, "success");
45
+ }
46
+ /**
47
+ * Log warning message
48
+ */
49
+ warning(message) {
50
+ this.log(message, "warning");
51
+ }
52
+ /**
53
+ * Log error message
54
+ */
55
+ error(message) {
56
+ this.log(message, "error");
57
+ }
58
+ /**
59
+ * Log debug message
60
+ */
61
+ debug(message) {
62
+ this.log(message, "debug");
63
+ }
64
+ /**
65
+ * Log dim message (for less important info)
66
+ */
67
+ dim(message) {
68
+ this.log(message, "dim");
69
+ }
70
+ /**
71
+ * Enable or disable logging
72
+ */
73
+ setEnabled(enabled) {
74
+ this.enabled = enabled;
75
+ }
76
+ }
77
+ /**
78
+ * Global logger instance
79
+ */
80
+ export const logger = new Logger();
81
+ /**
82
+ * Convenience functions for quick logging
83
+ */
84
+ export const log = {
85
+ info: (msg) => logger.info(msg),
86
+ success: (msg) => logger.success(msg),
87
+ warning: (msg) => logger.warning(msg),
88
+ error: (msg) => logger.error(msg),
89
+ debug: (msg) => logger.debug(msg),
90
+ dim: (msg) => logger.dim(msg),
91
+ };
92
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Page utilities for extracting responses from NotebookLM web UI
3
+ *
4
+ * This module provides functions to:
5
+ * - Extract latest assistant responses from the page
6
+ * - Wait for new responses with streaming detection
7
+ * - Detect placeholders and loading states
8
+ * - Snapshot existing responses for comparison
9
+ *
10
+ * Based on the Python implementation from page_utils.py
11
+ */
12
+ import type { Page } from "patchright";
13
+ /**
14
+ * Snapshot the latest response text currently visible
15
+ * Returns null if no response found
16
+ */
17
+ export declare function snapshotLatestResponse(page: Page): Promise<string | null>;
18
+ /**
19
+ * Snapshot ALL existing assistant response texts
20
+ * Used to capture visible responses BEFORE submitting a new question
21
+ */
22
+ export declare function snapshotAllResponses(page: Page): Promise<string[]>;
23
+ /**
24
+ * Count the number of visible assistant response elements
25
+ */
26
+ export declare function countResponseElements(page: Page): Promise<number>;
27
+ /**
28
+ * Wait for a new assistant response with streaming detection
29
+ *
30
+ * This function:
31
+ * 1. Polls the page for new response text
32
+ * 2. Detects streaming (text changes) vs. complete (text stable)
33
+ * 3. Requires text to be stable for 3 consecutive polls before returning
34
+ * 4. Ignores placeholders, question echoes, and known responses
35
+ *
36
+ * @param page Playwright page instance
37
+ * @param options Options for waiting
38
+ * @returns The new response text, or null if timeout
39
+ */
40
+ export declare function waitForLatestAnswer(page: Page, options?: {
41
+ question?: string;
42
+ timeoutMs?: number;
43
+ pollIntervalMs?: number;
44
+ ignoreTexts?: string[];
45
+ debug?: boolean;
46
+ }): Promise<string | null>;
47
+ declare const _default: {
48
+ snapshotLatestResponse: typeof snapshotLatestResponse;
49
+ snapshotAllResponses: typeof snapshotAllResponses;
50
+ countResponseElements: typeof countResponseElements;
51
+ waitForLatestAnswer: typeof waitForLatestAnswer;
52
+ };
53
+ export default _default;
54
+ //# sourceMappingURL=page-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-utils.d.ts","sourceRoot":"","sources":["../../src/utils/page-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAkDvC;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE/E;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BxE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BvE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACZ,GACL,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiHxB;;;;;;;AAuMD,wBAKE"}
@@ -0,0 +1,405 @@
1
+ /**
2
+ * Page utilities for extracting responses from NotebookLM web UI
3
+ *
4
+ * This module provides functions to:
5
+ * - Extract latest assistant responses from the page
6
+ * - Wait for new responses with streaming detection
7
+ * - Detect placeholders and loading states
8
+ * - Snapshot existing responses for comparison
9
+ *
10
+ * Based on the Python implementation from page_utils.py
11
+ */
12
+ import { log } from "./logger.js";
13
+ // ============================================================================
14
+ // Constants
15
+ // ============================================================================
16
+ /**
17
+ * CSS selectors to find assistant response elements
18
+ * Ordered by priority (most specific first)
19
+ */
20
+ const RESPONSE_SELECTORS = [
21
+ ".to-user-container .message-text-content",
22
+ "[data-message-author='bot']",
23
+ "[data-message-author='assistant']",
24
+ "[data-message-role='assistant']",
25
+ "[data-author='assistant']",
26
+ "[data-renderer*='assistant']",
27
+ "[data-automation-id='response-text']",
28
+ "[data-automation-id='assistant-response']",
29
+ "[data-automation-id='chat-response']",
30
+ "[data-testid*='assistant']",
31
+ "[data-testid*='response']",
32
+ "[aria-live='polite']",
33
+ "[role='listitem'][data-message-author]",
34
+ ];
35
+ // ============================================================================
36
+ // Helper Functions
37
+ // ============================================================================
38
+ /**
39
+ * Simple string hash function (for efficient comparison)
40
+ */
41
+ function hashString(str) {
42
+ let hash = 0;
43
+ for (let i = 0; i < str.length; i++) {
44
+ const char = str.charCodeAt(i);
45
+ hash = (hash << 5) - hash + char;
46
+ hash = hash & hash; // Convert to 32bit integer
47
+ }
48
+ return hash;
49
+ }
50
+ // ============================================================================
51
+ // Main Functions
52
+ // ============================================================================
53
+ /**
54
+ * Snapshot the latest response text currently visible
55
+ * Returns null if no response found
56
+ */
57
+ export async function snapshotLatestResponse(page) {
58
+ return await extractLatestText(page, new Set(), false, 0);
59
+ }
60
+ /**
61
+ * Snapshot ALL existing assistant response texts
62
+ * Used to capture visible responses BEFORE submitting a new question
63
+ */
64
+ export async function snapshotAllResponses(page) {
65
+ const allTexts = [];
66
+ const primarySelector = ".to-user-container";
67
+ try {
68
+ const containers = await page.$$(primarySelector);
69
+ if (containers.length > 0) {
70
+ for (const container of containers) {
71
+ try {
72
+ const textElement = await container.$(".message-text-content");
73
+ if (textElement) {
74
+ const text = await textElement.innerText();
75
+ if (text && text.trim()) {
76
+ allTexts.push(text.trim());
77
+ }
78
+ }
79
+ }
80
+ catch {
81
+ continue;
82
+ }
83
+ }
84
+ log.info(`📸 [SNAPSHOT] Captured ${allTexts.length} existing responses`);
85
+ }
86
+ }
87
+ catch (error) {
88
+ log.warning(`⚠️ [SNAPSHOT] Failed to snapshot responses: ${error}`);
89
+ }
90
+ return allTexts;
91
+ }
92
+ /**
93
+ * Count the number of visible assistant response elements
94
+ */
95
+ export async function countResponseElements(page) {
96
+ let count = 0;
97
+ for (const selector of RESPONSE_SELECTORS) {
98
+ try {
99
+ const elements = await page.$$(selector);
100
+ if (elements.length > 0) {
101
+ // Count only visible elements
102
+ for (const el of elements) {
103
+ try {
104
+ const isVisible = await el.isVisible();
105
+ if (isVisible) {
106
+ count++;
107
+ }
108
+ }
109
+ catch {
110
+ continue;
111
+ }
112
+ }
113
+ // If we found elements with this selector, stop trying others
114
+ if (count > 0) {
115
+ break;
116
+ }
117
+ }
118
+ }
119
+ catch {
120
+ continue;
121
+ }
122
+ }
123
+ return count;
124
+ }
125
+ /**
126
+ * Wait for a new assistant response with streaming detection
127
+ *
128
+ * This function:
129
+ * 1. Polls the page for new response text
130
+ * 2. Detects streaming (text changes) vs. complete (text stable)
131
+ * 3. Requires text to be stable for 3 consecutive polls before returning
132
+ * 4. Ignores placeholders, question echoes, and known responses
133
+ *
134
+ * @param page Playwright page instance
135
+ * @param options Options for waiting
136
+ * @returns The new response text, or null if timeout
137
+ */
138
+ export async function waitForLatestAnswer(page, options = {}) {
139
+ const { question = "", timeoutMs = 120000, pollIntervalMs = 1000, ignoreTexts = [], debug = false, } = options;
140
+ const deadline = Date.now() + timeoutMs;
141
+ const sanitizedQuestion = question.trim().toLowerCase();
142
+ // Track ALL known texts as HASHES (memory efficient!)
143
+ const knownHashes = new Set();
144
+ for (const text of ignoreTexts) {
145
+ if (typeof text === "string" && text.trim()) {
146
+ knownHashes.add(hashString(text.trim()));
147
+ }
148
+ }
149
+ if (debug) {
150
+ log.debug(`🔍 [DEBUG] Waiting for NEW answer. Ignoring ${knownHashes.size} known responses`);
151
+ }
152
+ let pollCount = 0;
153
+ let lastCandidate = null;
154
+ let stableCount = 0; // Track how many times we see the same text
155
+ const requiredStablePolls = 3; // Text must be stable for 3 consecutive polls
156
+ while (Date.now() < deadline) {
157
+ pollCount++;
158
+ // Check if NotebookLM is still "thinking" (most reliable indicator)
159
+ try {
160
+ const thinkingElement = await page.$('div.thinking-message');
161
+ if (thinkingElement) {
162
+ const isVisible = await thinkingElement.isVisible();
163
+ if (isVisible) {
164
+ if (debug && pollCount % 5 === 0) {
165
+ log.debug("🔍 [DEBUG] NotebookLM still thinking (div.thinking-message visible)...");
166
+ }
167
+ await page.waitForTimeout(pollIntervalMs);
168
+ continue;
169
+ }
170
+ }
171
+ }
172
+ catch {
173
+ // Ignore errors checking thinking state
174
+ }
175
+ // Extract latest NEW text
176
+ const candidate = await extractLatestText(page, knownHashes, debug, pollCount);
177
+ if (candidate) {
178
+ const normalized = candidate.trim();
179
+ if (normalized) {
180
+ const lower = normalized.toLowerCase();
181
+ // Check if it's the question echo
182
+ if (lower === sanitizedQuestion) {
183
+ if (debug) {
184
+ log.debug("🔍 [DEBUG] Found question echo, ignoring");
185
+ }
186
+ knownHashes.add(hashString(normalized)); // Mark as seen
187
+ await page.waitForTimeout(pollIntervalMs);
188
+ continue;
189
+ }
190
+ // ========================================
191
+ // STREAMING DETECTION: Check if text is stable
192
+ // ========================================
193
+ if (normalized === lastCandidate) {
194
+ // Text hasn't changed - it's stable
195
+ stableCount++;
196
+ if (debug && stableCount === requiredStablePolls) {
197
+ log.debug(`✅ [DEBUG] Text stable for ${stableCount} polls (${normalized.length} chars)`);
198
+ }
199
+ }
200
+ else {
201
+ // Text changed - streaming in progress
202
+ if (debug && lastCandidate) {
203
+ log.debug(`🔄 [DEBUG] Text changed (${normalized.length} chars, was ${lastCandidate.length})`);
204
+ }
205
+ stableCount = 1;
206
+ lastCandidate = normalized;
207
+ }
208
+ // Only return once text is stable
209
+ if (stableCount >= requiredStablePolls) {
210
+ if (debug) {
211
+ log.debug(`✅ [DEBUG] Returning stable answer (${normalized.length} chars)`);
212
+ }
213
+ return normalized;
214
+ }
215
+ }
216
+ }
217
+ await page.waitForTimeout(pollIntervalMs);
218
+ }
219
+ if (debug) {
220
+ log.debug(`⏱️ [DEBUG] Timeout after ${pollCount} polls`);
221
+ }
222
+ return null;
223
+ }
224
+ /**
225
+ * Extract the latest NEW response text from the page
226
+ * Uses hash-based comparison for efficiency
227
+ *
228
+ * @param page Playwright page instance
229
+ * @param knownHashes Set of hashes of already-seen response texts
230
+ * @param debug Enable debug logging
231
+ * @param pollCount Current poll number (for conditional logging)
232
+ * @returns First NEW response text found, or null
233
+ */
234
+ async function extractLatestText(page, knownHashes, debug, pollCount) {
235
+ // Try the primary selector first (most specific for NotebookLM)
236
+ const primarySelector = ".to-user-container";
237
+ try {
238
+ const containers = await page.$$(primarySelector);
239
+ const totalContainers = containers.length;
240
+ // Early exit if no new containers possible
241
+ if (totalContainers <= knownHashes.size) {
242
+ if (debug && pollCount % 5 === 0) {
243
+ log.dim(`⏭️ [EXTRACT] No new containers (${totalContainers} total, ${knownHashes.size} known)`);
244
+ }
245
+ return null;
246
+ }
247
+ if (containers.length > 0) {
248
+ // Only log every 5th poll to reduce noise
249
+ if (debug && pollCount % 5 === 0) {
250
+ log.dim(`🔍 [EXTRACT] Scanning ${totalContainers} containers (${knownHashes.size} known)`);
251
+ }
252
+ let skipped = 0;
253
+ let empty = 0;
254
+ // Scan ALL containers to find the FIRST with NEW text
255
+ for (let idx = 0; idx < containers.length; idx++) {
256
+ const container = containers[idx];
257
+ try {
258
+ const textElement = await container.$(".message-text-content");
259
+ if (textElement) {
260
+ const text = await textElement.innerText();
261
+ if (text && text.trim()) {
262
+ // Hash-based comparison (faster & less memory)
263
+ const textHash = hashString(text.trim());
264
+ if (!knownHashes.has(textHash)) {
265
+ log.success(`✅ [EXTRACT] Found NEW text in container[${idx}]: ${text.trim().length} chars`);
266
+ return text.trim();
267
+ }
268
+ else {
269
+ skipped++;
270
+ }
271
+ }
272
+ else {
273
+ empty++;
274
+ }
275
+ }
276
+ }
277
+ catch {
278
+ continue;
279
+ }
280
+ }
281
+ // Only log summary if debug enabled
282
+ if (debug && pollCount % 5 === 0) {
283
+ log.dim(`⏭️ [EXTRACT] No NEW text (skipped ${skipped} known, ${empty} empty)`);
284
+ }
285
+ return null; // Don't fall through to fallback!
286
+ }
287
+ else {
288
+ if (debug) {
289
+ log.warning("⚠️ [EXTRACT] No containers found");
290
+ }
291
+ }
292
+ }
293
+ catch (error) {
294
+ log.error(`❌ [EXTRACT] Primary selector failed: ${error}`);
295
+ }
296
+ // Fallback: Try other selectors (only if primary selector failed/found nothing)
297
+ if (debug) {
298
+ log.dim("🔄 [EXTRACT] Trying fallback selectors...");
299
+ }
300
+ for (const selector of RESPONSE_SELECTORS) {
301
+ try {
302
+ const elements = await page.$$(selector);
303
+ if (elements.length === 0)
304
+ continue;
305
+ // Scan ALL elements to find the first with NEW text
306
+ for (const element of elements) {
307
+ try {
308
+ // Prefer full container text when available
309
+ let container = element;
310
+ try {
311
+ const closest = await element.evaluateHandle((el) => {
312
+ return el.closest("[data-message-author], [data-message-role], [data-author], " +
313
+ "[data-testid*='assistant'], [data-automation-id*='response'], article, section");
314
+ });
315
+ if (closest) {
316
+ container = closest.asElement() || element;
317
+ }
318
+ }
319
+ catch {
320
+ container = element;
321
+ }
322
+ const text = await container.innerText();
323
+ if (text && text.trim() && !knownHashes.has(hashString(text.trim()))) {
324
+ return text.trim();
325
+ }
326
+ }
327
+ catch {
328
+ continue;
329
+ }
330
+ }
331
+ }
332
+ catch {
333
+ continue;
334
+ }
335
+ }
336
+ // Final fallback: JavaScript evaluation
337
+ try {
338
+ const fallbackText = await page.evaluate(() => {
339
+ // @ts-expect-error - DOM types available in browser context
340
+ const unique = new Set();
341
+ // @ts-expect-error - DOM types available in browser context
342
+ const isVisible = (el) => {
343
+ // @ts-expect-error - DOM types available in browser context
344
+ if (!el || !el.isConnected)
345
+ return false;
346
+ const rect = el.getBoundingClientRect();
347
+ if (rect.width === 0 || rect.height === 0)
348
+ return false;
349
+ // @ts-expect-error - window available in browser context
350
+ const style = window.getComputedStyle(el);
351
+ if (style.visibility === "hidden" ||
352
+ style.display === "none" ||
353
+ parseFloat(style.opacity || "1") === 0) {
354
+ return false;
355
+ }
356
+ return true;
357
+ };
358
+ const selectors = [
359
+ "[data-message-author]",
360
+ "[data-message-role]",
361
+ "[data-author]",
362
+ "[data-renderer*='assistant']",
363
+ "[data-testid*='assistant']",
364
+ "[data-automation-id*='response']",
365
+ ];
366
+ const candidates = [];
367
+ for (const selector of selectors) {
368
+ // @ts-expect-error - document available in browser context
369
+ for (const el of document.querySelectorAll(selector)) {
370
+ if (!isVisible(el))
371
+ continue;
372
+ if (unique.has(el))
373
+ continue;
374
+ unique.add(el);
375
+ // @ts-expect-error - DOM types available in browser context
376
+ const text = el.innerText || el.textContent || "";
377
+ if (!text.trim())
378
+ continue;
379
+ candidates.push(text.trim());
380
+ }
381
+ }
382
+ if (candidates.length > 0) {
383
+ return candidates[candidates.length - 1];
384
+ }
385
+ return null;
386
+ });
387
+ if (typeof fallbackText === "string" && fallbackText.trim()) {
388
+ return fallbackText.trim();
389
+ }
390
+ }
391
+ catch {
392
+ // Ignore evaluation errors
393
+ }
394
+ return null;
395
+ }
396
+ // ============================================================================
397
+ // Exports
398
+ // ============================================================================
399
+ export default {
400
+ snapshotLatestResponse,
401
+ snapshotAllResponses,
402
+ countResponseElements,
403
+ waitForLatestAnswer,
404
+ };
405
+ //# sourceMappingURL=page-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-utils.js","sourceRoot":"","sources":["../../src/utils/page-utils.ts"],"names":[],"mappings":"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"}