@jupyterlite/ai 0.9.1 → 0.10.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.
Files changed (66) hide show
  1. package/README.md +5 -214
  2. package/lib/agent.d.ts +58 -66
  3. package/lib/agent.js +274 -300
  4. package/lib/approval-buttons.d.ts +19 -82
  5. package/lib/approval-buttons.js +36 -289
  6. package/lib/chat-model-registry.d.ts +6 -0
  7. package/lib/chat-model-registry.js +4 -1
  8. package/lib/chat-model.d.ts +19 -54
  9. package/lib/chat-model.js +243 -303
  10. package/lib/components/clear-button.d.ts +6 -1
  11. package/lib/components/clear-button.js +8 -3
  12. package/lib/components/completion-status.d.ts +5 -0
  13. package/lib/components/completion-status.js +5 -4
  14. package/lib/components/model-select.d.ts +6 -1
  15. package/lib/components/model-select.js +9 -8
  16. package/lib/components/stop-button.d.ts +6 -1
  17. package/lib/components/stop-button.js +8 -3
  18. package/lib/components/token-usage-display.d.ts +5 -0
  19. package/lib/components/token-usage-display.js +2 -2
  20. package/lib/components/tool-select.d.ts +6 -1
  21. package/lib/components/tool-select.js +6 -5
  22. package/lib/index.js +58 -38
  23. package/lib/models/settings-model.d.ts +1 -1
  24. package/lib/providers/built-in-providers.js +38 -19
  25. package/lib/providers/models.d.ts +3 -3
  26. package/lib/providers/provider-registry.d.ts +3 -4
  27. package/lib/providers/provider-registry.js +1 -4
  28. package/lib/tokens.d.ts +5 -6
  29. package/lib/tools/commands.d.ts +2 -1
  30. package/lib/tools/commands.js +37 -46
  31. package/lib/tools/file.js +49 -73
  32. package/lib/tools/notebook.js +370 -445
  33. package/lib/widgets/ai-settings.d.ts +6 -0
  34. package/lib/widgets/ai-settings.js +72 -71
  35. package/lib/widgets/main-area-chat.d.ts +2 -0
  36. package/lib/widgets/main-area-chat.js +5 -2
  37. package/lib/widgets/provider-config-dialog.d.ts +2 -0
  38. package/lib/widgets/provider-config-dialog.js +34 -34
  39. package/package.json +12 -12
  40. package/src/agent.ts +342 -361
  41. package/src/approval-buttons.ts +43 -389
  42. package/src/chat-model-registry.ts +9 -1
  43. package/src/chat-model.ts +355 -370
  44. package/src/completion/completion-provider.ts +2 -3
  45. package/src/components/clear-button.tsx +16 -3
  46. package/src/components/completion-status.tsx +18 -4
  47. package/src/components/model-select.tsx +21 -8
  48. package/src/components/stop-button.tsx +16 -3
  49. package/src/components/token-usage-display.tsx +14 -2
  50. package/src/components/tool-select.tsx +23 -5
  51. package/src/index.ts +75 -36
  52. package/src/models/settings-model.ts +1 -1
  53. package/src/providers/built-in-providers.ts +38 -19
  54. package/src/providers/models.ts +3 -3
  55. package/src/providers/provider-registry.ts +4 -8
  56. package/src/tokens.ts +5 -6
  57. package/src/tools/commands.ts +39 -50
  58. package/src/tools/file.ts +49 -75
  59. package/src/tools/notebook.ts +451 -510
  60. package/src/widgets/ai-settings.tsx +153 -84
  61. package/src/widgets/main-area-chat.ts +8 -2
  62. package/src/widgets/provider-config-dialog.tsx +54 -41
  63. package/style/base.css +13 -73
  64. package/lib/mcp/browser.d.ts +0 -68
  65. package/lib/mcp/browser.js +0 -138
  66. package/src/mcp/browser.ts +0 -220
package/src/tools/file.ts CHANGED
@@ -4,7 +4,7 @@ import { IDocumentManager } from '@jupyterlab/docmanager';
4
4
  import { IDocumentWidget } from '@jupyterlab/docregistry';
5
5
  import { IEditorTracker } from '@jupyterlab/fileeditor';
6
6
 
7
- import { tool } from '@openai/agents';
7
+ import { tool } from 'ai';
8
8
 
9
9
  import { z } from 'zod';
10
10
 
@@ -15,10 +15,10 @@ import { IDiffManager, ITool } from '../tokens';
15
15
  */
