@notebook-intelligence/notebook-intelligence 2.2.8 → 2.3.1

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/api.d.ts CHANGED
@@ -11,6 +11,8 @@ export interface IDeviceVerificationInfo {
11
11
  userCode: string;
12
12
  }
13
13
  export declare class NBIConfig {
14
+ get userHomeDir(): string;
15
+ get configFilePath(): string;
14
16
  get llmProviders(): [any];
15
17
  get chatModels(): [any];
16
18
  get inlineCompletionModels(): [any];
@@ -40,6 +42,7 @@ export declare class NBIAPI {
40
42
  static fetchCapabilities(): Promise<void>;
41
43
  static setConfig(config: any): Promise<void>;
42
44
  static updateOllamaModelList(): Promise<void>;
45
+ static reloadMCPServerList(): Promise<any>;
43
46
  static chatRequest(messageId: string, chatId: string, prompt: string, language: string, filename: string, additionalContext: IContextItem[], chatMode: string, toolSelections: IToolSelections, responseEmitter: IChatCompletionResponseEmitter): Promise<void>;
44
47
  static generateCode(chatId: string, prompt: string, prefix: string, suffix: string, existingCode: string, language: string, filename: string, responseEmitter: IChatCompletionResponseEmitter): Promise<void>;
45
48
  static sendChatUserInput(messageId: string, data: any): Promise<void>;
package/lib/api.js CHANGED
@@ -20,6 +20,12 @@ export class NBIConfig {
20
20
  this.chatParticipants = [];
21
21
  this.changed = new Signal(this);
22
22
  }
23
+ get userHomeDir() {
24
+ return this.capabilities.user_home_dir;
25
+ }
26
+ get configFilePath() {
27
+ return this.capabilities.config_file_path;
28
+ }
23
29
  get llmProviders() {
24
30
  return this.capabilities.llm_providers;
25
31
  }
@@ -170,6 +176,19 @@ class NBIAPI {
170
176
  });
171
177
  });
172
178
  }
179
+ static async reloadMCPServerList() {
180
+ return new Promise((resolve, reject) => {
181
+ requestAPI('reload-mcp-servers', { method: 'POST' })
182
+ .then(async (data) => {
183
+ await NBIAPI.fetchCapabilities();
184
+ resolve(data);
185
+ })
186
+ .catch(reason => {
187
+ console.error(`Failed to reload MCP server list.\n${reason}`);
188
+ reject(reason);
189
+ });
190
+ });
191
+ }
173
192
  static async chatRequest(messageId, chatId, prompt, language, filename, additionalContext, chatMode, toolSelections, responseEmitter) {
174
193
  this._messageReceived.connect((_, msg) => {
175
194
  msg = JSON.parse(msg);
@@ -254,17 +254,25 @@ function ChatResponse(props) {
254
254
  case ResponseStreamDataType.Markdown:
255
255
  case ResponseStreamDataType.MarkdownPart:
256
256
  return (React.createElement(React.Fragment, null,
257
- item.reasoningContent && (React.createElement("div", { className: "chat-reasoning-content" },
258
- React.createElement("div", { className: "chat-reasoning-content-title", onClick: (event) => onExpandCollapseClick(event) },
257
+ item.reasoningContent && (React.createElement("div", { className: "expandable-content" },
258
+ React.createElement("div", { className: "expandable-content-title", onClick: (event) => onExpandCollapseClick(event) },
259
259
  React.createElement(VscTriangleRight, { className: "collapsed-icon" }),
260
260
  React.createElement(VscTriangleDown, { className: "expanded-icon" }),
261
261
  ' ',
262
262
  item.reasoningFinished
263
263
  ? 'Thought'
264
264
  : `Thinking (${Math.floor(item.reasoningTime)} s)`),
265
- React.createElement("div", { className: "chat-reasoning-content-text" },
265
+ React.createElement("div", { className: "expandable-content-text" },
266
266
  React.createElement(MarkdownRenderer, { key: `key-${index}`, getApp: props.getApp, getActiveDocumentInfo: props.getActiveDocumentInfo }, item.reasoningContent)))),
267
- React.createElement(MarkdownRenderer, { key: `key-${index}`, getApp: props.getApp, getActiveDocumentInfo: props.getActiveDocumentInfo }, item.content)));
267
+ React.createElement(MarkdownRenderer, { key: `key-${index}`, getApp: props.getApp, getActiveDocumentInfo: props.getActiveDocumentInfo }, item.content),
268
+ item.contentDetail ? (React.createElement("div", { className: "expandable-content" },
269
+ React.createElement("div", { className: "expandable-content-title", onClick: (event) => onExpandCollapseClick(event) },
270
+ React.createElement(VscTriangleRight, { className: "collapsed-icon" }),
271
+ React.createElement(VscTriangleDown, { className: "expanded-icon" }),
272
+ ' ',
273
+ item.contentDetail.title),
274
+ React.createElement("div", { className: "expandable-content-text" },
275
+ React.createElement(MarkdownRenderer, { key: `key-${index}`, getApp: props.getApp, getActiveDocumentInfo: props.getActiveDocumentInfo }, item.contentDetail.content)))) : null));
268
276
  case ResponseStreamDataType.Image:
269
277
  return (React.createElement("div", { className: "chat-response-img", key: `key-${index}` },
270
278
  React.createElement("img", { src: item.content })));
@@ -796,6 +804,7 @@ function SidebarComponent(props) {
796
804
  id: UUID.uuid4(),
797
805
  type: nbiContent.type,
798
806
  content: nbiContent.content,
807
+ contentDetail: nbiContent.detail,
799
808
  created: new Date(response.created)
800
809
  });
801
810
  }
@@ -1491,10 +1500,12 @@ function GitHubCopilotLoginDialogBodyComponent(props) {
1491
1500
  React.createElement("div", { className: "jp-Dialog-buttonLabel" }, "Cancel activation"))))));
