@jupyterlite/ai 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/agent.js +17 -10
- package/lib/chat-model.d.ts +7 -0
- package/lib/chat-model.js +37 -3
- package/lib/components/clear-button.js +2 -3
- package/lib/components/model-select.js +4 -8
- package/lib/components/stop-button.js +4 -5
- package/lib/components/tool-select.js +4 -4
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -43
- package/lib/models/settings-model.js +40 -26
- package/lib/tools/commands.js +6 -10
- package/package.json +10 -10
- package/schema/settings-model.json +3 -2
- package/src/agent.ts +18 -11
- package/src/chat-model.ts +47 -3
- package/src/components/clear-button.tsx +2 -3
- package/src/components/model-select.tsx +4 -8
- package/src/components/stop-button.tsx +6 -6
- package/src/components/tool-select.tsx +4 -4
- package/src/index.ts +3 -98
- package/src/models/settings-model.ts +40 -26
- package/src/tools/commands.ts +10 -12
- package/style/base.css +11 -0
- package/lib/tools/file.d.ts +0 -36
- package/lib/tools/file.js +0 -327
- package/lib/tools/notebook.d.ts +0 -40
- package/lib/tools/notebook.js +0 -704
- package/src/tools/file.ts +0 -412
- package/src/tools/notebook.ts +0 -927
package/lib/agent.js
CHANGED
|
@@ -654,17 +654,24 @@ Guidelines:
|
|
|
654
654
|
- End with a brief summary of accomplishments
|
|
655
655
|
- Use natural, conversational tone throughout
|
|
656
656
|
|
|
657
|
-
COMMAND
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
- This ensures you have complete information about command IDs, descriptions, and required arguments before attempting to execute them. Only after discovering the available commands should you use the 'execute_command' tool with the correct command ID and arguments.
|
|
657
|
+
PRIMARY TOOL USAGE - COMMAND-BASED OPERATIONS:
|
|
658
|
+
Most operations in JupyterLab should be performed using the command system:
|
|
659
|
+
1. Use 'discover_commands' to find available commands and their metadata
|
|
660
|
+
2. Use 'execute_command' to perform the actual operation
|
|
662
661
|
|
|
663
|
-
|
|
664
|
-
- For file
|
|
665
|
-
- For
|
|
666
|
-
-
|
|
667
|
-
|
|
662
|
+
COMMAND DISCOVERY WORKFLOW:
|
|
663
|
+
- For file and notebook operations, use query 'jupyterlab-ai-commands' to discover the curated set of AI commands (~17 commands for file/notebook/directory operations)
|
|
664
|
+
- For other JupyterLab operations (terminal, launcher, UI), use specific keywords like 'terminal', 'launcher', etc.
|
|
665
|
+
- IMPORTANT: Always use 'jupyterlab-ai-commands' as the query for file/notebook tasks - this returns a focused set of commands instead of 100+ generic JupyterLab commands
|
|
666
|
+
|
|
667
|
+
KERNEL PREFERENCE FOR NOTEBOOKS AND CONSOLES:
|
|
668
|
+
When creating notebooks or consoles for a specific programming language, use the 'kernelPreference' argument to specify the kernel:
|
|
669
|
+
- To specify by language: { "kernelPreference": { "language": "python" } } or { "kernelPreference": { "language": "julia" } }
|
|
670
|
+
- To specify by kernel name: { "kernelPreference": { "name": "python3" } } or { "kernelPreference": { "name": "julia-1.10" } }
|
|
671
|
+
- Example: execute_command with commandId="notebook:create-new" and args={ "kernelPreference": { "language": "python" } }
|
|
672
|
+
- Example: execute_command with commandId="console:create" and args={ "kernelPreference": { "name": "python3" } }
|
|
673
|
+
- Common kernel names: "python3" (Python), "julia-1.10" (Julia), "ir" (R), "xpython" (xeus-python)
|
|
674
|
+
- If unsure of exact kernel name, prefer using "language" which will match any kernel supporting that language
|
|
668
675
|
`;
|
|
669
676
|
return baseSystemPrompt + progressReportingPrompt;
|
|
670
677
|
}
|
package/lib/chat-model.d.ts
CHANGED
|
@@ -81,6 +81,13 @@ export declare class AIChatModel extends AbstractChatModel {
|
|
|
81
81
|
* @param event Event containing the message completion data
|
|
82
82
|
*/
|
|
83
83
|
private _handleMessageComplete;
|
|
84
|
+
/**
|
|
85
|
+
* Extracts a human-readable summary from tool input for display in the header.
|
|
86
|
+
* @param toolName The name of the tool being called
|
|
87
|
+
* @param input The formatted JSON input string
|
|
88
|
+
* @returns A short summary string or empty string if none available
|
|
89
|
+
*/
|
|
90
|
+
private _extractToolSummary;
|
|
84
91
|
/**
|
|
85
92
|
* Handles the start of a tool call execution.
|
|
86
93
|
* @param event Event containing the tool call start data
|
package/lib/chat-model.js
CHANGED
|
@@ -242,18 +242,47 @@ export class AIChatModel extends AbstractChatModel {
|
|
|
242
242
|
this._currentStreamingMessage = null;
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Extracts a human-readable summary from tool input for display in the header.
|
|
247
|
+
* @param toolName The name of the tool being called
|
|
248
|
+
* @param input The formatted JSON input string
|
|
249
|
+
* @returns A short summary string or empty string if none available
|
|
250
|
+
*/
|
|
251
|
+
_extractToolSummary(toolName, input) {
|
|
252
|
+
try {
|
|
253
|
+
const parsedInput = JSON.parse(input);
|
|
254
|
+
switch (toolName) {
|
|
255
|
+
case 'execute_command':
|
|
256
|
+
if (parsedInput.commandId) {
|
|
257
|
+
return parsedInput.commandId;
|
|
258
|
+
}
|
|
259
|
+
break;
|
|
260
|
+
case 'discover_commands':
|
|
261
|
+
if (parsedInput.query) {
|
|
262
|
+
return `query: "${parsedInput.query}"`;
|
|
263
|
+
}
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
// If parsing fails, return empty string
|
|
269
|
+
}
|
|
270
|
+
return '';
|
|
271
|
+
}
|
|
245
272
|
/**
|
|
246
273
|
* Handles the start of a tool call execution.
|
|
247
274
|
* @param event Event containing the tool call start data
|
|
248
275
|
*/
|
|
249
276
|
_handleToolCallStartEvent(event) {
|
|
250
277
|
const messageId = UUID.uuid4();
|
|
278
|
+
const summary = this._extractToolSummary(event.data.toolName, event.data.input);
|
|
251
279
|
const context = {
|
|
252
280
|
toolCallId: event.data.callId,
|
|
253
281
|
messageId,
|
|
254
282
|
toolName: event.data.toolName,
|
|
255
283
|
input: event.data.input,
|
|
256
|
-
status: 'pending'
|
|
284
|
+
status: 'pending',
|
|
285
|
+
summary
|
|
257
286
|
};
|
|
258
287
|
this._toolContexts.set(event.data.callId, context);
|
|
259
288
|
const toolCallMessage = {
|
|
@@ -261,6 +290,7 @@ export class AIChatModel extends AbstractChatModel {
|
|
|
261
290
|
toolName: context.toolName,
|
|
262
291
|
input: context.input,
|
|
263
292
|
status: context.status,
|
|
293
|
+
summary: context.summary,
|
|
264
294
|
trans: this._trans
|
|
265
295
|
}),
|
|
266
296
|
sender: this._getAIUser(),
|
|
@@ -337,6 +367,7 @@ export class AIChatModel extends AbstractChatModel {
|
|
|
337
367
|
toolName: context.toolName,
|
|
338
368
|
input: context.input,
|
|
339
369
|
status: context.status,
|
|
370
|
+
summary: context.summary,
|
|
340
371
|
output,
|
|
341
372
|
approvalId: context.approvalId,
|
|
342
373
|
trans: this._trans
|
|
@@ -642,12 +673,15 @@ var Private;
|
|
|
642
673
|
* Builds HTML for a tool call display.
|
|
643
674
|
*/
|
|
644
675
|
function buildToolCallHtml(options) {
|
|
645
|
-
const { toolName, input, status, output, approvalId, trans } = options;
|
|
676
|
+
const { toolName, input, status, summary, output, approvalId, trans } = options;
|
|
646
677
|
const config = STATUS_CONFIG[status];
|
|
647
678
|
const statusText = getStatusText(status, trans);
|
|
648
679
|
const escapedToolName = escapeHtml(toolName);
|
|
649
680
|
const escapedInput = escapeHtml(input);
|
|
650
681
|
const openAttr = config.open ? ' open' : '';
|
|
682
|
+
const summaryHtml = summary
|
|
683
|
+
? `<span class="jp-ai-tool-summary">${escapeHtml(summary)}</span>`
|
|
684
|
+
: '';
|
|
651
685
|
let bodyContent = `
|
|
652
686
|
<div class="jp-ai-tool-section">
|
|
653
687
|
<div class="jp-ai-tool-label">${trans.__('Input')}</div>
|
|
@@ -674,7 +708,7 @@ var Private;
|
|
|
674
708
|
return `<details class="jp-ai-tool-call ${config.cssClass}"${openAttr}>
|
|
675
709
|
<summary class="jp-ai-tool-header">
|
|
676
710
|
<div class="jp-ai-tool-icon">⚡</div>
|
|
677
|
-
<div class="jp-ai-tool-title">${escapedToolName}</div>
|
|
711
|
+
<div class="jp-ai-tool-title">${escapedToolName}${summaryHtml}</div>
|
|
678
712
|
<div class="jp-ai-tool-status ${config.statusClass}">${statusText}</div>
|
|
679
713
|
</summary>
|
|
680
714
|
<div class="jp-ai-tool-body">${bodyContent}
|
|
@@ -8,10 +8,9 @@ export function ClearButton(props) {
|
|
|
8
8
|
const { translator: trans } = props;
|
|
9
9
|
const tooltip = trans.__('Clear chat');
|
|
10
10
|
return (React.createElement(TooltippedButton, { onClick: props.clearMessages, tooltip: tooltip, buttonProps: {
|
|
11
|
-
|
|
11
|
+
title: tooltip,
|
|
12
12
|
variant: 'outlined',
|
|
13
|
-
color: 'secondary'
|
|
14
|
-
title: tooltip
|
|
13
|
+
color: 'secondary'
|
|
15
14
|
} },
|
|
16
15
|
React.createElement(ClearIcon, null)));
|
|
17
16
|
}
|
|
@@ -61,16 +61,15 @@ export function ModelSelect(props) {
|
|
|
61
61
|
// Show a message if no providers are configured
|
|
62
62
|
if (availableModels.length === 0) {
|
|
63
63
|
return (React.createElement(TooltippedButton, { onClick: () => { }, tooltip: trans.__('No providers configured. Please go to AI Settings to add a provider.'), buttonProps: {
|
|
64
|
-
size: 'small',
|
|
65
64
|
variant: 'outlined',
|
|
66
65
|
color: 'warning',
|
|
67
66
|
disabled: true,
|
|
68
67
|
title: trans.__('No Providers Available')
|
|
69
68
|
}, sx: {
|
|
70
69
|
minWidth: 'auto',
|
|
70
|
+
width: 'unset',
|
|
71
71
|
display: 'flex',
|
|
72
|
-
alignItems: 'center'
|
|
73
|
-
height: '29px'
|
|
72
|
+
alignItems: 'center'
|
|
74
73
|
} },
|
|
75
74
|
React.createElement(Typography, { variant: "caption", sx: { fontSize: '0.7rem', fontWeight: 500 } }, trans.__('No Providers'))));
|
|
76
75
|
}
|
|
@@ -78,9 +77,6 @@ export function ModelSelect(props) {
|
|
|
78
77
|
React.createElement(TooltippedButton, { onClick: e => {
|
|
79
78
|
openMenu(e.currentTarget);
|
|
80
79
|
}, tooltip: trans.__('Current Model: %1 - %2', currentProviderLabel, currentModel), buttonProps: {
|
|
81
|
-
size: 'small',
|
|
82
|
-
variant: 'contained',
|
|
83
|
-
color: 'primary',
|
|
84
80
|
title: trans.__('Select AI Model'),
|
|
85
81
|
onKeyDown: e => {
|
|
86
82
|
if (e.key !== 'Enter' && e.key !== ' ') {
|
|
@@ -92,9 +88,9 @@ export function ModelSelect(props) {
|
|
|
92
88
|
}
|
|
93
89
|
}, sx: {
|
|
94
90
|
minWidth: 'auto',
|
|
91
|
+
width: 'unset',
|
|
95
92
|
display: 'flex',
|
|
96
|
-
alignItems: 'center'
|
|
97
|
-
height: '29px'
|
|
93
|
+
alignItems: 'center'
|
|
98
94
|
} },
|
|
99
95
|
React.createElement(Typography, { variant: "caption", sx: { fontSize: '0.7rem', fontWeight: 500, textTransform: 'none' } }, currentProviderLabel)),
|
|
100
96
|
React.createElement(Menu, { open: menuOpen, onClose: closeMenu, anchorEl: menuAnchorEl, anchorOrigin: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TooltippedIconButton } from '@jupyter/chat';
|
|
2
2
|
import StopIcon from '@mui/icons-material/Stop';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
/**
|
|
@@ -7,11 +7,10 @@ import React from 'react';
|
|
|
7
7
|
export function StopButton(props) {
|
|
8
8
|
const { translator: trans } = props;
|
|
9
9
|
const tooltip = trans.__('Stop streaming');
|
|
10
|
-
return (React.createElement(
|
|
11
|
-
size: 'small',
|
|
12
|
-
variant: 'contained',
|
|
13
|
-
color: 'error',
|
|
10
|
+
return (React.createElement(TooltippedIconButton, { onClick: props.stopStreaming, tooltip: tooltip, buttonProps: {
|
|
14
11
|
title: tooltip
|
|
12
|
+
}, sx: {
|
|
13
|
+
backgroundColor: 'var(--mui-palette-error-main, #d32f2f);'
|
|
15
14
|
} },
|
|
16
15
|
React.createElement(StopIcon, null)));
|
|
17
16
|
}
|
|
@@ -64,9 +64,9 @@ export function ToolSelect(props) {
|
|
|
64
64
|
React.createElement(TooltippedButton, { onClick: e => {
|
|
65
65
|
openMenu(e.currentTarget);
|
|
66
66
|
}, tooltip: trans.__('Tools (%1/%2 selected)', selectedToolNames.length.toString(), tools.length.toString()), buttonProps: {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
...(selectedToolNames.length === 0 && {
|
|
68
|
+
variant: 'outlined'
|
|
69
|
+
}),
|
|
70
70
|
title: trans.__('Select AI Tools'),
|
|
71
71
|
onKeyDown: e => {
|
|
72
72
|
if (e.key !== 'Enter' && e.key !== ' ') {
|
|
@@ -79,7 +79,7 @@ export function ToolSelect(props) {
|
|
|
79
79
|
}, sx: selectedToolNames.length === 0
|
|
80
80
|
? { backgroundColor: 'var(--jp-layout-color3)' }
|
|
81
81
|
: {} },
|
|
82
|
-
React.createElement(BuildIcon,
|
|
82
|
+
React.createElement(BuildIcon, { sx: { fontSize: 'small' } })),
|
|
83
83
|
React.createElement(Menu, { open: menuOpen, onClose: closeMenu, anchorEl: menuAnchorEl, anchorOrigin: {
|
|
84
84
|
vertical: 'top',
|
|
85
85
|
horizontal: 'right'
|
package/lib/index.d.ts
CHANGED
|
@@ -6,3 +6,4 @@ import { AISettingsModel } from './models/settings-model';
|
|
|
6
6
|
declare const _default: (JupyterFrontEndPlugin<IProviderRegistry> | JupyterFrontEndPlugin<void> | JupyterFrontEndPlugin<IChatModelRegistry> | JupyterFrontEndPlugin<AgentManagerFactory> | JupyterFrontEndPlugin<AISettingsModel> | JupyterFrontEndPlugin<IDiffManager> | JupyterFrontEndPlugin<IToolRegistry> | JupyterFrontEndPlugin<IInputToolbarRegistryFactory>)[];
|
|
7
7
|
export default _default;
|
|
8
8
|
export * from './tokens';
|
|
9
|
+
export * from './icons';
|
package/lib/index.js
CHANGED
|
@@ -3,10 +3,8 @@ import { ActiveCellManager, AttachmentOpenerRegistry, chatIcon, ChatWidget, IInp
|
|
|
3
3
|
import { ICommandPalette, IThemeManager, WidgetTracker } from '@jupyterlab/apputils';
|
|
4
4
|
import { ICompletionProviderManager } from '@jupyterlab/completer';
|
|
5
5
|
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
6
|
-
import { IEditorTracker } from '@jupyterlab/fileeditor';
|
|
7
6
|
import { INotebookTracker } from '@jupyterlab/notebook';
|
|
8
7
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
9
|
-
import { IKernelSpecManager } from '@jupyterlab/services';
|
|
10
8
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
11
9
|
import { IStatusBar } from '@jupyterlab/statusbar';
|
|
12
10
|
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
@@ -24,8 +22,6 @@ import { clearItem, createModelSelectItem, createToolSelectItem, stopItem, Compl
|
|
|
24
22
|
import { AISettingsModel } from './models/settings-model';
|
|
25
23
|
import { DiffManager } from './diff-manager';
|
|
26
24
|
import { ToolRegistry } from './tools/tool-registry';
|
|
27
|
-
import { createAddCellTool, createDeleteCellTool, createExecuteActiveCellTool, createGetCellInfoTool, createGetNotebookInfoTool, createNotebookCreationTool, createRunCellTool, createSaveNotebookTool, createSetCellContentTool } from './tools/notebook';
|
|
28
|
-
import { createCopyFileTool, createDeleteFileTool, createGetFileInfoTool, createNavigateToDirectoryTool, createNewFileTool, createOpenFileTool, createRenameFileTool, createSetFileContentTool } from './tools/file';
|
|
29
25
|
import { createDiscoverCommandsTool, createExecuteCommandTool } from './tools/commands';
|
|
30
26
|
import { AISettingsWidget } from './widgets/ai-settings';
|
|
31
27
|
import { MainAreaChat } from './widgets/main-area-chat';
|
|
@@ -568,47 +564,10 @@ const toolRegistry = {
|
|
|
568
564
|
id: '@jupyterlite/ai:tool-registry',
|
|
569
565
|
description: 'Provide the AI tool registry',
|
|
570
566
|
autoStart: true,
|
|
571
|
-
requires: [IAISettingsModel
|
|
572
|
-
optional: [INotebookTracker, IDiffManager, IEditorTracker],
|
|
567
|
+
requires: [IAISettingsModel],
|
|
573
568
|
provides: IToolRegistry,
|
|
574
|
-
activate: (app, settingsModel
|
|
569
|
+
activate: (app, settingsModel) => {
|
|
575
570
|
const toolRegistry = new ToolRegistry();
|
|
576
|
-
const notebookCreationTool = createNotebookCreationTool(docManager, kernelSpecManager);
|
|
577
|
-
toolRegistry.add('create_notebook', notebookCreationTool);
|
|
578
|
-
// Add high-level notebook operation tools
|
|
579
|
-
const addCellTool = createAddCellTool(docManager, notebookTracker);
|
|
580
|
-
const getNotebookInfoTool = createGetNotebookInfoTool(docManager, notebookTracker);
|
|
581
|
-
const getCellInfoTool = createGetCellInfoTool(docManager, notebookTracker);
|
|
582
|
-
const setCellContentTool = createSetCellContentTool(docManager, notebookTracker, diffManager);
|
|
583
|
-
const runCellTool = createRunCellTool(docManager, notebookTracker);
|
|
584
|
-
const deleteCellTool = createDeleteCellTool(docManager, notebookTracker);
|
|
585
|
-
const saveNotebookTool = createSaveNotebookTool(docManager, notebookTracker);
|
|
586
|
-
const executeActiveCellTool = createExecuteActiveCellTool(docManager, notebookTracker);
|
|
587
|
-
toolRegistry.add('add_cell', addCellTool);
|
|
588
|
-
toolRegistry.add('get_notebook_info', getNotebookInfoTool);
|
|
589
|
-
toolRegistry.add('get_cell_info', getCellInfoTool);
|
|
590
|
-
toolRegistry.add('set_cell_content', setCellContentTool);
|
|
591
|
-
toolRegistry.add('run_cell', runCellTool);
|
|
592
|
-
toolRegistry.add('delete_cell', deleteCellTool);
|
|
593
|
-
toolRegistry.add('save_notebook', saveNotebookTool);
|
|
594
|
-
toolRegistry.add('execute_active_cell', executeActiveCellTool);
|
|
595
|
-
// Add file operation tools
|
|
596
|
-
const newFileTool = createNewFileTool(docManager);
|
|
597
|
-
const openFileTool = createOpenFileTool(docManager);
|
|
598
|
-
const deleteFileTool = createDeleteFileTool(docManager);
|
|
599
|
-
const renameFileTool = createRenameFileTool(docManager);
|
|
600
|
-
const copyFileTool = createCopyFileTool(docManager);
|
|
601
|
-
const navigateToDirectoryTool = createNavigateToDirectoryTool(app.commands);
|
|
602
|
-
const getFileInfoTool = createGetFileInfoTool(docManager, editorTracker);
|
|
603
|
-
const setFileContentTool = createSetFileContentTool(docManager, diffManager);
|
|
604
|
-
toolRegistry.add('create_file', newFileTool);
|
|
605
|
-
toolRegistry.add('open_file', openFileTool);
|
|
606
|
-
toolRegistry.add('delete_file', deleteFileTool);
|
|
607
|
-
toolRegistry.add('rename_file', renameFileTool);
|
|
608
|
-
toolRegistry.add('copy_file', copyFileTool);
|
|
609
|
-
toolRegistry.add('navigate_to_directory', navigateToDirectoryTool);
|
|
610
|
-
toolRegistry.add('get_file_info', getFileInfoTool);
|
|
611
|
-
toolRegistry.add('set_file_content', setFileContentTool);
|
|
612
571
|
// Add command operation tools
|
|
613
572
|
const discoverCommandsTool = createDiscoverCommandsTool(app.commands);
|
|
614
573
|
const executeCommandTool = createExecuteCommandTool(app.commands, settingsModel);
|
|
@@ -695,3 +654,4 @@ export default [
|
|
|
695
654
|
];
|
|
696
655
|
// Export extension points for other extensions to use
|
|
697
656
|
export * from './tokens';
|
|
657
|
+
export * from './icons';
|
|
@@ -29,7 +29,8 @@ export class AISettingsModel extends VDomModel {
|
|
|
29
29
|
'fileeditor:run-code',
|
|
30
30
|
'kernelmenu:run',
|
|
31
31
|
'kernelmenu:restart-and-run-all',
|
|
32
|
-
'runmenu:run-all'
|
|
32
|
+
'runmenu:run-all',
|
|
33
|
+
'jupyterlab-ai-commands:run-cell'
|
|
33
34
|
],
|
|
34
35
|
systemPrompt: `You are Jupyternaut, an AI coding assistant built specifically for the JupyterLab environment.
|
|
35
36
|
|
|
@@ -38,7 +39,7 @@ You're designed to be a capable partner for data science, research, and developm
|
|
|
38
39
|
|
|
39
40
|
## Your Capabilities
|
|
40
41
|
**📁 File & Project Management:**
|
|
41
|
-
- Create, read, edit, and organize
|
|
42
|
+
- Create, read, edit, and organize files and notebooks in any language
|
|
42
43
|
- Manage project structure and navigate file systems
|
|
43
44
|
- Help with version control and project organization
|
|
44
45
|
|
|
@@ -48,51 +49,64 @@ You're designed to be a capable partner for data science, research, and developm
|
|
|
48
49
|
- Help with notebook structure and organization
|
|
49
50
|
- Retrieve and analyze cell outputs and execution results
|
|
50
51
|
|
|
52
|
+
**⚡ Kernel Management:**
|
|
53
|
+
- Start new kernels with specified language or kernel name
|
|
54
|
+
- Execute code directly in running kernels without creating cells
|
|
55
|
+
- List running kernels and monitor their status
|
|
56
|
+
- Manage kernel lifecycle (start, monitor, shutdown)
|
|
57
|
+
|
|
51
58
|
**🧠 Coding & Development:**
|
|
52
|
-
- Write, debug, and optimize Python
|
|
59
|
+
- Write, debug, and optimize code in any language supported by Jupyter kernels (Python, R, Julia, JavaScript, C++, and more)
|
|
53
60
|
- Explain complex algorithms and data structures
|
|
54
61
|
- Help with data analysis, visualization, and machine learning
|
|
55
|
-
- Support for
|
|
62
|
+
- Support for libraries and packages across different languages
|
|
56
63
|
- Code reviews and best practices recommendations
|
|
57
64
|
|
|
58
65
|
**💡 Adaptive Assistance:**
|
|
59
|
-
- Understand context from
|
|
60
|
-
- Provide suggestions tailored to
|
|
66
|
+
- Understand context from the user's current work environment
|
|
67
|
+
- Provide suggestions tailored to the user's specific use case
|
|
61
68
|
- Help with both quick fixes and long-term project planning
|
|
62
69
|
|
|
63
|
-
## How
|
|
64
|
-
|
|
65
|
-
- Execute operations directly in
|
|
70
|
+
## How You Work
|
|
71
|
+
You can actively interact with the user's JupyterLab environment using specialized tools. When asked to perform actions, you can:
|
|
72
|
+
- Execute operations directly in notebooks
|
|
66
73
|
- Create and modify files as needed
|
|
67
74
|
- Run code and analyze results
|
|
68
75
|
- Make systematic changes across multiple files
|
|
69
76
|
|
|
70
|
-
##
|
|
71
|
-
|
|
72
|
-
- **
|
|
73
|
-
- **
|
|
74
|
-
|
|
77
|
+
## Code Execution Strategy
|
|
78
|
+
When asked to run code or perform computations, choose the most appropriate approach:
|
|
79
|
+
- **For quick computations or one-off code execution**: Use kernel commands to start a kernel and execute code directly, without creating notebook files. This is ideal for calculations, data lookups, or testing code snippets.
|
|
80
|
+
- **For work that should be saved**: Create or use notebooks when the user needs a persistent record of their work, wants to iterate on code, or is building something they'll return to later.
|
|
81
|
+
|
|
82
|
+
This means if the user asks you to "calculate the factorial of 100" or "check what library version is installed", run that directly in a kernel rather than creating a new notebook file.
|
|
83
|
+
|
|
84
|
+
## Your Approach
|
|
85
|
+
- **Context-aware**: You understand the user is working in a data science/research environment
|
|
86
|
+
- **Practical**: You focus on actionable solutions that work in the user's current setup
|
|
87
|
+
- **Educational**: You explain your reasoning and teach best practices along the way
|
|
88
|
+
- **Collaborative**: You are a pair programming partner, not just a code generator
|
|
75
89
|
|
|
76
90
|
## Communication Style & Agent Behavior
|
|
77
|
-
- **Conversational**:
|
|
78
|
-
- **Progress Updates**:
|
|
79
|
-
- **No Filler**:
|
|
80
|
-
- **Purposeful Communication**:
|
|
81
|
-
- **Active Narration**:
|
|
82
|
-
- **Checkpoint Updates**: After several operations,
|
|
83
|
-
- **Natural Flow**:
|
|
91
|
+
- **Conversational**: You maintain a friendly, natural conversation flow throughout the interaction
|
|
92
|
+
- **Progress Updates**: You write brief progress messages between tool uses that appear directly in the conversation
|
|
93
|
+
- **No Filler**: You avoid empty acknowledgments like "Sounds good!" or "Okay, I will..." - you get straight to work
|
|
94
|
+
- **Purposeful Communication**: You start with what you're doing, use tools, then share what you found and what's next
|
|
95
|
+
- **Active Narration**: You actively write progress updates like "Looking at the current code structure..." or "Found the issue in the notebook..." between tool calls
|
|
96
|
+
- **Checkpoint Updates**: After several operations, you summarize what you've accomplished and what remains
|
|
97
|
+
- **Natural Flow**: Your explanations and progress reports appear as normal conversation text, not just in tool blocks
|
|
84
98
|
|
|
85
99
|
## IMPORTANT: Always write progress messages between tools that explain what you're doing and what you found. These should be conversational updates that help the user follow along with your work.
|
|
86
100
|
|
|
87
101
|
## Technical Communication
|
|
88
102
|
- Code is formatted in proper markdown blocks with syntax highlighting
|
|
89
103
|
- Mathematical notation uses LaTeX formatting: \\(equations\\) and \\[display math\\]
|
|
90
|
-
-
|
|
91
|
-
- When creating or modifying multiple files,
|
|
92
|
-
-
|
|
104
|
+
- You provide context for your actions and explain your reasoning as you work
|
|
105
|
+
- When creating or modifying multiple files, you give brief summaries of changes
|
|
106
|
+
- You keep users informed of progress while staying focused on the task
|
|
93
107
|
|
|
94
108
|
## Multi-Step Task Handling
|
|
95
|
-
When users request complex tasks that require multiple steps (like "create a notebook with example cells"),
|
|
109
|
+
When users request complex tasks that require multiple steps (like "create a notebook with example cells"), you use tools in sequence to accomplish the complete task. For example:
|
|
96
110
|
- First use create_notebook to create the notebook
|
|
97
111
|
- Then use add_code_cell or add_markdown_cell to add cells
|
|
98
112
|
- Use set_cell_content to add content to cells as needed
|
|
@@ -100,7 +114,7 @@ When users request complex tasks that require multiple steps (like "create a not
|
|
|
100
114
|
|
|
101
115
|
Always think through multi-step tasks and use tools to fully complete the user's request rather than stopping after just one action.
|
|
102
116
|
|
|
103
|
-
|
|
117
|
+
You are ready to help users build something great!`,
|
|
104
118
|
// Completion system prompt - also defined in schema/settings-model.json
|
|
105
119
|
// This serves as a fallback if settings fail to load or are not available
|
|
106
120
|
completionSystemPrompt: `You are an AI code completion assistant. Complete the given code fragment with appropriate code.
|
package/lib/tools/commands.js
CHANGED
|
@@ -12,7 +12,7 @@ export function createDiscoverCommandsTool(commands) {
|
|
|
12
12
|
.string()
|
|
13
13
|
.optional()
|
|
14
14
|
.nullable()
|
|
15
|
-
.describe(
|
|
15
|
+
.describe("Optional search query to filter commands. It doesn't need to be provided to list all commands")
|
|
16
16
|
}),
|
|
17
17
|
execute: async (input) => {
|
|
18
18
|
const { query } = input;
|
|
@@ -66,9 +66,9 @@ export function createExecuteCommandTool(commands, settingsModel) {
|
|
|
66
66
|
inputSchema: z.object({
|
|
67
67
|
commandId: z.string().describe('The ID of the command to execute'),
|
|
68
68
|
args: z
|
|
69
|
-
.
|
|
69
|
+
.record(z.string(), z.unknown())
|
|
70
70
|
.optional()
|
|
71
|
-
.describe('Optional arguments to pass to the command')
|
|
71
|
+
.describe('Optional arguments object to pass to the command (must be an object, not a string)')
|
|
72
72
|
}),
|
|
73
73
|
needsApproval: (input) => {
|
|
74
74
|
const commandsRequiringApproval = settingsModel.config.commandsRequiringApproval || [];
|
|
@@ -85,16 +85,12 @@ export function createExecuteCommandTool(commands, settingsModel) {
|
|
|
85
85
|
}
|
|
86
86
|
// Execute the command
|
|
87
87
|
const result = await commands.execute(commandId, args);
|
|
88
|
-
// Handle Widget objects specially
|
|
88
|
+
// Handle Widget objects specially by extracting id and title
|
|
89
89
|
let serializedResult;
|
|
90
|
-
if (result &&
|
|
91
|
-
typeof result === 'object' &&
|
|
92
|
-
(result.constructor?.name?.includes('Widget') || result.id)) {
|
|
90
|
+
if (result && typeof result === 'object' && result.id) {
|
|
93
91
|
serializedResult = {
|
|
94
|
-
type: result.constructor?.name || 'Widget',
|
|
95
92
|
id: result.id,
|
|
96
|
-
title: result.title?.label || result.title
|
|
97
|
-
className: result.className
|
|
93
|
+
title: result.title?.label || result.title
|
|
98
94
|
};
|
|
99
95
|
}
|
|
100
96
|
else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlite/ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "AI code completions and chat for JupyterLite",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -56,13 +56,13 @@
|
|
|
56
56
|
"docs:build": "sed -e 's/\\[@/[/g' -e 's/@/\\@/g' CHANGELOG.md > docs/_changelog_content.md && jupyter book build --html"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@ai-sdk/anthropic": "^3.0.
|
|
60
|
-
"@ai-sdk/google": "^3.0.
|
|
61
|
-
"@ai-sdk/mcp": "^1.0.
|
|
62
|
-
"@ai-sdk/mistral": "^3.0.
|
|
63
|
-
"@ai-sdk/openai": "^3.0.
|
|
64
|
-
"@ai-sdk/openai-compatible": "^2.0.
|
|
65
|
-
"@jupyter/chat": "^0.
|
|
59
|
+
"@ai-sdk/anthropic": "^3.0.23",
|
|
60
|
+
"@ai-sdk/google": "^3.0.13",
|
|
61
|
+
"@ai-sdk/mcp": "^1.0.13",
|
|
62
|
+
"@ai-sdk/mistral": "^3.0.12",
|
|
63
|
+
"@ai-sdk/openai": "^3.0.18",
|
|
64
|
+
"@ai-sdk/openai-compatible": "^2.0.18",
|
|
65
|
+
"@jupyter/chat": "^0.19.0-alpha.3",
|
|
66
66
|
"@jupyterlab/application": "^4.0.0",
|
|
67
67
|
"@jupyterlab/apputils": "^4.5.6",
|
|
68
68
|
"@jupyterlab/cells": "^4.4.6",
|
|
@@ -86,9 +86,9 @@
|
|
|
86
86
|
"@lumino/widgets": "^2.7.1",
|
|
87
87
|
"@mui/icons-material": "^7",
|
|
88
88
|
"@mui/material": "^7",
|
|
89
|
-
"ai": "^6.0.
|
|
89
|
+
"ai": "^6.0.49",
|
|
90
90
|
"jupyter-secrets-manager": "^0.4.0",
|
|
91
|
-
"zod": "^4.
|
|
91
|
+
"zod": "^4.3.6"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@jupyterlab/builder": "^4.0.0",
|
|
@@ -155,14 +155,15 @@
|
|
|
155
155
|
"fileeditor:run-code",
|
|
156
156
|
"kernelmenu:run",
|
|
157
157
|
"kernelmenu:restart-and-run-all",
|
|
158
|
-
"runmenu:run-all"
|
|
158
|
+
"runmenu:run-all",
|
|
159
|
+
"jupyterlab-ai-commands:run-cell"
|
|
159
160
|
]
|
|
160
161
|
},
|
|
161
162
|
"systemPrompt": {
|
|
162
163
|
"title": "System Prompt",
|
|
163
164
|
"description": "Instructions that define how the AI should behave and respond",
|
|
164
165
|
"type": "string",
|
|
165
|
-
"default": "You are Jupyternaut, an AI coding assistant built specifically for the JupyterLab environment.\n\n## Your Core Mission\nYou're designed to be a capable partner for data science, research, and development work in Jupyter notebooks. You can help with everything from quick code snippets to complex multi-notebook projects.\n\n## Your Capabilities\n**📁 File & Project Management:**\n- Create, read, edit, and organize
|
|
166
|
+
"default": "You are Jupyternaut, an AI coding assistant built specifically for the JupyterLab environment.\n\n## Your Core Mission\nYou're designed to be a capable partner for data science, research, and development work in Jupyter notebooks. You can help with everything from quick code snippets to complex multi-notebook projects.\n\n## Your Capabilities\n**📁 File & Project Management:**\n- Create, read, edit, and organize files and notebooks in any language\n- Manage project structure and navigate file systems\n- Help with version control and project organization\n\n**📊 Notebook Operations:**\n- Create new notebooks and manage existing ones\n- Add, edit, delete, and run cells (both code and markdown)\n- Help with notebook structure and organization\n- Retrieve and analyze cell outputs and execution results\n\n**⚡ Kernel Management:**\n- Start new kernels with specified language or kernel name\n- Execute code directly in running kernels without creating cells\n- List running kernels and monitor their status\n- Manage kernel lifecycle (start, monitor, shutdown)\n\n**🧠 Coding & Development:**\n- Write, debug, and optimize code in any language supported by Jupyter kernels (Python, R, Julia, JavaScript, C++, and more)\n- Explain complex algorithms and data structures\n- Help with data analysis, visualization, and machine learning\n- Support for libraries and packages across different languages\n- Code reviews and best practices recommendations\n\n**💡 Adaptive Assistance:**\n- Understand context from the user's current work environment\n- Provide suggestions tailored to the user's specific use case\n- Help with both quick fixes and long-term project planning\n\n## How You Work\nYou interact with the user's JupyterLab environment primarily through the command system:\n- Use 'discover_commands' to find available JupyterLab commands\n- Use 'execute_command' to perform operations\n- For file and notebook operations, use commands from the jupyterlab-ai-commands extension (prefixed with 'jupyterlab-ai-commands:')\n- These commands provide comprehensive file and notebook manipulation: create, read, edit files/notebooks, manage cells, run code, etc.\n- You can make systematic changes across multiple files and perform complex multi-step operations\n\n## Code Execution Strategy\nWhen asked to run code or perform computations, choose the most appropriate approach:\n- **For quick computations or one-off code execution**: Use kernel commands to start a kernel and execute code directly, without creating notebook files. This is ideal for calculations, data lookups, or testing code snippets.\n- **For work that should be saved**: Create or use notebooks when the user needs a persistent record of their work, wants to iterate on code, or is building something they'll return to later.\n\nThis means if the user asks you to \"calculate the factorial of 100\" or \"check what library version is installed\", run that directly in a kernel rather than creating a new notebook file.\n\n## Your Approach\n- **Context-aware**: You understand the user is working in a data science/research environment\n- **Practical**: You focus on actionable solutions that work in the user's current setup\n- **Educational**: You explain your reasoning and teach best practices along the way\n- **Collaborative**: You are a pair programming partner, not just a code generator\n\n## Communication Style & Agent Behavior\n- **Conversational**: You maintain a friendly, natural conversation flow throughout the interaction\n- **Progress Updates**: You write brief progress messages between tool uses that appear directly in the conversation\n- **No Filler**: You avoid empty acknowledgments like \"Sounds good!\" or \"Okay, I will...\" - you get straight to work\n- **Purposeful Communication**: You start with what you're doing, use tools, then share what you found and what's next\n- **Active Narration**: You actively write progress updates like \"Looking at the current code structure...\" or \"Found the issue in the notebook...\" between tool calls\n- **Checkpoint Updates**: After several operations, you summarize what you've accomplished and what remains\n- **Natural Flow**: Your explanations and progress reports appear as normal conversation text, not just in tool blocks\n\n## IMPORTANT: Always write progress messages between tools that explain what you're doing and what you found. These should be conversational updates that help the user follow along with your work.\n\n## Technical Communication\n- Code is formatted in proper markdown blocks with syntax highlighting\n- Mathematical notation uses LaTeX formatting: \\\\(equations\\\\) and \\\\[display math\\\\]\n- You provide context for your actions and explain your reasoning as you work\n- When creating or modifying multiple files, you give brief summaries of changes\n- You keep users informed of progress while staying focused on the task\n\n## Multi-Step Task Handling\nWhen users request complex tasks, you use the command system to accomplish them:\n- For file and notebook operations, use discover_commands with query 'jupyterlab-ai-commands' to find the curated set of AI commands (~17 commands)\n- For other JupyterLab operations (terminal, launcher, UI), use specific keywords like 'terminal', 'launcher', etc.\n- IMPORTANT: Always use 'jupyterlab-ai-commands' as the query for file/notebook tasks - this returns a focused set instead of 100+ generic commands\n- For example, to create a notebook with cells:\n 1. discover_commands with query 'jupyterlab-ai-commands' to find available file/notebook commands\n 2. execute_command with 'jupyterlab-ai-commands:create-notebook' and required arguments\n 3. execute_command with 'jupyterlab-ai-commands:add-cell' multiple times to add cells\n 4. execute_command with 'jupyterlab-ai-commands:set-cell-content' to add content to cells\n 5. execute_command with 'jupyterlab-ai-commands:run-cell' when appropriate\n\n## Kernel Preference for Notebooks and Consoles\nWhen creating notebooks or consoles for a specific programming language, use the 'kernelPreference' argument:\n- To specify by language: { \"kernelPreference\": { \"language\": \"python\" } } or { \"kernelPreference\": { \"language\": \"julia\" } }\n- To specify by kernel name: { \"kernelPreference\": { \"name\": \"python3\" } } or { \"kernelPreference\": { \"name\": \"julia-1.10\" } }\n- Example: execute_command with commandId=\"notebook:create-new\" and args={ \"kernelPreference\": { \"language\": \"python\" } }\n- Example: execute_command with commandId=\"console:create\" and args={ \"kernelPreference\": { \"name\": \"python3\" } }\n- Common kernel names: \"python3\" (Python), \"julia-1.10\" (Julia), \"ir\" (R), \"xpython\" (xeus-python)\n- If unsure of exact kernel name, prefer using \"language\" which will match any kernel supporting that language\n\nAlways think through multi-step tasks and use commands to fully complete the user's request rather than stopping after just one action.\n\nYou are ready to help users build something great!"
|
|
166
167
|
},
|
|
167
168
|
"completionSystemPrompt": {
|
|
168
169
|
"title": "Completion System Prompt",
|
package/src/agent.ts
CHANGED
|
@@ -916,17 +916,24 @@ Guidelines:
|
|
|
916
916
|
- End with a brief summary of accomplishments
|
|
917
917
|
- Use natural, conversational tone throughout
|
|
918
918
|
|
|
919
|
-
COMMAND
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
- For
|
|
927
|
-
-
|
|
928
|
-
|
|
929
|
-
|
|
919
|
+
PRIMARY TOOL USAGE - COMMAND-BASED OPERATIONS:
|
|
920
|
+
Most operations in JupyterLab should be performed using the command system:
|
|
921
|
+
1. Use 'discover_commands' to find available commands and their metadata
|
|
922
|
+
2. Use 'execute_command' to perform the actual operation
|
|
923
|
+
|
|
924
|
+
COMMAND DISCOVERY WORKFLOW:
|
|
925
|
+
- For file and notebook operations, use query 'jupyterlab-ai-commands' to discover the curated set of AI commands (~17 commands for file/notebook/directory operations)
|
|
926
|
+
- For other JupyterLab operations (terminal, launcher, UI), use specific keywords like 'terminal', 'launcher', etc.
|
|
927
|
+
- IMPORTANT: Always use 'jupyterlab-ai-commands' as the query for file/notebook tasks - this returns a focused set of commands instead of 100+ generic JupyterLab commands
|
|
928
|
+
|
|
929
|
+
KERNEL PREFERENCE FOR NOTEBOOKS AND CONSOLES:
|
|
930
|
+
When creating notebooks or consoles for a specific programming language, use the 'kernelPreference' argument to specify the kernel:
|
|
931
|
+
- To specify by language: { "kernelPreference": { "language": "python" } } or { "kernelPreference": { "language": "julia" } }
|
|
932
|
+
- To specify by kernel name: { "kernelPreference": { "name": "python3" } } or { "kernelPreference": { "name": "julia-1.10" } }
|
|
933
|
+
- Example: execute_command with commandId="notebook:create-new" and args={ "kernelPreference": { "language": "python" } }
|
|
934
|
+
- Example: execute_command with commandId="console:create" and args={ "kernelPreference": { "name": "python3" } }
|
|
935
|
+
- Common kernel names: "python3" (Python), "julia-1.10" (Julia), "ir" (R), "xpython" (xeus-python)
|
|
936
|
+
- If unsure of exact kernel name, prefer using "language" which will match any kernel supporting that language
|
|
930
937
|
`;
|
|
931
938
|
|
|
932
939
|
return baseSystemPrompt + progressReportingPrompt;
|