@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.
- package/README.md +5 -214
- package/lib/agent.d.ts +58 -66
- package/lib/agent.js +274 -300
- package/lib/approval-buttons.d.ts +19 -82
- package/lib/approval-buttons.js +36 -289
- package/lib/chat-model-registry.d.ts +6 -0
- package/lib/chat-model-registry.js +4 -1
- package/lib/chat-model.d.ts +19 -54
- package/lib/chat-model.js +243 -303
- package/lib/components/clear-button.d.ts +6 -1
- package/lib/components/clear-button.js +8 -3
- package/lib/components/completion-status.d.ts +5 -0
- package/lib/components/completion-status.js +5 -4
- package/lib/components/model-select.d.ts +6 -1
- package/lib/components/model-select.js +9 -8
- package/lib/components/stop-button.d.ts +6 -1
- package/lib/components/stop-button.js +8 -3
- package/lib/components/token-usage-display.d.ts +5 -0
- package/lib/components/token-usage-display.js +2 -2
- package/lib/components/tool-select.d.ts +6 -1
- package/lib/components/tool-select.js +6 -5
- package/lib/index.js +58 -38
- package/lib/models/settings-model.d.ts +1 -1
- package/lib/providers/built-in-providers.js +38 -19
- package/lib/providers/models.d.ts +3 -3
- package/lib/providers/provider-registry.d.ts +3 -4
- package/lib/providers/provider-registry.js +1 -4
- package/lib/tokens.d.ts +5 -6
- package/lib/tools/commands.d.ts +2 -1
- package/lib/tools/commands.js +37 -46
- package/lib/tools/file.js +49 -73
- package/lib/tools/notebook.js +370 -445
- package/lib/widgets/ai-settings.d.ts +6 -0
- package/lib/widgets/ai-settings.js +72 -71
- package/lib/widgets/main-area-chat.d.ts +2 -0
- package/lib/widgets/main-area-chat.js +5 -2
- package/lib/widgets/provider-config-dialog.d.ts +2 -0
- package/lib/widgets/provider-config-dialog.js +34 -34
- package/package.json +12 -12
- package/src/agent.ts +342 -361
- package/src/approval-buttons.ts +43 -389
- package/src/chat-model-registry.ts +9 -1
- package/src/chat-model.ts +355 -370
- package/src/completion/completion-provider.ts +2 -3
- package/src/components/clear-button.tsx +16 -3
- package/src/components/completion-status.tsx +18 -4
- package/src/components/model-select.tsx +21 -8
- package/src/components/stop-button.tsx +16 -3
- package/src/components/token-usage-display.tsx +14 -2
- package/src/components/tool-select.tsx +23 -5
- package/src/index.ts +75 -36
- package/src/models/settings-model.ts +1 -1
- package/src/providers/built-in-providers.ts +38 -19
- package/src/providers/models.ts +3 -3
- package/src/providers/provider-registry.ts +4 -8
- package/src/tokens.ts +5 -6
- package/src/tools/commands.ts +39 -50
- package/src/tools/file.ts +49 -75
- package/src/tools/notebook.ts +451 -510
- package/src/widgets/ai-settings.tsx +153 -84
- package/src/widgets/main-area-chat.ts +8 -2
- package/src/widgets/provider-config-dialog.tsx +54 -41
- package/style/base.css +13 -73
- package/lib/mcp/browser.d.ts +0 -68
- package/lib/mcp/browser.js +0 -138
- package/src/mcp/browser.ts +0 -220
|
@@ -11,15 +11,17 @@ export const anthropicProvider = {
|
|
|
11
11
|
name: 'Anthropic Claude',
|
|
12
12
|
apiKeyRequirement: 'required',
|
|
13
13
|
defaultModels: [
|
|
14
|
+
'claude-opus-4-5',
|
|
15
|
+
'claude-opus-4-5-20251101',
|
|
14
16
|
'claude-sonnet-4-5',
|
|
15
17
|
'claude-sonnet-4-5-20250929',
|
|
16
18
|
'claude-haiku-4-5',
|
|
17
19
|
'claude-haiku-4-5-20251001',
|
|
18
20
|
'claude-opus-4-1',
|
|
19
|
-
'claude-opus-4-0',
|
|
20
|
-
'claude-sonnet-4-0',
|
|
21
21
|
'claude-opus-4-1-20250805',
|
|
22
|
+
'claude-opus-4-0',
|
|
22
23
|
'claude-opus-4-20250514',
|
|
24
|
+
'claude-sonnet-4-0',
|
|
23
25
|
'claude-sonnet-4-20250514',
|
|
24
26
|
'claude-3-7-sonnet-latest',
|
|
25
27
|
'claude-3-7-sonnet-20250219',
|
|
@@ -53,8 +55,11 @@ export const googleProvider = {
|
|
|
53
55
|
name: 'Google Generative AI',
|
|
54
56
|
apiKeyRequirement: 'required',
|
|
55
57
|
defaultModels: [
|
|
56
|
-
'gemini-
|
|
58
|
+
'gemini-3-pro-preview',
|
|
59
|
+
'gemini-3-pro-image-preview',
|
|
60
|
+
'gemini-3-flash-preview',
|
|
57
61
|
'gemini-2.5-pro',
|
|
62
|
+
'gemini-2.5-flash',
|
|
58
63
|
'gemini-2.5-flash-image-preview',
|
|
59
64
|
'gemini-2.5-flash-lite',
|
|
60
65
|
'gemini-2.5-flash-lite-preview-09-2025',
|
|
@@ -79,6 +84,9 @@ export const googleProvider = {
|
|
|
79
84
|
'gemini-1.5-pro-latest',
|
|
80
85
|
'gemini-1.5-pro-001',
|
|
81
86
|
'gemini-1.5-pro-002',
|
|
87
|
+
'gemini-pro-latest',
|
|
88
|
+
'gemini-flash-latest',
|
|
89
|
+
'gemini-flash-lite-latest',
|
|
82
90
|
'gemini-exp-1206',
|
|
83
91
|
'gemma-3-12b-it',
|
|
84
92
|
'gemma-3-27b-it'
|
|
@@ -143,12 +151,32 @@ export const openaiProvider = {
|
|
|
143
151
|
name: 'OpenAI',
|
|
144
152
|
apiKeyRequirement: 'required',
|
|
145
153
|
defaultModels: [
|
|
146
|
-
'
|
|
147
|
-
'
|
|
148
|
-
'
|
|
149
|
-
'
|
|
154
|
+
'gpt-5.2',
|
|
155
|
+
'gpt-5.2-chat-latest',
|
|
156
|
+
'gpt-5.2-pro',
|
|
157
|
+
'gpt-5.1',
|
|
158
|
+
'gpt-5.1-chat-latest',
|
|
159
|
+
'gpt-5.1-codex',
|
|
160
|
+
'gpt-5.1-codex-mini',
|
|
161
|
+
'gpt-5.1-codex-max',
|
|
162
|
+
'gpt-5',
|
|
163
|
+
'gpt-5-2025-08-07',
|
|
164
|
+
'gpt-5-chat-latest',
|
|
165
|
+
'gpt-5-codex',
|
|
166
|
+
'gpt-5-pro',
|
|
167
|
+
'gpt-5-pro-2025-10-06',
|
|
168
|
+
'gpt-5-mini',
|
|
169
|
+
'gpt-5-mini-2025-08-07',
|
|
170
|
+
'gpt-5-nano',
|
|
171
|
+
'gpt-5-nano-2025-08-07',
|
|
150
172
|
'o3',
|
|
151
173
|
'o3-2025-04-16',
|
|
174
|
+
'o3-mini',
|
|
175
|
+
'o3-mini-2025-01-31',
|
|
176
|
+
'o1',
|
|
177
|
+
'o1-2024-12-17',
|
|
178
|
+
'gpt-4.5-preview',
|
|
179
|
+
'gpt-4.5-preview-2025-02-27',
|
|
152
180
|
'gpt-4.1',
|
|
153
181
|
'gpt-4.1-2025-04-14',
|
|
154
182
|
'gpt-4.1-mini',
|
|
@@ -161,23 +189,14 @@ export const openaiProvider = {
|
|
|
161
189
|
'gpt-4o-2024-11-20',
|
|
162
190
|
'gpt-4o-mini',
|
|
163
191
|
'gpt-4o-mini-2024-07-18',
|
|
192
|
+
'chatgpt-4o-latest',
|
|
164
193
|
'gpt-4-turbo',
|
|
165
194
|
'gpt-4-turbo-2024-04-09',
|
|
166
195
|
'gpt-4',
|
|
167
196
|
'gpt-4-0613',
|
|
168
|
-
'gpt-4.5-preview',
|
|
169
|
-
'gpt-4.5-preview-2025-02-27',
|
|
170
|
-
'gpt-3.5-turbo-0125',
|
|
171
197
|
'gpt-3.5-turbo',
|
|
172
|
-
'gpt-3.5-turbo-
|
|
173
|
-
'
|
|
174
|
-
'gpt-5',
|
|
175
|
-
'gpt-5-2025-08-07',
|
|
176
|
-
'gpt-5-mini',
|
|
177
|
-
'gpt-5-mini-2025-08-07',
|
|
178
|
-
'gpt-5-nano',
|
|
179
|
-
'gpt-5-nano-2025-08-07',
|
|
180
|
-
'gpt-5-chat-latest'
|
|
198
|
+
'gpt-3.5-turbo-0125',
|
|
199
|
+
'gpt-3.5-turbo-1106'
|
|
181
200
|
],
|
|
182
201
|
supportsBaseURL: true,
|
|
183
202
|
supportsHeaders: true,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LanguageModel } from 'ai';
|
|
2
2
|
import type { IProviderRegistry } from '../tokens';
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options for creating language models.
|
|
@@ -29,9 +29,9 @@ export interface IModelOptions {
|
|
|
29
29
|
* Create a completion model using the provider registry.
|
|
30
30
|
* Built-in providers are automatically registered during extension initialization.
|
|
31
31
|
*/
|
|
32
|
-
export declare function createCompletionModel(options: IModelOptions, registry?: IProviderRegistry):
|
|
32
|
+
export declare function createCompletionModel(options: IModelOptions, registry?: IProviderRegistry): LanguageModel;
|
|
33
33
|
/**
|
|
34
34
|
* Create a chat model using the provider registry.
|
|
35
35
|
* Built-in providers are automatically registered during extension initialization.
|
|
36
36
|
*/
|
|
37
|
-
export declare function createModel(options: IModelOptions, registry?: IProviderRegistry):
|
|
37
|
+
export declare function createModel(options: IModelOptions, registry?: IProviderRegistry): LanguageModel;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ISignal } from '@lumino/signaling';
|
|
2
|
-
import type {
|
|
3
|
-
import type { Model } from '@openai/agents';
|
|
2
|
+
import type { LanguageModel } from 'ai';
|
|
4
3
|
import type { IModelOptions } from './models';
|
|
5
4
|
import { IProviderInfo, IProviderRegistry } from '../tokens';
|
|
6
5
|
/**
|
|
@@ -32,14 +31,14 @@ export declare class ProviderRegistry implements IProviderRegistry {
|
|
|
32
31
|
* @param options Model configuration options
|
|
33
32
|
* @returns Chat model instance or null if creation fails
|
|
34
33
|
*/
|
|
35
|
-
createChatModel(id: string, options: IModelOptions):
|
|
34
|
+
createChatModel(id: string, options: IModelOptions): LanguageModel | null;
|
|
36
35
|
/**
|
|
37
36
|
* Create a completion model instance using the specified provider
|
|
38
37
|
* @param id Provider ID
|
|
39
38
|
* @param options Model configuration options
|
|
40
39
|
* @returns Language model instance or null if creation fails
|
|
41
40
|
*/
|
|
42
|
-
createCompletionModel(id: string, options: IModelOptions):
|
|
41
|
+
createCompletionModel(id: string, options: IModelOptions): LanguageModel | null;
|
|
43
42
|
/**
|
|
44
43
|
* Get list of all available provider IDs
|
|
45
44
|
* @returns Array of provider IDs
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Signal } from '@lumino/signaling';
|
|
2
|
-
import { aisdk } from '@openai/agents-extensions';
|
|
3
2
|
/**
|
|
4
3
|
* Implementation of the provider registry
|
|
5
4
|
*/
|
|
@@ -46,9 +45,7 @@ export class ProviderRegistry {
|
|
|
46
45
|
if (!provider) {
|
|
47
46
|
return null;
|
|
48
47
|
}
|
|
49
|
-
|
|
50
|
-
// wrap with aisdk for compatibility with the agent framework
|
|
51
|
-
return aisdk(languageModel);
|
|
48
|
+
return provider.factory(options);
|
|
52
49
|
}
|
|
53
50
|
/**
|
|
54
51
|
* Create a completion model instance using the specified provider
|
package/lib/tokens.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
2
|
import { ISignal } from '@lumino/signaling';
|
|
3
|
-
import {
|
|
4
|
-
import { LanguageModelV2 } from '@ai-sdk/provider';
|
|
3
|
+
import type { Tool, LanguageModel } from 'ai';
|
|
5
4
|
import { AgentManager } from './agent';
|
|
6
5
|
import type { AISettingsModel } from './models/settings-model';
|
|
7
6
|
import type { IModelOptions } from './providers/models';
|
|
@@ -19,7 +18,7 @@ export declare namespace CommandIds {
|
|
|
19
18
|
/**
|
|
20
19
|
* Type definition for a tool
|
|
21
20
|
*/
|
|
22
|
-
export type ITool =
|
|
21
|
+
export type ITool = Tool;
|
|
23
22
|
/**
|
|
24
23
|
* Interface for token usage statistics from AI model interactions
|
|
25
24
|
*/
|
|
@@ -89,7 +88,7 @@ export declare const IProviderRegistry: Token<IProviderRegistry>;
|
|
|
89
88
|
* Interface for a provider factory function that creates language models
|
|
90
89
|
*/
|
|
91
90
|
export interface IProviderFactory {
|
|
92
|
-
(options: IModelOptions):
|
|
91
|
+
(options: IModelOptions): LanguageModel;
|
|
93
92
|
}
|
|
94
93
|
/**
|
|
95
94
|
* Provider information
|
|
@@ -165,11 +164,11 @@ export interface IProviderRegistry {
|
|
|
165
164
|
/**
|
|
166
165
|
* Create a chat model instance for the given provider.
|
|
167
166
|
*/
|
|
168
|
-
createChatModel(id: string, options: IModelOptions):
|
|
167
|
+
createChatModel(id: string, options: IModelOptions): LanguageModel | null;
|
|
169
168
|
/**
|
|
170
169
|
* Create a completion model instance for the given provider.
|
|
171
170
|
*/
|
|
172
|
-
createCompletionModel(id: string, options: IModelOptions):
|
|
171
|
+
createCompletionModel(id: string, options: IModelOptions): LanguageModel | null;
|
|
173
172
|
/**
|
|
174
173
|
* Get all available provider IDs.
|
|
175
174
|
*/
|
package/lib/tools/commands.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { AISettingsModel } from '../models/settings-model';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function createDiscoverCommandsTool(commands: CommandRegistry): ITool;
|
|
8
8
|
/**
|
|
9
|
-
* Create a tool to execute a specific JupyterLab command
|
|
9
|
+
* Create a tool to execute a specific JupyterLab command.
|
|
10
|
+
* Commands in the settings' commandsRequiringApproval list will need approval.
|
|
10
11
|
*/
|
|
11
12
|
export declare function createExecuteCommandTool(commands: CommandRegistry, settingsModel: AISettingsModel): ITool;
|
package/lib/tools/commands.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { tool } from '
|
|
1
|
+
import { tool } from 'ai';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
/**
|
|
4
4
|
* Create a tool to discover all available commands and their metadata
|
|
5
5
|
*/
|
|
6
6
|
export function createDiscoverCommandsTool(commands) {
|
|
7
7
|
return tool({
|
|
8
|
-
|
|
8
|
+
title: 'Discover Commands',
|
|
9
9
|
description: 'Discover all available JupyterLab commands with their metadata, arguments, and descriptions',
|
|
10
|
-
|
|
11
|
-
// currently unused, but could be used to filter commands by a search term
|
|
10
|
+
inputSchema: z.object({
|
|
12
11
|
query: z
|
|
13
12
|
.string()
|
|
14
13
|
.optional()
|
|
@@ -57,23 +56,23 @@ export function createDiscoverCommandsTool(commands) {
|
|
|
57
56
|
});
|
|
58
57
|
}
|
|
59
58
|
/**
|
|
60
|
-
* Create a tool to execute a specific JupyterLab command
|
|
59
|
+
* Create a tool to execute a specific JupyterLab command.
|
|
60
|
+
* Commands in the settings' commandsRequiringApproval list will need approval.
|
|
61
61
|
*/
|
|
62
62
|
export function createExecuteCommandTool(commands, settingsModel) {
|
|
63
63
|
return tool({
|
|
64
|
-
|
|
64
|
+
title: 'Execute Command',
|
|
65
65
|
description: 'Execute a specific JupyterLab command with optional arguments',
|
|
66
|
-
|
|
66
|
+
inputSchema: z.object({
|
|
67
67
|
commandId: z.string().describe('The ID of the command to execute'),
|
|
68
68
|
args: z
|
|
69
69
|
.any()
|
|
70
70
|
.optional()
|
|
71
71
|
.describe('Optional arguments to pass to the command')
|
|
72
72
|
}),
|
|
73
|
-
needsApproval:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return commandsRequiringApproval.some(cmd => commandId.includes(cmd) || cmd.includes(commandId));
|
|
73
|
+
needsApproval: (input) => {
|
|
74
|
+
const commandsRequiringApproval = settingsModel.config.commandsRequiringApproval || [];
|
|
75
|
+
return commandsRequiringApproval.includes(input.commandId);
|
|
77
76
|
},
|
|
78
77
|
execute: async (input) => {
|
|
79
78
|
const { commandId, args } = input;
|
|
@@ -84,44 +83,36 @@ export function createExecuteCommandTool(commands, settingsModel) {
|
|
|
84
83
|
error: `Command '${commandId}' does not exist. Use 'discover_commands' to see available commands.`
|
|
85
84
|
};
|
|
86
85
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
className: result.className
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
// For other objects, try JSON serialization with fallback
|
|
104
|
-
try {
|
|
105
|
-
serializedResult = JSON.parse(JSON.stringify(result));
|
|
106
|
-
}
|
|
107
|
-
catch {
|
|
108
|
-
serializedResult = result
|
|
109
|
-
? '[Complex object - cannot serialize]'
|
|
110
|
-
: 'Command executed successfully';
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
success: true,
|
|
115
|
-
commandId,
|
|
116
|
-
result: serializedResult
|
|
86
|
+
// Execute the command
|
|
87
|
+
const result = await commands.execute(commandId, args);
|
|
88
|
+
// Handle Widget objects specially (including subclasses like DocumentWidget)
|
|
89
|
+
let serializedResult;
|
|
90
|
+
if (result &&
|
|
91
|
+
typeof result === 'object' &&
|
|
92
|
+
(result.constructor?.name?.includes('Widget') || result.id)) {
|
|
93
|
+
serializedResult = {
|
|
94
|
+
type: result.constructor?.name || 'Widget',
|
|
95
|
+
id: result.id,
|
|
96
|
+
title: result.title?.label || result.title,
|
|
97
|
+
className: result.className
|
|
117
98
|
};
|
|
118
99
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
100
|
+
else {
|
|
101
|
+
// For other objects, try JSON serialization with fallback
|
|
102
|
+
try {
|
|
103
|
+
serializedResult = JSON.parse(JSON.stringify(result));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
serializedResult = result
|
|
107
|
+
? '[Complex object - cannot serialize]'
|
|
108
|
+
: 'Command executed successfully';
|
|
109
|
+
}
|
|
124
110
|
}
|
|
111
|
+
return {
|
|
112
|
+
success: true,
|
|
113
|
+
commandId,
|
|
114
|
+
result: serializedResult
|
|
115
|
+
};
|
|
125
116
|
}
|
|
126
117
|
});
|
|
127
118
|
}
|
package/lib/tools/file.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { PathExt } from '@jupyterlab/coreutils';
|
|
2
|
-
import { tool } from '
|
|
2
|
+
import { tool } from 'ai';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
/**
|
|
5
5
|
* Create a tool for creating new files of various types
|
|
6
6
|
*/
|
|
7
7
|
export function createNewFileTool(docManager) {
|
|
8
8
|
return tool({
|
|
9
|
-
|
|
9
|
+
title: 'New File',
|
|
10
10
|
description: 'Create a new file of specified type (text, python, markdown, json, etc.)',
|
|
11
|
-
|
|
11
|
+
inputSchema: z.object({
|
|
12
12
|
fileName: z.string().describe('Name of the file to create'),
|
|
13
13
|
fileType: z
|
|
14
14
|
.string()
|
|
@@ -25,12 +25,6 @@ export function createNewFileTool(docManager) {
|
|
|
25
25
|
.nullable()
|
|
26
26
|
.describe('Directory where to create the file (optional)')
|
|
27
27
|
}),
|
|
28
|
-
errorFunction: (context, error) => {
|
|
29
|
-
return JSON.stringify({
|
|
30
|
-
success: false,
|
|
31
|
-
error: `Failed to create file: ${error instanceof Error ? error.message : String(error)}`
|
|
32
|
-
});
|
|
33
|
-
},
|
|
34
28
|
execute: async (input) => {
|
|
35
29
|
const { fileName, content = '', cwd, fileType = 'text' } = input;
|
|
36
30
|
const registeredFileType = docManager.registry.getFileType(fileType);
|
|
@@ -77,22 +71,19 @@ export function createNewFileTool(docManager) {
|
|
|
77
71
|
*/
|
|
78
72
|
export function createOpenFileTool(docManager) {
|
|
79
73
|
return tool({
|
|
80
|
-
|
|
74
|
+
title: 'Open File',
|
|
81
75
|
description: 'Open a file in the editor',
|
|
82
|
-
|
|
76
|
+
inputSchema: z.object({
|
|
83
77
|
filePath: z.string().describe('Path to the file to open')
|
|
84
78
|
}),
|
|
85
|
-
errorFunction: (context, error) => {
|
|
86
|
-
return JSON.stringify({
|
|
87
|
-
success: false,
|
|
88
|
-
error: `Failed to open file: ${error instanceof Error ? error.message : String(error)}`
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
79
|
execute: async (input) => {
|
|
92
80
|
const { filePath } = input;
|
|
93
81
|
const widget = docManager.openOrReveal(filePath);
|
|
94
82
|
if (!widget) {
|
|
95
|
-
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
error: `Could not open file: ${filePath}`
|
|
86
|
+
};
|
|
96
87
|
}
|
|
97
88
|
return {
|
|
98
89
|
success: true,
|
|
@@ -108,17 +99,11 @@ export function createOpenFileTool(docManager) {
|
|
|
108
99
|
*/
|
|
109
100
|
export function createDeleteFileTool(docManager) {
|
|
110
101
|
return tool({
|
|
111
|
-
|
|
102
|
+
title: 'Delete File',
|
|
112
103
|
description: 'Delete a file from the file system',
|
|
113
|
-
|
|
104
|
+
inputSchema: z.object({
|
|
114
105
|
filePath: z.string().describe('Path to the file to delete')
|
|
115
106
|
}),
|
|
116
|
-
errorFunction: (context, error) => {
|
|
117
|
-
return JSON.stringify({
|
|
118
|
-
success: false,
|
|
119
|
-
error: `Failed to delete file: ${error instanceof Error ? error.message : String(error)}`
|
|
120
|
-
});
|
|
121
|
-
},
|
|
122
107
|
execute: async (input) => {
|
|
123
108
|
const { filePath } = input;
|
|
124
109
|
await docManager.services.contents.delete(filePath);
|
|
@@ -135,18 +120,12 @@ export function createDeleteFileTool(docManager) {
|
|
|
135
120
|
*/
|
|
136
121
|
export function createRenameFileTool(docManager) {
|
|
137
122
|
return tool({
|
|
138
|
-
|
|
123
|
+
title: 'Rename File',
|
|
139
124
|
description: 'Rename a file or move it to a different location',
|
|
140
|
-
|
|
125
|
+
inputSchema: z.object({
|
|
141
126
|
oldPath: z.string().describe('Current path of the file'),
|
|
142
127
|
newPath: z.string().describe('New path/name for the file')
|
|
143
128
|
}),
|
|
144
|
-
errorFunction: (context, error) => {
|
|
145
|
-
return JSON.stringify({
|
|
146
|
-
success: false,
|
|
147
|
-
error: `Failed to rename file: ${error instanceof Error ? error.message : String(error)}`
|
|
148
|
-
});
|
|
149
|
-
},
|
|
150
129
|
execute: async (input) => {
|
|
151
130
|
const { oldPath, newPath } = input;
|
|
152
131
|
await docManager.services.contents.rename(oldPath, newPath);
|
|
@@ -164,20 +143,14 @@ export function createRenameFileTool(docManager) {
|
|
|
164
143
|
*/
|
|
165
144
|
export function createCopyFileTool(docManager) {
|
|
166
145
|
return tool({
|
|
167
|
-
|
|
146
|
+
title: 'Copy File',
|
|
168
147
|
description: 'Copy a file to a new location',
|
|
169
|
-
|
|
148
|
+
inputSchema: z.object({
|
|
170
149
|
sourcePath: z.string().describe('Path of the file to copy'),
|
|
171
150
|
destinationPath: z
|
|
172
151
|
.string()
|
|
173
152
|
.describe('Destination path for the copied file')
|
|
174
153
|
}),
|
|
175
|
-
errorFunction: (context, error) => {
|
|
176
|
-
return JSON.stringify({
|
|
177
|
-
success: false,
|
|
178
|
-
error: `Failed to copy file: ${error instanceof Error ? error.message : String(error)}`
|
|
179
|
-
});
|
|
180
|
-
},
|
|
181
154
|
execute: async (input) => {
|
|
182
155
|
const { sourcePath, destinationPath } = input;
|
|
183
156
|
await docManager.services.contents.copy(sourcePath, destinationPath);
|
|
@@ -195,17 +168,11 @@ export function createCopyFileTool(docManager) {
|
|
|
195
168
|
*/
|
|
196
169
|
export function createNavigateToDirectoryTool(commands) {
|
|
197
170
|
return tool({
|
|
198
|
-
|
|
171
|
+
title: 'Navigate to Directory',
|
|
199
172
|
description: 'Navigate to a specific directory in the file browser',
|
|
200
|
-
|
|
173
|
+
inputSchema: z.object({
|
|
201
174
|
directoryPath: z.string().describe('Path to the directory to navigate to')
|
|
202
175
|
}),
|
|
203
|
-
errorFunction: (context, error) => {
|
|
204
|
-
return JSON.stringify({
|
|
205
|
-
success: false,
|
|
206
|
-
error: `Failed to navigate to directory: ${error instanceof Error ? error.message : String(error)}`
|
|
207
|
-
});
|
|
208
|
-
},
|
|
209
176
|
execute: async (input) => {
|
|
210
177
|
const { directoryPath } = input;
|
|
211
178
|
await commands.execute('filebrowser:go-to-path', {
|
|
@@ -224,21 +191,15 @@ export function createNavigateToDirectoryTool(commands) {
|
|
|
224
191
|
*/
|
|
225
192
|
export function createGetFileInfoTool(docManager, editorTracker) {
|
|
226
193
|
return tool({
|
|
227
|
-
|
|
194
|
+
title: 'Get File Info',
|
|
228
195
|
description: '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.',
|
|
229
|
-
|
|
196
|
+
inputSchema: z.object({
|
|
230
197
|
filePath: z
|
|
231
198
|
.string()
|
|
232
199
|
.optional()
|
|
233
200
|
.nullable()
|
|
234
201
|
.describe('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.')
|
|
235
202
|
}),
|
|
236
|
-
errorFunction: (context, error) => {
|
|
237
|
-
return JSON.stringify({
|
|
238
|
-
success: false,
|
|
239
|
-
error: `Failed to get file info: ${error instanceof Error ? error.message : String(error)}`
|
|
240
|
-
});
|
|
241
|
-
},
|
|
242
203
|
execute: async (input) => {
|
|
243
204
|
const { filePath } = input;
|
|
244
205
|
let widget = null;
|
|
@@ -248,22 +209,34 @@ export function createGetFileInfoTool(docManager, editorTracker) {
|
|
|
248
209
|
docManager.openOrReveal(filePath) ??
|
|
249
210
|
null;
|
|
250
211
|
if (!widget) {
|
|
251
|
-
|
|
212
|
+
return JSON.stringify({
|
|
213
|
+
success: false,
|
|
214
|
+
error: `Failed to open file at path: ${filePath}`
|
|
215
|
+
});
|
|
252
216
|
}
|
|
253
217
|
}
|
|
254
218
|
else {
|
|
255
219
|
widget = editorTracker?.currentWidget ?? null;
|
|
256
220
|
if (!widget) {
|
|
257
|
-
|
|
221
|
+
return JSON.stringify({
|
|
222
|
+
success: false,
|
|
223
|
+
error: 'No active file in the editor and no file path provided'
|
|
224
|
+
});
|
|
258
225
|
}
|
|
259
226
|
}
|
|
260
227
|
if (!widget.context) {
|
|
261
|
-
|
|
228
|
+
return JSON.stringify({
|
|
229
|
+
success: false,
|
|
230
|
+
error: 'Widget is not a document'
|
|
231
|
+
});
|
|
262
232
|
}
|
|
263
233
|
await widget.context.ready;
|
|
264
234
|
const model = widget.context.model;
|
|
265
235
|
if (!model) {
|
|
266
|
-
|
|
236
|
+
return JSON.stringify({
|
|
237
|
+
success: false,
|
|
238
|
+
error: 'File model not available'
|
|
239
|
+
});
|
|
267
240
|
}
|
|
268
241
|
const sharedModel = model.sharedModel;
|
|
269
242
|
const content = sharedModel.getSource();
|
|
@@ -288,9 +261,9 @@ export function createGetFileInfoTool(docManager, editorTracker) {
|
|
|
288
261
|
*/
|
|
289
262
|
export function createSetFileContentTool(docManager, diffManager) {
|
|
290
263
|
return tool({
|
|
291
|
-
|
|
264
|
+
title: 'Set File Content',
|
|
292
265
|
description: '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.',
|
|
293
|
-
|
|
266
|
+
inputSchema: z.object({
|
|
294
267
|
filePath: z
|
|
295
268
|
.string()
|
|
296
269
|
.describe('Path to the file to update (e.g., "script.py", "README.md", "config.json")'),
|
|
@@ -301,12 +274,6 @@ export function createSetFileContentTool(docManager, diffManager) {
|
|
|
301
274
|
.default(true)
|
|
302
275
|
.describe('Whether to save the file after updating (default: true)')
|
|
303
276
|
}),
|
|
304
|
-
errorFunction: (context, error) => {
|
|
305
|
-
return JSON.stringify({
|
|
306
|
-
success: false,
|
|
307
|
-
error: `Failed to set file content: ${error instanceof Error ? error.message : String(error)}`
|
|
308
|
-
});
|
|
309
|
-
},
|
|
310
277
|
execute: async (input) => {
|
|
311
278
|
const { filePath, content, save = true } = input;
|
|
312
279
|
let widget = docManager.findWidget(filePath);
|
|
@@ -314,15 +281,24 @@ export function createSetFileContentTool(docManager, diffManager) {
|
|
|
314
281
|
widget = docManager.openOrReveal(filePath);
|
|
315
282
|
}
|
|
316
283
|
if (!widget) {
|
|
317
|
-
|
|
284
|
+
return JSON.stringify({
|
|
285
|
+
success: false,
|
|
286
|
+
error: `Failed to open file at path: ${filePath}`
|
|
287
|
+
});
|
|
318
288
|
}
|
|
319
289
|
await widget.context.ready;
|
|
320
290
|
const model = widget.context.model;
|
|
321
291
|
if (!model) {
|
|
322
|
-
|
|
292
|
+
return JSON.stringify({
|
|
293
|
+
success: false,
|
|
294
|
+
error: 'File model not available'
|
|
295
|
+
});
|
|
323
296
|
}
|
|
324
297
|
if (model.readOnly) {
|
|
325
|
-
|
|
298
|
+
return JSON.stringify({
|
|
299
|
+
success: false,
|
|
300
|
+
error: 'File is read-only and cannot be modified'
|
|
301
|
+
});
|
|
326
302
|
}
|
|
327
303
|
const sharedModel = model.sharedModel;
|
|
328
304
|
const originalContent = sharedModel.getSource();
|