1492
1501
  }
1493
1502
  function ConfigurationDialogBodyComponent(props) {
1503
+ var _a;
1494
1504
  const nbiConfig = NBIAPI.config;
1495
1505
  const llmProviders = nbiConfig.llmProviders;
1496
1506
  const [chatModels, setChatModels] = useState([]);
1497
1507
  const [inlineCompletionModels, setInlineCompletionModels] = useState([]);
1508
+ const [mcpServerNames, setMcpServerNames] = useState(((_a = nbiConfig.toolConfig.mcpServers) === null || _a === void 0 ? void 0 : _a.map((server) => server.id)) || []);
1498
1509
  const handleSaveClick = async () => {
1499
1510
  const config = {
1500
1511
  chat_model: {
@@ -1586,6 +1597,11 @@ function ConfigurationDialogBodyComponent(props) {
1586
1597
  setInlineCompletionModelProperties(updatedProperties);
1587
1598
  }
1588
1599
  };
1600
+ const handleReloadMCPServersClick = async () => {
1601
+ var _a;
1602
+ const data = await NBIAPI.reloadMCPServerList();
1603
+ setMcpServerNames(((_a = data.mcpServers) === null || _a === void 0 ? void 0 : _a.map((server) => server.id)) || []);
1604
+ };
1589
1605
  useEffect(() => {
1590
1606
  updateModelOptionsForProvider(chatModelProvider, 'chat');
1591
1607
  updateModelOptionsForProvider(inlineCompletionModelProvider, 'inline-completion');
@@ -1670,7 +1686,32 @@ function ConfigurationDialogBodyComponent(props) {
1670
1686
  React.createElement("input", { type: "checkbox", checked: storeGitHubAccessToken, onChange: event => {
1671
1687
  setStoreGitHubAccessToken(event.target.checked);
1672
1688
  } }),
1673
- "Remember my GitHub Copilot access token"))))))),
1689
+ "Remember my GitHub Copilot access token")))))),
1690
+ React.createElement("div", { className: "model-config-section" },
1691
+ React.createElement("div", { className: "model-config-section-header" },
1692
+ "MCP Servers [",
1693
+ mcpServerNames.length,
1694
+ "]"),
1695
+ React.createElement("div", { className: "model-config-section-body" },
1696
+ React.createElement("div", { className: "model-config-section-row" },
1697
+ React.createElement("div", { className: "model-config-section-column" },
1698
+ mcpServerNames.length === 0 && (React.createElement("div", null, "No MCP servers found. Add MCP servers in the configuration file.")),
1699
+ mcpServerNames.length > 0 && (React.createElement("div", null, mcpServerNames.sort().join(', ')))),
1700
+ React.createElement("div", { className: "model-config-section-column", style: { flexGrow: 'initial' } },
1701
+ React.createElement("button", { className: "jp-Dialog-button jp-mod-reject jp-mod-styled", onClick: handleReloadMCPServersClick },
1702
+ React.createElement("div", { className: "jp-Dialog-buttonLabel" }, "Reload")))))),
1703
+ React.createElement("div", { className: "model-config-section" },
1704
+ React.createElement("div", { className: "model-config-section-header" }, "Config file path"),
1705
+ React.createElement("div", { className: "model-config-section-body" },
1706
+ React.createElement("div", { className: "model-config-section-row" },
1707
+ React.createElement("div", { className: "model-config-section-column" },
1708
+ React.createElement("span", { className: "user-code-span", onClick: () => {
1709
+ navigator.clipboard.writeText(NBIAPI.config.configFilePath);
1710
+ return true;
1711
+ } },
1712
+ NBIAPI.config.configFilePath,
1713
+ ' ',
1714
+ React.createElement("span", { className: "copy-icon", dangerouslySetInnerHTML: { __html: copySvgstr } }))))))),
1674
1715
  React.createElement("div", { className: "config-dialog-footer" },
1675
1716
  React.createElement("button", { className: "jp-Dialog-button jp-mod-accept jp-mod-styled", onClick: handleSaveClick },
1676
1717
  React.createElement("div", { className: "jp-Dialog-buttonLabel" }, "Save")))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notebook-intelligence/notebook-intelligence",
