@jupyterlite/ai 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +5 -214
  2. package/lib/agent.d.ts +58 -66
  3. package/lib/agent.js +274 -300
  4. package/lib/approval-buttons.d.ts +19 -82
  5. package/lib/approval-buttons.js +36 -289
  6. package/lib/chat-model-registry.d.ts +6 -0
  7. package/lib/chat-model-registry.js +4 -1
  8. package/lib/chat-model.d.ts +19 -54
  9. package/lib/chat-model.js +243 -303
  10. package/lib/components/clear-button.d.ts +6 -1
  11. package/lib/components/clear-button.js +8 -3
  12. package/lib/components/completion-status.d.ts +5 -0
  13. package/lib/components/completion-status.js +5 -4
  14. package/lib/components/model-select.d.ts +6 -1
  15. package/lib/components/model-select.js +9 -8
  16. package/lib/components/stop-button.d.ts +6 -1
  17. package/lib/components/stop-button.js +8 -3
  18. package/lib/components/token-usage-display.d.ts +5 -0
  19. package/lib/components/token-usage-display.js +2 -2
  20. package/lib/components/tool-select.d.ts +6 -1
  21. package/lib/components/tool-select.js +6 -5
  22. package/lib/index.js +58 -38
  23. package/lib/models/settings-model.d.ts +1 -1
  24. package/lib/providers/built-in-providers.js +38 -19
  25. package/lib/providers/models.d.ts +3 -3
  26. package/lib/providers/provider-registry.d.ts +3 -4
  27. package/lib/providers/provider-registry.js +1 -4
  28. package/lib/tokens.d.ts +5 -6
  29. package/lib/tools/commands.d.ts +2 -1
  30. package/lib/tools/commands.js +37 -46
  31. package/lib/tools/file.js +49 -73
  32. package/lib/tools/notebook.js +370 -445
  33. package/lib/widgets/ai-settings.d.ts +6 -0
  34. package/lib/widgets/ai-settings.js +72 -71
  35. package/lib/widgets/main-area-chat.d.ts +2 -0
  36. package/lib/widgets/main-area-chat.js +5 -2
  37. package/lib/widgets/provider-config-dialog.d.ts +2 -0
  38. package/lib/widgets/provider-config-dialog.js +34 -34
  39. package/package.json +12 -12
  40. package/src/agent.ts +342 -361
  41. package/src/approval-buttons.ts +43 -389
  42. package/src/chat-model-registry.ts +9 -1
  43. package/src/chat-model.ts +355 -370
  44. package/src/completion/completion-provider.ts +2 -3
  45. package/src/components/clear-button.tsx +16 -3
  46. package/src/components/completion-status.tsx +18 -4
  47. package/src/components/model-select.tsx +21 -8
  48. package/src/components/stop-button.tsx +16 -3
  49. package/src/components/token-usage-display.tsx +14 -2
  50. package/src/components/tool-select.tsx +23 -5
  51. package/src/index.ts +75 -36
  52. package/src/models/settings-model.ts +1 -1
  53. package/src/providers/built-in-providers.ts +38 -19
  54. package/src/providers/models.ts +3 -3
  55. package/src/providers/provider-registry.ts +4 -8
  56. package/src/tokens.ts +5 -6
  57. package/src/tools/commands.ts +39 -50
  58. package/src/tools/file.ts +49 -75
  59. package/src/tools/notebook.ts +451 -510
  60. package/src/widgets/ai-settings.tsx +153 -84
  61. package/src/widgets/main-area-chat.ts +8 -2
  62. package/src/widgets/provider-config-dialog.tsx +54 -41
  63. package/style/base.css +13 -73
  64. package/lib/mcp/browser.d.ts +0 -68
  65. package/lib/mcp/browser.js +0 -138
  66. package/src/mcp/browser.ts +0 -220
@@ -5,8 +5,7 @@ import {
5
5
  IInlineCompletionProvider
6
6
  } from '@jupyterlab/completer';
7
7
  import { NotebookPanel } from '@jupyterlab/notebook';
