@notebook-intelligence/notebook-intelligence 3.1.0 → 4.0.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.
@@ -6,10 +6,11 @@ import { VscWarning } from 'react-icons/vsc';
6
6
  import * as path from 'path';
7
7
 
8
8
  import copySvgstr from '../../style/icons/copy.svg';
9
- import { NBIAPI } from '../api';
9
+ import { ClaudeModelType, ClaudeToolType, NBIAPI } from '../api';
10
10
  import { CheckBoxItem } from './checkbox';
11
11
  import { PillItem } from './pill';
12
12
  import { mcpServerSettingsToEnabledState } from './mcp-util';
13
+ import claudeSvg from '../../style/claude.svg';
13
14
 
14
15
  const OPENAI_COMPATIBLE_CHAT_MODEL_ID = 'openai-compatible-chat-model';
15
16
  const LITELLM_COMPATIBLE_CHAT_MODEL_ID = 'litellm-compatible-chat-model';
@@ -69,6 +70,11 @@ function SettingsPanelComponent(props: any) {
69
70
  onEditMCPConfigClicked={props.onEditMCPConfigClicked}
70
71
  />
71
72
  )}
73
+ {activeTab === 'claude' && (
74
+ <SettingsPanelComponentClaude
75
+ onEditMCPConfigClicked={props.onEditMCPConfigClicked}
76
+ />
77
+ )}
72
78
  </div>
73
79
  </div>
74
80
  );
