@roomi-fields/notebooklm-mcp 1.1.2
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/LICENSE +22 -0
- package/README.md +548 -0
- package/dist/auth/auth-manager.d.ts +139 -0
- package/dist/auth/auth-manager.d.ts.map +1 -0
- package/dist/auth/auth-manager.js +981 -0
- package/dist/auth/auth-manager.js.map +1 -0
- package/dist/config.d.ts +89 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +216 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/http-wrapper.d.ts +8 -0
- package/dist/http-wrapper.d.ts.map +1 -0
- package/dist/http-wrapper.js +221 -0
- package/dist/http-wrapper.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +499 -0
- package/dist/index.js.map +1 -0
- package/dist/library/notebook-library.d.ts +81 -0
- package/dist/library/notebook-library.d.ts.map +1 -0
- package/dist/library/notebook-library.js +362 -0
- package/dist/library/notebook-library.js.map +1 -0
- package/dist/library/types.d.ts +67 -0
- package/dist/library/types.d.ts.map +1 -0
- package/dist/library/types.js +8 -0
- package/dist/library/types.js.map +1 -0
- package/dist/session/browser-session.d.ts +108 -0
- package/dist/session/browser-session.d.ts.map +1 -0
- package/dist/session/browser-session.js +630 -0
- package/dist/session/browser-session.js.map +1 -0
- package/dist/session/session-manager.d.ts +76 -0
- package/dist/session/session-manager.d.ts.map +1 -0
- package/dist/session/session-manager.js +273 -0
- package/dist/session/session-manager.js.map +1 -0
- package/dist/session/shared-context-manager.d.ts +107 -0
- package/dist/session/shared-context-manager.d.ts.map +1 -0
- package/dist/session/shared-context-manager.js +447 -0
- package/dist/session/shared-context-manager.js.map +1 -0
- package/dist/tools/index.d.ts +225 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +1396 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cleanup-manager.d.ts +133 -0
- package/dist/utils/cleanup-manager.d.ts.map +1 -0
- package/dist/utils/cleanup-manager.js +673 -0
- package/dist/utils/cleanup-manager.js.map +1 -0
- package/dist/utils/logger.d.ts +61 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +92 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/page-utils.d.ts +54 -0
- package/dist/utils/page-utils.d.ts.map +1 -0
- package/dist/utils/page-utils.js +422 -0
- package/dist/utils/page-utils.js.map +1 -0
- package/dist/utils/stealth-utils.d.ts +135 -0
- package/dist/utils/stealth-utils.d.ts.map +1 -0
- package/dist/utils/stealth-utils.js +398 -0
- package/dist/utils/stealth-utils.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Context Manager with Persistent Chrome Profile
|
|
3
|
+
*
|
|
4
|
+
* Manages ONE global persistent BrowserContext for ALL sessions.
|
|
5
|
+
* This is critical for avoiding bot detection:
|
|
6
|
+
*
|
|
7
|
+
* - Google tracks browser fingerprints (Canvas, WebGL, Audio, Fonts, etc.)
|
|
8
|
+
* - Multiple contexts = Multiple fingerprints = Suspicious!
|
|
9
|
+
* - ONE persistent context = ONE consistent fingerprint = Normal user
|
|
10
|
+
* - Persistent user_data_dir = SAME fingerprint across all app restarts!
|
|
11
|
+
*
|
|
12
|
+
* Based on the Python implementation from shared_context_manager.py
|
|
13
|
+
*/
|
|
14
|
+
import { chromium } from "patchright";
|
|
15
|
+
import { CONFIG } from "../config.js";
|
|
16
|
+
import { log } from "../utils/logger.js";
|
|
17
|
+
import fs from "fs";
|
|
18
|
+
import path from "path";
|
|
19
|
+
/**
|
|
20
|
+
* Shared Context Manager
|
|
21
|
+
*
|
|
22
|
+
* Benefits:
|
|
23
|
+
* 1. ONE consistent browser fingerprint for all sessions
|
|
24
|
+
* 2. Fingerprint persists across app restarts (user_data_dir)
|
|
25
|
+
* 3. Mimics real user behavior (one browser, multiple tabs)
|
|
26
|
+
* 4. Google sees: "Same browser since day 1"
|
|
27
|
+
*/
|
|
28
|
+
export class SharedContextManager {
|
|
29
|
+
authManager;
|
|
30
|
+
globalContext = null;
|
|
31
|
+
contextCreatedAt = null;
|
|
32
|
+
currentProfileDir = null;
|
|
33
|
+
isIsolatedProfile = false;
|
|
34
|
+
currentHeadlessMode = null;
|
|
35
|
+
constructor(authManager) {
|
|
36
|
+
this.authManager = authManager;
|
|
37
|
+
log.info("🌐 SharedContextManager initialized (PERSISTENT MODE)");
|
|
38
|
+
log.info(` Chrome Profile: ${CONFIG.chromeProfileDir}`);
|
|
39
|
+
log.success(" Fingerprint: PERSISTENT across restarts! 🎯");
|
|
40
|
+
// Cleanup old isolated profiles at startup (best-effort)
|
|
41
|
+
if (CONFIG.cleanupInstancesOnStartup) {
|
|
42
|
+
void this.pruneIsolatedProfiles("startup");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the global shared persistent context, or create new if needed
|
|
47
|
+
*
|
|
48
|
+
* Context is recreated only when:
|
|
49
|
+
* - First time (no context exists in this app instance)
|
|
50
|
+
* - Context was closed/invalid
|
|
51
|
+
*
|
|
52
|
+
* Note: Auth expiry does NOT recreate context - we reuse the SAME
|
|
53
|
+
* fingerprint and just re-login!
|
|
54
|
+
*
|
|
55
|
+
* @param overrideHeadless Optional override for headless mode (true = show browser)
|
|
56
|
+
*/
|
|
57
|
+
async getOrCreateContext(overrideHeadless) {
|
|
58
|
+
// Check if headless mode needs to be changed (e.g., show_browser=true)
|
|
59
|
+
// If yes, close the browser so it gets recreated with the new mode
|
|
60
|
+
if (this.needsHeadlessModeChange(overrideHeadless)) {
|
|
61
|
+
log.warning("🔄 Headless mode change detected - recreating browser context...");
|
|
62
|
+
await this.closeContext();
|
|
63
|
+
}
|
|
64
|
+
if (await this.needsRecreation()) {
|
|
65
|
+
log.warning("🔄 Creating/Loading persistent context...");
|
|
66
|
+
await this.recreateContext(overrideHeadless);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
log.success("♻️ Reusing existing persistent context");
|
|
70
|
+
}
|
|
71
|
+
return this.globalContext;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if global context needs to be recreated
|
|
75
|
+
*/
|
|
76
|
+
async needsRecreation() {
|
|
77
|
+
// No context exists yet (first time or after manual close)
|
|
78
|
+
if (!this.globalContext) {
|
|
79
|
+
log.info(" ℹ️ No context exists yet");
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
// Async validity check (will throw if closed)
|
|
83
|
+
try {
|
|
84
|
+
await this.globalContext.cookies();
|
|
85
|
+
log.dim(" ✅ Context still valid (browser open)");
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
log.warning(" ⚠️ Context appears closed - will recreate");
|
|
90
|
+
this.globalContext = null;
|
|
91
|
+
this.contextCreatedAt = null;
|
|
92
|
+
this.currentHeadlessMode = null;
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create/Load the global PERSISTENT context with Chrome user_data_dir
|
|
98
|
+
*
|
|
99
|
+
* This is THE KEY to fingerprint persistence!
|
|
100
|
+
*
|
|
101
|
+
* First time:
|
|
102
|
+
* - Chrome creates new profile in user_data_dir
|
|
103
|
+
* - Generates fingerprint (Canvas, WebGL, Audio, etc.)
|
|
104
|
+
* - Saves everything to disk
|
|
105
|
+
*
|
|
106
|
+
* Subsequent starts:
|
|
107
|
+
* - Chrome loads profile from user_data_dir
|
|
108
|
+
* - SAME fingerprint as before! ✅
|
|
109
|
+
* - Google sees: "Same browser since day 1"
|
|
110
|
+
*
|
|
111
|
+
* @param overrideHeadless Optional override for headless mode (true = show browser)
|
|
112
|
+
*/
|
|
113
|
+
async recreateContext(overrideHeadless) {
|
|
114
|
+
// Close old context if exists
|
|
115
|
+
if (this.globalContext) {
|
|
116
|
+
try {
|
|
117
|
+
log.info(" 🗑️ Closing old context...");
|
|
118
|
+
await this.globalContext.close();
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
log.warning(` ⚠️ Error closing old context: ${error}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Check for saved auth
|
|
125
|
+
const statePath = await this.authManager.getValidStatePath();
|
|
126
|
+
if (statePath) {
|
|
127
|
+
log.success(` 📂 Found auth state: ${statePath}`);
|
|
128
|
+
log.info(" 💡 Will load cookies into persistent profile");
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
log.warning(" 🆕 No saved auth - fresh persistent profile");
|
|
132
|
+
log.info(" 💡 First login will save auth to persistent profile");
|
|
133
|
+
}
|
|
134
|
+
// Determine headless mode: use override if provided, otherwise use CONFIG
|
|
135
|
+
const shouldBeHeadless = overrideHeadless !== undefined ? !overrideHeadless : CONFIG.headless;
|
|
136
|
+
if (overrideHeadless !== undefined) {
|
|
137
|
+
log.info(` Browser visibility override: ${overrideHeadless ? 'VISIBLE' : 'HEADLESS'}`);
|
|
138
|
+
}
|
|
139
|
+
// Build launch options for persistent context
|
|
140
|
+
// NOTE: userDataDir is passed as first parameter, NOT in options!
|
|
141
|
+
const launchOptions = {
|
|
142
|
+
headless: shouldBeHeadless,
|
|
143
|
+
channel: "chrome",
|
|
144
|
+
viewport: CONFIG.viewport,
|
|
145
|
+
locale: "en-US",
|
|
146
|
+
timezoneId: "Europe/Berlin",
|
|
147
|
+
// ✅ CRITICAL FIX: Pass storageState directly at launch!
|
|
148
|
+
// This is the PROPER way to handle session cookies (Playwright bug workaround)
|
|
149
|
+
// Benefits:
|
|
150
|
+
// - Session cookies persist correctly
|
|
151
|
+
// - No need for addCookies() workarounds
|
|
152
|
+
// - Chrome loads everything automatically
|
|
153
|
+
...(statePath && { storageState: statePath }),
|
|
154
|
+
args: [
|
|
155
|
+
"--disable-blink-features=AutomationControlled",
|
|
156
|
+
"--disable-dev-shm-usage",
|
|
157
|
+
"--no-first-run",
|
|
158
|
+
"--no-default-browser-check",
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
// 🔥 CRITICAL: launchPersistentContext creates/loads Chrome profile
|
|
162
|
+
// Strategy handling for concurrent instances
|
|
163
|
+
const baseProfile = CONFIG.chromeProfileDir;
|
|
164
|
+
const strategy = CONFIG.profileStrategy;
|
|
165
|
+
const tryLaunch = async (userDataDir) => {
|
|
166
|
+
log.info(" 🚀 Launching persistent Chrome context...");
|
|
167
|
+
log.dim(` 📍 Profile location: ${userDataDir}`);
|
|
168
|
+
if (statePath) {
|
|
169
|
+
log.info(` 📄 Loading auth state: ${statePath}`);
|
|
170
|
+
}
|
|
171
|
+
return chromium.launchPersistentContext(userDataDir, launchOptions);
|
|
172
|
+
};
|
|
173
|
+
try {
|
|
174
|
+
if (strategy === "isolated") {
|
|
175
|
+
const isolatedDir = await this.prepareIsolatedProfileDir(baseProfile);
|
|
176
|
+
this.globalContext = await tryLaunch(isolatedDir);
|
|
177
|
+
this.currentProfileDir = isolatedDir;
|
|
178
|
+
this.isIsolatedProfile = true;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// single or auto → first try base
|
|
182
|
+
this.globalContext = await tryLaunch(baseProfile);
|
|
183
|
+
this.currentProfileDir = baseProfile;
|
|
184
|
+
this.isIsolatedProfile = false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
const msg = String(e?.message || e);
|
|
189
|
+
const isSingleton = /ProcessSingleton|SingletonLock|profile is already in use/i.test(msg);
|
|
190
|
+
if (strategy === "single" || !isSingleton) {
|
|
191
|
+
// hard fail
|
|
192
|
+
if (isSingleton && strategy === "single") {
|
|
193
|
+
log.error("❌ Chrome profile already in use and strategy=single. Close other instance or set NOTEBOOK_PROFILE_STRATEGY=auto/isolated.");
|
|
194
|
+
}
|
|
195
|
+
throw e;
|
|
196
|
+
}
|
|
197
|
+
// auto strategy with lock → fall back to isolated instance dir
|
|
198
|
+
log.warning("⚠️ Base Chrome profile in use by another process. Falling back to isolated per-instance profile...");
|
|
199
|
+
const isolatedDir = await this.prepareIsolatedProfileDir(baseProfile);
|
|
200
|
+
this.globalContext = await tryLaunch(isolatedDir);
|
|
201
|
+
this.currentProfileDir = isolatedDir;
|
|
202
|
+
this.isIsolatedProfile = true;
|
|
203
|
+
}
|
|
204
|
+
this.contextCreatedAt = Date.now();
|
|
205
|
+
this.currentHeadlessMode = shouldBeHeadless;
|
|
206
|
+
// Track close event to force recreation next time
|
|
207
|
+
try {
|
|
208
|
+
this.globalContext.on("close", () => {
|
|
209
|
+
log.warning(" 🛑 Persistent context was closed externally");
|
|
210
|
+
this.globalContext = null;
|
|
211
|
+
this.contextCreatedAt = null;
|
|
212
|
+
this.currentHeadlessMode = null;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
catch { }
|
|
216
|
+
// Validate cookies if we loaded state
|
|
217
|
+
if (statePath) {
|
|
218
|
+
try {
|
|
219
|
+
if (await this.authManager.validateCookiesExpiry(this.globalContext)) {
|
|
220
|
+
log.success(" ✅ Authentication state loaded successfully");
|
|
221
|
+
log.success(" 🎯 Session cookies persisted correctly!");
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
log.warning(" ⚠️ Cookies expired - will need re-login");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
log.warning(` ⚠️ Could not validate auth state: ${error}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
log.success("✅ Persistent context ready!");
|
|
232
|
+
log.dim(` Context ID: ${this.getContextId()}`);
|
|
233
|
+
log.dim(` Chrome Profile: ${CONFIG.chromeProfileDir}`);
|
|
234
|
+
log.success(" 🎯 Fingerprint: PERSISTENT (same across restarts!)");
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Manually close the global context (e.g., on shutdown)
|
|
238
|
+
*
|
|
239
|
+
* Note: This closes the context for ALL sessions!
|
|
240
|
+
* Chrome will save everything to user_data_dir automatically.
|
|
241
|
+
*/
|
|
242
|
+
async closeContext() {
|
|
243
|
+
if (this.globalContext) {
|
|
244
|
+
log.warning("🛑 Closing persistent context...");
|
|
245
|
+
log.info(" 💾 Chrome is saving profile to disk...");
|
|
246
|
+
try {
|
|
247
|
+
await this.globalContext.close();
|
|
248
|
+
this.globalContext = null;
|
|
249
|
+
this.contextCreatedAt = null;
|
|
250
|
+
this.currentHeadlessMode = null;
|
|
251
|
+
log.success("✅ Persistent context closed");
|
|
252
|
+
log.success(` 💾 Profile saved: ${this.currentProfileDir || CONFIG.chromeProfileDir}`);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
log.error(`❌ Error closing context: ${error}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Best-effort cleanup on shutdown
|
|
259
|
+
if (CONFIG.cleanupInstancesOnShutdown) {
|
|
260
|
+
try {
|
|
261
|
+
// If this process used an isolated profile, remove it now
|
|
262
|
+
if (this.isIsolatedProfile && this.currentProfileDir) {
|
|
263
|
+
await this.safeRemoveIsolatedProfile(this.currentProfileDir);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
log.warning(` ⚠️ Cleanup (self) failed: ${err}`);
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
await this.pruneIsolatedProfiles("shutdown");
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
log.warning(` ⚠️ Cleanup (prune) failed: ${err}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
async prepareIsolatedProfileDir(baseProfile) {
|
|
278
|
+
const stamp = `${process.pid}-${Date.now()}`;
|
|
279
|
+
const dir = path.join(CONFIG.chromeInstancesDir, `instance-${stamp}`);
|
|
280
|
+
try {
|
|
281
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
282
|
+
if (CONFIG.cloneProfileOnIsolated && fs.existsSync(baseProfile)) {
|
|
283
|
+
log.info(" 🧬 Cloning base Chrome profile into isolated instance (may take time)...");
|
|
284
|
+
// Best-effort clone without locks
|
|
285
|
+
await fs.promises.cp(baseProfile, dir, {
|
|
286
|
+
recursive: true,
|
|
287
|
+
errorOnExist: false,
|
|
288
|
+
force: true,
|
|
289
|
+
filter: (src) => {
|
|
290
|
+
const bn = path.basename(src);
|
|
291
|
+
return !/^Singleton/i.test(bn) && !bn.endsWith(".lock") && !bn.endsWith(".tmp");
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
log.success(" ✅ Clone complete");
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
log.info(" 🧪 Using fresh isolated Chrome profile (no clone)");
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
log.warning(` ⚠️ Could not prepare isolated profile: ${err}`);
|
|
302
|
+
}
|
|
303
|
+
return dir;
|
|
304
|
+
}
|
|
305
|
+
async pruneIsolatedProfiles(phase) {
|
|
306
|
+
const root = CONFIG.chromeInstancesDir;
|
|
307
|
+
let entries;
|
|
308
|
+
try {
|
|
309
|
+
const names = await fs.promises.readdir(root, { withFileTypes: true });
|
|
310
|
+
entries = [];
|
|
311
|
+
for (const d of names) {
|
|
312
|
+
if (!d.isDirectory())
|
|
313
|
+
continue;
|
|
314
|
+
const p = path.join(root, d.name);
|
|
315
|
+
try {
|
|
316
|
+
const st = await fs.promises.stat(p);
|
|
317
|
+
entries.push({ path: p, mtimeMs: st.mtimeMs });
|
|
318
|
+
}
|
|
319
|
+
catch { }
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
return; // directory absent is fine
|
|
324
|
+
}
|
|
325
|
+
if (entries.length === 0)
|
|
326
|
+
return;
|
|
327
|
+
const now = Date.now();
|
|
328
|
+
const ttlMs = CONFIG.instanceProfileTtlHours * 3600 * 1000;
|
|
329
|
+
const maxCount = Math.max(0, CONFIG.instanceProfileMaxCount);
|
|
330
|
+
// Sort newest first
|
|
331
|
+
entries.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
332
|
+
const keep = new Set();
|
|
333
|
+
const toDelete = new Set();
|
|
334
|
+
// Keep newest up to maxCount
|
|
335
|
+
for (let i = 0; i < entries.length; i++) {
|
|
336
|
+
const e = entries[i];
|
|
337
|
+
const ageMs = now - e.mtimeMs;
|
|
338
|
+
const overTtl = ttlMs > 0 && ageMs > ttlMs;
|
|
339
|
+
const overCount = i >= maxCount;
|
|
340
|
+
const isCurrent = this.currentProfileDir && path.resolve(e.path) === path.resolve(this.currentProfileDir);
|
|
341
|
+
if (!isCurrent && (overTtl || overCount)) {
|
|
342
|
+
toDelete.add(e.path);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
keep.add(e.path);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (toDelete.size === 0)
|
|
349
|
+
return;
|
|
350
|
+
log.info(`🧹 Pruning isolated profiles (${phase})...`);
|
|
351
|
+
for (const p of toDelete) {
|
|
352
|
+
try {
|
|
353
|
+
await this.safeRemoveIsolatedProfile(p);
|
|
354
|
+
log.dim(` 🗑️ removed ${p}`);
|
|
355
|
+
}
|
|
356
|
+
catch (err) {
|
|
357
|
+
log.warning(` ⚠️ Failed to remove ${p}: ${err}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
async safeRemoveIsolatedProfile(dir) {
|
|
362
|
+
// Never remove the base profile
|
|
363
|
+
if (path.resolve(dir) === path.resolve(CONFIG.chromeProfileDir))
|
|
364
|
+
return;
|
|
365
|
+
// Only remove within instances root
|
|
366
|
+
if (!path.resolve(dir).startsWith(path.resolve(CONFIG.chromeInstancesDir)))
|
|
367
|
+
return;
|
|
368
|
+
// Best-effort: try removing typical lock files first, then the directory
|
|
369
|
+
try {
|
|
370
|
+
await fs.promises.rm(dir, { recursive: true, force: true });
|
|
371
|
+
}
|
|
372
|
+
catch (err) {
|
|
373
|
+
// If rm is not available in older node, fallback to rmdir
|
|
374
|
+
try {
|
|
375
|
+
await fs.promises.rmdir(dir, { recursive: true });
|
|
376
|
+
}
|
|
377
|
+
catch { }
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Get information about the global persistent context
|
|
382
|
+
*/
|
|
383
|
+
getContextInfo() {
|
|
384
|
+
if (!this.globalContext) {
|
|
385
|
+
return {
|
|
386
|
+
exists: false,
|
|
387
|
+
user_data_dir: CONFIG.chromeProfileDir,
|
|
388
|
+
persistent: true,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const ageSeconds = this.contextCreatedAt
|
|
392
|
+
? (Date.now() - this.contextCreatedAt) / 1000
|
|
393
|
+
: undefined;
|
|
394
|
+
const ageHours = ageSeconds ? ageSeconds / 3600 : undefined;
|
|
395
|
+
return {
|
|
396
|
+
exists: true,
|
|
397
|
+
age_seconds: ageSeconds,
|
|
398
|
+
age_hours: ageHours,
|
|
399
|
+
fingerprint_id: this.getContextId(),
|
|
400
|
+
user_data_dir: CONFIG.chromeProfileDir,
|
|
401
|
+
persistent: true,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Get the current headless mode of the browser context
|
|
406
|
+
*
|
|
407
|
+
* @returns boolean | null - true if headless, false if visible, null if no context exists
|
|
408
|
+
*/
|
|
409
|
+
getCurrentHeadlessMode() {
|
|
410
|
+
return this.currentHeadlessMode;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Check if the browser context needs to be recreated due to headless mode change
|
|
414
|
+
*
|
|
415
|
+
* @param overrideHeadless - Optional override for headless mode (true = show browser)
|
|
416
|
+
* @returns boolean - true if context needs to be recreated with new mode
|
|
417
|
+
*/
|
|
418
|
+
needsHeadlessModeChange(overrideHeadless) {
|
|
419
|
+
// No context exists yet = will be created with correct mode anyway
|
|
420
|
+
if (this.currentHeadlessMode === null) {
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
// Calculate target headless mode
|
|
424
|
+
// If override is specified, use it (!overrideHeadless because true = show browser = headless false)
|
|
425
|
+
// Otherwise, use CONFIG.headless (which may have been temporarily modified by browser_options)
|
|
426
|
+
const targetHeadless = overrideHeadless !== undefined
|
|
427
|
+
? !overrideHeadless
|
|
428
|
+
: CONFIG.headless;
|
|
429
|
+
// Compare with current mode
|
|
430
|
+
const needsChange = this.currentHeadlessMode !== targetHeadless;
|
|
431
|
+
if (needsChange) {
|
|
432
|
+
log.info(` Browser mode change detected: ${this.currentHeadlessMode ? 'HEADLESS' : 'VISIBLE'} → ${targetHeadless ? 'HEADLESS' : 'VISIBLE'}`);
|
|
433
|
+
}
|
|
434
|
+
return needsChange;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Get context ID for logging
|
|
438
|
+
*/
|
|
439
|
+
getContextId() {
|
|
440
|
+
if (!this.globalContext) {
|
|
441
|
+
return "none";
|
|
442
|
+
}
|
|
443
|
+
// Use object hash as ID
|
|
444
|
+
return `ctx-${this.globalContext._guid || "unknown"}`;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
//# sourceMappingURL=shared-context-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-context-manager.js","sourceRoot":"","sources":["../../src/session/shared-context-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Implementations
|
|
3
|
+
*
|
|
4
|
+
* Implements all MCP tools for NotebookLM integration:
|
|
5
|
+
* - ask_question: Ask NotebookLM with session support
|
|
6
|
+
* - list_sessions: List all active sessions
|
|
7
|
+
* - close_session: Close a specific session
|
|
8
|
+
* - reset_session: Reset session chat history
|
|
9
|
+
* - get_health: Server health check
|
|
10
|
+
* - setup_auth: Interactive authentication setup
|
|
11
|
+
*
|
|
12
|
+
* Based on the Python implementation from tools/*.py
|
|
13
|
+
*/
|
|
14
|
+
import { SessionManager } from "../session/session-manager.js";
|
|
15
|
+
import { AuthManager } from "../auth/auth-manager.js";
|
|
16
|
+
import { NotebookLibrary } from "../library/notebook-library.js";
|
|
17
|
+
import type { AddNotebookInput, UpdateNotebookInput } from "../library/types.js";
|
|
18
|
+
import { type BrowserOptions } from "../config.js";
|
|
19
|
+
import type { AskQuestionResult, ToolResult, Tool, ProgressCallback } from "../types.js";
|
|
20
|
+
/**
|
|
21
|
+
* Build Tool Definitions with NotebookLibrary context
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildToolDefinitions(library: NotebookLibrary): Tool[];
|
|
24
|
+
/**
|
|
25
|
+
* MCP Tool Handlers
|
|
26
|
+
*/
|
|
27
|
+
export declare class ToolHandlers {
|
|
28
|
+
private sessionManager;
|
|
29
|
+
private authManager;
|
|
30
|
+
private library;
|
|
31
|
+
constructor(sessionManager: SessionManager, authManager: AuthManager, library: NotebookLibrary);
|
|
32
|
+
/**
|
|
33
|
+
* Handle ask_question tool
|
|
34
|
+
*/
|
|
35
|
+
handleAskQuestion(args: {
|
|
36
|
+
question: string;
|
|
37
|
+
session_id?: string;
|
|
38
|
+
notebook_id?: string;
|
|
39
|
+
notebook_url?: string;
|
|
40
|
+
show_browser?: boolean;
|
|
41
|
+
browser_options?: BrowserOptions;
|
|
42
|
+
}, sendProgress?: ProgressCallback): Promise<ToolResult<AskQuestionResult>>;
|
|
43
|
+
/**
|
|
44
|
+
* Handle list_sessions tool
|
|
45
|
+
*/
|
|
46
|
+
handleListSessions(): Promise<ToolResult<{
|
|
47
|
+
active_sessions: number;
|
|
48
|
+
max_sessions: number;
|
|
49
|
+
session_timeout: number;
|
|
50
|
+
oldest_session_seconds: number;
|
|
51
|
+
total_messages: number;
|
|
52
|
+
sessions: Array<{
|
|
53
|
+
id: string;
|
|
54
|
+
created_at: number;
|
|
55
|
+
last_activity: number;
|
|
56
|
+
age_seconds: number;
|
|
57
|
+
inactive_seconds: number;
|
|
58
|
+
message_count: number;
|
|
59
|
+
notebook_url: string;
|
|
60
|
+
}>;
|
|
61
|
+
}>>;
|
|
62
|
+
/**
|
|
63
|
+
* Handle close_session tool
|
|
64
|
+
*/
|
|
65
|
+
handleCloseSession(args: {
|
|
66
|
+
session_id: string;
|
|
67
|
+
}): Promise<ToolResult<{
|
|
68
|
+
status: string;
|
|
69
|
+
message: string;
|
|
70
|
+
session_id: string;
|
|
71
|
+
}>>;
|
|
72
|
+
/**
|
|
73
|
+
* Handle reset_session tool
|
|
74
|
+
*/
|
|
75
|
+
handleResetSession(args: {
|
|
76
|
+
session_id: string;
|
|
77
|
+
}): Promise<ToolResult<{
|
|
78
|
+
status: string;
|
|
79
|
+
message: string;
|
|
80
|
+
session_id: string;
|
|
81
|
+
}>>;
|
|
82
|
+
/**
|
|
83
|
+
* Handle get_health tool
|
|
84
|
+
*/
|
|
85
|
+
handleGetHealth(): Promise<ToolResult<{
|
|
86
|
+
status: string;
|
|
87
|
+
authenticated: boolean;
|
|
88
|
+
notebook_url: string;
|
|
89
|
+
active_sessions: number;
|
|
90
|
+
max_sessions: number;
|
|
91
|
+
session_timeout: number;
|
|
92
|
+
total_messages: number;
|
|
93
|
+
headless: boolean;
|
|
94
|
+
auto_login_enabled: boolean;
|
|
95
|
+
stealth_enabled: boolean;
|
|
96
|
+
troubleshooting_tip?: string;
|
|
97
|
+
}>>;
|
|
98
|
+
/**
|
|
99
|
+
* Handle setup_auth tool
|
|
100
|
+
*
|
|
101
|
+
* Opens a browser window for manual login with live progress updates.
|
|
102
|
+
* The operation waits synchronously for login completion (up to 10 minutes).
|
|
103
|
+
*/
|
|
104
|
+
handleSetupAuth(args: {
|
|
105
|
+
show_browser?: boolean;
|
|
106
|
+
browser_options?: BrowserOptions;
|
|
107
|
+
}, sendProgress?: ProgressCallback): Promise<ToolResult<{
|
|
108
|
+
status: string;
|
|
109
|
+
message: string;
|
|
110
|
+
authenticated: boolean;
|
|
111
|
+
duration_seconds?: number;
|
|
112
|
+
}>>;
|
|
113
|
+
/**
|
|
114
|
+
* Handle re_auth tool
|
|
115
|
+
*
|
|
116
|
+
* Performs a complete re-authentication:
|
|
117
|
+
* 1. Closes all active browser sessions
|
|
118
|
+
* 2. Deletes all saved authentication data (cookies, Chrome profile)
|
|
119
|
+
* 3. Opens browser for fresh Google login
|
|
120
|
+
*
|
|
121
|
+
* Use for switching Google accounts or recovering from rate limits.
|
|
122
|
+
*/
|
|
123
|
+
handleReAuth(args: {
|
|
124
|
+
show_browser?: boolean;
|
|
125
|
+
browser_options?: BrowserOptions;
|
|
126
|
+
}, sendProgress?: ProgressCallback): Promise<ToolResult<{
|
|
127
|
+
status: string;
|
|
128
|
+
message: string;
|
|
129
|
+
authenticated: boolean;
|
|
130
|
+
duration_seconds?: number;
|
|
131
|
+
}>>;
|
|
132
|
+
/**
|
|
133
|
+
* Handle add_notebook tool
|
|
134
|
+
*/
|
|
135
|
+
handleAddNotebook(args: AddNotebookInput): Promise<ToolResult<{
|
|
136
|
+
notebook: any;
|
|
137
|
+
}>>;
|
|
138
|
+
/**
|
|
139
|
+
* Handle list_notebooks tool
|
|
140
|
+
*/
|
|
141
|
+
handleListNotebooks(): Promise<ToolResult<{
|
|
142
|
+
notebooks: any[];
|
|
143
|
+
active_notebook_id: string | null;
|
|
144
|
+
}>>;
|
|
145
|
+
/**
|
|
146
|
+
* Handle get_notebook tool
|
|
147
|
+
*/
|
|
148
|
+
handleGetNotebook(args: {
|
|
149
|
+
id: string;
|
|
150
|
+
}): Promise<ToolResult<{
|
|
151
|
+
notebook: any;
|
|
152
|
+
}>>;
|
|
153
|
+
/**
|
|
154
|
+
* Handle select_notebook tool
|
|
155
|
+
*/
|
|
156
|
+
handleSelectNotebook(args: {
|
|
157
|
+
id: string;
|
|
158
|
+
}): Promise<ToolResult<{
|
|
159
|
+
notebook: any;
|
|
160
|
+
}>>;
|
|
161
|
+
/**
|
|
162
|
+
* Handle update_notebook tool
|
|
163
|
+
*/
|
|
164
|
+
handleUpdateNotebook(args: UpdateNotebookInput): Promise<ToolResult<{
|
|
165
|
+
notebook: any;
|
|
166
|
+
}>>;
|
|
167
|
+
/**
|
|
168
|
+
* Handle remove_notebook tool
|
|
169
|
+
*/
|
|
170
|
+
handleRemoveNotebook(args: {
|
|
171
|
+
id: string;
|
|
172
|
+
}): Promise<ToolResult<{
|
|
173
|
+
removed: boolean;
|
|
174
|
+
closed_sessions: number;
|
|
175
|
+
}>>;
|
|
176
|
+
/**
|
|
177
|
+
* Handle search_notebooks tool
|
|
178
|
+
*/
|
|
179
|
+
handleSearchNotebooks(args: {
|
|
180
|
+
query: string;
|
|
181
|
+
}): Promise<ToolResult<{
|
|
182
|
+
notebooks: any[];
|
|
183
|
+
}>>;
|
|
184
|
+
/**
|
|
185
|
+
* Handle get_library_stats tool
|
|
186
|
+
*/
|
|
187
|
+
handleGetLibraryStats(): Promise<ToolResult<any>>;
|
|
188
|
+
/**
|
|
189
|
+
* Handle cleanup_data tool
|
|
190
|
+
*
|
|
191
|
+
* ULTRATHINK Deep Cleanup - scans entire system for ALL NotebookLM MCP files
|
|
192
|
+
*/
|
|
193
|
+
handleCleanupData(args: {
|
|
194
|
+
confirm: boolean;
|
|
195
|
+
preserve_library?: boolean;
|
|
196
|
+
}): Promise<ToolResult<{
|
|
197
|
+
status: string;
|
|
198
|
+
mode: string;
|
|
199
|
+
preview?: {
|
|
200
|
+
categories: Array<{
|
|
201
|
+
name: string;
|
|
202
|
+
description: string;
|
|
203
|
+
paths: string[];
|
|
204
|
+
totalBytes: number;
|
|
205
|
+
optional: boolean;
|
|
206
|
+
}>;
|
|
207
|
+
totalPaths: number;
|
|
208
|
+
totalSizeBytes: number;
|
|
209
|
+
};
|
|
210
|
+
result?: {
|
|
211
|
+
deletedPaths: string[];
|
|
212
|
+
failedPaths: string[];
|
|
213
|
+
totalSizeBytes: number;
|
|
214
|
+
categorySummary: Record<string, {
|
|
215
|
+
count: number;
|
|
216
|
+
bytes: number;
|
|
217
|
+
}>;
|
|
218
|
+
};
|
|
219
|
+
}>>;
|
|
220
|
+
/**
|
|
221
|
+
* Cleanup all resources (called on server shutdown)
|
|
222
|
+
*/
|
|
223
|
+
cleanup(): Promise<void>;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=index.d.ts.map
|