Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/notebooklm/_artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,8 @@ async def generate_mind_map(
self,
notebook_id: str,
source_ids: builtins.list[str] | None = None,
language: str = "en",
instructions: str | None = None,
) -> dict[str, Any]:
"""Generate an interactive mind map.

Expand All @@ -997,6 +999,8 @@ async def generate_mind_map(
Args:
notebook_id: The notebook ID.
source_ids: Source IDs to include. If None, uses all sources.
language: Language code (default: "en").
instructions: Custom instructions for the mind map.

Returns:
Dictionary with 'mind_map' (JSON data) and 'note_id'.
Expand All @@ -1014,7 +1018,7 @@ async def generate_mind_map(
None,
None,
None,
["interactive_mindmap", [["[CONTEXT]", ""]], ""],
["interactive_mindmap", [["[CONTEXT]", instructions or ""]], language],
None,
[2, None, [1]],
]
Expand Down
23 changes: 15 additions & 8 deletions src/notebooklm/cli/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,9 +995,13 @@ async def _generate():
help="Notebook ID (uses current if not set)",
)
@click.option("--source", "-s", "source_ids", multiple=True, help="Limit to specific source IDs")
@click.option("--language", default=None, help="Output language (default: from config or 'en')")
@click.option("--instructions", default=None, help="Custom instructions for the mind map")
@json_option
@with_client
def generate_mind_map(ctx, notebook_id, source_ids, json_output, client_auth):
def generate_mind_map(
ctx, notebook_id, source_ids, language, instructions, json_output, client_auth
):
"""Generate mind map.

\b
Expand All @@ -1010,16 +1014,19 @@ async def _run():
nb_id_resolved = await resolve_notebook_id(client, nb_id)
sources = await resolve_source_ids(client, nb_id_resolved, source_ids)

# Show status spinner only for console output
if json_output:
result = await client.artifacts.generate_mind_map(
nb_id_resolved, source_ids=sources
async def _generate():
return await client.artifacts.generate_mind_map(
nb_id_resolved,
source_ids=sources,
language=resolve_language(language),
instructions=instructions,
)

if json_output:
result = await _generate()
else:
with console.status("Generating mind map..."):
result = await client.artifacts.generate_mind_map(
nb_id_resolved, source_ids=sources
)
result = await _generate()

_output_mind_map_result(result, json_output)

Expand Down
25 changes: 25 additions & 0 deletions tests/unit/test_source_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,31 @@ async def test_generate_mind_map_source_encoding(self, mock_core, mock_notes_api

assert source_ids_nested == [[["src_mm_1"]], [["src_mm_2"]]]

@pytest.mark.asyncio
async def test_generate_mind_map_passes_language_and_instructions(
self, mock_core, mock_notes_api
):
"""Test generate_mind_map passes language and instructions to RPC payload."""
api = ArtifactsAPI(mock_core, mock_notes_api)

mock_core.get_source_ids.return_value = ["src_1"]
mock_core.rpc_call.return_value = [['{"name": "Mind Map", "children": []}']]

await api.generate_mind_map(
notebook_id="nb_123",
source_ids=["src_1"],
language="ja",
instructions="Focus on key themes",
)

call_args = mock_core.rpc_call.call_args
params = call_args.args[1]

# params[5] should contain the mind map config with language and instructions
mind_map_config = params[5]
assert mind_map_config[1][0][1] == "Focus on key themes"
assert mind_map_config[2] == "ja"

@pytest.mark.asyncio
async def test_suggest_reports_uses_get_suggested_reports(self, mock_core, mock_notes_api):
"""Test suggest_reports uses GET_SUGGESTED_REPORTS RPC."""
Expand Down
Loading