@@ -88,6 +94,19 @@ function SettingsPanelTabsComponent(props: any) {
88
94
  >
89
95
  General
90
96
  </div>
97
+ <div
98
+ className={`nbi-settings-panel-tab ${activeTab === 'claude' ? 'active' : ''}`}
99
+ onClick={() => {
100
+ setActiveTab('claude');
101
+ props.onTabSelected('claude');
102
+ }}
103
+ >
104
+ <span
105
+ className="claude-icon"
106
+ dangerouslySetInnerHTML={{ __html: claudeSvg }}
107
+ ></span>
108
+ Claude
109
+ </div>
91
110
  <div
92
111
  className={`nbi-settings-panel-tab ${activeTab === 'mcp-servers' ? 'active' : ''}`}
93
112
  onClick={() => {
@@ -796,3 +815,304 @@ function SettingsPanelComponentMCPServers(props: any) {
796
815
  </div>
797
816
  );
798
817
  }
818
+
819
+ function SettingsPanelComponentClaude(props: any) {
820
+ const nbiConfig = NBIAPI.config;
821
+ const claudeSettingsRef = useRef<any>(nbiConfig.claudeSettings);
822
+ const [_renderCount, setRenderCount] = useState(1);
823
+ const [claudeEnabled, setClaudeEnabled] = useState(
824
+ nbiConfig.isInClaudeCodeMode
825
+ );
826
+ const [chatModel, setChatModel] = useState(
827
+ nbiConfig.claudeSettings.chat_model ?? ClaudeModelType.Default
828
+ );
829
+ const [inlineCompletionModel, setInlineCompletionModel] = useState(
830
+ nbiConfig.claudeSettings.inline_completion_model ?? ClaudeModelType.Default
831
+ );
832
+ const [apiKey, setApiKey] = useState(nbiConfig.claudeSettings.api_key ?? '');
833
+ const [baseUrl, setBaseUrl] = useState(
834
+ nbiConfig.claudeSettings.base_url ?? ''
835
+ );
836
+ const [settingSources, setSettingSources] = useState(
837
+ nbiConfig.claudeSettings.setting_sources ?? []
838
+ );
839
+ const [tools, setTools] = useState(
840
+ nbiConfig.claudeSettings.tools ?? [
841
+ ClaudeToolType.ClaudeCodeTools,
842
+ ClaudeToolType.JupyterUITools
843
+ ]
844
+ );
845
+
846
+ useEffect(() => {
847
+ NBIAPI.configChanged.connect(() => {
848
+ claudeSettingsRef.current = nbiConfig.claudeSettings;
849
+ setRenderCount(renderCount => renderCount + 1);
850
+ });
851
+ }, []);
852
+
853
+ const syncSettingsToServerState = () => {
854
+ NBIAPI.setConfig({
855
+ claude_settings: {
856
+ enabled: claudeEnabled,
857
+ chat_model: chatModel,
858
+ inline_completion_model: inlineCompletionModel,
859
+ api_key: apiKey,
860
+ base_url: baseUrl,
861
+ setting_sources: settingSources,
862
+ tools: tools
863
+ }
864
+ });
865
+ };
866
+
867
+ useEffect(() => {
868
+ syncSettingsToServerState();
869
+ }, [
870
+ claudeEnabled,
871
+ chatModel,
872
+ inlineCompletionModel,
873
+ apiKey,
874
+ baseUrl,
875
+ settingSources,
876
+ tools
877
+ ]);
878
+
879
+ return (
880
+ <div className="config-dialog">
881
+ <div className="config-dialog-body">
882
+ <div className="model-config-section">
883
+ <div className="model-config-section-header">Enable Claude mode</div>
884
+ <div className="model-config-section-body">
885
+ <div className="model-config-section-row">
886
+ <span>
887
+ This requires a{' '}
888
+ <a href="https://claude.ai" target="_blank">
889
+ Claude
890
+ </a>{' '}
891
+ account and{' '}
892
+ <a href="https://code.claude.com/" target="_blank">
893
+ Claude Code
894
+ </a>{' '}
895
+ installed in your system.
896
+ </span>
897
+ </div>
898
+ <div className="model-config-section-row">
899
+ <div className="model-config-section-column">
900
+ <div>
901
+ <CheckBoxItem
902
+ header={true}
903
+ label="Enable Claude mode"
904
+ checked={claudeEnabled}
905
+ onClick={() => {
906
+ setClaudeEnabled(!claudeEnabled);
907
+ }}
908
+ ></CheckBoxItem>
909
+ </div>
910
+ </div>
911
+ </div>
912
+ </div>
913
+ </div>
914
+
915
+ <div className="model-config-section">
916
+ <div className="model-config-section-header">Models</div>
917
+ <div className="model-config-section-body">
918
+ <div className="model-config-section-row">
919
+ <div className="model-config-section-column">
920
+ <div>Chat model</div>
921
+ <div>
922
+ <select
923
+ className="jp-mod-styled"
924
+ onChange={event => setChatModel(event.target.value)}
925
+ >
926
+ <option
927
+ value={ClaudeModelType.Default}
928
+ selected={chatModel === ClaudeModelType.Default}
929
+ >
930
+ Default (recommended)
931
+ </option>
932
+ <option
933
+ value={ClaudeModelType.ClaudeOpus45}
934
+ selected={chatModel === ClaudeModelType.ClaudeOpus45}
935
+ >
936
+ Claude Opus 4.5
937
+ </option>
938
+ <option
939
+ value={ClaudeModelType.ClaudeHaiku45}
940
+ selected={chatModel === ClaudeModelType.ClaudeHaiku45}
941
+ >
942
+ Claude Haiku 4.5
943
+ </option>
944
+ </select>
945
+ </div>
946
+ </div>
947
+ <div className="model-config-section-column">
948
+ <div>Auto-complete model</div>
949
+ <div>
950
+ <select
951
+ className="jp-mod-styled"
952
+ onChange={event =>
953
+ setInlineCompletionModel(event.target.value)
954
+ }
955
+ >
956
+ <option
957
+ value={ClaudeModelType.Default}
958
+ selected={
959
+ inlineCompletionModel === ClaudeModelType.Default
960
+ }
961
+ >
962
+ Default (recommended)
963
+ </option>
964
+ <option
965
+ value={ClaudeModelType.ClaudeOpus45}
966
+ selected={
967
+ inlineCompletionModel === ClaudeModelType.ClaudeOpus45
968
+ }
969
+ >
970
+ Claude Opus 4.5
971
+ </option>
972
+ <option
973
+ value={ClaudeModelType.ClaudeHaiku45}
974
+ selected={
975
+ inlineCompletionModel === ClaudeModelType.ClaudeHaiku45
976
+ }
977
+ >
978
+ Claude Haiku 4.5
979
+ </option>
980
+ </select>
981
+ </div>
982
+ </div>
983
+ </div>
984
+ </div>
985
+ </div>
986
+
987
+ <div className="model-config-section">
988
+ <div className="model-config-section-header">
989
+ Chat Agent setting sources
990
+ </div>
991
+ <div className="model-config-section-body">
992
+ <div className="model-config-section-row">
993
+ <div className="model-config-section-column">
994
+ <div>
995
+ <CheckBoxItem
996
+ header={true}
997
+ label="User"
998
+ checked={settingSources.includes('user')}
999
+ onClick={() => {
1000
+ setSettingSources(
1001
+ settingSources.includes('user')
1002
+ ? settingSources.filter(
1003
+ (source: string) => source !== 'user'
1004
+ )
1005
+ : [...settingSources, 'user']
1006
+ );
1007
+ }}
1008
+ ></CheckBoxItem>
1009
+ </div>
1010
+ </div>
1011
+ <div className="model-config-section-column">
1012
+ <div>
1013
+ <CheckBoxItem
1014
+ header={true}
1015
+ label="Project (Jupyter root directory)"
1016
+ checked={settingSources.includes('project')}
1017
+ onClick={() => {
1018
+ setSettingSources(
1019
+ settingSources.includes('project')
1020
+ ? settingSources.filter(
1021
+ (source: string) => source !== 'project'
1022
+ )
1023
+ : [...settingSources, 'project']
1024
+ );
1025
+ }}
1026
+ ></CheckBoxItem>
1027
+ </div>
1028
+ </div>
1029
+ </div>
1030
+ </div>
1031
+ </div>
1032
+
1033
+ <div className="model-config-section">
1034
+ <div className="model-config-section-header">Chat Agent tools</div>
1035
+ <div className="model-config-section-body">
1036
+ <div className="model-config-section-row">
1037
+ <div className="model-config-section-column">
1038
+ <div>
1039
+ <CheckBoxItem
1040
+ header={true}
1041
+ label="Claude Code tools"
1042
+ checked={tools.includes(ClaudeToolType.ClaudeCodeTools)}
1043
+ disabled={true}
1044
+ onClick={() => {
1045
+ setTools(
1046
+ tools.includes(ClaudeToolType.ClaudeCodeTools)
1047
+ ? tools.filter(
1048
+ (tool: string) =>
1049
+ tool !== ClaudeToolType.ClaudeCodeTools
1050
+ )
1051
+ : [...tools, ClaudeToolType.ClaudeCodeTools]
1052
+ );
1053
+ }}
1054
+ ></CheckBoxItem>
1055
+ </div>
1056
+ </div>
1057
+ <div className="model-config-section-column">
1058
+ <div>
1059
+ <CheckBoxItem
1060
+ header={true}
1061
+ label="Jupyter UI tools"
1062
+ checked={tools.includes(ClaudeToolType.JupyterUITools)}
1063
+ onClick={() => {
1064
+ setTools(
1065
+ tools.includes(ClaudeToolType.JupyterUITools)
1066
+ ? tools.filter(
1067
+ (tool: string) =>
1068
+ tool !== ClaudeToolType.JupyterUITools
1069
+ )
1070
+ : [...tools, ClaudeToolType.JupyterUITools]
1071
+ );
1072
+ }}
1073
+ ></CheckBoxItem>
1074
+ </div>
1075
+ </div>
1076
+ </div>
1077
+ </div>
1078
+ </div>
1079
+
1080
+ <div className="model-config-section">
1081
+ <div className="model-config-section-header">Claude account</div>
1082
+ <div className="model-config-section-body">
1083
+ <div className="model-config-section-row">
1084
+ <div className="model-config-section-column">
1085
+ <div className="form-field-row">
1086
+ <div className="form-field-description">
1087
+ API Key (optional)
1088
+ </div>
1089
+ <input
1090
+ name="chat-model-id-input"
1091
+ placeholder="API Key"
1092
+ className="jp-mod-styled"
1093
+ spellCheck={false}
1094
+ value={apiKey}
1095
+ onChange={event => setApiKey(event.target.value)}
1096
+ />
1097
+ </div>
1098
+ <div className="form-field-row">
1099
+ <div className="form-field-description">
1100
+ Base URL (optional)
1101
+ </div>
1102
+ <input
1103
+ name="chat-model-id-input"
1104
+ placeholder="https://api.anthropic.com"
1105
+ className="jp-mod-styled"
1106
+ spellCheck={false}
1107
+ value={baseUrl}
1108
+ onChange={event => setBaseUrl(event.target.value)}
1109
+ />
1110
+ </div>
1111
+ </div>
1112
+ </div>
1113
+ </div>
1114
+ </div>
1115
+ </div>
1116
+ </div>
1117
+ );
1118
+ }
package/src/index.ts CHANGED
@@ -398,9 +398,10 @@ class NBIInlineCompletionProvider
398
398
 
399
399
  const nbiConfig = NBIAPI.config;
400
400
  const inlineCompletionsEnabled =
401
- nbiConfig.inlineCompletionModel.provider === GITHUB_COPILOT_PROVIDER_ID
401
+ nbiConfig.isInClaudeCodeMode ||
402
+ (nbiConfig.inlineCompletionModel.provider === GITHUB_COPILOT_PROVIDER_ID
402
403
  ? NBIAPI.getLoginStatus() === GitHubCopilotLoginStatus.LoggedIn
403
- : nbiConfig.inlineCompletionModel.provider !== 'none';
404
+ : nbiConfig.inlineCompletionModel.provider !== 'none');
404
405
 
405
406
  this._telemetryEmitter.emitTelemetryEvent({
406
407
  type: TelemetryEventType.InlineCompletionRequest,
@@ -1020,9 +1021,12 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
1020
1021
  };
1021
1022
 
1022
1023
  const isChatEnabled = (): boolean => {
1023
- return NBIAPI.config.chatModel.provider === GITHUB_COPILOT_PROVIDER_ID
1024
- ? !githubLoginRequired()
1025
- : NBIAPI.config.chatModel.provider !== 'none';
1024
+ return (
1025
+ NBIAPI.config.isInClaudeCodeMode ||
1026
+ (NBIAPI.config.chatModel.provider === GITHUB_COPILOT_PROVIDER_ID
1027
+ ? !githubLoginRequired()
1028
+ : NBIAPI.config.chatModel.provider !== 'none')
1029
+ );
1026
1030
  };
1027
1031
 
1028
1032
  const isActiveCellCodeCell = (): boolean => {
@@ -1876,12 +1880,17 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
1876
1880
  item: githubCopilotStatusBarItem,
1877
1881
  align: 'right',
1878
1882
  rank: 100,
1879
- isActive: () => NBIAPI.config.usingGitHubCopilotModel
1883
+ isActive: () =>
1884
+ !NBIAPI.config.isInClaudeCodeMode &&
1885
+ NBIAPI.config.usingGitHubCopilotModel
1880
1886
  }
1881
1887
  );
1882
1888
 
1883
1889
  NBIAPI.configChanged.connect(() => {
1884
- if (NBIAPI.config.usingGitHubCopilotModel) {
1890
+ if (
1891
+ !NBIAPI.config.isInClaudeCodeMode &&
1892
+ NBIAPI.config.usingGitHubCopilotModel
1893
+ ) {
1885
1894
  githubCopilotStatusBarItem.show();
1886
1895
  } else {
1887
1896
  githubCopilotStatusBarItem.hide();
package/src/tokens.ts CHANGED
@@ -33,7 +33,8 @@ export enum BackendMessageType {
33
33
  StreamEnd = 'stream-end',
34
34
  RunUICommand = 'run-ui-command',
35
35
  GitHubCopilotLoginStatusChange = 'github-copilot-login-status-change',
36
- MCPServerStatusChange = 'mcp-server-status-change'
36
+ MCPServerStatusChange = 'mcp-server-status-change',
37
+ ClaudeCodeStatusChange = 'claude-code-status-change'
37
38
  }
38
39
 
39
40
  export enum ResponseStreamDataType {
@@ -45,7 +46,8 @@ export enum ResponseStreamDataType {
45
46
  Button = 'button',
46
47
  Anchor = 'anchor',
47
48
  Progress = 'progress',
48
- Confirmation = 'confirmation'
49
+ Confirmation = 'confirmation',
50
+ AskUserQuestion = 'ask-user-question'
49
51
  }
50
52
 
51
53
  export enum ContextType {
@@ -108,6 +110,7 @@ export enum BuiltinToolsetType {
108
110
  }
109
111
 
110
112
  export const GITHUB_COPILOT_PROVIDER_ID = 'github-copilot';
113
+ export const CLAUDE_CODE_CHAT_PARTICIPANT_ID = 'claude-code';
111
114
 
112
115
  export enum TelemetryEventType {
113
116
  InlineCompletionRequest = 'inline-completion-request',
package/style/base.css CHANGED
@@ -485,6 +485,12 @@ pre:has(.code-block-header) {
485
485
  height: 12px;
486
486
  }
487
487
 
488
+ .claude-icon svg {
489
+ width: 16px;
490
+ height: 16px;
491
+ color: #d97757;
492
+ }
493
+
488
494
  .send-button {
489
495
  display: flex;
490
496
  align-items: center;
@@ -855,6 +861,8 @@ svg.access-token-warning {
855
861
  }
856
862
 
857
863
  .nbi-settings-panel-tab {
864
+ display: flex;
865
+ gap: 5px;
858
866
  cursor: pointer;
859
867
  padding: 10px;
860
868
  border-radius: 4px;
@@ -951,3 +959,67 @@ svg.access-token-warning {
951
959
  margin: 5px;
952
960
  font-style: italic;
953
961
  }
962
+
963
+ .config-dialog-body a {
964
+ color: var(--jp-content-link-color);
965
+ }
966
+
967
+ .chat-mode-widgets-container .claude-icon svg {
968
+ margin-top: 4px;
969
+ width: 18px;
970
+ height: 18px;
971
+ }
972
+
973
+ .chat-confirmation-form.ask-user-question {
974
+ display: flex;
975
+ flex-direction: column;
976
+ }
977
+
978
+ .ask-user-question-container {
979
+ padding: 10px;
980
+ display: flex;
981
+ flex-direction: column;
982
+ gap: 10px;
983
+ border-bottom: 1px solid var(--jp-border-color1);
984
+ }
985
+
986
+ .ask-user-question .ask-user-question-container:nth-last-child(-n + 2) {
987
+ border-bottom: none;
988
+ }
989
+
990
+ .ask-user-question-form {
991
+ display: flex;
992
+ flex-direction: column;
993
+ gap: 5px;
994
+ }
995
+
996
+ .ask-user-question-question {
997
+ font-weight: bold;
998
+ }
999
+
1000
+ .ask-user-question-header {
1001
+ font-style: italic;
1002
+ }
1003
+
1004
+ .ask-user-question-options {
1005
+ display: flex;
1006
+ flex-direction: column;
1007
+ }
1008
+
1009
+ .ask-user-question-option {
1010
+ display: flex;
1011
+ flex-direction: column;
1012
+ }
1013
+
1014
+ .ask-user-question-option-description {
1015
+ padding-left: 5px;
1016
+ color: var(--jp-ui-font-color2);
1017
+ padding-bottom: 4px;
1018
+ overflow: hidden;
1019
+ text-overflow: ellipsis;
1020
+ white-space: nowrap;
1021
+ }
1022
+
1023
+ .ask-user-question-footer {
1024
+ padding: 0 0 5px 10px;
1025
+ }
@@ -0,0 +1 @@
1
+ <svg width="1200" height="1200" viewBox="0 0 1200 1200" xmlns="http://www.w3.org/2000/svg"><g id="g314"><path id="path147" fill="currentColor" stroke="none" d="M 233.959793 800.214905 L 468.644287 668.536987 L 472.590637 657.100647 L 468.644287 650.738403 L 457.208069 650.738403 L 417.986633 648.322144 L 283.892639 644.69812 L 167.597321 639.865845 L 54.926208 633.825623 L 26.577238 627.785339 L 3.3e-05 592.751709 L 2.73832 575.27533 L 26.577238 559.248352 L 60.724873 562.228149 L 136.187973 567.382629 L 249.422867 575.194763 L 331.570496 580.026978 L 453.261841 592.671082 L 472.590637 592.671082 L 475.328857 584.859009 L 468.724915 580.026978 L 463.570557 575.194763 L 346.389313 495.785217 L 219.543671 411.865906 L 153.100723 363.543762 L 117.181267 339.060425 L 99.060455 316.107361 L 91.248367 266.01355 L 123.865784 230.093994 L 167.677887 233.073853 L 178.872513 236.053772 L 223.248367 270.201477 L 318.040283 343.570496 L 441.825592 434.738342 L 459.946411 449.798706 L 467.194672 444.64447 L 468.080597 441.020203 L 459.946411 427.409485 L 392.617493 305.718323 L 320.778564 181.932983 L 288.80542 130.630859 L 280.348999 99.865845 C 277.369171 87.221436 275.194641 76.590698 275.194641 63.624268 L 312.322174 13.20813 L 332.8591 6.604126 L 382.389313 13.20813 L 403.248352 31.328979 L 434.013519 101.71814 L 483.865753 212.537048 L 561.181274 363.221497 L 583.812134 407.919434 L 595.892639 449.315491 L 600.40271 461.959839 L 608.214783 461.959839 L 608.214783 454.711609 L 614.577271 369.825623 L 626.335632 265.61084 L 637.771851 131.516846 L 641.718201 93.745117 L 660.402832 48.483276 L 697.530334 24.000122 L 726.52356 37.852417 L 750.362549 72 L 747.060486 94.067139 L 732.886047 186.201416 L 705.100708 330.52356 L 686.979919 427.167847 L 697.530334 427.167847 L 709.61084 415.087341 L 758.496704 350.174561 L 840.644348 247.490051 L 876.885925 206.738342 L 919.167847 161.71814 L 946.308838 140.29541 L 997.61084 140.29541 L 1035.38269 196.429626 L 1018.469849 254.416199 L 965.637634 321.422852 L 921.825562 378.201538 L 859.006714 462.765259 L 819.785278 530.41626 L 823.409424 535.812073 L 832.75177 534.92627 L 974.657776 504.724915 L 1051.328979 490.872559 L 1142.818848 475.167786 L 1184.214844 494.496582 L 1188.724854 514.147644 L 1172.456421 554.335693 L 1074.604126 578.496765 L 959.838989 601.449829 L 788.939636 641.879272 L 786.845764 643.409485 L 789.261841 646.389343 L 866.255127 653.637634 L 899.194702 655.409424 L 979.812134 655.409424 L 1129.932861 666.604187 L 1169.154419 692.537109 L 1192.671265 724.268677 L 1188.724854 748.429688 L 1128.322144 779.194641 L 1046.818848 759.865845 L 856.590759 714.604126 L 791.355774 698.335754 L 782.335693 698.335754 L 782.335693 703.731567 L 836.69812 756.885986 L 936.322205 846.845581 L 1061.073975 962.81897 L 1067.436279 991.490112 L 1051.409424 1014.120911 L 1034.496704 1011.704712 L 924.885986 929.234924 L 882.604126 892.107544 L 786.845764 811.48999 L 780.483276 811.48999 L 780.483276 819.946289 L 802.550415 852.241699 L 919.087341 1027.409424 L 925.127625 1081.127686 L 916.671204 1098.604126 L 886.469849 1109.154419 L 853.288696 1103.114136 L 785.073914 1007.355835 L 714.684631 899.516785 L 657.906067 802.872498 L 650.979858 806.81897 L 617.476624 1167.704834 L 601.771851 1186.147705 L 565.530212 1200 L 535.328857 1177.046997 L 519.302124 1139.919556 L 535.328857 1066.550537 L 554.657776 970.792053 L 570.362488 894.68457 L 584.536926 800.134277 L 592.993347 768.724976 L 592.429626 766.630859 L 585.503479 767.516968 L 514.22821 865.369263 L 405.825531 1011.865906 L 320.053711 1103.677979 L 299.516815 1111.812256 L 263.919525 1093.369263 L 267.221497 1060.429688 L 287.114136 1031.114136 L 405.825531 880.107361 L 477.422913 786.52356 L 523.651062 732.483276 L 523.328918 724.671265 L 520.590698 724.671265 L 205.288605 929.395935 L 149.154434 936.644409 L 124.993355 914.01355 L 127.973183 876.885986 L 139.409409 864.80542 L 234.201385 799.570435 L 233.879227 799.8927 Z"/></g></svg>