@jupyterlite/ai 0.10.0 → 0.11.1

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 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 DISCOVERY:
658
- - When you want to execute JupyterLab commands, ALWAYS use the 'discover_commands' tool first to find available commands and their metadata, with the optional query parameter.
659
- - The query should typically be a single word, e.g., 'terminal', 'notebook', 'cell', 'file', 'edit', 'view', 'run', etc, to find relevant commands.
660
- - If searching with a query does not yield the desired command, try again with a different query or use an empty query to list all commands.
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
- TOOL SELECTION GUIDELINES:
664
- - For file operations (create, read, write, modify files and directories): Use dedicated file manipulation tools
665
- - For general JupyterLab UI interactions (opening panels, running commands, navigating interface): Use the general command tool (execute_command)
666
- - Examples of file operations: Creating notebooks, editing code files, managing project structure
667
- - Examples of UI interactions: Opening terminal, switching tabs, running notebook cells, accessing menus
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
  }
@@ -15,6 +15,11 @@ export declare class ChatModelRegistry implements IChatModelRegistry {
15
15
  get(name: string): AIChatModel | undefined;
16
16
  getAll(): AIChatModel[];
17
17
  remove(name: string): void;
18
+ /**
19
+ * Getter/setter for the active cell manager.
20
+ */
21
+ get activeCellManager(): ActiveCellManager | undefined;
22
+ set activeCellManager(manager: ActiveCellManager | undefined);
18
23
  private _models;
19
24
  private _docManager;
20
25
  private _agentManagerFactory;
@@ -49,7 +54,7 @@ export declare namespace ChatModelRegistry {
49
54
  /**
50
55
  * The active cell manager.
51
56
  */
52
- activeCellManager: ActiveCellManager | undefined;
57
+ activeCellManager?: ActiveCellManager | undefined;
53
58
  /**
54
59
  * The application language translation bundle.
55
60
  */
@@ -52,6 +52,9 @@ export class ChatModelRegistry {
52
52
  add(model) {
53
53
  if (!this._models.find(m => m.name === model.name)) {
54
54
  this._models.push(model);
55
+ model.disposed.connect(() => {
56
+ this.remove(model.name);
57
+ });
55
58
  }
56
59
  }
57
60
  get(name) {
@@ -66,6 +69,15 @@ export class ChatModelRegistry {
66
69
  this._models.splice(index, 1);
67
70
  }
68
71
  }
72
+ /**
73
+ * Getter/setter for the active cell manager.
74
+ */
75
+ get activeCellManager() {
76
+ return this._activeCellManager;
77
+ }
78
+ set activeCellManager(manager) {
79
+ this._activeCellManager = manager;
80
+ }
69
81
  _models = [];
70
82
  _docManager;
71
83
  _agentManagerFactory;
@@ -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
- size: 'small',
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 { TooltippedButton } from '@jupyter/chat';
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(TooltippedButton, { onClick: props.stopStreaming, tooltip: tooltip, buttonProps: {
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
- size: 'small',
68
- variant: selectedToolNames.length > 0 ? 'contained' : 'outlined',
69
- color: 'primary',
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, null)),
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';
@@ -109,20 +105,11 @@ const chatModelRegistry = {
109
105
  description: 'Registry for the current chat model',
110
106
  autoStart: true,
111
107
  requires: [IAISettingsModel, IAgentManagerFactory, IDocumentManager],
112
- optional: [IProviderRegistry, INotebookTracker, IToolRegistry, ITranslator],
108
+ optional: [IProviderRegistry, IToolRegistry, ITranslator],
113
109
  provides: IChatModelRegistry,
114
- activate: (app, settingsModel, agentManagerFactory, docManager, providerRegistry, notebookTracker, toolRegistry, translator) => {
110
+ activate: (app, settingsModel, agentManagerFactory, docManager, providerRegistry, toolRegistry, translator) => {
115
111
  const trans = (translator ?? nullTranslator).load('jupyterlite_ai');
116
- // Create ActiveCellManager if notebook tracker is available
117
- let activeCellManager;
118
- if (notebookTracker) {
119
- activeCellManager = new ActiveCellManager({
120
- tracker: notebookTracker,
121
- shell: app.shell
122
- });
123
- }
124
112
  return new ChatModelRegistry({
125
- activeCellManager,
126
113
  settingsModel,
127
114
  agentManagerFactory,
128
115
  docManager,
@@ -145,8 +132,14 @@ const plugin = {
145
132
  IChatModelRegistry,
146
133
  IAISettingsModel
147
134
  ],
148
- optional: [IThemeManager, ILayoutRestorer, ILabShell, ITranslator],
149
- activate: (app, rmRegistry, inputToolbarFactory, modelRegistry, settingsModel, themeManager, restorer, labShell, translator) => {
135
+ optional: [
136
+ IThemeManager,
137
+ ILayoutRestorer,
138
+ ILabShell,
139
+ INotebookTracker,
140
+ ITranslator
141
+ ],
142
+ activate: (app, rmRegistry, inputToolbarFactory, modelRegistry, settingsModel, themeManager, restorer, labShell, notebookTracker, translator) => {
150
143
  const trans = (translator ?? nullTranslator).load('jupyterlite_ai');
151
144
  // Create attachment opener registry to handle file attachments
152
145
  const attachmentOpenerRegistry = new AttachmentOpenerRegistry();
@@ -156,6 +149,16 @@ const plugin = {
156
149
  attachmentOpenerRegistry.set('notebook', attachment => {
157
150
  app.commands.execute('docmanager:open', { path: attachment.value });
158
151
  });
152
+ // Create ActiveCellManager if notebook tracker is available, and add it to the
153
+ // model registry.
154
+ let activeCellManager;
155
+ if (notebookTracker) {
156
+ activeCellManager = new ActiveCellManager({
157
+ tracker: notebookTracker,
158
+ shell: app.shell
159
+ });
160
+ }
161
+ modelRegistry.activeCellManager = activeCellManager;
159
162
  // Create chat panel with drag/drop functionality
160
163
  const chatPanel = new MultiChatPanel({
161
164
  rmRegistry,
@@ -568,47 +571,10 @@ const toolRegistry = {
568
571
  id: '@jupyterlite/ai:tool-registry',
569
572
  description: 'Provide the AI tool registry',
570
573
  autoStart: true,
571
- requires: [IAISettingsModel, IDocumentManager, IKernelSpecManager],
572
- optional: [INotebookTracker, IDiffManager, IEditorTracker],
574
+ requires: [IAISettingsModel],
573
575
  provides: IToolRegistry,
574
- activate: (app, settingsModel, docManager, kernelSpecManager, notebookTracker, diffManager, editorTracker) => {
576
+ activate: (app, settingsModel) => {
575
577
  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
578
  // Add command operation tools
613
579
  const discoverCommandsTool = createDiscoverCommandsTool(app.commands);
614
580
  const executeCommandTool = createExecuteCommandTool(app.commands, settingsModel);
@@ -695,3 +661,4 @@ export default [
695
661
  ];
696
662
  // Export extension points for other extensions to use
697
663
  export * from './tokens';
664
+ 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 Python files and notebooks
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 code
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 scientific computing libraries (numpy, pandas, matplotlib, etc.)
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 your current work environment
60
- - Provide suggestions tailored to your specific use case
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 I Work
64
- I can actively interact with your JupyterLab environment using specialized tools. When you ask me to perform actions, I can:
65
- - Execute operations directly in your notebooks
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
- ## My Approach
71
- - **Context-aware**: I understand you're working in a data science/research environment
72
- - **Practical**: I focus on actionable solutions that work in your current setup
73
- - **Educational**: I explain my reasoning and teach best practices along the way
74
- - **Collaborative**: Think of me as a pair programming partner, not just a code generator
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**: I maintain a friendly, natural conversation flow throughout our interaction
78
- - **Progress Updates**: I write brief progress messages between tool uses that appear directly in our conversation
79
- - **No Filler**: I avoid empty acknowledgments like "Sounds good!" or "Okay, I will..." - I get straight to work
80
- - **Purposeful Communication**: I start with what I'm doing, use tools, then share what I found and what's next
81
- - **Active Narration**: I actively write progress updates like "Looking at the current code structure..." or "Found the issue in the notebook..." between tool calls
82
- - **Checkpoint Updates**: After several operations, I summarize what I've accomplished and what remains
83
- - **Natural Flow**: My explanations and progress reports appear as normal conversation text, not just in tool blocks
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
- - I provide context for my actions and explain my reasoning as I work
91
- - When creating or modifying multiple files, I give brief summaries of changes
92
- - I keep users informed of progress while staying focused on the task
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"), I use tools in sequence to accomplish the complete task. For example:
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
- Ready to help you build something great! What are you working on?`,
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/tokens.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ActiveCellManager } from '@jupyter/chat';
1
2
  import { Token } from '@lumino/coreutils';
2
3
  import { ISignal } from '@lumino/signaling';
3
4
  import type { Tool, LanguageModel } from 'ai';
@@ -194,6 +195,7 @@ export interface IChatModelRegistry {
194
195
  getAll(): AIChatModel[];
195
196
  remove(name: string): void;
196
197
  createModel(name?: string, activeProvider?: string, tokenUsage?: ITokenUsage): AIChatModel;
198
+ activeCellManager: ActiveCellManager | undefined;
197
199
  }
198
200
  export declare const IChatModelRegistry: Token<IChatModelRegistry>;
199
201
  /**
@@ -12,7 +12,7 @@ export function createDiscoverCommandsTool(commands) {
12
12
  .string()
13
13
  .optional()
14
14
  .nullable()
15
- .describe('Optional search query to filter commands')
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
- .any()
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 (including subclasses like DocumentWidget)
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.10.0",
3
+ "version": "0.11.1",
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/@/\\&#64;/g' CHANGELOG.md > docs/_changelog_content.md && jupyter book build --html"
57
57
  },
58
58
  "dependencies": {
59
- "@ai-sdk/anthropic": "^3.0.1",
60
- "@ai-sdk/google": "^3.0.1",
61
- "@ai-sdk/mcp": "^1.0.1",
62
- "@ai-sdk/mistral": "^3.0.1",
63
- "@ai-sdk/openai": "^3.0.1",
64
- "@ai-sdk/openai-compatible": "^2.0.1",
65
- "@jupyter/chat": "^0.18.2",
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.0",
89
+ "ai": "^6.0.49",
90
90
  "jupyter-secrets-manager": "^0.4.0",
91
- "zod": "^4.2.1"
91
+ "zod": "^4.3.6"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@jupyterlab/builder": "^4.0.0",