notebooklm-sdk 0.1.7 → 0.1.8
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/dist/{auth-Ba2hsZW_.d.cts → auth-Dxsm8894.d.cts} +1 -1
- package/dist/{auth-Ba2hsZW_.d.ts → auth-Dxsm8894.d.ts} +1 -1
- package/dist/auth.cjs +47 -21
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +8 -4
- package/dist/auth.d.ts +8 -4
- package/dist/auth.js +47 -23
- package/dist/auth.js.map +1 -1
- package/dist/bin.cjs +176 -31
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +178 -33
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +26 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.js +27 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -50,6 +50,6 @@ interface ConnectOptions {
|
|
|
50
50
|
}>;
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
declare function connect(opts
|
|
53
|
+
declare function connect(opts?: ConnectOptions): Promise<AuthTokens>;
|
|
54
54
|
|
|
55
55
|
export { type AuthTokens as A, type CookieMap as C, type ConnectOptions as a, buildCookieHeader as b, buildGoogleCookieHeader as c, connect as d, loadCookiesFromMap as e, fetchTokens as f, loadCookiesFromObject as g, loadCookiesFromString as h, loadCookiesFromFile as l };
|
|
@@ -50,6 +50,6 @@ interface ConnectOptions {
|
|
|
50
50
|
}>;
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
declare function connect(opts
|
|
53
|
+
declare function connect(opts?: ConnectOptions): Promise<AuthTokens>;
|
|
54
54
|
|
|
55
55
|
export { type AuthTokens as A, type CookieMap as C, type ConnectOptions as a, buildCookieHeader as b, buildGoogleCookieHeader as c, connect as d, loadCookiesFromMap as e, fetchTokens as f, loadCookiesFromObject as g, loadCookiesFromString as h, loadCookiesFromFile as l };
|
package/dist/auth.cjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var fs = require('fs');
|
|
4
|
+
var os = require('os');
|
|
5
|
+
var path = require('path');
|
|
4
6
|
var playwright = require('playwright');
|
|
5
7
|
|
|
6
8
|
// src/auth.ts
|
|
@@ -29,14 +31,15 @@ var AuthError = class extends RPCError {
|
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
// src/auth.ts
|
|
34
|
+
var DEFAULT_SESSION_FILE = path.join(os.homedir(), ".notebooklm", "session.json");
|
|
32
35
|
function loadCookiesFromFile(filePath) {
|
|
33
36
|
let raw;
|
|
34
37
|
try {
|
|
35
38
|
raw = fs.readFileSync(filePath, "utf-8");
|
|
36
39
|
} catch {
|
|
37
40
|
throw new AuthError(
|
|
38
|
-
`
|
|
39
|
-
|
|
41
|
+
`Session file not found: ${filePath}
|
|
42
|
+
Run: npx notebooklm-sdk login`
|
|
40
43
|
);
|
|
41
44
|
}
|
|
42
45
|
return extractCookiesFromStorageState(JSON.parse(raw));
|
|
@@ -80,7 +83,7 @@ function extractCookiesFromStorageState(storageState) {
|
|
|
80
83
|
}
|
|
81
84
|
if (!cookies["SID"]) {
|
|
82
85
|
throw new AuthError(
|
|
83
|
-
"Missing required cookie: SID.
|
|
86
|
+
"Missing required cookie: SID. Session may be invalid or expired.\nRun: npx notebooklm-sdk login"
|
|
84
87
|
);
|
|
85
88
|
}
|
|
86
89
|
return cookies;
|
|
@@ -120,7 +123,7 @@ function extractCsrfToken(html, finalUrl) {
|
|
|
120
123
|
const match = /"SNlM0e"\s*:\s*"([^"]+)"/.exec(html);
|
|
121
124
|
if (!match?.[1]) {
|
|
122
125
|
if (isGoogleAuthRedirect(finalUrl) || html.includes("accounts.google.com")) {
|
|
123
|
-
throw new AuthError("
|
|
126
|
+
throw new AuthError("Session expired or invalid.\nRun: npx notebooklm-sdk login");
|
|
124
127
|
}
|
|
125
128
|
throw new AuthError("CSRF token (SNlM0e) not found in NotebookLM page HTML.");
|
|
126
129
|
}
|
|
@@ -130,7 +133,7 @@ function extractSessionId(html, finalUrl) {
|
|
|
130
133
|
const match = /"FdrFJe"\s*:\s*"([^"]+)"/.exec(html);
|
|
131
134
|
if (!match?.[1]) {
|
|
132
135
|
if (isGoogleAuthRedirect(finalUrl) || html.includes("accounts.google.com")) {
|
|
133
|
-
throw new AuthError("
|
|
136
|
+
throw new AuthError("Session expired or invalid.\nRun: npx notebooklm-sdk login");
|
|
134
137
|
}
|
|
135
138
|
throw new AuthError("Session ID (FdrFJe) not found in NotebookLM page HTML.");
|
|
136
139
|
}
|
|
@@ -139,7 +142,7 @@ function extractSessionId(html, finalUrl) {
|
|
|
139
142
|
function isGoogleAuthRedirect(url) {
|
|
140
143
|
return url.includes("accounts.google.com") || url.includes("signin");
|
|
141
144
|
}
|
|
142
|
-
async function connect(opts) {
|
|
145
|
+
async function connect(opts = {}) {
|
|
143
146
|
let cookieMap;
|
|
144
147
|
let googleCookieHeader = null;
|
|
145
148
|
if (opts.cookies) {
|
|
@@ -156,11 +159,24 @@ async function connect(opts) {
|
|
|
156
159
|
}
|
|
157
160
|
} else {
|
|
158
161
|
const envCookies = process.env["NOTEBOOKLM_COOKIES"];
|
|
159
|
-
|
|
162
|
+
const envFile = process.env["NOTEBOOKLM_COOKIES_FILE"];
|
|
163
|
+
if (envFile) {
|
|
164
|
+
cookieMap = loadCookiesFromFile(envFile);
|
|
165
|
+
} else if (fs.existsSync(DEFAULT_SESSION_FILE)) {
|
|
166
|
+
const raw = fs.readFileSync(DEFAULT_SESSION_FILE, "utf-8");
|
|
167
|
+
const storageState = JSON.parse(raw);
|
|
168
|
+
cookieMap = loadCookiesFromObject(storageState);
|
|
169
|
+
googleCookieHeader = buildGoogleCookieHeader(storageState);
|
|
170
|
+
} else if (fs.existsSync("storage_state.json")) {
|
|
171
|
+
const raw = fs.readFileSync("storage_state.json", "utf-8");
|
|
172
|
+
const storageState = JSON.parse(raw);
|
|
173
|
+
cookieMap = loadCookiesFromObject(storageState);
|
|
174
|
+
googleCookieHeader = buildGoogleCookieHeader(storageState);
|
|
175
|
+
} else if (envCookies) {
|
|
160
176
|
cookieMap = loadCookiesFromString(envCookies);
|
|
161
177
|
} else {
|
|
162
178
|
throw new AuthError(
|
|
163
|
-
"No
|
|
179
|
+
"No session found. Run: npx notebooklm-sdk login"
|
|
164
180
|
);
|
|
165
181
|
}
|
|
166
182
|
}
|
|
@@ -174,27 +190,35 @@ async function connect(opts) {
|
|
|
174
190
|
googleCookieHeader: googleCookieHeader ?? cookieHeader
|
|
175
191
|
};
|
|
176
192
|
}
|
|
193
|
+
var DEFAULT_SESSION_DIR = path.join(os.homedir(), ".notebooklm");
|
|
194
|
+
var DEFAULT_SESSION_FILE2 = path.join(DEFAULT_SESSION_DIR, "session.json");
|
|
177
195
|
var NOTEBOOKLM_URL2 = "https://notebooklm.google.com/";
|
|
178
196
|
var GOOGLE_ACCOUNTS_URL = "https://accounts.google.com/";
|
|
179
197
|
async function login(opts = {}) {
|
|
180
|
-
const {
|
|
198
|
+
const {
|
|
199
|
+
persistFolder = path.join(DEFAULT_SESSION_DIR, ".auth_profile"),
|
|
200
|
+
headless = false,
|
|
201
|
+
browserType = "chromium"
|
|
202
|
+
} = opts;
|
|
203
|
+
try {
|
|
204
|
+
playwright.chromium.executablePath();
|
|
205
|
+
} catch {
|
|
206
|
+
throw new Error(
|
|
207
|
+
"Playwright browser not found. Run: npx playwright install chromium"
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
if (!fs.existsSync(DEFAULT_SESSION_DIR)) {
|
|
211
|
+
fs.mkdirSync(DEFAULT_SESSION_DIR, { recursive: true });
|
|
212
|
+
}
|
|
181
213
|
let context;
|
|
182
214
|
const launchOptions = {
|
|
183
215
|
headless,
|
|
184
216
|
args: ["--disable-blink-features=AutomationControlled"]
|
|
185
217
|
};
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
191
|
-
} else {
|
|
192
|
-
const browser = await playwright.chromium.launch({
|
|
193
|
-
...launchOptions,
|
|
194
|
-
channel: browserType === "msedge" ? "msedge" : void 0
|
|
195
|
-
});
|
|
196
|
-
context = await browser.newContext();
|
|
197
|
-
}
|
|
218
|
+
context = await playwright.chromium.launchPersistentContext(persistFolder, {
|
|
219
|
+
...launchOptions,
|
|
220
|
+
channel: browserType === "msedge" ? "msedge" : void 0
|
|
221
|
+
});
|
|
198
222
|
const page = context.pages()[0] || await context.newPage();
|
|
199
223
|
await page.goto(NOTEBOOKLM_URL2);
|
|
200
224
|
if (page.url().includes("accounts.google.com")) {
|
|
@@ -218,6 +242,8 @@ async function login(opts = {}) {
|
|
|
218
242
|
};
|
|
219
243
|
}
|
|
220
244
|
|
|
245
|
+
exports.DEFAULT_SESSION_DIR = DEFAULT_SESSION_DIR;
|
|
246
|
+
exports.DEFAULT_SESSION_FILE = DEFAULT_SESSION_FILE2;
|
|
221
247
|
exports.buildCookieHeader = buildCookieHeader;
|
|
222
248
|
exports.buildGoogleCookieHeader = buildGoogleCookieHeader;
|
|
223
249
|
exports.connect = connect;
|
package/dist/auth.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/errors.ts","../src/auth.ts","../src/auth/browser.ts"],"names":["readFileSync","NOTEBOOKLM_URL","chromium"],"mappings":"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","file":"auth.cjs","sourcesContent":["/**\n * All exceptions for notebooklm-sdk.\n *\n * All errors extend NotebookLMError so you can catch everything with:\n * try { ... } catch (e) { if (e instanceof NotebookLMError) ... }\n */\n\nexport class NotebookLMError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Network (transport-level, before RPC processing)\n// ---------------------------------------------------------------------------\n\nexport class NetworkError extends NotebookLMError {\n readonly methodId?: string;\n readonly originalError?: Error;\n\n constructor(message: string, opts: { methodId?: string; originalError?: Error } = {}) {\n super(message);\n this.methodId = opts.methodId;\n this.originalError = opts.originalError;\n }\n}\n\nexport class RPCTimeoutError extends NetworkError {}\n\n// ---------------------------------------------------------------------------\n// RPC Protocol (after connection established)\n// ---------------------------------------------------------------------------\n\nexport class RPCError extends NotebookLMError {\n readonly methodId?: string;\n readonly rawResponse?: string;\n readonly rpcCode?: string | number;\n readonly foundIds: string[];\n\n constructor(\n message: string,\n opts: {\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n foundIds?: string[];\n } = {},\n ) {\n super(message);\n this.methodId = opts.methodId;\n this.rawResponse = opts.rawResponse ? opts.rawResponse.slice(0, 500) : undefined;\n this.rpcCode = opts.rpcCode;\n this.foundIds = opts.foundIds ?? [];\n }\n}\n\nexport class AuthError extends RPCError {}\n\nexport class RateLimitError extends RPCError {\n readonly retryAfter?: number;\n\n constructor(\n message: string,\n opts: {\n retryAfter?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n foundIds?: string[];\n } = {},\n ) {\n super(message, opts);\n this.retryAfter = opts.retryAfter;\n }\n}\n\nexport class ServerError extends RPCError {\n readonly statusCode?: number;\n\n constructor(\n message: string,\n opts: {\n statusCode?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n } = {},\n ) {\n super(message, opts);\n this.statusCode = opts.statusCode;\n }\n}\n\nexport class ClientError extends RPCError {\n readonly statusCode?: number;\n\n constructor(\n message: string,\n opts: {\n statusCode?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n } = {},\n ) {\n super(message, opts);\n this.statusCode = opts.statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Notebooks\n// ---------------------------------------------------------------------------\n\nexport class NotebookError extends NotebookLMError {}\n\nexport class NotebookNotFoundError extends NotebookError {\n readonly notebookId: string;\n\n constructor(notebookId: string) {\n super(`Notebook not found: ${notebookId}`);\n this.notebookId = notebookId;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Sources\n// ---------------------------------------------------------------------------\n\nexport class SourceError extends NotebookLMError {}\n\nexport class SourceNotFoundError extends SourceError {\n readonly sourceId: string;\n\n constructor(sourceId: string) {\n super(`Source not found: ${sourceId}`);\n this.sourceId = sourceId;\n }\n}\n\nexport class SourceAddError extends SourceError {\n readonly url: string;\n readonly cause?: Error;\n\n constructor(url: string, opts: { cause?: Error; message?: string } = {}) {\n super(\n opts.message ??\n `Failed to add source: ${url}\\n` +\n \"Possible causes:\\n\" +\n \" - URL is invalid or inaccessible\\n\" +\n \" - Content is behind a paywall or requires authentication\\n\" +\n \" - Rate limiting or quota exceeded\",\n );\n this.url = url;\n this.cause = opts.cause;\n }\n}\n\nexport class SourceProcessingError extends SourceError {\n readonly sourceId: string;\n readonly status: number;\n\n constructor(sourceId: string, status = 3, message?: string) {\n super(message ?? `Source ${sourceId} failed to process`);\n this.sourceId = sourceId;\n this.status = status;\n }\n}\n\nexport class SourceTimeoutError extends SourceError {\n readonly sourceId: string;\n readonly timeout: number;\n readonly lastStatus?: number;\n\n constructor(sourceId: string, timeout: number, lastStatus?: number) {\n const statusInfo = lastStatus != null ? ` (last status: ${lastStatus})` : \"\";\n super(`Source ${sourceId} not ready after ${timeout.toFixed(1)}s${statusInfo}`);\n this.sourceId = sourceId;\n this.timeout = timeout;\n this.lastStatus = lastStatus;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Artifacts\n// ---------------------------------------------------------------------------\n\nexport class ArtifactError extends NotebookLMError {}\n\nexport class ArtifactNotFoundError extends ArtifactError {\n readonly artifactId: string;\n readonly artifactType?: string;\n\n constructor(artifactId: string, artifactType?: string) {\n const typeInfo = artifactType ? ` ${artifactType}` : \"\";\n super(`${typeInfo.trim() || \"Artifact\"} ${artifactId} not found`);\n this.artifactId = artifactId;\n this.artifactType = artifactType;\n }\n}\n\nexport class ArtifactNotReadyError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly status?: string;\n\n constructor(artifactType: string, opts: { artifactId?: string; status?: string } = {}) {\n const base = opts.artifactId\n ? `${artifactType} artifact ${opts.artifactId} is not ready`\n : `No completed ${artifactType} found`;\n const statusInfo = opts.status ? ` (status: ${opts.status})` : \"\";\n super(`${base}${statusInfo}`);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.status = opts.status;\n }\n}\n\nexport class ArtifactParseError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly details?: string;\n readonly cause?: Error;\n\n constructor(\n artifactType: string,\n opts: { details?: string; artifactId?: string; cause?: Error } = {},\n ) {\n let msg = `Failed to parse ${artifactType} artifact`;\n if (opts.artifactId) msg += ` ${opts.artifactId}`;\n if (opts.details) msg += `: ${opts.details}`;\n super(msg);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.details = opts.details;\n this.cause = opts.cause;\n }\n}\n\nexport class ArtifactDownloadError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly details?: string;\n readonly cause?: Error;\n\n constructor(\n artifactType: string,\n opts: { details?: string; artifactId?: string; cause?: Error } = {},\n ) {\n let msg = `Failed to download ${artifactType} artifact`;\n if (opts.artifactId) msg += ` ${opts.artifactId}`;\n if (opts.details) msg += `: ${opts.details}`;\n super(msg);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.details = opts.details;\n this.cause = opts.cause;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Chat\n// ---------------------------------------------------------------------------\n\nexport class ChatError extends NotebookLMError {}\n","import { readFileSync } from \"node:fs\";\nimport { AuthError } from \"./types/errors.js\";\n\nexport interface CookieMap {\n [key: string]: string;\n}\n\nexport interface AuthTokens {\n cookies: CookieMap;\n csrfToken: string;\n sessionId: string;\n cookieHeader: string;\n /** Cookie header containing only .google.com domain cookies — for media downloads */\n googleCookieHeader: string;\n}\n\n// ---------------------------------------------------------------------------\n// Cookie loading\n// ---------------------------------------------------------------------------\n\n/** Load cookies from a Playwright storage_state.json file. */\nexport function loadCookiesFromFile(filePath: string): CookieMap {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch {\n throw new AuthError(\n `Cookie file not found: ${filePath}\\n` + \"Provide valid Playwright storage state JSON.\",\n );\n }\n return extractCookiesFromStorageState(JSON.parse(raw));\n}\n\n/** Load cookies from a raw Playwright storage state object. */\nexport function loadCookiesFromObject(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): CookieMap {\n return extractCookiesFromStorageState(storageState);\n}\n\n/** Build a cookie header containing only .google.com domain cookies (for media downloads). */\nexport function buildGoogleCookieHeader(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): string {\n const map: CookieMap = {};\n for (const c of storageState.cookies ?? []) {\n if (c.domain === \".google.com\" && c.name && c.value) {\n map[c.name] = map[c.name] ?? c.value;\n }\n }\n return buildCookieHeader(map);\n}\n\n/** Load cookies from a flat cookie map (already parsed). */\nexport function loadCookiesFromMap(map: CookieMap): CookieMap {\n return { ...map };\n}\n\n/** Load cookies from a \"; \"-separated cookie string (e.g. process.env.NOTEBOOKLM_COOKIES). */\nexport function loadCookiesFromString(cookieStr: string): CookieMap {\n const map: CookieMap = {};\n for (const part of cookieStr.split(/;\\s*/)) {\n const idx = part.indexOf(\"=\");\n if (idx > 0) {\n const name = part.slice(0, idx).trim();\n const value = part.slice(idx + 1).trim();\n if (name) map[name] = value;\n }\n }\n return map;\n}\n\nfunction extractCookiesFromStorageState(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): CookieMap {\n const cookies: CookieMap = {};\n const domainTrack: Record<string, string> = {};\n\n for (const cookie of storageState.cookies ?? []) {\n const { domain, name, value } = cookie;\n if (!isAllowedDomain(domain) || !name) continue;\n\n const isBase = domain === \".google.com\";\n if (!(name in cookies) || isBase) {\n cookies[name] = value;\n domainTrack[name] = domain;\n }\n }\n\n if (!cookies[\"SID\"]) {\n throw new AuthError(\n \"Missing required cookie: SID. \" +\n \"Provide valid Playwright storage state with Google cookies.\",\n );\n }\n return cookies;\n}\n\nfunction isAllowedDomain(domain: string): boolean {\n if (\n domain === \".google.com\" ||\n domain === \"notebooklm.google.com\" ||\n domain === \".googleusercontent.com\"\n ) {\n return true;\n }\n if (domain.startsWith(\".google.\")) {\n return true; // Allow all regional Google domains\n }\n return false;\n}\n\nexport function buildCookieHeader(cookies: CookieMap): string {\n return Object.entries(cookies)\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \");\n}\n\n// ---------------------------------------------------------------------------\n// Token fetching\n// ---------------------------------------------------------------------------\n\nconst NOTEBOOKLM_URL = \"https://notebooklm.google.com/\";\n\nexport async function fetchTokens(\n cookies: CookieMap,\n): Promise<{ csrfToken: string; sessionId: string }> {\n const cookieHeader = buildCookieHeader(cookies);\n\n const response = await fetch(NOTEBOOKLM_URL, {\n headers: { Cookie: cookieHeader },\n redirect: \"follow\",\n });\n\n if (!response.ok) {\n throw new AuthError(`Failed to fetch NotebookLM page: HTTP ${response.status}`);\n }\n\n const finalUrl = response.url;\n if (isGoogleAuthRedirect(finalUrl)) {\n throw new AuthError(`Redirected to login page: ${finalUrl}. Cookies may be expired.`);\n }\n\n const html = await response.text();\n const csrfToken = extractCsrfToken(html, finalUrl);\n const sessionId = extractSessionId(html, finalUrl);\n\n return { csrfToken, sessionId };\n}\n\nfunction extractCsrfToken(html: string, finalUrl: string): string {\n const match = /\"SNlM0e\"\\s*:\\s*\"([^\"]+)\"/.exec(html);\n if (!match?.[1]) {\n if (isGoogleAuthRedirect(finalUrl) || html.includes(\"accounts.google.com\")) {\n throw new AuthError(\"Authentication expired or invalid. Cookies may need to be refreshed.\");\n }\n throw new AuthError(\"CSRF token (SNlM0e) not found in NotebookLM page HTML.\");\n }\n return match[1];\n}\n\nfunction extractSessionId(html: string, finalUrl: string): string {\n const match = /\"FdrFJe\"\\s*:\\s*\"([^\"]+)\"/.exec(html);\n if (!match?.[1]) {\n if (isGoogleAuthRedirect(finalUrl) || html.includes(\"accounts.google.com\")) {\n throw new AuthError(\"Authentication expired or invalid. Cookies may need to be refreshed.\");\n }\n throw new AuthError(\"Session ID (FdrFJe) not found in NotebookLM page HTML.\");\n }\n return match[1];\n}\n\nfunction isGoogleAuthRedirect(url: string): boolean {\n return url.includes(\"accounts.google.com\") || url.includes(\"signin\");\n}\n\n// ---------------------------------------------------------------------------\n// Connect options\n// ---------------------------------------------------------------------------\n\nexport interface ConnectOptions {\n /** \"; \"-separated cookie string (e.g. \"SID=abc; HSID=xyz\") */\n cookies?: string;\n /** Path to Playwright storage_state.json */\n cookiesFile?: string;\n /** Pre-parsed cookie map */\n cookiesObject?: CookieMap | { cookies?: Array<{ name: string; value: string; domain: string }> };\n}\n\nexport async function connect(opts: ConnectOptions): Promise<AuthTokens> {\n let cookieMap: CookieMap;\n let googleCookieHeader: string | null = null;\n\n if (opts.cookies) {\n cookieMap = loadCookiesFromString(opts.cookies);\n } else if (opts.cookiesFile) {\n cookieMap = loadCookiesFromFile(opts.cookiesFile);\n } else if (opts.cookiesObject) {\n if (\"cookies\" in opts.cookiesObject && Array.isArray(opts.cookiesObject.cookies)) {\n const storageState = opts.cookiesObject as {\n cookies: Array<{ name: string; value: string; domain: string }>;\n };\n cookieMap = loadCookiesFromObject(storageState);\n googleCookieHeader = buildGoogleCookieHeader(storageState);\n } else {\n cookieMap = loadCookiesFromMap(opts.cookiesObject as CookieMap);\n }\n } else {\n // Fallback: check environment variable\n const envCookies = process.env[\"NOTEBOOKLM_COOKIES\"];\n if (envCookies) {\n cookieMap = loadCookiesFromString(envCookies);\n } else {\n throw new AuthError(\n \"No cookies provided. Pass cookies, cookiesFile, or cookiesObject to connect().\",\n );\n }\n }\n\n const { csrfToken, sessionId } = await fetchTokens(cookieMap);\n const cookieHeader = buildCookieHeader(cookieMap);\n\n return {\n cookies: cookieMap,\n csrfToken,\n sessionId,\n cookieHeader,\n googleCookieHeader: googleCookieHeader ?? cookieHeader,\n };\n}\n","import { type BrowserContext, chromium, type Page } from \"playwright\";\nimport { type CookieMap, loadCookiesFromObject } from \"../auth.js\";\n\nexport interface LoginOptions {\n /**\n * Path to a directory for a persistent browser profile.\n * If provided, session remains logged in for future calls.\n */\n persistFolder?: string;\n /**\n * Browser type to use. Default is \"chromium\".\n */\n browserType?: \"chromium\" | \"msedge\";\n /**\n * Whether to run the browser in headless mode. Default is false.\n * Headless login is usually blocked by Google, so this is mostly for testing or refreshes.\n */\n headless?: boolean;\n}\n\nconst NOTEBOOKLM_URL = \"https://notebooklm.google.com/\";\nconst GOOGLE_ACCOUNTS_URL = \"https://accounts.google.com/\";\n\n/**\n * Log in to NotebookLM via a headful browser window.\n *\n * Flow:\n * 1. Opens browser to NotebookLM.\n * 2. If already logged in (via persistFolder), it proceeds.\n * 3. If not, it waits for the user to reach the home page.\n * 4. Captures cookies and returns them.\n */\nexport async function login(opts: LoginOptions = {}): Promise<{\n cookies: CookieMap;\n storageState: any;\n cookieHeader: string;\n}> {\n const { persistFolder, headless = false, browserType = \"chromium\" } = opts;\n\n let context: BrowserContext;\n\n const launchOptions = {\n headless,\n args: [\"--disable-blink-features=AutomationControlled\"],\n };\n\n if (persistFolder) {\n context = await chromium.launchPersistentContext(persistFolder, {\n ...launchOptions,\n channel: browserType === \"msedge\" ? \"msedge\" : undefined,\n });\n } else {\n const browser = await chromium.launch({\n ...launchOptions,\n channel: browserType === \"msedge\" ? \"msedge\" : undefined,\n });\n context = await browser.newContext();\n }\n\n const page = context.pages()[0] || (await context.newPage());\n await page.goto(NOTEBOOKLM_URL);\n\n // Check if we are on the login page\n if (page.url().includes(\"accounts.google.com\")) {\n console.log(\"Please log in to Google in the browser window...\");\n\n // Wait for navigation back to NotebookLM or successful login indicator\n // We poll until the URL includes notebooklm.google.com and it's not a generic landing page\n await page.waitForURL(\n (url) => {\n return url.hostname === \"notebooklm.google.com\" && !url.pathname.includes(\"/login\");\n },\n { timeout: 0 },\n ); // No timeout, wait for user\n }\n\n // Ensure we are fully loaded on the accounts domain too to capture those cookies\n await page.goto(GOOGLE_ACCOUNTS_URL, { waitUntil: \"load\" });\n await page.goto(NOTEBOOKLM_URL, { waitUntil: \"load\" });\n\n const storageState = await context.storageState();\n const cookies = loadCookiesFromObject(storageState as any);\n\n await context.close();\n\n return {\n cookies,\n storageState,\n cookieHeader: Object.entries(cookies)\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \"),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/errors.ts","../src/auth.ts","../src/auth/browser.ts"],"names":["join","homedir","readFileSync","existsSync","DEFAULT_SESSION_FILE","NOTEBOOKLM_URL","chromium","mkdirSync"],"mappings":"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","file":"auth.cjs","sourcesContent":["/**\n * All exceptions for notebooklm-sdk.\n *\n * All errors extend NotebookLMError so you can catch everything with:\n * try { ... } catch (e) { if (e instanceof NotebookLMError) ... }\n */\n\nexport class NotebookLMError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Network (transport-level, before RPC processing)\n// ---------------------------------------------------------------------------\n\nexport class NetworkError extends NotebookLMError {\n readonly methodId?: string;\n readonly originalError?: Error;\n\n constructor(message: string, opts: { methodId?: string; originalError?: Error } = {}) {\n super(message);\n this.methodId = opts.methodId;\n this.originalError = opts.originalError;\n }\n}\n\nexport class RPCTimeoutError extends NetworkError {}\n\n// ---------------------------------------------------------------------------\n// RPC Protocol (after connection established)\n// ---------------------------------------------------------------------------\n\nexport class RPCError extends NotebookLMError {\n readonly methodId?: string;\n readonly rawResponse?: string;\n readonly rpcCode?: string | number;\n readonly foundIds: string[];\n\n constructor(\n message: string,\n opts: {\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n foundIds?: string[];\n } = {},\n ) {\n super(message);\n this.methodId = opts.methodId;\n this.rawResponse = opts.rawResponse ? opts.rawResponse.slice(0, 500) : undefined;\n this.rpcCode = opts.rpcCode;\n this.foundIds = opts.foundIds ?? [];\n }\n}\n\nexport class AuthError extends RPCError {}\n\nexport class RateLimitError extends RPCError {\n readonly retryAfter?: number;\n\n constructor(\n message: string,\n opts: {\n retryAfter?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n foundIds?: string[];\n } = {},\n ) {\n super(message, opts);\n this.retryAfter = opts.retryAfter;\n }\n}\n\nexport class ServerError extends RPCError {\n readonly statusCode?: number;\n\n constructor(\n message: string,\n opts: {\n statusCode?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n } = {},\n ) {\n super(message, opts);\n this.statusCode = opts.statusCode;\n }\n}\n\nexport class ClientError extends RPCError {\n readonly statusCode?: number;\n\n constructor(\n message: string,\n opts: {\n statusCode?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n } = {},\n ) {\n super(message, opts);\n this.statusCode = opts.statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Notebooks\n// ---------------------------------------------------------------------------\n\nexport class NotebookError extends NotebookLMError {}\n\nexport class NotebookNotFoundError extends NotebookError {\n readonly notebookId: string;\n\n constructor(notebookId: string) {\n super(`Notebook not found: ${notebookId}`);\n this.notebookId = notebookId;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Sources\n// ---------------------------------------------------------------------------\n\nexport class SourceError extends NotebookLMError {}\n\nexport class SourceNotFoundError extends SourceError {\n readonly sourceId: string;\n\n constructor(sourceId: string) {\n super(`Source not found: ${sourceId}`);\n this.sourceId = sourceId;\n }\n}\n\nexport class SourceAddError extends SourceError {\n readonly url: string;\n readonly cause?: Error;\n\n constructor(url: string, opts: { cause?: Error; message?: string } = {}) {\n super(\n opts.message ??\n `Failed to add source: ${url}\\n` +\n \"Possible causes:\\n\" +\n \" - URL is invalid or inaccessible\\n\" +\n \" - Content is behind a paywall or requires authentication\\n\" +\n \" - Rate limiting or quota exceeded\",\n );\n this.url = url;\n this.cause = opts.cause;\n }\n}\n\nexport class SourceProcessingError extends SourceError {\n readonly sourceId: string;\n readonly status: number;\n\n constructor(sourceId: string, status = 3, message?: string) {\n super(message ?? `Source ${sourceId} failed to process`);\n this.sourceId = sourceId;\n this.status = status;\n }\n}\n\nexport class SourceTimeoutError extends SourceError {\n readonly sourceId: string;\n readonly timeout: number;\n readonly lastStatus?: number;\n\n constructor(sourceId: string, timeout: number, lastStatus?: number) {\n const statusInfo = lastStatus != null ? ` (last status: ${lastStatus})` : \"\";\n super(`Source ${sourceId} not ready after ${timeout.toFixed(1)}s${statusInfo}`);\n this.sourceId = sourceId;\n this.timeout = timeout;\n this.lastStatus = lastStatus;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Artifacts\n// ---------------------------------------------------------------------------\n\nexport class ArtifactError extends NotebookLMError {}\n\nexport class ArtifactNotFoundError extends ArtifactError {\n readonly artifactId: string;\n readonly artifactType?: string;\n\n constructor(artifactId: string, artifactType?: string) {\n const typeInfo = artifactType ? ` ${artifactType}` : \"\";\n super(`${typeInfo.trim() || \"Artifact\"} ${artifactId} not found`);\n this.artifactId = artifactId;\n this.artifactType = artifactType;\n }\n}\n\nexport class ArtifactNotReadyError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly status?: string;\n\n constructor(artifactType: string, opts: { artifactId?: string; status?: string } = {}) {\n const base = opts.artifactId\n ? `${artifactType} artifact ${opts.artifactId} is not ready`\n : `No completed ${artifactType} found`;\n const statusInfo = opts.status ? ` (status: ${opts.status})` : \"\";\n super(`${base}${statusInfo}`);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.status = opts.status;\n }\n}\n\nexport class ArtifactParseError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly details?: string;\n readonly cause?: Error;\n\n constructor(\n artifactType: string,\n opts: { details?: string; artifactId?: string; cause?: Error } = {},\n ) {\n let msg = `Failed to parse ${artifactType} artifact`;\n if (opts.artifactId) msg += ` ${opts.artifactId}`;\n if (opts.details) msg += `: ${opts.details}`;\n super(msg);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.details = opts.details;\n this.cause = opts.cause;\n }\n}\n\nexport class ArtifactDownloadError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly details?: string;\n readonly cause?: Error;\n\n constructor(\n artifactType: string,\n opts: { details?: string; artifactId?: string; cause?: Error } = {},\n ) {\n let msg = `Failed to download ${artifactType} artifact`;\n if (opts.artifactId) msg += ` ${opts.artifactId}`;\n if (opts.details) msg += `: ${opts.details}`;\n super(msg);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.details = opts.details;\n this.cause = opts.cause;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Chat\n// ---------------------------------------------------------------------------\n\nexport class ChatError extends NotebookLMError {}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { AuthError } from \"./types/errors.js\";\n\n/** Default session file written by `npx notebooklm-sdk login`. */\nconst DEFAULT_SESSION_FILE = join(homedir(), \".notebooklm\", \"session.json\");\n\nexport interface CookieMap {\n [key: string]: string;\n}\n\nexport interface AuthTokens {\n cookies: CookieMap;\n csrfToken: string;\n sessionId: string;\n cookieHeader: string;\n /** Cookie header containing only .google.com domain cookies — for media downloads */\n googleCookieHeader: string;\n}\n\n// ---------------------------------------------------------------------------\n// Cookie loading\n// ---------------------------------------------------------------------------\n\n/** Load cookies from a Playwright storage_state.json file. */\nexport function loadCookiesFromFile(filePath: string): CookieMap {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch {\n throw new AuthError(\n `Session file not found: ${filePath}\\nRun: npx notebooklm-sdk login`,\n );\n }\n return extractCookiesFromStorageState(JSON.parse(raw));\n}\n\n/** Load cookies from a raw Playwright storage state object. */\nexport function loadCookiesFromObject(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): CookieMap {\n return extractCookiesFromStorageState(storageState);\n}\n\n/** Build a cookie header containing only .google.com domain cookies (for media downloads). */\nexport function buildGoogleCookieHeader(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): string {\n const map: CookieMap = {};\n for (const c of storageState.cookies ?? []) {\n if (c.domain === \".google.com\" && c.name && c.value) {\n map[c.name] = map[c.name] ?? c.value;\n }\n }\n return buildCookieHeader(map);\n}\n\n/** Load cookies from a flat cookie map (already parsed). */\nexport function loadCookiesFromMap(map: CookieMap): CookieMap {\n return { ...map };\n}\n\n/** Load cookies from a \"; \"-separated cookie string (e.g. process.env.NOTEBOOKLM_COOKIES). */\nexport function loadCookiesFromString(cookieStr: string): CookieMap {\n const map: CookieMap = {};\n for (const part of cookieStr.split(/;\\s*/)) {\n const idx = part.indexOf(\"=\");\n if (idx > 0) {\n const name = part.slice(0, idx).trim();\n const value = part.slice(idx + 1).trim();\n if (name) map[name] = value;\n }\n }\n return map;\n}\n\nfunction extractCookiesFromStorageState(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): CookieMap {\n const cookies: CookieMap = {};\n const domainTrack: Record<string, string> = {};\n\n for (const cookie of storageState.cookies ?? []) {\n const { domain, name, value } = cookie;\n if (!isAllowedDomain(domain) || !name) continue;\n\n const isBase = domain === \".google.com\";\n if (!(name in cookies) || isBase) {\n cookies[name] = value;\n domainTrack[name] = domain;\n }\n }\n\n if (!cookies[\"SID\"]) {\n throw new AuthError(\n \"Missing required cookie: SID. Session may be invalid or expired.\\nRun: npx notebooklm-sdk login\",\n );\n }\n return cookies;\n}\n\nfunction isAllowedDomain(domain: string): boolean {\n if (\n domain === \".google.com\" ||\n domain === \"notebooklm.google.com\" ||\n domain === \".googleusercontent.com\"\n ) {\n return true;\n }\n if (domain.startsWith(\".google.\")) {\n return true; // Allow all regional Google domains\n }\n return false;\n}\n\nexport function buildCookieHeader(cookies: CookieMap): string {\n return Object.entries(cookies)\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \");\n}\n\n// ---------------------------------------------------------------------------\n// Token fetching\n// ---------------------------------------------------------------------------\n\nconst NOTEBOOKLM_URL = \"https://notebooklm.google.com/\";\n\nexport async function fetchTokens(\n cookies: CookieMap,\n): Promise<{ csrfToken: string; sessionId: string }> {\n const cookieHeader = buildCookieHeader(cookies);\n\n const response = await fetch(NOTEBOOKLM_URL, {\n headers: { Cookie: cookieHeader },\n redirect: \"follow\",\n });\n\n if (!response.ok) {\n throw new AuthError(`Failed to fetch NotebookLM page: HTTP ${response.status}`);\n }\n\n const finalUrl = response.url;\n if (isGoogleAuthRedirect(finalUrl)) {\n throw new AuthError(`Redirected to login page: ${finalUrl}. Cookies may be expired.`);\n }\n\n const html = await response.text();\n const csrfToken = extractCsrfToken(html, finalUrl);\n const sessionId = extractSessionId(html, finalUrl);\n\n return { csrfToken, sessionId };\n}\n\nfunction extractCsrfToken(html: string, finalUrl: string): string {\n const match = /\"SNlM0e\"\\s*:\\s*\"([^\"]+)\"/.exec(html);\n if (!match?.[1]) {\n if (isGoogleAuthRedirect(finalUrl) || html.includes(\"accounts.google.com\")) {\n throw new AuthError(\"Session expired or invalid.\\nRun: npx notebooklm-sdk login\");\n }\n throw new AuthError(\"CSRF token (SNlM0e) not found in NotebookLM page HTML.\");\n }\n return match[1];\n}\n\nfunction extractSessionId(html: string, finalUrl: string): string {\n const match = /\"FdrFJe\"\\s*:\\s*\"([^\"]+)\"/.exec(html);\n if (!match?.[1]) {\n if (isGoogleAuthRedirect(finalUrl) || html.includes(\"accounts.google.com\")) {\n throw new AuthError(\"Session expired or invalid.\\nRun: npx notebooklm-sdk login\");\n }\n throw new AuthError(\"Session ID (FdrFJe) not found in NotebookLM page HTML.\");\n }\n return match[1];\n}\n\nfunction isGoogleAuthRedirect(url: string): boolean {\n return url.includes(\"accounts.google.com\") || url.includes(\"signin\");\n}\n\n// ---------------------------------------------------------------------------\n// Connect options\n// ---------------------------------------------------------------------------\n\nexport interface ConnectOptions {\n /** \"; \"-separated cookie string (e.g. \"SID=abc; HSID=xyz\") */\n cookies?: string;\n /** Path to Playwright storage_state.json */\n cookiesFile?: string;\n /** Pre-parsed cookie map */\n cookiesObject?: CookieMap | { cookies?: Array<{ name: string; value: string; domain: string }> };\n}\n\nexport async function connect(opts: ConnectOptions = {}): Promise<AuthTokens> {\n let cookieMap: CookieMap;\n let googleCookieHeader: string | null = null;\n\n if (opts.cookies) {\n cookieMap = loadCookiesFromString(opts.cookies);\n } else if (opts.cookiesFile) {\n cookieMap = loadCookiesFromFile(opts.cookiesFile);\n } else if (opts.cookiesObject) {\n if (\"cookies\" in opts.cookiesObject && Array.isArray(opts.cookiesObject.cookies)) {\n const storageState = opts.cookiesObject as {\n cookies: Array<{ name: string; value: string; domain: string }>;\n };\n cookieMap = loadCookiesFromObject(storageState);\n googleCookieHeader = buildGoogleCookieHeader(storageState);\n } else {\n cookieMap = loadCookiesFromMap(opts.cookiesObject as CookieMap);\n }\n } else {\n // Auto-discovery: ~/.notebooklm/session.json → ./storage_state.json → env var\n const envCookies = process.env[\"NOTEBOOKLM_COOKIES\"];\n const envFile = process.env[\"NOTEBOOKLM_COOKIES_FILE\"];\n if (envFile) {\n cookieMap = loadCookiesFromFile(envFile);\n } else if (existsSync(DEFAULT_SESSION_FILE)) {\n const raw = readFileSync(DEFAULT_SESSION_FILE, \"utf-8\");\n const storageState = JSON.parse(raw);\n cookieMap = loadCookiesFromObject(storageState);\n googleCookieHeader = buildGoogleCookieHeader(storageState);\n } else if (existsSync(\"storage_state.json\")) {\n const raw = readFileSync(\"storage_state.json\", \"utf-8\");\n const storageState = JSON.parse(raw);\n cookieMap = loadCookiesFromObject(storageState);\n googleCookieHeader = buildGoogleCookieHeader(storageState);\n } else if (envCookies) {\n cookieMap = loadCookiesFromString(envCookies);\n } else {\n throw new AuthError(\n \"No session found. Run: npx notebooklm-sdk login\",\n );\n }\n }\n\n const { csrfToken, sessionId } = await fetchTokens(cookieMap);\n const cookieHeader = buildCookieHeader(cookieMap);\n\n return {\n cookies: cookieMap,\n csrfToken,\n sessionId,\n cookieHeader,\n googleCookieHeader: googleCookieHeader ?? cookieHeader,\n };\n}\n","import { existsSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type BrowserContext, chromium, type Page } from \"playwright\";\nimport { type CookieMap, loadCookiesFromObject } from \"../auth.js\";\n\n/** Default directory for storing NotebookLM session files (~/.notebooklm). */\nexport const DEFAULT_SESSION_DIR = join(homedir(), \".notebooklm\");\n/** Default session file path (~/.notebooklm/session.json). */\nexport const DEFAULT_SESSION_FILE = join(DEFAULT_SESSION_DIR, \"session.json\");\n\nexport interface LoginOptions {\n /**\n * Path to a directory for a persistent browser profile.\n * Defaults to ~/.notebooklm/.auth_profile.\n */\n persistFolder?: string;\n /**\n * Browser type to use. Default is \"chromium\".\n */\n browserType?: \"chromium\" | \"msedge\";\n /**\n * Whether to run the browser in headless mode. Default is false.\n * Headless login is usually blocked by Google, so this is mostly for testing or refreshes.\n */\n headless?: boolean;\n}\n\nconst NOTEBOOKLM_URL = \"https://notebooklm.google.com/\";\nconst GOOGLE_ACCOUNTS_URL = \"https://accounts.google.com/\";\n\n/**\n * Log in to NotebookLM via a headful browser window.\n *\n * Flow:\n * 1. Opens browser to NotebookLM.\n * 2. If already logged in (via persistFolder), it proceeds.\n * 3. If not, it waits for the user to reach the home page.\n * 4. Captures cookies and returns them.\n */\nexport async function login(opts: LoginOptions = {}): Promise<{\n cookies: CookieMap;\n storageState: any;\n cookieHeader: string;\n}> {\n const {\n persistFolder = join(DEFAULT_SESSION_DIR, \".auth_profile\"),\n headless = false,\n browserType = \"chromium\",\n } = opts;\n\n // Pre-flight: verify Playwright browser is installed\n try {\n chromium.executablePath();\n } catch {\n throw new Error(\n \"Playwright browser not found. Run: npx playwright install chromium\",\n );\n }\n\n // Ensure the session directory exists\n if (!existsSync(DEFAULT_SESSION_DIR)) {\n mkdirSync(DEFAULT_SESSION_DIR, { recursive: true });\n }\n\n let context: BrowserContext;\n\n const launchOptions = {\n headless,\n args: [\"--disable-blink-features=AutomationControlled\"],\n };\n\n context = await chromium.launchPersistentContext(persistFolder, {\n ...launchOptions,\n channel: browserType === \"msedge\" ? \"msedge\" : undefined,\n });\n\n const page = context.pages()[0] || (await context.newPage());\n await page.goto(NOTEBOOKLM_URL);\n\n // Check if we are on the login page\n if (page.url().includes(\"accounts.google.com\")) {\n console.log(\"Please log in to Google in the browser window...\");\n\n // Wait for navigation back to NotebookLM or successful login indicator\n // We poll until the URL includes notebooklm.google.com and it's not a generic landing page\n await page.waitForURL(\n (url) => {\n return url.hostname === \"notebooklm.google.com\" && !url.pathname.includes(\"/login\");\n },\n { timeout: 0 },\n ); // No timeout, wait for user\n }\n\n // Ensure we are fully loaded on the accounts domain too to capture those cookies\n await page.goto(GOOGLE_ACCOUNTS_URL, { waitUntil: \"load\" });\n await page.goto(NOTEBOOKLM_URL, { waitUntil: \"load\" });\n\n const storageState = await context.storageState();\n const cookies = loadCookiesFromObject(storageState as any);\n\n await context.close();\n\n return {\n cookies,\n storageState,\n cookieHeader: Object.entries(cookies)\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \"),\n };\n}\n"]}
|
package/dist/auth.d.cts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { C as CookieMap } from './auth-
|
|
2
|
-
export { A as AuthTokens, a as ConnectOptions, b as buildCookieHeader, c as buildGoogleCookieHeader, d as connect, f as fetchTokens, l as loadCookiesFromFile, e as loadCookiesFromMap, g as loadCookiesFromObject, h as loadCookiesFromString } from './auth-
|
|
1
|
+
import { C as CookieMap } from './auth-Dxsm8894.cjs';
|
|
2
|
+
export { A as AuthTokens, a as ConnectOptions, b as buildCookieHeader, c as buildGoogleCookieHeader, d as connect, f as fetchTokens, l as loadCookiesFromFile, e as loadCookiesFromMap, g as loadCookiesFromObject, h as loadCookiesFromString } from './auth-Dxsm8894.cjs';
|
|
3
3
|
|
|
4
|
+
/** Default directory for storing NotebookLM session files (~/.notebooklm). */
|
|
5
|
+
declare const DEFAULT_SESSION_DIR: string;
|
|
6
|
+
/** Default session file path (~/.notebooklm/session.json). */
|
|
7
|
+
declare const DEFAULT_SESSION_FILE: string;
|
|
4
8
|
interface LoginOptions {
|
|
5
9
|
/**
|
|
6
10
|
* Path to a directory for a persistent browser profile.
|
|
7
|
-
*
|
|
11
|
+
* Defaults to ~/.notebooklm/.auth_profile.
|
|
8
12
|
*/
|
|
9
13
|
persistFolder?: string;
|
|
10
14
|
/**
|
|
@@ -32,4 +36,4 @@ declare function login(opts?: LoginOptions): Promise<{
|
|
|
32
36
|
cookieHeader: string;
|
|
33
37
|
}>;
|
|
34
38
|
|
|
35
|
-
export { CookieMap, type LoginOptions, login };
|
|
39
|
+
export { CookieMap, DEFAULT_SESSION_DIR, DEFAULT_SESSION_FILE, type LoginOptions, login };
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { C as CookieMap } from './auth-
|
|
2
|
-
export { A as AuthTokens, a as ConnectOptions, b as buildCookieHeader, c as buildGoogleCookieHeader, d as connect, f as fetchTokens, l as loadCookiesFromFile, e as loadCookiesFromMap, g as loadCookiesFromObject, h as loadCookiesFromString } from './auth-
|
|
1
|
+
import { C as CookieMap } from './auth-Dxsm8894.js';
|
|
2
|
+
export { A as AuthTokens, a as ConnectOptions, b as buildCookieHeader, c as buildGoogleCookieHeader, d as connect, f as fetchTokens, l as loadCookiesFromFile, e as loadCookiesFromMap, g as loadCookiesFromObject, h as loadCookiesFromString } from './auth-Dxsm8894.js';
|
|
3
3
|
|
|
4
|
+
/** Default directory for storing NotebookLM session files (~/.notebooklm). */
|
|
5
|
+
declare const DEFAULT_SESSION_DIR: string;
|
|
6
|
+
/** Default session file path (~/.notebooklm/session.json). */
|
|
7
|
+
declare const DEFAULT_SESSION_FILE: string;
|
|
4
8
|
interface LoginOptions {
|
|
5
9
|
/**
|
|
6
10
|
* Path to a directory for a persistent browser profile.
|
|
7
|
-
*
|
|
11
|
+
* Defaults to ~/.notebooklm/.auth_profile.
|
|
8
12
|
*/
|
|
9
13
|
persistFolder?: string;
|
|
10
14
|
/**
|
|
@@ -32,4 +36,4 @@ declare function login(opts?: LoginOptions): Promise<{
|
|
|
32
36
|
cookieHeader: string;
|
|
33
37
|
}>;
|
|
34
38
|
|
|
35
|
-
export { CookieMap, type LoginOptions, login };
|
|
39
|
+
export { CookieMap, DEFAULT_SESSION_DIR, DEFAULT_SESSION_FILE, type LoginOptions, login };
|
package/dist/auth.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { readFileSync } from 'fs';
|
|
1
|
+
import { readFileSync, existsSync, mkdirSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
2
4
|
import { chromium } from 'playwright';
|
|
3
5
|
|
|
4
6
|
// src/auth.ts
|
|
@@ -27,14 +29,15 @@ var AuthError = class extends RPCError {
|
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
// src/auth.ts
|
|
32
|
+
var DEFAULT_SESSION_FILE = join(homedir(), ".notebooklm", "session.json");
|
|
30
33
|
function loadCookiesFromFile(filePath) {
|
|
31
34
|
let raw;
|
|
32
35
|
try {
|
|
33
36
|
raw = readFileSync(filePath, "utf-8");
|
|
34
37
|
} catch {
|
|
35
38
|
throw new AuthError(
|
|
36
|
-
`
|
|
37
|
-
|
|
39
|
+
`Session file not found: ${filePath}
|
|
40
|
+
Run: npx notebooklm-sdk login`
|
|
38
41
|
);
|
|
39
42
|
}
|
|
40
43
|
return extractCookiesFromStorageState(JSON.parse(raw));
|
|
@@ -78,7 +81,7 @@ function extractCookiesFromStorageState(storageState) {
|
|
|
78
81
|
}
|
|
79
82
|
if (!cookies["SID"]) {
|
|
80
83
|
throw new AuthError(
|
|
81
|
-
"Missing required cookie: SID.
|
|
84
|
+
"Missing required cookie: SID. Session may be invalid or expired.\nRun: npx notebooklm-sdk login"
|
|
82
85
|
);
|
|
83
86
|
}
|
|
84
87
|
return cookies;
|
|
@@ -118,7 +121,7 @@ function extractCsrfToken(html, finalUrl) {
|
|
|
118
121
|
const match = /"SNlM0e"\s*:\s*"([^"]+)"/.exec(html);
|
|
119
122
|
if (!match?.[1]) {
|
|
120
123
|
if (isGoogleAuthRedirect(finalUrl) || html.includes("accounts.google.com")) {
|
|
121
|
-
throw new AuthError("
|
|
124
|
+
throw new AuthError("Session expired or invalid.\nRun: npx notebooklm-sdk login");
|
|
122
125
|
}
|
|
123
126
|
throw new AuthError("CSRF token (SNlM0e) not found in NotebookLM page HTML.");
|
|
124
127
|
}
|
|
@@ -128,7 +131,7 @@ function extractSessionId(html, finalUrl) {
|
|
|
128
131
|
const match = /"FdrFJe"\s*:\s*"([^"]+)"/.exec(html);
|
|
129
132
|
if (!match?.[1]) {
|
|
130
133
|
if (isGoogleAuthRedirect(finalUrl) || html.includes("accounts.google.com")) {
|
|
131
|
-
throw new AuthError("
|
|
134
|
+
throw new AuthError("Session expired or invalid.\nRun: npx notebooklm-sdk login");
|
|
132
135
|
}
|
|
133
136
|
throw new AuthError("Session ID (FdrFJe) not found in NotebookLM page HTML.");
|
|
134
137
|
}
|
|
@@ -137,7 +140,7 @@ function extractSessionId(html, finalUrl) {
|
|
|
137
140
|
function isGoogleAuthRedirect(url) {
|
|
138
141
|
return url.includes("accounts.google.com") || url.includes("signin");
|
|
139
142
|
}
|
|
140
|
-
async function connect(opts) {
|
|
143
|
+
async function connect(opts = {}) {
|
|
141
144
|
let cookieMap;
|
|
142
145
|
let googleCookieHeader = null;
|
|
143
146
|
if (opts.cookies) {
|
|
@@ -154,11 +157,24 @@ async function connect(opts) {
|
|
|
154
157
|
}
|
|
155
158
|
} else {
|
|
156
159
|
const envCookies = process.env["NOTEBOOKLM_COOKIES"];
|
|
157
|
-
|
|
160
|
+
const envFile = process.env["NOTEBOOKLM_COOKIES_FILE"];
|
|
161
|
+
if (envFile) {
|
|
162
|
+
cookieMap = loadCookiesFromFile(envFile);
|
|
163
|
+
} else if (existsSync(DEFAULT_SESSION_FILE)) {
|
|
164
|
+
const raw = readFileSync(DEFAULT_SESSION_FILE, "utf-8");
|
|
165
|
+
const storageState = JSON.parse(raw);
|
|
166
|
+
cookieMap = loadCookiesFromObject(storageState);
|
|
167
|
+
googleCookieHeader = buildGoogleCookieHeader(storageState);
|
|
168
|
+
} else if (existsSync("storage_state.json")) {
|
|
169
|
+
const raw = readFileSync("storage_state.json", "utf-8");
|
|
170
|
+
const storageState = JSON.parse(raw);
|
|
171
|
+
cookieMap = loadCookiesFromObject(storageState);
|
|
172
|
+
googleCookieHeader = buildGoogleCookieHeader(storageState);
|
|
173
|
+
} else if (envCookies) {
|
|
158
174
|
cookieMap = loadCookiesFromString(envCookies);
|
|
159
175
|
} else {
|
|
160
176
|
throw new AuthError(
|
|
161
|
-
"No
|
|
177
|
+
"No session found. Run: npx notebooklm-sdk login"
|
|
162
178
|
);
|
|
163
179
|
}
|
|
164
180
|
}
|
|
@@ -172,27 +188,35 @@ async function connect(opts) {
|
|
|
172
188
|
googleCookieHeader: googleCookieHeader ?? cookieHeader
|
|
173
189
|
};
|
|
174
190
|
}
|
|
191
|
+
var DEFAULT_SESSION_DIR = join(homedir(), ".notebooklm");
|
|
192
|
+
var DEFAULT_SESSION_FILE2 = join(DEFAULT_SESSION_DIR, "session.json");
|
|
175
193
|
var NOTEBOOKLM_URL2 = "https://notebooklm.google.com/";
|
|
176
194
|
var GOOGLE_ACCOUNTS_URL = "https://accounts.google.com/";
|
|
177
195
|
async function login(opts = {}) {
|
|
178
|
-
const {
|
|
196
|
+
const {
|
|
197
|
+
persistFolder = join(DEFAULT_SESSION_DIR, ".auth_profile"),
|
|
198
|
+
headless = false,
|
|
199
|
+
browserType = "chromium"
|
|
200
|
+
} = opts;
|
|
201
|
+
try {
|
|
202
|
+
chromium.executablePath();
|
|
203
|
+
} catch {
|
|
204
|
+
throw new Error(
|
|
205
|
+
"Playwright browser not found. Run: npx playwright install chromium"
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
if (!existsSync(DEFAULT_SESSION_DIR)) {
|
|
209
|
+
mkdirSync(DEFAULT_SESSION_DIR, { recursive: true });
|
|
210
|
+
}
|
|
179
211
|
let context;
|
|
180
212
|
const launchOptions = {
|
|
181
213
|
headless,
|
|
182
214
|
args: ["--disable-blink-features=AutomationControlled"]
|
|
183
215
|
};
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
});
|
|
189
|
-
} else {
|
|
190
|
-
const browser = await chromium.launch({
|
|
191
|
-
...launchOptions,
|
|
192
|
-
channel: browserType === "msedge" ? "msedge" : void 0
|
|
193
|
-
});
|
|
194
|
-
context = await browser.newContext();
|
|
195
|
-
}
|
|
216
|
+
context = await chromium.launchPersistentContext(persistFolder, {
|
|
217
|
+
...launchOptions,
|
|
218
|
+
channel: browserType === "msedge" ? "msedge" : void 0
|
|
219
|
+
});
|
|
196
220
|
const page = context.pages()[0] || await context.newPage();
|
|
197
221
|
await page.goto(NOTEBOOKLM_URL2);
|
|
198
222
|
if (page.url().includes("accounts.google.com")) {
|
|
@@ -216,6 +240,6 @@ async function login(opts = {}) {
|
|
|
216
240
|
};
|
|
217
241
|
}
|
|
218
242
|
|
|
219
|
-
export { buildCookieHeader, buildGoogleCookieHeader, connect, fetchTokens, loadCookiesFromFile, loadCookiesFromMap, loadCookiesFromObject, loadCookiesFromString, login };
|
|
243
|
+
export { DEFAULT_SESSION_DIR, DEFAULT_SESSION_FILE2 as DEFAULT_SESSION_FILE, buildCookieHeader, buildGoogleCookieHeader, connect, fetchTokens, loadCookiesFromFile, loadCookiesFromMap, loadCookiesFromObject, loadCookiesFromString, login };
|
|
220
244
|
//# sourceMappingURL=auth.js.map
|
|
221
245
|
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/errors.ts","../src/auth.ts","../src/auth/browser.ts"],"names":["NOTEBOOKLM_URL"],"mappings":"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","file":"auth.js","sourcesContent":["/**\n * All exceptions for notebooklm-sdk.\n *\n * All errors extend NotebookLMError so you can catch everything with:\n * try { ... } catch (e) { if (e instanceof NotebookLMError) ... }\n */\n\nexport class NotebookLMError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Network (transport-level, before RPC processing)\n// ---------------------------------------------------------------------------\n\nexport class NetworkError extends NotebookLMError {\n readonly methodId?: string;\n readonly originalError?: Error;\n\n constructor(message: string, opts: { methodId?: string; originalError?: Error } = {}) {\n super(message);\n this.methodId = opts.methodId;\n this.originalError = opts.originalError;\n }\n}\n\nexport class RPCTimeoutError extends NetworkError {}\n\n// ---------------------------------------------------------------------------\n// RPC Protocol (after connection established)\n// ---------------------------------------------------------------------------\n\nexport class RPCError extends NotebookLMError {\n readonly methodId?: string;\n readonly rawResponse?: string;\n readonly rpcCode?: string | number;\n readonly foundIds: string[];\n\n constructor(\n message: string,\n opts: {\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n foundIds?: string[];\n } = {},\n ) {\n super(message);\n this.methodId = opts.methodId;\n this.rawResponse = opts.rawResponse ? opts.rawResponse.slice(0, 500) : undefined;\n this.rpcCode = opts.rpcCode;\n this.foundIds = opts.foundIds ?? [];\n }\n}\n\nexport class AuthError extends RPCError {}\n\nexport class RateLimitError extends RPCError {\n readonly retryAfter?: number;\n\n constructor(\n message: string,\n opts: {\n retryAfter?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n foundIds?: string[];\n } = {},\n ) {\n super(message, opts);\n this.retryAfter = opts.retryAfter;\n }\n}\n\nexport class ServerError extends RPCError {\n readonly statusCode?: number;\n\n constructor(\n message: string,\n opts: {\n statusCode?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n } = {},\n ) {\n super(message, opts);\n this.statusCode = opts.statusCode;\n }\n}\n\nexport class ClientError extends RPCError {\n readonly statusCode?: number;\n\n constructor(\n message: string,\n opts: {\n statusCode?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n } = {},\n ) {\n super(message, opts);\n this.statusCode = opts.statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Notebooks\n// ---------------------------------------------------------------------------\n\nexport class NotebookError extends NotebookLMError {}\n\nexport class NotebookNotFoundError extends NotebookError {\n readonly notebookId: string;\n\n constructor(notebookId: string) {\n super(`Notebook not found: ${notebookId}`);\n this.notebookId = notebookId;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Sources\n// ---------------------------------------------------------------------------\n\nexport class SourceError extends NotebookLMError {}\n\nexport class SourceNotFoundError extends SourceError {\n readonly sourceId: string;\n\n constructor(sourceId: string) {\n super(`Source not found: ${sourceId}`);\n this.sourceId = sourceId;\n }\n}\n\nexport class SourceAddError extends SourceError {\n readonly url: string;\n readonly cause?: Error;\n\n constructor(url: string, opts: { cause?: Error; message?: string } = {}) {\n super(\n opts.message ??\n `Failed to add source: ${url}\\n` +\n \"Possible causes:\\n\" +\n \" - URL is invalid or inaccessible\\n\" +\n \" - Content is behind a paywall or requires authentication\\n\" +\n \" - Rate limiting or quota exceeded\",\n );\n this.url = url;\n this.cause = opts.cause;\n }\n}\n\nexport class SourceProcessingError extends SourceError {\n readonly sourceId: string;\n readonly status: number;\n\n constructor(sourceId: string, status = 3, message?: string) {\n super(message ?? `Source ${sourceId} failed to process`);\n this.sourceId = sourceId;\n this.status = status;\n }\n}\n\nexport class SourceTimeoutError extends SourceError {\n readonly sourceId: string;\n readonly timeout: number;\n readonly lastStatus?: number;\n\n constructor(sourceId: string, timeout: number, lastStatus?: number) {\n const statusInfo = lastStatus != null ? ` (last status: ${lastStatus})` : \"\";\n super(`Source ${sourceId} not ready after ${timeout.toFixed(1)}s${statusInfo}`);\n this.sourceId = sourceId;\n this.timeout = timeout;\n this.lastStatus = lastStatus;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Artifacts\n// ---------------------------------------------------------------------------\n\nexport class ArtifactError extends NotebookLMError {}\n\nexport class ArtifactNotFoundError extends ArtifactError {\n readonly artifactId: string;\n readonly artifactType?: string;\n\n constructor(artifactId: string, artifactType?: string) {\n const typeInfo = artifactType ? ` ${artifactType}` : \"\";\n super(`${typeInfo.trim() || \"Artifact\"} ${artifactId} not found`);\n this.artifactId = artifactId;\n this.artifactType = artifactType;\n }\n}\n\nexport class ArtifactNotReadyError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly status?: string;\n\n constructor(artifactType: string, opts: { artifactId?: string; status?: string } = {}) {\n const base = opts.artifactId\n ? `${artifactType} artifact ${opts.artifactId} is not ready`\n : `No completed ${artifactType} found`;\n const statusInfo = opts.status ? ` (status: ${opts.status})` : \"\";\n super(`${base}${statusInfo}`);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.status = opts.status;\n }\n}\n\nexport class ArtifactParseError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly details?: string;\n readonly cause?: Error;\n\n constructor(\n artifactType: string,\n opts: { details?: string; artifactId?: string; cause?: Error } = {},\n ) {\n let msg = `Failed to parse ${artifactType} artifact`;\n if (opts.artifactId) msg += ` ${opts.artifactId}`;\n if (opts.details) msg += `: ${opts.details}`;\n super(msg);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.details = opts.details;\n this.cause = opts.cause;\n }\n}\n\nexport class ArtifactDownloadError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly details?: string;\n readonly cause?: Error;\n\n constructor(\n artifactType: string,\n opts: { details?: string; artifactId?: string; cause?: Error } = {},\n ) {\n let msg = `Failed to download ${artifactType} artifact`;\n if (opts.artifactId) msg += ` ${opts.artifactId}`;\n if (opts.details) msg += `: ${opts.details}`;\n super(msg);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.details = opts.details;\n this.cause = opts.cause;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Chat\n// ---------------------------------------------------------------------------\n\nexport class ChatError extends NotebookLMError {}\n","import { readFileSync } from \"node:fs\";\nimport { AuthError } from \"./types/errors.js\";\n\nexport interface CookieMap {\n [key: string]: string;\n}\n\nexport interface AuthTokens {\n cookies: CookieMap;\n csrfToken: string;\n sessionId: string;\n cookieHeader: string;\n /** Cookie header containing only .google.com domain cookies — for media downloads */\n googleCookieHeader: string;\n}\n\n// ---------------------------------------------------------------------------\n// Cookie loading\n// ---------------------------------------------------------------------------\n\n/** Load cookies from a Playwright storage_state.json file. */\nexport function loadCookiesFromFile(filePath: string): CookieMap {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch {\n throw new AuthError(\n `Cookie file not found: ${filePath}\\n` + \"Provide valid Playwright storage state JSON.\",\n );\n }\n return extractCookiesFromStorageState(JSON.parse(raw));\n}\n\n/** Load cookies from a raw Playwright storage state object. */\nexport function loadCookiesFromObject(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): CookieMap {\n return extractCookiesFromStorageState(storageState);\n}\n\n/** Build a cookie header containing only .google.com domain cookies (for media downloads). */\nexport function buildGoogleCookieHeader(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): string {\n const map: CookieMap = {};\n for (const c of storageState.cookies ?? []) {\n if (c.domain === \".google.com\" && c.name && c.value) {\n map[c.name] = map[c.name] ?? c.value;\n }\n }\n return buildCookieHeader(map);\n}\n\n/** Load cookies from a flat cookie map (already parsed). */\nexport function loadCookiesFromMap(map: CookieMap): CookieMap {\n return { ...map };\n}\n\n/** Load cookies from a \"; \"-separated cookie string (e.g. process.env.NOTEBOOKLM_COOKIES). */\nexport function loadCookiesFromString(cookieStr: string): CookieMap {\n const map: CookieMap = {};\n for (const part of cookieStr.split(/;\\s*/)) {\n const idx = part.indexOf(\"=\");\n if (idx > 0) {\n const name = part.slice(0, idx).trim();\n const value = part.slice(idx + 1).trim();\n if (name) map[name] = value;\n }\n }\n return map;\n}\n\nfunction extractCookiesFromStorageState(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): CookieMap {\n const cookies: CookieMap = {};\n const domainTrack: Record<string, string> = {};\n\n for (const cookie of storageState.cookies ?? []) {\n const { domain, name, value } = cookie;\n if (!isAllowedDomain(domain) || !name) continue;\n\n const isBase = domain === \".google.com\";\n if (!(name in cookies) || isBase) {\n cookies[name] = value;\n domainTrack[name] = domain;\n }\n }\n\n if (!cookies[\"SID\"]) {\n throw new AuthError(\n \"Missing required cookie: SID. \" +\n \"Provide valid Playwright storage state with Google cookies.\",\n );\n }\n return cookies;\n}\n\nfunction isAllowedDomain(domain: string): boolean {\n if (\n domain === \".google.com\" ||\n domain === \"notebooklm.google.com\" ||\n domain === \".googleusercontent.com\"\n ) {\n return true;\n }\n if (domain.startsWith(\".google.\")) {\n return true; // Allow all regional Google domains\n }\n return false;\n}\n\nexport function buildCookieHeader(cookies: CookieMap): string {\n return Object.entries(cookies)\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \");\n}\n\n// ---------------------------------------------------------------------------\n// Token fetching\n// ---------------------------------------------------------------------------\n\nconst NOTEBOOKLM_URL = \"https://notebooklm.google.com/\";\n\nexport async function fetchTokens(\n cookies: CookieMap,\n): Promise<{ csrfToken: string; sessionId: string }> {\n const cookieHeader = buildCookieHeader(cookies);\n\n const response = await fetch(NOTEBOOKLM_URL, {\n headers: { Cookie: cookieHeader },\n redirect: \"follow\",\n });\n\n if (!response.ok) {\n throw new AuthError(`Failed to fetch NotebookLM page: HTTP ${response.status}`);\n }\n\n const finalUrl = response.url;\n if (isGoogleAuthRedirect(finalUrl)) {\n throw new AuthError(`Redirected to login page: ${finalUrl}. Cookies may be expired.`);\n }\n\n const html = await response.text();\n const csrfToken = extractCsrfToken(html, finalUrl);\n const sessionId = extractSessionId(html, finalUrl);\n\n return { csrfToken, sessionId };\n}\n\nfunction extractCsrfToken(html: string, finalUrl: string): string {\n const match = /\"SNlM0e\"\\s*:\\s*\"([^\"]+)\"/.exec(html);\n if (!match?.[1]) {\n if (isGoogleAuthRedirect(finalUrl) || html.includes(\"accounts.google.com\")) {\n throw new AuthError(\"Authentication expired or invalid. Cookies may need to be refreshed.\");\n }\n throw new AuthError(\"CSRF token (SNlM0e) not found in NotebookLM page HTML.\");\n }\n return match[1];\n}\n\nfunction extractSessionId(html: string, finalUrl: string): string {\n const match = /\"FdrFJe\"\\s*:\\s*\"([^\"]+)\"/.exec(html);\n if (!match?.[1]) {\n if (isGoogleAuthRedirect(finalUrl) || html.includes(\"accounts.google.com\")) {\n throw new AuthError(\"Authentication expired or invalid. Cookies may need to be refreshed.\");\n }\n throw new AuthError(\"Session ID (FdrFJe) not found in NotebookLM page HTML.\");\n }\n return match[1];\n}\n\nfunction isGoogleAuthRedirect(url: string): boolean {\n return url.includes(\"accounts.google.com\") || url.includes(\"signin\");\n}\n\n// ---------------------------------------------------------------------------\n// Connect options\n// ---------------------------------------------------------------------------\n\nexport interface ConnectOptions {\n /** \"; \"-separated cookie string (e.g. \"SID=abc; HSID=xyz\") */\n cookies?: string;\n /** Path to Playwright storage_state.json */\n cookiesFile?: string;\n /** Pre-parsed cookie map */\n cookiesObject?: CookieMap | { cookies?: Array<{ name: string; value: string; domain: string }> };\n}\n\nexport async function connect(opts: ConnectOptions): Promise<AuthTokens> {\n let cookieMap: CookieMap;\n let googleCookieHeader: string | null = null;\n\n if (opts.cookies) {\n cookieMap = loadCookiesFromString(opts.cookies);\n } else if (opts.cookiesFile) {\n cookieMap = loadCookiesFromFile(opts.cookiesFile);\n } else if (opts.cookiesObject) {\n if (\"cookies\" in opts.cookiesObject && Array.isArray(opts.cookiesObject.cookies)) {\n const storageState = opts.cookiesObject as {\n cookies: Array<{ name: string; value: string; domain: string }>;\n };\n cookieMap = loadCookiesFromObject(storageState);\n googleCookieHeader = buildGoogleCookieHeader(storageState);\n } else {\n cookieMap = loadCookiesFromMap(opts.cookiesObject as CookieMap);\n }\n } else {\n // Fallback: check environment variable\n const envCookies = process.env[\"NOTEBOOKLM_COOKIES\"];\n if (envCookies) {\n cookieMap = loadCookiesFromString(envCookies);\n } else {\n throw new AuthError(\n \"No cookies provided. Pass cookies, cookiesFile, or cookiesObject to connect().\",\n );\n }\n }\n\n const { csrfToken, sessionId } = await fetchTokens(cookieMap);\n const cookieHeader = buildCookieHeader(cookieMap);\n\n return {\n cookies: cookieMap,\n csrfToken,\n sessionId,\n cookieHeader,\n googleCookieHeader: googleCookieHeader ?? cookieHeader,\n };\n}\n","import { type BrowserContext, chromium, type Page } from \"playwright\";\nimport { type CookieMap, loadCookiesFromObject } from \"../auth.js\";\n\nexport interface LoginOptions {\n /**\n * Path to a directory for a persistent browser profile.\n * If provided, session remains logged in for future calls.\n */\n persistFolder?: string;\n /**\n * Browser type to use. Default is \"chromium\".\n */\n browserType?: \"chromium\" | \"msedge\";\n /**\n * Whether to run the browser in headless mode. Default is false.\n * Headless login is usually blocked by Google, so this is mostly for testing or refreshes.\n */\n headless?: boolean;\n}\n\nconst NOTEBOOKLM_URL = \"https://notebooklm.google.com/\";\nconst GOOGLE_ACCOUNTS_URL = \"https://accounts.google.com/\";\n\n/**\n * Log in to NotebookLM via a headful browser window.\n *\n * Flow:\n * 1. Opens browser to NotebookLM.\n * 2. If already logged in (via persistFolder), it proceeds.\n * 3. If not, it waits for the user to reach the home page.\n * 4. Captures cookies and returns them.\n */\nexport async function login(opts: LoginOptions = {}): Promise<{\n cookies: CookieMap;\n storageState: any;\n cookieHeader: string;\n}> {\n const { persistFolder, headless = false, browserType = \"chromium\" } = opts;\n\n let context: BrowserContext;\n\n const launchOptions = {\n headless,\n args: [\"--disable-blink-features=AutomationControlled\"],\n };\n\n if (persistFolder) {\n context = await chromium.launchPersistentContext(persistFolder, {\n ...launchOptions,\n channel: browserType === \"msedge\" ? \"msedge\" : undefined,\n });\n } else {\n const browser = await chromium.launch({\n ...launchOptions,\n channel: browserType === \"msedge\" ? \"msedge\" : undefined,\n });\n context = await browser.newContext();\n }\n\n const page = context.pages()[0] || (await context.newPage());\n await page.goto(NOTEBOOKLM_URL);\n\n // Check if we are on the login page\n if (page.url().includes(\"accounts.google.com\")) {\n console.log(\"Please log in to Google in the browser window...\");\n\n // Wait for navigation back to NotebookLM or successful login indicator\n // We poll until the URL includes notebooklm.google.com and it's not a generic landing page\n await page.waitForURL(\n (url) => {\n return url.hostname === \"notebooklm.google.com\" && !url.pathname.includes(\"/login\");\n },\n { timeout: 0 },\n ); // No timeout, wait for user\n }\n\n // Ensure we are fully loaded on the accounts domain too to capture those cookies\n await page.goto(GOOGLE_ACCOUNTS_URL, { waitUntil: \"load\" });\n await page.goto(NOTEBOOKLM_URL, { waitUntil: \"load\" });\n\n const storageState = await context.storageState();\n const cookies = loadCookiesFromObject(storageState as any);\n\n await context.close();\n\n return {\n cookies,\n storageState,\n cookieHeader: Object.entries(cookies)\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \"),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/errors.ts","../src/auth.ts","../src/auth/browser.ts"],"names":["join","homedir","DEFAULT_SESSION_FILE","NOTEBOOKLM_URL","existsSync"],"mappings":"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","file":"auth.js","sourcesContent":["/**\n * All exceptions for notebooklm-sdk.\n *\n * All errors extend NotebookLMError so you can catch everything with:\n * try { ... } catch (e) { if (e instanceof NotebookLMError) ... }\n */\n\nexport class NotebookLMError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Network (transport-level, before RPC processing)\n// ---------------------------------------------------------------------------\n\nexport class NetworkError extends NotebookLMError {\n readonly methodId?: string;\n readonly originalError?: Error;\n\n constructor(message: string, opts: { methodId?: string; originalError?: Error } = {}) {\n super(message);\n this.methodId = opts.methodId;\n this.originalError = opts.originalError;\n }\n}\n\nexport class RPCTimeoutError extends NetworkError {}\n\n// ---------------------------------------------------------------------------\n// RPC Protocol (after connection established)\n// ---------------------------------------------------------------------------\n\nexport class RPCError extends NotebookLMError {\n readonly methodId?: string;\n readonly rawResponse?: string;\n readonly rpcCode?: string | number;\n readonly foundIds: string[];\n\n constructor(\n message: string,\n opts: {\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n foundIds?: string[];\n } = {},\n ) {\n super(message);\n this.methodId = opts.methodId;\n this.rawResponse = opts.rawResponse ? opts.rawResponse.slice(0, 500) : undefined;\n this.rpcCode = opts.rpcCode;\n this.foundIds = opts.foundIds ?? [];\n }\n}\n\nexport class AuthError extends RPCError {}\n\nexport class RateLimitError extends RPCError {\n readonly retryAfter?: number;\n\n constructor(\n message: string,\n opts: {\n retryAfter?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n foundIds?: string[];\n } = {},\n ) {\n super(message, opts);\n this.retryAfter = opts.retryAfter;\n }\n}\n\nexport class ServerError extends RPCError {\n readonly statusCode?: number;\n\n constructor(\n message: string,\n opts: {\n statusCode?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n } = {},\n ) {\n super(message, opts);\n this.statusCode = opts.statusCode;\n }\n}\n\nexport class ClientError extends RPCError {\n readonly statusCode?: number;\n\n constructor(\n message: string,\n opts: {\n statusCode?: number;\n methodId?: string;\n rawResponse?: string;\n rpcCode?: string | number;\n } = {},\n ) {\n super(message, opts);\n this.statusCode = opts.statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Notebooks\n// ---------------------------------------------------------------------------\n\nexport class NotebookError extends NotebookLMError {}\n\nexport class NotebookNotFoundError extends NotebookError {\n readonly notebookId: string;\n\n constructor(notebookId: string) {\n super(`Notebook not found: ${notebookId}`);\n this.notebookId = notebookId;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Sources\n// ---------------------------------------------------------------------------\n\nexport class SourceError extends NotebookLMError {}\n\nexport class SourceNotFoundError extends SourceError {\n readonly sourceId: string;\n\n constructor(sourceId: string) {\n super(`Source not found: ${sourceId}`);\n this.sourceId = sourceId;\n }\n}\n\nexport class SourceAddError extends SourceError {\n readonly url: string;\n readonly cause?: Error;\n\n constructor(url: string, opts: { cause?: Error; message?: string } = {}) {\n super(\n opts.message ??\n `Failed to add source: ${url}\\n` +\n \"Possible causes:\\n\" +\n \" - URL is invalid or inaccessible\\n\" +\n \" - Content is behind a paywall or requires authentication\\n\" +\n \" - Rate limiting or quota exceeded\",\n );\n this.url = url;\n this.cause = opts.cause;\n }\n}\n\nexport class SourceProcessingError extends SourceError {\n readonly sourceId: string;\n readonly status: number;\n\n constructor(sourceId: string, status = 3, message?: string) {\n super(message ?? `Source ${sourceId} failed to process`);\n this.sourceId = sourceId;\n this.status = status;\n }\n}\n\nexport class SourceTimeoutError extends SourceError {\n readonly sourceId: string;\n readonly timeout: number;\n readonly lastStatus?: number;\n\n constructor(sourceId: string, timeout: number, lastStatus?: number) {\n const statusInfo = lastStatus != null ? ` (last status: ${lastStatus})` : \"\";\n super(`Source ${sourceId} not ready after ${timeout.toFixed(1)}s${statusInfo}`);\n this.sourceId = sourceId;\n this.timeout = timeout;\n this.lastStatus = lastStatus;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Artifacts\n// ---------------------------------------------------------------------------\n\nexport class ArtifactError extends NotebookLMError {}\n\nexport class ArtifactNotFoundError extends ArtifactError {\n readonly artifactId: string;\n readonly artifactType?: string;\n\n constructor(artifactId: string, artifactType?: string) {\n const typeInfo = artifactType ? ` ${artifactType}` : \"\";\n super(`${typeInfo.trim() || \"Artifact\"} ${artifactId} not found`);\n this.artifactId = artifactId;\n this.artifactType = artifactType;\n }\n}\n\nexport class ArtifactNotReadyError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly status?: string;\n\n constructor(artifactType: string, opts: { artifactId?: string; status?: string } = {}) {\n const base = opts.artifactId\n ? `${artifactType} artifact ${opts.artifactId} is not ready`\n : `No completed ${artifactType} found`;\n const statusInfo = opts.status ? ` (status: ${opts.status})` : \"\";\n super(`${base}${statusInfo}`);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.status = opts.status;\n }\n}\n\nexport class ArtifactParseError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly details?: string;\n readonly cause?: Error;\n\n constructor(\n artifactType: string,\n opts: { details?: string; artifactId?: string; cause?: Error } = {},\n ) {\n let msg = `Failed to parse ${artifactType} artifact`;\n if (opts.artifactId) msg += ` ${opts.artifactId}`;\n if (opts.details) msg += `: ${opts.details}`;\n super(msg);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.details = opts.details;\n this.cause = opts.cause;\n }\n}\n\nexport class ArtifactDownloadError extends ArtifactError {\n readonly artifactType: string;\n readonly artifactId?: string;\n readonly details?: string;\n readonly cause?: Error;\n\n constructor(\n artifactType: string,\n opts: { details?: string; artifactId?: string; cause?: Error } = {},\n ) {\n let msg = `Failed to download ${artifactType} artifact`;\n if (opts.artifactId) msg += ` ${opts.artifactId}`;\n if (opts.details) msg += `: ${opts.details}`;\n super(msg);\n this.artifactType = artifactType;\n this.artifactId = opts.artifactId;\n this.details = opts.details;\n this.cause = opts.cause;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain: Chat\n// ---------------------------------------------------------------------------\n\nexport class ChatError extends NotebookLMError {}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { AuthError } from \"./types/errors.js\";\n\n/** Default session file written by `npx notebooklm-sdk login`. */\nconst DEFAULT_SESSION_FILE = join(homedir(), \".notebooklm\", \"session.json\");\n\nexport interface CookieMap {\n [key: string]: string;\n}\n\nexport interface AuthTokens {\n cookies: CookieMap;\n csrfToken: string;\n sessionId: string;\n cookieHeader: string;\n /** Cookie header containing only .google.com domain cookies — for media downloads */\n googleCookieHeader: string;\n}\n\n// ---------------------------------------------------------------------------\n// Cookie loading\n// ---------------------------------------------------------------------------\n\n/** Load cookies from a Playwright storage_state.json file. */\nexport function loadCookiesFromFile(filePath: string): CookieMap {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch {\n throw new AuthError(\n `Session file not found: ${filePath}\\nRun: npx notebooklm-sdk login`,\n );\n }\n return extractCookiesFromStorageState(JSON.parse(raw));\n}\n\n/** Load cookies from a raw Playwright storage state object. */\nexport function loadCookiesFromObject(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): CookieMap {\n return extractCookiesFromStorageState(storageState);\n}\n\n/** Build a cookie header containing only .google.com domain cookies (for media downloads). */\nexport function buildGoogleCookieHeader(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): string {\n const map: CookieMap = {};\n for (const c of storageState.cookies ?? []) {\n if (c.domain === \".google.com\" && c.name && c.value) {\n map[c.name] = map[c.name] ?? c.value;\n }\n }\n return buildCookieHeader(map);\n}\n\n/** Load cookies from a flat cookie map (already parsed). */\nexport function loadCookiesFromMap(map: CookieMap): CookieMap {\n return { ...map };\n}\n\n/** Load cookies from a \"; \"-separated cookie string (e.g. process.env.NOTEBOOKLM_COOKIES). */\nexport function loadCookiesFromString(cookieStr: string): CookieMap {\n const map: CookieMap = {};\n for (const part of cookieStr.split(/;\\s*/)) {\n const idx = part.indexOf(\"=\");\n if (idx > 0) {\n const name = part.slice(0, idx).trim();\n const value = part.slice(idx + 1).trim();\n if (name) map[name] = value;\n }\n }\n return map;\n}\n\nfunction extractCookiesFromStorageState(storageState: {\n cookies?: Array<{ name: string; value: string; domain: string }>;\n}): CookieMap {\n const cookies: CookieMap = {};\n const domainTrack: Record<string, string> = {};\n\n for (const cookie of storageState.cookies ?? []) {\n const { domain, name, value } = cookie;\n if (!isAllowedDomain(domain) || !name) continue;\n\n const isBase = domain === \".google.com\";\n if (!(name in cookies) || isBase) {\n cookies[name] = value;\n domainTrack[name] = domain;\n }\n }\n\n if (!cookies[\"SID\"]) {\n throw new AuthError(\n \"Missing required cookie: SID. Session may be invalid or expired.\\nRun: npx notebooklm-sdk login\",\n );\n }\n return cookies;\n}\n\nfunction isAllowedDomain(domain: string): boolean {\n if (\n domain === \".google.com\" ||\n domain === \"notebooklm.google.com\" ||\n domain === \".googleusercontent.com\"\n ) {\n return true;\n }\n if (domain.startsWith(\".google.\")) {\n return true; // Allow all regional Google domains\n }\n return false;\n}\n\nexport function buildCookieHeader(cookies: CookieMap): string {\n return Object.entries(cookies)\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \");\n}\n\n// ---------------------------------------------------------------------------\n// Token fetching\n// ---------------------------------------------------------------------------\n\nconst NOTEBOOKLM_URL = \"https://notebooklm.google.com/\";\n\nexport async function fetchTokens(\n cookies: CookieMap,\n): Promise<{ csrfToken: string; sessionId: string }> {\n const cookieHeader = buildCookieHeader(cookies);\n\n const response = await fetch(NOTEBOOKLM_URL, {\n headers: { Cookie: cookieHeader },\n redirect: \"follow\",\n });\n\n if (!response.ok) {\n throw new AuthError(`Failed to fetch NotebookLM page: HTTP ${response.status}`);\n }\n\n const finalUrl = response.url;\n if (isGoogleAuthRedirect(finalUrl)) {\n throw new AuthError(`Redirected to login page: ${finalUrl}. Cookies may be expired.`);\n }\n\n const html = await response.text();\n const csrfToken = extractCsrfToken(html, finalUrl);\n const sessionId = extractSessionId(html, finalUrl);\n\n return { csrfToken, sessionId };\n}\n\nfunction extractCsrfToken(html: string, finalUrl: string): string {\n const match = /\"SNlM0e\"\\s*:\\s*\"([^\"]+)\"/.exec(html);\n if (!match?.[1]) {\n if (isGoogleAuthRedirect(finalUrl) || html.includes(\"accounts.google.com\")) {\n throw new AuthError(\"Session expired or invalid.\\nRun: npx notebooklm-sdk login\");\n }\n throw new AuthError(\"CSRF token (SNlM0e) not found in NotebookLM page HTML.\");\n }\n return match[1];\n}\n\nfunction extractSessionId(html: string, finalUrl: string): string {\n const match = /\"FdrFJe\"\\s*:\\s*\"([^\"]+)\"/.exec(html);\n if (!match?.[1]) {\n if (isGoogleAuthRedirect(finalUrl) || html.includes(\"accounts.google.com\")) {\n throw new AuthError(\"Session expired or invalid.\\nRun: npx notebooklm-sdk login\");\n }\n throw new AuthError(\"Session ID (FdrFJe) not found in NotebookLM page HTML.\");\n }\n return match[1];\n}\n\nfunction isGoogleAuthRedirect(url: string): boolean {\n return url.includes(\"accounts.google.com\") || url.includes(\"signin\");\n}\n\n// ---------------------------------------------------------------------------\n// Connect options\n// ---------------------------------------------------------------------------\n\nexport interface ConnectOptions {\n /** \"; \"-separated cookie string (e.g. \"SID=abc; HSID=xyz\") */\n cookies?: string;\n /** Path to Playwright storage_state.json */\n cookiesFile?: string;\n /** Pre-parsed cookie map */\n cookiesObject?: CookieMap | { cookies?: Array<{ name: string; value: string; domain: string }> };\n}\n\nexport async function connect(opts: ConnectOptions = {}): Promise<AuthTokens> {\n let cookieMap: CookieMap;\n let googleCookieHeader: string | null = null;\n\n if (opts.cookies) {\n cookieMap = loadCookiesFromString(opts.cookies);\n } else if (opts.cookiesFile) {\n cookieMap = loadCookiesFromFile(opts.cookiesFile);\n } else if (opts.cookiesObject) {\n if (\"cookies\" in opts.cookiesObject && Array.isArray(opts.cookiesObject.cookies)) {\n const storageState = opts.cookiesObject as {\n cookies: Array<{ name: string; value: string; domain: string }>;\n };\n cookieMap = loadCookiesFromObject(storageState);\n googleCookieHeader = buildGoogleCookieHeader(storageState);\n } else {\n cookieMap = loadCookiesFromMap(opts.cookiesObject as CookieMap);\n }\n } else {\n // Auto-discovery: ~/.notebooklm/session.json → ./storage_state.json → env var\n const envCookies = process.env[\"NOTEBOOKLM_COOKIES\"];\n const envFile = process.env[\"NOTEBOOKLM_COOKIES_FILE\"];\n if (envFile) {\n cookieMap = loadCookiesFromFile(envFile);\n } else if (existsSync(DEFAULT_SESSION_FILE)) {\n const raw = readFileSync(DEFAULT_SESSION_FILE, \"utf-8\");\n const storageState = JSON.parse(raw);\n cookieMap = loadCookiesFromObject(storageState);\n googleCookieHeader = buildGoogleCookieHeader(storageState);\n } else if (existsSync(\"storage_state.json\")) {\n const raw = readFileSync(\"storage_state.json\", \"utf-8\");\n const storageState = JSON.parse(raw);\n cookieMap = loadCookiesFromObject(storageState);\n googleCookieHeader = buildGoogleCookieHeader(storageState);\n } else if (envCookies) {\n cookieMap = loadCookiesFromString(envCookies);\n } else {\n throw new AuthError(\n \"No session found. Run: npx notebooklm-sdk login\",\n );\n }\n }\n\n const { csrfToken, sessionId } = await fetchTokens(cookieMap);\n const cookieHeader = buildCookieHeader(cookieMap);\n\n return {\n cookies: cookieMap,\n csrfToken,\n sessionId,\n cookieHeader,\n googleCookieHeader: googleCookieHeader ?? cookieHeader,\n };\n}\n","import { existsSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type BrowserContext, chromium, type Page } from \"playwright\";\nimport { type CookieMap, loadCookiesFromObject } from \"../auth.js\";\n\n/** Default directory for storing NotebookLM session files (~/.notebooklm). */\nexport const DEFAULT_SESSION_DIR = join(homedir(), \".notebooklm\");\n/** Default session file path (~/.notebooklm/session.json). */\nexport const DEFAULT_SESSION_FILE = join(DEFAULT_SESSION_DIR, \"session.json\");\n\nexport interface LoginOptions {\n /**\n * Path to a directory for a persistent browser profile.\n * Defaults to ~/.notebooklm/.auth_profile.\n */\n persistFolder?: string;\n /**\n * Browser type to use. Default is \"chromium\".\n */\n browserType?: \"chromium\" | \"msedge\";\n /**\n * Whether to run the browser in headless mode. Default is false.\n * Headless login is usually blocked by Google, so this is mostly for testing or refreshes.\n */\n headless?: boolean;\n}\n\nconst NOTEBOOKLM_URL = \"https://notebooklm.google.com/\";\nconst GOOGLE_ACCOUNTS_URL = \"https://accounts.google.com/\";\n\n/**\n * Log in to NotebookLM via a headful browser window.\n *\n * Flow:\n * 1. Opens browser to NotebookLM.\n * 2. If already logged in (via persistFolder), it proceeds.\n * 3. If not, it waits for the user to reach the home page.\n * 4. Captures cookies and returns them.\n */\nexport async function login(opts: LoginOptions = {}): Promise<{\n cookies: CookieMap;\n storageState: any;\n cookieHeader: string;\n}> {\n const {\n persistFolder = join(DEFAULT_SESSION_DIR, \".auth_profile\"),\n headless = false,\n browserType = \"chromium\",\n } = opts;\n\n // Pre-flight: verify Playwright browser is installed\n try {\n chromium.executablePath();\n } catch {\n throw new Error(\n \"Playwright browser not found. Run: npx playwright install chromium\",\n );\n }\n\n // Ensure the session directory exists\n if (!existsSync(DEFAULT_SESSION_DIR)) {\n mkdirSync(DEFAULT_SESSION_DIR, { recursive: true });\n }\n\n let context: BrowserContext;\n\n const launchOptions = {\n headless,\n args: [\"--disable-blink-features=AutomationControlled\"],\n };\n\n context = await chromium.launchPersistentContext(persistFolder, {\n ...launchOptions,\n channel: browserType === \"msedge\" ? \"msedge\" : undefined,\n });\n\n const page = context.pages()[0] || (await context.newPage());\n await page.goto(NOTEBOOKLM_URL);\n\n // Check if we are on the login page\n if (page.url().includes(\"accounts.google.com\")) {\n console.log(\"Please log in to Google in the browser window...\");\n\n // Wait for navigation back to NotebookLM or successful login indicator\n // We poll until the URL includes notebooklm.google.com and it's not a generic landing page\n await page.waitForURL(\n (url) => {\n return url.hostname === \"notebooklm.google.com\" && !url.pathname.includes(\"/login\");\n },\n { timeout: 0 },\n ); // No timeout, wait for user\n }\n\n // Ensure we are fully loaded on the accounts domain too to capture those cookies\n await page.goto(GOOGLE_ACCOUNTS_URL, { waitUntil: \"load\" });\n await page.goto(NOTEBOOKLM_URL, { waitUntil: \"load\" });\n\n const storageState = await context.storageState();\n const cookies = loadCookiesFromObject(storageState as any);\n\n await context.close();\n\n return {\n cookies,\n storageState,\n cookieHeader: Object.entries(cookies)\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \"),\n };\n}\n"]}
|