notebooklm-sdk 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -242
- 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 +45 -25
- 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 +45 -27
- package/dist/auth.js.map +1 -1
- package/dist/bin.cjs +170 -31
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +172 -33
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +199 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -26
- package/dist/index.d.ts +42 -26
- package/dist/index.js +200 -87
- package/dist/index.js.map +1 -1
- package/package.json +11 -3
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { readFileSync } from 'fs';
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
2
4
|
|
|
3
5
|
var __defProp = Object.defineProperty;
|
|
4
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -451,10 +453,8 @@ function loadCookiesFromFile(filePath) {
|
|
|
451
453
|
try {
|
|
452
454
|
raw = readFileSync(filePath, "utf-8");
|
|
453
455
|
} catch {
|
|
454
|
-
throw new AuthError(
|
|
455
|
-
|
|
456
|
-
Provide valid Playwright storage state JSON.`
|
|
457
|
-
);
|
|
456
|
+
throw new AuthError(`Session file not found: ${filePath}
|
|
457
|
+
Run: npx notebooklm-sdk login`);
|
|
458
458
|
}
|
|
459
459
|
return extractCookiesFromStorageState(JSON.parse(raw));
|
|
460
460
|
}
|
|
@@ -497,7 +497,7 @@ function extractCookiesFromStorageState(storageState) {
|
|
|
497
497
|
}
|
|
498
498
|
if (!cookies["SID"]) {
|
|
499
499
|
throw new AuthError(
|
|
500
|
-
"Missing required cookie: SID.
|
|
500
|
+
"Missing required cookie: SID. Session may be invalid or expired.\nRun: npx notebooklm-sdk login"
|
|
501
501
|
);
|
|
502
502
|
}
|
|
503
503
|
return cookies;
|
|
@@ -536,7 +536,7 @@ function extractCsrfToken(html, finalUrl) {
|
|
|
536
536
|
const match = /"SNlM0e"\s*:\s*"([^"]+)"/.exec(html);
|
|
537
537
|
if (!match?.[1]) {
|
|
538
538
|
if (isGoogleAuthRedirect(finalUrl) || html.includes("accounts.google.com")) {
|
|
539
|
-
throw new AuthError("
|
|
539
|
+
throw new AuthError("Session expired or invalid.\nRun: npx notebooklm-sdk login");
|
|
540
540
|
}
|
|
541
541
|
throw new AuthError("CSRF token (SNlM0e) not found in NotebookLM page HTML.");
|
|
542
542
|
}
|
|
@@ -546,7 +546,7 @@ function extractSessionId(html, finalUrl) {
|
|
|
546
546
|
const match = /"FdrFJe"\s*:\s*"([^"]+)"/.exec(html);
|
|
547
547
|
if (!match?.[1]) {
|
|
548
548
|
if (isGoogleAuthRedirect(finalUrl) || html.includes("accounts.google.com")) {
|
|
549
|
-
throw new AuthError("
|
|
549
|
+
throw new AuthError("Session expired or invalid.\nRun: npx notebooklm-sdk login");
|
|
550
550
|
}
|
|
551
551
|
throw new AuthError("Session ID (FdrFJe) not found in NotebookLM page HTML.");
|
|
552
552
|
}
|
|
@@ -555,7 +555,7 @@ function extractSessionId(html, finalUrl) {
|
|
|
555
555
|
function isGoogleAuthRedirect(url) {
|
|
556
556
|
return url.includes("accounts.google.com") || url.includes("signin");
|
|
557
557
|
}
|
|
558
|
-
async function connect(opts) {
|
|
558
|
+
async function connect(opts = {}) {
|
|
559
559
|
let cookieMap;
|
|
560
560
|
let googleCookieHeader = null;
|
|
561
561
|
if (opts.cookies) {
|
|
@@ -572,12 +572,23 @@ async function connect(opts) {
|
|
|
572
572
|
}
|
|
573
573
|
} else {
|
|
574
574
|
const envCookies = process.env["NOTEBOOKLM_COOKIES"];
|
|
575
|
-
|
|
575
|
+
const envFile = process.env["NOTEBOOKLM_COOKIES_FILE"];
|
|
576
|
+
if (envFile) {
|
|
577
|
+
cookieMap = loadCookiesFromFile(envFile);
|
|
578
|
+
} else if (existsSync(DEFAULT_SESSION_FILE)) {
|
|
579
|
+
const raw = readFileSync(DEFAULT_SESSION_FILE, "utf-8");
|
|
580
|
+
const storageState = JSON.parse(raw);
|
|
581
|
+
cookieMap = loadCookiesFromObject(storageState);
|
|
582
|
+
googleCookieHeader = buildGoogleCookieHeader(storageState);
|
|
583
|
+
} else if (existsSync("storage_state.json")) {
|
|
584
|
+
const raw = readFileSync("storage_state.json", "utf-8");
|
|
585
|
+
const storageState = JSON.parse(raw);
|
|
586
|
+
cookieMap = loadCookiesFromObject(storageState);
|
|
587
|
+
googleCookieHeader = buildGoogleCookieHeader(storageState);
|
|
588
|
+
} else if (envCookies) {
|
|
576
589
|
cookieMap = loadCookiesFromString(envCookies);
|
|
577
590
|
} else {
|
|
578
|
-
throw new AuthError(
|
|
579
|
-
"No cookies provided. Pass cookies, cookiesFile, or cookiesObject to connect()."
|
|
580
|
-
);
|
|
591
|
+
throw new AuthError("No session found. Run: npx notebooklm-sdk login");
|
|
581
592
|
}
|
|
582
593
|
}
|
|
583
594
|
const { csrfToken, sessionId } = await fetchTokens(cookieMap);
|
|
@@ -590,10 +601,11 @@ async function connect(opts) {
|
|
|
590
601
|
googleCookieHeader: googleCookieHeader ?? cookieHeader
|
|
591
602
|
};
|
|
592
603
|
}
|
|
593
|
-
var NOTEBOOKLM_URL;
|
|
604
|
+
var DEFAULT_SESSION_FILE, NOTEBOOKLM_URL;
|
|
594
605
|
var init_auth = __esm({
|
|
595
606
|
"src/auth.ts"() {
|
|
596
607
|
init_errors();
|
|
608
|
+
DEFAULT_SESSION_FILE = join(homedir(), ".notebooklm", "session.json");
|
|
597
609
|
NOTEBOOKLM_URL = "https://notebooklm.google.com/";
|
|
598
610
|
}
|
|
599
611
|
});
|
|
@@ -711,26 +723,6 @@ function parseArtifact(data, notebookId) {
|
|
|
711
723
|
_raw: Array.isArray(data) ? data : []
|
|
712
724
|
};
|
|
713
725
|
}
|
|
714
|
-
function parseNote(data) {
|
|
715
|
-
const id = typeof data[0] === "string" ? data[0] : "";
|
|
716
|
-
const content = typeof data[1] === "string" ? data[1] : "";
|
|
717
|
-
const title = typeof data[2] === "string" ? data[2] : null;
|
|
718
|
-
let createdAt = null;
|
|
719
|
-
let updatedAt = null;
|
|
720
|
-
if (Array.isArray(data[3]) && typeof data[3][0] === "number") {
|
|
721
|
-
try {
|
|
722
|
-
createdAt = new Date(data[3][0] * 1e3);
|
|
723
|
-
} catch {
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (Array.isArray(data[4]) && typeof data[4][0] === "number") {
|
|
727
|
-
try {
|
|
728
|
-
updatedAt = new Date(data[4][0] * 1e3);
|
|
729
|
-
} catch {
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
return { id, title, content, createdAt, updatedAt };
|
|
733
|
-
}
|
|
734
726
|
|
|
735
727
|
// src/api/artifacts.ts
|
|
736
728
|
function tripleNest(ids) {
|
|
@@ -740,18 +732,13 @@ function doubleNest(ids) {
|
|
|
740
732
|
return ids.map((id) => [id]);
|
|
741
733
|
}
|
|
742
734
|
var ArtifactsAPI = class {
|
|
743
|
-
constructor(rpc, auth) {
|
|
735
|
+
constructor(rpc, auth, notes) {
|
|
744
736
|
this.rpc = rpc;
|
|
745
737
|
this.auth = auth;
|
|
738
|
+
this.notes = notes;
|
|
746
739
|
}
|
|
747
740
|
async list(notebookId) {
|
|
748
|
-
const
|
|
749
|
-
const result = await this.rpc.call(RPCMethod.LIST_ARTIFACTS, params, {
|
|
750
|
-
sourcePath: `/notebook/${notebookId}`,
|
|
751
|
-
allowNull: true
|
|
752
|
-
});
|
|
753
|
-
if (!Array.isArray(result) || !result.length) return [];
|
|
754
|
-
const rawList = Array.isArray(result[0]) ? result[0] : result;
|
|
741
|
+
const rawList = await this._listRaw(notebookId);
|
|
755
742
|
const artifacts = [];
|
|
756
743
|
for (const item of rawList) {
|
|
757
744
|
if (Array.isArray(item)) {
|
|
@@ -763,6 +750,15 @@ var ArtifactsAPI = class {
|
|
|
763
750
|
}
|
|
764
751
|
return artifacts;
|
|
765
752
|
}
|
|
753
|
+
async _listRaw(notebookId) {
|
|
754
|
+
const params = [[2], notebookId, 'NOT artifact.status = "ARTIFACT_STATUS_SUGGESTED"'];
|
|
755
|
+
const result = await this.rpc.call(RPCMethod.LIST_ARTIFACTS, params, {
|
|
756
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
757
|
+
allowNull: true
|
|
758
|
+
});
|
|
759
|
+
if (!Array.isArray(result) || !result.length) return [];
|
|
760
|
+
return Array.isArray(result[0]) ? result[0] : result;
|
|
761
|
+
}
|
|
766
762
|
async get(notebookId, artifactId) {
|
|
767
763
|
const artifacts = await this.list(notebookId);
|
|
768
764
|
return artifacts.find((a) => a.id === artifactId) ?? null;
|
|
@@ -942,6 +938,37 @@ var ArtifactsAPI = class {
|
|
|
942
938
|
];
|
|
943
939
|
return this._callGenerate(notebookId, params);
|
|
944
940
|
}
|
|
941
|
+
async createDataTable(notebookId, opts = {}) {
|
|
942
|
+
const language = opts.language ?? "en";
|
|
943
|
+
const sourceIds = opts.sourceIds ?? await this.rpc.getSourceIds(notebookId);
|
|
944
|
+
const triple = tripleNest(sourceIds);
|
|
945
|
+
const params = [
|
|
946
|
+
[2],
|
|
947
|
+
notebookId,
|
|
948
|
+
[
|
|
949
|
+
null,
|
|
950
|
+
null,
|
|
951
|
+
ArtifactTypeCode.DATA_TABLE,
|
|
952
|
+
triple,
|
|
953
|
+
null,
|
|
954
|
+
null,
|
|
955
|
+
null,
|
|
956
|
+
null,
|
|
957
|
+
null,
|
|
958
|
+
null,
|
|
959
|
+
null,
|
|
960
|
+
null,
|
|
961
|
+
null,
|
|
962
|
+
null,
|
|
963
|
+
null,
|
|
964
|
+
null,
|
|
965
|
+
null,
|
|
966
|
+
null,
|
|
967
|
+
[null, [opts.instructions ?? null, language]]
|
|
968
|
+
]
|
|
969
|
+
];
|
|
970
|
+
return this._callGenerate(notebookId, params);
|
|
971
|
+
}
|
|
945
972
|
async createReport(notebookId, opts = {}) {
|
|
946
973
|
const format = opts.format ?? "briefing_doc";
|
|
947
974
|
const language = opts.language ?? "en";
|
|
@@ -1007,7 +1034,15 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1007
1034
|
sourcePath: `/notebook/${notebookId}`,
|
|
1008
1035
|
allowNull: true
|
|
1009
1036
|
});
|
|
1010
|
-
|
|
1037
|
+
const mindMapJson = Array.isArray(result) && Array.isArray(result[0]) && typeof result[0][0] === "string" ? result[0][0] : null;
|
|
1038
|
+
if (!mindMapJson) throw new Error("Mind map generation returned no content");
|
|
1039
|
+
let title = "Mind Map";
|
|
1040
|
+
try {
|
|
1041
|
+
const parsed = JSON.parse(mindMapJson);
|
|
1042
|
+
if (typeof parsed["name"] === "string") title = parsed["name"];
|
|
1043
|
+
} catch {
|
|
1044
|
+
}
|
|
1045
|
+
return this.notes.create(notebookId, mindMapJson, title);
|
|
1011
1046
|
}
|
|
1012
1047
|
// ---------------------------------------------------------------------------
|
|
1013
1048
|
// Polling / download
|
|
@@ -1063,6 +1098,48 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1063
1098
|
}
|
|
1064
1099
|
return null;
|
|
1065
1100
|
}
|
|
1101
|
+
/** Download a completed slide deck as PDF or PPTX. Returns a Buffer. */
|
|
1102
|
+
async downloadSlideDeck(notebookId, artifactId, format = "pdf") {
|
|
1103
|
+
const rawList = await this._listRaw(notebookId);
|
|
1104
|
+
const raw = rawList.find(
|
|
1105
|
+
(a) => a[0] === artifactId && a[2] === ArtifactTypeCode.SLIDE_DECK
|
|
1106
|
+
);
|
|
1107
|
+
if (!raw) throw new ArtifactNotReadyError("slide_deck", { artifactId });
|
|
1108
|
+
const metadata = raw[16];
|
|
1109
|
+
if (!Array.isArray(metadata)) throw new ArtifactNotReadyError("slide_deck", { artifactId });
|
|
1110
|
+
const url = format === "pptx" ? metadata[4] : metadata[3];
|
|
1111
|
+
if (typeof url !== "string" || !url.startsWith("http")) {
|
|
1112
|
+
throw new ArtifactNotReadyError("slide_deck", { artifactId, status: `no ${format} url` });
|
|
1113
|
+
}
|
|
1114
|
+
return this._fetchMediaWithCookies(url);
|
|
1115
|
+
}
|
|
1116
|
+
/** Download a completed infographic as PNG. Returns a Buffer. */
|
|
1117
|
+
async downloadInfographic(notebookId, artifactId) {
|
|
1118
|
+
const rawList = await this._listRaw(notebookId);
|
|
1119
|
+
const raw = rawList.find(
|
|
1120
|
+
(a) => a[0] === artifactId && a[2] === ArtifactTypeCode.INFOGRAPHIC
|
|
1121
|
+
);
|
|
1122
|
+
if (!raw) throw new ArtifactNotReadyError("infographic", { artifactId });
|
|
1123
|
+
let url = null;
|
|
1124
|
+
for (let i = raw.length - 1; i >= 0; i--) {
|
|
1125
|
+
const item = raw[i];
|
|
1126
|
+
if (Array.isArray(item) && Array.isArray(item[2]) && Array.isArray(item[2][0]) && Array.isArray(item[2][0][1]) && typeof item[2][0][1][0] === "string" && item[2][0][1][0].startsWith("http")) {
|
|
1127
|
+
url = item[2][0][1][0];
|
|
1128
|
+
break;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
if (!url) throw new ArtifactNotReadyError("infographic", { artifactId });
|
|
1132
|
+
return this._fetchMediaWithCookies(url);
|
|
1133
|
+
}
|
|
1134
|
+
/** Get parsed headers and rows from a completed data table artifact. */
|
|
1135
|
+
async getDataTableContent(notebookId, artifactId) {
|
|
1136
|
+
const artifacts = await this._listRaw(notebookId);
|
|
1137
|
+
const raw = artifacts.find(
|
|
1138
|
+
(a) => Array.isArray(a) && a[0] === artifactId && a[2] === ArtifactTypeCode.DATA_TABLE
|
|
1139
|
+
);
|
|
1140
|
+
if (!raw || !Array.isArray(raw) || !Array.isArray(raw[18])) return null;
|
|
1141
|
+
return parseDataTable(raw[18]);
|
|
1142
|
+
}
|
|
1066
1143
|
// ---------------------------------------------------------------------------
|
|
1067
1144
|
// Internal
|
|
1068
1145
|
// ---------------------------------------------------------------------------
|
|
@@ -1119,6 +1196,34 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1119
1196
|
return { artifactId: null, status: "failed" };
|
|
1120
1197
|
}
|
|
1121
1198
|
};
|
|
1199
|
+
function extractCellText(cell) {
|
|
1200
|
+
if (typeof cell === "string") return cell;
|
|
1201
|
+
if (typeof cell === "number") return "";
|
|
1202
|
+
if (Array.isArray(cell)) return cell.map(extractCellText).join("");
|
|
1203
|
+
return "";
|
|
1204
|
+
}
|
|
1205
|
+
function parseDataTable(rawData) {
|
|
1206
|
+
try {
|
|
1207
|
+
const nav = rawData;
|
|
1208
|
+
const rowsArray = nav[0][0][0][0][4][2];
|
|
1209
|
+
if (!rowsArray?.length) throw new Error("Empty data table");
|
|
1210
|
+
const headers = [];
|
|
1211
|
+
const rows = [];
|
|
1212
|
+
for (let i = 0; i < rowsArray.length; i++) {
|
|
1213
|
+
const rowSection = rowsArray[i];
|
|
1214
|
+
if (!Array.isArray(rowSection) || rowSection.length < 3) continue;
|
|
1215
|
+
const cellArray = rowSection[2];
|
|
1216
|
+
if (!Array.isArray(cellArray)) continue;
|
|
1217
|
+
const values = cellArray.map(extractCellText);
|
|
1218
|
+
if (i === 0) headers.push(...values);
|
|
1219
|
+
else rows.push(values);
|
|
1220
|
+
}
|
|
1221
|
+
if (!headers.length) throw new Error("No headers found");
|
|
1222
|
+
return { headers, rows };
|
|
1223
|
+
} catch (e) {
|
|
1224
|
+
throw new Error(`Failed to parse data table: ${e}`);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1122
1227
|
function sleep(ms) {
|
|
1123
1228
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1124
1229
|
}
|
|
@@ -1455,61 +1560,69 @@ var NotesAPI = class {
|
|
|
1455
1560
|
this.rpc = rpc;
|
|
1456
1561
|
}
|
|
1457
1562
|
async list(notebookId) {
|
|
1458
|
-
const
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
const
|
|
1463
|
-
|
|
1464
|
-
if (!Array.isArray(result)) return { notes, mindMaps };
|
|
1465
|
-
try {
|
|
1466
|
-
const notesData = result[0];
|
|
1467
|
-
if (Array.isArray(notesData)) {
|
|
1468
|
-
for (const n of notesData) {
|
|
1469
|
-
if (Array.isArray(n)) notes.push(parseNote(n));
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
const mapsData = result[1];
|
|
1473
|
-
if (Array.isArray(mapsData)) {
|
|
1474
|
-
for (const m of mapsData) {
|
|
1475
|
-
if (Array.isArray(m)) {
|
|
1476
|
-
mindMaps.push({
|
|
1477
|
-
id: typeof m[0] === "string" ? m[0] : "",
|
|
1478
|
-
title: typeof m[2] === "string" ? m[2] : null,
|
|
1479
|
-
content: typeof m[1] === "string" ? m[1] : "",
|
|
1480
|
-
createdAt: Array.isArray(m[3]) && typeof m[3][0] === "number" ? new Date(m[3][0] * 1e3) : null
|
|
1481
|
-
});
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
} catch {
|
|
1486
|
-
}
|
|
1487
|
-
return { notes, mindMaps };
|
|
1563
|
+
const all = await this._fetchAll(notebookId);
|
|
1564
|
+
return all.filter((n) => !this._isMindMap(n.content));
|
|
1565
|
+
}
|
|
1566
|
+
async listMindMaps(notebookId) {
|
|
1567
|
+
const all = await this._fetchAll(notebookId);
|
|
1568
|
+
return all.filter((n) => this._isMindMap(n.content));
|
|
1488
1569
|
}
|
|
1489
1570
|
async create(notebookId, content, title) {
|
|
1490
|
-
const
|
|
1491
|
-
const result = await this.rpc.call(RPCMethod.CREATE_NOTE,
|
|
1492
|
-
sourcePath: `/notebook/${notebookId}
|
|
1571
|
+
const createParams = [notebookId, "", [1], null, "New Note"];
|
|
1572
|
+
const result = await this.rpc.call(RPCMethod.CREATE_NOTE, createParams, {
|
|
1573
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1574
|
+
allowNull: true
|
|
1493
1575
|
});
|
|
1494
|
-
|
|
1495
|
-
throw new Error("
|
|
1576
|
+
const noteId = Array.isArray(result) && Array.isArray(result[0]) && typeof result[0][0] === "string" ? result[0][0] : Array.isArray(result) && typeof result[0] === "string" ? result[0] : null;
|
|
1577
|
+
if (!noteId) throw new Error("CREATE_NOTE did not return a note ID");
|
|
1578
|
+
await this.update(notebookId, noteId, content, title ?? "New Note");
|
|
1579
|
+
return { id: noteId, title: title ?? null, content, createdAt: null, updatedAt: /* @__PURE__ */ new Date() };
|
|
1496
1580
|
}
|
|
1497
1581
|
async update(notebookId, noteId, content, title) {
|
|
1498
|
-
const params = [notebookId, noteId, content, title ??
|
|
1499
|
-
|
|
1500
|
-
sourcePath: `/notebook/${notebookId}
|
|
1582
|
+
const params = [notebookId, noteId, [[[content, title ?? "New Note", [], 0]]]];
|
|
1583
|
+
await this.rpc.call(RPCMethod.UPDATE_NOTE, params, {
|
|
1584
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1585
|
+
allowNull: true
|
|
1501
1586
|
});
|
|
1502
|
-
if (Array.isArray(result)) return parseNote(result);
|
|
1503
1587
|
return { id: noteId, title: title ?? null, content, createdAt: null, updatedAt: /* @__PURE__ */ new Date() };
|
|
1504
1588
|
}
|
|
1505
1589
|
async delete(notebookId, noteId) {
|
|
1506
|
-
const params = [notebookId,
|
|
1590
|
+
const params = [notebookId, null, [noteId]];
|
|
1507
1591
|
await this.rpc.call(RPCMethod.DELETE_NOTE, params, {
|
|
1508
1592
|
sourcePath: `/notebook/${notebookId}`,
|
|
1509
1593
|
allowNull: true
|
|
1510
1594
|
});
|
|
1511
1595
|
return true;
|
|
1512
1596
|
}
|
|
1597
|
+
async _fetchAll(notebookId) {
|
|
1598
|
+
const result = await this.rpc.call(RPCMethod.GET_NOTES_AND_MIND_MAPS, [notebookId], {
|
|
1599
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1600
|
+
allowNull: true
|
|
1601
|
+
});
|
|
1602
|
+
if (!Array.isArray(result) || !Array.isArray(result[0])) return [];
|
|
1603
|
+
const notes = [];
|
|
1604
|
+
for (const item of result[0]) {
|
|
1605
|
+
if (!Array.isArray(item) || typeof item[0] !== "string") continue;
|
|
1606
|
+
if (item[1] === null && item[2] === 2) continue;
|
|
1607
|
+
const content = this._extractContent(item);
|
|
1608
|
+
notes.push(this._parseItem(item, notebookId, content));
|
|
1609
|
+
}
|
|
1610
|
+
return notes;
|
|
1611
|
+
}
|
|
1612
|
+
_isMindMap(content) {
|
|
1613
|
+
return content.includes('"children":') || content.includes('"nodes":');
|
|
1614
|
+
}
|
|
1615
|
+
_extractContent(item) {
|
|
1616
|
+
if (typeof item[1] === "string") return item[1];
|
|
1617
|
+
if (Array.isArray(item[1]) && typeof item[1][1] === "string") return item[1][1];
|
|
1618
|
+
return "";
|
|
1619
|
+
}
|
|
1620
|
+
_parseItem(item, _notebookId, content) {
|
|
1621
|
+
const inner = Array.isArray(item[1]) ? item[1] : null;
|
|
1622
|
+
const title = inner && typeof inner[4] === "string" && inner[4] ? inner[4] : null;
|
|
1623
|
+
const createdAt = Array.isArray(item[3]) && typeof item[3][0] === "number" ? new Date(item[3][0] * 1e3) : null;
|
|
1624
|
+
return { id: item[0], title, content, createdAt, updatedAt: null };
|
|
1625
|
+
}
|
|
1513
1626
|
};
|
|
1514
1627
|
|
|
1515
1628
|
// src/api/research.ts
|
|
@@ -1646,7 +1759,7 @@ var ResearchAPI = class {
|
|
|
1646
1759
|
const webSources = sources.filter((s) => s.url && !reportSourceSet.has(s));
|
|
1647
1760
|
if (!webSources.length && !reportSources.length) return [];
|
|
1648
1761
|
const sourceArray = [
|
|
1649
|
-
...reportSources.map((s) => buildReportEntry(s.title, s.reportMarkdown)),
|
|
1762
|
+
...reportSources.filter((s) => s.reportMarkdown).map((s) => buildReportEntry(s.title, s.reportMarkdown)),
|
|
1650
1763
|
...webSources.map((s) => buildWebEntry(s.url, s.title))
|
|
1651
1764
|
];
|
|
1652
1765
|
const params = [null, [1], effectiveTaskId, notebookId, sourceArray];
|
|
@@ -2376,9 +2489,9 @@ var NotebookLMClient = class _NotebookLMClient {
|
|
|
2376
2489
|
const rpc = new RPCCore(auth, opts.timeoutMs);
|
|
2377
2490
|
this.notebooks = new NotebooksAPI(rpc);
|
|
2378
2491
|
this.sources = new SourcesAPI(rpc, auth);
|
|
2379
|
-
this.artifacts = new ArtifactsAPI(rpc, auth);
|
|
2380
|
-
this.chat = new ChatAPI(rpc, auth);
|
|
2381
2492
|
this.notes = new NotesAPI(rpc);
|
|
2493
|
+
this.artifacts = new ArtifactsAPI(rpc, auth, this.notes);
|
|
2494
|
+
this.chat = new ChatAPI(rpc, auth);
|
|
2382
2495
|
this.research = new ResearchAPI(rpc);
|
|
2383
2496
|
this.settings = new SettingsAPI(rpc);
|
|
2384
2497
|
this.sharing = new SharingAPI(rpc);
|
|
@@ -2395,7 +2508,7 @@ var NotebookLMClient = class _NotebookLMClient {
|
|
|
2395
2508
|
* Connect to NotebookLM using cookies.
|
|
2396
2509
|
* Fetches CSRF and session tokens from the NotebookLM homepage.
|
|
2397
2510
|
*/
|
|
2398
|
-
static async connect(opts, clientOpts = {}) {
|
|
2511
|
+
static async connect(opts = {}, clientOpts = {}) {
|
|
2399
2512
|
const auth = await connect(opts);
|
|
2400
2513
|
return new _NotebookLMClient(auth, clientOpts);
|
|
2401
2514
|
}
|