16
16
  export function createNewFileTool(docManager: IDocumentManager): ITool {
17
17
  return tool({
18
- name: 'create_file',
18
+ title: 'New File',
19
19
  description:
20
20
  'Create a new file of specified type (text, python, markdown, json, etc.)',
21
- parameters: z.object({
21
+ inputSchema: z.object({
22
22
  fileName: z.string().describe('Name of the file to create'),
23
23
  fileType: z
24
24
  .string()
@@ -37,12 +37,6 @@ export function createNewFileTool(docManager: IDocumentManager): ITool {
37
37
  .nullable()
38
38
  .describe('Directory where to create the file (optional)')
39
39
  }),
40
- errorFunction: (context, error) => {
41
- return JSON.stringify({
42
- success: false,
43
- error: `Failed to create file: ${error instanceof Error ? error.message : String(error)}`
44
- });
45
- },
46
40
  execute: async (input: {
47
41
  fileName: string;
48
42
  fileType?: string;
@@ -106,24 +100,21 @@ export function createNewFileTool(docManager: IDocumentManager): ITool {
106
100
  */
107
101
  export function createOpenFileTool(docManager: IDocumentManager): ITool {
108
102
  return tool({
109
- name: 'open_file',
103
+ title: 'Open File',
110
104
  description: 'Open a file in the editor',
111
- parameters: z.object({
105
+ inputSchema: z.object({
112
106
  filePath: z.string().describe('Path to the file to open')
113
107
  }),
114
- errorFunction: (context, error) => {
115
- return JSON.stringify({
116
- success: false,
117
- error: `Failed to open file: ${error instanceof Error ? error.message : String(error)}`
118
- });
119
- },
120
108
  execute: async (input: { filePath: string }) => {
121
109
  const { filePath } = input;
122
110
 
123
111
  const widget = docManager.openOrReveal(filePath);
124
112
 
125
113
  if (!widget) {
126
- throw new Error(`Could not open file: ${filePath}`);
114
+ return {
115
+ success: false,
116
+ error: `Could not open file: ${filePath}`
117
+ };
127
118
  }
128
119
 
129
120
  return {
@@ -141,17 +132,11 @@ export function createOpenFileTool(docManager: IDocumentManager): ITool {
141
132
  */
142
133
  export function createDeleteFileTool(docManager: IDocumentManager): ITool {
143
134
  return tool({
144
- name: 'delete_file',
135
+ title: 'Delete File',
145
136
  description: 'Delete a file from the file system',
146
- parameters: z.object({
137
+ inputSchema: z.object({
147
138
  filePath: z.string().describe('Path to the file to delete')
148
139
  }),
149
- errorFunction: (context, error) => {
150
- return JSON.stringify({
151
- success: false,
152
- error: `Failed to delete file: ${error instanceof Error ? error.message : String(error)}`
153
- });
154
- },
155
140
  execute: async (input: { filePath: string }) => {
156
141
  const { filePath } = input;
157
142
 
@@ -171,18 +156,12 @@ export function createDeleteFileTool(docManager: IDocumentManager): ITool {
171
156
  */
172
157
  export function createRenameFileTool(docManager: IDocumentManager): ITool {
173
158
  return tool({
174
- name: 'rename_file',
159
+ title: 'Rename File',
175
160
  description: 'Rename a file or move it to a different location',
176
- parameters: z.object({
161
+ inputSchema: z.object({
177
162
  oldPath: z.string().describe('Current path of the file'),
178
163
  newPath: z.string().describe('New path/name for the file')
179
164
  }),
180
- errorFunction: (context, error) => {
181
- return JSON.stringify({
182
- success: false,
183
- error: `Failed to rename file: ${error instanceof Error ? error.message : String(error)}`
184
- });
185
- },
186
165
  execute: async (input: { oldPath: string; newPath: string }) => {
187
166
  const { oldPath, newPath } = input;
188
167
 
@@ -203,20 +182,14 @@ export function createRenameFileTool(docManager: IDocumentManager): ITool {
203
182
  */
204
183
  export function createCopyFileTool(docManager: IDocumentManager): ITool {
205
184
  return tool({
206
- name: 'copy_file',
185
+ title: 'Copy File',
207
186
  description: 'Copy a file to a new location',
208
- parameters: z.object({
187
+ inputSchema: z.object({
209
188
  sourcePath: z.string().describe('Path of the file to copy'),
210
189
  destinationPath: z
211
190
  .string()
212
191
  .describe('Destination path for the copied file')
213
192
  }),
214
- errorFunction: (context, error) => {
215
- return JSON.stringify({
216
- success: false,
217
- error: `Failed to copy file: ${error instanceof Error ? error.message : String(error)}`
218
- });
219
- },
220
193
  execute: async (input: { sourcePath: string; destinationPath: string }) => {
221
194
  const { sourcePath, destinationPath } = input;
222
195
 
@@ -239,17 +212,11 @@ export function createNavigateToDirectoryTool(
239
212
  commands: CommandRegistry
240
213
  ): ITool {
241
214
  return tool({
242
- name: 'navigate_to_directory',
215
+ title: 'Navigate to Directory',
243
216
  description: 'Navigate to a specific directory in the file browser',
244
- parameters: z.object({
217
+ inputSchema: z.object({
245
218
  directoryPath: z.string().describe('Path to the directory to navigate to')
246
219
  }),
247
- errorFunction: (context, error) => {
248
- return JSON.stringify({
249
- success: false,
250
- error: `Failed to navigate to directory: ${error instanceof Error ? error.message : String(error)}`
251
- });
252
- },
253
220
  execute: async (input: { directoryPath: string }) => {
254
221
  const { directoryPath } = input;
255
222
 
@@ -274,10 +241,10 @@ export function createGetFileInfoTool(
274
241
  editorTracker?: IEditorTracker
275
242
  ): ITool {
276
243
  return tool({
277
- name: 'get_file_info',
244
+ title: 'Get File Info',
278
245
  description:
279
246
  'Get information about a file including its path, name, extension, and content. Works with text-based files like Python files, markdown, JSON, etc. For Jupyter notebooks, use dedicated notebook tools instead. If no file path is provided, returns information about the currently active file in the editor.',
280
- parameters: z.object({
247
+ inputSchema: z.object({
281
248
  filePath: z
282
249
  .string()
283
250
  .optional()
@@ -286,12 +253,6 @@ export function createGetFileInfoTool(
286
253
  'Path to the file to read (e.g., "script.py", "README.md", "config.json"). If not provided, uses the currently active file in the editor.'
287
254
  )
288
255
  }),
289
- errorFunction: (context, error) => {
290
- return JSON.stringify({
291
- success: false,
292
- error: `Failed to get file info: ${error instanceof Error ? error.message : String(error)}`
293
- });
294
- },
295
256
  execute: async (input: { filePath?: string | null }) => {
296
257
  const { filePath } = input;
297
258
 
@@ -304,20 +265,27 @@ export function createGetFileInfoTool(
304
265
  null;
305
266
 
306
267
  if (!widget) {
307
- throw new Error(`Failed to open file at path: ${filePath}`);
268
+ return JSON.stringify({
269
+ success: false,
270
+ error: `Failed to open file at path: ${filePath}`
271
+ });
308
272
  }
309
273
  } else {
310
274
  widget = editorTracker?.currentWidget ?? null;
311
275
 
312
276
  if (!widget) {
313
- throw new Error(
314
- 'No active file in the editor and no file path provided'
315
- );
277
+ return JSON.stringify({
278
+ success: false,
279
+ error: 'No active file in the editor and no file path provided'
280
+ });
316
281
  }
317
282
  }
318
283
 
319
284
  if (!widget.context) {
320
- throw new Error('Widget is not a document');
285
+ return JSON.stringify({
286
+ success: false,
287
+ error: 'Widget is not a document'
288
+ });
321
289
  }
322
290
 
323
291
  await widget.context.ready;
@@ -325,7 +293,10 @@ export function createGetFileInfoTool(
325
293
  const model = widget.context.model;
326
294
 
327
295
  if (!model) {
328
- throw new Error('File model not available');
296
+ return JSON.stringify({
297
+ success: false,
298
+ error: 'File model not available'
299
+ });
329
300
  }
330
301
 
331
302
  const sharedModel = model.sharedModel;
@@ -356,10 +327,10 @@ export function createSetFileContentTool(
356
327
  diffManager?: IDiffManager
357
328
  ): ITool {
358
329
  return tool({
359
- name: 'set_file_content',
330
+ title: 'Set File Content',
360
331
  description:
361
332
  'Set or update the content of an existing file. This will replace the entire content of the file. For Jupyter notebooks, use dedicated notebook tools instead.',
362
- parameters: z.object({
333
+ inputSchema: z.object({
363
334
  filePath: z
364
335
  .string()
365
336
  .describe(
@@ -372,12 +343,6 @@ export function createSetFileContentTool(
372
343
  .default(true)
373
344
  .describe('Whether to save the file after updating (default: true)')
374
345
  }),
375
- errorFunction: (context, error) => {
376
- return JSON.stringify({
377
- success: false,
378
- error: `Failed to set file content: ${error instanceof Error ? error.message : String(error)}`
379
- });
380
- },
381
346
  execute: async (input: {
382
347
  filePath: string;
383
348
  content: string;
@@ -392,7 +357,10 @@ export function createSetFileContentTool(
392
357
  }
393
358
 
394
359
  if (!widget) {
395
- throw new Error(`Failed to open file at path: ${filePath}`);
360
+ return JSON.stringify({
361
+ success: false,
362
+ error: `Failed to open file at path: ${filePath}`
363
+ });
396
364
  }
397
365
 
398
366
  await widget.context.ready;
@@ -400,11 +368,17 @@ export function createSetFileContentTool(
400
368
  const model = widget.context.model;
401
369
 
402
370
  if (!model) {
403
- throw new Error('File model not available');
371
+ return JSON.stringify({
372
+ success: false,
373
+ error: 'File model not available'
374
+ });
404
375
  }
405
376
 
406
377
  if (model.readOnly) {
407
- throw new Error('File is read-only and cannot be modified');
378
+ return JSON.stringify({
379
+ success: false,
380
+ error: 'File is read-only and cannot be modified'
381
+ });
408
382
  }
409
383
 
410
384
  const sharedModel = model.sharedModel;