8
- import { LanguageModelV2 } from '@ai-sdk/provider';
9
- import { generateText } from 'ai';
8
+ import { generateText, type LanguageModel } from 'ai';
10
9
  import { ISecretsManager } from 'jupyter-secrets-manager';
11
10
 
12
11
  import { AISettingsModel } from '../models/settings-model';
@@ -293,7 +292,7 @@ export class AICompletionProvider implements IInlineCompletionProvider {
293
292
 
294
293
  private _settingsModel: AISettingsModel;
295
294
  private _providerRegistry?: IProviderRegistry;
296
- private _model: LanguageModelV2 | null = null;
295
+ private _model: LanguageModel | null = null;
297
296
  private _secretsManager?: ISecretsManager;
298
297
  }
299
298
 
@@ -1,5 +1,7 @@
1
1
  import { InputToolbarRegistry, TooltippedButton } from '@jupyter/chat';
2
2
 
3
+ import type { TranslationBundle } from '@jupyterlab/translation';
4
+
3
5
  import ClearIcon from '@mui/icons-material/Clear';
4
6
 
5
7
  import React from 'react';
@@ -15,13 +17,18 @@ export interface IClearButtonProps
15
17
  * The function to clear messages.
16
18
  */
17
19
  clearMessages: () => void;
20
+ /**
21
+ * The application language translator.
22
+ */
23
+ translator: TranslationBundle;
18
24
  }
19
25
 
20
26
  /**
21
27
  * The clear button component.
22
28
  */
