Skip to content

Commit 08a1ab4

Browse files
committed
Discover and execute JupyterLab commands
1 parent 9d36817 commit 08a1ab4

File tree

5 files changed

+359
-226
lines changed

5 files changed

+359
-226
lines changed

jupyterlab_commands_toolkit/__init__.py

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
# in editable mode with pip. It is highly recommended to install
66
# the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs
77
import warnings
8-
warnings.warn("Importing 'jupyterlab_commands_toolkit' outside a proper installation.")
8+
9+
warnings.warn(
10+
"Importing 'jupyterlab_commands_toolkit' outside a proper installation."
11+
)
912
__version__ = "dev"
1013

1114
import pathlib
@@ -20,19 +23,63 @@
2023
# If jupyter-ai is not available, the AI toolkit won't be available
2124
toolkit = None
2225

26+
2327
def _jupyter_labextension_paths():
24-
return [{
25-
"src": "labextension",
26-
"dest": "jupyterlab-commands-toolkit"
27-
}]
28+
return [{"src": "labextension", "dest": "jupyterlab-commands-toolkit"}]
2829

2930

3031
def _jupyter_server_extension_points():
31-
return [{
32-
"module": "jupyterlab_commands_toolkit"
33-
}]
32+
return [{"module": "jupyterlab_commands_toolkit"}]
33+
3434

