# https://github.com/teng-lin/notebooklm-py 项目说明书

生成时间：2026-05-31 20:50:41 UTC

## 目录

- [项目介绍](#page-project-intro)
- [快速开始](#page-quickstart)
- [客户端架构](#page-client-architecture)
- [RPC 协议层](#page-rpc-protocol)
- [中间件链](#page-middleware-chain)
- [笔记本 API](#page-notebooks-api)
- [源与制品 API](#page-sources-artifacts)
- [内容生成](#page-content-generation)
- [认证与 Cookie 生命周期](#page-auth-cookie-lifecycle)
- [多账户与配置文件](#page-multi-profile)

<a id='page-project-intro'></a>

## 项目介绍

### 相关页面

相关主题：[快速开始](#page-quickstart), [客户端架构](#page-client-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)
- [src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)
- [src/notebooklm/_kernel.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_kernel.py)
- [CLAUDE.md](https://github.com/teng-lin/notebooklm-py/blob/main/CLAUDE.md)
- [AGENTS.md](https://github.com/teng-lin/notebooklm-py/blob/main/AGENTS.md)
- [src/notebooklm/_artifact_payloads.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_payloads.py)
- [src/notebooklm/_types/notebooks.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_types/notebooks.py)
</details>

# 项目介绍

## 项目概述

notebooklm-py 是一个非官方的 Python 客户端库，用于与 Google NotebookLM 服务进行交互。该项目提供了完整的 API 和 CLI 接口，使开发者能够程序化地访问 NotebookLM 的各项功能。

> **⚠️ 重要声明**：此库使用未公开的 Google API，这些 API 可能随时变更而无需通知。项目与 Google 没有任何关联，最适合用于原型设计、研究和个人项目。

资料来源：[README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

## 核心定位

该项目的目标用户群体包括：

| 用户类型 | 使用场景 |
|---------|---------|
| **AI Agent 工具** | 将 NotebookLM 集成到 Claude Code、Codex 等 LLM 代理中 |
| **研究自动化** | 批量导入源文件（URL、PDF、YouTube、Google Drive）并进行自动化研究 |
| **最终用户** | 通过 CLI 直接与 NotebookLM 交互 |
| **库使用者** | 将库作为 Python 依赖引入自己的项目 |

资料来源：[README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

## 项目架构

### 整体架构图

```mermaid
graph TD
    subgraph "用户层"
        CLI[CLI 命令行工具]
        LIB[Python 库/客户端]
    end
    
    subgraph "核心模块"
        CLIENT[NotebookLMClient]
        KERNEL[_kernel 核心引擎]
    end
    
    subgraph "功能模块"
        NB[notebooks API]
        SRC[sources API]
        ART[artifacts API]
        CHT[chat API]
        RES[research API]
        NTS[notes API]
        SET[settings API]
        SHR[sharing API]
    end
    
    subgraph "基础设施"
        RPC[RPC 协议编解码]
        AUTH[认证模块]
        MID[中间件链]
        TRN[传输层]
    end
    
    CLI --> CLIENT
    LIB --> CLIENT
    CLIENT --> KERNEL
    KERNEL --> NB
    KERNEL --> SRC
    KERNEL --> ART
    KERNEL --> CHT
    KERNEL --> RES
    KERNEL --> NTS
    KERNEL --> SET
    KERNEL --> SHR
    KERNEL --> RPC
    KERNEL --> AUTH
    KERNEL --> MID
    MID --> TRN
```

### 目录结构

```
src/notebooklm/
├── __init__.py           # 公共 API 导出
├── client.py             # NotebookLMClient 主客户端类
├── _kernel.py            # 核心引擎实现
├── _types/               # 类型定义
│   └── notebooks.py      # Notebook 相关类型
├── cli/                  # CLI 命令模块
│   ├── _download_specs.py # 下载规格定义
│   └── services/         # CLI 服务层
├── rpc/                  # RPC 协议处理
│   └── types.py          # RPC 方法 ID
└── auth.py               # 认证模块
```

资料来源：[CLAUDE.md](https://github.com/teng-lin/notebooklm-py/blob/main/CLAUDE.md)

## 核心客户端

### NotebookLMClient 类

`NotebookLMClient` 是项目的主入口点，提供异步上下文管理器支持：

```python
# 方式一：从存储的认证信息创建（推荐）
async with NotebookLMClient.from_storage() as client:
    notebooks = await client.notebooks.list()

# 方式二：从 AuthTokens 直接创建
auth = AuthTokens(cookies, csrf_token, session_id)
async with NotebookLMClient(auth) as client:
    notebooks = await client.notebooks.list()
```

资料来源：[src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)

### 构造函数参数

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `auth` | `AuthTokens` | 必填 | 认证令牌 |
| `timeout` | `float` | `DEFAULT_TIMEOUT` | 请求超时时间 |
| `storage_path` | `Path \| None` | `None` | 存储路径 |
| `keepalive` | `float \| None` | `None` | 保活间隔 |
| `keepalive_min_interval` | `float` | `DEFAULT_KEEPALIVE_MIN_INTERVAL` | 最小保活间隔 |
| `rate_limit_max_retries` | `int` | `3` | 速率限制最大重试次数 |
| `server_error_max_retries` | `int` | - | 服务器错误最大重试次数 |

资料来源：[src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)

## 功能模块

### API 模块总览

| 模块 | 功能 | 主要方法 |
|------|------|---------|
| **notebooks** | 笔记本管理 | 创建、列出、删除、重命名 |
| **sources** | 源文件管理 | 添加 URL、文本、文件、YouTube、Drive |
| **artifacts** | AI 内容生成 | 音频、视频、幻灯片、报告等 |
| **chat** | 对话功能 | 提问、管理对话历史 |
| **research** | 研究代理 | Web/Drive 研究（快速/深度模式） |
| **notes** | 笔记管理 | 创建和管理用户笔记 |
| **settings** | 设置管理 | 用户偏好设置 |
| **sharing** | 分享管理 | 链接权限管理 |

资料来源：[src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)

### 内容生成能力

```mermaid
graph LR
    A[源文件] --> B[Artifact 生成]
    B --> C1[音频概览]
    B --> C2[视频概览]
    B --> C3[幻灯片]
    B --> C4[信息图]
    B --> C5[测验]
    B --> C6[闪卡]
    B --> C7[报告]
    B --> C8[数据表]
    B --> C9[思维导图]
```

#### 支持的生成类型

| 类型 | 选项 | 下载格式 |
|------|------|---------|
| **音频概览** | 4 种格式（深度、简短、评论、辩论）、3 种长度、50+ 语言 | MP3/MP4 |
| **视频概览** | 3 种格式（解释、简短、电影）、9 种视觉风格 | MP4 |
| **幻灯片** | 详细或演示模式，可调整长度 | PDF, PPTX |
| **信息图** | 3 种方向、3 种详细级别 | PNG |
| **测验** | 可配置数量和难度 | JSON, Markdown, HTML |
| **闪卡** | 可配置数量和难度 | JSON, Markdown, HTML |
| **报告** | 简报、研究指南、博客或自定义提示 | Markdown |
| **数据表** | 通过自然语言自定义结构 | CSV |
| **思维导图** | 交互式层级可视化 | JSON |

资料来源：[README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

### 源文件类型

支持以下源文件类型：

| 类型 | 说明 |
|------|------|
| **URL** | 网页链接 |
| **YouTube** | YouTube 视频 |
| **文件** | PDF、文本、Markdown、Word、EPUB、音频、视频、图片 |
| **Google Drive** | Google 云端硬盘文件 |
| **粘贴文本** | 直接粘贴的文本内容 |

资料来源：[README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

## CLI 命令行工具

### 命令结构

CLI 采用 Click 框架构建，提供以下命令组：

```mermaid
graph TD
    ROOT[notebooklm] --> AUTH[auth]
    ROOT --> PROFILE[profile]
    ROOT --> NOTEBOOK[notebook]
    ROOT --> SOURCE[source]
    ROOT --> DOWNLOAD[download]
    ROOT --> GENERATE[generate]
    ROOT --> METADATA[metadata]
    
    AUTH --> LOGIN[login]
    AUTH --> LOGOUT[logout]
    AUTH --> REFRESH[refresh]
    
    NOTEBOOK --> LIST[list]
    NOTEBOOK --> CREATE[create]
    NOTEBOOK --> DELETE[delete]
    
    SOURCE --> ADD[add]
    SOURCE --> CLEAN[clean]
```

### 全局选项

| 选项 | 说明 |
|------|------|
| `--profile` / `-p` | 指定配置文件 |
| `--json` | JSON 格式输出 |

### 特殊功能

- **多账户配置**：支持通过 `notebooklm profile` 命令切换不同 Google 账户
- **Shell 自动补全**：支持 shell 命令补全
- **标准输入管道**：支持通过管道传入数据
- **SIGINT 恢复**：支持中断后恢复

资料来源：[README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

## 数据模型

### NotebookMetadata

```python
@dataclass
class NotebookMetadata:
    """Combined notebook metadata with sources list."""
    notebook: Notebook
    sources: list[SourceSummary] = field(default_factory=list)
```

| 属性 | 类型 | 说明 |
|------|------|------|
| `id` | `str` | 笔记本 ID |
| `title` | `str` | 笔记本标题 |
| `created_at` | `datetime \| None` | 创建时间 |
| `is_owner` | `bool` | 是否为所有者 |
| `sources` | `list[SourceSummary]` | 源文件摘要列表 |

资料来源：[src/notebooklm/_types/notebooks.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_types/notebooks.py)

### NotebookDescription

```python
@dataclass
class NotebookDescription:
    """AI-generated description and suggested topics for a notebook."""
    summary: str
    suggested_topics: list[SuggestedTopic] = field(default_factory=list)
```

资料来源：[src/notebooklm/_types/notebooks.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_types/notebooks.py)

## 中间件链

项目实现了模块化的中间件系统，遵循 ADR-009 定义的顺序：

```mermaid
graph LR
    A[请求] --> B[DrainMiddleware]
    B --> C[MetricsMiddleware]
    C --> D[SemaphoreMiddleware]
    D --> E[RetryMiddleware]
    E --> F[AuthMiddleware]
    F --> G[ErrorInjectionMiddleware]
    G --> H[TracingMiddleware]
    H --> I[传输层]
```

资料来源：[src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)

## 内部模块命名约定

项目使用下划线前缀约定区分模块类型：

| 模式 | 含义 | 示例 |
|------|------|------|
| `_*.py` | 核心服务层 | `_sources.py`, `_artifacts.py` |
| `_rpc_*.py` | RPC 协议处理 | `_rpc_call`, `_rpc_types` |
| `__*.py` | 私有实现 | `__init__` |

资料来源：[CLAUDE.md](https://github.com/teng-lin/notebooklm-py/blob/main/CLAUDE.md)

## 版本历史

| 版本 | 发布日期 | 主要变更 |
|------|----------|---------|
| v0.6.0 | - | 异常层次结构对称性恢复 |
| v0.5.0 | 2026-05-23 | CLI UX 大改版、认证可靠性增强 |
| v0.4.0 | - | 多账户配置文件支持 |
| v0.3.4 | - | Notebook 元数据导出、电影视频支持 |

资料来源：[README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

## 认证机制

### 认证方式

1. **浏览器 Cookie 导入**：复用浏览器中的 SID cookie
2. **多账户 Profile**：不同 Google 账户独立配置
3. **环境变量**：`NOTEBOOKLM_PROFILE` 支持命令行全局指定

### AuthTokens 结构

```python
AuthTokens(cookies, csrf_token, session_id)
```

### 已知限制

> Google SID cookie 会频繁过期，在长时间运行的自动化工作流中可能需要多次重新认证。

资料来源：[README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

## 开发指南

### 贡献者安装

```bash
uv sync --frozen --extra browser --extra dev --extra markdown
source .venv/bin/activate
uv run playwright install chromium
uv run pytest
```

### 代码检查

```bash
uv run ruff check .
uv run ruff format .
uv run mypy src/notebooklm
uv run pre-commit run --all-files
```

### 技术规范

- **Python 版本**：3.10+
- **缩进**：4 空格
- **引号**：双引号
- **行长度**：100 字符
- **测试**：pytest
- **格式**：ruff

资料来源：[AGENTS.md](https://github.com/teng-lin/notebooklm-py/blob/main/AGENTS.md)

## 相关资源

- [官方文档](https://github.com/teng-lin/notebooklm-py)
- [PyPI 主页](https://pypi.org/project/notebooklm-py/)
- [问题追踪](https://github.com/teng-lin/notebooklm-py/issues)
- [故障排除指南](docs/troubleshooting.md)

---

<a id='page-quickstart'></a>

## 快速开始

### 相关页面

相关主题：[项目介绍](#page-project-intro), [认证与 Cookie 生命周期](#page-auth-cookie-lifecycle)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)
- [docs/installation.md](https://github.com/teng-lin/notebooklm-py/blob/main/docs/installation.md)
- [src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)
- [src/notebooklm/auth.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/auth.py)
- [examples/quickstart.py](https://github.com/teng-lin/notebooklm-py/blob/main/examples/quickstart.py)
- [src/notebooklm/_auth/extraction.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_auth/extraction.py)
</details>

# 快速开始

本页面为 notebooklm-py 新用户提供从安装到首次成功调用的完整指引。涵盖两种核心使用方式：命令行界面（CLI）和 Python 异步客户端库。

---

## 环境要求

| 组件 | 最低版本 | 说明 |
|------|----------|------|
| Python | 3.10+ | 异步语法支持要求 |
| pip / uv | 最新版 | 包管理器 |
| 网络 | 可访问 Google NotebookLM | 需有效的 Google 账号认证 |

资料来源：[AGENTS.md:12]()

---

## 安装方式

### 标准安装（推荐）

```bash
pip install notebooklm-py
```

### 完整安装（含可选依赖）

```bash
# 包含 Markdown 导出支持
pip install 'notebooklm-py[markdown]'

# 包含浏览器自动化认证
pip install 'notebooklm-py[browser]'

# 包含所有可选依赖
pip install 'notebooklm-py[markdown,browser]'
```

### 开发安装

```bash
uv sync --frozen --extra browser --extra dev --extra markdown
source .venv/bin/activate
uv run playwright install chromium
```

资料来源：[docs/installation.md](https://github.com/teng-lin/notebooklm-py/blob/main/docs/installation.md)

---

## 认证配置

notebooklm-py 使用 Google SID 会话 cookie 进行认证，有三种获取方式：

### 方式一：浏览器导入（交互式）

```bash
notebooklm login
```

此命令会启动浏览器自动化流程，自动从你的 Google 账号提取认证 cookie。适用于手动操作的终端用户。

资料来源：[src/notebooklm/auth.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/auth.py)

### 方式二：手动提取 Cookie

从浏览器开发者工具复制以下 cookie：

| Cookie 名称 | 来源 | 说明 |
|------------|------|------|
| `SID` | `google.com` | 主会话标识符 |
| `__Secure-1PSIDTS` | `accounts.google.com` | 安全时间戳 |
| `__Secure-1PSID` | `accounts.google.com` | 认证令牌 |

```bash
notebooklm use --sid "your-sid-value" --1psidts "your-ts-value" --1psid "your-psid-value"
```

### 方式三：环境变量

```bash
export NOTEBOOKLM_SID="your-sid-value"
export NOTEBOOKLM_1PSIDTS="your-ts-value"
export NOTEBOOKLM_1PSID="your-psid-value"
```

资料来源：[src/notebooklm/_auth/extraction.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_auth/extraction.py)

---

## 使用方式一：命令行界面（CLI）

CLI 是大多数用户的首选入口，提供完整的功能覆盖。

### 基础命令结构

```bash
notebooklm [全局选项] <命令组> <子命令> [参数]
```

### 全局选项

| 选项 | 说明 |
|------|------|
| `--json` | 输出 JSON 格式结果 |
| `--profile <name>` / `-p <name>` | 指定认证配置文件 |
| `--help` | 显示帮助信息 |

### 常用命令速查

```bash
# 笔记本管理
notebooklm notebook list                    # 列出所有笔记本
notebooklm notebook create "我的笔记本"       # 创建笔记本
notebooklm notebook summary <id>             # 获取摘要

# 源管理
notebooklm source add <notebook_id> <url>    # 添加 URL 源
notebooklm source list <notebook_id>         # 列出源
notebooklm source clean <notebook_id>        # 清理无效源

# 内容生成
notebooklm generate audio <notebook_id>      # 生成音频概览
notebooklm generate report <notebook_id>      # 生成报告
notebooklm generate mind-map <notebook_id>   # 生成思维导图

# 聊天对话
notebooklm chat ask <notebook_id> "问题内容"  # 提问

# 认证管理
notebooklm auth refresh                       # 刷新认证
notebooklm profile list                       # 列出配置文件
```

### 退出码规范

| 状态 | 退出码 | 说明 |
|------|--------|------|
| 成功 | 0 | 命令正常执行 |
| 错误 | 1 | 可预见的业务错误（资源不存在等） |
| 系统错误 | 2 | 未预期的运行时异常 |

资料来源：[README.md:Features](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

---

## 使用方式二：Python 客户端库

适用于程序化调用、自动化脚本和 AI Agent 集成场景。

### 异步编程模式

notebooklm-py 完全基于 `asyncio`，所有 API 调用均为异步方法。

```python
import asyncio
from notebooklm import NotebookLMClient

async def main():
    async with NotebookLMClient.from_storage() as client:
        notebooks = await client.notebooks.list()
        print(notebooks)

asyncio.run(main())
```

### 初始化方式

#### 从持久化存储加载（推荐）

```python
from notebooklm import NotebookLMClient

async with NotebookLMClient.from_storage() as client:
    # client 已自动加载存储的认证信息
    pass
```

#### 直接传入认证令牌

```python
from notebooklm import NotebookLMClient, AuthTokens

auth = AuthTokens(
    cookies={"SID": "your-sid"},
    csrf_token="your-csrf",
    session_id="your-session"
)
async with NotebookLMClient(auth) as client:
    pass
```

#### 构造函数参数

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `auth` | `AuthTokens` | 必需 | 认证令牌 |
| `timeout` | `float` | `300.0` | 请求超时（秒） |
| `storage_path` | `Path \| None` | `None` | 认证存储路径 |
| `keepalive` | `float \| None` | `None` | 心跳保活间隔 |
| `rate_limit_max_retries` | `int` | `3` | 速率限制重试次数 |

资料来源：[src/notebooklm/client.py:55-65](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)

---

## 典型工作流示例

### 工作流一：创建笔记本并添加源

```mermaid
graph TD
    A[创建笔记本] --> B[获取 notebook_id]
    B --> C[添加 URL 源]
    C --> D[等待源转换完成]
    D --> E[生成内容]
```

```python
from notebooklm import NotebookLMClient

async def workflow():
    async with NotebookLMClient.from_storage() as client:
        # 创建笔记本
        notebook = await client.notebooks.create("我的研究笔记")
        notebook_id = notebook.id
        
        # 添加 URL 源
        source = await client.sources.add_url(
            notebook_id=notebook_id,
            url="https://example.com/article"
        )
        
        # 列出源
        sources = await client.sources.list(notebook_id)
        print(f"笔记本包含 {len(sources)} 个源")
```

### 工作流二：生成 AI 内容

```python
async def generate_content():
    async with NotebookLMClient.from_storage() as client:
        notebook_id = "your-notebook-id"
        source_ids = ["source-id-1", "source-id-2"]
        
        # 生成音频概览
        audio = await client.artifacts.create_audio(
            notebook_id=notebook_id,
            source_ids=source_ids,
            language="zh-CN"
        )
        
        # 生成报告
        report = await client.artifacts.create_report(
            notebook_id=notebook_id,
            source_ids=source_ids,
            format="briefing-doc"
        )
```

### 工作流三：聊天问答

```python
async def chat_workflow():
    async with NotebookLMClient.from_storage() as client:
        notebook_id = "your-notebook-id"
        
        # 发送问题
        response = await client.chat.ask(
            notebook_id=notebook_id,
            query="本文的主要观点是什么？"
        )
        
        print(f"回答: {response.content}")
```

资料来源：[examples/quickstart.py](https://github.com/teng-lin/notebooklm-py/blob/main/examples/quickstart.py)

---

## 客户端 API 概览

NotebookLMClient 提供以下子 API：

| API | 用途 |
|-----|------|
| `client.notebooks` | 笔记本 CRUD 操作 |
| `client.sources` | 源管理（URL、文件、YouTube 等） |
| `client.artifacts` | AI 内容生成（音频、视频、报告等） |
| `client.chat` | 对话问答 |
| `client.research` | 研究代理 |
| `client.notes` | 笔记管理 |
| `client.settings` | 用户设置 |
| `client.sharing` | 共享权限管理 |

```mermaid
graph LR
    A[NotebookLMClient] --> B[notebooks]
    A --> C[sources]
    A --> D[artifacts]
    A --> E[chat]
    A --> F[research]
    A --> G[notes]
    A --> H[settings]
    A --> I[sharing]
```

资料来源：[src/notebooklm/client.py:35-48](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)

---

## 错误处理

### 常见异常类型

| 异常类型 | 触发条件 |
|----------|----------|
| `NotebookNotFoundError` | 笔记本不存在 |
| `SourceNotFoundError` | 源不存在 |
| `ArtifactNotFoundError` | 制品不存在 |
| `AuthenticationError` | 认证失败或过期 |
| `RateLimitError` | 请求频率超限 |

### 处理示例

```python
from notebooklm import NotebookLMClient
from notebooklm.exceptions import NotebookNotFoundError, AuthenticationError

async def safe_workflow():
    try:
        async with NotebookLMClient.from_storage() as client:
            notebook = await client.notebooks.get("non-existent-id")
    except NotebookNotFoundError:
        print("笔记本不存在")
    except AuthenticationError:
        print("认证过期，请重新登录: notebooklm login")
```

---

## 多账户支持

notebooklm-py 支持通过配置文件管理多个 Google 账号：

```bash
# 创建新配置文件
notebooklm profile create work

# 切换到指定配置
notebooklm profile switch work

# 使用全局选项临时指定
notebooklm --profile work notebook list
```

配置文件存储在 `~/.notebooklm/profiles/<name>/` 目录下。

资料来源：[v0.4.0 release notes](https://github.com/teng-lin/notebooklm-py/releases/tag/v0.4.0)

---

## 下一步

| 资源 | 说明 |
|------|------|
| [CLI 参考](cli-reference.md) | 完整的命令行接口文档 |
| [API 参考](api-reference.md) | Python 客户端详细 API 文档 |
| [示例代码](../examples/) | 各类使用场景的完整示例 |
| [故障排除](troubleshooting.md) | 常见问题与解决方案 |

---

## 相关社区问题

以下 Issue 与快速开始流程相关：

- [#297](https://github.com/teng-lin/notebooklm-py/issues/297) - Auth expiry UX：讨论了 Cookie 过期后的用户体验问题，建议实现自动刷新 hook

---

<a id='page-client-architecture'></a>

## 客户端架构

### 相关页面

相关主题：[项目介绍](#page-project-intro), [中间件链](#page-middleware-chain), [RPC 协议层](#page-rpc-protocol)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)
- [src/notebooklm/_sources.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_sources.py)
- [src/notebooklm/_notebooks.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_notebooks.py)
- [src/notebooklm/_research.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/research.py)
- [src/notebooklm/_types/notebooks.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_types/notebooks.py)
- [src/notebooklm/_types/research.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_types/research.py)
</details>

# 客户端架构

## 概述

`notebooklm-py` 是一个异步 Python 客户端库，通过逆向工程 NotebookLM 的内部 RPC 协议实现对 Google NotebookLM 服务的编程访问。客户端架构采用分层设计，将 RPC 通信、API 抽象、CLI 接口和数据类型解耦到独立模块中。

## 架构层次

```
┌─────────────────────────────────────────────────────────────┐
│                      CLI 层 (cli/)                          │
│  Click 命令行接口：notebook_cmd, source_cmd, download_cmd   │
├─────────────────────────────────────────────────────────────┤
│                    API 层 (_*)                              │
│  NotebooksAPI, SourcesAPI, ArtifactsAPI, ChatAPI, ResearchAPI│
├─────────────────────────────────────────────────────────────┤
│                   传输层 (_transport)                        │
│  RPC 调用、认证注入、错误映射、中间件链                       │
├─────────────────────────────────────────────────────────────┤
│                    RPC 层 (rpc/)                            │
│  协议编码/解码、RPC 方法 ID、请求构建                        │
├─────────────────────────────────────────────────────────────┤
│                    网络层 (httpx)                            │
│  HTTP/2 会话管理、Cookie 持久化                              │
└─────────────────────────────────────────────────────────────┘
```

## 核心组件

### NotebookLMClient 主类

`NotebookLMClient` 是库的入口点，负责初始化所有子 API 并管理生命周期：

```python
class NotebookLMClient:
    def __init__(
        self,
        auth: AuthTokens,
        timeout: float = DEFAULT_TIMEOUT,
        storage_path: Path | None = None,
        keepalive: float | None = None,
        rate_limit_max_retries: int = 3,
        server_error_max_retries: int = DEFAULT_SERVER_ERROR_RETRIES,
    )
```

**主要属性**：

| 属性 | 类型 | 说明 |
|------|------|------|
| `notebooks` | NotebooksAPI | 笔记本的创建、列表、重命名、删除 |
| `sources` | SourcesAPI | 来源管理（URL、YouTube、文件、Drive） |
| `artifacts` | ArtifactsAPI | AI 生成内容（音频、视频、报告等） |
| `chat` | ChatAPI | 对话问答 |
| `research` | ResearchAPI | Web/Drive 研究代理 |
| `notes` | NotesAPI | 用户笔记管理 |
| `settings` | SettingsAPI | 用户设置 |
| `sharing` | SharingAPI | 共享和权限管理 |
| `auth` | AuthTokens | 认证令牌 |

**使用模式**：

```python
# 方式一：从存储的认证创建（标准用法）
async with NotebookLMClient.from_storage() as client:
    notebooks = await client.notebooks.list()

# 方式二：从 AuthTokens 直接创建
auth = AuthTokens(cookies, csrf_token, session_id)
async with NotebookLMClient(auth) as client:
    notebooks = await client.notebooks.list()
```

资料来源：[src/notebooklm/client.py:1-100]()

### 子 API 模块

#### NotebooksAPI

负责笔记本的基本操作管理：

```python
class NotebooksAPI:
    async def list(self, ...) -> list[Notebook]
    async def create(self, title: str) -> Notebook
    async def delete(self, notebook_id: str) -> bool
    async def rename(self, notebook_id: str, new_title: str) -> Notebook
    async def get_description(self, notebook_id: str) -> NotebookDescription
    async def get_metadata(self, notebook_id: str) -> NotebookMetadata
```

资料来源：[src/notebooklm/_notebooks.py:80-150]()

#### SourcesAPI

负责来源的添加、列表、刷新和内容获取：

```python
class SourcesAPI:
    async def add_url(self, notebook_id: str, url: str) -> Source
    async def add_youtube(self, notebook_id: str, video_url: str) -> Source
    async def add_file(self, notebook_id: str, file_path: Path) -> Source
    async def add_text(self, notebook_id: str, text: str, title: str) -> Source
    async def list(self, notebook_id: str) -> list[Source]
    async def refresh(self, notebook_id: str) -> bool
    async def get_guide(self, notebook_id: str, source_id: str) -> SourceGuide
    async def get_fulltext(self, notebook_id: str, source_id: str) -> SourceFulltext
```

**SourceGuide 数据结构**：

```python
@dataclass
class SourceGuide:
    summary: str  # AI 生成的摘要（Markdown 格式，带粗体关键词）
    keywords: tuple[str, ...]  # 主题关键词元组
```

资料来源：[src/notebooklm/_sources.py:50-150]()

#### ResearchAPI

提供 Web 和 Drive 研究代理功能：

```python
class ResearchAPI:
    async def start(self, notebook_id: str, sources: Sequence[ResearchSourceInput]) -> ResearchStart
    async def wait_for_completion(
        self,
        task: ResearchTask,
        *,
        initial_interval: float = DEFAULT_INITIAL_INTERVAL,
        interval: float = 5.0,
        timeout: float = 300.0,
    ) -> list[ResearchTask]
    async def import_sources(self, notebook_id: str, task_id: str) -> list[Source]
```

**ResearchSource 数据结构**：

```python
@dataclass
class ResearchSource:
    url: str
    title: str
    result_type: ResearchResultType  # WEB 或 DRIVE
    research_task_id: str | None
    report_markdown: str
```

资料来源：[src/notebooklm/_research.py:1-100]()
资料来源：[src/notebooklm/_types/research.py:20-60]()

#### ArtifactsAPI

负责 AI 生成内容的创建、轮询和下载：

```python
class ArtifactsAPI:
    async def generate_audio(self, notebook_id: str, source_ids: list[str], ...)
    async def generate_video(self, notebook_id: str, source_ids: list[str], ...)
    async def generate_slides(self, notebook_id: str, source_ids: list[str], ...)
    async def generate_report(self, notebook_id: str, source_ids: list[str], ...)
    async def generate_mind_map(self, notebook_id: str, source_ids: list[str], ...)
    async def download_mind_map(self, notebook_id: str, output_path: str, ...) -> str
```

资料来源：[src/notebooklm/_artifact_downloads.py:80-150]()

#### ChatAPI

对话问答功能：

```python
async def ask(
    self,
    notebook_id: str,
    query: str,
    conversation_id: str | None = None,
    model: str | None = None,
) -> ChatResponse
```

#### NotesAPI

用户笔记管理：

```python
async def create(self, notebook_id: str, content: str, title: str | None = None) -> Note
async def update(self, note_id: str, content: str | None = None, title: str | None = None) -> Note
async def delete(self, note_id: str) -> bool
```

## 认证架构

### AuthTokens 数据类

```python
@dataclass
class AuthTokens:
    cookies: dict[str, str]           # Google SID 等 Cookie
    csrf_token: str                   # CSRF 令牌
    session_id: str                   # 会话 ID
```

### 认证存储

支持多账户 profiles，存储路径为 `~/.notebooklm/profiles/<name>/`，可通过以下方式指定：

- `notebooklm profile` 子命令
- 全局 `--profile` / `-p` 标志
- `NOTEBOOKLM_PROFILE` 环境变量

### keepalive 机制

构造函数支持 `keepalive` 参数，用于在长时间运行的工作流中自动维持会话活跃：

```python
async with NotebookLMClient(auth, keepalive=300) as client:  # 每5分钟保活
    ...
```

## 中间件链

客户端使用中间件链处理请求，按顺序执行：

```
请求 → 错误注入 → 认证 → 重试 → 速率限制 → 指标 → 追踪 → 排水 → RPC 调用
```

各中间件模块位于 `src/notebooklm/_middleware*.py`：

| 中间件 | 功能 |
|--------|------|
| `drain` | 响应排水处理 |
| `metrics` | 请求/响应指标收集 |
| `semaphore` | 并发控制 |
| `retry` | 失败重试 |
| `auth` | 认证令牌注入 |
| `error_injection` | 测试用错误注入 |
| `tracing` | 请求追踪 |

资料来源：[src/notebooklm/_middleware_chain.py]()

## 类型系统

### 公共类型

| 类型 | 文件 | 说明 |
|------|------|------|
| `Notebook` | `_types/notebooks.py` | 笔记本实体 |
| `Source` | `_types/sources.py` | 来源实体 |
| `Note` | `_types/notes.py` | 笔记实体 |
| `Artifact` | `_types/artifacts.py` | AI 生成产物 |
| `ResearchSource` | `_types/research.py` | 研究来源 |
| `ChatMessage` | `_types/chat.py` | 对话消息 |

### NotebookMetadata 组合类型

```python
@dataclass
class NotebookMetadata:
    """组合笔记本元数据，包含笔记本信息和来源列表。"""
    notebook: Notebook
    sources: list[SourceSummary]
```

资料来源：[src/notebooklm/_types/notebooks.py:40-80]()

## 异常层次

```
RPCError
├── NetworkError
├── RPCTimeoutError
├── ValidationError
├── SourceNotFoundError (继承 SourceError + RPCError)
├── ArtifactNotFoundError (继承 ArtifactError + RPCError)
├── NotebookNotFoundError (继承 NotebookError + RPCError)
└── NoteNotFoundError
```

v0.6.0 恢复了异常层次对称性，`SourceNotFoundError` 和 `ArtifactNotFoundError` 现同时继承自 `RPCError`。

## CLI 集成

CLI 层使用 Click 框架，命令注册在 `src/notebooklm/cli/` 目录：

| 命令模块 | 功能 |
|----------|------|
| `notebook_cmd.py` | list, create, delete, rename, summary, metadata |
| `source_cmd.py` | add, list, clean |
| `download_cmd.py` | download (支持所有 artifact 类型) |
| `research_cmd.py` | start, wait, import |
| `share_cmd.py` | link, revoke, permission |

CLI 共享客户端通过 `auth_runtime.py` 中的 `with_client` 装饰器注入。

## 社区相关问题

以下 Issues 与客户端架构设计相关：

- **#1247**: v0.8.0 将翻转 `sources.get()`、`artifacts.get()`、`notes.get()` 和 `mind_maps.get()` 的行为，从返回 `None` 改为抛出 `*NotFoundError`
- **#1291**: `client.mind_maps` 的 rename/get_tree 方法应使用 `MindMapNotFoundError` 替代裸 `ValueError`
- **#1290**: 三个方法 (`refresh`、`delete_conversation`、`clear_cache`) 返回始终为 `True` 的 `bool`，需重新评估 API 设计
- **#297**: 用户请求支持 Cookie 刷新钩子，避免频繁重新认证

## 总结

`notebooklm-py` 客户端采用分层架构，通过 `NotebooksAPI`、`SourcesAPI`、`ArtifactsAPI` 等子模块提供类型安全的 API 访问。RPC 通信封装在底层，认证和中间件机制确保了可靠性和可扩展性。异步设计 (`async/await`) 使其适合长时间运行的代理工作流。

---

<a id='page-rpc-protocol'></a>

## RPC 协议层

### 相关页面

相关主题：[客户端架构](#page-client-architecture), [中间件链](#page-middleware-chain)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/notebooklm/rpc/types.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/rpc/types.py)
- [src/notebooklm/rpc/_batchexecute.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/rpc/_batchexecute.py)
- [src/notebooklm/rpc/_exceptions.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/rpc/_exceptions.py)
- [src/notebooklm/_middleware_context.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_context.py)
- [src/notebooklm/_idempotency.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_idempotency.py)
- [src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)
- [src/notebooklm/__init__.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/__init__.py)
</details>

# RPC 协议层

## 概述

RPC 协议层是 notebooklm-py 客户端与 NotebookLM 后端服务通信的核心基础设施。该层封装了所有与 Google NotebookLM API 的交互逻辑，包括请求编码、响应解码、错误处理、重试机制和认证刷新等功能。

RPC 层的主要职责：

| 职责 | 描述 |
|------|------|
| **协议编码** | 将 Python 调用转换为 Google RPC 格式的请求 |
| **请求调度** | 通过批量执行接口 (BATCHEXECUTE) 发送 RPC 调用 |
| **响应解析** | 解码服务器响应并转换为类型化 Python 对象 |
| **错误映射** | 将服务器错误转换为语义化的异常类型 |
| **中间件链** | 提供认证刷新、重试、限流等横切关注点 |

资料来源：[src/notebooklm/client.py:1-50](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)

## 架构设计

### 整体架构

RPC 层采用洋葱模型设计，核心调用路径经过多层中间件处理：

```mermaid
graph TD
    subgraph "调用者 (API Layer)"
        A[NotebooksAPI<br/>SourcesAPI<br/>ArtifactsAPI]
    end
    
    subgraph "中间件链 (Middleware Chain)"
        B[DrainMiddleware]
        C[MetricsMiddleware]
        D[SemaphoreMiddleware]
        E[RetryMiddleware]
        F[AuthMiddleware]
        G[ErrorInjectionMiddleware]
        H[TracingMiddleware]
    end
    
    subgraph "RPC 执行器"
        I[RpcExecutor]
        J[BatchExecuteTransport]
    end
    
    subgraph "传输层"
        K[HTTP Client<br/>Google Session]
    end
    
    A --> B
    B --> C
    C --> D
    D --> E
    E --> F
    F --> G
    G --> H
    H --> I
    I --> J
    J --> K
```

中间件顺序遵循 ADR-009 规范，通过 `_middleware_chain.py` 构建。

资料来源：[src/notebooklm/_middleware_chain.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_chain.py)

### 请求流程

```mermaid
sequenceDiagram
    participant C as 调用者
    participant M as 中间件链
    participant E as RpcExecutor
    participant T as BatchExecuteTransport
    participant H as HTTP层
    
    C->>M: rpc_call(method, params)
    M->>M: 认证刷新检查
    M->>M: 重试预算检查
    M->>E: 执行RPC调用
    E->>T: 构建BATCHEXECUTE请求
    T->>H: POST /batchexecute
    H-->>T: RPC响应
    T-->>E: 解析响应
    E-->>M: 返回结果
    M-->>C: 返回/抛出异常
```

## 核心组件

### RPC 方法注册表

`RPCMethod` 枚举定义了所有支持的 RPC 方法标识符，是协议层的核心类型定义：

| 组件 | 路径 | 职责 |
|------|------|------|
| `rpc/types.py` | 包含 `RPCMethod` 枚举 | 所有 RPC 方法 ID 的单一数据源 |
| `rpc/_batchexecute.py` | 批量执行传输层 | 构建和解码 BATCHEXECUTE 请求/响应 |
| `rpc/_exceptions.py` | RPC 异常定义 | 协议层错误类型层次结构 |

资料来源：[src/notebooklm/rpc/types.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/rpc/types.py)

### RPC 方法分类

| 类别 | 方法示例 | 幂等性 |
|------|----------|--------|
| **笔记本操作** | `LIST_NOTEBOOKS`, `GET_NOTEBOOK`, `RENAME_NOTEBOOK`, `CREATE_NOTEBOOK` | 读/幂等 |
| **源管理** | `ADD_SOURCE`, `ADD_SOURCE_FILE`, `GET_SOURCE`, `LIST_SOURCES` | 探查后创建 |
| **工件生成** | `CREATE_ARTIFACT`, `POLL_ARTIFACT`, `GET_INTERACTIVE_HTML` | 轮询模式 |
| **聊天** | `SEND_CHAT`, `GET_CONVERSATION` | 非幂等 |
| **研究** | `START_RESEARCH`, `POLL_RESEARCH`, `IMPORT_RESEARCH` | 轮询模式 |
| **笔记** | `UPDATE_NOTE`, `LIST_NOTES` | 部分幂等 |
| **分享** | `SHARE_NOTEBOOK`, `SHARE_ARTIFACT` | 幂等 |

资料来源：[src/notebooklm/_idempotency.py:1-80](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_idempotency.py)

## 异常处理

### 异常层次结构

RPC 协议层定义了完整的异常继承体系：

```
RPCError (基类)
├── RPCTimeoutError
├── RPCResponseTooLargeError
├── ServerError
│   └── (子类)
├── ValidationError
├── UnknownRPCMethodError
└── WaitTimeoutError
```

在 v0.6.0 中，`SourceNotFoundError` 和 `ArtifactNotFoundError` 被调整为同时继承自 `RPCError`，与 `NotebookNotFoundError` 保持对称。

资料来源：[src/notebooklm/rpc/_exceptions.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/rpc/_exceptions.py)

### 跨域异常伞

| 异常类型 | 继承链 | 用途 |
|----------|--------|------|
| `WaitTimeoutError` | RPCError | wait/poll 类操作超时 |
| `SourceError` | Exception | 源操作错误域 |
| `ArtifactError` | Exception | 工件操作错误域 |
| `ResearchError` | Exception | 研究任务错误域 |

资料来源：[src/notebooklm/__init__.py:1-80](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/__init__.py)

## 请求上下文

`RpcRequest.context` 字典用于在中间件链中传递元数据，关键上下文键定义在 `_middleware_context.py`：

| 上下文键 | 类型 | 用途 |
|----------|------|------|
| `RPC_CONTEXT_RPC_METHOD` | `str` | 当前 RPC 方法标识 |
| `RPC_CONTEXT_DISABLE_INTERNAL_RETRIES` | `bool` | 禁用内部重试 |
| `RPC_CONTEXT_BUILD_REQUEST` | `Callable` | 请求构建回调 |
| `RPC_CONTEXT_LOG_LABEL` | `str` | 日志标签 |
| `RPC_CONTEXT_AUTH_SNAPSHOT` | `dict` | 认证状态快照 |
| `RPC_CONTEXT_AUTH_REFRESHED` | `bool` | 认证已刷新标记 |
| `RPC_CONTEXT_RPC_QUEUE_WAIT_SECONDS` | `float` | RPC 队列等待时间 |
| `RPC_CONTEXT_REFRESH_BUDGET` | `RefreshBudget` | 刷新预算（共享单次刷新权限） |

资料来源：[src/notebooklm/_middleware_context.py:1-40](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_context.py)

### 刷新预算机制

`RefreshBudget` 允许 HTTP 401 和解码后认证错误序列共享**单次刷新配额**，确保在 `wire-401 + decoded-auth-error` 场景下只执行一次刷新：

```python
# 伪代码说明
class RefreshBudget:
    refreshed: bool = False  # 单一刷新配额
```

资料来源：[src/notebooklm/_middleware_context.py:27-32](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_context.py)

## 幂等性策略

`IDEMPOTENCY_REGISTRY` 为每个 RPC 方法定义了重试安全策略：

| 策略 | 行为 | 适用场景 |
|------|------|----------|
| `NON_IDEMPOTENT_NO_RETRY` | 不重试 | 纯写操作，无可靠去重键 |
| `PROBE_THEN_CREATE` | 先探查后创建 | 需要基线比对的场景 |
| `IDEMPOTENT_SET_OP` | 安全的读/设置操作 | 可安全重试的读取 |

### 特殊处理示例

```python
# Google Drive 源添加 - 通过 URL 片段探查
IDEMPOTENCY_REGISTRY.register(
    RPCMethod.ADD_SOURCE,
    IdempotencyPolicy.PROBE_THEN_CREATE,
    variant="drive",
    notes="probe by /d/<file_id> URL segment marker on notebook list",
)

# 文本源添加 - 无可靠去重键
IDEMPOTENCY_REGISTRY.register(
    RPCMethod.ADD_SOURCE,
    IdempotencyPolicy.NON_IDEMPOTENT_NO_RETRY,
    variant="text",
    notes="no reliable dedupe key — titles non-unique, body not exposed",
)
```

资料来源：[src/notebooklm/_idempotency.py:1-50](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_idempotency.py)

## 批量执行协议

### BATCHEXECUTE 请求格式

RPC 调用通过 Google 的 BATCHEXECUTE 端点执行，请求格式：

```python
# 请求结构
{
    "f.req": [[method_id, params_array]],
    "at": "csrf_token"
}
```

### 响应解析

服务器响应包含嵌套的 RPC 响应数组，需要通过 `safe_index` 安全访问：

```python
# 典型响应结构
[[[status_code, result_or_error], ...], ...]
```

资料来源：[src/notebooklm/rpc/_batchexecute.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/rpc/_batchexecute.py)

## 中间件详解

### 中间件执行顺序

| 顺序 | 中间件 | 功能 |
|------|--------|------|
| 1 | `DrainMiddleware` | 资源清理 |
| 2 | `MetricsMiddleware` | 性能指标收集 |
| 3 | `SemaphoreMiddleware` | 并发限流 |
| 4 | `RetryMiddleware` | 失败重试 |
| 5 | `AuthMiddleware` | 认证令牌注入 |
| 6 | `ErrorInjectionMiddleware` | 错误注入（仅测试） |
| 7 | `TracingMiddleware` | 请求追踪 |

资料来源：[src/notebooklm/_middleware_chain.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_chain.py)

## 版本与兼容性

### 关键版本里程碑

| 版本 | 变更 | 相关 Issue |
|------|------|------------|
| v0.8.0 | `get()` 方法改为抛出 `*NotFoundError` 而非返回 `None` | #1247 |
| v0.7.0 | 引入 `get()` 返回值 `None` 的弃用警告 | #1206 |
| v0.6.0 | 异常层次对称性恢复，`SourceNotFoundError`/`ArtifactNotFoundError` 继承 `RPCError` | Release v0.6.0 |

### 弃用路径

当前 `get()` 方法返回 `None` 但会发出警告，计划在 v0.8.0 中切换为抛出异常：

```python
# 当前行为 (v0.7.x)
source = sources.get(source_id)  # None + 警告

# 目标行为 (v0.8.0)
source = sources.get(source_id)  # SourceNotFoundError 异常
```

资料来源：[社区 Issue #1247](https://github.com/teng-lin/notebooklm-py/issues/1247)

## 开发指南

### 添加新 RPC 方法

1. 在 `rpc/types.py` 的 `RPCMethod` 枚举中添加新方法 ID
2. 在 `IDEMPOTENCY_REGISTRY` 中注册幂等性策略
3. 在对应 API 服务的 `_*.py` 中实现调用逻辑

### 健康检查

`scripts/check_rpc_health.py` 提供 RPC 方法可用性诊断脚本，用于验证各方法在当前 NotebookLM 版本中的支持状态。

### 错误处理最佳实践

| 场景 | 推荐处理 |
|------|----------|
| 网络超时 | 使用 `RPCTimeoutError` 捕获，配置重试 |
| 认证失效 | 中间件自动刷新，无需手动处理 |
| 业务逻辑错误 | 使用域特定异常（如 `SourceNotFoundError`） |
| 资源未找到 | 捕获 `*NotFoundError`，提供用户友好的错误消息 |

---

<a id='page-middleware-chain'></a>

## 中间件链

### 相关页面

相关主题：[客户端架构](#page-client-architecture), [认证与 Cookie 生命周期](#page-auth-cookie-lifecycle)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/notebooklm/_middleware_chain.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_chain.py)
- [src/notebooklm/_middleware.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware.py)
- [src/notebooklm/_middleware_chain_host.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_chain_host.py)
- [src/notebooklm/_middleware_tracing.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_tracing.py)
- [src/notebooklm/_middleware_metrics.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_metrics.py)
- [src/notebooklm/_middleware_retry.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_retry.py)
- [src/notebooklm/_middleware_semaphore.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_semaphore.py)
- [src/notebooklm/_middleware_drain.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_drain.py)
- [src/notebooklm/_middleware_auth_refresh.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_middleware_auth_refresh.py)
</details>

# 中间件链

## 概述

中间件链是 notebooklm-py 客户端架构中的核心组件，负责在 RPC（远程过程调用）请求处理过程中注入横切关注点（cross-cutting concerns）。它采用装饰器模式（Decorator Pattern）构建可插拔的中间件栈，按照 ADR-009 定义的规范顺序组织各种中间件实现。

中间件链的主要职责包括：

- 请求重试与错误恢复
- 认证令牌自动刷新
- 速率限制与并发控制
- 请求追踪与指标收集
- 资源清理与连接池排空

资料来源：[CLAUDE.md:1]()

## 架构设计

### 整体架构图

```mermaid
graph TD
    Client["NotebookLMClient"]
    Host["MiddlewareChainHost"]
    Chain["MiddlewareChain"]
    
    subgraph MiddlewareStack["中间件栈 (按 ADR-009 顺序)"]
        Drain["DrainMiddleware<br/>资源排空"]
        Metrics["MetricsMiddleware<br/>指标收集"]
        Semaphore["SemaphoreMiddleware<br/>并发限制"]
        Retry["RetryMiddleware<br/>重试机制"]
        AuthRefresh["AuthRefreshMiddleware<br/>认证刷新"]
        Tracing["TracingMiddleware<br/>请求追踪"]
    end
    
    Transport["Transport Layer<br/>传输层"]
    RPC["RPC 调用"]
    
    Client --> Host
    Host --> Chain
    Chain --> Drain
    Drain --> Metrics
    Metrics --> Semaphore
    Semaphore --> Retry
    Retry --> AuthRefresh
    AuthRefresh --> Tracing
    Tracing --> Transport
    Transport --> RPC
    
    style Chain fill:#f9f,stroke:#333,stroke-width:2px
    style Host fill:#ff9,stroke:#333,stroke-width:2px
```

### 中间件执行流程

```mermaid
sequenceDiagram
    participant C as Client
    participant H as MiddlewareChainHost
    participant M1 as Drain
    participant M2 as Metrics
    participant M3 as Semaphore
    participant M4 as Retry
    participant M5 as AuthRefresh
    participant M6 as Tracing
    participant T as Transport
    
    C->>H: RPC 请求
    H->>M1: proceed(request)
    M1->>M2: proceed(request)
    M2->>M3: proceed(request)
    M3->>M4: proceed(request)
    M4->>M5: proceed(request)
    M5->>M6: proceed(request)
    M6->>T: 发送请求
    T-->>M6: 响应
    M6-->>M5: 响应
    M5-->>M4: 响应
    M4-->>M3: 响应
    M3-->>M2: 响应
    M2-->>M1: 响应
    M1-->>H: 响应
    H-->>C: 结果
```

## 中间件组件详解

### 组件总览

| 中间件名称 | 文件 | 职责 | 执行顺序 |
|-----------|------|------|---------|
| DrainMiddleware | `_middleware_drain.py` | 确保响应被完全消费，防止连接泄漏 | 1 (最外层) |
| MetricsMiddleware | `_middleware_metrics.py` | 收集请求耗时、错误率等指标 | 2 |
| SemaphoreMiddleware | `_middleware_semaphore.py` | 限制并发请求数量 | 3 |
| RetryMiddleware | `_middleware_retry.py` | 自动重试失败的请求 | 4 |
| AuthRefreshMiddleware | `_middleware_auth_refresh.py` | 自动刷新过期认证令牌 | 5 |
| TracingMiddleware | `_middleware_tracing.py` | 请求追踪与日志记录 | 6 (最内层) |

资料来源：[CLAUDE.md:1]()

### DrainMiddleware

**职责**：资源清理与连接池排空

DrainMiddleware 确保每个 RPC 响应的流（stream）被完全消费，防止连接池泄漏。这对于长时间运行的客户端和自动化工作流尤为重要。

**关键行为**：
- 在响应返回前检查流是否已完全读取
- 对于异步流，确保所有数据被消费
- 防止半开连接占用传输层资源

资料来源：[src/notebooklm/_middleware_drain.py]()

### MetricsMiddleware

**职责**：请求指标收集

MetricsMiddleware 收集每次 RPC 调用的性能指标，用于监控和调试。

**收集的指标**：
- 请求耗时
- 错误类型与频率
- 重试次数统计
- 并发阻塞时间

资料来源：[src/notebooklm/_middleware_metrics.py]()

### SemaphoreMiddleware

**职责**：并发请求限制

SemaphoreMiddleware 使用信号量（Semaphore）限制同时进行的请求数量，防止对 NotebookLM API 的过度并发访问。

**配置参数**：
- `max_concurrent_requests`：最大并发数（默认根据客户端配置）

资料来源：[src/notebooklm/_middleware_semaphore.py]()

### RetryMiddleware

**职责**：自动重试机制

RetryMiddleware 在遇到可恢复的错误时自动重试请求，采用指数退避策略避免对服务造成压力。

**重试策略**：
- 可重试错误类型识别
- 指数退避间隔
- 最大重试次数限制

资料来源：[src/notebooklm/_middleware_retry.py]()

### AuthRefreshMiddleware

**职责**：认证令牌自动刷新

AuthRefreshMiddleware 监测认证状态，在令牌即将过期或已失效时自动触发刷新流程。这是维持长时间运行任务（如 cron 作业、CI 会话、Claude Code agent）连续性的关键组件。

**刷新触发条件**：
- 检测到 401/403 响应
- 令牌剩余有效期低于阈值
- 认证错误传播

**用户反馈**：社区Issue #297 反映了认证过期对自动化场景的影响，AuthRefreshMiddleware 是解决该问题的核心机制。

资料来源：[src/notebooklm/_middleware_auth_refresh.py]()
资料来源：[社区Issue #297](https://github.com/teng-lin/notebooklm-py/issues/297)

### TracingMiddleware

**职责**：请求追踪与调试

TracingMiddleware 为每个请求添加追踪标识，记录详细的请求/响应日志，便于调试和问题排查。

**追踪信息**：
- 请求 ID
- 时间戳
- RPC 方法名称
- 请求/响应大小

资料来源：[src/notebooklm/_middleware_tracing.py]()

## 链式构建机制

### MiddlewareChain

`MiddlewareChain` 类负责按照预定义的顺序组合所有中间件。链的构建顺序遵循 ADR-009 决策记录中的规范。

```python
# 伪代码示例 - 链构建逻辑
class MiddlewareChain:
    @staticmethod
    def build(
        transport,
        *,
        metrics,
        semaphore,
        retry_config,
        auth_manager,
        tracing_enabled,
    ) -> MiddlewareChainHost:
        """按照 ADR-009 顺序构建中间件链."""
        
        # 从内到外构建（先构建的在内层）
        # 1. TracingMiddleware (最内层)
        # 2. AuthRefreshMiddleware
        # 3. RetryMiddleware
        # 4. SemaphoreMiddleware
        # 5. MetricsMiddleware
        # 6. DrainMiddleware (最外层)
        
        return chain_host
```

资料来源：[src/notebooklm/_middleware_chain.py]()

### MiddlewareChainHost

`MiddlewareChainHost` 是中间件链的宿主，持有链的引用并将所有 RPC 调用委托给链处理。它是客户端与中间件栈之间的桥梁。

**核心职责**：
- 管理中间件链生命周期
- 接收并分发 RPC 请求
- 处理中间件层的错误传播

资料来源：[src/notebooklm/_middleware_chain_host.py]()

## 错误处理

### 错误传播机制

中间件链采用洋葱模型（Onion Model）处理错误：错误从内层向外传播，每层中间件可以根据需要捕获、转换或重新抛出异常。

```mermaid
graph LR
    E1["错误发生<br/>Transport层"]
    E2["TracingMiddleware<br/>记录但不拦截"]
    E3["AuthRefreshMiddleware<br/>尝试刷新认证"]
    E4["RetryMiddleware<br/>触发重试"]
    E5["SemaphoreMiddleware<br/>释放信号量"]
    E6["MetricsMiddleware<br/>记录错误指标"]
    E7["DrainMiddleware<br/>确保资源清理"]
    E8["返回错误<br/>给客户端"]
    
    E1 --> E2 --> E3 --> E4 --> E5 --> E6 --> E7 --> E8
```

### 错误类型映射

不同的中间件层负责不同类型的错误处理：

| 错误场景 | 处理中间件 | 处理方式 |
|---------|-----------|---------|
| 网络超时 | RetryMiddleware | 指数退避重试 |
| 认证失效 | AuthRefreshMiddleware | 自动刷新令牌 |
| 速率限制 | SemaphoreMiddleware | 等待后重试 |
| 连接池耗尽 | DrainMiddleware | 确保流被完全消费 |

## 配置选项

### 客户端构造参数

在创建 `NotebookLMClient` 时，可以通过以下参数配置中间件行为：

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `rate_limit_max_retries` | `int` | `3` | 速率限制重试次数 |
| `server_error_max_retries` | `int` | - | 服务器错误重试次数 |
| `keepalive` | `float \| None` | `None` | 保持连接活跃的间隔秒数 |
| `keepalive_min_interval` | `float` | `60.0` | keepalive 检查最小间隔 |

资料来源：[src/notebooklm/client.py:1]()

### 环境变量配置

| 环境变量 | 说明 |
|---------|------|
| `NOTEBOOKLM_REFRESH_CMD` | 自定义认证刷新命令 |

## 版本演进与社区反馈

### v0.4.1 中的改进

v0.4.1 版本引入了 `keepalive=` 构造函数参数和 `NOTEBOOKLM_REFRESH_CMD` 环境变量，增强了中间件层的认证管理能力。这些改进直接响应了社区对长时间运行任务稳定性的需求。

资料来源：[v0.4.1 Release Notes](https://github.com/teng-lin/notebooklm-py/releases/tag/v0.4.1)

### v0.6.0 的异常层级调整

v0.6.0 版本恢复了异常层级对称性，`SourceNotFoundError` 和 `ArtifactNotFoundError` 现在同时继承自 `RPCError` 和各自领域基类，与 `NotebookNotFoundError` 保持一致。这影响了中间件层错误传播的行为。

资料来源：[v0.6.0 Release Notes](https://github.com/teng-lin/notebooklm-py/releases/tag/v0.6.0)

## 最佳实践

### 开发者指南

1. **不要修改 PROTECTED 区域**：中间件链中的某些区域受 PROTECTED 标记保护，修改前需获得明确授权。

2. **遵循 ADR-009 顺序**：新增中间件时必须按照规范顺序插入链中。

3. **保持中间件无状态**：中间件应避免持有请求相关状态，以确保并发安全。

### 故障排查

| 症状 | 可能原因 | 排查步骤 |
|------|---------|---------|
| 请求卡住 | SemaphoreMiddleware 达到最大并发 | 检查并发限制配置 |
| 认证循环失败 | AuthRefreshMiddleware 无法刷新令牌 | 检查 `NOTEBOOKLM_REFRESH_CMD` |
| 连接池泄漏 | DrainMiddleware 未正确排空 | 检查响应是否完全消费 |

## 相关文档

- [CLAUDE.md](./CLAUDE.md) - 项目结构与模块组织
- [AGENTS.md](./AGENTS.md) - 开发者贡献指南
- [ADR-0009](./docs/adr/ADR-0009-middleware-chain.md) - 中间件链设计决策记录

---

<a id='page-notebooks-api'></a>

## 笔记本 API

### 相关页面

相关主题：[源与制品 API](#page-sources-artifacts)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/notebooklm/client.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/client.py)
- [src/notebooklm/_types/notebooks.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_types/notebooks.py)
- [src/notebooklm/_notebook_metadata.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_notebook_metadata.py)
- [src/notebooklm/cli/notebook_cmd.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/cli/notebook_cmd.py)
- [src/notebooklm/_sharing_manager.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_sharing_manager.py)
</details>

# 笔记本 API

## 概述

笔记本 API（`NotebooksAPI`）是 notebooklm-py 库的核心组件之一，提供对 Google NotebookLM 笔记本实例的完整操作能力。通过该 API，用户可以创建、列出、重命名、删除笔记本，获取笔记本描述和元数据，以及管理与笔记本关联的共享权限。

笔记本是 NotebookLM 的核心资源单元，所有 Sources（来源）、Artifacts（产物）、Chat（对话）和 Notes（笔记）都依附于特定的笔记本存在。资料来源：[src/notebooklm/client.py:1-50]()

## 架构设计

### 模块关系

Notebook API 采用分层架构设计，与其他 API 模块协同工作：

```mermaid
graph TB
    Client[NotebookLMClient] --> NotebooksAPI[NotebooksAPI]
    Client --> SourcesAPI[SourcesAPI]
    Client --> ArtifactsAPI[ArtifactsAPI]
    Client --> ChatAPI[ChatAPI]
    Client --> ResearchAPI[ResearchAPI]
    Client --> NotesAPI[NotesAPI]
    Client --> SharingAPI[SharingAPI]
    
    NotebooksAPI --> NotebookMetadata[NotebookMetadata]
    NotebooksAPI --> NotebookDescription[NotebookDescription]
    NotebooksAPI --> SharingManager[SharingManager]
    
    NotebooksAPI --> RPCLayer[RPC 调用层]
    RPCLayer --> Transport[传输层]
```

### 核心数据类型

笔记本 API 依赖以下关键数据类型，均定义于 `_types/notebooks.py`：

| 类型 | 用途 | 关键字段 |
|------|------|----------|
| `Notebook` | 笔记本基本模型 | `id`, `title`, `created_at`, `is_owner` |
| `NotebookDescription` | AI 生成的笔记本描述 | `summary`, `suggested_topics` |
| `SuggestedTopic` | 建议主题/问题 | `question`, `prompt` |
| `NotebookMetadata` | 完整元数据（含来源列表） | `notebook`, `sources` |
| `SourceSummary` | 来源摘要 | `id`, `title`, `kind` |

资料来源：[src/notebooklm/_types/notebooks.py:1-80]()

## NotebooksAPI 类

### 类签名与初始化

```python
class NotebooksAPI:
    def __init__(self, rpc: RpcCaller, source_lister: NotebookSourceLister | None = None)
```

`NotebooksAPI` 接收 RPC 调用器和可选的来源列表器实例。来源列表器用于 `get_metadata()` 方法中获取笔记本关联的来源列表。

### 核心方法

| 方法 | 返回类型 | 功能描述 |
|------|----------|----------|
| `list()` | `list[Notebook]` | 列出当前用户所有笔记本 |
| `create(title)` | `Notebook` | 创建新笔记本 |
| `delete(notebook_id)` | `None` | 删除指定笔记本 |
| `rename(notebook_id, new_title)` | `Notebook` | 重命名笔记本 |
| `get_description(notebook_id)` | `NotebookDescription` | 获取 AI 生成的描述和推荐话题 |
| `get_metadata(notebook_id)` | `NotebookMetadata` | 获取完整元数据（含来源列表） |

资料来源：[src/notebooklm/client.py:80-120]()

### 方法详细说明

#### list()

返回当前认证用户拥有的所有笔记本列表。每个 `Notebook` 对象包含：

- `id`: 笔记本唯一标识符
- `title`: 笔记本标题
- `created_at`: 创建时间戳
- `is_owner`: 是否为笔记本所有者

#### get_description()

获取笔记本的 AI 生成描述，包含摘要和建议话题：

```python
description = await client.notebooks.get_description("notebook_id_xxx")
print(description.summary)  # AI 生成的摘要
for topic in description.suggested_topics:
    print(topic.question)  # 建议的问题
    print(topic.prompt)   # 对应的提示词
```

#### get_metadata()

v0.3.4 新增的便捷方法，聚合返回笔记本基础信息和关联来源列表：

```python
metadata = await client.notebooks.get_metadata("notebook_id_xxx")
print(f"笔记本: {metadata.title}")
for source in metadata.sources:
    print(f"  - {source.title} ({source.kind})")
```

资料来源：[src/notebooklm/_notebook_metadata.py:1-60]()

## CLI 命令

笔记本相关的 CLI 命令位于 `notebooklm cli notebook_cmd.py`，通过 Click 框架实现。

### 命令概览

| 命令 | 用法 | 功能 |
|------|------|------|
| `list` | `notebooklm list [--json] [--limit N] [--no-truncate]` | 列出所有笔记本 |
| `create` | `notebooklm create "标题"` | 创建新笔记本 |
| `delete` | `notebooklm delete NOTEBOOK_ID` | 删除笔记本（需确认） |
| `rename` | `notebooklm rename NOTEBOOK_ID "新标题"` | 重命名笔记本 |
| `summary` | `notebooklm summary [--topics] [--json]` | 获取笔记本摘要 |
| `metadata` | `notebooklm metadata [--json]` | 导出笔记本元数据 |

资料来源：[src/notebooklm/cli/notebook_cmd.py:1-150]()

### list 命令

```bash
# 列出所有笔记本（表格形式）
notebooklm list

# 限制显示数量
notebooklm list --limit 10

# JSON 格式输出（适合脚本处理）
notebooklm list --json
```

### summary 命令

支持部分 ID 匹配（模糊搜索）：

```bash
# 获取摘要
notebooklm summary abc

# 包含推荐话题
notebooklm summary abc --topics

# JSON 输出
notebooklm summary abc --json
```

### metadata 命令

导出笔记本的完整元数据，包含来源列表：

```bash
# 人类可读输出
notebooklm metadata abc

# JSON 输出
notebooklm metadata abc --json
```

## 错误处理与异常

### 异常层次结构

v0.6.0 恢复了异常层次结构的对称性，`NotebookNotFoundError` 继承自 `RPCError` 和 `NotebookError`：

```mermaid
graph LR
    NotebookError[NotebookError] --> NotebookNotFoundError[NotebookNotFoundError]
    RPCError[RPCError] --> NotebookNotFoundError
```

### v0.8.0 Breaking Change

根据 Issue #1247，v0.8.0 将翻转 `notebooks.get()` 等方法的返回值行为：

- **当前行为（v0.7.0）**: 返回 `None` 并发出弃用警告
- **v0.8.0**: 缺失实体时抛出 `*NotFoundError`

```python
# 当前（带警告）
notebook = await client.notebooks.get("missing_id")  # 返回 None + 警告

# v0.8.0（breaking change）
notebook = await client.notebooks.get("missing_id")  # 抛出 NotebookNotFoundError
```

## 使用示例

### 异步上下文管理器用法

推荐的标准用法：

```python
from notebooklm import NotebookLMClient

async def main():
    async with NotebookLMClient.from_storage() as client:
        # 列出笔记本
        notebooks = await client.notebooks.list()
        for nb in notebooks:
            print(f"{nb.id}: {nb.title}")
        
        # 创建笔记本
        new_nb = await client.notebooks.create("我的研究笔记")
        print(f"创建了: {new_nb.id}")
        
        # 获取元数据
        metadata = await client.notebooks.get_metadata(new_nb.id)
        print(f"包含 {len(metadata.sources)} 个来源")
```

### 批量操作示例

```python
async def batch_cleanup():
    async with NotebookLMClient.from_storage() as client:
        notebooks = await client.notebooks.list()
        
        # 删除所有测试笔记本
        for nb in notebooks:
            if nb.title.startswith("测试"):
                await client.notebooks.delete(nb.id)
                print(f"已删除: {nb.title}")
```

## 与其他 API 的关系

笔记本作为顶层资源，与其他 API 模块的关系如下：

```mermaid
graph TB
    Notebook[笔记本<br/>NotebooksAPI] --> Sources[来源<br/>SourcesAPI]
    Notebook --> Artifacts[产物<br/>ArtifactsAPI]
    Notebook --> Chat[对话<br/>ChatAPI]
    Notebook --> Notes[笔记<br/>NotesAPI]
    Notebook --> Sharing[共享<br/>SharingAPI]
    Notebook --> Research[研究<br/>ResearchAPI]
```

每个子 API 的方法都需要传入 `notebook_id` 参数来指定目标笔记本：

```python
# 添加来源到指定笔记本
await client.sources.add_url(notebook_id, "https://example.com")

# 在指定笔记本中生成报告
await client.artifacts.generate_report(notebook_id, sources_ids=[...])
```

## 配置与存储

### 笔记本 ID 的部分匹配

CLI 中的 `notebook_id` 参数支持部分匹配：

```bash
# 以下命令等效（如果仓库中存在以 "abc" 开头的笔记本 ID）
notebooklm summary abc
notebooklm summary abc123def456
```

### 多账户支持

通过 `--profile` 标志或 `NOTEBOOKLM_PROFILE` 环境变量，可以在不同 Google 账户的笔记本间切换：

```bash
# 使用工作账户
notebooklm --profile work list

# 使用个人账户
notebooklm --profile personal summary abc
```

## 社区相关问题

### 活跃讨论

- **Issue #297**: 用户反馈频繁的 Cookie 过期问题，建议提供 Cookie 刷新钩子机制，以支持长时间运行的自动化工作流

### 版本演进

| 版本 | 关键变更 |
|------|----------|
| v0.3.4 | 新增 `NotebookMetadata` 类型和 `get_metadata()` 方法 |
| v0.4.0 | 新增多账户 Profile 功能，支持笔记本的账户隔离 |
| v0.5.0 | CLI UX 全面改进，包括笔记本命令的 `--json` 输出 |
| v0.6.0 | 异常层次结构对称性恢复 |
| v0.8.0 | `get()` 方法将抛出 `NotFoundError`（待发布） |

---

<a id='page-sources-artifacts'></a>

## 源与制品 API

### 相关页面

相关主题：[笔记本 API](#page-notebooks-api), [内容生成](#page-content-generation)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/notebooklm/_sources.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_sources.py)
- [src/notebooklm/_source_add.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_add.py)
- [src/notebooklm/_source_content.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_content.py)
- [src/notebooklm/_source_listing.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_listing.py)
- [src/notebooklm/_source_upload.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_upload.py)
- [src/notebooklm/_source_polling.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_polling.py)
- [src/notebooklm/_artifacts.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifacts.py)
- [src/notebooklm/_artifact_downloads.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_downloads.py)
- [src/notebooklm/_artifact_payloads.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_payloads.py)
- [src/notebooklm/_artifact_polling.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_polling.py)
- [src/notebooklm/_mind_map.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_mind_map.py)
- [src/notebooklm/cli/generate_cmd.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/cli/generate_cmd.py)
</details>

# 源与制品 API

## 概述

源与制品 API 是 notebooklm-py 库的核心功能模块，封装了 NotebookLM 的两大核心概念：**源（Source）**和**制品（Artifact）**。

- **源（Source）**：用户添加到笔记本的学习材料，支持 URL、YouTube、PDF、文本、Word、Markdown、EPUB、音频、视频、图片、Google Drive 等多种格式
- **制品（Artifact）**：基于源材料由 AI 生成的衍生内容，包括音频概览、视频概览、幻灯片、信息图、测验、闪卡、报告、数据表格和思维导图等

该 API 通过 `NotebookLMClient` 的 `sources` 和 `artifacts` 属性对外暴露，提供完整的异步操作能力。资料来源：[_sources.py:1-50](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_sources.py)，[_artifacts.py:1-60](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifacts.py)

---

## 源 API（Sources API）

### 功能范围

Sources API 负责管理笔记本中的所有学习材料，提供添加、列表、删除、刷新等操作，以及获取源的摘要和全文内容。资料来源：[_sources.py:50-150](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_sources.py)

### 支持的源类型

| 类型 | 说明 | 适用方法 |
|------|------|----------|
| URL | 网页链接 | `add_url()` |
| YouTube | YouTube 视频 | `add_youtube()` |
| PDF | PDF 文档 | `add_file()` |
| Text | 纯文本 | `add_text()` |
| Markdown | Markdown 文档 | `add_file()` |
| Word | .docx 文档 | `add_file()` |
| EPUB | 电子书格式 | `add_file()` |
| Audio | 音频文件 | `add_file()` |
| Video | 视频文件 | `add_file()` |
| Image | 图片文件 | `add_file()` |
| Google Drive | Drive 文件夹 | `add_drive()` |
| Pasted Text | 直接粘贴的文本 | `add_text()` |

### 核心方法

#### 添加源

```python
# 添加 URL
source = await client.sources.add_url(notebook_id, "https://example.com/article")

# 添加文本
source = await client.sources.add_text(notebook_id, "这里是文本内容", title="我的文本")

# 添加文件（自动检测类型）
source = await client.sources.add_file(notebook_id, "/path/to/document.pdf")

# 添加 YouTube 视频
source = await client.sources.add_youtube(notebook_id, "https://youtube.com/watch?v=...")

# 添加 Google Drive 源
source = await client.sources.add_drive(notebook_id, folder_id="...")
```

添加源操作内部会触发上传流程（对于文件）或爬取流程（对于 URL/YouTube），并通过轮询机制等待转换完成。资料来源：[_source_add.py:1-100](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_add.py)，[_source_upload.py:1-80](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_upload.py)

#### 获取源信息

```python
# 获取源详情
source = await client.sources.get(notebook_id, source_id)

# 获取源摘要（AI 生成的摘要和关键词）
guide = await client.sources.get_guide(notebook_id, source_id)
print(guide.summary)    # AI 生成的摘要（Markdown 格式，带加粗关键词）
print(guide.keywords)   # 主题关键词列表

# 获取源全文内容
fulltext = await client.sources.get_fulltext(
    notebook_id, 
    source_id, 
    output_format="markdown"  # 或 "text"
)
print(fulltext.content)
print(fulltext.char_count)
```

`get_guide()` 返回 `SourceGuide` 对象，包含 AI 生成的摘要（Markdown 格式，带加粗关键词）和关键词元组。`get_fulltext()` 支持 `text` 和 `markdown` 两种输出格式，Markdown 格式需要安装 `markdownify` 包。资料来源：[_source_content.py:1-100](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_content.py)

#### 源列表与刷新

```python
# 列出笔记本所有源
sources = await client.sources.list(notebook_id)

# 检查源是否需要刷新（URL/Drive 源）
is_fresh = await client.sources.check_freshness(notebook_id, source_id)

# 刷新源
await client.sources.refresh(notebook_id, source_id)

# 删除源
await client.sources.delete(notebook_id, source_id)
```

### 源上传流程

文件上传采用并发控制的管道机制，支持可恢复上传。流程如下：

```mermaid
graph TD
    A[add_file] --> B[检测文件类型]
    B --> C[构建上传载荷]
    C --> D[注册上传会话]
    D --> E{需要分片?}
    E -->|是| F[分片上传]
    E -->|否| G[单次上传]
    F --> H[轮询等待完成]
    G --> H
    H --> I[返回源信息]
```

上传服务通过信号量限制并发数，避免对 NotebookLM API 造成过大压力。资料来源：[_source_upload.py:80-200](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_upload.py)

---

## 制品 API（Artifacts API）

### 功能范围

Artifacts API 负责基于源材料生成和管理各类 AI 内容制品。这是 NotebookLM 区别于普通笔记工具的核心能力。资料来源：[_artifacts.py:60-150](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifacts.py)

### 制品类型

| 类型 | 说明 | 输出格式 |
|------|------|----------|
| **Audio Overview** | 音频概览，4种格式（深度讲解、简报、评论、辩论） | MP3/MP4 |
| **Video Overview** | 视频概览，3种格式（讲解、简报、电影感） | MP4 |
| **Slide Deck** | 幻灯片，支持详细或演示格式 | PDF, PPTX |
| **Infographic** | 信息图，3种方向、3种详细程度 | PNG |
| **Quiz** | 测验，可配置数量和难度 | JSON, Markdown, HTML |
| **Flashcards** | 闪卡，可配置数量和难度 | JSON, Markdown, HTML |
| **Report** | 报告（简报、学习指南、博客、自定义） | Markdown |
| **Data Table** | 数据表格，通过自然语言指定结构 | CSV |
| **Mind Map** | 思维导图，交互式层级可视化 | JSON |

### 生成制品

```python
# 生成音频概览
audio = await client.artifacts.generate_audio_overview(
    notebook_id,
    source_ids=["src_001", "src_002"],
    language="zh-CN",
    audio_format="deep_dive",  # 或 brief, critique, debate
    audio_length="long",       # 或 short, medium
    instructions="请用专业术语"
)

# 生成视频概览
video = await client.artifacts.generate_video_overview(
    notebook_id,
    source_ids=["src_001"],
    language="zh-CN",
    video_format="explainer"  # 或 brief, cinematic
)

# 生成幻灯片
slides = await client.artifacts.generate_slide_deck(
    notebook_id,
    source_ids=["src_001", "src_002"],
    slide_format="detailed",  # 或 presenter
    slide_length=15
)

# 生成报告
report = await client.artifacts.generate_report(
    notebook_id,
    source_ids=["src_001"],
    report_format="briefing_doc",  # 或 study_guide, blog_post
    instructions="请重点关注技术细节"
)

# 生成测验
quiz = await client.artifacts.generate_quiz(
    notebook_id,
    source_ids=["src_001"],
    quiz_count=10,
    difficulty="intermediate"
)

# 生成闪卡
flashcards = await client.artifacts.generate_flashcards(
    notebook_id,
    source_ids=["src_001"],
    card_count=20,
    difficulty="beginner"
)

# 生成思维导图
mind_map = await client.artifacts.generate_mind_map(
    notebook_id,
    source_ids=["src_001"]
)
```

所有生成方法均支持 `wait=True` 参数以等待完成，或通过 `timeout` 和 `interval` 控制轮询行为。资料来源：[_artifact_payloads.py:1-200](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_payloads.py)

### 下载制品

```python
# 下载音频为 MP3
output_path = await client.artifacts.download_audio(
    notebook_id,
    output_path="./audio.mp3",
    artifact_id="art_xxx"
)

# 下载幻灯片为 PPTX
output_path = await client.artifacts.download_slide_deck(
    notebook_id,
    output_path="./slides.pptx",
    artifact_id="art_xxx",
    output_format="pptx"
)

# 下载报告为 Markdown
output_path = await client.artifacts.download_report(
    notebook_id,
    output_path="./report.md",
    artifact_id="art_xxx"
)

# 下载思维导图为 JSON
output_path = await client.artifacts.download_mind_map(
    notebook_id,
    output_path="./mindmap.json",
    artifact_id="art_xxx"
)

# 批量下载
results = await client.artifacts.download_all_audio_overviews(notebook_id)
results = await client.artifacts.download_all_reports(notebook_id)
```

下载服务使用 `asyncio.to_thread()` 将文件写入操作卸载到线程池，避免阻塞事件循环。资料来源：[_artifact_downloads.py:1-150](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_downloads.py)

### 制品列表

```python
# 获取笔记本所有制品
artifacts = await client.artifacts.list(notebook_id)

# 按类型筛选
reports = await client.artifacts.list_reports(notebook_id)
audio_overviews = await client.artifacts.list_audio_overviews(notebook_id)
```

---

## 思维导图（Mind Maps）

思维导图是一种特殊的制品类型，支持两种后端模式：

1. **Note-backed 模式**：思维导图数据存储在笔记本笔记中
2. **Interactive 模式**：思维导图数据存储为独立的交互式制品

```python
# 获取思维导图 JSON 树
tree = await client.mind_maps.get_tree(notebook_id, mind_map_id)
print(tree.root)  # 根节点

# 重命名思维导图
await client.mind_maps.rename(notebook_id, mind_map_id, "新的标题")

# 删除思维导图
await client.mind_maps.delete(notebook_id, mind_map_id)

# 下载为 JSON
json_data = await client.mind_maps.to_json(notebook_id, mind_map_id)
```

> ⚠️ **API 设计注意**：当前 `rename()` 和 `get_tree()` 方法在找不到思维导图时会抛出原始 `ValueError`，而其他 API 一致地抛出 `*NotFoundError`。这是 v0.8.0 版本计划修复的 API 一致性问题。资料来源：[_mind_map.py:1-100](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_mind_map.py)，[#1291](https://github.com/teng-lin/notebooklm-py/issues/1291)

---

## 轮询机制

制品生成和源转换都是异步过程，需要通过轮询等待完成。库内置了两种轮询服务：

### 制品轮询（Artifact Polling）

```python
async def _poll_task_models(self, notebook_id: str) -> list[ResearchTask]:
    params = [None, None, notebook_id]
    result = await self._rpc.rpc_call(
        RPCMethod.POLL_RESEARCH,
        params,
        source_path=f"/notebook/{notebook_id}",
    )
    return parse_research_task_models(result)
```

### 源轮询（Source Polling）

用于跟踪文件上传和 URL 爬取的转换状态。资料来源：[_source_polling.py:1-80](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_source_polling.py)，[_artifact_polling.py:1-80](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_polling.py)

```mermaid
graph LR
    A[开始生成] --> B{等待完成?}
    B -->|是| C[轮询状态]
    C --> D{完成?}
    D -->|否| C
    D -->|是| E[返回制品]
    B -->|否| F[返回待处理状态]
```

---

## 错误处理

### 异常层次结构

v0.6.0 版本恢复了异常层次结构的对称性，`SourceNotFoundError` 和 `ArtifactNotFoundError` 现在同时继承自 `RPCError` 和各自的领域基类：

```python
# 异常继承链
RPCError
├── SourceNotFoundError (继承自 RPCError + SourceError)
├── ArtifactNotFoundError (继承自 RPCError + ArtifactError)
└── NotebookNotFoundError (继承自 RPCError)

SourceError
├── SourceNotFoundError
└── SourceParseError

ArtifactError
├── ArtifactNotFoundError
└── ArtifactParseError
```

### v0.7.0 → v0.8.0 迁移

从 v0.7.0 开始，`get()` 方法在实体不存在时返回 `None` 并发出弃用警告，计划在 v0.8.0 中切换为抛出 `*NotFoundError`。资料来源：[_sources.py:100-150](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_sources.py)，[#1247](https://github.com/teng-lin/notebooklm-py/issues/1247)

```python
# v0.7.0（当前）
source = await client.sources.get(notebook_id, source_id)
# 不存在时返回 None 并警告

# v0.8.0（计划）
source = await client.sources.get(notebook_id, source_id)
# 不存在时抛出 SourceNotFoundError
```

---

## CLI 集成

### 生成命令

通过 CLI 生成制品：

```bash
# 生成报告
notebooklm generate report
notebooklm generate report --format study-guide
notebooklm generate report -s src_001 -s src_002

# 生成音频概览
notebooklm generate audio --language zh-CN --format deep-dive

# 生成思维导图
notebooklm generate mind-map

# 等待完成
notebooklm generate report --wait --timeout 300
```

### 下载命令

```bash
# 下载各种制品
notebooklm download report <output_path>
notebooklm download audio <output_path>
notebooklm download flashcards <output_path> --format json

# 批量下载
notebooklm download all-reports ./reports/
```

资料来源：[cli/generate_cmd.py:1-100](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/cli/generate_cmd.py)

---

## 使用示例

### 完整工作流

```python
import asyncio
from notebooklm import NotebookLMClient

async def main():
    # 创建客户端
    async with NotebookLMClient.from_storage() as client:
        # 创建笔记本
        notebook = await client.notebooks.create("我的研究笔记本")
        notebook_id = notebook.id
        
        # 添加多个源
        url_source = await client.sources.add_url(
            notebook_id, 
            "https://example.com/article"
        )
        file_source = await client.sources.add_file(
            notebook_id, 
            "./research.pdf"
        )
        
        # 获取源摘要
        guide = await client.sources.get_guide(notebook_id, url_source.id)
        print(f"摘要: {guide.summary}")
        print(f"关键词: {guide.keywords}")
        
        # 生成多种制品
        report = await client.artifacts.generate_report(
            notebook_id,
            source_ids=[url_source.id, file_source.id],
            report_format="study_guide",
            wait=True,
            timeout=600
        )
        
        # 下载报告
        report_path = await client.artifacts.download_report(
            notebook_id,
            output_path="./study_guide.md",
            artifact_id=report.id
        )
        
        # 生成并下载思维导图
        mind_map = await client.artifacts.generate_mind_map(
            notebook_id,
            source_ids=[url_source.id],
            wait=True
        )
        json_path = await client.artifacts.download_mind_map(
            notebook_id,
            output_path="./mindmap.json",
            artifact_id=mind_map.id
        )
        
        print(f"报告已保存: {report_path}")
        print(f"思维导图已保存: {json_path}")

asyncio.run(main())
```

---

## 相关链接

- [CLI 命令参考](./cli-commands.md)
- [认证与存储](./authentication.md)
- [研究 API](./research-api.md)
- [异常处理](./error-handling.md)

---

<a id='page-content-generation'></a>

## 内容生成

### 相关页面

相关主题：[源与制品 API](#page-sources-artifacts)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/notebooklm/_generate.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_generate.py)
- [src/notebooklm/_artifact_polling.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_polling.py)
- [src/notebooklm/_mind_maps_api.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_mind_maps_api.py)
- [src/notebooklm/cli/generate_cmd.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/cli/generate_cmd.py)
- [src/notebooklm/_artifact_payloads.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_payloads.py)
- [src/notebooklm/cli/_download_specs.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/cli/_download_specs.py)
- [src/notebooklm/cli/services/generate.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/cli/services/generate.py)
- [src/notebooklm/_artifact_downloads.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_artifact_downloads.py)
</details>

# 内容生成

内容生成是 notebooklm-py 库的核心功能模块，允许用户通过 API 或 CLI 为笔记本中的来源资料生成多种格式的 AI 辅助内容。该系统封装了 NotebookLM 的底层 RPC 接口，提供统一的异步生成和轮询机制。

## 功能概述

内容生成模块支持生成以下类型的内容制品（Artifacts）：

| 类型 | 格式选项 | 下载格式 | 说明 |
|------|----------|----------|------|
| 音频概览 (Audio Overview) | deep-dive, brief, critique, debate | MP3/MP4 | 4种风格，3种长度，50+语言 |
| 视频概览 (Video Overview) | explainer, brief, cinematic | MP4 | 3种格式，9种视觉风格 |
| 幻灯片 (Slide Deck) | detailed, presenter | PDF, PPTX | 可调整长度，支持单页修订 |
| 信息图 (Infographic) | 3种方向 | PNG | 3种详细级别 |
| 测验 (Quiz) | 可配置数量和难度 | JSON, Markdown, HTML | - |
| 闪卡 (Flashcards) | 可配置数量和难度 | JSON, Markdown, HTML | - |
| 报告 (Report) | briefing doc, study guide, blog post, custom | Markdown | 支持自定义提示词追加 |
| 数据表 (Data Table) | 自然语言指定结构 | CSV | - |
| 思维导图 (Mind Map) | 交互式层级可视化 | JSON | 支持重命名和树形数据提取 |

## 架构设计

### 核心组件关系

```mermaid
graph TD
    A[客户端 API] --> B[ArtifactsAPI]
    B --> C[生成请求构建]
    C --> D[RPC 调用层]
    D --> E[Artifact Polling 服务]
    E --> F[轮询循环]
    F -->|未完成| E
    F -->|完成| G[结果解析]
    G --> H[下载管理]
    
    I[MindMapsAPI] --> J[思维导图专用接口]
    J --> K[JSON 树导出]
```

### 模块职责划分

| 模块 | 职责 |
|------|------|
| `_generate.py` | 核心生成逻辑，RPC 方法调用封装 |
| `_artifact_polling.py` | 异步生成任务的轮询协调服务 |
| `_artifact_payloads.py` | 各类型内容的请求参数构建 |
| `_artifact_downloads.py` | 制品下载和本地文件保存 |
| `_mind_maps_api.py` | 思维导图专用 API |

## API 层

### 客户端初始化

通过 `NotebookLMClient` 访问生成功能：

```python
from notebooklm import NotebookLMClient

async with NotebookLMClient.from_storage() as client:
    # 创建笔记本
    notebook = await client.notebooks.create(title="研究项目")
    
    # 添加来源
    await client.sources.add_url(notebook.id, "https://example.com/article")
    
    # 生成内容
    artifacts = await client.artifacts.generate_audio_overview(
        notebook.id,
        source_ids=[...],
        language="zh"
    )
```

### 主要生成方法

#### 音频概览生成

```python
artifacts = await client.artifacts.generate_audio_overview(
    notebook_id: str,
    source_ids: list[str],
    language: str = "en",
    audio_format: AudioFormat | None = None,  # DEEP_DIVE, BRIEF, CRITIQUE, DEBATE
    audio_length: AudioLength | None = None,  # SHORT, DEFAULT, LONG
    instructions: str | None = None,
    wait: bool = False,  # 是否等待完成
)
```

资料来源：[src/notebooklm/_generate.py:80-120]()

#### 视频概览生成

```python
artifacts = await client.artifacts.generate_video_overview(
    notebook_id: str,
    source_ids: list[str],
    language: str = "en",
    video_format: VideoFormat | None = None,  # EXPLAINER, BRIEF, CINEMATIC
    video_style: VideoStyle | None = None,    # AUTO_SELECT, CLASSIC, WHITEBOARD, etc.
    instructions: str | None = None,
    wait: bool = False,
)
```

#### 报告生成

```python
artifacts = await client.artifacts.generate_report(
    notebook_id: str,
    source_ids: list[str] | None = None,
    report_format: ReportFormat = ReportFormat.BRIEFING_DOC,
    description: str | None = None,
    append_instructions: str | None = None,  # 追加到模板的自定义指令
    language: str = "en",
    wait: bool = False,
)
```

资料来源：[src/notebooklm/cli/generate_cmd.py:45-70]()

#### 幻灯片生成

```python
artifacts = await client.artifacts.generate_slide_deck(
    notebook_id: str,
    source_ids: list[str] | None = None,
    slide_format: SlideFormat = SlideFormat.DETAILED,
    slide_count: int | None = None,
    language: str = "en",
    wait: bool = False,
)
```

#### 思维导图生成与管理

```python
# 生成思维导图
mind_maps = await client.mind_maps.list(notebook_id)

# 重命名思维导图
await client.mind_maps.rename(notebook_id, mind_map_id, new_title)

# 获取思维导树数据
tree_data = await client.mind_maps.get_tree(notebook_id, mind_map_id)

# 下载为 JSON
json_path = await client.artifacts.download_mind_map(
    notebook_id,
    output_path="./mind_map.json",
    artifact_id=mind_map_id
)
```

## CLI 命令

### 生成命令组

```bash
notebooklm generate <type> [OPTIONS]
```

| 子命令 | 说明 |
|--------|------|
| `notebooklm generate audio` | 生成音频概览 |
| `notebooklm generate video` | 生成视频概览 |
| `notebooklm generate report` | 生成报告文档 |
| `notebooklm generate slides` | 生成幻灯片 |
| `notebooklm generate flashcards` | 生成闪卡 |
| `notebooklm generate quiz` | 生成测验 |
| `notebooklm generate infographic` | 生成信息图 |
| `notebooklm generate mind-map` | 生成思维导图 |

### 通用参数

| 参数 | 说明 |
|------|------|
| `-s, --source` | 指定来源 ID（可多次使用） |
| `-l, --language` | 输出语言（默认: en） |
| `--json` | 机器可读 JSON 输出 |
| `--wait` | 等待生成完成 |
| `--timeout` | 最大等待时间（秒） |

### 示例

```bash
# 生成 briefing 报告
notebooklm generate report --format briefing-doc

# 生成学习指南并追加自定义指令
notebooklm generate report --format study-guide --append "目标受众: 初级"

# 生成音频概览
notebooklm generate audio --format brief --language zh

# 生成幻灯片
notebooklm generate slides --count 15 --format presenter

# 生成思维导图
notebooklm generate mind-map
```

资料来源：[src/notebooklm/cli/generate_cmd.py:30-75]()

### 下载命令

```bash
notebooklm download <type> [OPTIONS] [OUTPUT_PATH]
```

支持下载所有生成的内容类型：

```bash
notebooklm download audio output/audio.mp3
notebooklm download video output/video.mp4
notebooklm download report report.md
notebooklm download slides --format pdf slides.pdf
notebooklm download flashcards --format json cards.json
notebooklm download flashcards --format html cards.html
```

资料来源：[src/notebooklm/cli/_download_specs.py:1-80]()

## 异步轮询机制

生成任务是异步执行的，系统使用轮询机制监控任务状态。

### 轮询流程

```mermaid
sequenceDiagram
    participant C as 客户端
    participant P as Polling 服务
    participant API as NotebookLM API
    
    C->>P: 发起生成请求
    P->>API: 创建任务，获取 task_id
    loop 轮询循环
        P->>API: poll_research(task_id)
        alt 任务进行中
            API-->>P: PENDING
        else 任务完成
            API-->>P: COMPLETED + result
        end
    end
    P-->>C: 返回生成结果
```

### 配置参数

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `wait` | 是否等待生成完成 | `False` |
| `timeout` | 最大等待时间（秒） | `600` |
| `interval` | 轮询间隔（秒） | `5` |
| `max_retries` | 最大重试次数 | `3` |

### 轮询核心实现

```python
async def _poll_task_models(self, notebook_id: str) -> list[ResearchTask]:
    """轮询任务模型状态"""
    params = [None, None, notebook_id]
    result = await self._rpc.rpc_call(
        RPCMethod.POLL_RESEARCH,
        params,
        source_path=f"/notebook/{notebook_id}",
    )
    return parse_research_task_models(result)
```

资料来源：[src/notebooklm/_research.py:60-75]()

## 请求参数构建

每种内容类型都有专用的参数构建函数：

### 音频参数构建

```python
def build_audio_artifact_params(
    notebook_id: str,
    source_ids: list[str],
    *,
    language: str,
    instructions: str | None,
    audio_format: AudioFormat | None,
    audio_length: AudioLength | None,
) -> list[Any]:
    """构建音频生成的 RPC 参数"""
    source_ids_triple = nest_source_ids(source_ids, 2)
    source_ids_double = nest_source_ids(source_ids, 1)
    
    format_code = audio_format.value if audio_format else AudioFormat.DEEP_DIVE.value
    length_code = audio_length.value if audio_length else AudioLength.DEFAULT.value
    
    return [
        [2],
        notebook_id,
        [
            None, None, ArtifactTypeCode.AUDIO.value,
            source_ids_triple,
            None, None,
            [
                None,
                [instructions, length_code, None, source_ids_double, language, None, format_code],
            ],
        ],
    ]
```

资料来源：[src/notebooklm/_artifact_payloads.py:80-120]()

### 格式映射表

```python
_AUDIO_FORMAT_MAP = {
    "deep-dive": AudioFormat.DEEP_DIVE,
    "brief": AudioFormat.BRIEF,
    "critique": AudioFormat.CRITIQUE,
    "debate": AudioFormat.DEBATE,
}

_VIDEO_FORMAT_MAP = {
    "explainer": VideoFormat.EXPLAINER,
    "brief": VideoFormat.BRIEF,
    "cinematic": VideoFormat.CINEMATIC,
}

_VIDEO_STYLE_MAP = {
    "auto": VideoStyle.AUTO_SELECT,
    "classic": VideoStyle.CLASSIC,
    "whiteboard": VideoStyle.WHITEBOARD,
    "kawaii": VideoStyle.KAWAII,
    "anime": VideoStyle.ANIME,
    "watercolor": VideoStyle.WATERCOLOR,
}
```

资料来源：[src/notebooklm/cli/services/generate.py:30-70]()

## 下载管理

### 本地文件保存

生成完成后可通过下载接口保存到本地：

```python
# 下载音频/视频
audio_path = await client.artifacts.download_audio(
    notebook_id,
    output_path="./audio.mp3",
    artifact_id=artifact_id
)

# 下载幻灯片
slides_path = await client.artifacts.download_slides(
    notebook_id,
    output_path="./slides.pdf",
    format="pdf",
    artifact_id=artifact_id
)

# 下载报告
report_path = await client.artifacts.download_report(
    notebook_id,
    output_path="./report.md",
    artifact_id=artifact_id
)

# 下载思维导图
mind_map_path = await client.artifacts.download_mind_map(
    notebook_id,
    output_path="./mind_map.json",
    artifact_id=artifact_id
)
```

### 下载实现核心

```python
async def download_mind_map(
    self,
    notebook_id: str,
    output_path: str,
    artifact_id: str | None = None,
) -> str:
    """下载思维导图为 JSON 格式"""
    mind_maps_service = self._mind_maps
    
    # 首先获取笔记支持的思维导图列表
    mind_maps = await mind_maps_service.list_mind_maps(notebook_id)
    
    # 根据 ID 选择目标导图
    # ...
    
    # 异步写入文件
    def _write_json() -> None:
        output.write_text(json_data, encoding="utf-8")
    
    await asyncio.to_thread(_write_json)
    return str(output)
```

资料来源：[src/notebooklm/_artifact_downloads.py:150-200]()

## 异常处理

### 常见异常类型

| 异常 | 说明 |
|------|------|
| `ArtifactNotFoundError` | 制品不存在 |
| `ArtifactParseError` | 制品解析失败 |
| `GenerationTimeoutError` | 生成超时 |
| `NotebookNotFoundError` | 笔记本不存在 |
| `SourceNotFoundError` | 来源不存在 |
| `UnknownRPCMethodError` | 未知 RPC 方法 |

### 异常继承关系

v0.6.0 恢复了异常层次对称性：

```
RPCError
├── NotebookNotFoundError
├── SourceNotFoundError  ← 继承自 RPCError
└── ArtifactNotFoundError  ← 继承自 RPCError
```

资料来源：[v0.6.0 Release Notes](https://github.com/teng-lin/notebooklm-py/releases/tag/v0.6.0)

## 最佳实践

### 异步等待模式

```python
# 方式1: 客户端轮询
artifacts = await client.artifacts.generate_report(
    notebook.id,
    wait=False  # 立即返回，后续轮询
)
# 手动轮询
for attempt in range(60):
    artifacts = await client.artifacts.list(notebook.id)
    if artifacts:
        break
    await asyncio.sleep(5)

# 方式2: 服务端等待
artifacts = await client.artifacts.generate_report(
    notebook.id,
    wait=True,
    timeout=300  # 最多等待5分钟
)
```

### 批量生成

```python
# 批量生成不同格式的报告
formats = [
    ReportFormat.BRIEFING_DOC,
    ReportFormat.STUDY_GUIDE,
    ReportFormat.BLOG_POST,
]

tasks = [
    client.artifacts.generate_report(notebook.id, report_format=f, wait=True)
    for f in formats
]

reports = await asyncio.gather(*tasks)
```

### 来源过滤

```python
# 只使用特定来源生成
sources = await client.sources.list(notebook.id)
pdf_sources = [s for s in sources if s.kind == "pdf"]
source_ids = [s.id for s in pdf_sources]

audio = await client.artifacts.generate_audio_overview(
    notebook.id,
    source_ids=source_ids
)
```

## 相关文档

- [API 参考](../api/client.md) - 完整的客户端 API 文档
- [CLI 使用指南](../cli/commands.md) - 命令行工具详细用法
- [异常处理](../api/exceptions.md) - 异常类型和处理方式
- [认证与授权](./auth.md) - 身份验证配置

---

<a id='page-auth-cookie-lifecycle'></a>

## 认证与 Cookie 生命周期

### 相关页面

相关主题：[快速开始](#page-quickstart), [多账户与配置文件](#page-multi-profile), [中间件链](#page-middleware-chain)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/notebooklm/auth.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/auth.py)
- [src/notebooklm/_auth/extraction.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_auth/extraction.py)
- [src/notebooklm/_auth/cookies.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_auth/cookies.py)
- [src/notebooklm/_auth/cookie_policy.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_auth/cookie_policy.py)
- [src/notebooklm/_auth/paths.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_auth/paths.py)
- [examples/refresh_browser_cookies.py](https://github.com/teng-lin/notebooklm-py/blob/main/examples/refresh_browser_cookies.py)
- [docs/auth-cookie-lifecycle.md](https://github.com/teng-lin/notebooklm-py/blob/main/docs/auth-cookie-lifecycle.md)
</details>

# 认证与 Cookie 生命周期

本文档介绍 notebooklm-py 的认证系统架构、Cookie 生命周期管理、多账户支持以及认证刷新技术方案。

## 概述

notebooklm-py 通过浏览器 Cookie 实现对 Google NotebookLM 服务的认证。认证系统负责提取、存储、验证和刷新 Cookie 凭证，确保客户端能够与 NotebookLM 后端保持持续的 RPC 通信。

**核心功能模块**：

| 模块 | 职责 |
|------|------|
| `auth.py` | 认证门面，暴露公共 API |
| `_auth/extraction.py` | HTML 页面中的 WIZ_global_data 解析 |
| `_auth/cookies.py` | Cookie 数据结构与序列化 |
| `_auth/cookie_policy.py` | Cookie 验证策略 |
| `_auth/paths.py` | 多账户存储路径管理 |

## 认证架构

### 整体架构图

```mermaid
graph TD
    A[用户浏览器] --> B[Cookie 提取]
    B --> C[WIZ_global_data 解析]
    C --> D[CSRF Token + Session ID]
    D --> E[AuthTokens 数据结构]
    E --> F[持久化存储]
    F --> G[NotebookLMClient]
    G --> H[RPC 调用]
    
    I[Playwright 浏览器] -->|自动化刷新| B
    J[外部刷新命令] -->|NOTEBOOKLM_REFRESH_CMD| K[刷新钩子]
    K --> D
```

### 关键数据类型

认证系统的核心数据结构为 `AuthTokens`，包含以下字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `cookies` | `dict[str, str]` | 浏览器 Cookie 字典 |
| `csrf_token` | `str` | CSRF 令牌（SNlM0e） |
| `session_id` | `str` | 会话标识符（FdrFJe） |

资料来源：[src/notebooklm/auth.py]()

## Cookie 提取机制

### WIZ_global_data 解析

NotebookLM（及 Google 其他产品）在页面 HTML 中嵌入 JavaScript 对象字面量 `WIZ_global_data`。所需的认证令牌（CSRF 和 Session ID）存储在此对象中。

```mermaid
graph LR
    A[HTML 页面源码] --> B[正则表达式匹配]
    B --> C[JSON 解析]
    C --> D[WIZ_global_data 对象]
    D --> E[提取 SNlM0e → CSRF]
    D --> F[提取 FdrFJe → Session ID]
```

### 提取优先级

`extraction.py` 中的 `_build_wiz_field_patterns` 函数定义了三种匹配优先级：

| 优先级 | 格式 | 示例 |
|--------|------|------|
| 1 | 双引号包裹 | `"value"` |
| 2 | 单引号包裹 | `'value'` |
| 3 | HTML 转义 | `&quot;value&quot;` |

资料来源：[src/notebooklm/_auth/extraction.py]()

### 公共提取 API

| 函数 | 说明 |
|------|------|
| `extract_wiz_field(html, key)` | 通用 WIZ_global_data 字段提取器 |
| `extract_csrf_from_html(html)` | 提取 CSRF 令牌（SNlM0e） |
| `extract_session_id_from_html(html)` | 提取会话 ID（FdrFJe） |

## 认证存储与生命周期

### 存储路径

认证数据按多账户 profile 组织，存储路径结构如下：

```
~/.notebooklm/
└── profiles/
    └── <profile_name>/
        └── auth.json       # 加密存储的凭证
```

| 环境变量 | CLI 参数 | 说明 |
|----------|----------|------|
| `NOTEBOOKLM_PROFILE` | `--profile` / `-p` | 指定使用的账户 profile |
| - | `notebooklm profile` | 管理多个 profile |

资料来源：[src/notebooklm/_auth/paths.py]()

### Cookie 策略验证

`cookie_policy.py` 实现 Cookie 有效性检查，包括：

- **过期检测**：验证 PSIDTS 等时间戳字段
- **完整性检查**：确保必需的 Cookie 字段存在
- **一致性验证**：CSRF 和 Session ID 必须同时存在

资料来源：[src/notebooklm/_auth/cookie_policy.py]()

## 多账户支持

### Profile 管理命令

```bash
# 创建新账户 profile
notebooklm profile create <profile_name>

# 列出所有 profile
notebooklm profile list

# 切换默认 profile
notebooklm profile switch <profile_name>

# 重命名 profile
notebooklm profile rename <old_name> <new_name>

# 删除 profile
notebooklm profile delete <profile_name>
```

### 认证门面

`auth.py` 模块提供了几乎纯重导出（仅 `enumerate_accounts` 函数有实际逻辑）：

```python
# 主要导出
from notebooklm.auth import (
    AuthTokens,        # 认证数据结构
    AuthError,        # 认证异常基类
    AuthExtractionError,  # 提取失败异常
    extract_wiz_field,
    extract_csrf_from_html,
    extract_session_id_from_html,
)
```

资料来源：[src/notebooklm/auth.py]()

## 认证刷新机制

### 社区需求

根据社区反馈（Issue #297），Google SID Cookie 频繁过期导致长时运行的工作流（如 cron jobs、tmux 会话、Claude Code agents）频繁中断，需要人工干预重新执行 `notebooklm login`。

### 刷新机制概览

```mermaid
graph TD
    A[检测到认证过期] --> B{NOTEBOOKLM_REFRESH_CMD 设置?}
    B -->|是| C[执行自定义刷新脚本]
    B -->|否| D[提示用户运行 notebooklm login]
    
    E[notebooklm auth refresh] --> F[Playwright 自动化]
    F --> G[打开 Google 登录页]
    G --> H[自动填充凭证]
    H --> I[提取新 Cookie]
    I --> J[更新本地存储]
```

### 自动刷新配置

| 配置项 | 说明 |
|--------|------|
| `NOTEBOOKLM_REFRESH_CMD` | 外部 Cookie 刷新脚本路径 |
| `keepalive=` | Client 构造参数，控制保活间隔 |

### Playwright 自动化刷新

`examples/refresh_browser_cookies.py` 提供了基于 Playwright 的自动化刷新示例：

```python
# 核心流程
1. 启动 Playwright Chromium 浏览器
2. 导航至 Google 登录页面
3. 自动填写保存的凭据（可选）
4. 完成 2FA 认证（需要人工交互）
5. 导航至 NotebookLM 页面
6. 提取更新后的 Cookie
7. 保存到对应 profile
```

## 客户端认证集成

### NotebookLMClient 构造参数

```python
from notebooklm import NotebookLMClient, AuthTokens

# 方式一：从存储加载
async with NotebookLMClient.from_storage() as client:
    ...

# 方式二：直接传入 AuthTokens
client = NotebookLMClient(
    auth=AuthTokens(cookies, csrf_token, session_id),
    keepalive=300.0,  # 5分钟保活
    keepalive_min_interval=60.0,
)
```

### 认证错误处理

| 异常类型 | 继承关系 | 触发场景 |
|----------|----------|----------|
| `AuthError` | `Exception` | 认证基类错误 |
| `AuthExtractionError` | `AuthError` | Cookie 提取失败 |
| `NotebookNotFoundError` | `RPCError`, `NotebookError` | Notebook 操作错误 |

v0.6.0 恢复了异常层次结构对称性，`SourceNotFoundError` 和 `ArtifactNotFoundError` 现在同时继承自 `RPCError` 和各自领域基类。

## 版本演进

| 版本 | 关键变更 |
|------|----------|
| v0.4.0 | 多账户 profiles 功能引入 |
| v0.4.1 | `notebooklm auth refresh` CLI 命令、`keepalive=` 参数、`NOTEBOOKLM_REFRESH_CMD` 环境变量 |
| v0.5.0 | 认证和 Cookie 可靠性加固、PSIDTS 冷启动恢复、fail-closed `notebooklm use` |
| v0.6.0 | 异常层次结构对称性恢复 |

## 最佳实践

### 安全建议

1. **保护认证文件**：存储路径应设置适当的文件系统权限
2. **定期刷新**：使用 `notebooklm auth refresh` 或配置外部刷新脚本
3. **Profile 隔离**：不同用途使用不同 profile，避免凭证混淆

### 故障排查

| 问题 | 可能原因 | 解决方案 |
|------|----------|----------|
| 认证过期频繁 | PSIDTS 生命周期短 | 配置 `NOTEBOOKLM_REFRESH_CMD` 自动化刷新 |
| Cookie 提取失败 | HTML 结构变化 | 更新 extraction.py 正则表达式 |
| Profile 切换无效 | 路径权限问题 | 检查 `~/.notebooklm/profiles/` 目录权限 |

## 相关文档

- [安装指南](docs/installation.md)
- [CLI 使用指南](src/notebooklm/cli/)
- [API 参考](src/notebooklm/client.py)
- [Cookie 生命周期详解](docs/auth-cookie-lifecycle.md)

---

<a id='page-multi-profile'></a>

## 多账户与配置文件

### 相关页面

相关主题：[认证与 Cookie 生命周期](#page-auth-cookie-lifecycle)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/notebooklm/_auth/paths.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_auth/paths.py)
- [src/notebooklm/paths.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/paths.py)
- [src/notebooklm/_atomic_io.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_atomic_io.py)
- [src/notebooklm/cli/profile_cmd.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/cli/profile_cmd.py)
- [src/notebooklm/notebooklm_cli.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/notebooklm_cli.py)
- [docs/configuration.md](https://github.com/teng-lin/notebooklm-py/blob/main/docs/configuration.md)
</details>

# 多账户与配置文件

## 概述

多账户与配置文件系统是 notebooklm-py v0.4.0 引入的核心功能，旨在解决用户在多个 Google 账户之间切换的需求。该系统允许用户创建、管理和切换不同的配置文件，每个配置文件拥有独立的认证状态、存储路径和会话数据，从而实现无需重复登录认证的多账户工作流。

该功能主要解决了以下使用场景：
- 在个人和工作 Google 账户之间快速切换
- 为不同的项目或客户维护独立的认证状态
- 在自动化脚本中针对特定账户运行命令
- 共享同一台机器的多用户场景

资料来源：[v0.4.0 发行说明](https://github.com/teng-lin/notebooklm-py/releases/tag/v0.4.0)

## 架构设计

### 存储结构

配置文件采用层级化的目录结构存储在用户主目录下。每个配置文件拥有独立的数据存储空间，确保账户间的数据完全隔离。

```
~/.notebooklm/
├── config.toml              # 全局配置（当前激活的配置文件等）
├── profiles/
│   ├── default/             # 默认配置文件
│   │   ├── auth/
│   │   │   ├── cookies.json
│   │   │   └── tokens.json
│   │   └── cache/
│   └── work/                # 工作配置文件
│       ├── auth/
│       │   ├── cookies.json
│       │   └── tokens.json
│       └── cache/
```

配置文件存储路径由 `paths.py` 模块中的函数统一管理，核心路径计算逻辑如下：

```python
# src/notebooklm/paths.py
def profile_storage_path(profile_name: str | None = None) -> Path:
    """返回指定配置文件的存储根目录。"""
    root = _storage_root()
    if profile_name is None:
        profile_name = _resolve_active_profile_name()
    return root / "profiles" / profile_name
```

资料来源：[src/notebooklm/paths.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/paths.py)

### 核心组件

| 组件 | 文件位置 | 职责 |
|------|----------|------|
| 路径管理 | `_auth/paths.py` | 配置文件路径解析、存储根目录定位 |
| 原子IO | `_atomic_io.py` | 配置文件的安全读写操作 |
| CLI命令 | `cli/profile_cmd.py` | profile 子命令实现 |
| CLI入口 | `notebooklm_cli.py` | 全局参数注册和命令注册 |

资料来源：[src/notebooklm/_auth/paths.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_auth/paths.py)

### 数据流图

```mermaid
graph TD
    A[用户命令] --> B{--profile 参数?}
    B -->|是| C[解析指定配置文件名]
    B -->|否| D{NOTEBOOKLM_PROFILE 环境变量?}
    D -->|是| E[读取环境变量]
    D -->|否| F[使用默认配置 default]
    C --> G[计算配置文件路径]
    E --> G
    F --> G
    G --> H[加载配置文件]
    H --> I[初始化认证会话]
    I --> J[执行用户命令]
```

## CLI 命令接口

### profile 子命令组

配置文件管理通过 `notebooklm profile` 子命令组提供，包含以下操作：

| 命令 | 说明 |
|------|------|
| `notebooklm profile create <name>` | 创建新的配置文件 |
| `notebooklm profile list` | 列出所有已存在的配置文件 |
| `notebooklm profile switch <name>` | 切换默认配置文件 |
| `notebooklm profile rename <old> <new>` | 重命名配置文件 |
| `notebooklm profile delete <name>` | 删除配置文件 |

资料来源：[v0.4.0 发行说明](https://github.com/teng-lin/notebooklm-py/releases/tag/v0.4.0)

### 全局参数

除专门的 profile 子命令外，所有 CLI 命令都支持通过全局参数指定配置文件：

| 参数 | 简写 | 说明 |
|------|------|------|
| `--profile <name>` | `-p <name>` | 指定目标配置文件 |
| `NOTEBOOKLM_PROFILE` | - | 环境变量方式指定配置文件 |

全局参数的注册和解析在 `notebooklm_cli.py` 中完成，确保在任何子命令执行前正确加载对应配置文件的认证状态。

资料来源：[src/notebooklm/notebooklm_cli.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/notebooklm_cli.py)

## 使用方式

### 创建配置文件

首次使用时，系统自动创建名为 `default` 的配置文件。用户可通过以下命令创建新的配置文件：

```bash
# 创建名为 work 的配置文件
notebooklm profile create work

# 创建后自动切换到新配置
notebooklm profile create client-a
notebooklm use  # 在新配置中登录
```

### 切换配置文件

有三种方式切换当前使用的配置文件：

**方式一：使用 switch 命令**
```bash
notebooklm profile switch work
```

**方式二：使用全局参数**
```bash
notebooklm --profile work notebooks list
```

**方式三：设置环境变量**
```bash
export NOTEBOOKLM_PROFILE=work
notebooklm notebooks list
```

### 删除配置文件

```bash
# 删除前会提示确认
notebooklm profile delete old-profile

# 强制删除（跳过确认）
notebooklm profile delete old-profile --yes
```

## 认证与 Cookie 管理

配置文件的核心价值在于隔离不同 Google 账户的认证状态。每个配置文件独立管理：

- **Cookie 文件** (`cookies.json`)：存储 Google SID 等会话 cookie
- **Token 文件** (`tokens.json`)：存储 CSRF token 和 session ID
- **缓存数据**：各 API 调用的临时缓存

这种隔离机制使得：
1. 用户可以在多个 Google 账户间快速切换，无需重复登录
2. 自动化脚本可以针对特定账户运行
3. 共享机器的多用户可以各自维护独立的认证状态

资料来源：[README.md - Beyond the Web UI](https://github.com/teng-lin/notebooklm-py/blob/main/README.md)

## 配置优先级

当存在多个配置文件指定方式时，系统按以下优先级（从高到低）确定使用的配置文件：

```mermaid
graph LR
    A["--profile / -p 参数"] --> B[优先级最高]
    C["NOTEBOOKLM_PROFILE 环境变量"] --> D[优先级其次]
    E["默认配置文件 default"] --> F[优先级最低]
```

## 原子性操作保障

配置文件操作涉及敏感的用户数据，因此 `_atomic_io.py` 模块提供了原子性读写机制：

- **写操作**：先写入临时文件，成功后原子替换目标文件
- **读操作**：检测文件完整性，避免读取损坏的配置
- **并发安全**：使用文件锁防止并发写入冲突

```python
# src/notebooklm/_atomic_io.py 核心模式
def write_config_atomic(path: Path, data: str) -> None:
    temp_path = path.with_suffix('.tmp')
    temp_path.write_text(data)
    temp_path.replace(path)  # 原子替换
```

资料来源：[src/notebooklm/_atomic_io.py](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_atomic_io.py)

## 最佳实践

### 脚本中的配置文件使用

在自动化脚本中推荐使用全局参数方式，避免环境变量污染：

```bash
#!/bin/bash
# 为不同客户运行报告生成
notebooklm --profile client-a generate report -s src_001
notebooklm --profile client-b generate report -s src_002
```

### CI/CD 集成

在 CI 环境中，可通过环境变量注入配置文件路径：

```yaml
# .github/workflows/ci.yml 示例
env:
  NOTEBOOKLM_PROFILE: ci-runner
  NOTEBOOKLM_REFRESH_CMD: ./scripts/refresh_auth.sh
```

### 配置文件备份

配置文件位于 `~/.notebooklm/profiles/` 目录，可直接备份：

```bash
# 备份所有配置
cp -r ~/.notebooklm/profiles ~/backup/profiles.bak

# 恢复配置
cp -r ~/backup/profiles.bak ~/.notebooklm/profiles
```

## 相关议题

社区反馈中与多账户功能相关的问题：

| 议题 | 说明 | 优先级 |
|------|------|--------|
| [#297](https://github.com/teng-lin/notebooklm-py/issues/297) | 认证过期UX：允许用户接入 cookie 刷新钩子，避免频繁重新登录 | 高 |
| v0.4.1 | 引入 `NOTEBOOKLM_REFRESH_CMD` 环境变量，支持自定义刷新命令 | 已解决 |

议题 #297 反映了用户对认证状态管理的持续关注，特别是长时间运行的自动化工作流中 cookie 过期的问题。多账户系统虽然解决了账户切换问题，但认证过期的根本问题仍需通过 cookie 刷新机制进一步优化。

资料来源：[社区问题 #297](https://github.com/teng-lin/notebooklm-py/issues/297)

## 参见

- [安装指南](../installation.md) - 完整的安装和初始配置说明
- [认证系统](../authentication.md) - Cookie 和认证状态管理详情
- [CLI 参考](../cli-reference.md) - 所有 CLI 命令的完整文档
- [发行说明 v0.4.0](https://github.com/teng-lin/notebooklm-py/releases/tag/v0.4.0) - 功能发布详情

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：teng-lin/notebooklm-py

摘要：发现 30 个潜在踩坑项，其中 3 个为 high/blocking；最高优先级：维护坑 - 来源证据：API: route client.mind_maps mutation sites through MindMapNotFoundError (rename/get_tree bare ValueError)。

## 1. 维护坑 · 来源证据：API: route client.mind_maps mutation sites through MindMapNotFoundError (rename/get_tree bare ValueError)

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个维护/版本相关的待验证问题：API: route client.mind_maps mutation sites through MindMapNotFoundError (rename/get_tree bare ValueError)
- 对用户的影响：可能影响升级、迁移或版本选择。
- 建议检查：来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_84d8e36f2175420382af42f6a85f022e | https://github.com/teng-lin/notebooklm-py/issues/1291 | 来源类型 github_issue 暴露的待验证使用条件。

## 2. 维护坑 · 来源证据：v0.8.0: flip sources/artifacts/notes/mind_maps.get() to raise *NotFoundError

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个维护/版本相关的待验证问题：v0.8.0: flip sources/artifacts/notes/mind_maps.get() to raise *NotFoundError
- 对用户的影响：可能影响升级、迁移或版本选择。
- 建议检查：来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_aed84a2b0ce748519e8c4b04b34e3b67 | https://github.com/teng-lin/notebooklm-py/issues/1247 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 3. 安全/权限坑 · 失败模式：security_permissions: Test hygiene: run the cassette-cleanliness guard inside pytest (defense-in-depth for credenti...

- 严重度：high
- 证据强度：source_linked
- 发现：Developers should check this security_permissions risk before relying on the project: Test hygiene: run the cassette-cleanliness guard inside pytest (defense-in-depth for credential leaks)
- 对用户的影响：Developers may expose sensitive permissions or credentials: Test hygiene: run the cassette-cleanliness guard inside pytest (defense-in-depth for credential leaks)
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: Test hygiene: run the cassette-cleanliness guard inside pytest (defense-in-depth for credential leaks). Context: Source discussion did not expose a precise runtime context.
- 防护动作：Do not recommend enabling privileged or credential-bearing paths until the source-backed risk is reviewed: https://github.com/teng-lin/notebooklm-py/issues/1292
- 证据：failure_mode_cluster:github_issue | fmev_bc923eee3d22d09a307c9b8bd9e67b45 | https://github.com/teng-lin/notebooklm-py/issues/1292 | Test hygiene: run the cassette-cleanliness guard inside pytest (defense-in-depth for credential leaks)

## 4. 安装坑 · 失败模式：installation: v0.2.1

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.2.1
- 对用户的影响：Upgrade or migration may change expected behavior: v0.2.1
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.2.1. Context: Observed during installation or first-run setup.
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_1785f1babed9cb7123f6ce16f7cabd8c | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.2.1 | v0.2.1

## 5. 安装坑 · 失败模式：installation: v0.3.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.3.0
- 对用户的影响：Upgrade or migration may change expected behavior: v0.3.0
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.3.0. Context: Observed when using python
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_0682708a98e1c2658031a1fb85382b73 | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.3.0 | v0.3.0

## 6. 安装坑 · 失败模式：installation: v0.4.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.4.0
- 对用户的影响：Upgrade or migration may change expected behavior: v0.4.0
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.4.0. Context: Observed when using python, playwright, windows
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_9ca899a22a1723caa88b91f3b23aa94a | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.4.0 | v0.4.0

## 7. 安装坑 · 失败模式：installation: v0.6.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.6.0
- 对用户的影响：Upgrade or migration may change expected behavior: v0.6.0
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.6.0. Context: Observed when using python
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_6697b8c66b7baff65ef8991167386a38 | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.6.0 | v0.6.0

## 8. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 建议检查：列出会写入的配置文件、目录和卸载/回滚步骤。
- 防护动作：涉及宿主配置目录时必须给回滚路径，不能只给安装命令。
- 证据：capability.host_targets | github_repo:1129786550 | https://github.com/teng-lin/notebooklm-py | host_targets=claude, claude_code

## 9. 配置坑 · 失败模式：configuration: v0.3.3

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: v0.3.3
- 对用户的影响：Upgrade or migration may change expected behavior: v0.3.3
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.3.3. Context: Observed when using python
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_d5e632c85b71175c7dccae55b7dcb9b1 | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.3.3 | v0.3.3

## 10. 配置坑 · 失败模式：configuration: v0.4.1

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: v0.4.1
- 对用户的影响：Upgrade or migration may change expected behavior: v0.4.1
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.4.1. Context: Source discussion did not expose a precise runtime context.
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_46b7bc285e00c2407204e85451de0016 | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.4.1 | v0.4.1

## 11. 配置坑 · 失败模式：configuration: v0.5.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: v0.5.0
- 对用户的影响：Upgrade or migration may change expected behavior: v0.5.0
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.5.0. Context: Observed when using python
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_88277b44954b3bc111bcd08b767ceb0e | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.5.0 | v0.5.0

## 12. 配置坑 · 来源证据：API: three methods return `bool` that is always `True` (refresh / delete_conversation / clear_cache)

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：API: three methods return `bool` that is always `True` (refresh / delete_conversation / clear_cache)
- 对用户的影响：可能影响升级、迁移或版本选择。
- 建议检查：来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_70ed738a48ca43f88c038e3fa51f113b | https://github.com/teng-lin/notebooklm-py/issues/1290 | 来源类型 github_issue 暴露的待验证使用条件。

## 13. 配置坑 · 来源证据：Make CLI exit-path allowlists robust to line shifts (drop line-number pinning)

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：Make CLI exit-path allowlists robust to line shifts (drop line-number pinning)
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_3e04722a6f92419bae62be17dfae7e3a | https://github.com/teng-lin/notebooklm-py/issues/1298 | 来源类型 github_issue 暴露的待验证使用条件。

## 14. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 建议检查：将假设转成下游验证清单。
- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。
- 证据：capability.assumptions | github_repo:1129786550 | https://github.com/teng-lin/notebooklm-py | README/documentation is current enough for a first validation pass.

## 15. 运行坑 · 失败模式：runtime: Exit-path lint gates re-parse each CLI file once per audit pass

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this runtime risk before relying on the project: Exit-path lint gates re-parse each CLI file once per audit pass
- 对用户的影响：Developers may hit a documented source-backed failure mode: Exit-path lint gates re-parse each CLI file once per audit pass
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: Exit-path lint gates re-parse each CLI file once per audit pass. Context: Source discussion did not expose a precise runtime context.
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_issue | fmev_891c98afa1f130da726689acd404d6e2 | https://github.com/teng-lin/notebooklm-py/issues/1302 | Exit-path lint gates re-parse each CLI file once per audit pass

## 16. 运行坑 · 失败模式：runtime: Make CLI exit-path allowlists robust to line shifts (drop line-number pinning)

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this runtime risk before relying on the project: Make CLI exit-path allowlists robust to line shifts (drop line-number pinning)
- 对用户的影响：Developers may hit a documented source-backed failure mode: Make CLI exit-path allowlists robust to line shifts (drop line-number pinning)
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: Make CLI exit-path allowlists robust to line shifts (drop line-number pinning). Context: Source discussion did not expose a precise runtime context.
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_issue | fmev_5679b2266176ae3d04e8bea535e90e95 | https://github.com/teng-lin/notebooklm-py/issues/1298 | Make CLI exit-path allowlists robust to line shifts (drop line-number pinning)

## 17. 运行坑 · 失败模式：runtime: v0.3.4

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this runtime risk before relying on the project: v0.3.4
- 对用户的影响：Upgrade or migration may change expected behavior: v0.3.4
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.3.4. Context: Observed when using python
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_1b9588c13c83ee18120628ab096c23b5 | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.3.4 | v0.3.4

## 18. 运行坑 · 来源证据：CLI quiet-enforcement lint gate scans only `*_cmd.py`, not all `cli/*.py`

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个运行相关的待验证问题：CLI quiet-enforcement lint gate scans only `*_cmd.py`, not all `cli/*.py`
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_b3634b6896e34d63b75266f9fc16813a | https://github.com/teng-lin/notebooklm-py/issues/1301 | 来源类型 github_issue 暴露的待验证使用条件。

## 19. 维护坑 · 失败模式：migration: API: route client.mind_maps mutation sites through MindMapNotFoundError (rename/get_tree bare...

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this migration risk before relying on the project: API: route client.mind_maps mutation sites through MindMapNotFoundError (rename/get_tree bare ValueError)
- 对用户的影响：Developers may hit a documented source-backed failure mode: API: route client.mind_maps mutation sites through MindMapNotFoundError (rename/get_tree bare ValueError)
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: API: route client.mind_maps mutation sites through MindMapNotFoundError (rename/get_tree bare ValueError). Context: Observed during version upgrade or migration.
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_issue | fmev_014324146f375d7bedf6957e53ad71c2 | https://github.com/teng-lin/notebooklm-py/issues/1291 | API: route client.mind_maps mutation sites through MindMapNotFoundError (rename/get_tree bare ValueError)

## 20. 维护坑 · 失败模式：migration: API: three methods return `bool` that is always `True` (refresh / delete_conversation / clear...

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this migration risk before relying on the project: API: three methods return `bool` that is always `True` (refresh / delete_conversation / clear_cache)
- 对用户的影响：Developers may hit a documented source-backed failure mode: API: three methods return `bool` that is always `True` (refresh / delete_conversation / clear_cache)
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: API: three methods return `bool` that is always `True` (refresh / delete_conversation / clear_cache). Context: Observed during version upgrade or migration.
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_issue | fmev_bd37e60fc24b8ca683cc4af1092ee9d0 | https://github.com/teng-lin/notebooklm-py/issues/1290 | API: three methods return `bool` that is always `True` (refresh / delete_conversation / clear_cache)

## 21. 维护坑 · 失败模式：migration: v0.8.0: flip sources/artifacts/notes/mind_maps.get() to raise *NotFoundError

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this migration risk before relying on the project: v0.8.0: flip sources/artifacts/notes/mind_maps.get() to raise *NotFoundError
- 对用户的影响：Developers may hit a documented source-backed failure mode: v0.8.0: flip sources/artifacts/notes/mind_maps.get() to raise *NotFoundError
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.8.0: flip sources/artifacts/notes/mind_maps.get() to raise *NotFoundError. Context: Observed when using python
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_issue | fmev_10bbab0b2fec01ea58322c5770a9c181 | https://github.com/teng-lin/notebooklm-py/issues/1247 | v0.8.0: flip sources/artifacts/notes/mind_maps.get() to raise *NotFoundError

## 22. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。
- 证据：evidence.maintainer_signals | github_repo:1129786550 | https://github.com/teng-lin/notebooklm-py | last_activity_observed missing

## 23. 安全/权限坑 · 下游验证发现风险项

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：下游已经要求复核，不能在页面中弱化。
- 建议检查：进入安全/权限治理复核队列。
- 防护动作：下游风险存在时必须保持 review/recommendation 降级。
- 证据：downstream_validation.risk_items | github_repo:1129786550 | https://github.com/teng-lin/notebooklm-py | no_demo; severity=medium

## 24. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 建议检查：把风险写入边界卡，并确认是否需要人工复核。
- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。
- 证据：risks.scoring_risks | github_repo:1129786550 | https://github.com/teng-lin/notebooklm-py | no_demo; severity=medium

## 25. 安全/权限坑 · 来源证据：Exit-path lint gates re-parse each CLI file once per audit pass

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Exit-path lint gates re-parse each CLI file once per audit pass
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_28adebd29111406ea99100bd3d81eeb8 | https://github.com/teng-lin/notebooklm-py/issues/1302 | 来源类型 github_issue 暴露的待验证使用条件。

## 26. 安全/权限坑 · 来源证据：Test hygiene: run the cassette-cleanliness guard inside pytest (defense-in-depth for credential leaks)

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Test hygiene: run the cassette-cleanliness guard inside pytest (defense-in-depth for credential leaks)
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_458e42810e2d4f7bb0f5420a15d97ff4 | https://github.com/teng-lin/notebooklm-py/issues/1292 | 来源类型 github_issue 暴露的待验证使用条件。

## 27. 能力坑 · 失败模式：capability: CLI quiet-enforcement lint gate scans only `*_cmd.py`, not all `cli/*.py`

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this capability risk before relying on the project: CLI quiet-enforcement lint gate scans only `*_cmd.py`, not all `cli/*.py`
- 对用户的影响：Developers may hit a documented source-backed failure mode: CLI quiet-enforcement lint gate scans only `*_cmd.py`, not all `cli/*.py`
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: CLI quiet-enforcement lint gate scans only `*_cmd.py`, not all `cli/*.py`. Context: Source discussion did not expose a precise runtime context.
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_issue | fmev_53e1d94c0db78abd46e10ca3db558949 | https://github.com/teng-lin/notebooklm-py/issues/1301 | CLI quiet-enforcement lint gate scans only `*_cmd.py`, not all `cli/*.py`

## 28. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。
- 防护动作：issue/PR 响应未知时，必须提示维护风险。
- 证据：evidence.maintainer_signals | github_repo:1129786550 | https://github.com/teng-lin/notebooklm-py | issue_or_pr_quality=unknown

## 29. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。
- 证据：evidence.maintainer_signals | github_repo:1129786550 | https://github.com/teng-lin/notebooklm-py | release_recency=unknown

## 30. 维护坑 · 失败模式：maintenance: v0.3.2

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this maintenance risk before relying on the project: v0.3.2
- 对用户的影响：Upgrade or migration may change expected behavior: v0.3.2
- 建议检查：Before packaging this project, run the relevant install/config/quickstart check for: v0.3.2. Context: Observed when using playwright, windows
- 防护动作：State this as source-backed community evidence, not as Doramagic reproduction.
- 证据：failure_mode_cluster:github_release | fmev_2422b6e9d2ac3aa7c4f3269cb5ab22b8 | https://github.com/teng-lin/notebooklm-py/releases/tag/v0.3.2 | v0.3.2

<!-- canonical_name: teng-lin/notebooklm-py; human_manual_source: deepwiki_human_wiki -->
