notebooklm-sdk 0.1.8 → 0.3.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.cjs +4 -10
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.js +4 -10
- package/dist/auth.js.map +1 -1
- package/dist/bin.cjs +4 -10
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +4 -10
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +324 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -20
- package/dist/index.d.ts +85 -20
- package/dist/index.js +325 -81
- package/dist/index.js.map +1 -1
- package/package.json +11 -3
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ __export(enums_exports, {
|
|
|
19
19
|
ArtifactTypeCode: () => ArtifactTypeCode,
|
|
20
20
|
AudioFormat: () => AudioFormat,
|
|
21
21
|
AudioLength: () => AudioLength,
|
|
22
|
+
ChatMode: () => ChatMode,
|
|
22
23
|
ExportType: () => ExportType,
|
|
23
24
|
InfographicDetail: () => InfographicDetail,
|
|
24
25
|
InfographicOrientation: () => InfographicOrientation,
|
|
@@ -36,6 +37,7 @@ __export(enums_exports, {
|
|
|
36
37
|
VideoStyle: () => VideoStyle,
|
|
37
38
|
artifactStatusFromCode: () => artifactStatusFromCode,
|
|
38
39
|
artifactTypeFromCode: () => artifactTypeFromCode,
|
|
40
|
+
chatModeToParams: () => chatModeToParams,
|
|
39
41
|
sourceStatusFromCode: () => sourceStatusFromCode,
|
|
40
42
|
sourceTypeFromCode: () => sourceTypeFromCode
|
|
41
43
|
});
|
|
@@ -57,7 +59,10 @@ function artifactStatusFromCode(code) {
|
|
|
57
59
|
function sourceStatusFromCode(code) {
|
|
58
60
|
return SOURCE_STATUS_MAP[code] ?? "unknown";
|
|
59
61
|
}
|
|
60
|
-
|
|
62
|
+
function chatModeToParams(mode) {
|
|
63
|
+
return CHAT_MODE_PARAMS[mode];
|
|
64
|
+
}
|
|
65
|
+
var RPCMethod, ArtifactTypeCode, ArtifactStatusCode, SourceStatusCode, AudioFormat, AudioLength, VideoFormat, VideoStyle, QuizQuantity, QuizDifficulty, InfographicOrientation, InfographicDetail, InfographicStyle, SlideDeckFormat, SlideDeckLength, ExportType, SOURCE_TYPE_MAP, ARTIFACT_TYPE_MAP, ARTIFACT_STATUS_MAP, SOURCE_STATUS_MAP, ChatMode, CHAT_MODE_PARAMS, ShareAccess, ShareViewLevel, SharePermission;
|
|
61
66
|
var init_enums = __esm({
|
|
62
67
|
"src/types/enums.ts"() {
|
|
63
68
|
RPCMethod = {
|
|
@@ -241,6 +246,22 @@ var init_enums = __esm({
|
|
|
241
246
|
3: "error",
|
|
242
247
|
5: "preparing"
|
|
243
248
|
};
|
|
249
|
+
ChatMode = {
|
|
250
|
+
/** General purpose — balanced length and style. */
|
|
251
|
+
DEFAULT: "default",
|
|
252
|
+
/** Educational focus with longer, learning-oriented responses. */
|
|
253
|
+
LEARNING_GUIDE: "learning_guide",
|
|
254
|
+
/** Short, concise answers. */
|
|
255
|
+
CONCISE: "concise",
|
|
256
|
+
/** Verbose, detailed answers. */
|
|
257
|
+
DETAILED: "detailed"
|
|
258
|
+
};
|
|
259
|
+
CHAT_MODE_PARAMS = {
|
|
260
|
+
default: [1, 1],
|
|
261
|
+
learning_guide: [3, 4],
|
|
262
|
+
concise: [1, 5],
|
|
263
|
+
detailed: [1, 4]
|
|
264
|
+
};
|
|
244
265
|
ShareAccess = {
|
|
245
266
|
/** Only explicitly shared users can access */
|
|
246
267
|
RESTRICTED: 0,
|
|
@@ -453,10 +474,8 @@ function loadCookiesFromFile(filePath) {
|
|
|
453
474
|
try {
|
|
454
475
|
raw = readFileSync(filePath, "utf-8");
|
|
455
476
|
} catch {
|
|
456
|
-
throw new AuthError(
|
|
457
|
-
|
|
458
|
-
Run: npx notebooklm-sdk login`
|
|
459
|
-
);
|
|
477
|
+
throw new AuthError(`Session file not found: ${filePath}
|
|
478
|
+
Run: npx notebooklm-sdk login`);
|
|
460
479
|
}
|
|
461
480
|
return extractCookiesFromStorageState(JSON.parse(raw));
|
|
462
481
|
}
|
|
@@ -590,9 +609,7 @@ async function connect(opts = {}) {
|
|
|
590
609
|
} else if (envCookies) {
|
|
591
610
|
cookieMap = loadCookiesFromString(envCookies);
|
|
592
611
|
} else {
|
|
593
|
-
throw new AuthError(
|
|
594
|
-
"No session found. Run: npx notebooklm-sdk login"
|
|
595
|
-
);
|
|
612
|
+
throw new AuthError("No session found. Run: npx notebooklm-sdk login");
|
|
596
613
|
}
|
|
597
614
|
}
|
|
598
615
|
const { csrfToken, sessionId } = await fetchTokens(cookieMap);
|
|
@@ -727,26 +744,6 @@ function parseArtifact(data, notebookId) {
|
|
|
727
744
|
_raw: Array.isArray(data) ? data : []
|
|
728
745
|
};
|
|
729
746
|
}
|
|
730
|
-
function parseNote(data) {
|
|
731
|
-
const id = typeof data[0] === "string" ? data[0] : "";
|
|
732
|
-
const content = typeof data[1] === "string" ? data[1] : "";
|
|
733
|
-
const title = typeof data[2] === "string" ? data[2] : null;
|
|
734
|
-
let createdAt = null;
|
|
735
|
-
let updatedAt = null;
|
|
736
|
-
if (Array.isArray(data[3]) && typeof data[3][0] === "number") {
|
|
737
|
-
try {
|
|
738
|
-
createdAt = new Date(data[3][0] * 1e3);
|
|
739
|
-
} catch {
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
if (Array.isArray(data[4]) && typeof data[4][0] === "number") {
|
|
743
|
-
try {
|
|
744
|
-
updatedAt = new Date(data[4][0] * 1e3);
|
|
745
|
-
} catch {
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
return { id, title, content, createdAt, updatedAt };
|
|
749
|
-
}
|
|
750
747
|
|
|
751
748
|
// src/api/artifacts.ts
|
|
752
749
|
function tripleNest(ids) {
|
|
@@ -756,18 +753,13 @@ function doubleNest(ids) {
|
|
|
756
753
|
return ids.map((id) => [id]);
|
|
757
754
|
}
|
|
758
755
|
var ArtifactsAPI = class {
|
|
759
|
-
constructor(rpc, auth) {
|
|
756
|
+
constructor(rpc, auth, notes) {
|
|
760
757
|
this.rpc = rpc;
|
|
761
758
|
this.auth = auth;
|
|
759
|
+
this.notes = notes;
|
|
762
760
|
}
|
|
763
761
|
async list(notebookId) {
|
|
764
|
-
const
|
|
765
|
-
const result = await this.rpc.call(RPCMethod.LIST_ARTIFACTS, params, {
|
|
766
|
-
sourcePath: `/notebook/${notebookId}`,
|
|
767
|
-
allowNull: true
|
|
768
|
-
});
|
|
769
|
-
if (!Array.isArray(result) || !result.length) return [];
|
|
770
|
-
const rawList = Array.isArray(result[0]) ? result[0] : result;
|
|
762
|
+
const rawList = await this._listRaw(notebookId);
|
|
771
763
|
const artifacts = [];
|
|
772
764
|
for (const item of rawList) {
|
|
773
765
|
if (Array.isArray(item)) {
|
|
@@ -779,6 +771,15 @@ var ArtifactsAPI = class {
|
|
|
779
771
|
}
|
|
780
772
|
return artifacts;
|
|
781
773
|
}
|
|
774
|
+
async _listRaw(notebookId) {
|
|
775
|
+
const params = [[2], notebookId, 'NOT artifact.status = "ARTIFACT_STATUS_SUGGESTED"'];
|
|
776
|
+
const result = await this.rpc.call(RPCMethod.LIST_ARTIFACTS, params, {
|
|
777
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
778
|
+
allowNull: true
|
|
779
|
+
});
|
|
780
|
+
if (!Array.isArray(result) || !result.length) return [];
|
|
781
|
+
return Array.isArray(result[0]) ? result[0] : result;
|
|
782
|
+
}
|
|
782
783
|
async get(notebookId, artifactId) {
|
|
783
784
|
const artifacts = await this.list(notebookId);
|
|
784
785
|
return artifacts.find((a) => a.id === artifactId) ?? null;
|
|
@@ -958,6 +959,37 @@ var ArtifactsAPI = class {
|
|
|
958
959
|
];
|
|
959
960
|
return this._callGenerate(notebookId, params);
|
|
960
961
|
}
|
|
962
|
+
async createDataTable(notebookId, opts = {}) {
|
|
963
|
+
const language = opts.language ?? "en";
|
|
964
|
+
const sourceIds = opts.sourceIds ?? await this.rpc.getSourceIds(notebookId);
|
|
965
|
+
const triple = tripleNest(sourceIds);
|
|
966
|
+
const params = [
|
|
967
|
+
[2],
|
|
968
|
+
notebookId,
|
|
969
|
+
[
|
|
970
|
+
null,
|
|
971
|
+
null,
|
|
972
|
+
ArtifactTypeCode.DATA_TABLE,
|
|
973
|
+
triple,
|
|
974
|
+
null,
|
|
975
|
+
null,
|
|
976
|
+
null,
|
|
977
|
+
null,
|
|
978
|
+
null,
|
|
979
|
+
null,
|
|
980
|
+
null,
|
|
981
|
+
null,
|
|
982
|
+
null,
|
|
983
|
+
null,
|
|
984
|
+
null,
|
|
985
|
+
null,
|
|
986
|
+
null,
|
|
987
|
+
null,
|
|
988
|
+
[null, [opts.instructions ?? null, language]]
|
|
989
|
+
]
|
|
990
|
+
];
|
|
991
|
+
return this._callGenerate(notebookId, params);
|
|
992
|
+
}
|
|
961
993
|
async createReport(notebookId, opts = {}) {
|
|
962
994
|
const format = opts.format ?? "briefing_doc";
|
|
963
995
|
const language = opts.language ?? "en";
|
|
@@ -1023,7 +1055,15 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1023
1055
|
sourcePath: `/notebook/${notebookId}`,
|
|
1024
1056
|
allowNull: true
|
|
1025
1057
|
});
|
|
1026
|
-
|
|
1058
|
+
const mindMapJson = Array.isArray(result) && Array.isArray(result[0]) && typeof result[0][0] === "string" ? result[0][0] : null;
|
|
1059
|
+
if (!mindMapJson) throw new Error("Mind map generation returned no content");
|
|
1060
|
+
let title = "Mind Map";
|
|
1061
|
+
try {
|
|
1062
|
+
const parsed = JSON.parse(mindMapJson);
|
|
1063
|
+
if (typeof parsed["name"] === "string") title = parsed["name"];
|
|
1064
|
+
} catch {
|
|
1065
|
+
}
|
|
1066
|
+
return this.notes.create(notebookId, mindMapJson, title);
|
|
1027
1067
|
}
|
|
1028
1068
|
// ---------------------------------------------------------------------------
|
|
1029
1069
|
// Polling / download
|
|
@@ -1079,6 +1119,81 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1079
1119
|
}
|
|
1080
1120
|
return null;
|
|
1081
1121
|
}
|
|
1122
|
+
/** Download a completed slide deck as PDF or PPTX. Returns a Buffer. */
|
|
1123
|
+
async downloadSlideDeck(notebookId, artifactId, format = "pdf") {
|
|
1124
|
+
const rawList = await this._listRaw(notebookId);
|
|
1125
|
+
const raw = rawList.find(
|
|
1126
|
+
(a) => a[0] === artifactId && a[2] === ArtifactTypeCode.SLIDE_DECK
|
|
1127
|
+
);
|
|
1128
|
+
if (!raw) throw new ArtifactNotReadyError("slide_deck", { artifactId });
|
|
1129
|
+
const metadata = raw[16];
|
|
1130
|
+
if (!Array.isArray(metadata)) throw new ArtifactNotReadyError("slide_deck", { artifactId });
|
|
1131
|
+
const url = format === "pptx" ? metadata[4] : metadata[3];
|
|
1132
|
+
if (typeof url !== "string" || !url.startsWith("http")) {
|
|
1133
|
+
throw new ArtifactNotReadyError("slide_deck", { artifactId, status: `no ${format} url` });
|
|
1134
|
+
}
|
|
1135
|
+
return this._fetchMediaWithCookies(url);
|
|
1136
|
+
}
|
|
1137
|
+
/** Download a completed infographic as PNG. Returns a Buffer. */
|
|
1138
|
+
async downloadInfographic(notebookId, artifactId) {
|
|
1139
|
+
const rawList = await this._listRaw(notebookId);
|
|
1140
|
+
const raw = rawList.find(
|
|
1141
|
+
(a) => a[0] === artifactId && a[2] === ArtifactTypeCode.INFOGRAPHIC
|
|
1142
|
+
);
|
|
1143
|
+
if (!raw) throw new ArtifactNotReadyError("infographic", { artifactId });
|
|
1144
|
+
let url = null;
|
|
1145
|
+
for (let i = raw.length - 1; i >= 0; i--) {
|
|
1146
|
+
const item = raw[i];
|
|
1147
|
+
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")) {
|
|
1148
|
+
url = item[2][0][1][0];
|
|
1149
|
+
break;
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
if (!url) throw new ArtifactNotReadyError("infographic", { artifactId });
|
|
1153
|
+
return this._fetchMediaWithCookies(url);
|
|
1154
|
+
}
|
|
1155
|
+
/** Get AI-suggested report formats based on notebook content. */
|
|
1156
|
+
async suggestReports(notebookId) {
|
|
1157
|
+
const params = [[2], notebookId];
|
|
1158
|
+
const result = await this.rpc.call(RPCMethod.GET_SUGGESTED_REPORTS, params, {
|
|
1159
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1160
|
+
allowNull: true,
|
|
1161
|
+
timeoutMs: 12e4
|
|
1162
|
+
});
|
|
1163
|
+
if (!Array.isArray(result) || !result.length) return [];
|
|
1164
|
+
const items = Array.isArray(result[0]) ? result[0] : result;
|
|
1165
|
+
const suggestions = [];
|
|
1166
|
+
for (const item of items) {
|
|
1167
|
+
if (Array.isArray(item) && item.length >= 5) {
|
|
1168
|
+
suggestions.push({
|
|
1169
|
+
title: typeof item[0] === "string" ? item[0] : "",
|
|
1170
|
+
description: typeof item[1] === "string" ? item[1] : "",
|
|
1171
|
+
prompt: typeof item[4] === "string" ? item[4] : "",
|
|
1172
|
+
audienceLevel: typeof item[5] === "number" ? item[5] : 2
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
return suggestions;
|
|
1177
|
+
}
|
|
1178
|
+
/** Revise an individual slide in a completed slide deck using a prompt. */
|
|
1179
|
+
async reviseSlide(notebookId, artifactId, slideIndex, prompt) {
|
|
1180
|
+
if (slideIndex < 0) throw new Error("slideIndex must be >= 0");
|
|
1181
|
+
const params = [[2], artifactId, [[[slideIndex, prompt]]]];
|
|
1182
|
+
const result = await this.rpc.call(RPCMethod.REVISE_SLIDE, params, {
|
|
1183
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1184
|
+
allowNull: true
|
|
1185
|
+
});
|
|
1186
|
+
return this._parseGenerationResult(result);
|
|
1187
|
+
}
|
|
1188
|
+
/** Get parsed headers and rows from a completed data table artifact. */
|
|
1189
|
+
async getDataTableContent(notebookId, artifactId) {
|
|
1190
|
+
const artifacts = await this._listRaw(notebookId);
|
|
1191
|
+
const raw = artifacts.find(
|
|
1192
|
+
(a) => Array.isArray(a) && a[0] === artifactId && a[2] === ArtifactTypeCode.DATA_TABLE
|
|
1193
|
+
);
|
|
1194
|
+
if (!raw || !Array.isArray(raw) || !Array.isArray(raw[18])) return null;
|
|
1195
|
+
return parseDataTable(raw[18]);
|
|
1196
|
+
}
|
|
1082
1197
|
// ---------------------------------------------------------------------------
|
|
1083
1198
|
// Internal
|
|
1084
1199
|
// ---------------------------------------------------------------------------
|
|
@@ -1135,6 +1250,34 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1135
1250
|
return { artifactId: null, status: "failed" };
|
|
1136
1251
|
}
|
|
1137
1252
|
};
|
|
1253
|
+
function extractCellText(cell) {
|
|
1254
|
+
if (typeof cell === "string") return cell;
|
|
1255
|
+
if (typeof cell === "number") return "";
|
|
1256
|
+
if (Array.isArray(cell)) return cell.map(extractCellText).join("");
|
|
1257
|
+
return "";
|
|
1258
|
+
}
|
|
1259
|
+
function parseDataTable(rawData) {
|
|
1260
|
+
try {
|
|
1261
|
+
const nav = rawData;
|
|
1262
|
+
const rowsArray = nav[0][0][0][0][4][2];
|
|
1263
|
+
if (!rowsArray?.length) throw new Error("Empty data table");
|
|
1264
|
+
const headers = [];
|
|
1265
|
+
const rows = [];
|
|
1266
|
+
for (let i = 0; i < rowsArray.length; i++) {
|
|
1267
|
+
const rowSection = rowsArray[i];
|
|
1268
|
+
if (!Array.isArray(rowSection) || rowSection.length < 3) continue;
|
|
1269
|
+
const cellArray = rowSection[2];
|
|
1270
|
+
if (!Array.isArray(cellArray)) continue;
|
|
1271
|
+
const values = cellArray.map(extractCellText);
|
|
1272
|
+
if (i === 0) headers.push(...values);
|
|
1273
|
+
else rows.push(values);
|
|
1274
|
+
}
|
|
1275
|
+
if (!headers.length) throw new Error("No headers found");
|
|
1276
|
+
return { headers, rows };
|
|
1277
|
+
} catch (e) {
|
|
1278
|
+
throw new Error(`Failed to parse data table: ${e}`);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1138
1281
|
function sleep(ms) {
|
|
1139
1282
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1140
1283
|
}
|
|
@@ -1265,6 +1408,19 @@ var ChatAPI = class {
|
|
|
1265
1408
|
}
|
|
1266
1409
|
return null;
|
|
1267
1410
|
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Set the chat mode for a notebook. Persists on the server — affects all
|
|
1413
|
+
* subsequent `ask()` calls until changed.
|
|
1414
|
+
*/
|
|
1415
|
+
async setMode(notebookId, mode) {
|
|
1416
|
+
const [goal, length] = chatModeToParams(mode);
|
|
1417
|
+
const chatSettings = [[goal], [length]];
|
|
1418
|
+
const params = [notebookId, [[null, null, null, null, null, null, null, chatSettings]]];
|
|
1419
|
+
await this.rpc.call(RPCMethod.RENAME_NOTEBOOK, params, {
|
|
1420
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1421
|
+
allowNull: true
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1268
1424
|
clearCache(conversationId) {
|
|
1269
1425
|
if (conversationId) {
|
|
1270
1426
|
this.conversationCache.delete(conversationId);
|
|
@@ -1435,6 +1591,9 @@ var NotebooksAPI = class {
|
|
|
1435
1591
|
}
|
|
1436
1592
|
return "";
|
|
1437
1593
|
}
|
|
1594
|
+
async removeFromRecent(notebookId) {
|
|
1595
|
+
await this.rpc.call(RPCMethod.REMOVE_RECENTLY_VIEWED, [notebookId], { allowNull: true });
|
|
1596
|
+
}
|
|
1438
1597
|
async getDescription(notebookId) {
|
|
1439
1598
|
const params = [notebookId, [2]];
|
|
1440
1599
|
const result = await this.rpc.call(RPCMethod.SUMMARIZE, params, {
|
|
@@ -1471,61 +1630,69 @@ var NotesAPI = class {
|
|
|
1471
1630
|
this.rpc = rpc;
|
|
1472
1631
|
}
|
|
1473
1632
|
async list(notebookId) {
|
|
1474
|
-
const
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
const
|
|
1479
|
-
|
|
1480
|
-
if (!Array.isArray(result)) return { notes, mindMaps };
|
|
1481
|
-
try {
|
|
1482
|
-
const notesData = result[0];
|
|
1483
|
-
if (Array.isArray(notesData)) {
|
|
1484
|
-
for (const n of notesData) {
|
|
1485
|
-
if (Array.isArray(n)) notes.push(parseNote(n));
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
const mapsData = result[1];
|
|
1489
|
-
if (Array.isArray(mapsData)) {
|
|
1490
|
-
for (const m of mapsData) {
|
|
1491
|
-
if (Array.isArray(m)) {
|
|
1492
|
-
mindMaps.push({
|
|
1493
|
-
id: typeof m[0] === "string" ? m[0] : "",
|
|
1494
|
-
title: typeof m[2] === "string" ? m[2] : null,
|
|
1495
|
-
content: typeof m[1] === "string" ? m[1] : "",
|
|
1496
|
-
createdAt: Array.isArray(m[3]) && typeof m[3][0] === "number" ? new Date(m[3][0] * 1e3) : null
|
|
1497
|
-
});
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
} catch {
|
|
1502
|
-
}
|
|
1503
|
-
return { notes, mindMaps };
|
|
1633
|
+
const all = await this._fetchAll(notebookId);
|
|
1634
|
+
return all.filter((n) => !this._isMindMap(n.content));
|
|
1635
|
+
}
|
|
1636
|
+
async listMindMaps(notebookId) {
|
|
1637
|
+
const all = await this._fetchAll(notebookId);
|
|
1638
|
+
return all.filter((n) => this._isMindMap(n.content));
|
|
1504
1639
|
}
|
|
1505
1640
|
async create(notebookId, content, title) {
|
|
1506
|
-
const
|
|
1507
|
-
const result = await this.rpc.call(RPCMethod.CREATE_NOTE,
|
|
1508
|
-
sourcePath: `/notebook/${notebookId}
|
|
1641
|
+
const createParams = [notebookId, "", [1], null, "New Note"];
|
|
1642
|
+
const result = await this.rpc.call(RPCMethod.CREATE_NOTE, createParams, {
|
|
1643
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1644
|
+
allowNull: true
|
|
1509
1645
|
});
|
|
1510
|
-
|
|
1511
|
-
throw new Error("
|
|
1646
|
+
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;
|
|
1647
|
+
if (!noteId) throw new Error("CREATE_NOTE did not return a note ID");
|
|
1648
|
+
await this.update(notebookId, noteId, content, title ?? "New Note");
|
|
1649
|
+
return { id: noteId, title: title ?? null, content, createdAt: null, updatedAt: /* @__PURE__ */ new Date() };
|
|
1512
1650
|
}
|
|
1513
1651
|
async update(notebookId, noteId, content, title) {
|
|
1514
|
-
const params = [notebookId, noteId, content, title ??
|
|
1515
|
-
|
|
1516
|
-
sourcePath: `/notebook/${notebookId}
|
|
1652
|
+
const params = [notebookId, noteId, [[[content, title ?? "New Note", [], 0]]]];
|
|
1653
|
+
await this.rpc.call(RPCMethod.UPDATE_NOTE, params, {
|
|
1654
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1655
|
+
allowNull: true
|
|
1517
1656
|
});
|
|
1518
|
-
if (Array.isArray(result)) return parseNote(result);
|
|
1519
1657
|
return { id: noteId, title: title ?? null, content, createdAt: null, updatedAt: /* @__PURE__ */ new Date() };
|
|
1520
1658
|
}
|
|
1521
1659
|
async delete(notebookId, noteId) {
|
|
1522
|
-
const params = [notebookId,
|
|
1660
|
+
const params = [notebookId, null, [noteId]];
|
|
1523
1661
|
await this.rpc.call(RPCMethod.DELETE_NOTE, params, {
|
|
1524
1662
|
sourcePath: `/notebook/${notebookId}`,
|
|
1525
1663
|
allowNull: true
|
|
1526
1664
|
});
|
|
1527
1665
|
return true;
|
|
1528
1666
|
}
|
|
1667
|
+
async _fetchAll(notebookId) {
|
|
1668
|
+
const result = await this.rpc.call(RPCMethod.GET_NOTES_AND_MIND_MAPS, [notebookId], {
|
|
1669
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
1670
|
+
allowNull: true
|
|
1671
|
+
});
|
|
1672
|
+
if (!Array.isArray(result) || !Array.isArray(result[0])) return [];
|
|
1673
|
+
const notes = [];
|
|
1674
|
+
for (const item of result[0]) {
|
|
1675
|
+
if (!Array.isArray(item) || typeof item[0] !== "string") continue;
|
|
1676
|
+
if (item[1] === null && item[2] === 2) continue;
|
|
1677
|
+
const content = this._extractContent(item);
|
|
1678
|
+
notes.push(this._parseItem(item, notebookId, content));
|
|
1679
|
+
}
|
|
1680
|
+
return notes;
|
|
1681
|
+
}
|
|
1682
|
+
_isMindMap(content) {
|
|
1683
|
+
return content.includes('"children":') || content.includes('"nodes":');
|
|
1684
|
+
}
|
|
1685
|
+
_extractContent(item) {
|
|
1686
|
+
if (typeof item[1] === "string") return item[1];
|
|
1687
|
+
if (Array.isArray(item[1]) && typeof item[1][1] === "string") return item[1][1];
|
|
1688
|
+
return "";
|
|
1689
|
+
}
|
|
1690
|
+
_parseItem(item, _notebookId, content) {
|
|
1691
|
+
const inner = Array.isArray(item[1]) ? item[1] : null;
|
|
1692
|
+
const title = inner && typeof inner[4] === "string" && inner[4] ? inner[4] : null;
|
|
1693
|
+
const createdAt = Array.isArray(item[3]) && typeof item[3][0] === "number" ? new Date(item[3][0] * 1e3) : null;
|
|
1694
|
+
return { id: item[0], title, content, createdAt, updatedAt: null };
|
|
1695
|
+
}
|
|
1529
1696
|
};
|
|
1530
1697
|
|
|
1531
1698
|
// src/api/research.ts
|
|
@@ -1662,7 +1829,7 @@ var ResearchAPI = class {
|
|
|
1662
1829
|
const webSources = sources.filter((s) => s.url && !reportSourceSet.has(s));
|
|
1663
1830
|
if (!webSources.length && !reportSources.length) return [];
|
|
1664
1831
|
const sourceArray = [
|
|
1665
|
-
...reportSources.map((s) => buildReportEntry(s.title, s.reportMarkdown)),
|
|
1832
|
+
...reportSources.filter((s) => s.reportMarkdown).map((s) => buildReportEntry(s.title, s.reportMarkdown)),
|
|
1666
1833
|
...webSources.map((s) => buildWebEntry(s.url, s.title))
|
|
1667
1834
|
];
|
|
1668
1835
|
const params = [null, [1], effectiveTaskId, notebookId, sourceArray];
|
|
@@ -2034,6 +2201,74 @@ var SourcesAPI = class {
|
|
|
2034
2201
|
const uploadResult = await uploadResp.text();
|
|
2035
2202
|
return uploadResult.trim();
|
|
2036
2203
|
}
|
|
2204
|
+
/** Get the AI-generated Source Guide (summary + keywords) for a source. */
|
|
2205
|
+
async getGuide(notebookId, sourceId) {
|
|
2206
|
+
const params = [[[[sourceId]]]];
|
|
2207
|
+
const result = await this.rpc.call(RPCMethod.GET_SOURCE_GUIDE, params, {
|
|
2208
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
2209
|
+
allowNull: true,
|
|
2210
|
+
timeoutMs: 12e4
|
|
2211
|
+
});
|
|
2212
|
+
let summary = "";
|
|
2213
|
+
let keywords = [];
|
|
2214
|
+
if (Array.isArray(result) && result.length > 0) {
|
|
2215
|
+
const outer = result[0];
|
|
2216
|
+
if (Array.isArray(outer) && outer.length > 0) {
|
|
2217
|
+
const inner = outer[0];
|
|
2218
|
+
if (Array.isArray(inner)) {
|
|
2219
|
+
if (inner.length > 1 && Array.isArray(inner[1]) && typeof inner[1][0] === "string") {
|
|
2220
|
+
summary = inner[1][0];
|
|
2221
|
+
}
|
|
2222
|
+
if (inner.length > 2 && Array.isArray(inner[2]) && Array.isArray(inner[2][0])) {
|
|
2223
|
+
keywords = inner[2][0].filter((k) => typeof k === "string");
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
return { summary, keywords };
|
|
2229
|
+
}
|
|
2230
|
+
/** Get the full indexed text content of a source. */
|
|
2231
|
+
async getFulltext(notebookId, sourceId) {
|
|
2232
|
+
const params = [[sourceId], [2], [2]];
|
|
2233
|
+
const result = await this.rpc.call(RPCMethod.GET_SOURCE, params, {
|
|
2234
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
2235
|
+
allowNull: true
|
|
2236
|
+
});
|
|
2237
|
+
if (!Array.isArray(result) || !result.length) {
|
|
2238
|
+
throw new Error(`Source ${sourceId} not found in notebook ${notebookId}`);
|
|
2239
|
+
}
|
|
2240
|
+
let title = "";
|
|
2241
|
+
let url = null;
|
|
2242
|
+
if (Array.isArray(result[0]) && result[0].length > 1) {
|
|
2243
|
+
title = typeof result[0][1] === "string" ? result[0][1] : "";
|
|
2244
|
+
const meta = result[0][2];
|
|
2245
|
+
if (Array.isArray(meta) && meta.length > 7 && Array.isArray(meta[7]) && typeof meta[7][0] === "string") {
|
|
2246
|
+
url = meta[7][0];
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
let content = "";
|
|
2250
|
+
if (Array.isArray(result[3]) && result[3].length > 0) {
|
|
2251
|
+
const texts = extractAllText(result[3][0]);
|
|
2252
|
+
content = texts.join("\n");
|
|
2253
|
+
}
|
|
2254
|
+
return { sourceId, title, content, url, charCount: content.length };
|
|
2255
|
+
}
|
|
2256
|
+
/** Check if a source has newer content available. Returns true if fresh, false if stale. */
|
|
2257
|
+
async checkFreshness(notebookId, sourceId) {
|
|
2258
|
+
const params = [null, [sourceId], [2]];
|
|
2259
|
+
const result = await this.rpc.call(RPCMethod.CHECK_SOURCE_FRESHNESS, params, {
|
|
2260
|
+
sourcePath: `/notebook/${notebookId}`,
|
|
2261
|
+
allowNull: true
|
|
2262
|
+
});
|
|
2263
|
+
if (result === true) return true;
|
|
2264
|
+
if (result === false) return false;
|
|
2265
|
+
if (Array.isArray(result)) {
|
|
2266
|
+
if (result.length === 0) return true;
|
|
2267
|
+
const first = result[0];
|
|
2268
|
+
if (Array.isArray(first) && first.length > 1 && first[1] === true) return true;
|
|
2269
|
+
}
|
|
2270
|
+
return false;
|
|
2271
|
+
}
|
|
2037
2272
|
async delete(notebookId, sourceId) {
|
|
2038
2273
|
const params = [notebookId, [sourceId], [2]];
|
|
2039
2274
|
await this.rpc.call(RPCMethod.DELETE_SOURCE, params, {
|
|
@@ -2088,6 +2323,15 @@ function extractSourceId(result) {
|
|
|
2088
2323
|
console.log("extractSourceId debug info: could not parse:", JSON.stringify(result, null, 2));
|
|
2089
2324
|
throw new Error("Could not extract source ID from API response");
|
|
2090
2325
|
}
|
|
2326
|
+
function extractAllText(data, maxDepth = 100) {
|
|
2327
|
+
if (maxDepth <= 0) return [];
|
|
2328
|
+
const texts = [];
|
|
2329
|
+
for (const item of data) {
|
|
2330
|
+
if (typeof item === "string" && item.length > 0) texts.push(item);
|
|
2331
|
+
else if (Array.isArray(item)) texts.push(...extractAllText(item, maxDepth - 1));
|
|
2332
|
+
}
|
|
2333
|
+
return texts;
|
|
2334
|
+
}
|
|
2091
2335
|
function sleep2(ms) {
|
|
2092
2336
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2093
2337
|
}
|
|
@@ -2392,9 +2636,9 @@ var NotebookLMClient = class _NotebookLMClient {
|
|
|
2392
2636
|
const rpc = new RPCCore(auth, opts.timeoutMs);
|
|
2393
2637
|
this.notebooks = new NotebooksAPI(rpc);
|
|
2394
2638
|
this.sources = new SourcesAPI(rpc, auth);
|
|
2395
|
-
this.artifacts = new ArtifactsAPI(rpc, auth);
|
|
2396
|
-
this.chat = new ChatAPI(rpc, auth);
|
|
2397
2639
|
this.notes = new NotesAPI(rpc);
|
|
2640
|
+
this.artifacts = new ArtifactsAPI(rpc, auth, this.notes);
|
|
2641
|
+
this.chat = new ChatAPI(rpc, auth);
|
|
2398
2642
|
this.research = new ResearchAPI(rpc);
|
|
2399
2643
|
this.settings = new SettingsAPI(rpc);
|
|
2400
2644
|
this.sharing = new SharingAPI(rpc);
|
|
@@ -2430,6 +2674,6 @@ var NotebookLMClient = class _NotebookLMClient {
|
|
|
2430
2674
|
init_enums();
|
|
2431
2675
|
init_errors();
|
|
2432
2676
|
|
|
2433
|
-
export { ArtifactDownloadError, ArtifactError, ArtifactNotFoundError, ArtifactNotReadyError, ArtifactParseError, ArtifactTypeCode, ArtifactsAPI, AudioFormat, AudioLength, AuthError, ChatAPI, ChatError, ClientError, ExportType, InfographicDetail, InfographicOrientation, InfographicStyle, NetworkError, NotebookError, NotebookLMClient, NotebookLMError, NotebookNotFoundError, NotebooksAPI, NotesAPI, QuizDifficulty, QuizQuantity, RPCError, RPCMethod, RPCTimeoutError, RateLimitError, ResearchAPI, ServerError, SettingsAPI, ShareAccess, SharePermission, ShareViewLevel, SharingAPI, SlideDeckFormat, SlideDeckLength, SourceAddError, SourceError, SourceNotFoundError, SourceProcessingError, SourceTimeoutError, SourcesAPI, VideoFormat, VideoStyle, connect };
|
|
2677
|
+
export { ArtifactDownloadError, ArtifactError, ArtifactNotFoundError, ArtifactNotReadyError, ArtifactParseError, ArtifactTypeCode, ArtifactsAPI, AudioFormat, AudioLength, AuthError, ChatAPI, ChatError, ChatMode, ClientError, ExportType, InfographicDetail, InfographicOrientation, InfographicStyle, NetworkError, NotebookError, NotebookLMClient, NotebookLMError, NotebookNotFoundError, NotebooksAPI, NotesAPI, QuizDifficulty, QuizQuantity, RPCError, RPCMethod, RPCTimeoutError, RateLimitError, ResearchAPI, ServerError, SettingsAPI, ShareAccess, SharePermission, ShareViewLevel, SharingAPI, SlideDeckFormat, SlideDeckLength, SourceAddError, SourceError, SourceNotFoundError, SourceProcessingError, SourceTimeoutError, SourcesAPI, VideoFormat, VideoStyle, connect };
|
|
2434
2678
|
//# sourceMappingURL=index.js.map
|
|
2435
2679
|
//# sourceMappingURL=index.js.map
|