@jupyterlite/ai 0.8.0 → 0.9.0-a0
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.d.ts +233 -0
- package/lib/agent.js +604 -0
- package/lib/chat-model.d.ts +195 -0
- package/lib/chat-model.js +590 -0
- package/lib/completion/completion-provider.d.ts +83 -0
- package/lib/completion/completion-provider.js +209 -0
- package/lib/completion/index.d.ts +1 -0
- package/lib/completion/index.js +1 -0
- package/lib/components/clear-button.d.ts +18 -0
- package/lib/components/clear-button.js +31 -0
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.js +3 -0
- package/lib/components/model-select.d.ts +19 -0
- package/lib/components/model-select.js +154 -0
- package/lib/components/stop-button.d.ts +3 -3
- package/lib/components/stop-button.js +8 -9
- package/lib/components/token-usage-display.d.ts +45 -0
- package/lib/components/token-usage-display.js +74 -0
- package/lib/components/tool-select.d.ts +27 -0
- package/lib/components/tool-select.js +130 -0
- package/lib/icons.d.ts +3 -1
- package/lib/icons.js +10 -13
- package/lib/index.d.ts +4 -5
- package/lib/index.js +322 -167
- package/lib/mcp/browser.d.ts +68 -0
- package/lib/mcp/browser.js +132 -0
- package/lib/models/settings-model.d.ts +69 -0
- package/lib/models/settings-model.js +295 -0
- package/lib/providers/built-in-providers.d.ts +9 -0
- package/lib/providers/built-in-providers.js +192 -0
- package/lib/providers/models.d.ts +37 -0
- package/lib/providers/models.js +28 -0
- package/lib/providers/provider-registry.d.ts +94 -0
- package/lib/providers/provider-registry.js +155 -0
- package/lib/tokens.d.ts +157 -86
- package/lib/tokens.js +16 -12
- package/lib/tools/commands.d.ts +11 -0
- package/lib/tools/commands.js +126 -0
- package/lib/tools/file.d.ts +27 -0
- package/lib/tools/file.js +262 -0
- package/lib/tools/notebook.d.ts +40 -0
- package/lib/tools/notebook.js +762 -0
- package/lib/tools/tool-registry.d.ts +35 -0
- package/lib/tools/tool-registry.js +55 -0
- package/lib/widgets/ai-settings.d.ts +39 -0
- package/lib/widgets/ai-settings.js +506 -0
- package/lib/widgets/chat-wrapper.d.ts +144 -0
- package/lib/widgets/chat-wrapper.js +390 -0
- package/lib/widgets/provider-config-dialog.d.ts +13 -0
- package/lib/widgets/provider-config-dialog.js +104 -0
- package/package.json +150 -41
- package/schema/settings-model.json +153 -0
- package/src/agent.ts +800 -0
- package/src/chat-model.ts +770 -0
- package/src/completion/completion-provider.ts +308 -0
- package/src/completion/index.ts +1 -0
- package/src/components/clear-button.tsx +56 -0
- package/src/components/index.ts +3 -0
- package/src/components/model-select.tsx +245 -0
- package/src/components/stop-button.tsx +11 -11
- package/src/components/token-usage-display.tsx +130 -0
- package/src/components/tool-select.tsx +218 -0
- package/src/icons.ts +12 -14
- package/src/index.ts +468 -238
- package/src/mcp/browser.ts +213 -0
- package/src/models/settings-model.ts +409 -0
- package/src/providers/built-in-providers.ts +216 -0
- package/src/providers/models.ts +79 -0
- package/src/providers/provider-registry.ts +189 -0
- package/src/tokens.ts +203 -90
- package/src/tools/commands.ts +151 -0
- package/src/tools/file.ts +307 -0
- package/src/tools/notebook.ts +964 -0
- package/src/tools/tool-registry.ts +63 -0
- package/src/types.d.ts +4 -0
- package/src/widgets/ai-settings.tsx +1100 -0
- package/src/widgets/chat-wrapper.tsx +543 -0
- package/src/widgets/provider-config-dialog.tsx +256 -0
- package/style/base.css +335 -14
- package/style/icons/jupyternaut-lite.svg +1 -1
- package/lib/base-completer.d.ts +0 -49
- package/lib/base-completer.js +0 -14
- package/lib/chat-handler.d.ts +0 -56
- package/lib/chat-handler.js +0 -201
- package/lib/completion-provider.d.ts +0 -34
- package/lib/completion-provider.js +0 -32
- package/lib/default-prompts.d.ts +0 -2
- package/lib/default-prompts.js +0 -31
- package/lib/default-providers/Anthropic/completer.d.ts +0 -12
- package/lib/default-providers/Anthropic/completer.js +0 -46
- package/lib/default-providers/Anthropic/settings-schema.json +0 -70
- package/lib/default-providers/ChromeAI/completer.d.ts +0 -12
- package/lib/default-providers/ChromeAI/completer.js +0 -56
- package/lib/default-providers/ChromeAI/instructions.d.ts +0 -6
- package/lib/default-providers/ChromeAI/instructions.js +0 -42
- package/lib/default-providers/ChromeAI/settings-schema.json +0 -18
- package/lib/default-providers/Gemini/completer.d.ts +0 -12
- package/lib/default-providers/Gemini/completer.js +0 -48
- package/lib/default-providers/Gemini/instructions.d.ts +0 -2
- package/lib/default-providers/Gemini/instructions.js +0 -9
- package/lib/default-providers/Gemini/settings-schema.json +0 -64
- package/lib/default-providers/MistralAI/completer.d.ts +0 -13
- package/lib/default-providers/MistralAI/completer.js +0 -52
- package/lib/default-providers/MistralAI/instructions.d.ts +0 -2
- package/lib/default-providers/MistralAI/instructions.js +0 -18
- package/lib/default-providers/MistralAI/settings-schema.json +0 -75
- package/lib/default-providers/Ollama/completer.d.ts +0 -12
- package/lib/default-providers/Ollama/completer.js +0 -43
- package/lib/default-providers/Ollama/instructions.d.ts +0 -2
- package/lib/default-providers/Ollama/instructions.js +0 -70
- package/lib/default-providers/Ollama/settings-schema.json +0 -143
- package/lib/default-providers/OpenAI/completer.d.ts +0 -12
- package/lib/default-providers/OpenAI/completer.js +0 -43
- package/lib/default-providers/OpenAI/settings-schema.json +0 -628
- package/lib/default-providers/WebLLM/completer.d.ts +0 -21
- package/lib/default-providers/WebLLM/completer.js +0 -127
- package/lib/default-providers/WebLLM/instructions.d.ts +0 -6
- package/lib/default-providers/WebLLM/instructions.js +0 -32
- package/lib/default-providers/WebLLM/settings-schema.json +0 -19
- package/lib/default-providers/index.d.ts +0 -2
- package/lib/default-providers/index.js +0 -179
- package/lib/provider.d.ts +0 -144
- package/lib/provider.js +0 -412
- package/lib/settings/base.json +0 -7
- package/lib/settings/index.d.ts +0 -3
- package/lib/settings/index.js +0 -3
- package/lib/settings/panel.d.ts +0 -226
- package/lib/settings/panel.js +0 -510
- package/lib/settings/textarea.d.ts +0 -2
- package/lib/settings/textarea.js +0 -18
- package/lib/settings/utils.d.ts +0 -2
- package/lib/settings/utils.js +0 -4
- package/lib/types/ai-model.d.ts +0 -24
- package/lib/types/ai-model.js +0 -5
- package/schema/chat.json +0 -28
- package/schema/provider-registry.json +0 -29
- package/schema/system-prompts.json +0 -22
- package/src/base-completer.ts +0 -75
- package/src/chat-handler.ts +0 -262
- package/src/completion-provider.ts +0 -64
- package/src/default-prompts.ts +0 -33
- package/src/default-providers/Anthropic/completer.ts +0 -59
- package/src/default-providers/ChromeAI/completer.ts +0 -73
- package/src/default-providers/ChromeAI/instructions.ts +0 -45
- package/src/default-providers/Gemini/completer.ts +0 -61
- package/src/default-providers/Gemini/instructions.ts +0 -9
- package/src/default-providers/MistralAI/completer.ts +0 -69
- package/src/default-providers/MistralAI/instructions.ts +0 -18
- package/src/default-providers/Ollama/completer.ts +0 -54
- package/src/default-providers/Ollama/instructions.ts +0 -70
- package/src/default-providers/OpenAI/completer.ts +0 -54
- package/src/default-providers/WebLLM/completer.ts +0 -151
- package/src/default-providers/WebLLM/instructions.ts +0 -33
- package/src/default-providers/index.ts +0 -211
- package/src/global.d.ts +0 -9
- package/src/provider.ts +0 -514
- package/src/settings/index.ts +0 -3
- package/src/settings/panel.tsx +0 -773
- package/src/settings/textarea.tsx +0 -33
- package/src/settings/utils.ts +0 -5
- package/src/types/ai-model.ts +0 -37
- package/src/types/service-worker.d.ts +0 -6
package/src/index.ts
CHANGED
|
@@ -1,68 +1,198 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ILabShell,
|
|
3
|
+
ILayoutRestorer,
|
|
4
|
+
JupyterFrontEnd,
|
|
5
|
+
JupyterFrontEndPlugin
|
|
6
|
+
} from '@jupyterlab/application';
|
|
7
|
+
|
|
1
8
|
import {
|
|
2
9
|
ActiveCellManager,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ChatCommandRegistry,
|
|
6
|
-
IActiveCellManager,
|
|
7
|
-
IChatCommandRegistry,
|
|
10
|
+
AttachmentOpenerRegistry,
|
|
11
|
+
ChatWidget,
|
|
8
12
|
InputToolbarRegistry
|
|
9
13
|
} from '@jupyter/chat';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ILayoutRestorer
|
|
14
|
-
} from '@jupyterlab/application';
|
|
15
|
-
import { ReactWidget, IThemeManager } from '@jupyterlab/apputils';
|
|
14
|
+
|
|
15
|
+
import { ICommandPalette, IThemeManager } from '@jupyterlab/apputils';
|
|
16
|
+
|
|
16
17
|
import { ICompletionProviderManager } from '@jupyterlab/completer';
|
|
18
|
+
|
|
19
|
+
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
20
|
+
|
|
17
21
|
import { INotebookTracker } from '@jupyterlab/notebook';
|
|
22
|
+
|
|
18
23
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
24
|
+
|
|
25
|
+
import { IKernelSpecManager, KernelSpec } from '@jupyterlab/services';
|
|
26
|
+
|
|
19
27
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
20
|
-
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
|
|
29
|
+
import { settingsIcon } from '@jupyterlab/ui-components';
|
|
30
|
+
|
|
31
|
+
import { AgentManager } from './agent';
|
|
32
|
+
import { AIChatModel } from './chat-model';
|
|
33
|
+
|
|
34
|
+
import {
|
|
35
|
+
ChatProviderRegistry,
|
|
36
|
+
CompletionProviderRegistry
|
|
37
|
+
} from './providers/provider-registry';
|
|
38
|
+
|
|
39
|
+
import {
|
|
40
|
+
IChatProviderRegistry,
|
|
41
|
+
ICompletionProviderRegistry,
|
|
42
|
+
IAISettingsModel,
|
|
43
|
+
IToolRegistry
|
|
44
|
+
} from './tokens';
|
|
45
|
+
|
|
46
|
+
import {
|
|
47
|
+
registerBuiltInChatProviders,
|
|
48
|
+
registerBuiltInCompletionProviders
|
|
49
|
+
} from './providers/built-in-providers';
|
|
50
|
+
|
|
51
|
+
import { AICompletionProvider } from './completion';
|
|
52
|
+
|
|
53
|
+
import { clearItem } from './components/clear-button';
|
|
54
|
+
|
|
55
|
+
import { createModelSelectItem } from './components/model-select';
|
|
56
|
+
|
|
30
57
|
import { stopItem } from './components/stop-button';
|
|
31
58
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
59
|
+
import { createToolSelectItem } from './components/tool-select';
|
|
60
|
+
|
|
61
|
+
import { AISettingsModel } from './models/settings-model';
|
|
62
|
+
|
|
63
|
+
import { ToolRegistry } from './tools/tool-registry';
|
|
64
|
+
|
|
65
|
+
import {
|
|
66
|
+
createAddCellTool,
|
|
67
|
+
createDeleteCellTool,
|
|
68
|
+
createExecuteActiveCellTool,
|
|
69
|
+
createGetCellInfoTool,
|
|
70
|
+
createGetNotebookInfoTool,
|
|
71
|
+
createNotebookCreationTool,
|
|
72
|
+
createRunCellTool,
|
|
73
|
+
createSaveNotebookTool,
|
|
74
|
+
createSetCellContentTool
|
|
75
|
+
} from './tools/notebook';
|
|
76
|
+
|
|
77
|
+
import {
|
|
78
|
+
createCopyFileTool,
|
|
79
|
+
createDeleteFileTool,
|
|
80
|
+
createNavigateToDirectoryTool,
|
|
81
|
+
createNewFileTool,
|
|
82
|
+
createOpenFileTool,
|
|
83
|
+
createRenameFileTool
|
|
84
|
+
} from './tools/file';
|
|
85
|
+
|
|
86
|
+
import {
|
|
87
|
+
createDiscoverCommandsTool,
|
|
88
|
+
createExecuteCommandTool
|
|
89
|
+
} from './tools/commands';
|
|
90
|
+
|
|
91
|
+
import { AISettingsWidget } from './widgets/ai-settings';
|
|
92
|
+
|
|
93
|
+
import { ChatWrapperWidget } from './widgets/chat-wrapper';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Command IDs namespace
|
|
97
|
+
*/
|
|
98
|
+
namespace CommandIds {
|
|
99
|
+
export const openSettings = '@jupyterlite/ai:open-settings';
|
|
100
|
+
export const reposition = '@jupyterlite/ai:reposition';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Chat provider registry plugin
|
|
105
|
+
*/
|
|
106
|
+
const chatProviderRegistryPlugin: JupyterFrontEndPlugin<IChatProviderRegistry> =
|
|
107
|
+
{
|
|
108
|
+
id: '@jupyterlite/ai:chat-provider-registry',
|
|
109
|
+
description: 'Chat AI provider registry',
|
|
110
|
+
autoStart: true,
|
|
111
|
+
provides: IChatProviderRegistry,
|
|
112
|
+
activate: () => {
|
|
113
|
+
return new ChatProviderRegistry();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Completion provider registry plugin
|
|
119
|
+
*/
|
|
120
|
+
const completionProviderRegistryPlugin: JupyterFrontEndPlugin<ICompletionProviderRegistry> =
|
|
121
|
+
{
|
|
122
|
+
id: '@jupyterlite/ai:completion-provider-registry',
|
|
123
|
+
description: 'Completion provider registry',
|
|
124
|
+
autoStart: true,
|
|
125
|
+
provides: ICompletionProviderRegistry,
|
|
126
|
+
activate: () => {
|
|
127
|
+
return new CompletionProviderRegistry();
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Built-in chat providers plugin
|
|
133
|
+
*/
|
|
134
|
+
const builtInChatProvidersPlugin: JupyterFrontEndPlugin<void> = {
|
|
135
|
+
id: '@jupyterlite/ai:built-in-chat-providers',
|
|
136
|
+
description: 'Register built-in chat AI providers',
|
|
137
|
+
autoStart: true,
|
|
138
|
+
requires: [IChatProviderRegistry],
|
|
139
|
+
activate: (app: JupyterFrontEnd, chatRegistry: IChatProviderRegistry) => {
|
|
140
|
+
registerBuiltInChatProviders(chatRegistry);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Built-in completion providers plugin
|
|
146
|
+
*/
|
|
147
|
+
const builtInCompletionProvidersPlugin: JupyterFrontEndPlugin<void> = {
|
|
148
|
+
id: '@jupyterlite/ai:built-in-completion-providers',
|
|
149
|
+
description: 'Register built-in completion providers',
|
|
35
150
|
autoStart: true,
|
|
36
|
-
|
|
37
|
-
activate: (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
151
|
+
requires: [ICompletionProviderRegistry],
|
|
152
|
+
activate: (
|
|
153
|
+
app: JupyterFrontEnd,
|
|
154
|
+
completionRegistry: ICompletionProviderRegistry
|
|
155
|
+
) => {
|
|
156
|
+
registerBuiltInCompletionProviders(completionRegistry);
|
|
41
157
|
}
|
|
42
158
|
};
|
|
43
159
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
160
|
+
/**
|
|
161
|
+
* Initialization data for the extension.
|
|
162
|
+
*/
|
|
163
|
+
const plugin: JupyterFrontEndPlugin<void> = {
|
|
164
|
+
id: '@jupyterlite/ai:plugin',
|
|
165
|
+
description: 'AI in JupyterLab',
|
|
47
166
|
autoStart: true,
|
|
48
|
-
requires: [
|
|
167
|
+
requires: [
|
|
168
|
+
IAISettingsModel,
|
|
169
|
+
IToolRegistry,
|
|
170
|
+
IRenderMimeRegistry,
|
|
171
|
+
IDocumentManager,
|
|
172
|
+
IChatProviderRegistry
|
|
173
|
+
],
|
|
49
174
|
optional: [
|
|
50
|
-
INotebookTracker,
|
|
51
|
-
ISettingRegistry,
|
|
52
175
|
IThemeManager,
|
|
53
|
-
|
|
176
|
+
ICommandPalette,
|
|
177
|
+
INotebookTracker,
|
|
178
|
+
ILayoutRestorer,
|
|
179
|
+
ILabShell
|
|
54
180
|
],
|
|
55
|
-
activate:
|
|
181
|
+
activate: (
|
|
56
182
|
app: JupyterFrontEnd,
|
|
57
|
-
|
|
183
|
+
settingsModel: AISettingsModel,
|
|
184
|
+
toolRegistry: IToolRegistry,
|
|
58
185
|
rmRegistry: IRenderMimeRegistry,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
186
|
+
docManager: IDocumentManager,
|
|
187
|
+
chatProviderRegistry: IChatProviderRegistry,
|
|
188
|
+
themeManager?: IThemeManager,
|
|
189
|
+
palette?: ICommandPalette,
|
|
190
|
+
notebookTracker?: INotebookTracker,
|
|
191
|
+
restorer?: ILayoutRestorer,
|
|
192
|
+
labShell?: ILabShell
|
|
193
|
+
): void => {
|
|
194
|
+
// Create ActiveCellManager if notebook tracker is available
|
|
195
|
+
let activeCellManager: ActiveCellManager | undefined;
|
|
66
196
|
if (notebookTracker) {
|
|
67
197
|
activeCellManager = new ActiveCellManager({
|
|
68
198
|
tracker: notebookTracker,
|
|
@@ -70,55 +200,45 @@ const chatPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
70
200
|
});
|
|
71
201
|
}
|
|
72
202
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
203
|
+
// Create Agent Manager first so it can be shared
|
|
204
|
+
const agentManager = new AgentManager({
|
|
205
|
+
settingsModel,
|
|
206
|
+
toolRegistry,
|
|
207
|
+
chatProviderRegistry: chatProviderRegistry
|
|
76
208
|
});
|
|
77
209
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
personaName = setting.get('personaName').composite as string;
|
|
87
|
-
|
|
88
|
-
// set the properties
|
|
89
|
-
chatHandler.config = { sendWithShiftEnter, enableCodeToolbar };
|
|
90
|
-
chatHandler.personaName = personaName;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
Promise.all([app.restored, settingsRegistry?.load(chatPlugin.id)])
|
|
94
|
-
.then(([, settings]) => {
|
|
95
|
-
if (!settings) {
|
|
96
|
-
console.warn(
|
|
97
|
-
'The SettingsRegistry is not loaded for the chat extension'
|
|
98
|
-
);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
loadSetting(settings);
|
|
102
|
-
settings.changed.connect(loadSetting);
|
|
103
|
-
})
|
|
104
|
-
.catch(reason => {
|
|
105
|
-
console.error(
|
|
106
|
-
`Something went wrong when reading the settings.\n${reason}`
|
|
107
|
-
);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
let chatWidget: ReactWidget | null = null;
|
|
210
|
+
// Create AI chat model
|
|
211
|
+
const chatModel = new AIChatModel({
|
|
212
|
+
user: { username: 'user', display_name: 'User' },
|
|
213
|
+
settingsModel,
|
|
214
|
+
agentManager,
|
|
215
|
+
activeCellManager,
|
|
216
|
+
documentManager: docManager
|
|
217
|
+
});
|
|
111
218
|
|
|
219
|
+
// Create input toolbar registry with all buttons
|
|
112
220
|
const inputToolbarRegistry = InputToolbarRegistry.defaultToolbarRegistry();
|
|
113
|
-
const stopButton = stopItem(
|
|
221
|
+
const stopButton = stopItem();
|
|
222
|
+
const clearButton = clearItem();
|
|
223
|
+
const toolSelectButton = createToolSelectItem(
|
|
224
|
+
toolRegistry,
|
|
225
|
+
settingsModel.config.toolsEnabled
|
|
226
|
+
);
|
|
227
|
+
const modelSelectButton = createModelSelectItem(settingsModel);
|
|
228
|
+
|
|
114
229
|
inputToolbarRegistry.addItem('stop', stopButton);
|
|
230
|
+
inputToolbarRegistry.addItem('clear', clearButton);
|
|
231
|
+
inputToolbarRegistry.addItem('model', modelSelectButton);
|
|
232
|
+
inputToolbarRegistry.addItem('tools', toolSelectButton);
|
|
233
|
+
|
|
234
|
+
// Listen to writers changes to show/hide stop button
|
|
235
|
+
chatModel.writersChanged.connect((_, writers) => {
|
|
236
|
+
// Check if AI is currently writing (streaming)
|
|
237
|
+
const aiWriting = writers.some(
|
|
238
|
+
writer => writer.user.username === 'ai-assistant'
|
|
239
|
+
);
|
|
115
240
|
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
writers.filter(
|
|
119
|
-
writer => writer.user.username === chatHandler.personaName
|
|
120
|
-
).length
|
|
121
|
-
) {
|
|
241
|
+
if (aiWriting) {
|
|
122
242
|
inputToolbarRegistry.hide('send');
|
|
123
243
|
inputToolbarRegistry.show('stop');
|
|
124
244
|
} else {
|
|
@@ -127,182 +247,292 @@ const chatPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
127
247
|
}
|
|
128
248
|
});
|
|
129
249
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
inputToolbarRegistry
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
250
|
+
// Listen for settings changes to update tool availability
|
|
251
|
+
settingsModel.stateChanged.connect(() => {
|
|
252
|
+
const config = settingsModel.config;
|
|
253
|
+
if (!config.toolsEnabled) {
|
|
254
|
+
inputToolbarRegistry.hide('tools');
|
|
255
|
+
} else {
|
|
256
|
+
inputToolbarRegistry.show('tools');
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Create attachment opener registry to handle file attachments
|
|
261
|
+
const attachmentOpenerRegistry = new AttachmentOpenerRegistry();
|
|
262
|
+
attachmentOpenerRegistry.set('file', attachment => {
|
|
263
|
+
app.commands.execute('docmanager:open', { path: attachment.value });
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
attachmentOpenerRegistry.set('notebook', attachment => {
|
|
267
|
+
app.commands.execute('docmanager:open', { path: attachment.value });
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Create chat panel with drag/drop functionality
|
|
271
|
+
const chatPanel = new ChatWidget({
|
|
272
|
+
model: chatModel,
|
|
273
|
+
rmRegistry,
|
|
274
|
+
themeManager,
|
|
275
|
+
inputToolbarRegistry,
|
|
276
|
+
attachmentOpenerRegistry
|
|
277
|
+
});
|
|
142
278
|
|
|
143
|
-
|
|
144
|
-
|
|
279
|
+
// Create wrapper widget with a toolbar
|
|
280
|
+
const chatWrapper = new ChatWrapperWidget({
|
|
281
|
+
chatPanel,
|
|
282
|
+
commands: app.commands,
|
|
283
|
+
chatModel,
|
|
284
|
+
settingsModel
|
|
285
|
+
});
|
|
145
286
|
|
|
146
|
-
app.shell.add(
|
|
287
|
+
app.shell.add(chatWrapper, 'left', { rank: 1000 });
|
|
288
|
+
|
|
289
|
+
const settingsWidget = new AISettingsWidget({
|
|
290
|
+
settingsModel,
|
|
291
|
+
agentManager,
|
|
292
|
+
themeManager,
|
|
293
|
+
chatProviderRegistry
|
|
294
|
+
});
|
|
295
|
+
settingsWidget.id = 'jupyterlite-ai-settings';
|
|
296
|
+
settingsWidget.title.icon = settingsIcon;
|
|
147
297
|
|
|
148
298
|
if (restorer) {
|
|
149
|
-
restorer.add(
|
|
299
|
+
restorer.add(chatWrapper, chatWrapper.id);
|
|
300
|
+
restorer.add(settingsWidget, settingsWidget.id);
|
|
150
301
|
}
|
|
302
|
+
|
|
303
|
+
registerCommands(app, palette, settingsWidget, labShell);
|
|
151
304
|
}
|
|
152
305
|
};
|
|
153
306
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
307
|
+
function registerCommands(
|
|
308
|
+
app: JupyterFrontEnd,
|
|
309
|
+
palette?: ICommandPalette,
|
|
310
|
+
settingsWidget?: AISettingsWidget,
|
|
311
|
+
labShell?: ILabShell
|
|
312
|
+
) {
|
|
313
|
+
const { commands } = app;
|
|
314
|
+
|
|
315
|
+
commands.addCommand(CommandIds.openSettings, {
|
|
316
|
+
label: 'AI Settings',
|
|
317
|
+
caption: 'Configure AI providers and behavior',
|
|
318
|
+
icon: settingsIcon,
|
|
319
|
+
execute: () => {
|
|
320
|
+
// Check if the widget already exists in shell
|
|
321
|
+
let widget = Array.from(app.shell.widgets('main')).find(
|
|
322
|
+
w => w.id === 'jupyterlite-ai-settings'
|
|
323
|
+
) as AISettingsWidget;
|
|
324
|
+
|
|
325
|
+
if (!widget && settingsWidget) {
|
|
326
|
+
// Use the pre-created widget
|
|
327
|
+
widget = settingsWidget;
|
|
328
|
+
app.shell.add(widget, 'main');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (widget) {
|
|
332
|
+
app.shell.activateById(widget.id);
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
describedBy: {
|
|
336
|
+
args: {}
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
if (labShell) {
|
|
341
|
+
commands.addCommand(CommandIds.reposition, {
|
|
342
|
+
label: 'Reposition Widget',
|
|
343
|
+
execute: (args: any) => {
|
|
344
|
+
const { widgetId, area, mode } = args;
|
|
345
|
+
const widget = widgetId
|
|
346
|
+
? Array.from(labShell.widgets('main')).find(w => w.id === widgetId) ||
|
|
347
|
+
labShell.currentWidget
|
|
348
|
+
: labShell.currentWidget;
|
|
349
|
+
|
|
350
|
+
if (!widget) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (area && area !== 'main') {
|
|
355
|
+
// Move to different area
|
|
356
|
+
labShell.move(widget, area);
|
|
357
|
+
labShell.activateById(widget.id);
|
|
358
|
+
} else if (mode) {
|
|
359
|
+
// Reposition within main area using split mode
|
|
360
|
+
labShell.add(widget, 'main', { mode, activate: true });
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
describedBy: {
|
|
364
|
+
args: {
|
|
365
|
+
type: 'object',
|
|
366
|
+
properties: {
|
|
367
|
+
widgetId: {
|
|
368
|
+
type: 'string',
|
|
369
|
+
description:
|
|
370
|
+
'The widget ID to reposition in the application shell'
|
|
371
|
+
},
|
|
372
|
+
area: {
|
|
373
|
+
type: 'string',
|
|
374
|
+
description: 'The name of the area to reposition the widget to'
|
|
375
|
+
},
|
|
376
|
+
mode: {
|
|
377
|
+
type: 'string',
|
|
378
|
+
enum: ['split-left', 'split-right', 'split-top', 'split-bottom'],
|
|
379
|
+
description: 'The mode to use when repositioning the widget'
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
166
384
|
});
|
|
167
|
-
manager.registerInlineProvider(completer);
|
|
168
385
|
}
|
|
169
|
-
};
|
|
170
386
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
app: JupyterFrontEnd,
|
|
180
|
-
editorRegistry: IFormRendererRegistry,
|
|
181
|
-
settingRegistry: ISettingRegistry,
|
|
182
|
-
rmRegistry?: IRenderMimeRegistry,
|
|
183
|
-
secretsManager?: ISecretsManager
|
|
184
|
-
): IAIProviderRegistry => {
|
|
185
|
-
const providerRegistry = new AIProviderRegistry({
|
|
186
|
-
token,
|
|
187
|
-
secretsManager
|
|
188
|
-
});
|
|
387
|
+
// Add to command palette if available
|
|
388
|
+
if (palette) {
|
|
389
|
+
palette.addItem({
|
|
390
|
+
command: CommandIds.openSettings,
|
|
391
|
+
category: 'AI Assistant'
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
189
395
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
396
|
+
/**
|
|
397
|
+
* A plugin to provide AI-powered code completion.
|
|
398
|
+
*/
|
|
399
|
+
const completionPlugin: JupyterFrontEndPlugin<void> = {
|
|
400
|
+
id: '@jupyterlite/ai:completion',
|
|
401
|
+
description: 'AI-powered code completion',
|
|
402
|
+
autoStart: true,
|
|
403
|
+
requires: [IAISettingsModel, ICompletionProviderRegistry],
|
|
404
|
+
optional: [ICompletionProviderManager],
|
|
405
|
+
activate: (
|
|
406
|
+
app: JupyterFrontEnd,
|
|
407
|
+
settingsModel: AISettingsModel,
|
|
408
|
+
completionProviderRegistry: ICompletionProviderRegistry,
|
|
409
|
+
manager?: ICompletionProviderManager
|
|
410
|
+
) => {
|
|
411
|
+
if (!manager) {
|
|
412
|
+
console.info(
|
|
413
|
+
'Completion provider manager not available, skipping AI completion setup'
|
|
198
414
|
);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
199
417
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
delete settings.schema.properties?.['UseSecretsManager'];
|
|
205
|
-
}
|
|
206
|
-
const updateProvider = () => {
|
|
207
|
-
// Get the Ai provider settings.
|
|
208
|
-
const providerSettings = settings.get('AIproviders')
|
|
209
|
-
.composite as ReadonlyPartialJSONObject;
|
|
210
|
-
|
|
211
|
-
// Update completer provider.
|
|
212
|
-
if (Object.keys(providerSettings).includes('completer')) {
|
|
213
|
-
providerRegistry.setCompleterProvider(
|
|
214
|
-
providerSettings['completer'] as ReadonlyPartialJSONObject
|
|
215
|
-
);
|
|
216
|
-
} else {
|
|
217
|
-
providerRegistry.setCompleterProvider({});
|
|
218
|
-
}
|
|
418
|
+
const completionProvider = new AICompletionProvider({
|
|
419
|
+
settingsModel,
|
|
420
|
+
completionProviderRegistry: completionProviderRegistry
|
|
421
|
+
});
|
|
219
422
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
providerSettings['chat'] as ReadonlyPartialJSONObject
|
|
224
|
-
);
|
|
225
|
-
} else {
|
|
226
|
-
providerRegistry.setChatProvider({});
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
settings.changed.connect(() => updateProvider());
|
|
231
|
-
updateProvider();
|
|
232
|
-
})
|
|
233
|
-
.catch(reason => {
|
|
234
|
-
console.error(
|
|
235
|
-
`Failed to load settings for ${providerRegistryPlugin.id}`,
|
|
236
|
-
reason
|
|
237
|
-
);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
return providerRegistry;
|
|
241
|
-
}
|
|
242
|
-
}));
|
|
423
|
+
manager.registerInlineProvider(completionProvider);
|
|
424
|
+
}
|
|
425
|
+
};
|
|
243
426
|
|
|
244
|
-
|
|
245
|
-
|
|
427
|
+
/**
|
|
428
|
+
* A plugin to provide the settings model.
|
|
429
|
+
*/
|
|
430
|
+
const settingsModel: JupyterFrontEndPlugin<AISettingsModel> = {
|
|
431
|
+
id: '@jupyterlite/ai:settings-model',
|
|
432
|
+
description: 'Provide the AI settings model',
|
|
246
433
|
autoStart: true,
|
|
247
|
-
|
|
248
|
-
|
|
434
|
+
provides: IAISettingsModel,
|
|
435
|
+
requires: [ISettingRegistry],
|
|
436
|
+
activate: (app: JupyterFrontEnd, settingRegistry: ISettingRegistry) => {
|
|
437
|
+
return new AISettingsModel({ settingRegistry });
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* A plugin to provide the tool registry.
|
|
443
|
+
*/
|
|
444
|
+
const toolRegistry: JupyterFrontEndPlugin<IToolRegistry> = {
|
|
445
|
+
id: '@jupyterlite/ai:tool-registry',
|
|
446
|
+
description: 'Provide the AI tool registry',
|
|
447
|
+
autoStart: true,
|
|
448
|
+
requires: [IAISettingsModel, IDocumentManager, IKernelSpecManager],
|
|
449
|
+
optional: [INotebookTracker],
|
|
450
|
+
provides: IToolRegistry,
|
|
249
451
|
activate: (
|
|
250
452
|
app: JupyterFrontEnd,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
453
|
+
settingsModel: AISettingsModel,
|
|
454
|
+
docManager: IDocumentManager,
|
|
455
|
+
kernelSpecManager: KernelSpec.IManager,
|
|
456
|
+
notebookTracker?: INotebookTracker
|
|
457
|
+
) => {
|
|
458
|
+
const toolRegistry = new ToolRegistry();
|
|
459
|
+
|
|
460
|
+
const notebookCreationTool = createNotebookCreationTool(
|
|
461
|
+
docManager,
|
|
462
|
+
kernelSpecManager
|
|
259
463
|
);
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
464
|
+
toolRegistry.add('create_notebook', notebookCreationTool);
|
|
465
|
+
|
|
466
|
+
// Add high-level notebook operation tools
|
|
467
|
+
const addCellTool = createAddCellTool(docManager, notebookTracker);
|
|
468
|
+
const getNotebookInfoTool = createGetNotebookInfoTool(
|
|
469
|
+
docManager,
|
|
470
|
+
notebookTracker
|
|
471
|
+
);
|
|
472
|
+
const getCellInfoTool = createGetCellInfoTool(docManager, notebookTracker);
|
|
473
|
+
const setCellContentTool = createSetCellContentTool(
|
|
474
|
+
docManager,
|
|
475
|
+
notebookTracker
|
|
476
|
+
);
|
|
477
|
+
const runCellTool = createRunCellTool(docManager, notebookTracker);
|
|
478
|
+
const deleteCellTool = createDeleteCellTool(docManager, notebookTracker);
|
|
479
|
+
const saveNotebookTool = createSaveNotebookTool(
|
|
480
|
+
docManager,
|
|
481
|
+
notebookTracker
|
|
482
|
+
);
|
|
483
|
+
const executeActiveCellTool = createExecuteActiveCellTool(
|
|
484
|
+
docManager,
|
|
485
|
+
notebookTracker
|
|
263
486
|
);
|
|
264
487
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
).composite as string;
|
|
274
|
-
}
|
|
488
|
+
toolRegistry.add('add_cell', addCellTool);
|
|
489
|
+
toolRegistry.add('get_notebook_info', getNotebookInfoTool);
|
|
490
|
+
toolRegistry.add('get_cell_info', getCellInfoTool);
|
|
491
|
+
toolRegistry.add('set_cell_content', setCellContentTool);
|
|
492
|
+
toolRegistry.add('run_cell', runCellTool);
|
|
493
|
+
toolRegistry.add('delete_cell', deleteCellTool);
|
|
494
|
+
toolRegistry.add('save_notebook', saveNotebookTool);
|
|
495
|
+
toolRegistry.add('execute_active_cell', executeActiveCellTool);
|
|
275
496
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
497
|
+
// Add file operation tools
|
|
498
|
+
const newFileTool = createNewFileTool(docManager);
|
|
499
|
+
const openFileTool = createOpenFileTool(docManager);
|
|
500
|
+
const deleteFileTool = createDeleteFileTool(docManager);
|
|
501
|
+
const renameFileTool = createRenameFileTool(docManager);
|
|
502
|
+
const copyFileTool = createCopyFileTool(docManager);
|
|
503
|
+
const navigateToDirectoryTool = createNavigateToDirectoryTool(app.commands);
|
|
504
|
+
|
|
505
|
+
toolRegistry.add('create_file', newFileTool);
|
|
506
|
+
toolRegistry.add('open_file', openFileTool);
|
|
507
|
+
toolRegistry.add('delete_file', deleteFileTool);
|
|
508
|
+
toolRegistry.add('rename_file', renameFileTool);
|
|
509
|
+
toolRegistry.add('copy_file', copyFileTool);
|
|
510
|
+
toolRegistry.add('navigate_to_directory', navigateToDirectoryTool);
|
|
511
|
+
|
|
512
|
+
// Add command operation tools
|
|
513
|
+
const discoverCommandsTool = createDiscoverCommandsTool(app.commands);
|
|
514
|
+
const executeCommandTool = createExecuteCommandTool(
|
|
515
|
+
app.commands,
|
|
516
|
+
settingsModel
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
toolRegistry.add('discover_commands', discoverCommandsTool);
|
|
520
|
+
toolRegistry.add('execute_command', executeCommandTool);
|
|
521
|
+
|
|
522
|
+
return toolRegistry;
|
|
295
523
|
}
|
|
296
524
|
};
|
|
297
525
|
|
|
298
526
|
export default [
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
527
|
+
chatProviderRegistryPlugin,
|
|
528
|
+
completionProviderRegistryPlugin,
|
|
529
|
+
builtInChatProvidersPlugin,
|
|
530
|
+
builtInCompletionProvidersPlugin,
|
|
531
|
+
plugin,
|
|
532
|
+
completionPlugin,
|
|
533
|
+
settingsModel,
|
|
534
|
+
toolRegistry
|
|
305
535
|
];
|
|
306
536
|
|
|
307
|
-
|
|
308
|
-
export * from './
|
|
537
|
+
// Export extension points for other extensions to use
|
|
538
|
+
export * from './tokens';
|