23
29
  export function ClearButton(props: IClearButtonProps): JSX.Element {
24
- const tooltip = 'Clear chat';
30
+ const { translator: trans } = props;
31
+ const tooltip = trans.__('Clear chat');
25
32
  return (
26
33
  <TooltippedButton
27
34
  onClick={props.clearMessages}
@@ -41,13 +48,19 @@ export function ClearButton(props: IClearButtonProps): JSX.Element {
41
48
  /**
42
49
  * Factory returning the clear button toolbar item.
43
50
  */
44
- export function clearItem(): InputToolbarRegistry.IToolbarItem {
51
+ export function clearItem(
52
+ translator: TranslationBundle
53
+ ): InputToolbarRegistry.IToolbarItem {
45
54
  return {
46
55
  element: (props: InputToolbarRegistry.IToolbarItemProps) => {
47
56
  const { model } = props;
48
57
  const clearMessages = () =>
49
58
  (model.chatContext as AIChatModel.IAIChatContext).clearMessages();
50
- const clearProps: IClearButtonProps = { ...props, clearMessages };
59
+ const clearProps: IClearButtonProps = {
60
+ ...props,
61
+ clearMessages,
62
+ translator
63
+ };
51
64
  return ClearButton(clearProps);
52
65
  },
53
66
  position: 0,
@@ -1,6 +1,7 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { AISettingsModel } from '../models/settings-model';
3
3
  import { ReactWidget } from '@jupyterlab/ui-components';
4
+ import type { TranslationBundle } from '@jupyterlab/translation';
4
5
  import { jupyternautIcon } from '../icons';
5
6
 
6
7
  const COMPLETION_STATUS_CLASS = 'jp-ai-completion-status';
@@ -14,12 +15,17 @@ interface ICompletionStatusProps {
14
15
  * The settings model.
15
16
  */
16
17
  settingsModel: AISettingsModel;
18
+ /**
19
+ * The application language translator.
20
+ */
21
+ translator: TranslationBundle;
17
22
  }
18
23
 
19
24
  /**
20
25
  * The completion status component.
21
26
  */
22
27
  function CompletionStatus(props: ICompletionStatusProps): JSX.Element {
28
+ const { translator: trans } = props;
23
29
  const [disabled, setDisabled] = useState<boolean>(true);
24
30
  const [title, setTitle] = useState<string>('');
25
31
 
@@ -30,15 +36,23 @@ function CompletionStatus(props: ICompletionStatusProps): JSX.Element {
30
36
  const stateChanged = (model: AISettingsModel) => {
31
37
  if (model.config.useSameProviderForChatAndCompleter) {
32
38
  setDisabled(false);
33
- setTitle(`Completion using ${model.getDefaultProvider()?.model}`);
39
+ setTitle(
40
+ trans.__(
41
+ 'Completion using %1',
42
+ model.getDefaultProvider()?.model ?? ''
43
+ )
44
+ );
34
45
  } else if (model.config.activeCompleterProvider) {
35
46
  setDisabled(false);
36
47
  setTitle(
37
- `Completion using ${model.getProvider(model.config.activeCompleterProvider)?.model}`
48
+ trans.__(
49
+ 'Completion using %1',
50
+ model.getProvider(model.config.activeCompleterProvider)?.model ?? ''
51
+ )
38
52
  );
39
53
  } else {
40
54
  setDisabled(true);
41
- setTitle('No completion');
55
+ setTitle(trans.__('No completion'));
42
56
  }
43
57
  };
44
58
 
@@ -48,7 +62,7 @@ function CompletionStatus(props: ICompletionStatusProps): JSX.Element {
48
62
  return () => {
49
63
  props.settingsModel.stateChanged.disconnect(stateChanged);
50
64
  };
51
- }, [props.settingsModel]);
65
+ }, [props.settingsModel, trans]);
52
66
 
53
67
  return (
54
68
  <jupyternautIcon.react
@@ -1,4 +1,5 @@
1
1
  import { InputToolbarRegistry, TooltippedButton } from '@jupyter/chat';
2
+ import type { TranslationBundle } from '@jupyterlab/translation';
2
3
  import CheckIcon from '@mui/icons-material/Check';
3
4
  import { Menu, MenuItem, Typography } from '@mui/material';
4
5
  import React, { useCallback, useEffect, useState } from 'react';
@@ -14,13 +15,17 @@ export interface IModelSelectProps
14
15
  * The settings model to get available models and current selection from.
15
16
  */
16
17
  settingsModel: AISettingsModel;
18
+ /**
19
+ * The application language translator.
20
+ */
21
+ translator: TranslationBundle;
17
22
  }
18
23
 
19
24
  /**
20
25
  * The model select component for choosing AI models.
21
26
  */
22
27
  export function ModelSelect(props: IModelSelectProps): JSX.Element {
23
- const { settingsModel, model } = props;
28
+ const { settingsModel, model, translator: trans } = props;
24
29
  const agentManager = (model.chatContext as AIChatModel.IAIChatContext)
25
30
  .agentManager;
26
31
 
@@ -97,13 +102,15 @@ export function ModelSelect(props: IModelSelectProps): JSX.Element {
97
102
  return (
98
103
  <TooltippedButton
99
104
  onClick={() => {}}
100
- tooltip="No providers configured. Please go to AI Settings to add a provider."
105
+ tooltip={trans.__(
106
+ 'No providers configured. Please go to AI Settings to add a provider.'
107
+ )}
101
108
  buttonProps={{
102
109
  size: 'small',
103
110
  variant: 'outlined',
104
111
  color: 'warning',
105
112
  disabled: true,
106
- title: 'No Providers Available'
113
+ title: trans.__('No Providers Available')
107
114
  }}
108
115
  sx={{
109
116
  minWidth: 'auto',
@@ -116,7 +123,7 @@ export function ModelSelect(props: IModelSelectProps): JSX.Element {
116
123
  variant="caption"
117
124
  sx={{ fontSize: '0.7rem', fontWeight: 500 }}
118
125
  >
119
- No Providers
126
+ {trans.__('No Providers')}
120
127
  </Typography>
121
128
  </TooltippedButton>
122
129
  );
@@ -128,12 +135,16 @@ export function ModelSelect(props: IModelSelectProps): JSX.Element {
128
135
  onClick={e => {
129
136
  openMenu(e.currentTarget);
130
137
  }}
131
- tooltip={`Current Model: ${currentProviderLabel} - ${currentModel}`}
138
+ tooltip={trans.__(
139
+ 'Current Model: %1 - %2',
140
+ currentProviderLabel,
141
+ currentModel
142
+ )}
132
143
  buttonProps={{
133
144
  size: 'small',
134
145
  variant: 'contained',
135
146
  color: 'primary',
136
- title: 'Select AI Model',
147
+ title: trans.__('Select AI Model'),
137
148
  onKeyDown: e => {
138
149
  if (e.key !== 'Enter' && e.key !== ' ') {
139
150
  return;
@@ -237,7 +248,8 @@ export function ModelSelect(props: IModelSelectProps): JSX.Element {
237
248
  * Factory function returning the toolbar item for model selection.
238
249
  */
239
250
  export function createModelSelectItem(
240
- settingsModel: AISettingsModel
251
+ settingsModel: AISettingsModel,
252
+ translator: TranslationBundle
241
253
  ): InputToolbarRegistry.IToolbarItem {
242
254
  return {
243
255
  element: (props: InputToolbarRegistry.IToolbarItemProps) => {
@@ -247,7 +259,8 @@ export function createModelSelectItem(
247
259
  }
248
260
  const modelSelectProps: IModelSelectProps = {
249
261
  ...props,
250
- settingsModel
262
+ settingsModel,
263
+ translator
251
264
  };
252
265
  return <ModelSelect {...modelSelectProps} />;
253
266
  },
@@ -1,5 +1,7 @@
1
1
  import { InputToolbarRegistry, TooltippedButton } from '@jupyter/chat';
2
2
 
3
+ import type { TranslationBundle } from '@jupyterlab/translation';
4
+
3
5
  import StopIcon from '@mui/icons-material/Stop';
4
6
 
5
7
  import React from 'react';
@@ -15,13 +17,18 @@ export interface IStopButtonProps
15
17
  * The function to stop streaming.
16
18
  */
17
19
  stopStreaming: () => void;
20
+ /**
21
+ * The application language translator.
22
+ */
23
+ translator: TranslationBundle;
18
24
  }
19
25
 
20
26
  /**
21
27
  * The stop button component.
22
28
  */
23
29
  export function StopButton(props: IStopButtonProps): JSX.Element {
24
- const tooltip = 'Stop streaming';
30
+ const { translator: trans } = props;
31
+ const tooltip = trans.__('Stop streaming');
25
32
  return (
26
33
  <TooltippedButton
27
34
  onClick={props.stopStreaming}
@@ -41,13 +48,19 @@ export function StopButton(props: IStopButtonProps): JSX.Element {
41
48
  /**
42
49
  * Factory returning the stop button toolbar item.
43
50
  */
44
- export function stopItem(): InputToolbarRegistry.IToolbarItem {
51
+ export function stopItem(
52
+ translator: TranslationBundle
53
+ ): InputToolbarRegistry.IToolbarItem {
45
54
  return {
46
55
  element: (props: InputToolbarRegistry.IToolbarItemProps) => {
47
56
  const { model } = props;
48
57
  const stopStreaming = () =>
49
58
  (model.chatContext as AIChatModel.IAIChatContext).stopStreaming();
50
- const stopProps: IStopButtonProps = { ...props, stopStreaming };
59
+ const stopProps: IStopButtonProps = {
60
+ ...props,
61
+ stopStreaming,
62
+ translator
63
+ };
51
64
  return StopButton(stopProps);
52
65
  },
53
66
  position: 50,
@@ -1,4 +1,5 @@
1
1
  import { ReactWidget, UseSignal } from '@jupyterlab/ui-components';
2
+ import type { TranslationBundle } from '@jupyterlab/translation';
2
3
  import React from 'react';
3
4
  import { ISignal } from '@lumino/signaling';
4
5
  import { AISettingsModel } from '../models/settings-model';
@@ -22,6 +23,11 @@ export interface ITokenUsageDisplayProps {
22
23
  * Initial token usage.
23
24
  */
24
25
  initialTokenUsage?: ITokenUsage;
26
+
27
+ /**
28
+ * The application language translator.
29
+ */
30
+ translator: TranslationBundle;
25
31
  }
26
32
 
27
33
  /**
@@ -32,7 +38,8 @@ export interface ITokenUsageDisplayProps {
32
38
  export const TokenUsageDisplay: React.FC<ITokenUsageDisplayProps> = ({
33
39
  tokenUsageChanged,
34
40
  settingsModel,
35
- initialTokenUsage
41
+ initialTokenUsage,
42
+ translator: trans
36
43
  }) => {
37
44
  return (
38
45
  <UseSignal signal={settingsModel.stateChanged} initialArgs={undefined}>
@@ -68,7 +75,12 @@ export const TokenUsageDisplay: React.FC<ITokenUsageDisplayProps> = ({
68
75
  borderRadius: '4px',
69
76
  whiteSpace: 'nowrap'
70
77
  }}
71
- title={`Token Usage - Sent: ${tokenUsage.inputTokens.toLocaleString()}, Received: ${tokenUsage.outputTokens.toLocaleString()}, Total: ${total.toLocaleString()}`}
78
+ title={trans.__(
79
+ 'Token Usage - Sent: %1, Received: %2, Total: %3',
80
+ tokenUsage.inputTokens.toLocaleString(),
81
+ tokenUsage.outputTokens.toLocaleString(),
82
+ total.toLocaleString()
83
+ )}
72
84
  >
73
85
  <span
74
86
  style={{
@@ -1,5 +1,7 @@
1
1
  import { InputToolbarRegistry, TooltippedButton } from '@jupyter/chat';
2
2
 
3
+ import type { TranslationBundle } from '@jupyterlab/translation';
4
+
3
5
  import BuildIcon from '@mui/icons-material/Build';
4
6
 
5
7
  import CheckIcon from '@mui/icons-material/Check';
@@ -32,13 +34,23 @@ export interface IToolSelectProps
32
34
  * Function to handle tool selection changes.
33
35
  */
34
36
  onToolSelectionChange: (selectedToolNames: string[]) => void;
37
+
38
+ /**
39
+ * The application language translator.
40
+ */
41
+ translator: TranslationBundle;
35
42
  }
36
43
 
37
44
  /**
38
45
  * The tool select component for choosing AI tools.
39
46
  */
40
47
  export function ToolSelect(props: IToolSelectProps): JSX.Element {
41
- const { toolRegistry, onToolSelectionChange, toolsEnabled } = props;
48
+ const {
49
+ toolRegistry,
50
+ onToolSelectionChange,
51
+ toolsEnabled,
52
+ translator: trans
53
+ } = props;
42
54
 
43
55
  const [selectedToolNames, setSelectedToolNames] = useState<string[]>([]);
44
56
  const [tools, setTools] = useState<INamedTool[]>(
@@ -111,12 +123,16 @@ export function ToolSelect(props: IToolSelectProps): JSX.Element {
111
123
  onClick={e => {
112
124
  openMenu(e.currentTarget);
113
125
  }}
114
- tooltip={`Tools (${selectedToolNames.length}/${tools.length} selected)`}
126
+ tooltip={trans.__(
127
+ 'Tools (%1/%2 selected)',
128
+ selectedToolNames.length.toString(),
129
+ tools.length.toString()
130
+ )}
115
131
  buttonProps={{
116
132
  size: 'small',
117
133
  variant: selectedToolNames.length > 0 ? 'contained' : 'outlined',
118
134
  color: 'primary',
119
- title: 'Select AI Tools',
135
+ title: trans.__('Select AI Tools'),
120
136
  onKeyDown: e => {
121
137
  if (e.key !== 'Enter' && e.key !== ' ') {
122
138
  return;
@@ -192,7 +208,8 @@ export function ToolSelect(props: IToolSelectProps): JSX.Element {
192
208
  */
193
209
  export function createToolSelectItem(
194
210
  toolRegistry: IToolRegistry,
195
- toolsEnabled: boolean = true
211
+ toolsEnabled: boolean = true,
212
+ translator: TranslationBundle
196
213
  ): InputToolbarRegistry.IToolbarItem {
197
214
  return {
198
215
  element: (props: InputToolbarRegistry.IToolbarItemProps) => {
@@ -209,7 +226,8 @@ export function createToolSelectItem(
209
226
  ...props,
210
227
  toolRegistry,
211
228
  onToolSelectionChange,
212
- toolsEnabled
229
+ toolsEnabled,
230
+ translator
213
231
  };
214
232
  return <ToolSelect {...toolSelectProps} />;
215
233
  },