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