@notebook-intelligence/notebook-intelligence 2.4.2 → 2.6.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/src/index.ts CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  import { IDocumentManager } from '@jupyterlab/docmanager';
10
10
  import { DocumentWidget, IDocumentWidget } from '@jupyterlab/docregistry';
11
11
 
12
- import { Dialog, ICommandPalette } from '@jupyterlab/apputils';
12
+ import { Dialog, ICommandPalette, MainAreaWidget } from '@jupyterlab/apputils';
13
13
  import { IMainMenu } from '@jupyterlab/mainmenu';
14
14
 
15
15
  import { IEditorLanguageRegistry } from '@jupyterlab/codemirror';
@@ -44,7 +44,7 @@ import { IStatusBar } from '@jupyterlab/statusbar';
44
44
 
45
45
  import {
46
46
  ChatSidebar,
47
- ConfigurationDialogBody,
47
+ FormInputDialogBody,
48
48
  GitHubCopilotLoginDialogBody,
49
49
  GitHubCopilotStatusBarItem,
50
50
  InlinePromptWidget,
@@ -65,6 +65,7 @@ import {
65
65
  } from './tokens';
66
66
  import sparklesSvgstr from '../style/icons/sparkles.svg';
67
67
  import copilotSvgstr from '../style/icons/copilot.svg';
68
+ import sparklesWarningSvgstr from '../style/icons/sparkles-warning.svg';
68
69
 
69
70
  import {
70
71
  applyCodeToSelectionInEditor,
@@ -81,6 +82,7 @@ import {
81
82
  import { UUID } from '@lumino/coreutils';
82
83
 
83
84
  import * as path from 'path';
85
+ import { SettingsPanel } from './components/settings-panel';
84
86
 
85
87
  namespace CommandIDs {
86
88
  export const chatuserInput = 'notebook-intelligence:chat-user-input';
@@ -126,6 +128,8 @@ namespace CommandIDs {
126
128
  'notebook-intelligence:set-current-file-content';
127
129
  export const openMCPConfigEditor =
128
130
  'notebook-intelligence:open-mcp-config-editor';
131
+ export const showFormInputDialog =
132
+ 'notebook-intelligence:show-form-input-dialog';
129
133
  }
130
134
 
131
135
  const DOCUMENT_WATCH_INTERVAL = 1000;
@@ -140,6 +144,10 @@ const sparkleIcon = new LabIcon({
140
144
  svgstr: sparklesSvgstr
141
145
  });
142
146
 
147
+ const sparkleWarningIcon = new LabIcon({
148
+ name: 'notebook-intelligence:sparkles-warning-icon',
149
+ svgstr: sparklesWarningSvgstr
150
+ });
143
151
  const emptyNotebookContent: any = {
144
152
  cells: [],
145
153
  metadata: {},
@@ -711,7 +719,7 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
711
719
  panel.id = 'notebook-intelligence-tab';
712
720
  panel.title.caption = 'Notebook Intelligence';
713
721
  const sidebarIcon = new LabIcon({
714
- name: 'ui-components:palette',
722
+ name: 'notebook-intelligence:sidebar-icon',
715
723
  svgstr: sparklesSvgstr
716
724
  });
717
725
  panel.title.icon = sidebarIcon;
@@ -739,6 +747,26 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
739
747
  app.shell.add(panel, 'left', { rank: 1000 });
740
748
  app.shell.activateById(panel.id);
741
749
 
750
+ const updateSidebarIcon = () => {
751
+ if (NBIAPI.getChatEnabled()) {
752
+ panel.title.icon = sidebarIcon;
753
+ } else {
754
+ panel.title.icon = sparkleWarningIcon;
755
+ }
756
+ };
757
+
758
+ NBIAPI.githubLoginStatusChanged.connect((_, args) => {
759
+ updateSidebarIcon();
760
+ });
761
+
762
+ NBIAPI.configChanged.connect((_, args) => {
763
+ updateSidebarIcon();
764
+ });
765
+
766
+ setTimeout(() => {
767
+ updateSidebarIcon();
768
+ }, 2000);
769
+
742
770
  app.commands.addCommand(CommandIDs.chatuserInput, {
743
771
  execute: args => {
744
772
  NBIAPI.sendChatUserInput(args.id as string, args.data);
@@ -820,6 +848,39 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
820
848
  }
821
849
  });
822
850
 
851
+ app.commands.addCommand(CommandIDs.showFormInputDialog, {
852
+ execute: async args => {
853
+ const title = args.title as string;
854
+ const fields = args.fields;
855
+
856
+ return new Promise<any>((resolve, reject) => {
857
+ let dialog: Dialog<unknown> | null = null;
858
+ const dialogBody = new FormInputDialogBody({
859
+ fields: fields,
860
+ onDone: (formData: any) => {
861
+ dialog.dispose();
862
+ resolve(formData);
863
+ }
864
+ });
865
+ dialog = new Dialog({
866
+ title: title,
867
+ hasClose: true,
868
+ body: dialogBody,
869
+ buttons: []
870
+ });
871
+
872
+ dialog
873
+ .launch()
874
+ .then((result: any) => {
875
+ reject();
876
+ })
877
+ .catch(() => {
878
+ reject(new Error('Failed to show form input dialog'));
879
+ });
880
+ });
881
+ }
882
+ });
883
+
823
884
  app.commands.addCommand(CommandIDs.createNewNotebookFromPython, {
824
885
  execute: async args => {
825
886
  let pythonKernelSpec = null;
@@ -1229,31 +1290,36 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
1229
1290
  }
1230
1291
  });
1231
1292
 
1293
+ const createNewSettingsWidget = () => {
1294
+ const settingsPanel = new SettingsPanel({
1295
+ onSave: () => {
1296
+ NBIAPI.fetchCapabilities();
1297
+ },
1298
+ onEditMCPConfigClicked: () => {
1299
+ app.commands.execute('notebook-intelligence:open-mcp-config-editor');
1300
+ }
1301
+ });
1302
+
1303
+ const widget = new MainAreaWidget({ content: settingsPanel });
1304
+ widget.id = 'nbi-settings';
1305
+ widget.title.label = 'NBI Settings';
1306
+ widget.title.closable = true;
1307
+
1308
+ return widget;
1309
+ };
1310
+
1311
+ let settingsWidget = createNewSettingsWidget();
1312
+
1232
1313
  app.commands.addCommand(CommandIDs.openConfigurationDialog, {
1233
1314
  label: 'Notebook Intelligence Settings',
1234
1315
  execute: args => {
1235
- let dialog: Dialog<unknown> | null = null;
1236
- const dialogBody = new ConfigurationDialogBody({
1237
- onSave: () => {
1238
- dialog?.dispose();
1239
- NBIAPI.fetchCapabilities();
1240
- },
1241
- onEditMCPConfigClicked: () => {
1242
- dialog?.dispose();
1243
- app.commands.execute(
1244
- 'notebook-intelligence:open-mcp-config-editor'
1245
- );
1246
- }
1247
- });
1248
- dialog = new Dialog({
1249
- title: 'Notebook Intelligence Settings',
1250
- hasClose: true,
1251
- body: dialogBody,
1252
- buttons: []
1253
- });
1254
- dialog.node.classList.add('config-dialog-container');
1255
-
1256
- dialog.launch();
1316
+ if (settingsWidget.isDisposed) {
1317
+ settingsWidget = createNewSettingsWidget();
1318
+ }
1319
+ if (!settingsWidget.isAttached) {
1320
+ app.shell.add(settingsWidget, 'main');
1321
+ }
1322
+ app.shell.activateById(settingsWidget.id);
1257
1323
  }
1258
1324
  });
1259
1325
 
@@ -1496,6 +1562,8 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
1496
1562
  existingCode,
1497
1563
  prefix: prefix,
1498
1564
  suffix: suffix,
1565
+ language: ActiveDocumentWatcher.activeDocumentInfo.language,
1566
+ filename: ActiveDocumentWatcher.activeDocumentInfo.filePath,
1499
1567
  onRequestSubmitted: (prompt: string) => {
1500
1568
  userPrompt = prompt;
1501
1569
  generatedContent = '';
package/src/tokens.ts CHANGED
@@ -32,7 +32,8 @@ export enum BackendMessageType {
32
32
  StreamMessage = 'stream-message',
33
33
  StreamEnd = 'stream-end',
34
34
  RunUICommand = 'run-ui-command',
35
- GitHubCopilotLoginStatusChange = 'github-copilot-login-status-change'
35
+ GitHubCopilotLoginStatusChange = 'github-copilot-login-status-change',
36
+ MCPServerStatusChange = 'mcp-server-status-change'
36
37
  }
37
38
 
38
39
  export enum ResponseStreamDataType {
@@ -52,6 +53,18 @@ export enum ContextType {
52
53
  CurrentFile = 'current-file'
53
54
  }
54
55
 
56
+ export enum MCPServerStatus {
57
+ NotConnected = 'not-connected',
58
+ Connecting = 'connecting',
59
+ Disconnecting = 'disconnecting',
60
+ FailedToConnect = 'failed-to-connect',
61
+ Connected = 'connected',
62
+ UpdatingToolList = 'updating-tool-list',
63
+ UpdatedToolList = 'updated-tool-list',
64
+ UpdatingPromptList = 'updating-prompt-list',
65
+ UpdatedPromptList = 'updated-prompt-list'
66
+ }
67
+
55
68
  export interface IContextItem {
56
69
  type: ContextType;
57
70
  content: string;
package/style/base.css CHANGED
@@ -355,7 +355,7 @@ pre:has(.code-block-header) {
355
355
  border: 1px solid var(--jp-border-color1);
356
356
  flex-direction: column;
357
357
  position: absolute;
358
- bottom: 98px;
358
+ bottom: 80px;
359
359
  left: 4px;
360
360
  gap: 2px;
361
361
  /* stylelint-disable */
@@ -602,7 +602,6 @@ body[data-jp-theme-light='false'] .inline-popover {
602
602
  display: flex;
603
603
  flex-direction: column;
604
604
  overflow-y: auto;
605
- padding: 10px 0;
606
605
  gap: 15px;
607
606
  }
608
607
 
@@ -829,3 +828,105 @@ svg.access-token-warning {
829
828
  text-overflow: ellipsis;
830
829
  white-space: nowrap;
831
830
  }
831
+
832
+ .nbi-settings-panel {
833
+ display: flex;
834
+ height: 100%;
835
+ }
836
+
837
+ .nbi-settings-panel-tabs {
838
+ display: flex;
839
+ flex-direction: column;
840
+ gap: 10px;
841
+ padding: 10px;
842
+ width: 150px;
843
+ background-color: var(--jp-layout-color2);
844
+ }
845
+
846
+ .nbi-settings-panel-tab {
847
+ cursor: pointer;
848
+ padding: 10px;
849
+ border-radius: 4px;
850
+ }
851
+
852
+ .nbi-settings-panel-tab:hover {
853
+ background-color: var(--jp-layout-color1);
854
+ }
855
+
856
+ .nbi-settings-panel-tab.active {
857
+ background-color: var(--jp-layout-color1);
858
+ font-weight: bold;
859
+ }
860
+
861
+ .nbi-settings-panel-tab-content {
862
+ flex-grow: 1;
863
+ padding: 20px;
864
+ }
865
+
866
+ .pill-item {
867
+ cursor: pointer;
868
+ background-color: var(--jp-layout-color1);
869
+ display: inline-block;
870
+ padding: 2px 6px;
871
+ margin: 2px 4px;
872
+ border-radius: 4px;
873
+ }
874
+
875
+ .pill-item:hover {
876
+ cursor: pointer;
877
+ background-color: var(--jp-layout-color2);
878
+ }
879
+
880
+ .pill-item.checked {
881
+ background-color: var(--jp-layout-color3);
882
+ }
883
+
884
+ .server-status-indicator {
885
+ width: 10px;
886
+ height: 10px;
887
+ margin: 2px;
888
+ border-radius: 50%;
889
+ background-color: var(--jp-brand-color0);
890
+ }
891
+
892
+ .server-status-indicator.connected,
893
+ .server-status-indicator.updated-tool-list,
894
+ .server-status-indicator.updated-prompt-list {
895
+ background-color: var(--jp-success-color1);
896
+ }
897
+
898
+ .server-status-indicator.connecting,
899
+ .server-status-indicator.disconnecting,
900
+ .server-status-indicator.updating-tool-list,
901
+ .server-status-indicator.updating-prompt-list {
902
+ background-color: var(--jp-warn-color1);
903
+ }
904
+
905
+ .server-status-indicator.not-connected,
906
+ .server-status-indicator.failed-to-connect {
907
+ background-color: var(--jp-error-color1);
908
+ }
909
+
910
+ .form-input-dialog-body {
911
+ width: 500px;
912
+ }
913
+
914
+ .form-input-dialog-body-content-fields {
915
+ display: flex;
916
+ flex-direction: column;
917
+ gap: 10px;
918
+ }
919
+
920
+ .form-input-dialog-body-content-field {
921
+ display: flex;
922
+ flex-direction: row;
923
+ align-items: center;
924
+ }
925
+
926
+ .form-input-dialog-body-content-field-label {
927
+ width: 50%;
928
+ }
929
+
930
+ .form-input-dialog-body-content-field-input {
931
+ width: 50%;
932
+ }
@@ -0,0 +1,5 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="var(--jp-inverse-layout-color3)"><path d="M 5.398 10.807 C 5.574 10.931 5.785 10.998 6 10.997 C 6.216 10.998 6.427 10.93 6.602 10.804 C 6.78 10.674 6.915 10.494 6.989 10.286 L 7.436 8.913 C 7.551 8.569 7.744 8.256 8 7.999 C 8.257 7.743 8.569 7.549 8.913 7.434 L 10.304 6.983 C 10.456 6.929 10.594 6.84 10.706 6.724 C 10.817 6.608 10.901 6.467 10.949 6.313 C 10.998 6.159 11.01 5.996 10.985 5.837 C 10.96 5.677 10.898 5.526 10.804 5.394 C 10.67 5.208 10.479 5.071 10.26 5.003 L 8.885 4.556 C 8.541 4.442 8.228 4.249 7.971 3.993 C 7.714 3.736 7.52 3.424 7.405 3.079 L 6.953 1.691 C 6.881 1.489 6.748 1.314 6.571 1.191 C 6.439 1.098 6.286 1.036 6.125 1.012 C 5.965 0.987 5.801 1.001 5.646 1.051 C 5.492 1.101 5.351 1.187 5.236 1.301 C 5.12 1.415 5.033 1.555 4.98 1.708 L 4.523 3.108 C 4.409 3.443 4.22 3.748 3.97 3.999 C 3.721 4.25 3.418 4.441 3.083 4.557 L 1.692 5.005 C 1.541 5.06 1.404 5.149 1.292 5.265 C 1.18 5.381 1.097 5.521 1.048 5.675 C 1 5.829 0.988 5.992 1.013 6.151 C 1.038 6.31 1.099 6.462 1.192 6.593 C 1.32 6.773 1.501 6.908 1.709 6.979 L 3.083 7.424 C 3.524 7.571 3.91 7.845 4.193 8.212 C 4.356 8.423 4.481 8.66 4.564 8.912 L 5.016 10.303 C 5.088 10.507 5.222 10.683 5.398 10.807 Z M 11.535 14.849 C 11.671 14.946 11.834 14.997 12 14.997 C 12.165 14.997 12.326 14.946 12.461 14.851 C 12.601 14.753 12.706 14.613 12.761 14.451 L 13.009 13.689 C 13.063 13.531 13.152 13.387 13.269 13.268 C 13.387 13.15 13.531 13.061 13.689 13.009 L 14.461 12.757 C 14.619 12.703 14.756 12.6 14.852 12.464 C 14.926 12.361 14.974 12.242 14.992 12.117 C 15.011 11.992 14.999 11.865 14.959 11.745 C 14.918 11.625 14.85 11.516 14.76 11.428 C 14.669 11.34 14.559 11.274 14.438 11.236 L 13.674 10.987 C 13.516 10.935 13.372 10.846 13.254 10.729 C 13.136 10.611 13.047 10.467 12.994 10.309 L 12.742 9.536 C 12.689 9.379 12.586 9.242 12.449 9.146 C 12.347 9.073 12.23 9.025 12.106 9.006 C 11.982 8.987 11.855 8.998 11.736 9.037 C 11.616 9.076 11.508 9.142 11.419 9.231 C 11.33 9.319 11.264 9.427 11.224 9.546 L 10.977 10.308 C 10.925 10.466 10.838 10.61 10.721 10.728 C 10.607 10.845 10.467 10.934 10.312 10.987 L 9.539 11.239 C 9.38 11.293 9.242 11.396 9.145 11.533 C 9.047 11.669 8.995 11.833 8.996 12.001 C 8.997 12.169 9.051 12.333 9.15 12.468 C 9.249 12.604 9.388 12.705 9.547 12.757 L 10.31 13.004 C 10.469 13.058 10.614 13.147 10.732 13.265 C 10.851 13.384 10.939 13.528 10.99 13.687 L 11.243 14.461 C 11.298 14.618 11.4 14.753 11.535 14.849 Z"/>
2
+ <g class="layer">
3
+ <circle cx="12" cy="4" fill="#FF0000" r="4" stroke="#FFFFFF" stroke-width="0"/>
4
+ </g>
5
+ </svg>