@notebook-intelligence/notebook-intelligence 1.3.2 → 1.3.3

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 CHANGED
@@ -45,19 +45,21 @@ for the frontend extension.
45
45
 
46
46
  ### Remembering GitHub Copilot login
47
47
 
48
- Notebook Intelligence uses system keyring to store the GitHub access tokens. If your stored access token fails to login (due to expiration or other reasons), you will be prompted to relogin on the UI. If you run into issues with this feature, check the Jupyter server logs and the [keyring package](https://github.com/jaraco/keyring) documentation.
48
+ Notebook Intelligence can remember your GitHub Copilot login so that you don't need to re-login after a JupyterLab or system restart. Please be aware of the security implications of using this feature.
49
49
 
50
- To let Notebook Intelligence remember your GitHub access token after you logged in:
50
+ > [!CAUTION]
51
+ > If you configure NBI to remember your GitHub Copilot login, it will encrypt the token and store into a data file at `~/.jupyter/nbi-data.json`. You should never share this file with others as they can access your tokens.
52
+ > Even though the token is encrypted, it is done so by using a default password and that's why it can be decrypted by others. In order to prevent that you can specify a custom password using the environment variable `NBI_GH_ACCESS_TOKEN_PASSWORD`.
51
53
 
52
54
  ```bash
53
- jupyter lab --NotebookIntelligence.github_access_token=remember
55
+ NBI_GH_ACCESS_TOKEN_PASSWORD=my_custom_password
54
56
  ```
55
57
 
56
- Once you set it to remember, it will continue to remember even if you skip `--NotebookIntelligence.github_access_token` at following launches. In order to forget the GitHub access token stored:
58
+ To let Notebook Intelligence remember your GitHub access token, go to Notebook Intelligence Settings dialog and check the option `Remember my GitHub Copilot access token` as shown below.
57
59
 
58
- ```bash
59
- jupyter lab --NotebookIntelligence.github_access_token=forget
60
- ```
60
+ <img src="media/remember-gh-access-token.png" alt="Remember access token" width=500 />
61
+
62
+ If your stored access token fails to login (due to expiration or other reasons), you will be prompted to relogin on the UI.
61
63
 
62
64
  ### Configuration files
63
65
 
package/lib/api.d.ts CHANGED
@@ -17,6 +17,7 @@ export declare class NBIConfig {
17
17
  get chatModel(): any;
18
18
  get inlineCompletionModel(): any;
19
19
  get usingGitHubCopilotModel(): boolean;
20
+ get storeGitHubAccessToken(): boolean;
20
21
  capabilities: any;
21
22
  chatParticipants: IChatParticipant[];
22
23
  changed: Signal<this, void>;
package/lib/api.js CHANGED
@@ -39,6 +39,9 @@ export class NBIConfig {
39
39
  return (this.chatModel.provider === GITHUB_COPILOT_PROVIDER_ID ||
40
40
  this.inlineCompletionModel.provider === GITHUB_COPILOT_PROVIDER_ID);
41
41
  }
42
+ get storeGitHubAccessToken() {
43
+ return this.capabilities.store_github_access_token === true;
44
+ }
42
45
  }
43
46
  class NBIAPI {
44
47
  static async initialize() {
@@ -9,7 +9,7 @@ import { MarkdownRenderer } from './markdown-renderer';
9
9
  import copySvgstr from '../style/icons/copy.svg';
10
10
  import copilotSvgstr from '../style/icons/copilot.svg';
11
11
  import copilotWarningSvgstr from '../style/icons/copilot-warning.svg';
12
- import { VscSend, VscStopCircle, VscEye, VscEyeClosed, VscTriangleRight, VscTriangleDown } from 'react-icons/vsc';
12
+ import { VscSend, VscStopCircle, VscEye, VscEyeClosed, VscTriangleRight, VscTriangleDown, VscWarning } from 'react-icons/vsc';
13
13
  import { extractLLMGeneratedCode, isDarkTheme } from './utils';
14
14
  const OPENAI_COMPATIBLE_CHAT_MODEL_ID = 'openai-compatible-chat-model';
15
15
  const LITELLM_COMPATIBLE_CHAT_MODEL_ID = 'litellm-compatible-chat-model';
@@ -1123,7 +1123,7 @@ function ConfigurationDialogBodyComponent(props) {
1123
1123
  const [chatModels, setChatModels] = useState([]);
1124
1124
  const [inlineCompletionModels, setInlineCompletionModels] = useState([]);
1125
1125
  const handleSaveClick = async () => {
1126
- await NBIAPI.setConfig({
1126
+ const config = {
1127
1127
  chat_model: {
1128
1128
  provider: chatModelProvider,
1129
1129
  model: chatModel,
@@ -1134,7 +1134,12 @@ function ConfigurationDialogBodyComponent(props) {
1134
1134
  model: inlineCompletionModel,
1135
1135
  properties: inlineCompletionModelProperties
1136
1136
  }
1137
- });
1137
+ };
1138
+ if (chatModelProvider === 'github-copilot' ||
1139
+ inlineCompletionModelProvider === 'github-copilot') {
1140
+ config.store_github_access_token = storeGitHubAccessToken;
1141
+ }
1142
+ await NBIAPI.setConfig(config);
1138
1143
  props.onSave();
1139
1144
  };
1140
1145
  const handleRefreshOllamaModelListClick = async () => {
@@ -1147,6 +1152,7 @@ function ConfigurationDialogBodyComponent(props) {
1147
1152
  const [chatModelProperties, setChatModelProperties] = useState([]);
1148
1153
  const [inlineCompletionModelProperties, setInlineCompletionModelProperties] = useState([]);
1149
1154
  const [inlineCompletionModel, setInlineCompletionModel] = useState(nbiConfig.inlineCompletionModel.model);
1155
+ const [storeGitHubAccessToken, setStoreGitHubAccessToken] = useState(nbiConfig.storeGitHubAccessToken);
1150
1156
  const updateModelOptionsForProvider = (providerId, modelType) => {
1151
1157
  if (modelType === 'chat') {
1152
1158
  setChatModelProvider(providerId);
@@ -1275,7 +1281,23 @@ function ConfigurationDialogBodyComponent(props) {
1275
1281
  property.name,
1276
1282
  " ",
1277
1283
  property.optional ? '(optional)' : ''),
1278
- React.createElement("input", { name: "inline-completion-model-id-input", placeholder: property.description, className: "jp-mod-styled", spellCheck: false, value: property.value, onChange: event => onModelPropertyChange('inline-completion', property.id, event.target.value) }))))))))),
1284
+ React.createElement("input", { name: "inline-completion-model-id-input", placeholder: property.description, className: "jp-mod-styled", spellCheck: false, value: property.value, onChange: event => onModelPropertyChange('inline-completion', property.id, event.target.value) })))))))),
1285
+ (chatModelProvider === 'github-copilot' ||
1286
+ inlineCompletionModelProvider === 'github-copilot') && (React.createElement("div", { className: "model-config-section" },
1287
+ React.createElement("div", { className: "model-config-section-header access-token-config-header" },
1288
+ "GitHub Copilot login",
1289
+ ' ',
1290
+ React.createElement("a", { href: "https://github.com/notebook-intelligence/notebook-intelligence/blob/main/README.md#remembering-github-copilot-login", target: "_blank" },
1291
+ ' ',
1292
+ React.createElement(VscWarning, { className: "access-token-warning", title: "Click to learn more about security implications" }))),
1293
+ React.createElement("div", { className: "model-config-section-body" },
1294
+ React.createElement("div", { className: "model-config-section-row" },
1295
+ React.createElement("div", { className: "model-config-section-column" },
1296
+ React.createElement("label", null,
1297
+ React.createElement("input", { type: "checkbox", checked: storeGitHubAccessToken, onChange: event => {
1298
+ setStoreGitHubAccessToken(event.target.checked);
1299
+ } }),
1300
+ "Remember my GitHub Copilot access token"))))))),
1279
1301
  React.createElement("div", { className: "config-dialog-footer" },
1280
1302
  React.createElement("button", { className: "jp-Dialog-button jp-mod-accept jp-mod-styled", onClick: handleSaveClick },
1281
1303
  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": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "AI coding assistant for JupyterLab",
5
5
  "keywords": [
6
6
  "AI",
package/src/api.ts CHANGED
@@ -56,6 +56,10 @@ export class NBIConfig {
56
56
  );
57
57
  }
58
58
 
59
+ get storeGitHubAccessToken(): boolean {
60
+ return this.capabilities.store_github_access_token === true;
61
+ }
62
+
59
63
  capabilities: any = {};
60
64
  chatParticipants: IChatParticipant[] = [];
61
65
 
@@ -41,7 +41,8 @@ import {
41
41
  VscEye,
42
42
  VscEyeClosed,
43
43
  VscTriangleRight,
44
- VscTriangleDown
44
+ VscTriangleDown,
45
+ VscWarning
45
46
  } from 'react-icons/vsc';
46
47
  import { extractLLMGeneratedCode, isDarkTheme } from './utils';
47
48
 
@@ -1823,7 +1824,7 @@ function ConfigurationDialogBodyComponent(props: any) {
1823
1824
  const [inlineCompletionModels, setInlineCompletionModels] = useState([]);
1824
1825
 
1825
1826
  const handleSaveClick = async () => {
1826
- await NBIAPI.setConfig({
1827
+ const config: any = {
1827
1828
  chat_model: {
1828
1829
  provider: chatModelProvider,
1829
1830
  model: chatModel,
@@ -1834,7 +1835,16 @@ function ConfigurationDialogBodyComponent(props: any) {
1834
1835
  model: inlineCompletionModel,
1835
1836
  properties: inlineCompletionModelProperties
1836
1837
  }
1837
- });
1838
+ };
1839
+
1840
+ if (
1841
+ chatModelProvider === 'github-copilot' ||
1842
+ inlineCompletionModelProvider === 'github-copilot'
1843
+ ) {
1844
+ config.store_github_access_token = storeGitHubAccessToken;
1845
+ }
1846
+
1847
+ await NBIAPI.setConfig(config);
1838
1848
 
1839
1849
  props.onSave();
1840
1850
  };
@@ -1856,6 +1866,9 @@ function ConfigurationDialogBodyComponent(props: any) {
1856
1866
  const [inlineCompletionModel, setInlineCompletionModel] = useState(
1857
1867
  nbiConfig.inlineCompletionModel.model
1858
1868
  );
1869
+ const [storeGitHubAccessToken, setStoreGitHubAccessToken] = useState(
1870
+ nbiConfig.storeGitHubAccessToken
1871
+ );
1859
1872
 
1860
1873
  const updateModelOptionsForProvider = (
1861
1874
  providerId: string,
@@ -2161,6 +2174,41 @@ function ConfigurationDialogBodyComponent(props: any) {
2161
2174
  </div>
2162
2175
  </div>
2163
2176
  </div>
2177
+
2178
+ {(chatModelProvider === 'github-copilot' ||
2179
+ inlineCompletionModelProvider === 'github-copilot') && (
2180
+ <div className="model-config-section">
2181
+ <div className="model-config-section-header access-token-config-header">
2182
+ GitHub Copilot login{' '}
2183
+ <a
2184
+ href="https://github.com/notebook-intelligence/notebook-intelligence/blob/main/README.md#remembering-github-copilot-login"
2185
+ target="_blank"
2186
+ >
2187
+ {' '}
2188
+ <VscWarning
2189
+ className="access-token-warning"
2190
+ title="Click to learn more about security implications"
2191
+ />
2192
+ </a>
2193
+ </div>
2194
+ <div className="model-config-section-body">
2195
+ <div className="model-config-section-row">
2196
+ <div className="model-config-section-column">
2197
+ <label>
2198
+ <input
2199
+ type="checkbox"
2200
+ checked={storeGitHubAccessToken}
2201
+ onChange={event => {
2202
+ setStoreGitHubAccessToken(event.target.checked);
2203
+ }}
2204
+ />
2205
+ Remember my GitHub Copilot access token
2206
+ </label>
2207
+ </div>
2208
+ </div>
2209
+ </div>
2210
+ </div>
2211
+ )}
2164
2212
  </div>
2165
2213
 
2166
2214
  <div className="config-dialog-footer">
package/style/base.css CHANGED
@@ -614,3 +614,15 @@ body[data-jp-theme-light='false'] .inline-popover {
614
614
  .chat-reasoning-content.expanded .collapsed-icon {
615
615
  display: none;
616
616
  }
617
+
618
+ .access-token-config-header {
619
+ display: flex;
620
+ align-items: center;
621
+ gap: 10px;
622
+ }
623
+
624
+ svg.access-token-warning {
625
+ color: var(--jp-warn-color0);
626
+ width: 18px;
627
+ height: 18px;
628
+ }