3
- "version": "2.2.8",
3
+ "version": "2.3.1",
4
4
  "description": "AI coding assistant for JupyterLab",
5
5
  "keywords": [
6
6
  "AI",
package/src/api.ts CHANGED
@@ -30,6 +30,14 @@ export interface IDeviceVerificationInfo {
30
30
  }
31
31
 
32
32
  export class NBIConfig {
33
+ get userHomeDir(): string {
34
+ return this.capabilities.user_home_dir;
35
+ }
36
+
37
+ get configFilePath(): string {
38
+ return this.capabilities.config_file_path;
39
+ }
40
+
33
41
  get llmProviders(): [any] {
34
42
  return this.capabilities.llm_providers;
35
43
  }
@@ -228,6 +236,20 @@ export class NBIAPI {
228
236
  });
229
237
  }
230
238
 
239
+ static async reloadMCPServerList(): Promise<any> {
240
+ return new Promise<any>((resolve, reject) => {
241
+ requestAPI<any>('reload-mcp-servers', { method: 'POST' })
242
+ .then(async data => {
243
+ await NBIAPI.fetchCapabilities();
244
+ resolve(data);
245
+ })
246
+ .catch(reason => {
247
+ console.error(`Failed to reload MCP server list.\n${reason}`);
248
+ reject(reason);
249
+ });
250
+ });
251
+ }
252
+
231
253
  static async chatRequest(
232
254
  messageId: string,
233
255
  chatId: string,
@@ -281,6 +281,7 @@ interface IChatMessageContent {
281
281
  id: string;
282
282
  type: ResponseStreamDataType;
283
283
  content: any;
284
+ contentDetail?: any;
284
285
  created: Date;
285
286
  reasoningContent?: string;
286
287
  reasoningFinished?: boolean;
@@ -465,9 +466,9 @@ function ChatResponse(props: any) {
465
466
  return (
466
467
  <>
467
468
  {item.reasoningContent && (
468
- <div className="chat-reasoning-content">
469
+ <div className="expandable-content">
469
470
  <div
470
- className="chat-reasoning-content-title"
471
+ className="expandable-content-title"
471
472
  onClick={(event: any) => onExpandCollapseClick(event)}
472
473
  >
473
474
  <VscTriangleRight className="collapsed-icon"></VscTriangleRight>
@@ -476,7 +477,7 @@ function ChatResponse(props: any) {
476
477
  ? 'Thought'
477
478
  : `Thinking (${Math.floor(item.reasoningTime)} s)`}
478
479
  </div>
479
- <div className="chat-reasoning-content-text">
480
+ <div className="expandable-content-text">
480
481
  <MarkdownRenderer
481
482
  key={`key-${index}`}
482
483
  getApp={props.getApp}
@@ -494,6 +495,27 @@ function ChatResponse(props: any) {
494
495
  >
495
496
  {item.content}
496
497
  </MarkdownRenderer>
498
+ {item.contentDetail ? (
499
+ <div className="expandable-content">
500
+ <div
501
+ className="expandable-content-title"
502
+ onClick={(event: any) => onExpandCollapseClick(event)}
503
+ >
504
+ <VscTriangleRight className="collapsed-icon"></VscTriangleRight>
505
+ <VscTriangleDown className="expanded-icon"></VscTriangleDown>{' '}
506
+ {item.contentDetail.title}
507
+ </div>
508
+ <div className="expandable-content-text">
509
+ <MarkdownRenderer
510
+ key={`key-${index}`}
511
+ getApp={props.getApp}
512
+ getActiveDocumentInfo={props.getActiveDocumentInfo}
513
+ >
514
+ {item.contentDetail.content}
515
+ </MarkdownRenderer>
516
+ </div>
517
+ </div>
518
+ ) : null}
497
519
  </>
498
520
  );
499
521
  case ResponseStreamDataType.Image:
@@ -1278,6 +1300,7 @@ function SidebarComponent(props: any) {
1278
1300
  id: UUID.uuid4(),
1279
1301
  type: nbiContent.type,
1280
1302
  content: nbiContent.content,
1303
+ contentDetail: nbiContent.detail,
1281
1304
  created: new Date(response.created)
1282
1305
  });
1283
1306
  } else {
@@ -2468,6 +2491,9 @@ function ConfigurationDialogBodyComponent(props: any) {
2468
2491
  const llmProviders = nbiConfig.llmProviders;
2469
2492
  const [chatModels, setChatModels] = useState([]);
2470
2493
  const [inlineCompletionModels, setInlineCompletionModels] = useState([]);
2494
+ const [mcpServerNames, setMcpServerNames] = useState(
2495
+ nbiConfig.toolConfig.mcpServers?.map((server: any) => server.id) || []
2496
+ );
2471
2497
 
2472
2498
  const handleSaveClick = async () => {
2473
2499
  const config: any = {
@@ -2587,6 +2613,11 @@ function ConfigurationDialogBodyComponent(props: any) {
2587
2613
  }
2588
2614
  };
2589
2615
 
2616
+ const handleReloadMCPServersClick = async () => {
2617
+ const data = await NBIAPI.reloadMCPServerList();
2618
+ setMcpServerNames(data.mcpServers?.map((server: any) => server.id) || []);
2619
+ };
2620
+
2590
2621
  useEffect(() => {
2591
2622
  updateModelOptionsForProvider(chatModelProvider, 'chat');
2592
2623
  updateModelOptionsForProvider(
@@ -2855,6 +2886,61 @@ function ConfigurationDialogBodyComponent(props: any) {
2855
2886
  </div>
2856
2887
  </div>
2857
2888
  )}
2889
+
2890
+ <div className="model-config-section">
2891
+ <div className="model-config-section-header">
2892
+ MCP Servers [{mcpServerNames.length}]
2893
+ </div>
2894
+ <div className="model-config-section-body">
2895
+ <div className="model-config-section-row">
2896
+ <div className="model-config-section-column">
2897
+ {mcpServerNames.length === 0 && (
2898
+ <div>
2899
+ No MCP servers found. Add MCP servers in the configuration
2900
+ file.
2901
+ </div>
2902
+ )}
2903
+ {mcpServerNames.length > 0 && (
2904
+ <div>{mcpServerNames.sort().join(', ')}</div>
2905
+ )}
2906
+ </div>
2907
+ <div
2908
+ className="model-config-section-column"
2909
+ style={{ flexGrow: 'initial' }}
2910
+ >
2911
+ <button
2912
+ className="jp-Dialog-button jp-mod-reject jp-mod-styled"
2913
+ onClick={handleReloadMCPServersClick}
2914
+ >
2915
+ <div className="jp-Dialog-buttonLabel">Reload</div>
2916
+ </button>
2917
+ </div>
2918
+ </div>
2919
+ </div>
2920
+ </div>
2921
+
2922
+ <div className="model-config-section">
2923
+ <div className="model-config-section-header">Config file path</div>
2924
+ <div className="model-config-section-body">
2925
+ <div className="model-config-section-row">
2926
+ <div className="model-config-section-column">
2927
+ <span
2928
+ className="user-code-span"
2929
+ onClick={() => {
2930
+ navigator.clipboard.writeText(NBIAPI.config.configFilePath);
2931
+ return true;
2932
+ }}
2933
+ >
2934
+ {NBIAPI.config.configFilePath}{' '}
2935
+ <span
2936
+ className="copy-icon"
2937
+ dangerouslySetInnerHTML={{ __html: copySvgstr }}
2938
+ ></span>
2939
+ </span>
2940
+ </div>
2941
+ </div>
2942
+ </div>
2943
+ </div>
2858
2944
  </div>
2859
2945
 
2860
2946
  <div className="config-dialog-footer">
package/style/base.css CHANGED
@@ -585,6 +585,10 @@ body[data-jp-theme-light='false'] .inline-popover {
585
585
  height: 100%;
586
586
  }
587
587
 
588
+ .config-dialog-container .jp-Dialog-content {
589
+ max-height: 600px;
590
+ }
591
+
588
592
  .config-dialog-container .jp-Dialog-footer {
589
593
  display: none;
590
594
  }
@@ -711,8 +715,9 @@ body[data-jp-theme-light='false'] .inline-popover {
711
715
  line-height: 20px;
712
716
  }
713
717
 
714
- .chat-reasoning-content-title {
718
+ .expandable-content-title {
715
719
  margin-top: 5px;
720
+ margin-bottom: 5px;
716
721
  display: flex;
717
722
  align-items: center;
718
723
  gap: 5px;
@@ -720,7 +725,7 @@ body[data-jp-theme-light='false'] .inline-popover {
720
725
  color: var(--jp-ui-font-color2);
721
726
  }
722
727
 
723
- .chat-reasoning-content-text {
728
+ .expandable-content-text {
724
729
  display: none;
725
730
  margin: 5px;
726
731
  padding: 0 5px;
@@ -728,23 +733,23 @@ body[data-jp-theme-light='false'] .inline-popover {
728
733
  border-radius: 5px;
729
734
  }
730
735
 
731
- .chat-reasoning-content .collapsed-icon {
736
+ .expandable-content .collapsed-icon {
732
737
  display: inline;
733
738
  }
734
739
 
735
- .chat-reasoning-content .expanded-icon {
740
+ .expandable-content .expanded-icon {
736
741
  display: none;
737
742
  }
738
743
 
739
- .chat-reasoning-content.expanded .expanded-icon {
744
+ .expandable-content.expanded .expanded-icon {
740
745
  display: inline;
741
746
  }
742
747
 
743
- .chat-reasoning-content.expanded .chat-reasoning-content-text {
748
+ .expandable-content.expanded .expandable-content-text {
744
749
  display: block;
745
750
  }
746
751
 
747
- .chat-reasoning-content.expanded .collapsed-icon {
752
+ .expandable-content.expanded .collapsed-icon {
748
753
  display: none;
749
754
  }
750
755