notebooklm-sdk 0.1.8 → 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.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 +176 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -20
- package/dist/index.d.ts +34 -20
- package/dist/index.js +176 -79
- package/dist/index.js.map +1 -1
- package/package.json +11 -3
package/dist/index.d.cts
CHANGED
|
@@ -280,11 +280,19 @@ interface Note {
|
|
|
280
280
|
createdAt: Date | null;
|
|
281
281
|
updatedAt: Date | null;
|
|
282
282
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
283
|
+
|
|
284
|
+
declare class NotesAPI {
|
|
285
|
+
private readonly rpc;
|
|
286
|
+
constructor(rpc: RPCCore);
|
|
287
|
+
list(notebookId: string): Promise<Note[]>;
|
|
288
|
+
listMindMaps(notebookId: string): Promise<Note[]>;
|
|
289
|
+
create(notebookId: string, content: string, title?: string): Promise<Note>;
|
|
290
|
+
update(notebookId: string, noteId: string, content: string, title?: string): Promise<Note>;
|
|
291
|
+
delete(notebookId: string, noteId: string): Promise<boolean>;
|
|
292
|
+
private _fetchAll;
|
|
293
|
+
private _isMindMap;
|
|
294
|
+
private _extractContent;
|
|
295
|
+
private _parseItem;
|
|
288
296
|
}
|
|
289
297
|
|
|
290
298
|
interface CreateAudioOptions {
|
|
@@ -322,6 +330,15 @@ interface CreateSlideDeckOptions {
|
|
|
322
330
|
instructions?: string;
|
|
323
331
|
language?: string;
|
|
324
332
|
}
|
|
333
|
+
interface CreateDataTableOptions {
|
|
334
|
+
sourceIds?: string[];
|
|
335
|
+
instructions?: string;
|
|
336
|
+
language?: string;
|
|
337
|
+
}
|
|
338
|
+
interface DataTableContent {
|
|
339
|
+
headers: string[];
|
|
340
|
+
rows: string[][];
|
|
341
|
+
}
|
|
325
342
|
type ReportFormat = "briefing_doc" | "study_guide" | "blog_post" | "custom";
|
|
326
343
|
interface CreateReportOptions {
|
|
327
344
|
format?: ReportFormat;
|
|
@@ -333,8 +350,10 @@ interface CreateReportOptions {
|
|
|
333
350
|
declare class ArtifactsAPI {
|
|
334
351
|
private readonly rpc;
|
|
335
352
|
private readonly auth;
|
|
336
|
-
|
|
353
|
+
private readonly notes;
|
|
354
|
+
constructor(rpc: RPCCore, auth: AuthTokens, notes: NotesAPI);
|
|
337
355
|
list(notebookId: string): Promise<Artifact[]>;
|
|
356
|
+
private _listRaw;
|
|
338
357
|
get(notebookId: string, artifactId: string): Promise<Artifact | null>;
|
|
339
358
|
delete(notebookId: string, artifactId: string): Promise<boolean>;
|
|
340
359
|
rename(notebookId: string, artifactId: string, newTitle: string): Promise<boolean>;
|
|
@@ -344,8 +363,9 @@ declare class ArtifactsAPI {
|
|
|
344
363
|
createFlashcards(notebookId: string, opts?: CreateQuizOptions): Promise<GenerationStatus>;
|
|
345
364
|
createInfographic(notebookId: string, opts?: CreateInfographicOptions): Promise<GenerationStatus>;
|
|
346
365
|
createSlideDeck(notebookId: string, opts?: CreateSlideDeckOptions): Promise<GenerationStatus>;
|
|
366
|
+
createDataTable(notebookId: string, opts?: CreateDataTableOptions): Promise<GenerationStatus>;
|
|
347
367
|
createReport(notebookId: string, opts?: CreateReportOptions): Promise<GenerationStatus>;
|
|
348
|
-
createMindMap(notebookId: string, sourceIds?: string[]): Promise<
|
|
368
|
+
createMindMap(notebookId: string, sourceIds?: string[]): Promise<Note>;
|
|
349
369
|
/** Poll until artifact reaches completed/failed status. */
|
|
350
370
|
waitUntilReady(notebookId: string, artifactId: string, timeout?: number, pollInterval?: number): Promise<Artifact>;
|
|
351
371
|
/** Download audio content as a Buffer. */
|
|
@@ -356,6 +376,12 @@ declare class ArtifactsAPI {
|
|
|
356
376
|
getReportMarkdown(notebookId: string, artifactId: string): Promise<string | null>;
|
|
357
377
|
/** Get interactive HTML for quiz/flashcard artifacts. */
|
|
358
378
|
getInteractiveHtml(notebookId: string, artifactId: string): Promise<string | null>;
|
|
379
|
+
/** Download a completed slide deck as PDF or PPTX. Returns a Buffer. */
|
|
380
|
+
downloadSlideDeck(notebookId: string, artifactId: string, format?: "pdf" | "pptx"): Promise<Buffer>;
|
|
381
|
+
/** Download a completed infographic as PNG. Returns a Buffer. */
|
|
382
|
+
downloadInfographic(notebookId: string, artifactId: string): Promise<Buffer>;
|
|
383
|
+
/** Get parsed headers and rows from a completed data table artifact. */
|
|
384
|
+
getDataTableContent(notebookId: string, artifactId: string): Promise<DataTableContent | null>;
|
|
359
385
|
/**
|
|
360
386
|
* Fetch a Google-hosted media URL, manually following redirects to ensure
|
|
361
387
|
* cookies are included on every hop. Node/Bun fetch strips the Cookie header
|
|
@@ -395,18 +421,6 @@ declare class NotebooksAPI {
|
|
|
395
421
|
getDescription(notebookId: string): Promise<NotebookDescription>;
|
|
396
422
|
}
|
|
397
423
|
|
|
398
|
-
declare class NotesAPI {
|
|
399
|
-
private readonly rpc;
|
|
400
|
-
constructor(rpc: RPCCore);
|
|
401
|
-
list(notebookId: string): Promise<{
|
|
402
|
-
notes: Note[];
|
|
403
|
-
mindMaps: MindMap[];
|
|
404
|
-
}>;
|
|
405
|
-
create(notebookId: string, content: string, title?: string): Promise<Note>;
|
|
406
|
-
update(notebookId: string, noteId: string, content: string, title?: string): Promise<Note>;
|
|
407
|
-
delete(notebookId: string, noteId: string): Promise<boolean>;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
424
|
interface ResearchTask {
|
|
411
425
|
taskId: string;
|
|
412
426
|
reportId: string | null;
|
|
@@ -553,4 +567,4 @@ declare class NotebookLMClient {
|
|
|
553
567
|
refreshTokens(): Promise<void>;
|
|
554
568
|
}
|
|
555
569
|
|
|
556
|
-
export { type AddSourceOptions, type Artifact, type ArtifactStatus, type ArtifactType, ArtifactTypeCode, ArtifactsAPI, type AskOptions, type AskResult, AudioFormat, type AudioFormatValue, AudioLength, type AudioLengthValue, AuthTokens, ChatAPI, type ChatReference, type ClientOptions, ConnectOptions, type ConversationTurn, type CreateAudioOptions, type CreateInfographicOptions, type CreateQuizOptions, type CreateReportOptions, type CreateSlideDeckOptions, type CreateVideoOptions, ExportType, type ExportTypeValue, type GenerationStatus, type ImportedSource, InfographicDetail, type InfographicDetailValue, InfographicOrientation, type InfographicOrientationValue, InfographicStyle, type InfographicStyleValue, type
|
|
570
|
+
export { type AddSourceOptions, type Artifact, type ArtifactStatus, type ArtifactType, ArtifactTypeCode, ArtifactsAPI, type AskOptions, type AskResult, AudioFormat, type AudioFormatValue, AudioLength, type AudioLengthValue, AuthTokens, ChatAPI, type ChatReference, type ClientOptions, ConnectOptions, type ConversationTurn, type CreateAudioOptions, type CreateDataTableOptions, type CreateInfographicOptions, type CreateQuizOptions, type CreateReportOptions, type CreateSlideDeckOptions, type CreateVideoOptions, type DataTableContent, ExportType, type ExportTypeValue, type GenerationStatus, type ImportedSource, InfographicDetail, type InfographicDetailValue, InfographicOrientation, type InfographicOrientationValue, InfographicStyle, type InfographicStyleValue, type Note, type Notebook, type NotebookDescription, NotebookLMClient, type NotebookMetadata, NotebooksAPI, NotesAPI, QuizDifficulty, type QuizDifficultyValue, QuizQuantity, type QuizQuantityValue, RPCMethod, type RPCMethodId, ResearchAPI, type ResearchResult, type ResearchSource, type ResearchTask, SettingsAPI, ShareAccess, type ShareAccessValue, SharePermission, type SharePermissionValue, type ShareStatus, ShareViewLevel, type ShareViewLevelValue, type SharedUser, SharingAPI, SlideDeckFormat, type SlideDeckFormatValue, SlideDeckLength, type SlideDeckLengthValue, type Source, type SourceStatus, type SourceSummary, type SourceType, SourcesAPI, type SuggestedTopic, VideoFormat, type VideoFormatValue, VideoStyle, type VideoStyleValue };
|
package/dist/index.d.ts
CHANGED
|
@@ -280,11 +280,19 @@ interface Note {
|
|
|
280
280
|
createdAt: Date | null;
|
|
281
281
|
updatedAt: Date | null;
|
|
282
282
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
283
|
+
|
|
284
|
+
declare class NotesAPI {
|
|
285
|
+
private readonly rpc;
|
|
286
|
+
constructor(rpc: RPCCore);
|
|
287
|
+
list(notebookId: string): Promise<Note[]>;
|
|
288
|
+
listMindMaps(notebookId: string): Promise<Note[]>;
|
|
289
|
+
create(notebookId: string, content: string, title?: string): Promise<Note>;
|
|
290
|
+
update(notebookId: string, noteId: string, content: string, title?: string): Promise<Note>;
|
|
291
|
+
delete(notebookId: string, noteId: string): Promise<boolean>;
|
|
292
|
+
private _fetchAll;
|
|
293
|
+
private _isMindMap;
|
|
294
|
+
private _extractContent;
|
|
295
|
+
private _parseItem;
|
|
288
296
|
}
|
|
289
297
|
|
|
290
298
|
interface CreateAudioOptions {
|
|
@@ -322,6 +330,15 @@ interface CreateSlideDeckOptions {
|
|
|
322
330
|
instructions?: string;
|
|
323
331
|
language?: string;
|
|
324
332
|
}
|
|
333
|
+
interface CreateDataTableOptions {
|
|
334
|
+
sourceIds?: string[];
|
|
335
|
+
instructions?: string;
|
|
336
|
+
language?: string;
|
|
337
|
+
}
|
|
338
|
+
interface DataTableContent {
|
|
339
|
+
headers: string[];
|
|
340
|
+
rows: string[][];
|
|
341
|
+
}
|
|
325
342
|
type ReportFormat = "briefing_doc" | "study_guide" | "blog_post" | "custom";
|
|
326
343
|
interface CreateReportOptions {
|
|
327
344
|
format?: ReportFormat;
|
|
@@ -333,8 +350,10 @@ interface CreateReportOptions {
|
|
|
333
350
|
declare class ArtifactsAPI {
|
|
334
351
|
private readonly rpc;
|
|
335
352
|
private readonly auth;
|
|
336
|
-
|
|
353
|
+
private readonly notes;
|
|
354
|
+
constructor(rpc: RPCCore, auth: AuthTokens, notes: NotesAPI);
|
|
337
355
|
list(notebookId: string): Promise<Artifact[]>;
|
|
356
|
+
private _listRaw;
|
|
338
357
|
get(notebookId: string, artifactId: string): Promise<Artifact | null>;
|
|
339
358
|
delete(notebookId: string, artifactId: string): Promise<boolean>;
|
|
340
359
|
rename(notebookId: string, artifactId: string, newTitle: string): Promise<boolean>;
|
|
@@ -344,8 +363,9 @@ declare class ArtifactsAPI {
|
|
|
344
363
|
createFlashcards(notebookId: string, opts?: CreateQuizOptions): Promise<GenerationStatus>;
|
|
345
364
|
createInfographic(notebookId: string, opts?: CreateInfographicOptions): Promise<GenerationStatus>;
|
|
346
365
|
createSlideDeck(notebookId: string, opts?: CreateSlideDeckOptions): Promise<GenerationStatus>;
|
|
366
|
+
createDataTable(notebookId: string, opts?: CreateDataTableOptions): Promise<GenerationStatus>;
|
|
347
367
|
createReport(notebookId: string, opts?: CreateReportOptions): Promise<GenerationStatus>;
|
|
348
|
-
createMindMap(notebookId: string, sourceIds?: string[]): Promise<
|
|
368
|
+
createMindMap(notebookId: string, sourceIds?: string[]): Promise<Note>;
|
|
349
369
|
/** Poll until artifact reaches completed/failed status. */
|
|
350
370
|
waitUntilReady(notebookId: string, artifactId: string, timeout?: number, pollInterval?: number): Promise<Artifact>;
|
|
351
371
|
/** Download audio content as a Buffer. */
|
|
@@ -356,6 +376,12 @@ declare class ArtifactsAPI {
|
|
|
356
376
|
getReportMarkdown(notebookId: string, artifactId: string): Promise<string | null>;
|
|
357
377
|
/** Get interactive HTML for quiz/flashcard artifacts. */
|
|
358
378
|
getInteractiveHtml(notebookId: string, artifactId: string): Promise<string | null>;
|
|
379
|
+
/** Download a completed slide deck as PDF or PPTX. Returns a Buffer. */
|
|
380
|
+
downloadSlideDeck(notebookId: string, artifactId: string, format?: "pdf" | "pptx"): Promise<Buffer>;
|
|
381
|
+
/** Download a completed infographic as PNG. Returns a Buffer. */
|
|
382
|
+
downloadInfographic(notebookId: string, artifactId: string): Promise<Buffer>;
|
|
383
|
+
/** Get parsed headers and rows from a completed data table artifact. */
|
|
384
|
+
getDataTableContent(notebookId: string, artifactId: string): Promise<DataTableContent | null>;
|
|
359
385
|
/**
|
|
360
386
|
* Fetch a Google-hosted media URL, manually following redirects to ensure
|
|
361
387
|
* cookies are included on every hop. Node/Bun fetch strips the Cookie header
|
|
@@ -395,18 +421,6 @@ declare class NotebooksAPI {
|
|
|
395
421
|
getDescription(notebookId: string): Promise<NotebookDescription>;
|
|
396
422
|
}
|
|
397
423
|
|
|
398
|
-
declare class NotesAPI {
|
|
399
|
-
private readonly rpc;
|
|
400
|
-
constructor(rpc: RPCCore);
|
|
401
|
-
list(notebookId: string): Promise<{
|
|
402
|
-
notes: Note[];
|
|
403
|
-
mindMaps: MindMap[];
|
|
404
|
-
}>;
|
|
405
|
-
create(notebookId: string, content: string, title?: string): Promise<Note>;
|
|
406
|
-
update(notebookId: string, noteId: string, content: string, title?: string): Promise<Note>;
|
|
407
|
-
delete(notebookId: string, noteId: string): Promise<boolean>;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
424
|
interface ResearchTask {
|
|
411
425
|
taskId: string;
|
|
412
426
|
reportId: string | null;
|
|
@@ -553,4 +567,4 @@ declare class NotebookLMClient {
|
|
|
553
567
|
refreshTokens(): Promise<void>;
|
|
554
568
|
}
|
|
555
569
|
|
|
556
|
-
export { type AddSourceOptions, type Artifact, type ArtifactStatus, type ArtifactType, ArtifactTypeCode, ArtifactsAPI, type AskOptions, type AskResult, AudioFormat, type AudioFormatValue, AudioLength, type AudioLengthValue, AuthTokens, ChatAPI, type ChatReference, type ClientOptions, ConnectOptions, type ConversationTurn, type CreateAudioOptions, type CreateInfographicOptions, type CreateQuizOptions, type CreateReportOptions, type CreateSlideDeckOptions, type CreateVideoOptions, ExportType, type ExportTypeValue, type GenerationStatus, type ImportedSource, InfographicDetail, type InfographicDetailValue, InfographicOrientation, type InfographicOrientationValue, InfographicStyle, type InfographicStyleValue, type
|
|
570
|
+
export { type AddSourceOptions, type Artifact, type ArtifactStatus, type ArtifactType, ArtifactTypeCode, ArtifactsAPI, type AskOptions, type AskResult, AudioFormat, type AudioFormatValue, AudioLength, type AudioLengthValue, AuthTokens, ChatAPI, type ChatReference, type ClientOptions, ConnectOptions, type ConversationTurn, type CreateAudioOptions, type CreateDataTableOptions, type CreateInfographicOptions, type CreateQuizOptions, type CreateReportOptions, type CreateSlideDeckOptions, type CreateVideoOptions, type DataTableContent, ExportType, type ExportTypeValue, type GenerationStatus, type ImportedSource, InfographicDetail, type InfographicDetailValue, InfographicOrientation, type InfographicOrientationValue, InfographicStyle, type InfographicStyleValue, type Note, type Notebook, type NotebookDescription, NotebookLMClient, type NotebookMetadata, NotebooksAPI, NotesAPI, QuizDifficulty, type QuizDifficultyValue, QuizQuantity, type QuizQuantityValue, RPCMethod, type RPCMethodId, ResearchAPI, type ResearchResult, type ResearchSource, type ResearchTask, SettingsAPI, ShareAccess, type ShareAccessValue, SharePermission, type SharePermissionValue, type ShareStatus, ShareViewLevel, type ShareViewLevelValue, type SharedUser, SharingAPI, SlideDeckFormat, type SlideDeckFormatValue, SlideDeckLength, type SlideDeckLengthValue, type Source, type SourceStatus, type SourceSummary, type SourceType, SourcesAPI, type SuggestedTopic, VideoFormat, type VideoFormatValue, VideoStyle, type VideoStyleValue };
|
package/dist/index.js
CHANGED
|
@@ -453,10 +453,8 @@ function loadCookiesFromFile(filePath) {
|
|
|
453
453
|
try {
|
|
454
454
|
raw = readFileSync(filePath, "utf-8");
|
|
455
455
|
} catch {
|
|
456
|
-
throw new AuthError(
|
|
457
|
-
|
|
458
|
-
Run: npx notebooklm-sdk login`
|
|
459
|
-
);
|
|
456
|
+
throw new AuthError(`Session file not found: ${filePath}
|
|
457
|
+
Run: npx notebooklm-sdk login`);
|
|
460
458
|
}
|
|
461
459
|
return extractCookiesFromStorageState(JSON.parse(raw));
|
|
462
460
|
}
|
|
@@ -590,9 +588,7 @@ async function connect(opts = {}) {
|
|
|
590
588
|
} else if (envCookies) {
|
|
591
589
|
cookieMap = loadCookiesFromString(envCookies);
|
|
592
590
|
} else {
|
|
593
|
-
throw new AuthError(
|
|
594
|
-
"No session found. Run: npx notebooklm-sdk login"
|
|
595
|
-
);
|
|
591
|
+
throw new AuthError("No session found. Run: npx notebooklm-sdk login");
|
|
596
592
|
}
|
|
597
593
|
}
|
|
598
594
|
const { csrfToken, sessionId } = await fetchTokens(cookieMap);
|
|
@@ -727,26 +723,6 @@ function parseArtifact(data, notebookId) {
|
|
|
727
723
|
_raw: Array.isArray(data) ? data : []
|
|
728
724
|
};
|
|
729
725
|
}
|
|
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
726
|
|
|
751
727
|
// src/api/artifacts.ts
|
|
752
728
|
function tripleNest(ids) {
|
|
@@ -756,18 +732,13 @@ function doubleNest(ids) {
|
|
|
756
732
|
return ids.map((id) => [id]);
|
|
757
733
|
}
|
|
758
734
|
var ArtifactsAPI = class {
|
|
759
|
-
constructor(rpc, auth) {
|
|
735
|
+
constructor(rpc, auth, notes) {
|
|
760
736
|
this.rpc = rpc;
|
|
761
737
|
this.auth = auth;
|
|
738
|
+
this.notes = notes;
|
|
762
739
|
}
|
|
763
740
|
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;
|
|
741
|
+
const rawList = await this._listRaw(notebookId);
|
|
771
742
|
const artifacts = [];
|
|
772
743
|
for (const item of rawList) {
|
|
773
744
|
if (Array.isArray(item)) {
|
|
@@ -779,6 +750,15 @@ var ArtifactsAPI = class {
|
|
|
779
750
|
}
|
|
780
751
|
return artifacts;
|
|
781
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
|
+
}
|
|
782
762
|
async get(notebookId, artifactId) {
|
|
783
763
|
const artifacts = await this.list(notebookId);
|
|
784
764
|
return artifacts.find((a) => a.id === artifactId) ?? null;
|
|
@@ -958,6 +938,37 @@ var ArtifactsAPI = class {
|
|
|
958
938
|
];
|
|
959
939
|
return this._callGenerate(notebookId, params);
|
|
960
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
|
+
}
|
|
961
972
|
async createReport(notebookId, opts = {}) {
|
|
962
973
|
const format = opts.format ?? "briefing_doc";
|
|
963
974
|
const language = opts.language ?? "en";
|
|
@@ -1023,7 +1034,15 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1023
1034
|
sourcePath: `/notebook/${notebookId}`,
|
|
1024
1035
|
allowNull: true
|
|
1025
1036
|
});
|
|
1026
|
-
|
|
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);
|
|
1027
1046
|
}
|
|
1028
1047
|
// ---------------------------------------------------------------------------
|
|
1029
1048
|
// Polling / download
|
|
@@ -1079,6 +1098,48 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1079
1098
|
}
|
|
1080
1099
|
return null;
|
|
1081
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
|
+
}
|
|
1082
1143
|
// ---------------------------------------------------------------------------
|
|
1083
1144
|
// Internal
|
|
1084
1145
|
// ---------------------------------------------------------------------------
|
|
@@ -1135,6 +1196,34 @@ ${opts.extraInstructions}` : cfg.prompt;
|
|
|
1135
1196
|
return { artifactId: null, status: "failed" };
|
|
1136
1197
|
}
|
|
1137
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
|
+
}
|
|
1138
1227
|
function sleep(ms) {
|
|
1139
1228
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1140
1229
|
}
|
|
@@ -1471,61 +1560,69 @@ var NotesAPI = class {
|
|
|
1471
1560
|
this.rpc = rpc;
|
|
1472
1561
|
}
|
|
1473
1562
|
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 };
|
|
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));
|
|
1504
1569
|
}
|
|
1505
1570
|
async create(notebookId, content, title) {
|
|
1506
|
-
const
|
|
1507
|
-
const result = await this.rpc.call(RPCMethod.CREATE_NOTE,
|
|
1508
|
-
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
|
|
1509
1575
|
});
|
|
1510
|
-
|
|
1511
|
-
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() };
|
|
1512
1580
|
}
|
|
1513
1581
|
async update(notebookId, noteId, content, title) {
|
|
1514
|
-
const params = [notebookId, noteId, content, title ??
|
|
1515
|
-
|
|
1516
|
-
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
|
|
1517
1586
|
});
|
|
1518
|
-
if (Array.isArray(result)) return parseNote(result);
|
|
1519
1587
|
return { id: noteId, title: title ?? null, content, createdAt: null, updatedAt: /* @__PURE__ */ new Date() };
|
|
1520
1588
|
}
|
|
1521
1589
|
async delete(notebookId, noteId) {
|
|
1522
|
-
const params = [notebookId,
|
|
1590
|
+
const params = [notebookId, null, [noteId]];
|
|
1523
1591
|
await this.rpc.call(RPCMethod.DELETE_NOTE, params, {
|
|
1524
1592
|
sourcePath: `/notebook/${notebookId}`,
|
|
1525
1593
|
allowNull: true
|
|
1526
1594
|
});
|
|
1527
1595
|
return true;
|
|
1528
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
|
+
}
|
|
1529
1626
|
};
|
|
1530
1627
|
|
|
1531
1628
|
// src/api/research.ts
|
|
@@ -1662,7 +1759,7 @@ var ResearchAPI = class {
|
|
|
1662
1759
|
const webSources = sources.filter((s) => s.url && !reportSourceSet.has(s));
|
|
1663
1760
|
if (!webSources.length && !reportSources.length) return [];
|
|
1664
1761
|
const sourceArray = [
|
|
1665
|
-
...reportSources.map((s) => buildReportEntry(s.title, s.reportMarkdown)),
|
|
1762
|
+
...reportSources.filter((s) => s.reportMarkdown).map((s) => buildReportEntry(s.title, s.reportMarkdown)),
|
|
1666
1763
|
...webSources.map((s) => buildWebEntry(s.url, s.title))
|
|
1667
1764
|
];
|
|
1668
1765
|
const params = [null, [1], effectiveTaskId, notebookId, sourceArray];
|
|
@@ -2392,9 +2489,9 @@ var NotebookLMClient = class _NotebookLMClient {
|
|
|
2392
2489
|
const rpc = new RPCCore(auth, opts.timeoutMs);
|
|
2393
2490
|
this.notebooks = new NotebooksAPI(rpc);
|
|
2394
2491
|
this.sources = new SourcesAPI(rpc, auth);
|
|
2395
|
-
this.artifacts = new ArtifactsAPI(rpc, auth);
|
|
2396
|
-
this.chat = new ChatAPI(rpc, auth);
|
|
2397
2492
|
this.notes = new NotesAPI(rpc);
|
|
2493
|
+
this.artifacts = new ArtifactsAPI(rpc, auth, this.notes);
|
|
2494
|
+
this.chat = new ChatAPI(rpc, auth);
|
|
2398
2495
|
this.research = new ResearchAPI(rpc);
|
|
2399
2496
|
this.settings = new SettingsAPI(rpc);
|
|
2400
2497
|
this.sharing = new SharingAPI(rpc);
|