3535
def _load_jupyter_server_extension(serverapp: ServerApp):
36-
schema_path = pathlib.Path(__file__).parent / "events" / "jupyterlab-command.yml"
37-
serverapp.event_logger.register_event_schema(schema_path)
38-
serverapp.log.info("jupyterlab_commands_toolkit extension loaded.")
36+
command_schema_path = (
37+
pathlib.Path(__file__).parent / "events" / "jupyterlab-command.yml"
38+
)
39+
serverapp.event_logger.register_event_schema(command_schema_path)
40+
41+
result_schema_path = (
42+
pathlib.Path(__file__).parent / "events" / "jupyterlab-command-result.yml"
43+
)
44+
serverapp.event_logger.register_event_schema(result_schema_path)
45+
46+
async def command_result_listener(logger, schema_id: str, data: dict) -> None:
47+
"""
48+
Handle command result events from the frontend.
49+
50+
This listener receives the results of JupyterLab commands that were
51+
executed in the frontend and processes them accordingly.
52+
"""
53+
from .tools import handle_command_result
54+
55+
try:
56+
request_id = data.get("requestId", "unknown")
57+
success = data.get("success", False)
58+
result = data.get("result")
59+
error = data.get("error")
60+
61+
serverapp.log.info(
62+
f"Received command result for request {request_id}: success={success}"
63+
)
64+
65+
if success:
66+
if result is not None:
67+
serverapp.log.debug(f"Command result: {result}")
68+
else:
69+
serverapp.log.warning(f"Command failed: {error}")
70+
71+
handle_command_result(data)
72+
73+
except Exception as e:
74+
serverapp.log.error(f"Error processing command result: {e}")
75+
76+
result_schema_id = (
77+
"https://events.jupyter.org/jupyterlab_command_toolkit/lab_command_result/v1"
78+
)
79+
serverapp.event_logger.add_listener(
80+
schema_id=result_schema_id, listener=command_result_listener
81+
)
82+
83+
serverapp.log.info(
84+
"jupyterlab_commands_toolkit extension loaded with bidirectional event communication."
85+
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"$id": https://events.jupyter.org/jupyterlab_command_toolkit/lab_command_result/v1
2+
version: 1
3+
title: A JupyterLab Command Execution Result
4+
personal-data: true
5+
description: |
6+
Result of a JupyterLab Command execution
7+
type: object
8+
required:
9+
- requestId
10+
- success
11+
properties:
12+
requestId:
13+
type: string
14+
description: The unique identifier for the command request
15+
success:
16+
type: boolean
17+
description: Whether the command executed successfully
18+
result:
19+
description: The result data from the command execution
20+
error:
21+
type: string
22+
description: Error message if the command failed
Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,55 @@
11
"""JupyterLab Commands toolkit for Jupyter AI"""
2-
from jupyter_ai.tools.models import Tool, Toolkit
3-
4-
from typing import Optional
5-
from .tools import (
6-
open_document,
7-
open_markdown_file_in_preview_mode,
8-
clear_all_outputs_in_notebook,
9-
show_diff_of_current_notebook,
10-
INSERT_MODE
11-
)
12-
13-
# Create the toolkit
14-
toolkit = Toolkit(
15-
name="jupyterlab_commands_toolkit",
16-
description="""A comprehensive toolkit for controlling JupyterLab interface and performing notebook operations through AI commands.
17-
18-
This toolkit provides programmatic access to JupyterLab's core functionality, enabling AI assistants to:
19-
20-
**Document Management:**
21-
- Open files, notebooks, and documents with precise control over layout positioning
22-
- Support for split-pane layouts (top, left, right, bottom) and tab management
23-
- Open markdown files in rendered preview mode for better readability
24-
25-
**Notebook Operations:**
26-
- Clear all cell outputs in the active notebook for cleanup and sharing
27-
- Display git diffs for notebooks using nbdime visualization
28-
- Maintain notebook structure while performing operations
29-
30-
**Layout Control:**
31-
- Split current workspace into multiple panes
32-
- Merge content with adjacent areas
33-
- Create new tabs before or after current position
34-
- Flexible positioning options for optimal workspace organization
35-
36-
**Key Features:**
37-
- Event-driven architecture using JupyterLab's command system
38-
- Seamless integration with Jupyter AI for natural language control
39-
- Support for relative file paths from server root directory
40-
- Comprehensive error handling and user feedback
41-
- Compatible with JupyterLab 4.0+ and modern Jupyter environments
42-
43-
Use these tools to programmatically manage your JupyterLab workspace, organize documents, and perform common notebook operations through conversational AI interfaces."""
44-
)
45-
46-
# Add tools to the toolkit
47-
toolkit.add_tool(Tool(callable=open_document, read=True))
48-
toolkit.add_tool(Tool(callable=open_markdown_file_in_preview_mode, read=True))
49-
toolkit.add_tool(Tool(callable=clear_all_outputs_in_notebook, read=True))
50-
toolkit.add_tool(Tool(callable=show_diff_of_current_notebook, read=True))
2+
3+
try:
4+
from jupyter_ai.tools.models import Tool, Toolkit
5+
6+
from typing import Optional
7+
from .tools import (
8+
open_document,
9+
open_markdown_file_in_preview_mode,
10+
clear_all_outputs_in_notebook,
11+
show_diff_of_current_notebook,
12+
INSERT_MODE,
13+
)
14+
15+
# Create the toolkit
16+
toolkit = Toolkit(
17+
name="jupyterlab_commands_toolkit",
18+
description="""A comprehensive toolkit for controlling JupyterLab interface and performing notebook operations through AI commands.
19+
20+
This toolkit provides programmatic access to JupyterLab's core functionality, enabling AI assistants to:
21+
22+
**Document Management:**
23+
- Open files, notebooks, and documents with precise control over layout positioning
24+
- Support for split-pane layouts (top, left, right, bottom) and tab management
25+
- Open markdown files in rendered preview mode for better readability
26+
27+
**Notebook Operations:**
28+
- Clear all cell outputs in the active notebook for cleanup and sharing
29+
- Display git diffs for notebooks using nbdime visualization
30+
- Maintain notebook structure while performing operations
31+
32+
**Layout Control:**
33+
- Split current workspace into multiple panes
34+
- Merge content with adjacent areas
35+
- Create new tabs before or after current position
36+
- Flexible positioning options for optimal workspace organization
37+
38+
**Key Features:**
39+
- Event-driven architecture using JupyterLab's command system
40+
- Seamless integration with Jupyter AI for natural language control
41+
- Support for relative file paths from server root directory
42+
- Comprehensive error handling and user feedback
43+
- Compatible with JupyterLab 4.0+ and modern Jupyter environments
44+
45+
Use these tools to programmatically manage your JupyterLab workspace, organize documents, and perform common notebook operations through conversational AI interfaces.""",
46+
)
47+
48+
# Add tools to the toolkit
49+
toolkit.add_tool(Tool(callable=open_document, read=True))
50+
toolkit.add_tool(Tool(callable=open_markdown_file_in_preview_mode, read=True))
51+
toolkit.add_tool(Tool(callable=clear_all_outputs_in_notebook, read=True))
52+
toolkit.add_tool(Tool(callable=show_diff_of_current_notebook, read=True))
53+
except ImportError:
54+
# If jupyter-ai is not available, the AI toolkit won't be available
55+
toolkit = None

0 commit comments

Comments
 (0)