@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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IThemeManager } from '@jupyterlab/apputils';
|
|
2
2
|
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
3
|
+
import type { TranslationBundle } from '@jupyterlab/translation';
|
|
3
4
|
import { Debouncer } from '@lumino/polling';
|
|
4
5
|
import Add from '@mui/icons-material/Add';
|
|
5
6
|
import Cable from '@mui/icons-material/Cable';
|
|
@@ -92,9 +93,10 @@ export class AISettingsWidget extends ReactWidget {
|
|
|
92
93
|
this._themeManager = options.themeManager;
|
|
93
94
|
this._providerRegistry = options.providerRegistry;
|
|
94
95
|
this._secretsManager = options.secretsManager;
|
|
96
|
+
this._trans = options.trans;
|
|
95
97
|
this.id = 'jupyterlite-ai-settings';
|
|
96
|
-
this.title.label = 'AI Settings';
|
|
97
|
-
this.title.caption = 'Configure AI providers and behavior';
|
|
98
|
+
this.title.label = this._trans.__('AI Settings');
|
|
99
|
+
this.title.caption = this._trans.__('Configure AI providers and behavior');
|
|
98
100
|
this.title.closable = true;
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -110,6 +112,7 @@ export class AISettingsWidget extends ReactWidget {
|
|
|
110
112
|
themeManager={this._themeManager}
|
|
111
113
|
providerRegistry={this._providerRegistry}
|
|
112
114
|
secretsManager={this._secretsManager}
|
|
115
|
+
trans={this._trans}
|
|
113
116
|
/>
|
|
114
117
|
);
|
|
115
118
|
}
|
|
@@ -119,6 +122,7 @@ export class AISettingsWidget extends ReactWidget {
|
|
|
119
122
|
private _themeManager?: IThemeManager;
|
|
120
123
|
private _providerRegistry: IProviderRegistry;
|
|
121
124
|
private _secretsManager?: ISecretsManager;
|
|
125
|
+
private _trans: TranslationBundle;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
/**
|
|
@@ -130,6 +134,7 @@ interface IAISettingsComponentProps {
|
|
|
130
134
|
themeManager?: IThemeManager;
|
|
131
135
|
providerRegistry: IProviderRegistry;
|
|
132
136
|
secretsManager?: ISecretsManager;
|
|
137
|
+
trans: TranslationBundle;
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
/**
|
|
@@ -142,10 +147,11 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
142
147
|
agentManagerFactory,
|
|
143
148
|
themeManager,
|
|
144
149
|
providerRegistry,
|
|
145
|
-
secretsManager
|
|
150
|
+
secretsManager,
|
|
151
|
+
trans
|
|
146
152
|
}) => {
|
|
147
153
|
if (!model) {
|
|
148
|
-
return <div>Settings model not available</div>;
|
|
154
|
+
return <div>{trans.__('Settings model not available')}</div>;
|
|
149
155
|
}
|
|
150
156
|
|
|
151
157
|
const [config, setConfig] = useState(model.config || {});
|
|
@@ -535,7 +541,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
535
541
|
<Box sx={{ mb: 2, display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
536
542
|
<Settings color="primary" sx={{ fontSize: 24 }} />
|
|
537
543
|
<Typography variant="h5" component="h1" sx={{ fontWeight: 600 }}>
|
|
538
|
-
AI Settings
|
|
544
|
+
{trans.__('AI Settings')}
|
|
539
545
|
</Typography>
|
|
540
546
|
</Box>
|
|
541
547
|
{/* Tabs */}
|
|
@@ -544,9 +550,9 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
544
550
|
value={activeTab}
|
|
545
551
|
onChange={(_, newValue) => setActiveTab(newValue)}
|
|
546
552
|
>
|
|
547
|
-
<Tab label=
|
|
548
|
-
<Tab label=
|
|
549
|
-
<Tab label=
|
|
553
|
+
<Tab label={trans.__('Providers')} />
|
|
554
|
+
<Tab label={trans.__('Behavior')} />
|
|
555
|
+
<Tab label={trans.__('MCP Servers')} />
|
|
550
556
|
</Tabs>
|
|
551
557
|
</Box>
|
|
552
558
|
|
|
@@ -558,17 +564,17 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
558
564
|
<Card elevation={2}>
|
|
559
565
|
<CardContent>
|
|
560
566
|
<Typography variant="h6" component="h2" gutterBottom>
|
|
561
|
-
Default Providers
|
|
567
|
+
{trans.__('Default Providers')}
|
|
562
568
|
</Typography>
|
|
563
569
|
|
|
564
570
|
<Box
|
|
565
571
|
sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}
|
|
566
572
|
>
|
|
567
573
|
<FormControl fullWidth>
|
|
568
|
-
<InputLabel>Chat Provider</InputLabel>
|
|
574
|
+
<InputLabel>{trans.__('Chat Provider')}</InputLabel>
|
|
569
575
|
<Select
|
|
570
576
|
value={config.defaultProvider}
|
|
571
|
-
label=
|
|
577
|
+
label={trans.__('Chat Provider')}
|
|
572
578
|
onChange={e => model.setActiveProvider(e.target.value)}
|
|
573
579
|
>
|
|
574
580
|
{config.providers.map(provider => (
|
|
@@ -592,15 +598,19 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
592
598
|
color="primary"
|
|
593
599
|
/>
|
|
594
600
|
}
|
|
595
|
-
label=
|
|
601
|
+
label={trans.__(
|
|
602
|
+
'Use same provider for chat and completions'
|
|
603
|
+
)}
|
|
596
604
|
/>
|
|
597
605
|
|
|
598
606
|
{!config.useSameProviderForChatAndCompleter && (
|
|
599
607
|
<FormControl fullWidth>
|
|
600
|
-
<InputLabel>
|
|
608
|
+
<InputLabel>
|
|
609
|
+
{trans.__('Completion Provider')}
|
|
610
|
+
</InputLabel>
|
|
601
611
|
<Select
|
|
602
612
|
value={config.activeCompleterProvider || ''}
|
|
603
|
-
label=
|
|
613
|
+
label={trans.__('Completion Provider')}
|
|
604
614
|
className="jp-ai-completion-provider-select"
|
|
605
615
|
onChange={e =>
|
|
606
616
|
model.setActiveCompleterProvider(
|
|
@@ -609,7 +619,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
609
619
|
}
|
|
610
620
|
>
|
|
611
621
|
<MenuItem value="">
|
|
612
|
-
<em>No completion</em>
|
|
622
|
+
<em>{trans.__('No completion')}</em>
|
|
613
623
|
</MenuItem>
|
|
614
624
|
{config.providers.map(provider => (
|
|
615
625
|
<MenuItem key={provider.id} value={provider.id}>
|
|
@@ -637,7 +647,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
637
647
|
>
|
|
638
648
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
639
649
|
<Typography variant="h6" component="h2">
|
|
640
|
-
Configured Providers
|
|
650
|
+
{trans.__('Configured Providers')}
|
|
641
651
|
</Typography>
|
|
642
652
|
</Box>
|
|
643
653
|
<Button
|
|
@@ -646,14 +656,15 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
646
656
|
onClick={openAddDialog}
|
|
647
657
|
size="small"
|
|
648
658
|
>
|
|
649
|
-
Add Provider
|
|
659
|
+
{trans.__('Add Provider')}
|
|
650
660
|
</Button>
|
|
651
661
|
</Box>
|
|
652
662
|
|
|
653
663
|
{config.providers.length === 0 ? (
|
|
654
664
|
<Alert severity="info">
|
|
655
|
-
|
|
656
|
-
|
|
665
|
+
{trans.__(
|
|
666
|
+
'No providers configured yet. Click "Add Provider" to get started.'
|
|
667
|
+
)}
|
|
657
668
|
</Alert>
|
|
658
669
|
) : (
|
|
659
670
|
<List>
|
|
@@ -700,7 +711,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
700
711
|
</Typography>
|
|
701
712
|
{isActive && (
|
|
702
713
|
<Chip
|
|
703
|
-
label=
|
|
714
|
+
label={trans.__('Chat')}
|
|
704
715
|
size="small"
|
|
705
716
|
color="primary"
|
|
706
717
|
icon={<CheckCircle />}
|
|
@@ -708,7 +719,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
708
719
|
)}
|
|
709
720
|
{isActiveCompleter && (
|
|
710
721
|
<Chip
|
|
711
|
-
label=
|
|
722
|
+
label={trans.__('Completion')}
|
|
712
723
|
size="small"
|
|
713
724
|
color="secondary"
|
|
714
725
|
icon={<CheckCircle />}
|
|
@@ -728,7 +739,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
728
739
|
{/* Display parameters if set */}
|
|
729
740
|
{params &&
|
|
730
741
|
(params.temperature !== undefined ||
|
|
731
|
-
params.
|
|
742
|
+
params.maxOutputTokens !== undefined ||
|
|
732
743
|
params.maxTurns !== undefined) && (
|
|
733
744
|
<Box
|
|
734
745
|
sx={{
|
|
@@ -740,21 +751,30 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
740
751
|
>
|
|
741
752
|
{params.temperature !== undefined && (
|
|
742
753
|
<Chip
|
|
743
|
-
label={
|
|
754
|
+
label={trans.__(
|
|
755
|
+
'Temp: %1',
|
|
756
|
+
params.temperature
|
|
757
|
+
)}
|
|
744
758
|
size="small"
|
|
745
759
|
variant="outlined"
|
|
746
760
|
/>
|
|
747
761
|
)}
|
|
748
|
-
{params.
|
|
762
|
+
{params.maxOutputTokens !== undefined && (
|
|
749
763
|
<Chip
|
|
750
|
-
label={
|
|
764
|
+
label={trans.__(
|
|
765
|
+
'Tokens: %1',
|
|
766
|
+
params.maxOutputTokens
|
|
767
|
+
)}
|
|
751
768
|
size="small"
|
|
752
769
|
variant="outlined"
|
|
753
770
|
/>
|
|
754
771
|
)}
|
|
755
772
|
{params.maxTurns !== undefined && (
|
|
756
773
|
<Chip
|
|
757
|
-
label={
|
|
774
|
+
label={trans.__(
|
|
775
|
+
'Turns: %1',
|
|
776
|
+
params.maxTurns
|
|
777
|
+
)}
|
|
758
778
|
size="small"
|
|
759
779
|
variant="outlined"
|
|
760
780
|
/>
|
|
@@ -794,10 +814,14 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
794
814
|
}
|
|
795
815
|
label={
|
|
796
816
|
<div>
|
|
797
|
-
<span>
|
|
817
|
+
<span>
|
|
818
|
+
{trans.__('Use the secrets manager to manage API keys')}
|
|
819
|
+
</span>
|
|
798
820
|
{!config.useSecretsManager && (
|
|
799
821
|
<Alert severity="warning" icon={<Error />} sx={{ mb: 2 }}>
|
|
800
|
-
|
|
822
|
+
{trans.__(
|
|
823
|
+
'The secrets are stored in plain text in settings'
|
|
824
|
+
)}
|
|
801
825
|
</Alert>
|
|
802
826
|
)}
|
|
803
827
|
</div>
|
|
@@ -811,7 +835,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
811
835
|
<Card elevation={2}>
|
|
812
836
|
<CardContent>
|
|
813
837
|
<Typography variant="h6" component="h2" gutterBottom>
|
|
814
|
-
Behavior Settings
|
|
838
|
+
{trans.__('Behavior Settings')}
|
|
815
839
|
</Typography>
|
|
816
840
|
|
|
817
841
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
@@ -829,10 +853,13 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
829
853
|
}
|
|
830
854
|
label={
|
|
831
855
|
<Box>
|
|
832
|
-
<Typography variant="body1">
|
|
856
|
+
<Typography variant="body1">
|
|
857
|
+
{trans.__('Enable Tools')}
|
|
858
|
+
</Typography>
|
|
833
859
|
<Typography variant="caption" color="text.secondary">
|
|
834
|
-
|
|
835
|
-
|
|
860
|
+
{trans.__(
|
|
861
|
+
'Allow the AI to use tools like notebook operations, code execution, and file management'
|
|
862
|
+
)}
|
|
836
863
|
</Typography>
|
|
837
864
|
</Box>
|
|
838
865
|
}
|
|
@@ -853,11 +880,12 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
853
880
|
label={
|
|
854
881
|
<Box>
|
|
855
882
|
<Typography variant="body1">
|
|
856
|
-
Send with Shift+Enter
|
|
883
|
+
{trans.__('Send with Shift+Enter')}
|
|
857
884
|
</Typography>
|
|
858
885
|
<Typography variant="caption" color="text.secondary">
|
|
859
|
-
|
|
860
|
-
|
|
886
|
+
{trans.__(
|
|
887
|
+
'Use Shift+Enter to send messages (Enter creates new line)'
|
|
888
|
+
)}
|
|
861
889
|
</Typography>
|
|
862
890
|
</Box>
|
|
863
891
|
}
|
|
@@ -877,9 +905,13 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
877
905
|
}
|
|
878
906
|
label={
|
|
879
907
|
<Box>
|
|
880
|
-
<Typography variant="body1">
|
|
908
|
+
<Typography variant="body1">
|
|
909
|
+
{trans.__('Show Token Usage')}
|
|
910
|
+
</Typography>
|
|
881
911
|
<Typography variant="caption" color="text.secondary">
|
|
882
|
-
|
|
912
|
+
{trans.__(
|
|
913
|
+
'Display token usage information in the chat toolbar'
|
|
914
|
+
)}
|
|
883
915
|
</Typography>
|
|
884
916
|
</Box>
|
|
885
917
|
}
|
|
@@ -899,9 +931,13 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
899
931
|
}
|
|
900
932
|
label={
|
|
901
933
|
<Box>
|
|
902
|
-
<Typography variant="body1">
|
|
934
|
+
<Typography variant="body1">
|
|
935
|
+
{trans.__('Show Cell Diff')}
|
|
936
|
+
</Typography>
|
|
903
937
|
<Typography variant="caption" color="text.secondary">
|
|
904
|
-
|
|
938
|
+
{trans.__(
|
|
939
|
+
'Show diff view when AI modifies cell content'
|
|
940
|
+
)}
|
|
905
941
|
</Typography>
|
|
906
942
|
</Box>
|
|
907
943
|
}
|
|
@@ -909,18 +945,22 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
909
945
|
|
|
910
946
|
{config.showCellDiff && (
|
|
911
947
|
<FormControl sx={{ ml: 4 }}>
|
|
912
|
-
<InputLabel>Diff Display Mode</InputLabel>
|
|
948
|
+
<InputLabel>{trans.__('Diff Display Mode')}</InputLabel>
|
|
913
949
|
<Select
|
|
914
950
|
value={config.diffDisplayMode}
|
|
915
|
-
label=
|
|
951
|
+
label={trans.__('Diff Display Mode')}
|
|
916
952
|
onChange={e =>
|
|
917
953
|
handleConfigUpdate({
|
|
918
954
|
diffDisplayMode: e.target.value as 'split' | 'unified'
|
|
919
955
|
})
|
|
920
956
|
}
|
|
921
957
|
>
|
|
922
|
-
<MenuItem value="split">
|
|
923
|
-
|
|
958
|
+
<MenuItem value="split">
|
|
959
|
+
{trans.__('Split View')}
|
|
960
|
+
</MenuItem>
|
|
961
|
+
<MenuItem value="unified">
|
|
962
|
+
{trans.__('Unified View')}
|
|
963
|
+
</MenuItem>
|
|
924
964
|
</Select>
|
|
925
965
|
</FormControl>
|
|
926
966
|
)}
|
|
@@ -939,9 +979,13 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
939
979
|
}
|
|
940
980
|
label={
|
|
941
981
|
<Box>
|
|
942
|
-
<Typography variant="body1">
|
|
982
|
+
<Typography variant="body1">
|
|
983
|
+
{trans.__('Show File Diff')}
|
|
984
|
+
</Typography>
|
|
943
985
|
<Typography variant="caption" color="text.secondary">
|
|
944
|
-
|
|
986
|
+
{trans.__(
|
|
987
|
+
'Show diff view when AI modifies file content'
|
|
988
|
+
)}
|
|
945
989
|
</Typography>
|
|
946
990
|
</Box>
|
|
947
991
|
}
|
|
@@ -953,29 +997,37 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
953
997
|
fullWidth
|
|
954
998
|
multiline
|
|
955
999
|
rows={3}
|
|
956
|
-
label=
|
|
1000
|
+
label={trans.__('System Prompt')}
|
|
957
1001
|
value={systemPromptValue}
|
|
958
1002
|
onChange={e => handleSystemPromptChange(e.target.value)}
|
|
959
|
-
placeholder=
|
|
960
|
-
|
|
1003
|
+
placeholder={trans.__(
|
|
1004
|
+
"Define the AI's behavior and personality..."
|
|
1005
|
+
)}
|
|
1006
|
+
helperText={trans.__(
|
|
1007
|
+
'Instructions that define how the AI should behave and respond'
|
|
1008
|
+
)}
|
|
961
1009
|
/>
|
|
962
1010
|
|
|
963
1011
|
<TextField
|
|
964
1012
|
fullWidth
|
|
965
1013
|
multiline
|
|
966
1014
|
rows={3}
|
|
967
|
-
label=
|
|
1015
|
+
label={trans.__('Completion System Prompt')}
|
|
968
1016
|
value={completionPromptValue}
|
|
969
1017
|
onChange={e => handleCompletionPromptChange(e.target.value)}
|
|
970
|
-
placeholder=
|
|
971
|
-
|
|
1018
|
+
placeholder={trans.__(
|
|
1019
|
+
'Define how the AI should generate code completions...'
|
|
1020
|
+
)}
|
|
1021
|
+
helperText={trans.__(
|
|
1022
|
+
'Instructions that define how the AI should generate code completions'
|
|
1023
|
+
)}
|
|
972
1024
|
/>
|
|
973
1025
|
|
|
974
1026
|
<Divider sx={{ my: 2 }} />
|
|
975
1027
|
|
|
976
1028
|
<Box>
|
|
977
1029
|
<Typography variant="body1" gutterBottom>
|
|
978
|
-
Commands Requiring Approval
|
|
1030
|
+
{trans.__('Commands Requiring Approval')}
|
|
979
1031
|
</Typography>
|
|
980
1032
|
<Typography
|
|
981
1033
|
variant="caption"
|
|
@@ -983,8 +1035,9 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
983
1035
|
gutterBottom
|
|
984
1036
|
sx={{ display: 'block' }}
|
|
985
1037
|
>
|
|
986
|
-
|
|
987
|
-
|
|
1038
|
+
{trans.__(
|
|
1039
|
+
'Commands that require user approval before AI can execute them'
|
|
1040
|
+
)}
|
|
988
1041
|
</Typography>
|
|
989
1042
|
|
|
990
1043
|
<List sx={{ mb: 2, maxHeight: 200, overflow: 'auto' }}>
|
|
@@ -1013,8 +1066,8 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1013
1066
|
|
|
1014
1067
|
<TextField
|
|
1015
1068
|
fullWidth
|
|
1016
|
-
label=
|
|
1017
|
-
placeholder=
|
|
1069
|
+
label={trans.__('Add New Command')}
|
|
1070
|
+
placeholder={trans.__('e.g., notebook:run-cell')}
|
|
1018
1071
|
onKeyDown={e => {
|
|
1019
1072
|
if (e.key === 'Enter') {
|
|
1020
1073
|
const value = (
|
|
@@ -1035,7 +1088,9 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1035
1088
|
}
|
|
1036
1089
|
}
|
|
1037
1090
|
}}
|
|
1038
|
-
helperText=
|
|
1091
|
+
helperText={trans.__(
|
|
1092
|
+
'Press Enter to add a command. Common commands: notebook:run-cell, console:execute, fileeditor:run-code'
|
|
1093
|
+
)}
|
|
1039
1094
|
/>
|
|
1040
1095
|
</Box>
|
|
1041
1096
|
</Box>
|
|
@@ -1057,7 +1112,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1057
1112
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
1058
1113
|
<Cable color="primary" />
|
|
1059
1114
|
<Typography variant="h6" component="h2">
|
|
1060
|
-
Remote MCP Servers
|
|
1115
|
+
{trans.__('Remote MCP Servers')}
|
|
1061
1116
|
</Typography>
|
|
1062
1117
|
</Box>
|
|
1063
1118
|
<Button
|
|
@@ -1066,19 +1121,21 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1066
1121
|
onClick={openAddMCPDialog}
|
|
1067
1122
|
size="small"
|
|
1068
1123
|
>
|
|
1069
|
-
Add Server
|
|
1124
|
+
{trans.__('Add Server')}
|
|
1070
1125
|
</Button>
|
|
1071
1126
|
</Box>
|
|
1072
1127
|
|
|
1073
1128
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
|
|
1074
|
-
|
|
1075
|
-
|
|
1129
|
+
{trans.__(
|
|
1130
|
+
"Configure remote Model Context Protocol (MCP) servers to extend the AI's capabilities with external tools and data sources."
|
|
1131
|
+
)}
|
|
1076
1132
|
</Typography>
|
|
1077
1133
|
|
|
1078
1134
|
{config.mcpServers.length === 0 ? (
|
|
1079
1135
|
<Alert severity="info">
|
|
1080
|
-
|
|
1081
|
-
|
|
1136
|
+
{trans.__(
|
|
1137
|
+
'No MCP servers configured yet. Click "Add Server" to connect to remote MCP services.'
|
|
1138
|
+
)}
|
|
1082
1139
|
</Alert>
|
|
1083
1140
|
) : (
|
|
1084
1141
|
<List>
|
|
@@ -1134,12 +1191,14 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1134
1191
|
variant="caption"
|
|
1135
1192
|
color="text.secondary"
|
|
1136
1193
|
>
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1194
|
+
{trans.__(
|
|
1195
|
+
'Status: %1',
|
|
1196
|
+
agentManagerFactory.isMCPServerConnected(
|
|
1197
|
+
server.name
|
|
1198
|
+
)
|
|
1199
|
+
? trans.__('Connected')
|
|
1200
|
+
: trans.__('Connection failed')
|
|
1201
|
+
)}
|
|
1143
1202
|
</Typography>
|
|
1144
1203
|
)}
|
|
1145
1204
|
</Box>
|
|
@@ -1170,6 +1229,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1170
1229
|
mode={editingProvider ? 'edit' : 'add'}
|
|
1171
1230
|
providerRegistry={providerRegistry}
|
|
1172
1231
|
handleSecretField={handleSecretField}
|
|
1232
|
+
trans={trans}
|
|
1173
1233
|
/>
|
|
1174
1234
|
|
|
1175
1235
|
{/* Provider Menu */}
|
|
@@ -1189,14 +1249,14 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1189
1249
|
}}
|
|
1190
1250
|
>
|
|
1191
1251
|
<Edit sx={{ mr: 1 }} />
|
|
1192
|
-
Edit
|
|
1252
|
+
{trans.__('Edit')}
|
|
1193
1253
|
</MenuItem>
|
|
1194
1254
|
<MenuItem
|
|
1195
1255
|
onClick={() => handleDeleteProvider(menuProviderId)}
|
|
1196
1256
|
sx={{ color: 'error.main' }}
|
|
1197
1257
|
>
|
|
1198
1258
|
<Delete sx={{ mr: 1 }} />
|
|
1199
|
-
Delete
|
|
1259
|
+
{trans.__('Delete')}
|
|
1200
1260
|
</MenuItem>
|
|
1201
1261
|
</Menu>
|
|
1202
1262
|
|
|
@@ -1207,6 +1267,7 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1207
1267
|
onSave={editingMCPServer ? handleEditMCPServer : handleAddMCPServer}
|
|
1208
1268
|
initialConfig={editingMCPServer}
|
|
1209
1269
|
mode={editingMCPServer ? 'edit' : 'add'}
|
|
1270
|
+
trans={trans}
|
|
1210
1271
|
/>
|
|
1211
1272
|
|
|
1212
1273
|
{/* MCP Server Menu */}
|
|
@@ -1226,14 +1287,14 @@ const AISettingsComponent: React.FC<IAISettingsComponentProps> = ({
|
|
|
1226
1287
|
}}
|
|
1227
1288
|
>
|
|
1228
1289
|
<Edit sx={{ mr: 1 }} />
|
|
1229
|
-
Edit
|
|
1290
|
+
{trans.__('Edit')}
|
|
1230
1291
|
</MenuItem>
|
|
1231
1292
|
<MenuItem
|
|
1232
1293
|
onClick={() => handleDeleteMCPServer(mcpMenuServerId)}
|
|
1233
1294
|
sx={{ color: 'error.main' }}
|
|
1234
1295
|
>
|
|
1235
1296
|
<Delete sx={{ mr: 1 }} />
|
|
1236
|
-
Delete
|
|
1297
|
+
{trans.__('Delete')}
|
|
1237
1298
|
</MenuItem>
|
|
1238
1299
|
</Menu>
|
|
1239
1300
|
</Box>
|
|
@@ -1250,6 +1311,7 @@ interface IMCPServerDialogProps {
|
|
|
1250
1311
|
onSave: (config: Omit<IMCPServerConfig, 'id'>) => void;
|
|
1251
1312
|
initialConfig?: IMCPServerConfig;
|
|
1252
1313
|
mode: 'add' | 'edit';
|
|
1314
|
+
trans: TranslationBundle;
|
|
1253
1315
|
}
|
|
1254
1316
|
|
|
1255
1317
|
/**
|
|
@@ -1262,7 +1324,8 @@ const MCPServerDialog: React.FC<IMCPServerDialogProps> = ({
|
|
|
1262
1324
|
onClose,
|
|
1263
1325
|
onSave,
|
|
1264
1326
|
initialConfig,
|
|
1265
|
-
mode
|
|
1327
|
+
mode,
|
|
1328
|
+
trans
|
|
1266
1329
|
}) => {
|
|
1267
1330
|
const [name, setName] = useState(initialConfig?.name || '');
|
|
1268
1331
|
const [url, setUrl] = useState(initialConfig?.url || '');
|
|
@@ -1314,26 +1377,28 @@ const MCPServerDialog: React.FC<IMCPServerDialogProps> = ({
|
|
|
1314
1377
|
return (
|
|
1315
1378
|
<Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
|
|
1316
1379
|
<DialogTitle>
|
|
1317
|
-
{mode === 'add'
|
|
1380
|
+
{mode === 'add'
|
|
1381
|
+
? trans.__('Add MCP Server')
|
|
1382
|
+
: trans.__('Edit MCP Server')}
|
|
1318
1383
|
</DialogTitle>
|
|
1319
1384
|
<DialogContent>
|
|
1320
1385
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, pt: 1 }}>
|
|
1321
1386
|
<TextField
|
|
1322
1387
|
autoFocus
|
|
1323
1388
|
fullWidth
|
|
1324
|
-
label=
|
|
1389
|
+
label={trans.__('Server Name')}
|
|
1325
1390
|
value={name}
|
|
1326
1391
|
onChange={e => setName(e.target.value)}
|
|
1327
|
-
placeholder=
|
|
1328
|
-
helperText=
|
|
1392
|
+
placeholder={trans.__('My MCP Server')}
|
|
1393
|
+
helperText={trans.__('A friendly name to identify this MCP server')}
|
|
1329
1394
|
/>
|
|
1330
1395
|
<TextField
|
|
1331
1396
|
fullWidth
|
|
1332
|
-
label=
|
|
1397
|
+
label={trans.__('Server URL')}
|
|
1333
1398
|
value={url}
|
|
1334
1399
|
onChange={e => setUrl(e.target.value)}
|
|
1335
|
-
placeholder=
|
|
1336
|
-
helperText=
|
|
1400
|
+
placeholder={trans.__('https://example.com/mcp')}
|
|
1401
|
+
helperText={trans.__('The HTTP/HTTPS URL of the MCP server')}
|
|
1337
1402
|
error={Boolean(url.trim() && !_isValidUrl(url.trim()))}
|
|
1338
1403
|
/>
|
|
1339
1404
|
<FormControlLabel
|
|
@@ -1344,14 +1409,14 @@ const MCPServerDialog: React.FC<IMCPServerDialogProps> = ({
|
|
|
1344
1409
|
color="primary"
|
|
1345
1410
|
/>
|
|
1346
1411
|
}
|
|
1347
|
-
label=
|
|
1412
|
+
label={trans.__('Enable this server')}
|
|
1348
1413
|
/>
|
|
1349
1414
|
</Box>
|
|
1350
1415
|
</DialogContent>
|
|
1351
1416
|
<DialogActions>
|
|
1352
|
-
<Button onClick={onClose}>Cancel</Button>
|
|
1417
|
+
<Button onClick={onClose}>{trans.__('Cancel')}</Button>
|
|
1353
1418
|
<Button onClick={handleSave} variant="contained" disabled={!canSave}>
|
|
1354
|
-
{mode === 'add' ? 'Add' : 'Save'}
|
|
1419
|
+
{mode === 'add' ? trans.__('Add') : trans.__('Save')}
|
|
1355
1420
|
</Button>
|
|
1356
1421
|
</DialogActions>
|
|
1357
1422
|
</Dialog>
|
|
@@ -1378,6 +1443,10 @@ export namespace AISettingsWidget {
|
|
|
1378
1443
|
* The token used to request the secrets manager.
|
|
1379
1444
|
*/
|
|
1380
1445
|
token: symbol;
|
|
1446
|
+
/**
|
|
1447
|
+
* The application language translation bundle.
|
|
1448
|
+
*/
|
|
1449
|
+
trans: TranslationBundle;
|
|
1381
1450
|
}
|
|
1382
1451
|
}
|
|
1383
1452
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ChatWidget } from '@jupyter/chat';
|
|
2
2
|
import { CommandToolbarButton, MainAreaWidget } from '@jupyterlab/apputils';
|
|
3
3
|
import { launchIcon } from '@jupyterlab/ui-components';
|
|
4
|
+
import type { TranslationBundle } from '@jupyterlab/translation';
|
|
4
5
|
import { CommandRegistry } from '@lumino/commands';
|
|
5
6
|
|
|
6
7
|
import { ApprovalButtons } from '../approval-buttons';
|
|
@@ -13,6 +14,7 @@ export namespace MainAreaChat {
|
|
|
13
14
|
export interface IOptions extends MainAreaWidget.IOptions<ChatWidget> {
|
|
14
15
|
commands: CommandRegistry;
|
|
15
16
|
settingsModel: AISettingsModel;
|
|
17
|
+
trans: TranslationBundle;
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -24,6 +26,8 @@ export class MainAreaChat extends MainAreaWidget<ChatWidget> {
|
|
|
24
26
|
super(options);
|
|
25
27
|
this.title.label = this.content.model.name;
|
|
26
28
|
|
|
29
|
+
const { trans } = options;
|
|
30
|
+
|
|
27
31
|
// add the move to side button.
|
|
28
32
|
this.toolbar.addItem(
|
|
29
33
|
'moveToSide',
|
|
@@ -42,13 +46,15 @@ export class MainAreaChat extends MainAreaWidget<ChatWidget> {
|
|
|
42
46
|
const tokenUsageWidget = new TokenUsageWidget({
|
|
43
47
|
tokenUsageChanged: this.model.tokenUsageChanged,
|
|
44
48
|
settingsModel: options.settingsModel,
|
|
45
|
-
initialTokenUsage: this.model.agentManager.tokenUsage
|
|
49
|
+
initialTokenUsage: this.model.agentManager.tokenUsage,
|
|
50
|
+
translator: trans
|
|
46
51
|
});
|
|
47
52
|
this.toolbar.addItem('token-usage', tokenUsageWidget);
|
|
48
53
|
|
|
49
54
|
// Add the approval button, tied to the chat widget.
|
|
50
55
|
this._approvalButtons = new ApprovalButtons({
|
|
51
|
-
chatPanel: this.content
|
|
56
|
+
chatPanel: this.content,
|
|
57
|
+
agentManager: this.model.agentManager
|
|
52
58
|
});
|
|
53
59
|
}
|
|
54
60
|
|